This is an implementation of TODO "Need to not hard-code the dll path"
Registration is implemented in somewhat hackish way:
- not all required keys are created, only minimal set to register DLL
at non-hard-coded location; install.reg is still required;
- not all created keys are removed, namely CLSID\{ca586...};
for full clean up, uninstall.reg is still required.
---
Makefile | 3 +-
dll.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++
+--------
dll.h | 3 ++
install.reg.in | 6 ----
4 files changed, 74 insertions(+), 20 deletions(-)
diff --git a/Makefile b/Makefile
index 4042879..f28c30e 100644
--- a/Makefile
+++ b/Makefile
@@ -33,8 +33,7 @@ uninst%: uninst%.reg
install.reg: install.reg.in Makefile
sed < $< > $@ \
- -e 's|@@MSYSGIT_PATH@@|$(MSYSGIT_PATH)|' \
- -e 's|@@DLL_PATH@@|$(DLL_PATH)|'
+ -e 's|@@MSYSGIT_PATH@@|$(MSYSGIT_PATH)|'
%-user.reg: %.reg
sed < $< > $@ \
diff --git a/dll.c b/dll.c
index bab9d9a..bce60c8 100644
--- a/dll.c
+++ b/dll.c
@@ -1,4 +1,6 @@
#include <shlobj.h>
+#include <assert.h>
+#include <stdio.h>
#include "dll.h"
#include "ext.h"
#include "factory.h"
@@ -7,6 +9,7 @@
* The following is just the necessary infrastructure for having
a .dll
* which can be registered as a COM object.
*/
+HINSTANCE hInst;
HRESULT PASCAL DllGetClassObject(REFCLSID obj_guid, REFIID
factory_guid,
void **factory_handle)
@@ -25,29 +28,84 @@ HRESULT PASCAL DllCanUnloadNow(void)
return (object_count || lock_count) ? S_FALSE : S_OK;
}
+// as per "How to: Convert Between System::Guid and _GUID"
+static void get_registration_path (char *string)
+{
+ GUID guid = CLSID_git_shell_ext;
+ sprintf (string,
+ KEY_CLSID
+ "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"
+ "\\InProcServer32",
+ guid.Data1, guid.Data2, guid.Data3,
+ guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
+ guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
+}
+
+static HRESULT register_git_shell_ext (HKEY root, const char *value)
+{
+ HKEY key;
+ DWORD disp; // required for RegCreateKeyEx, otherwise unused
+ char path_to_value[MAX_PATH]; // more than necessary for registry
key
+ HRESULT result;
+
+ assert (NULL != value);
+ assert (MAX_PATH > strlen(value));
+
+ get_registration_path (path_to_value);
+
+ result = RegCreateKeyEx(root, path_to_value,
+ 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
+ &key, &disp);
+ if (ERROR_SUCCESS != result)
+ return result;
+
+ result = RegSetValueEx(key, NULL, // value name: default value
+ 0, REG_SZ,
+ (LPBYTE)value, (DWORD)strlen(value));
+ if (ERROR_SUCCESS == result)
+ result = RegSetValueEx(key, "ThreadingModel",
+ 0, REG_SZ,
+ THREADING_MODEL, (DWORD)strlen(THREADING_MODEL));
+
+ RegCloseKey (key);
+
+ return result;
+}
+
HRESULT PASCAL DllRegisterServer(void)
{
char module[MAX_PATH];
- wchar_t module_name[MAX_PATH];
- ITypeLib *typelib = NULL;
-
- GetModuleFileName(NULL, module, MAX_PATH);
- MultiByteToWideChar(CP_ACP, 0, module, -1, module_name, MAX_PATH);
- if (LoadTypeLib(module_name, &typelib) == S_OK) {
- HRESULT result = RegisterTypeLib(typelib, module_name, NULL);
- typelib->lpVtbl->Release(typelib);
- return result;
- }
- return 1;
+ DWORD module_size;
+ HRESULT result;
+
+ if (0 == (module_size = GetModuleFileName(hInst, module, MAX_PATH)))
+ return GetLastError();
+
+ result = register_git_shell_ext (HKEY_LOCAL_MACHINE, module);
+ if (ERROR_SUCCESS != result)
+ result = register_git_shell_ext (HKEY_CURRENT_USER, module);
+
+ return result;
}
HRESULT PASCAL DllUnregisterServer(void)
{
- return S_OK;
+ HRESULT result;
+ char path_to_value[MAX_PATH]; // more than necessary for registry
key
+
+ get_registration_path (path_to_value);
+
+ result = RegDeleteKey (HKEY_LOCAL_MACHINE, path_to_value);
+ if (ERROR_SUCCESS != result)
+ result = RegDeleteKey (HKEY_CURRENT_USER, path_to_value);
+
+ return result;
}
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID
reserved)
{
+ hInst = instance;
+
if (reason == DLL_PROCESS_ATTACH) {
object_count = lock_count = 0;
DisableThreadLibraryCalls(instance);
diff --git a/dll.h b/dll.h
index e5de007..1a1ee29 100644
--- a/dll.h
+++ b/dll.h
@@ -5,6 +5,9 @@ const char *program_name = "Git-Cheetah";
const char *program_version = "Git-Cheetah.Application.1";
const char *program_id = "Git-Cheetah.Application";
+#define KEY_CLSID "Software\\Classes\\CLSID\\"
+#define THREADING_MODEL "Apartment"
+
HRESULT PASCAL DllGetClassObject(REFCLSID obj_guid, REFIID
factory_guid,
void **factory_handle);
HRESULT PASCAL DllCanUnloadNow(void);
diff --git a/install.reg.in b/install.reg.in
index 2eb8f13..29ae2ed 100644
--- a/install.reg.in
+++ b/install.reg.in
@@ -21,12 +21,6 @@ Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\CLSID\{ca586c80-7c84-4b88-8537-726724df6929}]
@="Git-Cheetah"
-[HKEY_CLASSES_ROOT\CLSID\
{ca586c80-7c84-4b88-8537-726724df6929}\InProcServer32]
[EMAIL PROTECTED]"@@DLL_PATH@@"
-
-[HKEY_CLASSES_ROOT\CLSID\
{ca586c80-7c84-4b88-8537-726724df6929}\InProcServer32]
-"ThreadingModel"="Apartment"
-
[HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers\Git-Cheetah]
[HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers\Git-Cheetah]
--
1.5.4.rc0.929.g50e2