From: Vibhav Pant vibhavp@gmail.com
--- dlls/rometadata/tests/Makefile.in | 1 + dlls/rometadata/tests/rometadata.c | 117 +++++++++++++++++++++++++++- dlls/rometadata/tests/rsrc.rc | 3 + dlls/rometadata/tests/test-enum.idl | 72 +++++++++++++++++ include/corhdr.h | 39 ++++++++++ 5 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 dlls/rometadata/tests/test-enum.idl
diff --git a/dlls/rometadata/tests/Makefile.in b/dlls/rometadata/tests/Makefile.in index 329f6a02473..1623a4904df 100644 --- a/dlls/rometadata/tests/Makefile.in +++ b/dlls/rometadata/tests/Makefile.in @@ -4,4 +4,5 @@ IMPORTS = combase rometadata SOURCES = \ rometadata.c \ rsrc.rc \ + test-enum.idl \ test-simple.idl diff --git a/dlls/rometadata/tests/rometadata.c b/dlls/rometadata/tests/rometadata.c index ad62d6759af..f347a574c11 100644 --- a/dlls/rometadata/tests/rometadata.c +++ b/dlls/rometadata/tests/rometadata.c @@ -1,5 +1,6 @@ /* * Copyright 2024 Zhiyi Zhang for CodeWeavers + * 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 @@ -21,6 +22,7 @@ #include <windows.h> #include "initguid.h" #include "cor.h" +#include "corhdr.h" #include "roapi.h" #include "rometadata.h" #include "rometadataapi.h" @@ -213,6 +215,7 @@ struct type_info DWORD exp_flags; const char *exp_name; const char *exp_namespace; + mdToken exp_base; };
struct column_info @@ -532,8 +535,8 @@ static void test_MetaDataDispenser_OpenScope(void) static const struct type_info type_defs[3] = { { 0, "<Module>", NULL }, - { TYPE_ATTR_INTERFACE | TYPE_ATTR_ABSTRACT | TYPE_ATTR_UNKNOWN, "ITest1", "Wine.Test" }, - { TYPE_ATTR_PUBLIC | TYPE_ATTR_SEALED | TYPE_ATTR_UNKNOWN, "Test1", "Wine.Test" }, + { tdInterface | tdAbstract | tdWindowsRuntime, "ITest1", "Wine.Test" }, + { tdPublic | tdSealed | tdWindowsRuntime, "Test1", "Wine.Test" }, }; const WCHAR *filename = load_resource(L"test-simple.winmd"); ULONG val = 0, i, guid_ctor_idx = 0, itest1_def_idx = 0; @@ -774,6 +777,115 @@ static void test_MetaDataDispenser_OpenScope(void) IMetaDataTables_Release(md_tables); }
+static void test_IMetaDataImport(void) +{ + static const struct type_info type_defs[] = + { + { tdPublic | tdSealed | tdWindowsRuntime, "TestEnum1", "Wine.Test", 0x1000001 }, + { tdPublic | tdSealed | tdSequentialLayout | tdWindowsRuntime, "TestStruct1", "Wine.Test", 0x1000005 }, + { tdInterface | tdAbstract | tdWindowsRuntime, "ITest2", "Wine.Test", 0x1000000 }, + { tdPublic | tdSealed | tdWindowsRuntime, "Test2", "Wine.Test", 0x100000b }, + }; + const WCHAR *filename = load_resource(L"test-enum.winmd"); + ULONG buf_len, buf_count, str_len, str_reqd, i; + IMetaDataDispenser *dispenser; + IMetaDataImport *md_import; + mdTypeDef *typedef_tokens; + HCORENUM henum = 0; + WCHAR *strW; + HRESULT hr; + ULONG val; + + hr = MetaDataGetDispenser(&CLSID_CorMetaDataDispenser, &IID_IMetaDataDispenser, (void **)&dispenser); + ok(hr == S_OK, "got hr %#lx\n", hr); + + hr = IMetaDataDispenser_OpenScope(dispenser, filename, 0, &IID_IMetaDataImport, (IUnknown **)&md_import); + ok(hr == S_OK, "got hr %#lx\n", hr); + IMetaDataDispenser_Release(dispenser); + + buf_count = 0xdeadbeef; + henum = NULL; + hr = IMetaDataImport_EnumTypeDefs(md_import, &henum, NULL, 0, &buf_count); + todo_wine ok(hr == S_FALSE, "got hr %#lx\n", hr); + todo_wine ok(buf_count == 0, "got buf_reqd %lu\n", buf_count); + todo_wine ok(!!henum, "got henum %p\n", henum); + + buf_len = 0; + hr = IMetaDataImport_CountEnum(md_import, henum, &buf_len); + todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + /* The <Module> typedef is ommitted. */ + todo_wine ok(buf_len == ARRAY_SIZE(type_defs), "got len %lu\n", buf_len); + + typedef_tokens = calloc(buf_len, sizeof(*typedef_tokens)); + ok(!!typedef_tokens, "got typedef_tokens %p\n", typedef_tokens); + hr = IMetaDataImport_EnumTypeDefs(md_import, &henum, typedef_tokens, buf_len, &buf_count); + todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + todo_wine ok(buf_len == buf_count, "got len %lu != %lu\n", buf_len, buf_count); + for (i = 0; i < buf_len; i++) + { + const struct type_info *info = &type_defs[i]; + mdTypeDef token = 0; + ULONG exp_len, len; + WCHAR bufW[80]; + char bufA[80]; + mdToken base; + + winetest_push_context("i=%lu", i); + + bufW[0] = L'\0'; + bufA[0] = '\0'; + exp_len = snprintf(bufA, sizeof(bufA), "%s.%s", info->exp_namespace, info->exp_name) + 1; + str_reqd = 0; + hr = IMetaDataImport_GetTypeDefProps(md_import, typedef_tokens[i], NULL, 0, &str_reqd, NULL, NULL); + todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + todo_wine ok(str_reqd == exp_len, "got str_reqd %lu != %lu\n", str_reqd, exp_len); + MultiByteToWideChar(CP_ACP, 0, bufA, -1, bufW, ARRAY_SIZE(bufW)); + + str_len = str_reqd; + strW = calloc(str_len, sizeof(WCHAR)); + hr = IMetaDataImport_GetTypeDefProps(md_import, typedef_tokens[i], strW, str_len - 1, &str_reqd, &val, &base); + todo_wine ok(hr == CLDB_S_TRUNCATION, "got hr %#lx\n", hr); + len = wcslen(strW); + todo_wine ok( len == str_len - 2, "got len %lu != %lu\n", len, str_len - 2); + if (hr == CLDB_S_TRUNCATION) + todo_wine ok(!wcsncmp(strW, bufW, str_len - 2), "got bufW %s != %s\n", debugstr_w(strW), + debugstr_wn(bufW, str_len - 2)); + val = base = 0; + hr = IMetaDataImport_GetTypeDefProps(md_import, typedef_tokens[i], strW, str_len, NULL, &val, &base); + todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + if (hr == S_OK) + ok(1 || !wcscmp(strW, bufW), "got strW %s != %s\n", debugstr_w(strW), debugstr_w(bufW)); + free(strW); + + todo_wine ok(val == info->exp_flags, "got val %#lx != %#lx\n", val, info->exp_flags); + todo_wine ok(base == info->exp_base, "got base %#x != %#x\n", base, info->exp_base); + + hr = IMetaDataImport_FindTypeDefByName(md_import, bufW, 0, &token); + todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + todo_wine ok(token == typedef_tokens[i], "got token %#x != %#x\n", token, typedef_tokens[i]); + + winetest_pop_context(); + } + hr = IMetaDataImport_EnumTypeDefs(md_import, &henum, typedef_tokens, buf_len, &buf_count); + todo_wine ok(hr == S_FALSE, "got hr %#lx\n", hr); + + hr = IMetaDataImport_ResetEnum(md_import, henum, 0); + todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + buf_count = 0xdeadbeef; + hr = IMetaDataImport_EnumTypeDefs(md_import, &henum, typedef_tokens, buf_len, &buf_count); + todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + todo_wine ok(buf_len == buf_count, "got len %lu != %lu\n", buf_len, buf_count); + hr = IMetaDataImport_EnumTypeDefs(md_import, &henum, typedef_tokens, buf_len, &buf_count); + todo_wine ok(hr == S_FALSE, "got hr %#lx\n", hr); + IMetaDataImport_CloseEnum(md_import, henum); + free(typedef_tokens); + + hr = IMetaDataImport_FindTypeDefByName(md_import, NULL, 0, NULL); + todo_wine ok(hr == E_INVALIDARG, "got hr %#lx\n", hr); + + IMetaDataImport_Release(md_import); +} + START_TEST(rometadata) { HRESULT hr; @@ -783,6 +895,7 @@ START_TEST(rometadata)
test_MetaDataGetDispenser(); test_MetaDataDispenser_OpenScope(); + test_IMetaDataImport();
RoUninitialize(); } diff --git a/dlls/rometadata/tests/rsrc.rc b/dlls/rometadata/tests/rsrc.rc index 9b2c6daded3..128971553a3 100644 --- a/dlls/rometadata/tests/rsrc.rc +++ b/dlls/rometadata/tests/rsrc.rc @@ -18,3 +18,6 @@
/* @makedep: test-simple.winmd */ test-simple.winmd RCDATA "test-simple.winmd" + +/* @makedep: test-enum.winmd */ +test-enum.winmd RCDATA "test-enum.winmd" diff --git a/dlls/rometadata/tests/test-enum.idl b/dlls/rometadata/tests/test-enum.idl new file mode 100644 index 00000000000..09c0a08a846 --- /dev/null +++ b/dlls/rometadata/tests/test-enum.idl @@ -0,0 +1,72 @@ +/* + * 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 + */ + +#ifdef __WIDL__ +#pragma makedep header winmd +#pragma winrt ns_prefix +#endif + +import "inspectable.idl"; +import "windowscontracts.idl"; + +namespace Wine.Test { + typedef struct TestStruct1 TestStruct1; + typedef enum TestEnum1 TestEnum1; + + interface ITest2; + + runtimeclass Test2; + + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + enum TestEnum1 + { + Foo = 0, + [contract(Windows.Foundation.UniversalApiContract, 2.0)] + Bar = 1, + [contract(Windows.Foundation.UniversalApiContract, 3.0)] + Baz = 2 + }; + + [contract(Windows.Foundation.UniversalApiContract, 2.0)] + struct TestStruct1 + { + int a; + int b; + int c; + }; + + [ + contract(Windows.Foundation.UniversalApiContract, 3.0), + exclusiveto(Wine.Test.Test2), + uuid(deadbeef-dead-beef-dead-deadbeef0002) + ] + interface ITest2 : IInspectable + { + HRESULT Method1([in] int a, [in] int b, [out, retval] int *out); + HRESULT Method2([in] TestEnum1 a, [out, retval] TestEnum1 *out); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 3.0), + marshaling_behavior(agile) + ] + runtimeclass Test2 + { + [default] interface Wine.Test.ITest2; + } +} diff --git a/include/corhdr.h b/include/corhdr.h index 91f67d25c0f..f3af49abc8d 100644 --- a/include/corhdr.h +++ b/include/corhdr.h @@ -129,4 +129,43 @@ typedef mdToken mdGenericParamConstraint; typedef mdToken mdString; typedef mdToken mdCPToken;
+typedef enum CorTypeAttr +{ + tdNotPublic = 0x000000, + tdPublic = 0x000001, + tdNestedPublic = 0x000002, + tdNestedPrivate = 0x000003, + tdNestedFamily = 0x000004, + tdNestedAssembly = 0x000005, + tdNestedFamANDAssem = 0x000006, + tdNestedFamORAssem = 0x000007, + tdAutoLayout = 0x000000, + tdSequentialLayout = 0x000008, + tdExplicitLayout = 0x000010, + tdExtendedLayout = 0x000018, + tdClass = 0x000000, + tdInterface = 0x000020, + tdAbstract = 0x000080, + tdSealed = 0x000100, + tdSpecialName = 0x000400, + tdImport = 0x001000, + tdSerializable = 0x002000, + tdWindowsRuntime = 0x004000, + tdAnsiClass = 0x000000, + tdUnicodeClass = 0x010000, + tdAutoClass = 0x020000, + tdCustomFormatClass = 0x030000, + tdBeforeFieldInit = 0x100000, + tdForwarder = 0x200000, + tdRTSpecialName = 0x000800, + tdHasSecurity = 0x040000, + + tdVisibilityMask = 0x000007, + tdLayoutMask = 0x000018, + tdClassSemanticsMask = 0x000020, + tdStringFormatMask = 0x030000, + tdCustomFormatMask = 0xc00000, + tdReservedMask = 0x040800 +} CorTypeAttr; + #endif /* __WINE_CORHDR_H */