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

View File

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

View File

@ -24,58 +24,82 @@ extern GUID g_CLSID;
extern void updateDraggingDir(char*);
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);
outputDebugStringF("synwinxt: < CDataHandlerExtension::ctor, g_refCount=%d", g_refCount);
}
CDataHandlerExtension::~CDataHandlerExtension()
{
outputDebugStringF("synwinxt: > CDataHandlerExtension::dtor, g_refCount=%d", g_refCount);
InterlockedDecrement(&g_refCount);
outputDebugStringF("synwinxt: < CDataHandlerExtension::dtor, g_refCount=%d", g_refCount);
}
HRESULT STDMETHODCALLTYPE
CDataHandlerExtension::QueryInterface(REFIID riid, void **ppvObject)
{
outputDebugStringF("synwinxt: > CDataHandlerExtension::QueryInterface");
static const QITAB qit[] =
{
QITABENT(CDataHandlerExtension, IPersistFile),
QITABENT(CDataHandlerExtension, IDataObject),
{ 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
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
CDataHandlerExtension::Release()
{
LONG count = InterlockedDecrement(&m_refCount);
if (count == 0) {
outputDebugStringF("synwinxt: > CDataHandlerExtension::Release, m_refCount=%d", m_refCount);
LONG r = InterlockedDecrement(&m_refCount);
if (r == 0) {
delete this;
}
return count;
outputDebugStringF("synwinxt: < CDataHandlerExtension::Release, r=%d", r);
return r;
}
HRESULT STDMETHODCALLTYPE
CDataHandlerExtension::Load(__RPC__in LPCOLESTR pszFileName, DWORD dwMode)
{
outputDebugStringF("synwinxt: > CDataHandlerExtension::Load");
char selectedFileDir[MAX_PATH];
StringCchCopyW(m_selectedFileDir, ARRAYSIZE(m_selectedFileDir), pszFileName);
WideCharToMultiByte(CP_ACP, 0, m_selectedFileDir, -1, selectedFileDir, MAX_PATH, NULL, NULL);
updateDraggingDir(selectedFileDir);
outputDebugStringF("synwinxt: < CDataHandlerExtension::Load");
return S_OK;
}
HRESULT STDMETHODCALLTYPE
CDataHandlerExtension::GetClassID(__RPC__out CLSID *pClassID)
{
outputDebugStringF("synwinxt: > CDataHandlerExtension::GetClassID");
*pClassID = g_CLSID;
outputDebugStringF("synwinxt: < CDataHandlerExtension::GetClassID");
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 unregisterShellExtDataHandler(CHAR* fileType, 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
outputDebugStringF(const char* str, ...)
@ -249,15 +56,243 @@ outputDebugStringF(const char* str, ...)
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
updateDraggingDir(char* dir)
{
outputDebugStringF("synwinxt: > updateDraggingDir, dir=%s", dir);
memcpy(g_draggingFileDir, dir, MAX_PATH);
outputDebugStringF("draggingFileDir: %s", g_draggingFileDir);
outputDebugStringF("synwinxt: < updateDraggingDir, g_draggingFileDir=%s", g_draggingFileDir);
}
void
getDraggingFileDir(char* dir)
{
outputDebugStringF("synwinxt: > getDraggingFileDir");
memcpy(dir, g_draggingFileDir, MAX_PATH);
outputDebugStringF("synwinxt: < getDraggingFileDir, dir=%s", dir);
}