- modified windows installer to register new shell ext dll for drag/drop.

- stopped release shell ext dll from crashing by initializing ref counting members.
- added logging to shell ext dll to debug crash.
This commit is contained in:
Nick Bolton 2013-08-31 17:05:17 +00:00
parent bf0204e7c2
commit 501e894d03
4 changed files with 294 additions and 207 deletions

View File

@ -62,6 +62,7 @@ InstallDirRegKey HKEY_LOCAL_MACHINE "SOFTWARE\${product}" ""
Delete "${dir}\launcher.exe" Delete "${dir}\launcher.exe"
Delete "${dir}\synrgyhk.dll" Delete "${dir}\synrgyhk.dll"
Delete "${dir}\synwinhk.dll" Delete "${dir}\synwinhk.dll"
Delete "${dir}\synwinxt.dll"
Delete "${dir}\libgcc_s_dw2-1.dll" Delete "${dir}\libgcc_s_dw2-1.dll"
Delete "${dir}\mingwm10.dll" Delete "${dir}\mingwm10.dll"
Delete "${dir}\QtCore4.dll" Delete "${dir}\QtCore4.dll"
@ -162,6 +163,7 @@ Section "Server and Client" core
File "${binDir}\Release\synergys.exe" File "${binDir}\Release\synergys.exe"
File "${binDir}\Release\synergyc.exe" File "${binDir}\Release\synergyc.exe"
File "${binDir}\Release\synergyd.exe" File "${binDir}\Release\synergyd.exe"
File "${binDir}\Release\synwinxt.dll"
; if the hook file exists, skip, assuming it couldn't be deleted ; if the hook file exists, skip, assuming it couldn't be deleted
; because it was in use by some process. ; because it was in use by some process.
@ -175,6 +177,9 @@ Section "Server and Client" core
DetailPrint "Adding firewall exception" DetailPrint "Adding firewall exception"
nsExec::ExecToStack "netsh firewall add allowedprogram $\"$INSTDIR\synergys.exe$\" Synergy ENABLE" nsExec::ExecToStack "netsh firewall add allowedprogram $\"$INSTDIR\synergys.exe$\" Synergy ENABLE"
; install the windows shell extension
ExecWait "regsvr32 /s $\"$INSTDIR\synwinxt.dll$\""
; install and run the service ; install and run the service
ExecWait "$INSTDIR\synergyd.exe /install" ExecWait "$INSTDIR\synergyd.exe /install"
@ -220,6 +225,9 @@ Section Uninstall
; delete all registry keys ; delete all registry keys
DeleteRegKey HKLM "SOFTWARE\${product}" DeleteRegKey HKLM "SOFTWARE\${product}"
DeleteRegKey HKLM "${controlPanelReg}\${product}" DeleteRegKey HKLM "${controlPanelReg}\${product}"
; uninstall the windows shell extension
ExecWait "regsvr32 /s /u $\"$INSTDIR\synwinxt.dll$\""
; note: edit macro to delete more files. ; note: edit macro to delete more files.
!insertmacro DeleteFiles $INSTDIR !insertmacro DeleteFiles $INSTDIR

View File

