From 552985214842965925143997a08fe98baf738679 Mon Sep 17 00:00:00 2001
From: George Hazan <george.hazan@gmail.com>
Date: Thu, 29 Aug 2013 20:53:23 +0000
Subject: - logging disabled for the future times - fixed crash when groups are
 enabled; - fixed incompatibility with Windows 7's Explorer; - correct error
 codes for COM; - version bump

git-svn-id: http://svn.miranda-ng.org/main/trunk@5886 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
---
 plugins/ShellExt/shellext_10.vcxproj         |  1 +
 plugins/ShellExt/shellext_10.vcxproj.filters |  3 ++
 plugins/ShellExt/shellext_11.vcxproj         |  1 +
 plugins/ShellExt/shellext_11.vcxproj.filters |  3 ++
 plugins/ShellExt/src/Version.h               |  2 +-
 plugins/ShellExt/src/main.cpp                | 22 +++-------
 plugins/ShellExt/src/shlcom.cpp              | 52 ++++++++++++++--------
 plugins/ShellExt/src/shlipc.cpp              |  4 +-
 plugins/ShellExt/src/stdafx.h                |  8 +++-
 plugins/ShellExt/src/utils.cpp               | 65 ++++++++++++++++++++++++++++
 10 files changed, 124 insertions(+), 37 deletions(-)
 create mode 100644 plugins/ShellExt/src/utils.cpp

diff --git a/plugins/ShellExt/shellext_10.vcxproj b/plugins/ShellExt/shellext_10.vcxproj
index fb9612b919..45cfcfa71c 100644
--- a/plugins/ShellExt/shellext_10.vcxproj
+++ b/plugins/ShellExt/shellext_10.vcxproj
@@ -206,6 +206,7 @@
     <ClCompile Include="src\stdafx.cpp">
       <PrecompiledHeader>Create</PrecompiledHeader>
     </ClCompile>
+    <ClCompile Include="src\utils.cpp" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
diff --git a/plugins/ShellExt/shellext_10.vcxproj.filters b/plugins/ShellExt/shellext_10.vcxproj.filters
index edd3cd00af..0e637ca837 100644
--- a/plugins/ShellExt/shellext_10.vcxproj.filters
+++ b/plugins/ShellExt/shellext_10.vcxproj.filters
@@ -58,5 +58,8 @@
     <ClCompile Include="src\shlicons.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="src\utils.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/plugins/ShellExt/shellext_11.vcxproj b/plugins/ShellExt/shellext_11.vcxproj
index a69693f4a5..d32623c2d2 100644
--- a/plugins/ShellExt/shellext_11.vcxproj
+++ b/plugins/ShellExt/shellext_11.vcxproj
@@ -209,6 +209,7 @@
     <ClCompile Include="src\stdafx.cpp">
       <PrecompiledHeader>Create</PrecompiledHeader>
     </ClCompile>
+    <ClCompile Include="src\utils.cpp" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
diff --git a/plugins/ShellExt/shellext_11.vcxproj.filters b/plugins/ShellExt/shellext_11.vcxproj.filters
index edd3cd00af..0e637ca837 100644
--- a/plugins/ShellExt/shellext_11.vcxproj.filters
+++ b/plugins/ShellExt/shellext_11.vcxproj.filters
@@ -58,5 +58,8 @@
     <ClCompile Include="src\shlicons.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="src\utils.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/plugins/ShellExt/src/Version.h b/plugins/ShellExt/src/Version.h
index d1fe4e6114..a0257b4297 100644
--- a/plugins/ShellExt/src/Version.h
+++ b/plugins/ShellExt/src/Version.h
@@ -1,7 +1,7 @@
 #define __MAJOR_VERSION      2
 #define __MINOR_VERSION      2
 #define __RELEASE_NUM        0
-#define __BUILD_NUM          1
+#define __BUILD_NUM          2
 
 #define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM
 #define __FILEVERSION_STRING_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM
diff --git a/plugins/ShellExt/src/main.cpp b/plugins/ShellExt/src/main.cpp
index 08050b22ea..33d1ed0b83 100644
--- a/plugins/ShellExt/src/main.cpp
+++ b/plugins/ShellExt/src/main.cpp
@@ -3,7 +3,7 @@
 HINSTANCE hInst;
 int hLangpack;
 
-static TCHAR tszLogPath[MAX_PATH];
+TCHAR tszLogPath[MAX_PATH];
 
 PLUGININFOEX pluginInfoEx = {
 	sizeof(PLUGININFOEX),
@@ -81,11 +81,15 @@ STDAPI DllRegisterServer()
 	if ( RegSetValueA(kClsid, "ProgID", REG_SZ, str3, sizeof(str3)))
 		return E_FAIL;
 
+	HRegKey kInprocServer(kClsid, "InprocServer32");
+	if (kInprocServer == NULL)
+		return E_FAIL;
+
 	TCHAR tszFileName[MAX_PATH];
 	GetModuleFileName(hInst, tszFileName, SIZEOF(tszFileName));
-	if ( RegSetValue(kClsid, _T("InprocServer32"), REG_SZ, tszFileName, lstrlen(tszFileName)))
+	if ( RegSetValueEx(kInprocServer, NULL, 0, REG_SZ, (LPBYTE)tszFileName, sizeof(TCHAR)*(lstrlen(tszFileName)+1)))
 		return E_FAIL;
-	if ( RegSetValueA(kClsid, "InprocServer32\\ThreadingModel", REG_SZ, str4, sizeof(str4)))
+	if ( RegSetValueExA(kInprocServer, "ThreadingModel", 0, REG_SZ, (PBYTE)str4, sizeof(str4)))
 		return E_FAIL;
 
 	//////////////////////////////////////////////////////////////////////////////////////
@@ -113,18 +117,6 @@ STDAPI DllUnregisterServer()
 
 /////////////////////////////////////////////////////////////////////////////////////////
 
-void logA(const char *format, ...)
-{
-	FILE *out = _tfopen(tszLogPath, _T("a+"));
-	if (out) {
-		va_list args;
-		va_start(args, format);
-		vfprintf(out, format, args);
-		va_end(args);
-		fclose(out);
-	}
-}
-
 extern "C" __declspec(dllexport) int Load(void)
 {
 	mir_getLP(&pluginInfoEx);
diff --git a/plugins/ShellExt/src/shlcom.cpp b/plugins/ShellExt/src/shlcom.cpp
index 7f37daedd2..2b498f08e8 100644
--- a/plugins/ShellExt/src/shlcom.cpp
+++ b/plugins/ShellExt/src/shlcom.cpp
@@ -91,7 +91,7 @@ void FreeGroupTreeAndEmptyGroups(HMENU hParentMenu, TGroupNode *pp, TGroupNode *
 			if (pp != NULL)
 				pp->dwItems++;
 
-		mir_free(p);
+		free(p);
 		p = q;
 	}
 }
@@ -189,7 +189,7 @@ void BuildContactTree(TGroupNode *group, TEnumData *lParam)
 			TGroupNode *pg = group;
 			unsigned Depth = 0;
 			while (sz != NULL) {
-				UINT Hash = mir_hashstr(sz);
+				UINT Hash = murmur_hash(sz);
 				// find this node within
 				while (pg != NULL) {
 					// does this node have the right hash and the right depth?
@@ -297,7 +297,7 @@ void BuildMenus(TEnumData *lParam)
 		// get the group
 		Token = strtok(LPSTR(pg) + sizeof(TSlotIPC), "\\");
 		while (Token != NULL) {
-			UINT Hash = mir_hashstr(Token);
+			UINT Hash = murmur_hash(Token);
 			// if the (sub)group doesn't exist, create it.
 			TGroupNode *q = FindGroupNode(p, Hash, Depth);
 			if (q == NULL) {
@@ -606,12 +606,22 @@ HRESULT TShlComRec::QueryInterface(REFIID riid, void **ppvObject)
 		return S_OK;
 	}
 
+	// and, finally, IUnknown
+	if (riid == IID_IUnknown) {
+		*ppvObject = this;
+		RefCount++;
+		logA("TShlComRec[%p] retrieved as IUnknown: %d\n", this, RefCount);
+		return S_OK;
+	}
+
 	*ppvObject = NULL;
-	RPC_CSTR szGuid;
-	UuidToStringA(&riid, &szGuid);
-	logA("TShlComRec[%p] failed as {%s}\n", this, szGuid);
-	RpcStringFreeA(&szGuid);
-	return CLASS_E_CLASSNOTAVAILABLE;
+	#ifdef LOG_ENABLED
+		RPC_CSTR szGuid;
+		UuidToStringA(&riid, &szGuid);
+		logA("TShlComRec[%p] failed as {%s}\n", this, szGuid);
+		RpcStringFreeA(&szGuid);
+	#endif
+	return E_NOINTERFACE;
 }
 
 ULONG TShlComRec::AddRef()
@@ -1011,8 +1021,14 @@ struct TClassFactoryRec : public IClassFactory
 
 HRESULT TClassFactoryRec::QueryInterface(REFIID riid, void **ppvObject)
 {
+	#ifdef LOG_ENABLED
+		RPC_CSTR szGuid;
+		UuidToStringA(&riid, &szGuid);
+		logA("TClassFactoryRec::QueryInterface {%08x-%04x-%04x-%08x%08x} failed\n", szGuid);
+		RpcStringFreeA(&szGuid);
+	#endif
 	*ppvObject = NULL;
-	return E_NOTIMPL;
+	return E_NOINTERFACE;
 }
 
 ULONG TClassFactoryRec::AddRef()
@@ -1215,7 +1231,7 @@ void ipcGetSkinIcons(THeaderIPC *ipch)
 				TSlotIPC *pct = ipcAlloc(ipch, sizeof(TSlotProtoIcons));
 				if (pct != NULL) {
 					// capture all the icons!
-					spi.hProto = mir_hashstr(pa->szModuleName);
+					spi.hProto = murmur_hash(pa->szModuleName);
 					for (int j = 0; j <= 10; j++)
 						spi.hIcons[j] = LoadSkinnedProtoIcon(pa->szModuleName, ID_STATUS_OFFLINE + j);
 
@@ -1300,7 +1316,7 @@ bool ipcGetSortedContacts(THeaderIPC *ipch, int *pSlot, bool bGroupMode)
 			// store
 			pContacts[i].hContact = hContact;
 			pContacts[i].dwStatus = dwStatus;
-			pContacts[i].hProto = mir_hashstr(szProto);
+			pContacts[i].hProto = murmur_hash(szProto);
 			i++;
 		}
 	}
@@ -1344,7 +1360,7 @@ bool ipcGetSortedContacts(THeaderIPC *ipch, int *pSlot, bool bGroupMode)
 				ipch->ContactsBegin = pct;
 			szSlot += cch + 1;
 			if (rc == 0) {
-				pct->hGroup = mir_hashstr(dbv.pszVal);
+				pct->hGroup = murmur_hash(dbv.pszVal);
 				lstrcpyA(szSlot, dbv.pszVal);
 				db_free(&dbv);
 			}
@@ -1537,12 +1553,14 @@ STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
 		return S_OK;
 	}
 
-	*ppv = NULL;
-	RPC_CSTR szGuid;
-	UuidToStringA(&riid, &szGuid);
-	logA("DllGetClassObject {%08x-%04x-%04x-%08x%08x} failed\n", szGuid);
-	RpcStringFreeA(&szGuid);
+	#ifdef LOG_ENABLED
+		RPC_CSTR szGuid;
+		UuidToStringA(&riid, &szGuid);
+		logA("DllGetClassObject {%08x-%04x-%04x-%08x%08x} failed\n", szGuid);
+		RpcStringFreeA(&szGuid);
+	#endif
 
+	*ppv = NULL;
 	return CLASS_E_CLASSNOTAVAILABLE;
 }
 
