This MR introduces a few minor changes to widl to support generating proxy code for WinRT's parameterized interfaces:
* Use the mangled, C-friendly interface name for naming variables `FormatStringOffsetTable`, `StubThunkTable`, etc) in proxy and stub code. * Use the default interface of a runtime class while creating type format strings in `write_ip_tfs`. * When proxy generation is enabled, also compute UUIDs for all specialized parameterized interface declarations in imported files.
Finally, I have also enabled proxy generation and registration for wintypes.dll as an example. We use the `PROXY_CLSID_IS` define as WinRT IDLs cannot use `coclass` to declare the `PSFactoryBuffer` class for the DLL.
-- v3: wintypes: Register proxies for interfaces. include: Add size and length annotations for IVector(View) and IIterator method params. include: Remove duplicate interface declarations.
From: Vibhav Pant vibhavp@gmail.com
This allows widl to generate legal C names for interfaces that have a namespace and/or are parameterized. --- tools/widl/proxy.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-)
diff --git a/tools/widl/proxy.c b/tools/widl/proxy.c index 9982efc635e..f2f3cdcf837 100644 --- a/tools/widl/proxy.c +++ b/tools/widl/proxy.c @@ -594,6 +594,7 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset) int first_func = 1; int needs_stub_thunks = 0; int needs_inline_stubs = need_inline_stubs( iface ) || need_delegation( iface ); + const char *name = iface->c_name ? iface->c_name : iface->name;
STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) { var_t *func = stmt->u.var; @@ -632,7 +633,7 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset)
count = count_methods(iface);
- print_proxy( "static const unsigned short %s_FormatStringOffsetTable[] =\n", iface->name ); + print_proxy( "static const unsigned short %s_FormatStringOffsetTable[] =\n", name ); print_proxy( "{\n" ); indent++; write_proxy_procformatstring_offsets( iface, 0 ); @@ -642,12 +643,12 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset) /* proxy info */ if (interpreted_mode) { - print_proxy( "static const MIDL_STUBLESS_PROXY_INFO %s_ProxyInfo =\n", iface->name ); + print_proxy( "static const MIDL_STUBLESS_PROXY_INFO %s_ProxyInfo =\n", name ); print_proxy( "{\n" ); indent++; print_proxy( "&Object_StubDesc,\n" ); print_proxy( "__MIDL_ProcFormatString.Format,\n" ); - print_proxy( "&%s_FormatStringOffsetTable[-3],\n", iface->name ); + print_proxy( "&%s_FormatStringOffsetTable[-3],\n", name ); print_proxy( "0,\n" ); print_proxy( "0,\n" ); print_proxy( "0\n" ); @@ -658,13 +659,13 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset) /* proxy vtable */ print_proxy( "static %sCINTERFACE_PROXY_VTABLE(%d) _%sProxyVtbl =\n", (interpreted_mode || need_delegation_indirect(iface)) ? "" : "const ", - count, iface->name); + count, name); print_proxy( "{\n"); indent++; print_proxy( "{\n"); indent++; - if (interpreted_mode) print_proxy( "&%s_ProxyInfo,\n", iface->name ); - print_proxy( "&IID_%s,\n", iface->name); + if (interpreted_mode) print_proxy( "&%s_ProxyInfo,\n", name ); + print_proxy( "&IID_%s,\n", name); indent--; print_proxy( "},\n"); print_proxy( "{\n"); @@ -678,7 +679,7 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset) /* stub thunk table */ if (needs_stub_thunks) { - print_proxy( "static const STUB_THUNK %s_StubThunkTable[] =\n", iface->name); + print_proxy( "static const STUB_THUNK %s_StubThunkTable[] =\n", name); print_proxy( "{\n"); indent++; write_thunk_methods( iface, 0 ); @@ -687,15 +688,15 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset) }
/* server info */ - print_proxy( "static const MIDL_SERVER_INFO %s_ServerInfo =\n", iface->name ); + print_proxy( "static const MIDL_SERVER_INFO %s_ServerInfo =\n", name ); print_proxy( "{\n" ); indent++; print_proxy( "&Object_StubDesc,\n" ); print_proxy( "0,\n" ); print_proxy( "__MIDL_ProcFormatString.Format,\n" ); - print_proxy( "&%s_FormatStringOffsetTable[-3],\n", iface->name ); + print_proxy( "&%s_FormatStringOffsetTable[-3],\n", name ); if (needs_stub_thunks) - print_proxy( "&%s_StubThunkTable[-3],\n", iface->name ); + print_proxy( "&%s_StubThunkTable[-3],\n", name ); else print_proxy( "0,\n" ); print_proxy( "0,\n" ); @@ -707,7 +708,7 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset) /* stub vtable */ if (needs_inline_stubs) { - print_proxy( "static const PRPC_STUB_FUNCTION %s_table[] =\n", iface->name); + print_proxy( "static const PRPC_STUB_FUNCTION %s_table[] =\n", name); print_proxy( "{\n"); indent++; write_stub_methods(iface, FALSE); @@ -716,15 +717,15 @@ static void write_proxy(type_t *iface, unsigned int *proc_offset) fprintf(proxy, "};\n\n"); } print_proxy( "static %sCInterfaceStubVtbl _%sStubVtbl =\n", - need_delegation_indirect(iface) ? "" : "const ", iface->name); + need_delegation_indirect(iface) ? "" : "const ", name); print_proxy( "{\n"); indent++; print_proxy( "{\n"); indent++; - print_proxy( "&IID_%s,\n", iface->name); - print_proxy( "&%s_ServerInfo,\n", iface->name ); + print_proxy( "&IID_%s,\n", name); + print_proxy( "&%s_ServerInfo,\n", name ); print_proxy( "%d,\n", count); - if (needs_inline_stubs) print_proxy( "&%s_table[-3]\n", iface->name ); + if (needs_inline_stubs) print_proxy( "&%s_table[-3]\n", name ); else print_proxy( "0\n" ); indent--; print_proxy( "},\n"); @@ -945,7 +946,7 @@ static void write_proxy_routines(const statement_list_t *stmts) fprintf(proxy, "static const CInterfaceProxyVtbl* const _%s_ProxyVtblList[] =\n", file_id); fprintf(proxy, "{\n"); for (i = 0; i < count; i++) - fprintf(proxy, " (const CInterfaceProxyVtbl*)&_%sProxyVtbl,\n", interfaces[i]->name); + fprintf(proxy, " (const CInterfaceProxyVtbl*)&_%sProxyVtbl,\n", interfaces[i]->c_name ? interfaces[i]->c_name : interfaces[i]->name); fprintf(proxy, " 0\n"); fprintf(proxy, "};\n"); fprintf(proxy, "\n"); @@ -953,7 +954,7 @@ static void write_proxy_routines(const statement_list_t *stmts) fprintf(proxy, "static const CInterfaceStubVtbl* const _%s_StubVtblList[] =\n", file_id); fprintf(proxy, "{\n"); for (i = 0; i < count; i++) - fprintf(proxy, " &_%sStubVtbl,\n", interfaces[i]->name); + fprintf(proxy, " &_%sStubVtbl,\n", interfaces[i]->c_name ? interfaces[i]->c_name : interfaces[i]->name); fprintf(proxy, " 0\n"); fprintf(proxy, "};\n"); fprintf(proxy, "\n"); @@ -961,7 +962,7 @@ static void write_proxy_routines(const statement_list_t *stmts) fprintf(proxy, "static PCInterfaceName const _%s_InterfaceNamesList[] =\n", file_id); fprintf(proxy, "{\n"); for (i = 0; i < count; i++) - fprintf(proxy, " "%s",\n", interfaces[i]->name); + fprintf(proxy, " "%s",\n", interfaces[i]->c_name ? interfaces[i]->c_name : interfaces[i]->name); fprintf(proxy, " 0\n"); fprintf(proxy, "};\n"); fprintf(proxy, "\n");
From: Vibhav Pant vibhavp@gmail.com
--- tools/widl/typegen.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 76d7a2bde21..41cd3884431 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -3748,7 +3748,12 @@ static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *t else { const type_t *base = is_ptr(type) ? type_pointer_get_ref_type(type) : type; - const struct uuid *uuid = get_attrp(base->attrs, ATTR_UUID); + const struct uuid *uuid; + + if (base->type_type == TYPE_RUNTIMECLASS) + base = type_runtimeclass_get_default_iface(base, 1); + + uuid = get_attrp(base->attrs, ATTR_UUID);
if (! uuid) error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
From: Vibhav Pant vibhavp@gmail.com
--- tools/widl/parser.y | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y index e57b1412a80..c6cbdd9f613 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -102,6 +102,7 @@ static struct namespace global_namespace = { static struct namespace *current_namespace = &global_namespace; static struct namespace *parameters_namespace = NULL; static statement_list_t *parameterized_type_stmts = NULL; +static statement_list_t *imp_parameterized_type_stmts = NULL;
static typelib_t *current_typelib;
@@ -405,7 +406,9 @@ decl_block: tDECLARE '{' decl_statements '}' { $$ = $3; } imp_decl_statements : %empty { $$ = NULL; } | imp_decl_statements tINTERFACE qualified_type '<' parameterized_type_args '>' ';' - { $$ = append_statement($1, make_statement_reference( @$, type_parameterized_type_specialize_declare($3, $5) )); } + { if (do_proxies) imp_parameterized_type_stmts = append_statement( imp_parameterized_type_stmts, make_statement_parameterized_type(@$, $3, $5) ); + $$ = append_statement($1, make_statement_reference( @$, type_parameterized_type_specialize_declare($3, $5) )); + } ;
imp_decl_block @@ -2898,6 +2901,21 @@ static statement_list_t *append_parameterized_type_stmts(statement_list_t *stmts { statement_t *stmt, *next;
+ if (imp_parameterized_type_stmts) + LIST_FOR_EACH_ENTRY(stmt, imp_parameterized_type_stmts, statement_t, entry) + { + switch(stmt->type) + { + case STMT_TYPE: + stmt->u.type = type_parameterized_type_specialize_define(stmt->u.type); + stmt->is_defined = 1; + break; + default: + assert(0); + break; + } + } + if (stmts && parameterized_type_stmts) LIST_FOR_EACH_ENTRY_SAFE(stmt, next, parameterized_type_stmts, statement_t, entry) { switch(stmt->type)
From: Vibhav Pant vibhavp@gmail.com
--- include/windows.foundation.idl | 1 - 1 file changed, 1 deletion(-)
diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl index f4c1ea2800e..5cfe0f36fab 100644 --- a/include/windows.foundation.idl +++ b/include/windows.foundation.idl @@ -142,7 +142,6 @@ namespace Windows.Foundation { interface Windows.Foundation.AsyncOperationCompletedHandler<HSTRING>; interface Windows.Foundation.AsyncOperationCompletedHandler<IInspectable *>; interface Windows.Foundation.AsyncOperationCompletedHandler<boolean>; - interface Windows.Foundation.AsyncOperationCompletedHandler<HSTRING>; interface Windows.Foundation.AsyncOperationCompletedHandler<UINT32>; interface Windows.Foundation.AsyncOperationCompletedHandler<Windows.Foundation.Uri *>; interface Windows.Foundation.AsyncOperationProgressHandler<UINT32, UINT32>;
From: Vibhav Pant vibhavp@gmail.com
--- include/windows.foundation.collections.idl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/include/windows.foundation.collections.idl b/include/windows.foundation.collections.idl index 2a8fd55be7d..1c381d087f3 100644 --- a/include/windows.foundation.collections.idl +++ b/include/windows.foundation.collections.idl @@ -150,7 +150,7 @@ cpp_quote("#endif") [propget] HRESULT Current([out, retval] T *value); [propget] HRESULT HasCurrent([out, retval] boolean *value); HRESULT MoveNext([out, retval] boolean *value); - HRESULT GetMany([in] UINT32 items_size, [out] T *items, [out, retval] UINT32 *value); + HRESULT GetMany([in] UINT32 items_size, [out, size_is(items_size), length_is(*value)] T *items, [out, retval] UINT32 *value); }
[ @@ -252,7 +252,7 @@ cpp_quote("#endif") HRESULT GetAt([in] UINT32 index, [out, retval] T *value); [propget] HRESULT Size([out, retval] UINT32 *value); HRESULT IndexOf([in, optional] T element, [out] UINT32 *index, [out, retval] BOOLEAN *value); - HRESULT GetMany([in] UINT32 start_index, [in] UINT32 items_size, [out] T *items, [out, retval] UINT32 *value); + HRESULT GetMany([in] UINT32 start_index, [in] UINT32 items_size, [out, size_is(items_size), length_is(*value)] T *items, [out, retval] UINT32 *value); }
[ @@ -272,8 +272,8 @@ cpp_quote("#endif") HRESULT Append([in, optional] T value); HRESULT RemoveAtEnd(); HRESULT Clear(); - HRESULT GetMany([in] UINT32 start_index, [in] UINT32 items_size, [out] T *items, [out, retval] UINT32 *value); - HRESULT ReplaceAll([in] UINT32 count, [in] T *items); + HRESULT GetMany([in] UINT32 start_index, [in] UINT32 items_size, [out, size_is(items_size), length_is(*value)] T *items, [out, retval] UINT32 *value); + HRESULT ReplaceAll([in] UINT32 count, [in, size_is(count)] T *items); }
[
From: Vibhav Pant vibhavp@gmail.com
--- dlls/wintypes/Makefile.in | 8 ++++++-- dlls/wintypes/main.c | 6 ------ dlls/wintypes/wintypes.spec | 3 +++ dlls/wintypes/wintypes_proxy.idl | 25 +++++++++++++++++++++++++ loader/wine.inf.in | 1 + 5 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 dlls/wintypes/wintypes_proxy.idl
diff --git a/dlls/wintypes/Makefile.in b/dlls/wintypes/Makefile.in index fd370133cf8..2ad52b0480e 100644 --- a/dlls/wintypes/Makefile.in +++ b/dlls/wintypes/Makefile.in @@ -1,6 +1,6 @@ MODULE = wintypes.dll IMPORTLIB = wintypes -IMPORTS = combase +IMPORTS = combase rpcrt4
SOURCES = \ buffer.c \ @@ -8,4 +8,8 @@ SOURCES = \ main.c \ propertyset.c \ storage.c \ - wintypes_private.idl + wintypes_private.idl \ + wintypes_proxy.idl + +dlldata_EXTRADEFS = -DPROXY_DELEGATION -DREGISTER_PROXY_DLL \ + -DPROXY_CLSID_IS="{0x11659A23,0x5884,0x4D1B,{0x9C,0xF6,0x67,0xD6,0xF4,0xF9,0x0B,0x36}}" diff --git a/dlls/wintypes/main.c b/dlls/wintypes/main.c index 02121194956..72d6e2da59c 100644 --- a/dlls/wintypes/main.c +++ b/dlls/wintypes/main.c @@ -1712,12 +1712,6 @@ static struct property_value_statics property_value_statics = 1 };
-HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **out) -{ - FIXME("clsid %s, riid %s, out %p stub!\n", debugstr_guid(clsid), debugstr_guid(riid), out); - return CLASS_E_CLASSNOTAVAILABLE; -} - HRESULT WINAPI DllGetActivationFactory(HSTRING classid, IActivationFactory **factory) { const WCHAR *buffer = WindowsGetStringRawBuffer(classid, NULL); diff --git a/dlls/wintypes/wintypes.spec b/dlls/wintypes/wintypes.spec index a1eb0f3830d..bf5f4741281 100644 --- a/dlls/wintypes/wintypes.spec +++ b/dlls/wintypes/wintypes.spec @@ -1,6 +1,9 @@ +3 stdcall -private GetProxyDllInfo(ptr ptr) @ stdcall -private DllCanUnloadNow() @ stdcall -private DllGetActivationFactory(ptr ptr) @ stdcall -private DllGetClassObject(ptr ptr ptr) +@ stdcall -private DllRegisterServer() +@ stdcall -private DllUnregisterServer() @ stub RoCreateNonAgilePropertySet @ stub RoCreatePropertySetSerializer @ stub RoGetBufferMarshaler diff --git a/dlls/wintypes/wintypes_proxy.idl b/dlls/wintypes/wintypes_proxy.idl new file mode 100644 index 00000000000..9463b2d4d05 --- /dev/null +++ b/dlls/wintypes/wintypes_proxy.idl @@ -0,0 +1,25 @@ +/* + * Proxies for wintypes.dll + * + * Copyright 2025 Vibhav Pant + * + * 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 + */ + +#pragma makedep proxy +#pragma makedep register +#pragma winrt ns_prefix + +#include "windows.foundation.idl" diff --git a/loader/wine.inf.in b/loader/wine.inf.in index 892078a4a96..6e8369fc7ab 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -705,6 +705,7 @@ HKLM,SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x86,"Version",2,"14.42.344 11,,wmadmod.dll,1 11,,wmvdecod.dll,1 11,,iexplore.exe,1 +11,,wintypes.dll,1
; 32bit-only fake dlls [FakeDllsWin32]