@ -20,47 +20,64 @@
#include <Shlwapi.h> #include <Shlwapi.h>
extern LONG g_refCount; extern LONG g_refCount;
extern void outputDebugStringF(const char *str, ...);
CClassFactory::CClassFactory() CClassFactory::CClassFactory() :
m_refCount(1)
{ {
outputDebugStringF("synwinxt: > CClassFactory::ctor, g_refCount=%d", g_refCount);
InterlockedIncrement(&g_refCount); InterlockedIncrement(&g_refCount);
outputDebugStringF("synwinxt: < CClassFactory::ctor, g_refCount=%d", g_refCount);
} }
CClassFactory::~CClassFactory() CClassFactory::~CClassFactory()
{ {
outputDebugStringF("synwinxt: > CClassFactory::dtor, g_refCount=%d", g_refCount);
InterlockedDecrement(&g_refCount); InterlockedDecrement(&g_refCount);
outputDebugStringF("synwinxt: < CClassFactory::dtor, g_refCount=%d", g_refCount);
} }
HRESULT STDMETHODCALLTYPE HRESULT STDMETHODCALLTYPE
CClassFactory::QueryInterface(REFIID riid, void **ppvObject) CClassFactory::QueryInterface(REFIID riid, void **ppvObject)
{ {
outputDebugStringF("synwinxt: > CClassFactory::QueryInterface");
static const QITAB qit[] = static const QITAB qit[] =
{ {
QITABENT(CClassFactory, IClassFactory), QITABENT(CClassFactory, IClassFactory),
{ 0 }, { 0 },
}; };
return QISearch(this, qit, riid, ppvObject); HRESULT hr = QISearch(this, qit, riid, ppvObject);
outputDebugStringF("synwinxt: < CClassFactory::QueryInterface, hr=%d", hr);
return hr;
} }
ULONG STDMETHODCALLTYPE ULONG STDMETHODCALLTYPE
CClassFactory::AddRef() CClassFactory::AddRef()
{ {
return InterlockedIncrement(&m_refCount); outputDebugStringF("synwinxt: > CClassFactory::AddRef, m_refCount=%d", m_refCount);
LONG r = InterlockedIncrement(&m_refCount);
outputDebugStringF("synwinxt: < CClassFactory::AddRef, r=%d, m_refCount=%d", r, m_refCount);
return r;
} }
ULONG STDMETHODCALLTYPE ULONG STDMETHODCALLTYPE
CClassFactory::Release() CClassFactory::Release()
{ {
LONG count = InterlockedDecrement(&m_refCount); outputDebugStringF("synwinxt: > CClassFactory::Release, m_refCount=%d", m_refCount);
if (count == 0) { LONG r = InterlockedDecrement(&m_refCount);
if (r == 0) {
delete this; delete this;
} }
return count;
outputDebugStringF("synwinxt: < CClassFactory::Release, r=%d", r);
return r;
} }
HRESULT STDMETHODCALLTYPE HRESULT STDMETHODCALLTYPE
CClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject) CClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject)
{ {
outputDebugStringF("synwinxt: > CClassFactory::CreateInstance");
if (pUnkOuter != NULL) { if (pUnkOuter != NULL) {
return CLASS_E_NOAGGREGATION; return CLASS_E_NOAGGREGATION;
} }
@ -70,18 +87,21 @@ CClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject
if (FAILED(hr)) { if (FAILED(hr)) {
delete pExtension; delete pExtension;
} }
outputDebugStringF("synwinxt: < CClassFactory::CreateInstance, hr=%d", hr);
return hr; return hr;
} }
HRESULT STDMETHODCALLTYPE HRESULT STDMETHODCALLTYPE
CClassFactory::LockServer(BOOL fLock) CClassFactory::LockServer(BOOL fLock)
{ {
outputDebugStringF("synwinxt: > CClassFactory::LockServer, g_refCount=%d", g_refCount);
if (fLock) { if (fLock) {
InterlockedIncrement(&g_refCount); InterlockedIncrement(&g_refCount);
} }
else { else {
InterlockedDecrement(&g_refCount); InterlockedDecrement(&g_refCount);
} }
outputDebugStringF("synwinxt: < CClassFactory::LockServer, g_refCount=%d", g_refCount);
return S_OK; return S_OK;
} }

View File

