Changelog: John K. Hohm <jhohm@acm.org> Completed implementation of comcat.dll, incl. Dll[Un]RegisterServer
? dlls/comcat/regsvr.c ? dlls/comcat/regsvr.h Index: dlls/comcat/Makefile.in =================================================================== RCS file: /home/wine/wine/dlls/comcat/Makefile.in,v retrieving revision 1.4 diff -u -r1.4 Makefile.in --- dlls/comcat/Makefile.in 2 Jun 2002 21:25:08 -0000 1.4 +++ dlls/comcat/Makefile.in 12 Jun 2002 05:00:24 -0000 @@ -14,7 +14,8 @@ factory.c \ manager.c \ register.c \ - information.c + information.c \ + regsvr.c @MAKE_DLL_RULES@ Index: dlls/comcat/comcat.h =================================================================== RCS file: /home/wine/wine/dlls/comcat/comcat.h,v retrieving revision 1.4 diff -u -r1.4 comcat.h --- dlls/comcat/comcat.h 2 Jun 2002 21:25:08 -0000 1.4 +++ dlls/comcat/comcat.h 12 Jun 2002 05:00:24 -0000 @@ -20,6 +20,7 @@ #include "windef.h" #include "winbase.h" +#include "winuser.h" #include "winreg.h" #include "winerror.h" @@ -61,3 +62,8 @@ extern ComCatMgrImpl COMCAT_ComCatMgr; extern ICOM_VTABLE(ICatRegister) COMCAT_ICatRegister_Vtbl; extern ICOM_VTABLE(ICatInformation) COMCAT_ICatInformation_Vtbl; + +/********************************************************************** + * Global string constant declarations + */ +extern const WCHAR clsid_keyname[6]; Index: dlls/comcat/comcat.spec =================================================================== RCS file: /home/wine/wine/dlls/comcat/comcat.spec,v retrieving revision 1.1 diff -u -r1.1 comcat.spec --- dlls/comcat/comcat.spec 14 May 2002 21:50:56 -0000 1.1 +++ dlls/comcat/comcat.spec 12 Jun 2002 05:00:24 -0000 @@ -1,4 +1,5 @@ name comcat +init COMCAT_DllEntryPoint @ stdcall DllCanUnloadNow() COMCAT_DllCanUnloadNow @ stdcall DllGetClassObject(ptr ptr ptr) COMCAT_DllGetClassObject Index: dlls/comcat/comcat_main.c =================================================================== RCS file: /home/wine/wine/dlls/comcat/comcat_main.c,v retrieving revision 1.1 diff -u -r1.1 comcat_main.c --- dlls/comcat/comcat_main.c 14 May 2002 21:50:56 -0000 1.1 +++ dlls/comcat/comcat_main.c 12 Jun 2002 05:00:24 -0000 @@ -19,12 +19,66 @@ */ #include "comcat.h" +#include "regsvr.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); DWORD dll_ref = 0; +HINSTANCE COMCAT_hInstance = 0; + +/*********************************************************************** + * Global string constant definitions + */ +const WCHAR clsid_keyname[6] = { 'C', 'L', 'S', 'I', 'D', 0 }; + +/*********************************************************************** + * Registration entries + */ +static const WCHAR class_keyname[39] = { + '{', '0', '0', '0', '2', 'E', '0', '0', '5', '-', '0', '0', + '0', '0', '-', '0', '0', '0', '0', '-', 'C', '0', '0', '0', + '-', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '4', + '6', '}', 0 }; +static const WCHAR class_name[26] = { + 'S', 't', 'd', 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', + 'C', 'a', 't', 'e', 'g', 'o', 'r', 'i', 'e', 's', 'M', 'g', + 'r', 0 }; +static const WCHAR ips32_keyname[15] = { + 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r', + '3', '2', 0 }; +static const WCHAR tm_valname[15] = { + 'T', 'h', 'r', 'e', 'a', 'd', 'i', 'n', 'g', 'M', 'o', 'd', + 'e', 'l', 0 }; +static const WCHAR tm_value[5] = { 'B', 'o', 't', 'h', 0 }; +static struct regsvr_entry regsvr_entries[6] = { + { HKEY_CLASSES_ROOT, 0, clsid_keyname }, + { 0, 1, class_keyname }, + { 1, 1, NULL, class_name }, + { 1, 1, ips32_keyname }, + { 3, 1, NULL, /*dynamic, path to dll module*/ }, + { 3, 1, tm_valname, tm_value } +}; + +/*********************************************************************** + * DllEntryPoint + */ +BOOL WINAPI COMCAT_DllEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad) +{ + TRACE("0x%x 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad); + + switch(fdwReason) { + case DLL_PROCESS_ATTACH: + COMCAT_hInstance = hinstDLL; + break; + + case DLL_PROCESS_DETACH: + COMCAT_hInstance = 0; + break; + } + return TRUE; +} /*********************************************************************** * DllGetClassObject (COMCAT.@) @@ -50,19 +104,33 @@ /*********************************************************************** * DllRegisterServer (COMCAT.@) */ - HRESULT WINAPI COMCAT_DllRegisterServer() { - FIXME("(): stub\n"); - return E_FAIL; + WCHAR dll_module[MAX_PATH]; + + TRACE("\n"); + + if (!GetModuleFileNameW(COMCAT_hInstance, dll_module, + sizeof dll_module / sizeof(WCHAR))) + return HRESULT_FROM_WIN32(GetLastError()); + + regsvr_entries[4].value = dll_module; + return regsvr_register(regsvr_entries, 6); } /*********************************************************************** * DllUnregisterServer (COMCAT.@) */ - HRESULT WINAPI COMCAT_DllUnregisterServer() { - FIXME("(): stub\n"); - return E_FAIL; + WCHAR dll_module[MAX_PATH]; + + TRACE("\n"); + + if (!GetModuleFileNameW(COMCAT_hInstance, dll_module, + sizeof dll_module / sizeof(WCHAR))) + return HRESULT_FROM_WIN32(GetLastError()); + + regsvr_entries[4].value = dll_module; + return regsvr_unregister(regsvr_entries, 6); } Index: dlls/comcat/information.c =================================================================== RCS file: /home/wine/wine/dlls/comcat/information.c,v retrieving revision 1.4 diff -u -r1.4 information.c --- dlls/comcat/information.c 2 Jun 2002 21:25:08 -0000 1.4 +++ dlls/comcat/information.c 12 Jun 2002 05:00:24 -0000 @@ -21,7 +21,6 @@ #include <string.h> #include "comcat.h" -#include "winuser.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); Index: dlls/comcat/register.c =================================================================== RCS file: /home/wine/wine/dlls/comcat/register.c,v retrieving revision 1.2 diff -u -r1.2 register.c --- dlls/comcat/register.c 19 May 2002 22:27:41 -0000 1.2 +++ dlls/comcat/register.c 12 Jun 2002 05:00:24 -0000 @@ -25,6 +25,28 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); /********************************************************************** + * File-scope string constants + */ +static const WCHAR comcat_keyname[21] = { + 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', ' ', 'C', 'a', + 't', 'e', 'g', 'o', 'r', 'i', 'e', 's', 0 }; +static const WCHAR impl_keyname[23] = { + '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 req_keyname[20] = { + 'R', 'e', 'q', 'u', 'i', 'r', 'e', 'd', + ' ', 'C', 'a', 't', 'e', 'g', 'o', 'r', + 'i', 'e', 's', 0 }; + +static HRESULT COMCAT_RegisterClassCategories( + REFCLSID rclsid, LPCWSTR type, + ULONG cCategories, CATID *rgcatid); +static HRESULT COMCAT_UnRegisterClassCategories( + REFCLSID rclsid, LPCWSTR type, + ULONG cCategories, CATID *rgcatid); + +/********************************************************************** * COMCAT_ICatRegister_QueryInterface */ static HRESULT WINAPI COMCAT_ICatRegister_QueryInterface( @@ -72,12 +94,45 @@ static HRESULT WINAPI COMCAT_ICatRegister_RegisterCategories( LPCATREGISTER iface, ULONG cCategories, - CATEGORYINFO *rgCategoryInfo) + CATEGORYINFO *rgci) { /* ICOM_THIS_MULTI(ComCatMgrImpl, regVtbl, iface); */ - FIXME("(): stub\n"); + HKEY comcat_key; + HRESULT res; + + TRACE("\n"); - return E_NOTIMPL; + if (iface == NULL || (cCategories && rgci == NULL)) + return E_POINTER; + + /* Create (or open) the component categories key. */ + res = RegCreateKeyExW(HKEY_CLASSES_ROOT, comcat_keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &comcat_key, NULL); + if (res != ERROR_SUCCESS) return E_FAIL; + + for (; cCategories; --cCategories, ++rgci) { + WCHAR fmt[4] = { '%', 'l', 'X', 0 }; + WCHAR keyname[39]; + WCHAR valname[9]; + HKEY cat_key; + + /* Create (or open) the key for this category. */ + if (!StringFromGUID2(&rgci->catid, keyname, 39)) continue; + res = RegCreateKeyExW(comcat_key, keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &cat_key, NULL); + if (res != ERROR_SUCCESS) continue; + + /* Set the value for this locale's description. */ + wsprintfW(valname, fmt, rgci->lcid); + RegSetValueExW(cat_key, valname, 0, REG_SZ, + (CONST BYTE*)(rgci->szDescription), + (lstrlenW(rgci->szDescription) + 1) * sizeof(WCHAR)); + + RegCloseKey(cat_key); + } + + RegCloseKey(comcat_key); + return S_OK; } /********************************************************************** @@ -89,9 +144,29 @@ CATID *rgcatid) { /* ICOM_THIS_MULTI(ComCatMgrImpl, regVtbl, iface); */ - FIXME("(): stub\n"); + HKEY comcat_key; + HRESULT res; - return E_NOTIMPL; + TRACE("\n"); + + if (iface == NULL || (cCategories && rgcatid == NULL)) + return E_POINTER; + + /* Open the component categories key. */ + res = RegOpenKeyExW(HKEY_CLASSES_ROOT, comcat_keyname, 0, + KEY_READ | KEY_WRITE, &comcat_key); + if (res != ERROR_SUCCESS) return E_FAIL; + + for (; cCategories; --cCategories, ++rgcatid) { + WCHAR keyname[39]; + + /* Delete the key for this category. */ + if (!StringFromGUID2(rgcatid, keyname, 39)) continue; + RegDeleteKeyW(comcat_key, keyname); + } + + RegCloseKey(comcat_key); + return S_OK; } /********************************************************************** @@ -104,9 +179,10 @@ CATID *rgcatid) { /* ICOM_THIS_MULTI(ComCatMgrImpl, regVtbl, iface); */ - FIXME("(): stub\n"); + TRACE("\n"); - return E_NOTIMPL; + return COMCAT_RegisterClassCategories( + rclsid, impl_keyname, cCategories, rgcatid); } /********************************************************************** @@ -119,9 +195,10 @@ CATID *rgcatid) { /* ICOM_THIS_MULTI(ComCatMgrImpl, regVtbl, iface); */ - FIXME("(): stub\n"); + TRACE("\n"); - return E_NOTIMPL; + return COMCAT_UnRegisterClassCategories( + rclsid, impl_keyname, cCategories, rgcatid); } /********************************************************************** @@ -134,9 +211,10 @@ CATID *rgcatid) { /* ICOM_THIS_MULTI(ComCatMgrImpl, regVtbl, iface); */ - FIXME("(): stub\n"); + TRACE("\n"); - return E_NOTIMPL; + return COMCAT_RegisterClassCategories( + rclsid, req_keyname, cCategories, rgcatid); } /********************************************************************** @@ -149,9 +227,10 @@ CATID *rgcatid) { /* ICOM_THIS_MULTI(ComCatMgrImpl, regVtbl, iface); */ - FIXME("(): stub\n"); + TRACE("\n"); - return E_NOTIMPL; + return COMCAT_UnRegisterClassCategories( + rclsid, req_keyname, cCategories, rgcatid); } /********************************************************************** @@ -170,3 +249,95 @@ COMCAT_ICatRegister_RegisterClassReqCategories, COMCAT_ICatRegister_UnRegisterClassReqCategories }; + +/********************************************************************** + * COMCAT_RegisterClassCategories + */ +static HRESULT COMCAT_RegisterClassCategories( + REFCLSID rclsid, + LPCWSTR type, + ULONG cCategories, + CATID *rgcatid) +{ + WCHAR keyname[39]; + HRESULT res; + HKEY clsid_key, class_key, type_key; + + if (cCategories && rgcatid == NULL) return E_POINTER; + + /* Format the class key name. */ + res = StringFromGUID2(rclsid, keyname, 39); + if (FAILED(res)) return res; + + /* Create (or open) the CLSID key. */ + res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL); + if (res != ERROR_SUCCESS) return E_FAIL; + + /* Create (or open) the class key. */ + res = RegCreateKeyExW(clsid_key, keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &class_key, NULL); + if (res == ERROR_SUCCESS) { + /* Create (or open) the category type key. */ + res = RegCreateKeyExW(class_key, type, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &type_key, NULL); + if (res == ERROR_SUCCESS) { + for (; cCategories; --cCategories, ++rgcatid) { + HKEY key; + + /* Format the category key name. */ + res = StringFromGUID2(rgcatid, keyname, 39); + if (FAILED(res)) continue; + + /* Do the register. */ + res = RegCreateKeyExW(type_key, keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &key, NULL); + if (res == ERROR_SUCCESS) RegCloseKey(key); + } + res = S_OK; + } else res = E_FAIL; + RegCloseKey(class_key); + } else res = E_FAIL; + RegCloseKey(clsid_key); + + return res; +} + +/********************************************************************** + * COMCAT_UnRegisterClassCategories + */ +static HRESULT COMCAT_UnRegisterClassCategories( + REFCLSID rclsid, + LPCWSTR type, + ULONG cCategories, + CATID *rgcatid) +{ + WCHAR keyname[68] = { 'C', 'L', 'S', 'I', 'D', '\\' }; + HRESULT res; + HKEY type_key; + + if (cCategories && rgcatid == NULL) return E_POINTER; + + /* Format the class category type key name. */ + res = StringFromGUID2(rclsid, keyname + 6, 39); + if (FAILED(res)) return res; + keyname[44] = '\\'; + lstrcpyW(keyname + 45, type); + + /* Open the class category type key. */ + res = RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, + KEY_READ | KEY_WRITE, &type_key); + if (res != ERROR_SUCCESS) return E_FAIL; + + for (; cCategories; --cCategories, ++rgcatid) { + /* Format the category key name. */ + res = StringFromGUID2(rgcatid, keyname, 39); + if (FAILED(res)) continue; + + /* Do the unregister. */ + RegDeleteKeyW(type_key, keyname); + } + RegCloseKey(type_key); + + return S_OK; +} --- /dev/null Fri Mar 15 21:55:30 2002 +++ dlls/comcat/regsvr.h Tue Jun 11 22:33:02 2002 @@ -0,0 +1,29 @@ +/* + * self-registerable dll helper functions + * + * Copyright (C) 2002 John K. Hohm + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +struct regsvr_entry { + int parent; /* entry number, or predefined HKEY_ */ + int unreg_del; /* recursively delete key on unregister? */ + LPCWSTR name; /* key or value name */ + LPCWSTR value; /* NULL for key */ +}; + +HRESULT regsvr_register(struct regsvr_entry const *entries, size_t count); +HRESULT regsvr_unregister(struct regsvr_entry const *entries, size_t count); --- /dev/null Fri Mar 15 21:55:30 2002 +++ dlls/comcat/regsvr.c Tue Jun 11 23:40:06 2002 @@ -0,0 +1,130 @@ +/* + * self-registerable dll helper functions + * + * Copyright (C) 2002 John K. Hohm + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winreg.h" +#include "winerror.h" + +#include "regsvr.h" + +static HRESULT recursive_delete_key(HKEY key); + +/*********************************************************************** + * regsvr_register + */ +HRESULT regsvr_register(struct regsvr_entry const *entries, size_t count) +{ + HKEY keys[count]; + struct regsvr_entry const *e; + int i; + HRESULT res = S_OK; + + /* Create keys and set values. */ + for (i = 0, e = entries; i < count; ++i, ++e) { + /* predefined HKEY_'s are all >= 0x80000000 */ + HKEY parent_key = e->parent < 0x80000000 ? + keys[e->parent] : (HKEY)e->parent; + if (e->value == NULL) { + res = RegCreateKeyExW(parent_key, e->name, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &keys[i], NULL); + } else { + res = RegSetValueExW(parent_key, e->name, 0, REG_SZ, + (CONST BYTE*)e->value, + (lstrlenW(e->value) + 1) * sizeof(WCHAR)); + } + if (res != ERROR_SUCCESS) break; + } + + /* Close keys. */ + for (--i, --e; 0 <= i; --i, --e) { + if (e->value == NULL) RegCloseKey(keys[i]); + } + + return res == ERROR_SUCCESS ? S_OK : HRESULT_FROM_WIN32(res); +} + +/*********************************************************************** + * regsvr_unregister + */ +HRESULT regsvr_unregister(struct regsvr_entry const *entries, size_t count) +{ + HKEY keys[count]; + struct regsvr_entry const *e; + int i; + HRESULT res = S_OK; + + /* Open (and possibly delete) keys. */ + for (i = 0, e = entries; i < count; ++i, ++e) { + /* predefined HKEY_'s are all >= 0x80000000 */ + HKEY parent_key = e->parent < 0x80000000 ? + keys[e->parent] : (HKEY)e->parent; + if (e->value == NULL && parent_key) { + res = RegOpenKeyExW(parent_key, e->name, 0, + KEY_READ | KEY_WRITE, &keys[i]); + if (res == ERROR_SUCCESS && e->unreg_del) + res = recursive_delete_key(keys[i]); + if (res == ERROR_FILE_NOT_FOUND) continue; + if (res != ERROR_SUCCESS) break; + } else keys[i] = 0; + } + + /* Close keys. */ + for (--i; 0 <= i; --i) { + if (keys[i]) RegCloseKey(keys[i]); + } + + return res != ERROR_SUCCESS && res != ERROR_FILE_NOT_FOUND ? + HRESULT_FROM_WIN32(res) : S_OK; +} + +/*********************************************************************** + * recursive_delete_key + */ +static LONG recursive_delete_key(HKEY key) +{ + LONG res; + DWORD index; + WCHAR subkey_name[MAX_PATH]; + DWORD cName; + HKEY subkey; + + for (index = 0; ; ++index) { + cName = sizeof subkey_name / sizeof(WCHAR); + res = RegEnumKeyExW(key, index, subkey_name, &cName, + NULL, NULL, NULL, NULL); + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { + res = ERROR_SUCCESS; /* presumably we're done enumerating */ + break; + } + res = RegOpenKeyExW(key, subkey_name, 0, + KEY_READ | KEY_WRITE, &subkey); + if (res == ERROR_FILE_NOT_FOUND) continue; + if (res != ERROR_SUCCESS) break; + + res = recursive_delete_key(subkey); + RegCloseKey(subkey); + if (res != ERROR_SUCCESS) break; + } + + if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0); + return res; +}