If possible you should do the registration in the same way as windows as we try to be like windows in every way. Depending on the dll the settings are either hardcoded in a dll (that's what most dlls do) or when it are default windows dlls the keys are stored in wine.inf.
In case of your dll I guess it should be hardcoded. Shipping extra files puts an extra burden on packagers and it likely isn't what windows is doing.
Regards, Roderick
I like the way Roy used a .INF file for the DLL server registration. Looking at some of the other DLL's code, this seems comparably like a very clean idea.
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 | 4 ++- dlls/qmgr/qmgr.h | 11 ++++++ dlls/qmgr/qmgr.inf | 31 ++++++++++++++++ dlls/qmgr/qmgr.spec | 4 +- dlls/qmgr/qmgr_main.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++-- dlls/qmgr/rsrc.rc | 20 +++++++++++ 6 files changed, 156 insertions(+), 6 deletions(-) create mode 100644 dlls/qmgr/qmgr.inf create mode 100644 dlls/qmgr/rsrc.rc
diff --git a/dlls/qmgr/Makefile.in b/dlls/qmgr/Makefile.in index a19eea6..7159607 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 = advpack kernel32 EXTRALIBS = -luuid
C_SRCS = \ @@ -11,6 +11,8 @@ C_SRCS = \ qmgr.c \ qmgr_main.c
+RC_SRCS = rsrc.rc
IDL_I_SRCS = qmgr_local.idl
@MAKE_DLL_RULES@ diff --git a/dlls/qmgr/qmgr.h b/dlls/qmgr/qmgr.h index 9b708c8..3ad314d 100644 --- a/dlls/qmgr/qmgr.h +++ b/dlls/qmgr/qmgr.h @@ -27,6 +27,8 @@ #define COBJMACROS #include "bits.h"
+#include <string.h>
/* Background copy manager vtbl and related data */ typedef struct { @@ -43,4 +45,13 @@ extern ClassFactoryImpl BITS_ClassFactory;
HRESULT BackgroundCopyManagerConstructor(IUnknown *pUnkOuter, LPVOID *ppObj);
+/* Little helper functions */ +static inline char * +qmgr_strdup(const char *s) +{
- size_t n = strlen(s) + 1;
- char *d = HeapAlloc(GetProcessHeap(), 0, n);
- return d ? memcpy(d, s, n) : NULL;
+}
#endif /* __QMGR_H__ */ diff --git a/dlls/qmgr/qmgr.inf b/dlls/qmgr/qmgr.inf new file mode 100644 index 0000000..0550f01 --- /dev/null +++ b/dlls/qmgr/qmgr.inf @@ -0,0 +1,31 @@ +[version] +Signature="$CHICAGO$"
+[Strings] +Services="System\CurrentControlSet\Services"
+[RegisterDll] +AddReg = Qmgr.Reg
+[UnregisterDll] +DelReg = Qmgr.Reg
+[Qmgr.Reg]
+HKCR,"AppID\BITS","AppID",,"%CLSID_BackgroundCopyQMgr%" +HKCR,"AppID%CLSID_BackgroundCopyQMgr%","LocalService",,"BITS" +HKCR,"CLSID%CLSID_BackgroundCopyManager%","AppID",,"%CLSID_BackgroundCopyQMgr%"
+HKLM,"Software\Microsoft\Windows NT\CurrentVersion\SvcHost","netsvcs",0x00010000,"BITS"
+HKLM,"%Services%\BITS","Type",0x00010001,00000110 +HKLM,"%Services%\BITS","Start",0x00010001,00000003 +HKLM,"%Services%\BITS","ErrorControl",0x00010001,00000001 +HKLM,"%Services%\BITS","Description",,"BITS Service" +HKLM,"%Services%\BITS","DispalyName",,"BITS" +HKLM,"%Services%\BITS","ImagePath",0x00020000,"svchost.exe -k netsvcs" +HKLM,"%Services%\BITS\Parameters","ServiceDll",0x00020000,"qmgr.dll" 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..2bb5258 100644 --- a/dlls/qmgr/qmgr_main.c +++ b/dlls/qmgr/qmgr_main.c @@ -21,15 +21,27 @@
- 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 "advpub.h"
+#include "bits.h" +#include "qmgr.h" +#include "initguid.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(qmgr);
+/* Handle to the base address of this DLL */ +static HINSTANCE hInst;
+/* 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) { @@ -41,6 +53,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) return FALSE; /* prefer native version */ case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hinstDLL);
hInst = hinstDLL; break; case DLL_PROCESS_DETACH: break;
@@ -48,3 +61,76 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
return TRUE;
}
+static HRESULT init_register_strtable(STRTABLEA *strtable) +{
- #define CLSID_EXPANSION_ENTRY(id) { "CLSID_" #id, &CLSID_ ## id }
- static const struct {
const char *name;
const CLSID *clsid;
- } expns[] = {
CLSID_EXPANSION_ENTRY(BackgroundCopyQMgr),
CLSID_EXPANSION_ENTRY(BackgroundCopyManager)
- };
- #undef CLSID_EXPANSION_ENTRY
- static STRENTRYA pse[sizeof expns / sizeof expns[0]];
- int i;
- strtable->cEntries = sizeof pse / sizeof pse[0];
- strtable->pse = pse;
- for (i = 0; i < strtable->cEntries; i++) {
static const char dummy_sample[] =
"{12345678-1234-1234-1234-123456789012}";
const CLSID *clsid = expns[i].clsid;
pse[i].pszName = qmgr_strdup(expns[i].name);
pse[i].pszValue = HeapAlloc(GetProcessHeap(), 0, sizeof
dummy_sample);
if (!pse[i].pszName || !pse[i].pszValue)
return E_OUTOFMEMORY;
sprintf(pse[i].pszValue,
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
clsid->Data1, clsid->Data2, clsid->Data3,
clsid->Data4[0],
clsid->Data4[1], clsid->Data4[2], clsid->Data4[3],
clsid->Data4[4],
clsid->Data4[5], clsid->Data4[6], clsid->Data4[7]);
- }
- return S_OK;
+}
+static void cleanup_register_strtable(STRTABLEA *strtable) +{
- int i;
- for (i = 0; i < strtable->cEntries; i++) {
HeapFree(GetProcessHeap(), 0, strtable->pse[i].pszName);
HeapFree(GetProcessHeap(), 0, strtable->pse[i].pszValue);
if (!strtable->pse[i].pszName || !strtable->pse[i].pszValue)
return;
- }
+}
+/* Use an INF file to register or unregister the DLL */ +static HRESULT register_server(BOOL do_register) +{
- HRESULT hr;
- STRTABLEA strtable;
- TRACE("(%x)\n", do_register);
- hr = init_register_strtable(&strtable);
- if (SUCCEEDED(hr))
hr = RegInstallA(hInst, do_register ? "RegisterDll" :
"UnregisterDll",
&strtable);
- cleanup_register_strtable(&strtable);
- if (FAILED(hr))
ERR("failed: %08x\n", hr);
- return hr;
+}
+HRESULT WINAPI DllRegisterServer() +{
- return register_server(TRUE);
+}
+HRESULT WINAPI DllUnregisterServer() +{
- return register_server(FALSE);
+} diff --git a/dlls/qmgr/rsrc.rc b/dlls/qmgr/rsrc.rc new file mode 100644 index 0000000..dfc64d0 --- /dev/null +++ b/dlls/qmgr/rsrc.rc @@ -0,0 +1,20 @@ +/*
- Copyright 2007 Google (Roy Shea)
- 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
USA
- */
+/* @makedep: qmgr.inf */ +REGINST REGINST qmgr.inf
On Thu, Jan 31, 2008 at 09:52:17PM +0100, Roderick Colenbrander wrote:
In case of your dll I guess it should be hardcoded. Shipping extra files puts an extra burden on packagers and it likely isn't what windows is doing.
The .INF is compiled into the DLL as a resource. Packagers shipping binaries won't have to do anything different. It simply makes editting the registry keys much easier and less error prone. Also, Roy obviously put a lot of work into doing it the nice way, so I feel bad ripping it out and hardcoding everything which just makes the code uglier anyway.
The .INF is not loaded from a path, it's loaded from the HINSTANCE of the DLL, which is provided to the DLL in DllMain.
I admit this isn't exactly the way Windows does it because the registry entries appear to be in the initialized data section of the Windows DLL, but then again, we don't have to maintain the Windows DLL.