diff --git a/plugins/ShellExt/src/shlipc.cpp b/plugins/ShellExt/src/shlipc.cpp
index f21c599d20..a58dd76055 100644
--- a/plugins/ShellExt/src/shlipc.cpp
+++ b/plugins/ShellExt/src/shlipc.cpp
@@ -19,9 +19,7 @@ TGroupNode* FindGroupNode(TGroupNode *p, const DWORD Hash, int Depth)
 
 TGroupNode* AllocGroupNode(TGroupNodeList *list, TGroupNode *Root, int Depth)
 {
-	TGroupNode *p = (TGroupNode*)mir_alloc( sizeof(TGroupNode));
-	p->Left = NULL;
-	p->Right = NULL;
+	TGroupNode *p = (TGroupNode*)calloc(1, sizeof(TGroupNode));
 	p->Depth = Depth;
 	if (Depth > 0) {
 		if (Root->Left == NULL)
diff --git a/plugins/ShellExt/src/stdafx.h b/plugins/ShellExt/src/stdafx.h
index a5753b7a91..4527f78a08 100644
--- a/plugins/ShellExt/src/stdafx.h
+++ b/plugins/ShellExt/src/stdafx.h
@@ -49,4 +49,10 @@ extern  HANDLE hLogger;
 
 int OnOptionsInit(WPARAM wParam, LPARAM lParam);
 
-void logA(const char *format, ...);
\ No newline at end of file
+#ifdef LOG_ENABLED
+void logA(const char *format, ...);
+#else
+#define logA(A, ...) 
+#endif
+
+UINT murmur_hash(const char *str);
diff --git a/plugins/ShellExt/src/utils.cpp b/plugins/ShellExt/src/utils.cpp
new file mode 100644
index 0000000000..22e033fb42
--- /dev/null
+++ b/plugins/ShellExt/src/utils.cpp
@@ -0,0 +1,65 @@
+#include "stdafx.h"
+
+#ifdef LOG_ENABLED
+extern TCHAR tszLogPath[];
+
+void logA(const char *format, ...)
+{
+	FILE *out = _tfopen(tszLogPath, _T("a+"));
+	if (out) {
+		va_list args;
+		va_start(args, format);
+		vfprintf(out, format, args);
+		va_end(args);
+		fclose(out);
+	}
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+UINT murmur_hash(const char *str)
+{
+	size_t len = lstrlenA(str);
+
+	// 'm' and 'r' are mixing constants generated offline.
+	// They're not really 'magic', they just happen to work well.
+	const unsigned int m = 0x5bd1e995;
+	const int r = 24;
+
+	// Initialize the hash to a 'random' value
+	unsigned int h = (unsigned)len;
+
+	// Mix 4 bytes at a time into the hash
+	const unsigned char *data = (const unsigned char*)str;
+
+	while (len >= 4) {
+		unsigned int k = *(unsigned int*)data;
+
+		k *= m;
+		k ^= k >> r;
+		k *= m;
+
+		h *= m;
+		h ^= k;
+
+		data += 4;
+		len -= 4;
+	}
+
+	// Handle the last few bytes of the input array
+	switch(len) {
+	case 3: h ^= data[2] << 16;
+	case 2: h ^= data[1] << 8;
+	case 1: h ^= data[0];
+			h *= m;
+	}
+
+	// Do a few final mixes of the hash to ensure the last few
+	// bytes are well-incorporated.
+	h ^= h >> 13;
+	h *= m;
+	h ^= h >> 15;
+
+	return h;
+}
-- 
cgit v1.2.3