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