@ -24,58 +24,82 @@ extern GUID g_CLSID;
extern void updateDraggingDir(char*); extern void updateDraggingDir(char*);
extern void outputDebugStringF(const char *str, ...); extern void outputDebugStringF(const char *str, ...);
CDataHandlerExtension::CDataHandlerExtension() CDataHandlerExtension::CDataHandlerExtension() :
m_refCount(1)
{ {
outputDebugStringF("synwinxt: > CDataHandlerExtension::ctor, g_refCount=%d", g_refCount);
InterlockedIncrement(&g_refCount); InterlockedIncrement(&g_refCount);
outputDebugStringF("synwinxt: < CDataHandlerExtension::ctor, g_refCount=%d", g_refCount);
} }
CDataHandlerExtension::~CDataHandlerExtension() CDataHandlerExtension::~CDataHandlerExtension()
{ {
outputDebugStringF("synwinxt: > CDataHandlerExtension::dtor, g_refCount=%d", g_refCount);
InterlockedDecrement(&g_refCount); InterlockedDecrement(&g_refCount);
outputDebugStringF("synwinxt: < CDataHandlerExtension::dtor, g_refCount=%d", g_refCount);
} }
HRESULT STDMETHODCALLTYPE HRESULT STDMETHODCALLTYPE
CDataHandlerExtension::QueryInterface(REFIID riid, void **ppvObject) CDataHandlerExtension::QueryInterface(REFIID riid, void **ppvObject)
{ {
outputDebugStringF("synwinxt: > CDataHandlerExtension::QueryInterface");
static const QITAB qit[] = static const QITAB qit[] =
{ {
QITABENT(CDataHandlerExtension, IPersistFile), QITABENT(CDataHandlerExtension, IPersistFile),
QITABENT(CDataHandlerExtension, IDataObject), QITABENT(CDataHandlerExtension, IDataObject),
{ 0 }, { 0 },
}; };
return QISearch(this, qit, riid, ppvObject); HRESULT hr = QISearch(this, qit, riid, ppvObject);
if (FAILED(hr)) {
outputDebugStringF("synwinxt: < CDataHandlerExtension::QueryInterface, hr=FAILED");
}
else {
outputDebugStringF("synwinxt: < CDataHandlerExtension::QueryInterface, hr=%d", hr);
}
return hr;
} }
ULONG STDMETHODCALLTYPE ULONG STDMETHODCALLTYPE
CDataHandlerExtension::AddRef() CDataHandlerExtension::AddRef()
{ {
return InterlockedIncrement(&m_refCount); outputDebugStringF("synwinxt: > CDataHandlerExtension::AddRef, m_refCount=%d", m_refCount);
LONG r = InterlockedIncrement(&m_refCount);
outputDebugStringF("synwinxt: < CDataHandlerExtension::AddRef, r=%d, m_refCount=%d", r, m_refCount);
return r;
} }
ULONG STDMETHODCALLTYPE ULONG STDMETHODCALLTYPE
CDataHandlerExtension::Release() CDataHandlerExtension::Release()
{ {
LONG count = InterlockedDecrement(&m_refCount); outputDebugStringF("synwinxt: > CDataHandlerExtension::Release, m_refCount=%d", m_refCount);
if (count == 0) { LONG r = InterlockedDecrement(&m_refCount);
if (r == 0) {
delete this; delete this;
} }
return count; outputDebugStringF("synwinxt: < CDataHandlerExtension::Release, r=%d", r);
return r;
} }
HRESULT STDMETHODCALLTYPE HRESULT STDMETHODCALLTYPE
CDataHandlerExtension::Load(__RPC__in LPCOLESTR pszFileName, DWORD dwMode) CDataHandlerExtension::Load(__RPC__in LPCOLESTR pszFileName, DWORD dwMode)
{ {
outputDebugStringF("synwinxt: > CDataHandlerExtension::Load");
char selectedFileDir[MAX_PATH]; char selectedFileDir[MAX_PATH];
StringCchCopyW(m_selectedFileDir, ARRAYSIZE(m_selectedFileDir), pszFileName); StringCchCopyW(m_selectedFileDir, ARRAYSIZE(m_selectedFileDir), pszFileName);
WideCharToMultiByte(CP_ACP, 0, m_selectedFileDir, -1, selectedFileDir, MAX_PATH, NULL, NULL); WideCharToMultiByte(CP_ACP, 0, m_selectedFileDir, -1, selectedFileDir, MAX_PATH, NULL, NULL);
updateDraggingDir(selectedFileDir); updateDraggingDir(selectedFileDir);
outputDebugStringF("synwinxt: < CDataHandlerExtension::Load");
return S_OK; return S_OK;
} }
HRESULT STDMETHODCALLTYPE HRESULT STDMETHODCALLTYPE
CDataHandlerExtension::GetClassID(__RPC__out CLSID *pClassID) CDataHandlerExtension::GetClassID(__RPC__out CLSID *pClassID)
{ {
outputDebugStringF("synwinxt: > CDataHandlerExtension::GetClassID");
*pClassID = g_CLSID; *pClassID = g_CLSID;
outputDebugStringF("synwinxt: < CDataHandlerExtension::GetClassID");
return S_OK; return S_OK;
} }

