From: Hans Leidekker hans@codeweavers.com
Note that this treats winmd files as architecture independent data files even though native stores them in both system32/winmetadata and syswow64/winmetadata. They are 32-bit dlls in both locations and while there are small differences in file sizes their content is not materially different. --- tools/makedep.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
diff --git a/tools/makedep.c b/tools/makedep.c index 9e4e147e4d9..09653a2066b 100644 --- a/tools/makedep.c +++ b/tools/makedep.c @@ -102,6 +102,7 @@ struct incl_file #define FLAG_C_UNIX 0x080000 /* file is part of a Unix library */ #define FLAG_SFD_FONTS 0x100000 /* sfd file generated bitmap fonts */ #define FLAG_ARM64EC_X64 0x200000 /* use x86_64 object on ARM64EC */ +#define FLAG_IDL_WINMD 0x400000 /* generates a metadata (.winmd) file */
static const struct { @@ -116,6 +117,7 @@ static const struct { FLAG_IDL_PROXY, "_p.c" }, { FLAG_IDL_SERVER, "_s.c" }, { FLAG_IDL_REGISTER, "_r.res" }, + { FLAG_IDL_WINMD, ".winmd" }, };
#define HASH_SIZE 197 @@ -1014,6 +1016,7 @@ static void parse_pragma_directive( struct file *source, char *str ) else if (!strcmp( flag, "typelib" )) source->flags |= FLAG_IDL_TYPELIB; else if (!strcmp( flag, "register" )) source->flags |= FLAG_IDL_REGISTER; else if (!strcmp( flag, "regtypelib" )) source->flags |= FLAG_IDL_REGTYPELIB; + else if (!strcmp( flag, "winmd" )) source->flags |= FLAG_IDL_WINMD; } else if (strendswith( source->name, ".rc" )) { @@ -2899,6 +2902,36 @@ static void output_source_res( struct makefile *make, struct incl_file *source, strarray_add( &make->res_files[source->arch], source->name ); }
+/******************************************************************* + * output_source_winmd + */ +static void output_source_winmd( struct makefile *make, struct incl_file *source, const char *obj ) +{ + struct strarray defines = get_source_defines( make, source, obj ); + struct strarray targets = empty_strarray; + char *name = strmake( "%s.winmd", obj ); + + strarray_add( &targets, name ); + strarray_add( &make->clean_files, name ); + strarray_add( &make->all_targets[0], name ); + + output_filenames_obj_dir( make, targets ); + output( ":" ); + output_filename( widl ); + output_filename( source->filename ); + output_filenames( source->dependencies ); + output( "\n" ); + + output_filenames_obj_dir( make, targets ); + output( ":\n" ); + output( "\t%s%s --winmd -o $@", cmd_prefix( "WIDL" ), widl ); + output_filename( "--nostdinc" ); + output_filenames( defines ); + output_filenames( get_expanded_make_var_array( make, "EXTRAIDLFLAGS" )); + output_filenames( get_expanded_file_local_var( make, obj, "EXTRAIDLFLAGS" )); + output_filename( source->filename ); + output( "\n" ); +}
/******************************************************************* * output_source_idl @@ -2912,6 +2945,8 @@ static void output_source_idl( struct makefile *make, struct incl_file *source, const char *dest; unsigned int i, arch;
+ if (source->file->flags & FLAG_IDL_WINMD) return output_source_winmd( make, source, obj ); + if (find_include_file( make, strmake( "%s.h", obj ))) source->file->flags |= FLAG_IDL_HEADER; if (!source->file->flags) return;
From: Hans Leidekker hans@codeweavers.com
--- include/windows.networking.idl | 1 + loader/wine.inf.in | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/include/windows.networking.idl b/include/windows.networking.idl index 2dfa25649a3..5264b04f3cf 100644 --- a/include/windows.networking.idl +++ b/include/windows.networking.idl @@ -17,6 +17,7 @@ */
#ifdef __WIDL__ +#pragma makedep winmd #pragma winrt ns_prefix #endif
diff --git a/loader/wine.inf.in b/loader/wine.inf.in index 892078a4a96..870a4cf5f66 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -54,7 +54,7 @@ AddService=MountMgr,0x800,MountMgrService RegisterDlls=RegisterDllsSection WineFakeDlls=FakeDlls UpdateInis=SystemIni -CopyFiles=ColorFiles,EtcFiles,InfFiles,NlsFiles,SortFiles +CopyFiles=ColorFiles,EtcFiles,InfFiles,NlsFiles,SortFiles,WinmdFiles AddReg=\ Classes,\ ContentIndex,\ @@ -111,7 +111,7 @@ AddReg=\ [BaseWow64Install] RegisterDlls=RegisterDllsSection WineFakeDlls=FakeDllsWin32,FakeDllsWow64 -CopyFiles=NlsFiles +CopyFiles=NlsFiles,WinmdFiles AddReg=\ CurrentVersion,\ Debugger,\ @@ -1298,6 +1298,10 @@ sortdefault.nls [WineSourceDirs] NlsFiles = nls SortFiles = nls +WinmdFiles = include + +[WinmdFiles] +windows.networking.winmd
[DestinationDirs] ColorFiles = 23 @@ -1305,3 +1309,4 @@ EtcFiles = 12,etc InfFiles = 17 NlsFiles = 11 SortFiles = 10,globalization\sorting +WinmdFiles = 11,winmetadata
Is there a way we can also make makedep add the generated metadata as a resource for unit tests? I have a draft branch that implements `dlls/rometadata`, and it would be nice to use widl-generated winmd files to test `IMetaDataImport` and friends instead of manually defining it in C code, which is quite unergonomic.
On Fri Sep 19 09:32:15 2025 +0000, Vibhav Pant wrote:
Is there a way we can also make makedep add the generated metadata as a resource for unit tests? I have a draft branch that implements `dlls/rometadata`, and it would be nice to use widl-generated winmd files to test `IMetaDataImport` and friends instead of manually defining it in C code, which is quite unergonomic.
Could it use metadata files that are already preinstalled?
On Fri Sep 19 09:32:15 2025 +0000, Nikolay Sivov wrote:
Could it use metadata files that are already preinstalled?
Sure, but I think testing against pre-installed metadata would also mean that the tests would need to account for subtle differences between the Wine and native versions of the file (for instance, order of entries). I feel that could lead to the tests being potentially brittle. I was more thinking of something like `dlls/oleaut32/tests/test_tlb.idl`, where the IDL (and the generated typelib) is a part of the tests.
On Fri Sep 19 09:49:24 2025 +0000, Vibhav Pant wrote:
Sure, but I think testing against pre-installed metadata would also mean that the tests would need to account for subtle differences between the Wine and native versions of the file (for instance, order of entries). I feel that could lead to the tests being potentially brittle. I was more thinking of something like `dlls/oleaut32/tests/test_tlb.idl`, where the IDL (and the generated typelib) is a part of the tests.
Typelib situation is different, because stdole typelib does not contain much to begin with. Metadata files are going to contain most of the things as I understand. Do they have API to create metadata files?
If API-visible things like order of elements is different, that should be addressed I think.
Typelib situation is different, because stdole typelib does not contain much to begin with. Metadata files are going to contain most of the things as I understand.
From what I understand, winmd files are the WinRT equivalent of typelibs. Both contain descriptions for interfaces/struct/enums/(runtime)classes/etc. Native also uses them to generate proxy/stubs from winmd metadata, like typelib marshaling.
Do they have API to create metadata files?
There's [`IMetaDataDispenser::DefineScope`](https://learn.microsoft.com/en-us/windows/win32/api/rometadataapi/nf-rometad...), which lets you get a `IMetaDataEmit` to emit metadata tables. This is probably what MIDL is using in the first place.
If API-visible things like order of elements is different, that should be addressed I think.
I believe that depends on how the order of how the types are defined/declares in the IDL file itself. I'm pretty sure that's also not guaranteed to be stable between updates/releases.
If API-visible things like order of elements is different, that should be addressed I think.
I believe that depends on how the order of how the types are defined/declares in the IDL file itself. I'm pretty sure that's also not guaranteed to be stable between updates/releases.
Then there is no need to test it.
On Fri Sep 19 10:11:30 2025 +0000, Nikolay Sivov wrote:
If API-visible things like order of elements is different, that
should be addressed I think.
I believe that depends on how the order of how the types are
defined/declares in the IDL file itself. I'm pretty sure that's also not guaranteed to be stable between updates/releases. Then there is no need to test it.
Apologies, I didn't mean that we need to test the order itself, but that the tests cannot assume that the entries are in a fixed order, so we'd need to enumerate through all of them and keep track of which ones are missing/found, which might be error prone at times.