From: Jacek Caban Subject: atl100: Added AtlRegisterClassCategoriesHelper implementation Message-Id: <50D86313.3060202@codeweavers.com> Date: Mon, 24 Dec 2012 15:13:39 +0100 --- dlls/atl100/atl.c | 75 +++++++++++++++++++++++++++++++++++++++- dlls/atl100/tests/Makefile.in | 2 +- dlls/atl100/tests/atl.c | 62 +++++++++++++++++++++++++++++++++ include/atlbase.h | 11 ++++++ 4 files changed, 147 insertions(+), 3 deletions(-) diff --git a/dlls/atl100/atl.c b/dlls/atl100/atl.c index 570fe5c..219365d 100644 --- a/dlls/atl100/atl.c +++ b/dlls/atl100/atl.c @@ -1,5 +1,6 @@ /* * Copyright 2012 Stefan Leichter + * Copyright 2012 Jacek Caban for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,6 +25,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(atl100); +static ICatRegister *catreg; + /*********************************************************************** * AtlAdvise [atl100.@] */ @@ -379,8 +382,60 @@ HRESULT WINAPI AtlComModuleGetClassObject(_ATL_COM_MODULE *pm, REFCLSID rclsid, */ HRESULT WINAPI AtlRegisterClassCategoriesHelper(REFCLSID clsid, const struct _ATL_CATMAP_ENTRY *catmap, BOOL reg) { - FIXME("(%s %p %x)\n", debugstr_guid(clsid), catmap, reg); - return E_NOTIMPL; + const struct _ATL_CATMAP_ENTRY *iter; + HRESULT hres; + + TRACE("(%s %p %x)\n", debugstr_guid(clsid), catmap, reg); + + if(!catreg) { + ICatRegister *new_catreg; + + hres = CoCreateInstance(&CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, + &IID_ICatRegister, (void**)&new_catreg); + if(FAILED(hres)) + return hres; + + if(InterlockedCompareExchangePointer((void**)&catreg, new_catreg, NULL)) + ICatRegister_Release(new_catreg); + } + + for(iter = catmap; iter->iType != _ATL_CATMAP_ENTRY_END; iter++) { + CATID catid = *iter->pcatid; /* For stupid lack of const in ICatRegister declaration. */ + + if(iter->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED) { + if(reg) + hres = ICatRegister_RegisterClassImplCategories(catreg, clsid, 1, &catid); + else + hres = ICatRegister_UnRegisterClassImplCategories(catreg, clsid, 1, &catid); + }else { + if(reg) + hres = ICatRegister_RegisterClassReqCategories(catreg, clsid, 1, &catid); + else + hres = ICatRegister_UnRegisterClassReqCategories(catreg, clsid, 1, &catid); + } + if(FAILED(hres)) + return hres; + } + + if(!reg) { + WCHAR reg_path[256] = {'C','L','S','I','D','\\'}, *ptr = reg_path+6; + + static const WCHAR implemented_catW[] = + {'I','m','p','l','e','m','e','n','t','e','d',' ','C','a','t','e','g','o','r','i','e','s',0}; + static const WCHAR required_catW[] = + {'R','e','q','u','i','r','e','d',' ','C','a','t','e','g','o','r','i','e','s',0}; + + ptr += StringFromGUID2(clsid, ptr, 64)-1; + *ptr++ = '\\'; + + memcpy(ptr, implemented_catW, sizeof(implemented_catW)); + RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path); + + memcpy(ptr, required_catW, sizeof(required_catW)); + RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path); + } + + return S_OK; } /*********************************************************************** @@ -390,3 +445,19 @@ DWORD WINAPI AtlGetVersion(void *pReserved) { return _ATL_VER; } + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + TRACE("(0x%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved); + + switch(fdwReason) { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinstDLL); + break; + case DLL_PROCESS_DETACH: + if(catreg) + ICatRegister_Release(catreg); + } + + return TRUE; +} diff --git a/dlls/atl100/tests/Makefile.in b/dlls/atl100/tests/Makefile.in index 4230bad..29e83d0 100644 --- a/dlls/atl100/tests/Makefile.in +++ b/dlls/atl100/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = atl100.dll -IMPORTS = ole32 atl100 +IMPORTS = atl100 ole32 advapi32 EXTRADEFS = -D_ATL_VER=_ATL_VER_100 C_SRCS = \ diff --git a/dlls/atl100/tests/atl.c b/dlls/atl100/tests/atl.c index 7e6a7e0..e7882fa 100644 --- a/dlls/atl100/tests/atl.c +++ b/dlls/atl100/tests/atl.c @@ -25,6 +25,18 @@ #include +static const GUID CLSID_Test = + {0x178fc163,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; +#define CLSID_TEST_STR "178fc163-0000-0000-0000-000000000046" + +static const GUID CATID_CatTest1 = + {0x178fc163,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x46}}; +#define CATID_CATTEST1_STR "178fc163-0000-0000-0000-000000000146" + +static const GUID CATID_CatTest2 = + {0x178fc163,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x46}}; +#define CATID_CATTEST2_STR "178fc163-0000-0000-0000-000000000246" + static void test_winmodule(void) { _AtlCreateWndData create_data[3]; @@ -95,11 +107,61 @@ static void test_winmodule(void) ok(winmod.m_pCreateWndList == create_data+1, "winmod.m_pCreateWndList != create_data\n"); } +#define test_key_exists(a,b) _test_key_exists(__LINE__,a,b) +static void _test_key_exists(unsigned line, HKEY root, const char *key_name) +{ + HKEY key; + DWORD res; + + res = RegOpenKeyA(root, key_name, &key); + ok_(__FILE__,line)(res == ERROR_SUCCESS, "Could not open key %s\n", key_name); + if(res == ERROR_SUCCESS) + RegCloseKey(key); +} + +#define test_key_not_exists(a,b) _test_key_not_exists(__LINE__,a,b) +static void _test_key_not_exists(unsigned line, HKEY root, const char *key_name) +{ + HKEY key; + DWORD res; + + res = RegOpenKeyA(root, key_name, &key); + ok_(__FILE__,line)(res == ERROR_FILE_NOT_FOUND, "Attempting to open %s returned %u\n", key_name, res); + if(res == ERROR_SUCCESS) + RegCloseKey(key); +} + +static void test_regcat(void) +{ + HRESULT hres; + + const struct _ATL_CATMAP_ENTRY catmap[] = { + {_ATL_CATMAP_ENTRY_IMPLEMENTED, &CATID_CatTest1}, + {_ATL_CATMAP_ENTRY_REQUIRED, &CATID_CatTest2}, + {_ATL_CATMAP_ENTRY_END} + }; + + hres = AtlRegisterClassCategoriesHelper(&CLSID_Test, catmap, TRUE); + ok(hres == S_OK, "AtlRegisterClassCategoriesHelper failed: %08x\n", hres); + + test_key_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}"); + test_key_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}\\Implemented Categories\\{" CATID_CATTEST1_STR "}"); + test_key_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}\\Required Categories\\{" CATID_CATTEST2_STR "}"); + + hres = AtlRegisterClassCategoriesHelper(&CLSID_Test, catmap, FALSE); + ok(hres == S_OK, "AtlRegisterClassCategoriesHelper failed: %08x\n", hres); + + test_key_not_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}\\Implemented Categories"); + test_key_not_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}\\Required Categories"); + test_key_exists(HKEY_CLASSES_ROOT, "CLSID\\{" CLSID_TEST_STR "}"); +} + START_TEST(atl) { CoInitialize(NULL); test_winmodule(); + test_regcat(); CoUninitialize(); } diff --git a/include/atlbase.h b/include/atlbase.h index 831150d..ee8167c 100644 --- a/include/atlbase.h +++ b/include/atlbase.h @@ -22,6 +22,7 @@ #define __WINE_ATLBASE_H__ #include +#include /* Wine extension: we (ab)use _ATL_VER to handle struct layout differences between ATL versions. */ #define _ATL_VER_30 0x0300 @@ -213,6 +214,16 @@ struct _ATL_REGMAP_ENTRY LPCOLESTR szData; }; +struct _ATL_CATMAP_ENTRY +{ + int iType; + const CATID *pcatid; +}; + +#define _ATL_CATMAP_ENTRY_END 0 +#define _ATL_CATMAP_ENTRY_IMPLEMENTED 1 +#define _ATL_CATMAP_ENTRY_REQUIRED 2 + HRESULT WINAPI AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID * iid, LPDWORD dpw); HRESULT WINAPI AtlAxAttachControl(IUnknown*,HWND,IUnknown**); HRESULT WINAPI AtlAxCreateControl(LPCOLESTR,HWND,IStream*,IUnknown**);