View File

@ -43,199 +43,6 @@ HRESULT registerInprocServer(CHAR* module, const CLSID& clsid, CHAR* threadModel
HRESULT registerShellExtDataHandler(CHAR* fileType, const CLSID& clsid); HRESULT registerShellExtDataHandler(CHAR* fileType, const CLSID& clsid);
HRESULT unregisterShellExtDataHandler(CHAR* fileType, const CLSID& clsid); HRESULT unregisterShellExtDataHandler(CHAR* fileType, const CLSID& clsid);
HRESULT unregisterInprocServer(const CLSID& clsid); HRESULT unregisterInprocServer(const CLSID& clsid);
void outputDebugStringF(const char *str, ...);
BOOL APIENTRY
DllMain(HMODULE module, DWORD reason, LPVOID reserved)
{
switch (reason) {
case DLL_PROCESS_ATTACH:
g_instance = module;
DisableThreadLibraryCalls(module);
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
STDAPI
DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppvObj)
{
HRESULT hr = E_OUTOFMEMORY;
*ppvObj = NULL;
CClassFactory *classFactory = new CClassFactory();
if (classFactory != NULL) {
hr = classFactory->QueryInterface(riid, ppvObj);
classFactory->Release();
}
return hr;
}
STDAPI
DllCanUnloadNow()
{
return g_refCount > 0 ? S_FALSE : S_OK;
}
STDAPI
DllRegisterServer()
{
HRESULT hr;
CHAR module[MAX_PATH];
if (GetModuleFileName(g_instance, module, ARRAYSIZE(module)) == 0) {
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
// Register the component.
hr = registerInprocServer(
module,
g_CLSID,
"Apartment");
if (SUCCEEDED(hr)) {
hr = registerShellExtDataHandler(
"*",
g_CLSID);
}
return hr;
}
STDAPI
DllUnregisterServer()
{
HRESULT hr = S_OK;
CHAR module[MAX_PATH];
if (GetModuleFileName(g_instance, module, ARRAYSIZE(module)) == 0) {
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
// Unregister the component.
hr = unregisterInprocServer(g_CLSID);
if (SUCCEEDED(hr)) {
// Unregister the context menu handler.
hr = unregisterShellExtDataHandler("*", g_CLSID);
}
return hr;
}
HRESULT
registerInprocServer(CHAR* module, const CLSID& clsid, CHAR* threadModel)
{
if (module == NULL || threadModel == NULL) {
return E_INVALIDARG;
}
HRESULT hr;
WCHAR CLASSID[MAX_PATH];
CHAR szCLSID[MAX_PATH];
StringFromGUID2(clsid, CLASSID, ARRAYSIZE(CLASSID));
WideCharToMultiByte(CP_ACP, 0, CLASSID, -1, szCLSID, MAX_PATH, NULL, NULL);
CHAR subkey[MAX_PATH];
// Create the HKCR\CLSID\{<CLSID>}\InprocServer32 key.
hr = StringCchPrintf(subkey, ARRAYSIZE(subkey), "CLSID\\%s\\InprocServer32", szCLSID);
if (SUCCEEDED(hr)) {
// Set the default value of the InprocServer32 key to the
// path of the COM module.
HKEY key = CArchMiscWindows::addKey(HKEY_CLASSES_ROOT, subkey);
CArchMiscWindows::setValue(key, NULL, module);
if (SUCCEEDED(hr)) {
// Set the threading model of the component.
CArchMiscWindows::setValue(key, "ThreadingModel", threadModel);
}
}
return hr;
}
HRESULT
unregisterInprocServer(const CLSID& clsid)
{
HRESULT hr = S_OK;
WCHAR CLASSID[MAX_PATH];
CHAR szCLSID[MAX_PATH];
StringFromGUID2(clsid, CLASSID, ARRAYSIZE(CLASSID));
WideCharToMultiByte(CP_ACP, 0, CLASSID, -1, szCLSID, MAX_PATH, NULL, NULL);
CHAR subkey[MAX_PATH];
// Delete the HKCR\CLSID\{<CLSID>} key.
hr = StringCchPrintf(subkey, ARRAYSIZE(subkey), "CLSID\\%s", szCLSID);
if (SUCCEEDED(hr)) {
hr = HRESULT_FROM_WIN32(RegDeleteTree(HKEY_CLASSES_ROOT, subkey));
}
return hr;
}
HRESULT
registerShellExtDataHandler(CHAR* fileType, const CLSID& clsid)
{
if (fileType == NULL) {
return E_INVALIDARG;
}
HRESULT hr;
WCHAR szCLSID[MAX_PATH];
CHAR CLASSID[MAX_PATH];
StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
WideCharToMultiByte(CP_ACP, 0, szCLSID, -1, CLASSID, MAX_PATH, NULL, NULL);
CHAR subkey[MAX_PATH];
// Create the key HKCR\<File Type>\shellex\DataHandler
hr = StringCchPrintf(subkey, ARRAYSIZE(subkey), "%s\\shellex\\DataHandler", fileType);
if (SUCCEEDED(hr)) {
// Set the default value of the key.
HKEY key = CArchMiscWindows::addKey(HKEY_CLASSES_ROOT, subkey);
CArchMiscWindows::setValue(key, NULL, CLASSID);
}
return hr;
}
HRESULT
unregisterShellExtDataHandler(CHAR* fileType, const CLSID& clsid)
{
if (fileType == NULL) {
return E_INVALIDARG;
}
HRESULT hr;
WCHAR CLASSID[MAX_PATH];
CHAR szCLSID[MAX_PATH];
StringFromGUID2(clsid, CLASSID, ARRAYSIZE(CLASSID));
WideCharToMultiByte(CP_ACP, 0, CLASSID, -1, szCLSID, MAX_PATH, NULL, NULL);
CHAR subkey[MAX_PATH];
// Remove the HKCR\<File Type>\shellex\DataHandler key.
hr = StringCchPrintf(subkey, ARRAYSIZE(subkey), "%s\\shellex\\DataHandler", fileType);
if (SUCCEEDED(hr)) {
hr = HRESULT_FROM_WIN32(RegDeleteTree(HKEY_CLASSES_ROOT, subkey));
}
return hr;
}
void void
outputDebugStringF(const char* str, ...) outputDebugStringF(const char* str, ...)
@ -249,15 +56,243 @@ outputDebugStringF(const char* str, ...)
OutputDebugStringA(buf); OutputDebugStringA(buf);
} }
BOOL APIENTRY
DllMain(HMODULE module, DWORD reason, LPVOID reserved)
{
outputDebugStringF("synwinxt: > DllMain, reason=%d", reason);
switch (reason) {
case DLL_PROCESS_ATTACH:
g_instance = module;
DisableThreadLibraryCalls(module);
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
outputDebugStringF("synwinxt: < DllMain");
return TRUE;
}
STDAPI
DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppvObj)
{
outputDebugStringF("synwinxt: > DllGetClassObject");
HRESULT hr = E_OUTOFMEMORY;
*ppvObj = NULL;
CClassFactory *classFactory = new CClassFactory();
if (classFactory != NULL) {
hr = classFactory->QueryInterface(riid, ppvObj);
classFactory->Release();
}
outputDebugStringF("synwinxt: < DllGetClassObject, hr=%d", hr);
return hr;
}
STDAPI
DllCanUnloadNow()
{
outputDebugStringF("synwinxt: > DllCanUnloadNow, g_refCount=%d", g_refCount);
int r = g_refCount > 0 ? S_FALSE : S_OK;
outputDebugStringF("synwinxt: < DllCanUnloadNow, g_refCount=%d, r=%d", g_refCount, r);
return r;
}
STDAPI
DllRegisterServer()
{
outputDebugStringF("synwinxt: > DllRegisterServer");
HRESULT hr;
CHAR module[MAX_PATH];
if (GetModuleFileName(g_instance, module, ARRAYSIZE(module)) == 0) {
hr = HRESULT_FROM_WIN32(GetLastError());
outputDebugStringF("synwinxt: < DllRegisterServer, hr=%d", hr);
return hr;
}
hr = registerInprocServer(
module,
g_CLSID,
"Apartment");
if (SUCCEEDED(hr)) {
hr = registerShellExtDataHandler(
"*",
g_CLSID);
}
outputDebugStringF("synwinxt: < DllRegisterServer, hr=%d", hr);
return hr;
}
STDAPI
DllUnregisterServer()
{
outputDebugStringF("synwinxt: > DllUnregisterServer");
HRESULT hr = S_OK;
CHAR module[MAX_PATH];
if (GetModuleFileName(g_instance, module, ARRAYSIZE(module)) == 0) {
hr = HRESULT_FROM_WIN32(GetLastError());
outputDebugStringF("synwinxt: < DllRegisterServer, hr=%d", hr);
return hr;
}
hr = unregisterInprocServer(g_CLSID);
if (SUCCEEDED(hr)) {
hr = unregisterShellExtDataHandler("*", g_CLSID);
}
outputDebugStringF("synwinxt: < DllUnregisterServer, hr=%d", hr);
return hr;
}
HRESULT
registerInprocServer(CHAR* module, const CLSID& clsid, CHAR* threadModel)
{
outputDebugStringF("synwinxt: > registerInprocServer");
if (module == NULL || threadModel == NULL) {
return E_INVALIDARG;
}
HRESULT hr;
WCHAR CLASSID[MAX_PATH];
CHAR szCLSID[MAX_PATH];
StringFromGUID2(clsid, CLASSID, ARRAYSIZE(CLASSID));
WideCharToMultiByte(CP_ACP, 0, CLASSID, -1, szCLSID, MAX_PATH, NULL, NULL);
CHAR subkey[MAX_PATH];
// create the HKCR\CLSID\{<CLSID>}\InprocServer32 key.
hr = StringCchPrintf(subkey, ARRAYSIZE(subkey), "CLSID\\%s\\InprocServer32", szCLSID);
if (SUCCEEDED(hr)) {
// set the default value of the InprocServer32 key to the
// path of the COM module.
HKEY key = CArchMiscWindows::addKey(HKEY_CLASSES_ROOT, subkey);
CArchMiscWindows::setValue(key, NULL, module);
if (SUCCEEDED(hr)) {
// set the threading model of the component.
CArchMiscWindows::setValue(key, "ThreadingModel", threadModel);
}
}
outputDebugStringF("synwinxt: < registerInprocServer, hr=%d", hr);
return hr;
}
HRESULT
unregisterInprocServer(const CLSID& clsid)
{
outputDebugStringF("synwinxt: > unregisterInprocServer");
HRESULT hr = S_OK;
WCHAR CLASSID[MAX_PATH];
CHAR szCLSID[MAX_PATH];
StringFromGUID2(clsid, CLASSID, ARRAYSIZE(CLASSID));
WideCharToMultiByte(CP_ACP, 0, CLASSID, -1, szCLSID, MAX_PATH, NULL, NULL);
CHAR subkey[MAX_PATH];
// delete the HKCR\CLSID\{<CLSID>} key.
hr = StringCchPrintf(subkey, ARRAYSIZE(subkey), "CLSID\\%s", szCLSID);
if (SUCCEEDED(hr)) {
hr = HRESULT_FROM_WIN32(RegDeleteTree(HKEY_CLASSES_ROOT, subkey));
}
if (FAILED(hr)) {
outputDebugStringF("synwinxt: < unregisterInprocServer, hr=FAILED");
}
else {
outputDebugStringF("synwinxt: < unregisterInprocServer, hr=%d", hr);
}
return hr;
}
HRESULT
registerShellExtDataHandler(CHAR* fileType, const CLSID& clsid)
{
outputDebugStringF("synwinxt: > registerShellExtDataHandler");
if (fileType == NULL) {
return E_INVALIDARG;
}
HRESULT hr;
WCHAR szCLSID[MAX_PATH];
CHAR CLASSID[MAX_PATH];
StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
WideCharToMultiByte(CP_ACP, 0, szCLSID, -1, CLASSID, MAX_PATH, NULL, NULL);
CHAR subkey[MAX_PATH];
// create the key HKCR\<File Type>\shellex\DataHandler
hr = StringCchPrintf(subkey, ARRAYSIZE(subkey), "%s\\shellex\\DataHandler", fileType);
if (SUCCEEDED(hr)) {
// set the default value of the key.
HKEY key = CArchMiscWindows::addKey(HKEY_CLASSES_ROOT, subkey);
CArchMiscWindows::setValue(key, NULL, CLASSID);
}
outputDebugStringF("synwinxt: < registerShellExtDataHandler, hr=%d", hr);
return hr;
}
HRESULT
unregisterShellExtDataHandler(CHAR* fileType, const CLSID& clsid)
{
outputDebugStringF("synwinxt: > unregisterShellExtDataHandler");
if (fileType == NULL) {
return E_INVALIDARG;
}
HRESULT hr;
WCHAR CLASSID[MAX_PATH];
CHAR szCLSID[MAX_PATH];
StringFromGUID2(clsid, CLASSID, ARRAYSIZE(CLASSID));
WideCharToMultiByte(CP_ACP, 0, CLASSID, -1, szCLSID, MAX_PATH, NULL, NULL);
CHAR subkey[MAX_PATH];
// remove the HKCR\<File Type>\shellex\DataHandler key.
hr = StringCchPrintf(subkey, ARRAYSIZE(subkey), "%s\\shellex\\DataHandler", fileType);
if (SUCCEEDED(hr)) {
hr = HRESULT_FROM_WIN32(RegDeleteTree(HKEY_CLASSES_ROOT, subkey));
}
outputDebugStringF("synwinxt: < unregisterShellExtDataHandler, hr=%d", hr);
return hr;
}
void void
updateDraggingDir(char* dir) updateDraggingDir(char* dir)
{ {
outputDebugStringF("synwinxt: > updateDraggingDir, dir=%s", dir);
memcpy(g_draggingFileDir, dir, MAX_PATH); memcpy(g_draggingFileDir, dir, MAX_PATH);
outputDebugStringF("draggingFileDir: %s", g_draggingFileDir); outputDebugStringF("synwinxt: < updateDraggingDir, g_draggingFileDir=%s", g_draggingFileDir);
} }
void void
getDraggingFileDir(char* dir) getDraggingFileDir(char* dir)
{ {
outputDebugStringF("synwinxt: > getDraggingFileDir");
memcpy(dir, g_draggingFileDir, MAX_PATH); memcpy(dir, g_draggingFileDir, MAX_PATH);
outputDebugStringF("synwinxt: < getDraggingFileDir, dir=%s", dir);
} }