wine dlls/comcat

John K. Hohm jhohm at acm.org
Wed Jun 12 00:08:57 CDT 2002


Changelog:
John K. Hohm <jhohm at acm.org>
Completed implementation of comcat.dll, incl. Dll[Un]RegisterServer
-------------- next part --------------
? 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;
+}


More information about the wine-patches mailing list