Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
February 2021
- 81 participants
- 1707 messages
[tools] testbot: Remove the Apache 2.2 instructions.
by Francois Gouget
Apache 2.2 is very old so simplify the sample configuration files.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/doc/vhost_winetestbot.conf | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/testbot/doc/vhost_winetestbot.conf b/testbot/doc/vhost_winetestbot.conf
index 7b84564a5..48a3917ce 100644
--- a/testbot/doc/vhost_winetestbot.conf
+++ b/testbot/doc/vhost_winetestbot.conf
@@ -23,11 +23,6 @@
PerlOptions +ParseHeaders
Options +ExecCGI
DirectoryIndex index.pl
-
- # Access control the Apache 2.2 way
- Order allow,deny
- Allow from all
- # And the Apache 2.4 way
Require all granted
</Directory>
</VirtualHost>
@@ -61,11 +56,6 @@
PerlOptions +ParseHeaders
Options +ExecCGI
DirectoryIndex index.pl
-
- # Access control the Apache 2.2 way
- Order allow,deny
- Allow from all
- # And the Apache 2.4 way
Require all granted
</Directory>
</VirtualHost>
--
2.20.1
Feb. 2, 2021
[tools] winetest: Remove the Apache 2.2 instructions.
by Francois Gouget
Apache 2.2 is very old so simplify the sample configuration files.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
winetest/vhost_winetest.conf | 4 ----
1 file changed, 4 deletions(-)
diff --git a/winetest/vhost_winetest.conf b/winetest/vhost_winetest.conf
index 797aac3f4..081025b1c 100644
--- a/winetest/vhost_winetest.conf
+++ b/winetest/vhost_winetest.conf
@@ -32,10 +32,6 @@
RewriteEngine On
RewriteRule "^$" "/data/" [R]
- # Access control the Apache 2.2 way
- Order allow,deny
- Allow from all
- # And the Apache 2.4 way
Require all granted
</Directory>
--
2.20.1
Feb. 2, 2021
[tools] patches: Remove the Apache 2.2 instructions.
by Francois Gouget
Apache 2.2 is very old so simplify the sample configuration files.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
patches/doc/vhost_source.conf | 4 ----
1 file changed, 4 deletions(-)
diff --git a/patches/doc/vhost_source.conf b/patches/doc/vhost_source.conf
index 03c25c6df..01c6dee15 100644
--- a/patches/doc/vhost_source.conf
+++ b/patches/doc/vhost_source.conf
@@ -6,10 +6,6 @@
ServerAdmin winehq(a)example.com
<Directory /home/winehq/opt/source>
- # Access control the Apache 2.2 way
- Order allow,deny
- Allow from all
- # And the Apache 2.4 way
Require all granted
</Directory>
</VirtualHost>
--
2.20.1
Feb. 2, 2021
[PATCH v4 2/2] wmphoto: Implement class factory for WmpDecoder.
by Rémi Bernon
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/wmphoto/Makefile.in | 10 ++-
dlls/wmphoto/main.c | 128 ++++++++++++++++++++++++++++++++++++---
dlls/wmphoto/unix_lib.c | 108 +++++++++++++++++++++++++++++++++
3 files changed, 235 insertions(+), 11 deletions(-)
create mode 100644 dlls/wmphoto/unix_lib.c
diff --git a/dlls/wmphoto/Makefile.in b/dlls/wmphoto/Makefile.in
index 24e1f49496a..8a626e61f18 100644
--- a/dlls/wmphoto/Makefile.in
+++ b/dlls/wmphoto/Makefile.in
@@ -1,7 +1,15 @@
MODULE = wmphoto.dll
+IMPORTS = windowscodecs uuid ole32 oleaut32 propsys rpcrt4 shlwapi
+PARENTSRC = ../windowscodecs
EXTRADLLFLAGS = -mno-cygwin
+EXTRAINCL = $(JXRLIB_CFLAGS)
-C_SRCS = main.c
+C_SRCS = \
+ decoder.c \
+ main.c \
+ unix_iface.c \
+ unix_lib.c \
+ wincodecs_common.c
IDL_SRCS = wmphoto.idl
diff --git a/dlls/wmphoto/main.c b/dlls/wmphoto/main.c
index d3a926e7704..7659dcb2ca8 100644
--- a/dlls/wmphoto/main.c
+++ b/dlls/wmphoto/main.c
@@ -1,5 +1,6 @@
/*
* Copyright 2017 Vincent Povirk for CodeWeavers
+ * Copyright 2020 Rémi Bernon for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -18,24 +19,121 @@
#include <stdarg.h>
+#define COBJMACROS
+
#include "windef.h"
#include "winbase.h"
#include "objbase.h"
#include "rpcproxy.h"
+#include "wincodecs_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
-static HINSTANCE WMPHOTO_hInstance;
+HRESULT create_instance(const CLSID *clsid, const IID *iid, void **ppv)
+{
+ return CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, iid, ppv);
+}
+
+HRESULT get_decoder_info(REFCLSID clsid, IWICBitmapDecoderInfo **info)
+{
+ IWICImagingFactory* factory;
+ IWICComponentInfo *compinfo;
+ HRESULT hr;
+
+ hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
+ &IID_IWICImagingFactory, (void **)&factory);
+ if (FAILED(hr))
+ return hr;
+
+ hr = IWICImagingFactory_CreateComponentInfo(factory, clsid, &compinfo);
+ if (FAILED(hr))
+ {
+ IWICImagingFactory_Release(factory);
+ return hr;
+ }
+
+ hr = IWICComponentInfo_QueryInterface(compinfo, &IID_IWICBitmapDecoderInfo,
+ (void **)info);
+
+ IWICComponentInfo_Release(compinfo);
+ IWICImagingFactory_Release(factory);
+ return hr;
+}
+
+struct class_factory
+{
+ IClassFactory IClassFactory_iface;
+};
+
+static HRESULT WINAPI wmp_class_factory_QueryInterface(IClassFactory *iface, REFIID iid, void **out)
+{
+ TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
+
+ if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IClassFactory))
+ {
+ *out = iface;
+ IClassFactory_AddRef(iface);
+ return S_OK;
+ }
+
+ *out = NULL;
+ FIXME("%s not implemented.\n", debugstr_guid(iid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI wmp_class_factory_AddRef(IClassFactory *iface) { return 2; }
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+static ULONG WINAPI wmp_class_factory_Release(IClassFactory *iface) { return 1; }
+
+static HRESULT WINAPI wmp_class_factory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID iid, void **out)
+{
+ struct decoder_info decoder_info;
+ struct decoder *decoder;
+ HRESULT hr;
+
+ TRACE("iface %p, outer %p, iid %s, out %p.\n", iface, outer, debugstr_guid(iid), out);
+
+ *out = NULL;
+ if (outer) return CLASS_E_NOAGGREGATION;
+
+ hr = get_unix_decoder(&CLSID_WICWmpDecoder, &decoder_info, &decoder);
+
+ if (SUCCEEDED(hr))
+ hr = CommonDecoder_CreateInstance(decoder, &decoder_info, iid, out);
+
+ return hr;
+}
+
+static HRESULT WINAPI wmp_class_factory_LockServer(IClassFactory *iface, BOOL lock)
+{
+ FIXME("iface %p, lock %d, stub!\n", iface, lock);
+ return S_OK;
+}
+
+static const IClassFactoryVtbl wmp_class_factory_vtbl =
+{
+ wmp_class_factory_QueryInterface,
+ wmp_class_factory_AddRef,
+ wmp_class_factory_Release,
+ wmp_class_factory_CreateInstance,
+ wmp_class_factory_LockServer,
+};
+
+static struct class_factory wmp_class_factory = {{&wmp_class_factory_vtbl}};
+
+HMODULE windowscodecs_module = 0;
+
+BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
{
- switch (fdwReason)
+ TRACE("instance %p, reason %d, reserved %p\n", instance, reason, reserved);
+
+ switch (reason)
{
case DLL_PROCESS_ATTACH:
- WMPHOTO_hInstance = hinstDLL;
- DisableThreadLibraryCalls(hinstDLL);
+ windowscodecs_module = instance;
+ DisableThreadLibraryCalls(instance);
break;
case DLL_WINE_PREATTACH:
return FALSE; /* prefer native version */
@@ -49,18 +147,28 @@ HRESULT WINAPI DllCanUnloadNow(void)
return S_FALSE;
}
-HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID * ppv)
+HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, LPVOID *out)
{
- FIXME("wmphoto: stub\n");
- return E_NOTIMPL;
+ struct class_factory *factory;
+
+ TRACE("clsid %s, iid %s, out %p.\n", debugstr_guid(clsid), debugstr_guid(iid), out);
+
+ if (IsEqualGUID(clsid, &CLSID_WICWmpDecoder)) factory = &wmp_class_factory;
+ else
+ {
+ FIXME("%s not implemented.\n", debugstr_guid(clsid));
+ return CLASS_E_CLASSNOTAVAILABLE;
+ }
+
+ return IClassFactory_QueryInterface(&factory->IClassFactory_iface, iid, out);
}
HRESULT WINAPI DllRegisterServer(void)
{
- return __wine_register_resources( WMPHOTO_hInstance );
+ return __wine_register_resources( windowscodecs_module );
}
HRESULT WINAPI DllUnregisterServer(void)
{
- return __wine_unregister_resources( WMPHOTO_hInstance );
+ return __wine_unregister_resources( windowscodecs_module );
}
diff --git a/dlls/wmphoto/unix_lib.c b/dlls/wmphoto/unix_lib.c
new file mode 100644
index 00000000000..198c93969f8
--- /dev/null
+++ b/dlls/wmphoto/unix_lib.c
@@ -0,0 +1,108 @@
+/*
+ * unix_lib.c - This is the Unix side of the Unix interface.
+ *
+ * Copyright 2020 Esme Povirk
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#if 0
+#pragma makedep unix
+#endif
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdarg.h>
+
+#define NONAMELESSUNION
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winternl.h"
+#include "winbase.h"
+#include "objbase.h"
+
+#include "initguid.h"
+#include "wincodecs_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
+
+#include "wincodecs_common.h"
+
+static const struct win32_funcs *win32_funcs;
+
+HRESULT CDECL stream_getsize(IStream *stream, ULONGLONG *size)
+{
+ return win32_funcs->stream_getsize(stream, size);
+}
+
+HRESULT CDECL stream_read(IStream *stream, void *buffer, ULONG read, ULONG *bytes_read)
+{
+ return win32_funcs->stream_read(stream, buffer, read, bytes_read);
+}
+
+HRESULT CDECL stream_seek(IStream *stream, LONGLONG ofs, DWORD origin, ULONGLONG *new_position)
+{
+ return win32_funcs->stream_seek(stream, ofs, origin, new_position);
+}
+
+HRESULT CDECL stream_write(IStream *stream, const void *buffer, ULONG write, ULONG *bytes_written)
+{
+ return win32_funcs->stream_write(stream, buffer, write, bytes_written);
+}
+
+HRESULT CDECL decoder_create(const CLSID *decoder_clsid, struct decoder_info *info, struct decoder **result)
+{
+ FIXME("decoder_clsid %s, info %p, result %p, stub!\n", debugstr_guid(decoder_clsid), info, result);
+ return E_NOTIMPL;
+}
+
+HRESULT CDECL encoder_create(const CLSID *encoder_clsid, struct encoder_info *info, struct encoder **result)
+{
+ FIXME("encoder_clsid %s, info %p, result %p, stub!\n", debugstr_guid(encoder_clsid), info, result);
+ return E_NOTIMPL;
+}
+
+static const struct unix_funcs unix_funcs = {
+ decoder_create,
+ decoder_initialize,
+ decoder_get_frame_info,
+ decoder_copy_pixels,
+ decoder_get_metadata_blocks,
+ decoder_get_color_context,
+ decoder_destroy,
+ encoder_create,
+ encoder_initialize,
+ encoder_get_supported_format,
+ encoder_create_frame,
+ encoder_write_lines,
+ encoder_commit_frame,
+ encoder_commit_file,
+ encoder_destroy
+};
+
+NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
+{
+ if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS;
+
+ win32_funcs = ptr_in;
+
+ *(const struct unix_funcs **)ptr_out = &unix_funcs;
+ return STATUS_SUCCESS;
+}
--
2.30.0
Feb. 2, 2021
[PATCH v4 1/2] windowscodecs: Use IWICImagingFactory_CreatePalette in write_source.
by Rémi Bernon
Instead of PaletteImpl_Create.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
v4: As an alternative to v3, with unix_lib.c copied to wmphoto instead,
as it seems to be preferred it over the #ifdef. I don't mind either.
dlls/windowscodecs/wincodecs_common.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/dlls/windowscodecs/wincodecs_common.c b/dlls/windowscodecs/wincodecs_common.c
index 37ad7128f10..1b146908be9 100644
--- a/dlls/windowscodecs/wincodecs_common.c
+++ b/dlls/windowscodecs/wincodecs_common.c
@@ -121,9 +121,17 @@ HRESULT write_source(IWICBitmapFrameEncode *iface,
if (need_palette)
{
+ IWICImagingFactory *factory;
IWICPalette *palette;
- hr = PaletteImpl_Create(&palette);
+ hr = create_instance(&CLSID_WICImagingFactory, &IID_IWICImagingFactory, (void**)&factory);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = IWICImagingFactory_CreatePalette(factory, &palette);
+ IWICImagingFactory_Release(factory);
+ }
+
if (SUCCEEDED(hr))
{
hr = IWICBitmapSource_CopyPalette(converted_source, palette);
--
2.30.0
Feb. 2, 2021
Re: [PATCH v2] gdi32: Fail in ExtTextOut if count is larger than INT_MAX.
by Huw Davies
On Sat, Jan 30, 2021 at 04:02:09PM +0200, Gabriel Ivăncescu wrote:
> Some applications pass values like -1 and crash when BIDI_Reorder can't
> allocate the memory.
>
> Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
> ---
> dlls/gdi32/font.c | 3 +++
> dlls/gdi32/tests/font.c | 2 ++
> dlls/gdi32/tests/metafile.c | 8 +++++++-
> 3 files changed, 12 insertions(+), 1 deletion(-)
>
> diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
> index 74ca482..de50bf0 100644
> --- a/dlls/gdi32/font.c
> +++ b/dlls/gdi32/font.c
> @@ -5823,6 +5823,8 @@ BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
> BOOL ret;
> LPINT lpDxW = NULL;
>
> + if (count > INT_MAX) return FALSE;
> +
What happens if ETO_OPAQUE and a valid rect are passed in this case?
Does the rect get drawn? You could test this by adding such a call
to draw_text_2() in gdi32/tests/dib.c
> diff --git a/dlls/gdi32/tests/metafile.c b/dlls/gdi32/tests/metafile.c
> index 8dae908..15af24a 100644
> --- a/dlls/gdi32/tests/metafile.c
> +++ b/dlls/gdi32/tests/metafile.c
> @@ -222,7 +222,13 @@ static void test_ExtTextOut(void)
> ret = ExtTextOutA(hdcMetafile, 0, 40, 0, NULL, text, lstrlenA(text), NULL);
> ok( ret, "ExtTextOutA error %d\n", GetLastError());
>
> - /* 4. test with unmatched BeginPath/EndPath calls */
> + /* 4. pass -1 to length */
> + SetLastError(0xdeadbeef);
> + ret = ExtTextOutA(hdcMetafile, 0, 0, 0, &rc, text, -1, NULL);
> + ok( !ret, "ExtTextOutA succeeded\n");
> + ok( GetLastError() == 0xdeadbeef, "ExtTextOutA error %d\n", GetLastError());
> +
> + /* 5. test with unmatched BeginPath/EndPath calls */
> ret = BeginPath(hdcMetafile);
> ok( ret, "BeginPath error %d\n", GetLastError());
> ret = BeginPath(hdcMetafile);
It would be interesting to know whether the metafile record actually gets
created in this case. Probably a stand-alone test at the end of this
function would be easier. Likewise for EMFs.
Huw.
Feb. 2, 2021
[PATCH] mscoree: Improve non-neutral assembly lookup logic.
by Rémi Bernon
And neutral logic too, and the combinations with custom privatePath
config.
This fixes a crash with Mafia III launcher, when it tries to load its
localized strings from culture-specific assemblies to display its
warning popup message.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/mscoree/metahost.c | 75 ++++++--
dlls/mscoree/tests/loadpaths.dll.cs | 33 ++++
dlls/mscoree/tests/loadpaths.exe.config | 8 +
dlls/mscoree/tests/loadpaths.exe.cs | 28 +++
dlls/mscoree/tests/mscoree.c | 226 ++++++++++++++++++++++++
dlls/mscoree/tests/resource.rc | 9 +
6 files changed, 360 insertions(+), 19 deletions(-)
create mode 100644 dlls/mscoree/tests/loadpaths.dll.cs
create mode 100644 dlls/mscoree/tests/loadpaths.exe.config
create mode 100644 dlls/mscoree/tests/loadpaths.exe.cs
diff --git a/dlls/mscoree/metahost.c b/dlls/mscoree/metahost.c
index a3ed1534753..d9b599fadc7 100644
--- a/dlls/mscoree/metahost.c
+++ b/dlls/mscoree/metahost.c
@@ -29,6 +29,7 @@
#include "winreg.h"
#include "winternl.h"
#include "ole2.h"
+#include "shlwapi.h"
#include "corerror.h"
#include "cor.h"
@@ -87,6 +88,7 @@ typedef void (CDECL *MonoProfilerRuntimeShutdownBeginCallback) (MonoProfiler *pr
MonoImage* (CDECL *mono_assembly_get_image)(MonoAssembly *assembly);
MonoAssembly* (CDECL *mono_assembly_load_from)(MonoImage *image, const char *fname, MonoImageOpenStatus *status);
const char* (CDECL *mono_assembly_name_get_name)(MonoAssemblyName *aname);
+const char* (CDECL *mono_assembly_name_get_culture)(MonoAssemblyName *aname);
MonoAssembly* (CDECL *mono_assembly_open)(const char *filename, MonoImageOpenStatus *status);
void (CDECL *mono_callspec_set_assembly)(MonoAssembly *assembly);
MonoClass* (CDECL *mono_class_from_mono_type)(MonoType *type);
@@ -193,6 +195,7 @@ static HRESULT load_mono(LPCWSTR mono_path)
LOAD_MONO_FUNCTION(mono_assembly_get_image);
LOAD_MONO_FUNCTION(mono_assembly_load_from);
LOAD_MONO_FUNCTION(mono_assembly_name_get_name);
+ LOAD_MONO_FUNCTION(mono_assembly_name_get_culture);
LOAD_MONO_FUNCTION(mono_assembly_open);
LOAD_MONO_FUNCTION(mono_config_parse);
LOAD_MONO_FUNCTION(mono_class_from_mono_type);
@@ -1651,24 +1654,48 @@ HRESULT get_file_from_strongname(WCHAR* stringnameW, WCHAR* assemblies_path, int
return hr;
}
+static MonoAssembly* mono_assembly_try_load(WCHAR *path)
+{
+ MonoAssembly *result = NULL;
+ MonoImageOpenStatus stat;
+ char *pathA;
+
+ if (!(pathA = WtoA(path))) return NULL;
+
+ result = mono_assembly_open(pathA, &stat);
+ HeapFree(GetProcessHeap(), 0, pathA);
+
+ if (result) TRACE("found: %s\n", debugstr_w(path));
+ return result;
+}
+
static MonoAssembly* CDECL mono_assembly_preload_hook_fn(MonoAssemblyName *aname, char **assemblies_path, void *user_data)
{
HRESULT hr;
MonoAssembly *result=NULL;
char *stringname=NULL;
const char *assemblyname;
- LPWSTR stringnameW;
- int stringnameW_size;
+ const char *culture;
+ LPWSTR stringnameW, cultureW;
+ int stringnameW_size, cultureW_size;
WCHAR path[MAX_PATH];
char *pathA;
MonoImageOpenStatus stat;
DWORD search_flags;
int i;
static const WCHAR dotdllW[] = {'.','d','l','l',0};
- static const WCHAR slashW[] = {'\\',0};
+ static const WCHAR dotexeW[] = {'.','e','x','e',0};
stringname = mono_stringify_assembly_name(aname);
assemblyname = mono_assembly_name_get_name(aname);
+ culture = mono_assembly_name_get_culture(aname);
+ if (culture)
+ {
+ cultureW_size = MultiByteToWideChar(CP_UTF8, 0, culture, -1, NULL, 0);
+ cultureW = HeapAlloc(GetProcessHeap(), 0, cultureW_size * sizeof(WCHAR));
+ if (cultureW) MultiByteToWideChar(CP_UTF8, 0, culture, -1, cultureW, cultureW_size);
+ }
+ else cultureW = NULL;
TRACE("%s\n", debugstr_a(stringname));
@@ -1684,26 +1711,34 @@ static MonoAssembly* CDECL mono_assembly_preload_hook_fn(MonoAssemblyName *aname
MultiByteToWideChar(CP_UTF8, 0, assemblyname, -1, stringnameW, stringnameW_size);
for (i = 0; private_path[i] != NULL; i++)
{
+ /* This is the lookup order used in Mono */
+ /* 1st try: [culture]/[name].dll (culture may be empty) */
wcscpy(path, private_path[i]);
- wcscat(path, slashW);
- wcscat(path, stringnameW);
+ if (cultureW) PathAppendW(path, cultureW);
+ PathAppendW(path, stringnameW);
wcscat(path, dotdllW);
- pathA = WtoA(path);
- if (pathA)
- {
- result = mono_assembly_open(pathA, &stat);
- if (result)
- {
- TRACE("found: %s\n", debugstr_w(path));
- HeapFree(GetProcessHeap(), 0, pathA);
- HeapFree(GetProcessHeap(), 0, stringnameW);
- mono_free(stringname);
- return result;
- }
- HeapFree(GetProcessHeap(), 0, pathA);
- }
+ result = mono_assembly_try_load(path);
+ if (result) break;
+
+ /* 2nd try: [culture]/[name].exe (culture may be empty) */
+ wcscpy(path + wcslen(path) - wcslen(dotdllW), dotexeW);
+ result = mono_assembly_try_load(path);
+ if (result) break;
+
+ /* 3rd try: [culture]/[name]/[name].dll (culture may be empty) */
+ path[wcslen(path) - wcslen(dotexeW)] = 0;
+ PathAppendW(path, stringnameW);
+ wcscat(path, dotdllW);
+ result = mono_assembly_try_load(path);
+ if (result) break;
+
+ /* 4th try: [culture]/[name]/[name].exe (culture may be empty) */
+ wcscpy(path + wcslen(path) - wcslen(dotdllW), dotexeW);
+ result = mono_assembly_try_load(path);
+ if (result) break;
}
HeapFree(GetProcessHeap(), 0, stringnameW);
+ if (result) goto done;
}
}
@@ -1745,6 +1780,8 @@ static MonoAssembly* CDECL mono_assembly_preload_hook_fn(MonoAssemblyName *aname
else
TRACE("skipping Windows GAC search due to override setting\n");
+done:
+ if (cultureW) HeapFree(GetProcessHeap(), 0, cultureW);
mono_free(stringname);
return result;
diff --git a/dlls/mscoree/tests/loadpaths.dll.cs b/dlls/mscoree/tests/loadpaths.dll.cs
new file mode 100644
index 00000000000..99732b011d8
--- /dev/null
+++ b/dlls/mscoree/tests/loadpaths.dll.cs
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 Rémi Bernon for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+using System.Reflection;
+
+#if NEUTRAL
+[assembly: AssemblyCulture("")]
+#else
+[assembly: AssemblyCulture("en")]
+#endif
+
+namespace LoadPaths
+{
+ public class Test2
+ {
+ public int Foo() { return 0; }
+ }
+}
diff --git a/dlls/mscoree/tests/loadpaths.exe.config b/dlls/mscoree/tests/loadpaths.exe.config
new file mode 100644
index 00000000000..be6d9fb95cd
--- /dev/null
+++ b/dlls/mscoree/tests/loadpaths.exe.config
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <probing privatePath="private"/>
+ </assemblyBinding>
+ </runtime>
+</configuration>
diff --git a/dlls/mscoree/tests/loadpaths.exe.cs b/dlls/mscoree/tests/loadpaths.exe.cs
new file mode 100644
index 00000000000..22c32603c59
--- /dev/null
+++ b/dlls/mscoree/tests/loadpaths.exe.cs
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2021 Rémi Bernon for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+namespace LoadPaths
+{
+ public static class Test
+ {
+ static int Main(string[] args)
+ {
+ return new Test2().Foo();
+ }
+ }
+}
diff --git a/dlls/mscoree/tests/mscoree.c b/dlls/mscoree/tests/mscoree.c
index 26c06246a94..4be3da8c731 100644
--- a/dlls/mscoree/tests/mscoree.c
+++ b/dlls/mscoree/tests/mscoree.c
@@ -538,6 +538,229 @@ static void test_createinstance(void)
}
}
+static BOOL write_resource(const WCHAR *resource, const WCHAR *filename)
+{
+ HANDLE file;
+ HRSRC rsrc;
+ void *data;
+ DWORD size;
+ BOOL ret;
+
+ rsrc = FindResourceW(GetModuleHandleW(NULL), resource, MAKEINTRESOURCEW(RT_RCDATA));
+ if (!rsrc) return FALSE;
+
+ data = LockResource(LoadResource(GetModuleHandleA(NULL), rsrc));
+ if (!data) return FALSE;
+
+ size = SizeofResource(GetModuleHandleA(NULL), rsrc);
+ if (!size) return FALSE;
+
+ file = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
+ if (file == INVALID_HANDLE_VALUE) return FALSE;
+
+ ret = WriteFile(file, data, size, &size, NULL);
+ CloseHandle(file);
+ return ret;
+}
+
+static BOOL compile_cs(const WCHAR *source, const WCHAR *target, const WCHAR *type, const WCHAR *args)
+{
+ static const WCHAR *csc = L"C:\\windows\\Microsoft.NET\\Framework\\v2.0.50727\\csc.exe";
+ WCHAR cmdline[2 * MAX_PATH + 74];
+ PROCESS_INFORMATION pi;
+ STARTUPINFOW si = { 0 };
+ BOOL ret;
+
+ if (!PathFileExistsW(csc))
+ {
+ skip("Can't find csc.exe\n");
+ return FALSE;
+ }
+
+ swprintf(cmdline, ARRAY_SIZE(cmdline), L"%s /t:%s %s /out:\"%s\" \"%s\"", csc, type, args, target, source);
+
+ si.cb = sizeof(si);
+ ret = CreateProcessW(csc, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+ ok(ret, "Could not create process: %u\n", GetLastError());
+
+ wait_child_process(pi.hProcess);
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+
+ ret = PathFileExistsW(target);
+ ok(ret, "Compilation failed\n");
+
+ return ret;
+}
+
+static void test_loadpaths_execute(const WCHAR *exe_name, const WCHAR *dll_name, const WCHAR *cfg_name,
+ const WCHAR *dll_dest, BOOL expect_failure, BOOL todo)
+{
+ WCHAR tmp[MAX_PATH], tmpdir[MAX_PATH], tmpexe[MAX_PATH], tmpcfg[MAX_PATH], tmpdll[MAX_PATH];
+ PROCESS_INFORMATION pi;
+ STARTUPINFOW si = { 0 };
+ WCHAR *ptr, *end;
+ DWORD exit_code = 0xdeadbeef;
+ LUID id;
+ BOOL ret;
+
+ GetTempPathW(MAX_PATH, tmp);
+ ret = AllocateLocallyUniqueId(&id);
+ ok(ret, "AllocateLocallyUniqueId failed: %u\n", GetLastError());
+ ret = GetTempFileNameW(tmp, L"loadpaths", id.LowPart, tmpdir);
+ ok(ret, "GetTempFileNameW failed: %u\n", GetLastError());
+
+ ret = CreateDirectoryW(tmpdir, NULL);
+ ok(ret, "CreateDirectoryW(%s) failed: %u\n", debugstr_w(tmpdir), GetLastError());
+
+ wcscpy(tmpexe, tmpdir);
+ PathAppendW(tmpexe, exe_name);
+ ret = CopyFileW(exe_name, tmpexe, FALSE);
+ ok(ret, "CopyFileW(%s) failed: %u\n", debugstr_w(tmpexe), GetLastError());
+
+ if (cfg_name)
+ {
+ wcscpy(tmpcfg, tmpdir);
+ PathAppendW(tmpcfg, cfg_name);
+ ret = CopyFileW(cfg_name, tmpcfg, FALSE);
+ ok(ret, "CopyFileW(%s) failed: %u\n", debugstr_w(tmpcfg), GetLastError());
+ }
+
+ ptr = tmpdir + wcslen(tmpdir);
+ PathAppendW(tmpdir, dll_dest);
+ while (*ptr && (ptr = wcschr(ptr + 1, '\\')))
+ {
+ *ptr = '\0';
+ ret = CreateDirectoryW(tmpdir, NULL);
+ ok(ret, "CreateDirectoryW(%s) failed: %u\n", debugstr_w(tmpdir), GetLastError());
+ *ptr = '\\';
+ }
+
+ wcscpy(tmpdll, tmpdir);
+ if ((ptr = wcsrchr(tmpdir, '\\'))) *ptr = '\0';
+
+ ret = CopyFileW(dll_name, tmpdll, FALSE);
+ ok(ret, "CopyFileW(%s) failed: %u\n", debugstr_w(tmpdll), GetLastError());
+
+ si.cb = sizeof(si);
+ ret = CreateProcessW(tmpexe, tmpexe, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+ ok(ret, "CreateProcessW(%s) failed: %u\n", debugstr_w(tmpexe), GetLastError());
+
+ if (expect_failure) ret = WaitForSingleObject(pi.hProcess, 500);
+ else
+ {
+ ret = WaitForSingleObject(pi.hProcess, 5000);
+ ok(ret == WAIT_OBJECT_0, "%s: WaitForSingleObject returned %d: %u\n", debugstr_w(dll_dest), ret, GetLastError());
+ }
+
+ GetExitCodeProcess(pi.hProcess, &exit_code);
+ if (ret == WAIT_TIMEOUT) TerminateProcess(pi.hProcess, 0xdeadbeef);
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+
+ if (expect_failure) todo_wine_if(todo) ok(exit_code != 0, "%s: Succeeded to execute process\n", debugstr_w(dll_dest));
+ else ok(exit_code == 0, "%s: Failed to execute process\n", debugstr_w(dll_dest));
+
+ /* sometimes the failing process never returns, in which case cleaning up won't work */
+ if (ret == WAIT_TIMEOUT && expect_failure) return;
+
+ if (cfg_name)
+ {
+ ret = DeleteFileW(tmpcfg);
+ ok(ret, "DeleteFileW(%s) failed: %u\n", debugstr_w(tmpcfg), GetLastError());
+ }
+ ret = DeleteFileW(tmpdll);
+ ok(ret, "DeleteFileW(%s) failed: %u\n", debugstr_w(tmpdll), GetLastError());
+ ret = DeleteFileW(tmpexe);
+ ok(ret, "DeleteFileW(%s) failed: %u\n", debugstr_w(tmpexe), GetLastError());
+
+ end = tmpdir + wcslen(tmp);
+ ptr = tmpdir + wcslen(tmpdir) - 1;
+ while (ptr > end && (ptr = wcsrchr(tmpdir, '\\')))
+ {
+ ret = RemoveDirectoryW(tmpdir);
+ ok(ret, "RemoveDirectoryW(%s) failed: %u\n", debugstr_w(tmpdir), GetLastError());
+ *ptr = '\0';
+ }
+}
+
+static void test_loadpaths(BOOL neutral)
+{
+ static const WCHAR *loadpaths[] = {L"", L"en", L"libloadpaths", L"en\\libloadpaths"};
+ static const WCHAR *dll_source = L"loadpaths.dll.cs";
+ static const WCHAR *dll_name = L"libloadpaths.dll";
+ static const WCHAR *exe_source = L"loadpaths.exe.cs";
+ static const WCHAR *exe_name = L"loadpaths.exe";
+ static const WCHAR *cfg_name = L"loadpaths.exe.config";
+ WCHAR tmp[MAX_PATH];
+ BOOL ret;
+ int i;
+
+ DeleteFileW(dll_source);
+ ret = write_resource(dll_source, dll_source);
+ ok(ret, "Could not write resource: %u\n", GetLastError());
+ DeleteFileW(dll_name);
+ ret = compile_cs(dll_source, dll_name, L"library", neutral ? L"-define:NEUTRAL" : L"");
+ if (!ret) return;
+ ret = DeleteFileW(dll_source);
+ ok(ret, "DeleteFileW failed: %u\n", GetLastError());
+
+ DeleteFileW(exe_source);
+ ret = write_resource(exe_source, exe_source);
+ ok(ret, "Could not write resource: %u\n", GetLastError());
+ DeleteFileW(exe_name);
+ ret = compile_cs(exe_source, exe_name, L"exe", L"/reference:libloadpaths.dll");
+ if (!ret) return;
+ ret = DeleteFileW(exe_source);
+ ok(ret, "DeleteFileW failed: %u\n", GetLastError());
+
+ DeleteFileW(cfg_name);
+ ret = write_resource(cfg_name, cfg_name);
+ ok(ret, "Could not write resource: %u\n", GetLastError());
+
+ for (i = 0; i < ARRAY_SIZE(loadpaths); ++i)
+ {
+ const WCHAR *path = loadpaths[i];
+ BOOL expect_failure = neutral ? wcsstr(path, L"en") != NULL
+ : wcsstr(path, L"en") == NULL;
+
+ wcscpy(tmp, path);
+ PathAppendW(tmp, dll_name);
+ test_loadpaths_execute(exe_name, dll_name, NULL, tmp, expect_failure, !neutral && !*path);
+
+ wcscpy(tmp, L"private");
+ if (*path) PathAppendW(tmp, path);
+ PathAppendW(tmp, dll_name);
+
+ test_loadpaths_execute(exe_name, dll_name, NULL, tmp, TRUE, FALSE);
+ test_loadpaths_execute(exe_name, dll_name, cfg_name, tmp, expect_failure, FALSE);
+
+ /* exe name for dll should work too */
+ if (*path)
+ {
+ wcscpy(tmp, path);
+ PathAppendW(tmp, dll_name);
+ wcscpy(tmp + wcslen(tmp) - 4, L".exe");
+ test_loadpaths_execute(exe_name, dll_name, NULL, tmp, expect_failure, FALSE);
+ }
+
+ wcscpy(tmp, L"private");
+ if (*path) PathAppendW(tmp, path);
+ PathAppendW(tmp, dll_name);
+ wcscpy(tmp + wcslen(tmp) - 4, L".exe");
+
+ test_loadpaths_execute(exe_name, dll_name, NULL, tmp, TRUE, FALSE);
+ test_loadpaths_execute(exe_name, dll_name, cfg_name, tmp, expect_failure, FALSE);
+ }
+
+ ret = DeleteFileW(cfg_name);
+ ok(ret, "DeleteFileW failed: %u\n", GetLastError());
+ ret = DeleteFileW(exe_name);
+ ok(ret, "DeleteFileW failed: %u\n", GetLastError());
+ ret = DeleteFileW(dll_name);
+ ok(ret, "DeleteFileW failed: %u\n", GetLastError());
+}
+
static void test_createdomain(void)
{
static const WCHAR test_name[] = {'t','e','s','t',0};
@@ -650,5 +873,8 @@ START_TEST(mscoree)
test_createdomain();
}
+ test_loadpaths(FALSE);
+ test_loadpaths(TRUE);
+
FreeLibrary(hmscoree);
}
diff --git a/dlls/mscoree/tests/resource.rc b/dlls/mscoree/tests/resource.rc
index 9a1b89f6569..34516f744a0 100644
--- a/dlls/mscoree/tests/resource.rc
+++ b/dlls/mscoree/tests/resource.rc
@@ -28,3 +28,12 @@ comtest_exe.manifest RCDATA comtest_exe.manifest
/* @makedep: comtest_dll.manifest */
comtest_dll.manifest RCDATA comtest_dll.manifest
+
+/* @makedep: loadpaths.exe.cs */
+loadpaths.exe.cs RCDATA loadpaths.exe.cs
+
+/* @makedep: loadpaths.dll.cs */
+loadpaths.dll.cs RCDATA loadpaths.dll.cs
+
+/* @makedep: loadpaths.exe.config */
+loadpaths.exe.config RCDATA loadpaths.exe.config
--
2.30.0
Feb. 2, 2021
[PATCH 5/5] include: Add Windows.Media.SpeechSynthesis.SpeechSynthesizer runtimeclass.
by Rémi Bernon
As an illustration for the newly supported attributes.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
include/windows.media.speechsynthesis.idl | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/include/windows.media.speechsynthesis.idl b/include/windows.media.speechsynthesis.idl
index 502261f79c6..87497678f30 100644
--- a/include/windows.media.speechsynthesis.idl
+++ b/include/windows.media.speechsynthesis.idl
@@ -24,10 +24,16 @@ import "inspectable.idl";
import "windows.foundation.idl";
namespace Windows {
+ namespace Foundation {
+ interface IClosable;
+ }
namespace Media {
namespace SpeechSynthesis {
typedef enum VoiceGender VoiceGender;
interface IInstalledVoicesStatic;
+ interface IInstalledVoicesStatic2;
+ interface ISpeechSynthesizer;
+ interface ISpeechSynthesizer2;
interface IVoiceInformation;
runtimeclass VoiceInformation;
}
@@ -66,6 +72,20 @@ namespace Windows {
{
[default] interface Windows.Media.SpeechSynthesis.IVoiceInformation;
}
+
+ [
+ activatable(Windows.Foundation.UniversalApiContract, 1.0),
+ contract(Windows.Foundation.UniversalApiContract, 1.0),
+ marshaling_behavior(agile),
+ static(Windows.Media.SpeechSynthesis.IInstalledVoicesStatic, Windows.Foundation.UniversalApiContract, 1.0),
+ static(Windows.Media.SpeechSynthesis.IInstalledVoicesStatic2, Windows.Foundation.UniversalApiContract, 5.0)
+ ]
+ runtimeclass SpeechSynthesizer
+ {
+ [default] interface Windows.Media.SpeechSynthesis.ISpeechSynthesizer;
+ interface Windows.Foundation.IClosable;
+ [contract(Windows.Foundation.UniversalApiContract, 4.0)] interface Windows.Media.SpeechSynthesis.ISpeechSynthesizer2;
+ }
}
}
}
--
2.30.0
Feb. 2, 2021
[PATCH 4/5] widl: Support WinRT static attribute parsing.
by Rémi Bernon
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
tools/widl/parser.l | 1 +
tools/widl/parser.y | 8 ++++++++
tools/widl/widltypes.h | 1 +
3 files changed, 10 insertions(+)
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index 264fa7f906c..af09b550317 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -427,6 +427,7 @@ static const struct keyword attr_keywords[] =
{"size_is", tSIZEIS, 0},
{"source", tSOURCE, 0},
{"standard", tSTANDARD, 1},
+ {"static", tSTATIC, 1},
{"strict_context_handle", tSTRICTCONTEXTHANDLE, 0},
{"string", tSTRING, 0},
{"switch_is", tSWITCHIS, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 3b7953ae19c..2ff5e0b5b3c 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -286,6 +286,7 @@ static typelib_t *current_typelib;
%type <expr> m_expr expr expr_const expr_int_const array m_bitfield
%type <expr_list> m_exprs /* exprs expr_list */ expr_list_int_const
%type <expr> contract_req
+%type <expr> static_attr
%type <type> interfacehdr
%type <stgclass> storage_cls_spec
%type <type_qualifier> type_qualifier m_type_qual_list
@@ -542,6 +543,11 @@ contract_req: decl_spec ',' contract_ver { if ($1->type->type_type != TYPE_APICO
$$ = make_exprt(EXPR_GTREQL, declare_var(NULL, $1, make_declarator(NULL), 0), $$);
}
+static_attr: decl_spec ',' contract_req { if ($1->type->type_type != TYPE_INTERFACE)
+ error_loc("type %s is not an interface\n", $1->type->name);
+ $$ = make_exprt(EXPR_MEMBER, declare_var(NULL, $1, make_declarator(NULL), 0), $3);
+ }
+
attribute: { $$ = NULL; }
| tACTIVATABLE '(' contract_req ')' { $$ = make_attrp(ATTR_ACTIVATABLE, $3); }
| tAGGREGATABLE { $$ = make_attr(ATTR_AGGREGATABLE); }
@@ -640,6 +646,7 @@ attribute: { $$ = NULL; }
| tRETVAL { $$ = make_attr(ATTR_RETVAL); }
| tSIZEIS '(' m_exprs ')' { $$ = make_attrp(ATTR_SIZEIS, $3); }
| tSOURCE { $$ = make_attr(ATTR_SOURCE); }
+ | tSTATIC '(' static_attr ')' { $$ = make_attrp(ATTR_STATIC, $3); }
| tSTRICTCONTEXTHANDLE { $$ = make_attr(ATTR_STRICTCONTEXTHANDLE); }
| tSTRING { $$ = make_attr(ATTR_STRING); }
| tSWITCHIS '(' expr ')' { $$ = make_attrp(ATTR_SWITCHIS, $3); }
@@ -2339,6 +2346,7 @@ struct allowed_attr allowed_attr[] =
/* ATTR_RETVAL */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "retval" },
/* ATTR_SIZEIS */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "size_is" },
/* ATTR_SOURCE */ { 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "source" },
+ /* ATTR_STATIC */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "static" },
/* ATTR_STRICTCONTEXTHANDLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "strict_context_handle" },
/* ATTR_STRING */ { 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "string" },
/* ATTR_SWITCHIS */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, "switch_is" },
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 5d4532d6434..facfff21453 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -163,6 +163,7 @@ enum attr_type
ATTR_RETVAL,
ATTR_SIZEIS,
ATTR_SOURCE,
+ ATTR_STATIC,
ATTR_STRICTCONTEXTHANDLE,
ATTR_STRING,
ATTR_SWITCHIS,
--
2.30.0
Feb. 2, 2021
[PATCH 3/5] widl: Support WinRT activatable attribute parsing.
by Rémi Bernon
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
tools/widl/parser.l | 1 +
tools/widl/parser.y | 3 +++
tools/widl/widltypes.h | 1 +
3 files changed, 5 insertions(+)
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index 7e20d30e7f0..264fa7f906c 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -320,6 +320,7 @@ static const struct keyword keywords[] = {
*/
static const struct keyword attr_keywords[] =
{
+ {"activatable", tACTIVATABLE, 1},
{"aggregatable", tAGGREGATABLE, 0},
{"agile", tAGILE, 1},
{"all_nodes", tALLNODES, 0},
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 1e3e254ec8c..3b7953ae19c 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -176,6 +176,7 @@ static typelib_t *current_typelib;
%token GREATEREQUAL LESSEQUAL
%token LOGICALOR LOGICALAND
%token ELLIPSIS
+%token tACTIVATABLE
%token tAGGREGATABLE
%token tAGILE
%token tALLNODES tALLOCATE tANNOTATION
@@ -542,6 +543,7 @@ contract_req: decl_spec ',' contract_ver { if ($1->type->type_type != TYPE_APICO
}
attribute: { $$ = NULL; }
+ | tACTIVATABLE '(' contract_req ')' { $$ = make_attrp(ATTR_ACTIVATABLE, $3); }
| tAGGREGATABLE { $$ = make_attr(ATTR_AGGREGATABLE); }
| tANNOTATION '(' aSTRING ')' { $$ = make_attrp(ATTR_ANNOTATION, $3); }
| tAPPOBJECT { $$ = make_attr(ATTR_APPOBJECT); }
@@ -2243,6 +2245,7 @@ struct allowed_attr
struct allowed_attr allowed_attr[] =
{
/* attr { D ACF M I Fn ARG T En Enm St Un Fi L DI M C AC R <display name> } */
+ /* ATTR_ACTIVATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, "activatable" },
/* ATTR_AGGREGATABLE */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, "aggregatable" },
/* ATTR_ALLOCATE */ { 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "allocate" },
/* ATTR_ANNOTATION */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "annotation" },
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 0fba33d6a09..5d4532d6434 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -69,6 +69,7 @@ typedef struct list warning_list_t;
enum attr_type
{
+ ATTR_ACTIVATABLE,
ATTR_AGGREGATABLE,
ATTR_ALLOCATE,
ATTR_ANNOTATION,
--
2.30.0
Feb. 2, 2021