qmgr: Implement DLL server registration. [take 3]
Dan Hipschman
dsh at linux.ucla.edu
Wed Feb 13 16:23:17 CST 2008
No .INF file this time.
ChangeLog:
Add the server registration code to qmgr.
From: Roy Shea <roy at cs.hmc.edu>
Date: Thu Dec 20 18:38:31 CST 2007
---
dlls/qmgr/Makefile.in | 2 +-
dlls/qmgr/qmgr.spec | 4 +-
dlls/qmgr/qmgr_main.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 240 insertions(+), 6 deletions(-)
diff --git a/dlls/qmgr/Makefile.in b/dlls/qmgr/Makefile.in
index a19eea6..2023d58 100644
--- a/dlls/qmgr/Makefile.in
+++ b/dlls/qmgr/Makefile.in
@@ -3,7 +3,7 @@ TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = qmgr.dll
-IMPORTS = kernel32
+IMPORTS = advapi32 kernel32 ole32
EXTRALIBS = -luuid
C_SRCS = \
diff --git a/dlls/qmgr/qmgr.spec b/dlls/qmgr/qmgr.spec
index 1a63b32..0f9b073 100644
--- a/dlls/qmgr/qmgr.spec
+++ b/dlls/qmgr/qmgr.spec
@@ -1,2 +1,2 @@
-@ stub DllRegisterServer
-@ stub DllUnregisterServer
+@ stdcall -private DllRegisterServer()
+@ stdcall -private DllUnregisterServer()
diff --git a/dlls/qmgr/qmgr_main.c b/dlls/qmgr/qmgr_main.c
index d00ac2d..c0b7d34 100644
--- a/dlls/qmgr/qmgr_main.c
+++ b/dlls/qmgr/qmgr_main.c
@@ -21,15 +21,26 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include <stdarg.h>
+#include <stdio.h>
-#include "windef.h"
-#include "winbase.h"
+#include "objbase.h"
+#include "winuser.h"
+#include "winreg.h"
+#include "olectl.h"
+#include "winsvc.h"
+#include "winnls.h"
+
+#include "bits.h"
+#include "qmgr.h"
+#include "initguid.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(qmgr);
+/* Other GUIDs used by this module */
+DEFINE_GUID(CLSID_BackgroundCopyQMgr, 0x69AD4AEE, 0x51BE, 0x439b, 0xA9,0x2C, 0x86,0xAE,0x49,0x0E,0x8B,0x30);
+
/* Entry point for DLL */
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
@@ -48,3 +59,226 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
return TRUE;
}
+
+static char szCLSID_BackgroundCopyQMgr[39];
+static char szCLSID_BackgroundCopyManager[39];
+
+static void init_guid_strings(void)
+{
+ if (!szCLSID_BackgroundCopyQMgr[0]) {
+ WCHAR buf[39];
+ StringFromGUID2(&CLSID_BackgroundCopyQMgr, buf, sizeof buf);
+ WideCharToMultiByte(CP_ACP, 0, buf, -1, szCLSID_BackgroundCopyQMgr,
+ sizeof szCLSID_BackgroundCopyQMgr, NULL, NULL);
+ StringFromGUID2(&CLSID_BackgroundCopyManager, buf, sizeof buf);
+ WideCharToMultiByte(CP_ACP, 0, buf, -1, szCLSID_BackgroundCopyManager,
+ sizeof szCLSID_BackgroundCopyManager, NULL, NULL);
+ }
+}
+
+static LONG set_val(HKEY root, const char *subkey, const char *name,
+ DWORD type, const char *value, DWORD size)
+{
+ HKEY key;
+ LONG res;
+
+ res = RegCreateKeyExA(root, subkey, 0, NULL, 0, KEY_READ | KEY_WRITE,
+ NULL, &key, NULL);
+ if (res != ERROR_SUCCESS) {
+ ERR("RegCreateKeyEx %p\\%s failed (%d)\n", root, subkey, res);
+ return res;
+ }
+
+ res = RegSetValueExA(key, name, 0, type, (const BYTE *) value, size);
+ RegCloseKey(key);
+ if (res != ERROR_SUCCESS)
+ ERR("RegSetValueEx %p\\%s\\%s failed (%d)\n", root, subkey, name, res);
+
+ return res;
+}
+
+static LONG del_key(HKEY root, const char *subkey)
+{
+ LONG res = RegDeleteTreeA(root, subkey);
+ if (res == ERROR_FILE_NOT_FOUND) {
+ TRACE("RegDeleteTree %p\\%s not found, ignoring\n", root, subkey);
+ return ERROR_SUCCESS;
+ }
+ else if (res != ERROR_SUCCESS)
+ ERR("RegDeleteTree %p\\%s failed (%d)\n", root, subkey, res);
+ return res;
+}
+
+static LONG del_val(HKEY root, const char *subkey, const char *name)
+{
+ HKEY key;
+ LONG res;
+
+ res = RegOpenKeyExA(root, subkey, 0, KEY_SET_VALUE, &key);
+ if (res == ERROR_FILE_NOT_FOUND) {
+ TRACE("RegOpenKeyEx %p\\%s not found, ignoring\n", root, subkey);
+ return ERROR_SUCCESS;
+ }
+ else if (res != ERROR_SUCCESS) {
+ ERR("RegOpenKeyEx %p\\%s failed (%d)\n", root, subkey, res);
+ return res;
+ }
+
+ res = RegDeleteValueA(key, name);
+ RegCloseKey(key);
+ if (res == ERROR_FILE_NOT_FOUND) {
+ TRACE("RegDeleteValue %p\\%s\\%s not found, ignoring\n", root, subkey,
+ name);
+ return ERROR_SUCCESS;
+ }
+ else if (res != ERROR_SUCCESS)
+ ERR("RegDeleteValue %p\\%s\\%s failed (%d)\n", root, subkey, name,
+ res);
+
+ return res;
+}
+
+static LONG register_service(BOOL do_register)
+{
+ #define SVCHOST_KEY "Software\\Microsoft\\Windows NT\\CurrentVersion\\SvcHost"
+ #define BITS_KEY "System\\CurrentControlSet\\Services\\BITS"
+ #define NETSVCS_NAME "netsvcs"
+
+ SC_HANDLE scm, service;
+
+ scm = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (!scm) {
+ ERR("OpenSCManager failed\n");
+ return GetLastError();
+ }
+
+ if (do_register)
+ service = CreateServiceA(scm, "BITS", "BITS", SERVICE_ALL_ACCESS,
+ SERVICE_WIN32_OWN_PROCESS,
+ SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
+ "svchost.exe -k netsvcs", NULL, NULL, NULL,
+ NULL, NULL);
+ else
+ service = OpenServiceA(scm, "BITS", DELETE);
+
+
+ CloseServiceHandle(scm);
+ if (!service) {
+ if (!do_register && GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
+ TRACE("OpenService does not exist, ignoring\n");
+ else {
+ ERR("Create/OpenService failed\n");
+ return GetLastError();
+ }
+ }
+ else {
+ if (!do_register)
+ if (!DeleteService(service))
+ ERR("DeleteService failed\n");
+ CloseServiceHandle(service);
+ }
+
+ if (do_register) {
+ LONG res;
+ res = set_val(HKEY_LOCAL_MACHINE, SVCHOST_KEY, NETSVCS_NAME,
+ REG_MULTI_SZ, "BITS\0", 6);
+ if (res != ERROR_SUCCESS)
+ return res;
+
+ res = set_val(HKEY_LOCAL_MACHINE,
+ BITS_KEY "\\Parameters",
+ "ServiceDll", REG_EXPAND_SZ, "qmgr.dll", 9);
+ if (res != ERROR_SUCCESS)
+ return res;
+
+ return ERROR_SUCCESS;
+ }
+ else {
+ LONG r1, r2;
+
+ r1 = del_val(HKEY_LOCAL_MACHINE, SVCHOST_KEY, NETSVCS_NAME);
+ /* BITS_KEY should already be removed by DeleteService, but in
+ case it failed... */
+ r2 = del_key(HKEY_LOCAL_MACHINE, BITS_KEY);
+ return r1 != ERROR_SUCCESS ? r1 : r2;
+ }
+}
+
+static LONG register_classes(void)
+{
+ LONG res;
+ char subkey[100];
+
+ res = set_val(HKEY_CLASSES_ROOT, "AppID\\BITS", "AppID", REG_SZ,
+ szCLSID_BackgroundCopyQMgr, 39);
+ if (res != ERROR_SUCCESS)
+ return res;
+
+ sprintf(subkey, "AppID\\%s", szCLSID_BackgroundCopyQMgr);
+ res = set_val(HKEY_CLASSES_ROOT, subkey, "LocalService", REG_SZ, "BITS",
+ 5);
+ if (res != ERROR_SUCCESS)
+ return res;
+
+ sprintf(subkey, "CLSID\\%s", szCLSID_BackgroundCopyManager);
+ return set_val(HKEY_CLASSES_ROOT, subkey, "AppID", REG_SZ,
+ szCLSID_BackgroundCopyQMgr, 39);
+}
+
+static LONG unregister_classes(void)
+{
+ LONG r1, r2;
+ char subkey[100];
+
+ r1 = del_key(HKEY_CLASSES_ROOT, "AppID\\BITS");
+
+ sprintf(subkey, "AppID\\%s", szCLSID_BackgroundCopyQMgr);
+ r2 = del_key(HKEY_CLASSES_ROOT, subkey);
+ if (r1 == ERROR_SUCCESS)
+ r1 = r2;
+
+ sprintf(subkey, "CLSID\\%s", szCLSID_BackgroundCopyManager);
+ r2 = del_key(HKEY_CLASSES_ROOT, subkey);
+
+ return r1 != ERROR_SUCCESS ? r1 : r2;
+}
+
+HRESULT WINAPI DllRegisterServer()
+{
+ LONG res;
+
+ TRACE("\n");
+ init_guid_strings();
+
+ res = register_service(TRUE);
+ if (res != ERROR_SUCCESS) {
+ ERR("couldn't register service: %d\n", res);
+ return SELFREG_E_CLASS;
+ }
+
+ res = register_classes();
+ if (res != ERROR_SUCCESS) {
+ ERR("couldn't register classes: %d\n", res);
+ return SELFREG_E_CLASS;
+ }
+
+ return S_OK;
+}
+
+HRESULT WINAPI DllUnregisterServer()
+{
+ LONG r1, r2;
+
+ TRACE("\n");
+ init_guid_strings();
+
+ r1 = register_service(FALSE);
+ if (r1 != ERROR_SUCCESS)
+ ERR("couldn't unregister service: %d\n", r1);
+
+ r2 = unregister_classes();
+ if (r2 != ERROR_SUCCESS)
+ ERR("couldn't unregister classes: %d\n", r2);
+
+ return r1 != ERROR_SUCCESS || r2 != ERROR_SUCCESS ? SELFREG_E_CLASS : S_OK;
+}
More information about the wine-patches
mailing list