Fisheye: Tag 6609ba39811176f4803f0556db3da30e9e457b9d refers to a dead (removed) revision in file `src/ch/TRegistry.cpp'.
Fisheye: No comparison available.  Pass `N' to diff?
Index: src/ch/TShellExtensionClient.cpp
===================================================================
diff -u -r9ddf8fdd5f641491dd30c49eb90f8f740314b6af -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/ch/TShellExtensionClient.cpp	(.../TShellExtensionClient.cpp)	(revision 9ddf8fdd5f641491dd30c49eb90f8f740314b6af)
+++ src/ch/TShellExtensionClient.cpp	(.../TShellExtensionClient.cpp)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -20,6 +20,7 @@
 #include "TShellExtensionClient.h"
 #include "objbase.h"
 #include "../chext/Logger.h"
+#include "../chext/guids.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
Index: src/ch/TShellExtensionClient.h
===================================================================
diff -u -rb556d023b748dfea230575959b6513acf29fd7b3 -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/ch/TShellExtensionClient.h	(.../TShellExtensionClient.h)	(revision b556d023b748dfea230575959b6513acf29fd7b3)
+++ src/ch/TShellExtensionClient.h	(.../TShellExtensionClient.h)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -19,9 +19,9 @@
 #ifndef __TSHELLEXTENSIONCLIENT_H__
 #define __TSHELLEXTENSIONCLIENT_H__
 
-#include "../chext/chext.h"
 #include "../liblogger/TLogger.h"
 #include "../common/ERegistrationResult.h"
+#include "../chext/IShellExtControl.h"
 
 class TShellExtensionClient
 {
Index: src/ch/WindowsVersion.cpp
===================================================================
diff -u -rb26ced3298e3e7e51d91f3ac70b56746786da83b -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/ch/WindowsVersion.cpp	(.../WindowsVersion.cpp)	(revision b26ced3298e3e7e51d91f3ac70b56746786da83b)
+++ src/ch/WindowsVersion.cpp	(.../WindowsVersion.cpp)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -18,7 +18,7 @@
 // ============================================================================
 #include "stdafx.h"
 #include "WindowsVersion.h"
-#include "TRegistry.h"
+#include "../common/TRegistry.h"
 #include <boost/lexical_cast.hpp>
 #include <boost/algorithm/string/replace.hpp>
 
Index: src/ch/ch.vc140.vcxproj
===================================================================
diff -u -r0d5b67ee96b435d63f7bf075dc8e28603793b187 -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/ch/ch.vc140.vcxproj	(.../ch.vc140.vcxproj)	(revision 0d5b67ee96b435d63f7bf075dc8e28603793b187)
+++ src/ch/ch.vc140.vcxproj	(.../ch.vc140.vcxproj)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -518,6 +518,7 @@
   <ItemGroup>
     <ClInclude Include="..\Common\ipcstructs.h" />
     <ClInclude Include="..\common\targetver.h" />
+    <ClInclude Include="..\common\TRegistry.h" />
     <ClInclude Include="..\common\TShellExtIpcConfigDataProvider.h" />
     <ClInclude Include="..\common\TShellExtMenuConfig.h" />
     <ClInclude Include="..\common\version.h" />
@@ -538,7 +539,6 @@
     <ClInclude Include="TPathProcessor.h" />
     <ClInclude Include="TProgressCtrlEx.h" />
     <ClInclude Include="TRecentPathsTools.h" />
-    <ClInclude Include="TRegistry.h" />
     <ClInclude Include="TShellExtensionConfig.h" />
     <ClInclude Include="TTaskManagerWrapper.h" />
     <ClInclude Include="TWindowMessageFilterHelper.h" />
@@ -773,6 +773,7 @@
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Testing Debug|x64'">NotUsing</PrecompiledHeader>
     </ClCompile>
+    <ClCompile Include="..\common\TRegistry.cpp" />
     <ClCompile Include="..\common\TShellExtIpcConfigDataProvider.cpp" />
     <ClCompile Include="..\common\TShellExtMenuConfig.cpp" />
     <ClCompile Include="AsyncHttpFile.cpp" />
@@ -791,7 +792,6 @@
     <ClCompile Include="TPathProcessor.cpp" />
     <ClCompile Include="TProgressCtrlEx.cpp" />
     <ClCompile Include="TRecentPathsTools.cpp" />
-    <ClCompile Include="TRegistry.cpp" />
     <ClCompile Include="TShellExtensionConfig.cpp" />
     <ClCompile Include="TTaskManagerWrapper.cpp" />
     <ClCompile Include="TWindowMessageFilterHelper.cpp" />
@@ -837,24 +837,6 @@
     <ClCompile Include="UpdateMultipleVersionInfo.cpp" />
     <ClCompile Include="UpdaterDlg.cpp" />
     <ClCompile Include="TShellExtensionClient.cpp" />
-    <ClCompile Include="..\chext\chext_i.c">
-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-      </PrecompiledHeader>
-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Testing Debug|Win32'">
-      </PrecompiledHeader>
-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-      </PrecompiledHeader>
-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Testing Debug|x64'">
-      </PrecompiledHeader>
-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-      </PrecompiledHeader>
-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Testing Release|Win32'">
-      </PrecompiledHeader>
-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-      </PrecompiledHeader>
-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Testing Release|x64'">
-      </PrecompiledHeader>
-    </ClCompile>
     <ClCompile Include="UpdateResponse.cpp" />
     <ClCompile Include="UpdateVersionInfo.cpp" />
     <ClCompile Include="WindowsVersion.cpp" />
Index: src/ch/ch.vc140.vcxproj.filters
===================================================================
diff -u -r5f6477e71c348782f8149a86c7a3ae903e5ff635 -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/ch/ch.vc140.vcxproj.filters	(.../ch.vc140.vcxproj.filters)	(revision 5f6477e71c348782f8149a86c7a3ae903e5ff635)
+++ src/ch/ch.vc140.vcxproj.filters	(.../ch.vc140.vcxproj.filters)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -203,9 +203,6 @@
     <ClInclude Include="WindowsVersion.h">
       <Filter>Source Files\Tools</Filter>
     </ClInclude>
-    <ClInclude Include="TRegistry.h">
-      <Filter>Source Files\Tools</Filter>
-    </ClInclude>
     <ClInclude Include="AsyncHttpFile.h">
       <Filter>Source Files\Tools</Filter>
     </ClInclude>
@@ -257,6 +254,9 @@
     <ClInclude Include="FeedbackReplaceDlg.h">
       <Filter>Source Files\GUI\Dialogs\Feedback</Filter>
     </ClInclude>
+    <ClInclude Include="..\common\TRegistry.h">
+      <Filter>Source Files\Shared</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\common\TShellExtMenuConfig.cpp">
@@ -361,9 +361,6 @@
     <ClCompile Include="TShellExtensionClient.cpp">
       <Filter>Source Files\Shell Extension</Filter>
     </ClCompile>
-    <ClCompile Include="..\chext\chext_i.c">
-      <Filter>Generated Files</Filter>
-    </ClCompile>
     <ClCompile Include="TProgressCtrlEx.cpp">
       <Filter>Source Files\GUI\Controls</Filter>
     </ClCompile>
@@ -385,9 +382,6 @@
     <ClCompile Include="WindowsVersion.cpp">
       <Filter>Source Files\Tools</Filter>
     </ClCompile>
-    <ClCompile Include="TRegistry.cpp">
-      <Filter>Source Files\Tools</Filter>
-    </ClCompile>
     <ClCompile Include="AsyncHttpFile.cpp">
       <Filter>Source Files\Tools</Filter>
     </ClCompile>
@@ -439,6 +433,9 @@
     <ClCompile Include="FeedbackReplaceDlg.cpp">
       <Filter>Source Files\GUI\Dialogs\Feedback</Filter>
     </ClCompile>
+    <ClCompile Include="..\common\TRegistry.cpp">
+      <Filter>Source Files\Shared</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <None Include="res\ch.rc2">
Index: src/chext/ClassFactory.cpp
===================================================================
diff -u
--- src/chext/ClassFactory.cpp	(revision 0)
+++ src/chext/ClassFactory.cpp	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -0,0 +1,74 @@
+// ============================================================================
+//  Copyright (C) 2001-2019 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program 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 General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#include "stdafx.h"
+#include "ClassFactory.h"
+#include "Logger.h"
+
+extern LONG g_DllRefCount;
+
+ClassFactory::ClassFactory() :
+	m_spLog(GetLogger(L"ClassFactory"))
+{
+	InterlockedIncrement(&g_DllRefCount);
+	LOG_DEBUG(m_spLog) << L"Constructing ClassFactory";
+}
+
+ClassFactory::~ClassFactory()
+{
+	InterlockedDecrement(&g_DllRefCount);
+}
+
+STDMETHODIMP ClassFactory::QueryInterface(REFIID riid, LPVOID *ppReturn)
+{
+	if (!ppReturn)
+		return E_POINTER;
+
+	*ppReturn = nullptr;
+
+	if (IsEqualIID(riid, IID_IUnknown))
+		*ppReturn = this;
+	else if (IsEqualIID(riid, IID_IClassFactory))
+		*ppReturn = (IClassFactory*)this;
+	else
+		return E_NOINTERFACE;
+
+	AddRef();
+	return S_OK;
+}
+
+STDMETHODIMP_(ULONG) ClassFactory::AddRef()
+{
+	return InterlockedIncrement(&m_ulRefCnt);
+}
+
+STDMETHODIMP_(ULONG) ClassFactory::Release()
+{
+	ULONG ulNewValue = InterlockedDecrement(&m_ulRefCnt);
+	if(ulNewValue)
+		return ulNewValue;
+
+	delete this;
+
+	return 0UL;
+}
+
+STDMETHODIMP ClassFactory::LockServer(BOOL)
+{
+	return E_NOTIMPL;
+}
Index: src/chext/ClassFactory.h
===================================================================
diff -u
--- src/chext/ClassFactory.h	(revision 0)
+++ src/chext/ClassFactory.h	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -0,0 +1,40 @@
+// ============================================================================
+//  Copyright (C) 2001-2019 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program 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 General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#pragma once
+
+#include "../liblogger/TLogger.h"
+
+class ClassFactory : public IClassFactory
+{
+public:
+	ClassFactory();
+	virtual ~ClassFactory();
+
+	//IUnknown methods
+	STDMETHODIMP QueryInterface(REFIID, LPVOID*) override;
+	STDMETHODIMP_(DWORD) AddRef() override;
+	STDMETHODIMP_(DWORD) Release() override;
+
+	//IClassFactory methods
+	STDMETHODIMP LockServer(BOOL) override;
+
+private:
+	DWORD m_ulRefCnt = 0;
+	logger::TLoggerPtr m_spLog;
+};
Index: src/chext/DllRegistration.cpp
===================================================================
diff -u
--- src/chext/DllRegistration.cpp	(revision 0)
+++ src/chext/DllRegistration.cpp	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -0,0 +1,214 @@
+// ============================================================================
+//  Copyright (C) 2001-2019 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program 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 General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#include "stdafx.h"
+#include "DllRegistration.h"
+#include "guids.h"
+#include "../common/TRegistry.h"
+
+namespace
+{
+	std::wstring CLSID2String(REFCLSID rclsid)
+	{
+		const size_t stBufferSize = 64;
+		wchar_t szBuffer[stBufferSize] = {};
+		_sntprintf_s(szBuffer, stBufferSize, _TRUNCATE, L"{%08lX-%04hX-%04hX-%02hX%02hX-%02hX%02hX%02hX%02hX%02hX%02hX}",
+			rclsid.Data1, rclsid.Data2, rclsid.Data3,
+			rclsid.Data4[0], rclsid.Data4[1], rclsid.Data4[2], rclsid.Data4[3],
+			rclsid.Data4[4], rclsid.Data4[5], rclsid.Data4[6], rclsid.Data4[7]);
+
+		return szBuffer;
+	}
+
+	std::wstring GetModulePath(HMODULE hModule)
+	{
+		wchar_t szPath[MAX_PATH + 2] = {};
+		DWORD dwSize = ::GetModuleFileName(hModule, szPath, MAX_PATH + 1);
+		if (dwSize != 0 && dwSize < MAX_PATH)
+		{
+			szPath[dwSize] = L'\0';
+			return szPath;
+		}
+
+		return std::wstring();
+	}
+
+	void CreateSingleValue(HKEY key, const wchar_t* pszKey, const wchar_t* pszValueKey, const wchar_t* pszValue)
+	{
+		TRegistry reg(key, pszKey, false);
+		reg.SetString(pszValueKey, pszValue);
+	}
+
+	void DeleteSingleValue(HKEY key, const wchar_t* pszKey, const wchar_t* pszValueKey)
+	{
+		TRegistry reg(key, pszKey, false);
+		reg.DeleteValue(pszValueKey);
+	}
+
+	void CreateNodeWithDefaultValue(HKEY key, const wchar_t* pszKey, const wchar_t* pszSubKey, const wchar_t* pszValue)
+	{
+		TRegistry reg(key, pszKey, false);
+		reg.CreateSubKey(pszSubKey);
+
+		std::wstring strNewKey = pszKey;
+		strNewKey += L'\\';
+		strNewKey += pszSubKey;
+
+		reg.ReOpen(key, strNewKey.c_str(), false);
+		reg.SetString(L"", pszValue);
+	}
+
+	void DeleteSingleNode(HKEY key, const wchar_t* pszKey, const wchar_t* pszValueKey)
+	{
+		TRegistry reg(key, pszKey, false);
+		reg.DeleteSubKey(pszValueKey);
+	}
+
+	void CreateNodes(HKEY key, const wchar_t* pszKey, std::wstring strSubKey)
+	{
+		TRegistry reg(key, pszKey, false);
+		reg.CreateSubKey(strSubKey.c_str());
+	}
+}
+
+DllRegistration::DllRegistration(HMODULE hModule)
+{
+	if (hModule == nullptr)
+		throw std::invalid_argument("hModule");
+
+	m_strModulePath = GetModulePath(hModule);
+	if (m_strModulePath.empty())
+		throw std::runtime_error("Cannot retrieve module path");
+}
+
+void DllRegistration::RegisterAll()
+{
+	RemoveLegacyEntries();
+
+	RegisterShellExtensionControl();
+	RegisterMenuExt();
+	RegisterDropMenuExt();
+}
+
+void DllRegistration::UnregisterAll()
+{
+	RemoveLegacyEntries();
+
+	UnregisterShellExtensionControl();
+	UnregisterMenuExt();
+	UnregisterDropMenuExt();
+}
+
+void DllRegistration::RegisterMenuExt()
+{
+	std::wstring strClsID = CLSID2String(CLSID_MenuExt);
+
+	RegisterClass(strClsID, L"MenuExt Class", L"Apartment");
+
+	CreateNodeWithDefaultValue(HKEY_CLASSES_ROOT, L"Directory\\Shellex\\ContextMenuHandlers", L"chext", strClsID.c_str());
+	CreateNodeWithDefaultValue(HKEY_CLASSES_ROOT, L"Directory\\Background\\Shellex\\ContextMenuHandlers", L"chext", strClsID.c_str());
+	CreateNodeWithDefaultValue(HKEY_CLASSES_ROOT, L"Folder\\Shellex\\ContextMenuHandlers", L"chext", strClsID.c_str());
+	CreateNodeWithDefaultValue(HKEY_CLASSES_ROOT, L"*\\Shellex\\ContextMenuHandlers", L"chext", strClsID.c_str());
+
+	CreateSingleValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", strClsID.c_str(), L"chext");
+}
+
+void DllRegistration::RegisterDropMenuExt()
+{
+	std::wstring strClsID = CLSID2String(CLSID_DropMenuExt);
+	RegisterClass(strClsID, L"DropMenuExt Class", L"Apartment");
+
+	CreateNodes(HKEY_CLASSES_ROOT, L"CLSID", strClsID + L"\\shellex\\MayChangeDefaultMenu");
+
+	CreateNodeWithDefaultValue(HKEY_CLASSES_ROOT, L"Directory\\Shellex\\DragDropHandlers", L"chext", strClsID.c_str());
+	CreateNodeWithDefaultValue(HKEY_CLASSES_ROOT, L"Drive\\Shellex\\DragDropHandlers", L"chext", strClsID.c_str());
+	CreateNodeWithDefaultValue(HKEY_CLASSES_ROOT, L"Folder\\Shellex\\DragDropHandlers", L"chext", strClsID.c_str());
+
+	CreateSingleValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", strClsID.c_str(), L"chext");
+}
+
+void DllRegistration::RegisterShellExtensionControl()
+{
+	RegisterClass(CLSID2String(CLSID_CShellExtControl), L"ShellExtControl Class", L"Both");
+}
+
+void DllRegistration::UnregisterMenuExt()
+{
+	std::wstring strClsID = CLSID2String(CLSID_MenuExt);
+
+	UnregisterClass(strClsID);
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"Directory\\Shellex\\ContextMenuHandlers", L"chext");
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"Directory\\Background\\Shellex\\ContextMenuHandlers", L"chext");
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"Folder\\Shellex\\ContextMenuHandlers", L"chext");
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"*\\Shellex\\ContextMenuHandlers", L"chext");
+
+	DeleteSingleValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", strClsID.c_str());
+}
+
+void DllRegistration::UnregisterDropMenuExt()
+{
+	std::wstring strClsID = CLSID2String(CLSID_DropMenuExt);
+
+	UnregisterClass(strClsID);
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"Directory\\Shellex\\DragDropHandlers", L"chext");
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"Drive\\Shellex\\DragDropHandlers", L"chext");
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"Folder\\Shellex\\DragDropHandlers", L"chext");
+
+	DeleteSingleValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", strClsID.c_str());
+}
+
+void DllRegistration::UnregisterShellExtensionControl()
+{
+	UnregisterClass(CLSID2String(CLSID_CShellExtControl));
+}
+
+void DllRegistration::RemoveLegacyEntries()
+{
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"", L"chext.MenuExt");
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"", L"chext.MenuExt.1");
+
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"", L"chext.DropMenuExt");
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"", L"chext.DropMenuExt.1");
+
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"", L"chext.ShellExtControl");
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"", L"chext.ShellExtControl.1");
+
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"Interface", L"{317E503A-9D2F-4F42-995E-D314CB9D89B0}");
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"TypeLib", L"{68FAFC14-8EB8-4DA1-90EB-6B3D22010505}");
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"AppID", L"{9D4C4C5F-EE90-4a6b-9245-244C369E4FAE}");
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"AppID", L"chext.dll");
+}
+
+void DllRegistration::RegisterClass(std::wstring strClsId, std::wstring strClassDescription, std::wstring strThreadingModel)
+{
+	std::wstring strGuidNode = L"CLSID\\" + strClsId;
+	std::wstring strInprocServerNode = strGuidNode + L"\\InprocServer32";
+
+	CreateNodes(HKEY_CLASSES_ROOT, L"CLSID", strClsId + L"\\InprocServer32");
+
+	CreateSingleValue(HKEY_CLASSES_ROOT, strGuidNode.c_str(), L"", strClassDescription.c_str());
+
+	TRegistry reg(HKEY_CLASSES_ROOT, strInprocServerNode.c_str(), false);
+	reg.SetString(L"", m_strModulePath.c_str());
+	reg.SetString(L"ThreadingModel", strThreadingModel.c_str());
+}
+
+void DllRegistration::UnregisterClass(std::wstring strClsId)
+{
+	DeleteSingleNode(HKEY_CLASSES_ROOT, L"CLSID", strClsId.c_str());
+}
Index: src/chext/DllRegistration.h
===================================================================
diff -u
--- src/chext/DllRegistration.h	(revision 0)
+++ src/chext/DllRegistration.h	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -0,0 +1,46 @@
+// ============================================================================
+//  Copyright (C) 2001-2019 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program 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 General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+
+#pragma once
+
+class DllRegistration
+{
+public:
+	DllRegistration(HMODULE hModule);
+
+	void RegisterAll();
+	void UnregisterAll();
+
+	void RegisterMenuExt();
+	void RegisterDropMenuExt();
+	void RegisterShellExtensionControl();
+
+	void UnregisterMenuExt();
+	void UnregisterDropMenuExt();
+	void UnregisterShellExtensionControl();
+
+	void RemoveLegacyEntries();
+
+private:
+	void RegisterClass(std::wstring strClsId, std::wstring strClassDescription, std::wstring strThreadingModel);
+	void UnregisterClass(std::wstring strClsId);
+
+private:
+	std::wstring m_strModulePath;
+};
Index: src/chext/DropMenuExt.cpp
===================================================================
diff -u -r9ddf8fdd5f641491dd30c49eb90f8f740314b6af -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/chext/DropMenuExt.cpp	(.../DropMenuExt.cpp)	(revision 9ddf8fdd5f641491dd30c49eb90f8f740314b6af)
+++ src/chext/DropMenuExt.cpp	(.../DropMenuExt.cpp)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -17,7 +17,6 @@
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
 #include "stdafx.h"
-#include "chext.h"
 #include "DropMenuExt.h"
 #include "../Common/ipcstructs.h"
 #include "../libchengine/TTaskDefinition.h"
@@ -48,6 +47,44 @@
 	}
 }
 
+STDMETHODIMP CDropMenuExt::QueryInterface(REFIID riid, LPVOID FAR *ppvObject)
+{
+	if (!ppvObject)
+		return E_POINTER;
+
+	*ppvObject = nullptr;
+
+	if (IsEqualIID(riid, IID_IShellExtInit) || IsEqualIID(riid, IID_IUnknown))
+		*ppvObject = static_cast<IShellExtInit*>(this);
+	else if (IsEqualIID(riid, IID_IContextMenu))
+		*ppvObject = static_cast<IContextMenu*>(this);
+	else if (IsEqualIID(riid, IID_IContextMenu2))
+		*ppvObject = static_cast<IContextMenu2*>(this);
+	else if (IsEqualIID(riid, IID_IContextMenu3))
+		*ppvObject = static_cast<IContextMenu3*>(this);
+	else
+		return E_NOINTERFACE;
+
+	AddRef();
+	return S_OK;
+}
+
+STDMETHODIMP_(ULONG) CDropMenuExt::AddRef()
+{
+	return InterlockedIncrement(&m_ulRefCnt);
+}
+
+STDMETHODIMP_(ULONG) CDropMenuExt::Release()
+{
+	ULONG ulNewValue = InterlockedDecrement(&m_ulRefCnt);
+	if (ulNewValue)
+		return ulNewValue;
+
+	delete this;
+
+	return 0UL;
+}
+
 STDMETHODIMP CDropMenuExt::Initialize(LPCITEMIDLIST pidlFolder, IDataObject* piDataObject, HKEY /*hkeyProgID*/)
 {
 	try
Index: src/chext/DropMenuExt.h
===================================================================
diff -u -rb26ced3298e3e7e51d91f3ac70b56746786da83b -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/chext/DropMenuExt.h	(.../DropMenuExt.h)	(revision b26ced3298e3e7e51d91f3ac70b56746786da83b)
+++ src/chext/DropMenuExt.h	(.../DropMenuExt.h)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -24,30 +24,23 @@
 #include "../common/TShellExtMenuConfig.h"
 #include "TShellExtData.h"
 #include "../liblogger/TLogger.h"
+#include "ShellExtControl.h"
 
 /////////////////////////////////////////////////////////////////////////////
 // CDropMenuExt
-class ATL_NO_VTABLE CDropMenuExt : 
-	public CComObjectRootEx<CComSingleThreadModel>,
-	public CComCoClass<CDropMenuExt, &CLSID_DropMenuExt>,
+class CDropMenuExt :
 	public IShellExtInit,
 	public IContextMenu3
 {
 public:
 	CDropMenuExt();
 	~CDropMenuExt();
 
-DECLARE_REGISTRY_RESOURCEID(IDR_DROPMENUEXT)
-DECLARE_NOT_AGGREGATABLE(CDropMenuExt)
-
-DECLARE_PROTECT_FINAL_CONSTRUCT()
-
-BEGIN_COM_MAP(CDropMenuExt)
-	COM_INTERFACE_ENTRY(IShellExtInit)
-	COM_INTERFACE_ENTRY(IContextMenu)
-END_COM_MAP()
-
 public:
+	STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *) override;
+	STDMETHODIMP_(ULONG) AddRef() override;
+	STDMETHODIMP_(ULONG) Release() override;
+
 	STDMETHOD(InvokeCommand) (LPCMINVOKECOMMANDINFO lpici);
 	STDMETHOD(Initialize)(LPCITEMIDLIST pidlFolder, IDataObject* piDataObject, HKEY /*hkeyProgID*/);
 	STDMETHOD(GetCommandString)(UINT_PTR idCmd, UINT uFlags, UINT* /*pwReserved*/, LPSTR pszName, UINT cchMax);
@@ -57,6 +50,8 @@
 	STDMETHOD(HandleMenuMsg2)(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plResult);
 
 protected:
+	volatile ULONG m_ulRefCnt = 0;
+
 	IShellExtControl* m_piShellExtControl;
 
 	TShellExtData m_tShellExtData;
Fisheye: Tag 6609ba39811176f4803f0556db3da30e9e457b9d refers to a dead (removed) revision in file `src/chext/DropMenuExt.htm'.
Fisheye: No comparison available.  Pass `N' to diff?
Fisheye: Tag 6609ba39811176f4803f0556db3da30e9e457b9d refers to a dead (removed) revision in file `src/chext/DropMenuExt.rgs'.
Fisheye: No comparison available.  Pass `N' to diff?
Index: src/chext/DropMenuExtClassFactory.cpp
===================================================================
diff -u
--- src/chext/DropMenuExtClassFactory.cpp	(revision 0)
+++ src/chext/DropMenuExtClassFactory.cpp	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -0,0 +1,41 @@
+// ============================================================================
+//  Copyright (C) 2001-2019 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program 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 General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#include "stdafx.h"
+#include "DropMenuExtClassFactory.h"
+#include <new.h>
+#include "DropMenuExt.h"
+
+STDMETHODIMP DropMenuExtClassFactory::CreateInstance(LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject)
+{
+	if (!ppObject)
+		return E_POINTER;
+
+	*ppObject = nullptr;
+	if (pUnknown != nullptr)
+		return CLASS_E_NOAGGREGATION;
+
+	auto pMenuExt = new (std::nothrow) CDropMenuExt();
+	if (!pMenuExt)
+		return E_OUTOFMEMORY;
+
+	const HRESULT hr = pMenuExt->QueryInterface(riid, ppObject);
+	if (FAILED(hr))
+		delete pMenuExt;
+	return hr;
+}
Fisheye: tag b79aca0d66b1084f230022efe39cc89307482e6d is not in file src/chext/DropMenuExtClassFactory.h
Index: src/chext/IShellExtControl.h
===================================================================
diff -u
--- src/chext/IShellExtControl.h	(revision 0)
+++ src/chext/IShellExtControl.h	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -0,0 +1,35 @@
+// ============================================================================
+//  Copyright (C) 2001-2019 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program 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 General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#pragma once
+
+#include <ObjBase.h>
+
+enum EShellExtFlags
+{
+	eShellExt_None = 0,
+	eShellExt_Enabled = 1
+};
+
+interface IShellExtControl : public IUnknown
+{
+public:
+	virtual HRESULT STDMETHODCALLTYPE GetVersion(/* [out] */ LONG *plVersion, /* [out] */ BSTR *pbstrVersion) = 0;
+	virtual HRESULT STDMETHODCALLTYPE SetFlags(LONG lFlags, LONG lMask) = 0;
+	virtual HRESULT STDMETHODCALLTYPE GetFlags(LONG *plFlags) = 0;
+};
Index: src/chext/MenuExt.cpp
===================================================================
diff -u -rd3371a00eafb40afa4251953591ff1004343e1be -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/chext/MenuExt.cpp	(.../MenuExt.cpp)	(revision d3371a00eafb40afa4251953591ff1004343e1be)
+++ src/chext/MenuExt.cpp	(.../MenuExt.cpp)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -17,7 +17,6 @@
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
 #include "stdafx.h"
-#include "chext.h"
 #include "MenuExt.h"
 #include "../common/ipcstructs.h"
 #include "stdio.h"
@@ -49,6 +48,44 @@
 	}
 }
 
+STDMETHODIMP CMenuExt::QueryInterface(REFIID riid, LPVOID FAR *ppvObject)
+{
+	if (!ppvObject)
+		return E_POINTER;
+
+	*ppvObject = nullptr;
+
+	if (IsEqualIID(riid, IID_IShellExtInit) || IsEqualIID(riid, IID_IUnknown))
+		*ppvObject = static_cast<IShellExtInit*>(this);
+	else if (IsEqualIID(riid, IID_IContextMenu))
+		*ppvObject = static_cast<IContextMenu*>(this);
+	else if (IsEqualIID(riid, IID_IContextMenu2))
+		*ppvObject = static_cast<IContextMenu2*>(this);
+	else if (IsEqualIID(riid, IID_IContextMenu3))
+		*ppvObject = static_cast<IContextMenu3*>(this);
+	else
+		return E_NOINTERFACE;
+
+	AddRef();
+	return S_OK;
+}
+
+STDMETHODIMP_(ULONG) CMenuExt::AddRef()
+{
+	return InterlockedIncrement(&m_ulRefCnt);
+}
+
+STDMETHODIMP_(ULONG) CMenuExt::Release()
+{
+	ULONG ulNewValue = InterlockedDecrement(&m_ulRefCnt);
+	if (ulNewValue)
+		return ulNewValue;
+
+	delete this;
+
+	return 0UL;
+}
+
 STDMETHODIMP CMenuExt::Initialize(LPCITEMIDLIST pidlFolder, IDataObject* piDataObject, HKEY /*hkeyProgID*/)
 {
 	try
Index: src/chext/MenuExt.h
===================================================================
diff -u -rb26ced3298e3e7e51d91f3ac70b56746786da83b -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/chext/MenuExt.h	(.../MenuExt.h)	(revision b26ced3298e3e7e51d91f3ac70b56746786da83b)
+++ src/chext/MenuExt.h	(.../MenuExt.h)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -24,35 +24,26 @@
 #include "../common/TShellExtMenuConfig.h"
 #include "TShellExtData.h"
 #include "../liblogger/TLogger.h"
+#include "ShellExtControl.h"
 
 class TShellMenuItem;
 
 /////////////////////////////////////////////////////////////////////////////
 // CMenuExt
-class ATL_NO_VTABLE CMenuExt : 
-	public CComObjectRootEx<CComSingleThreadModel>,
-	public CComCoClass<CMenuExt, &CLSID_MenuExt>,
+class CMenuExt :
 	public IShellExtInit,
 	public IContextMenu3
 {
 public:
 	CMenuExt();
 	~CMenuExt();
 
-DECLARE_REGISTRY_RESOURCEID(IDR_MENUEXT)
-DECLARE_NOT_AGGREGATABLE(CMenuExt)
-
-DECLARE_PROTECT_FINAL_CONSTRUCT()
-
-BEGIN_COM_MAP(CMenuExt)
-	COM_INTERFACE_ENTRY(IShellExtInit)
-	COM_INTERFACE_ENTRY(IContextMenu)
-	COM_INTERFACE_ENTRY(IContextMenu2)
-	COM_INTERFACE_ENTRY(IContextMenu3)
-END_COM_MAP()
-
 // IMenuExt
 public:
+	STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *) override;
+	STDMETHODIMP_(ULONG) AddRef() override;
+	STDMETHODIMP_(ULONG) Release() override;
+
 	STDMETHOD(Initialize)(LPCITEMIDLIST pidlFolder, IDataObject* piDataObject, HKEY /*hkeyProgID*/);
 	STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO lpici);
 	STDMETHOD(GetCommandString)(UINT_PTR idCmd, UINT uFlags, UINT* /*pwReserved*/, LPSTR pszName, UINT cchMax);
@@ -64,6 +55,7 @@
 	HRESULT DrawMenuItem(LPDRAWITEMSTRUCT lpdis);
 
 private:
+	volatile ULONG m_ulRefCnt = 0;
 	TShellExtData m_tShellExtData;
 
 	TShellExtMenuConfig m_tShellExtMenuConfig;
Fisheye: Tag 6609ba39811176f4803f0556db3da30e9e457b9d refers to a dead (removed) revision in file `src/chext/MenuExt.htm'.
Fisheye: No comparison available.  Pass `N' to diff?
Fisheye: Tag 6609ba39811176f4803f0556db3da30e9e457b9d refers to a dead (removed) revision in file `src/chext/MenuExt.rgs'.
Fisheye: No comparison available.  Pass `N' to diff?
Index: src/chext/MenuExtClassFactory.cpp
===================================================================
diff -u
--- src/chext/MenuExtClassFactory.cpp	(revision 0)
+++ src/chext/MenuExtClassFactory.cpp	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -0,0 +1,41 @@
+// ============================================================================
+//  Copyright (C) 2001-2019 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program 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 General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#include "stdafx.h"
+#include "MenuExtClassFactory.h"
+#include "MenuExt.h"
+#include <new.h>
+
+STDMETHODIMP MenuExtClassFactory::CreateInstance(LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject)
+{
+	if (!ppObject)
+		return E_POINTER;
+
+	*ppObject = nullptr;
+	if (pUnknown != nullptr)
+		return CLASS_E_NOAGGREGATION;
+
+	auto pMenuExt = new (std::nothrow) CMenuExt();
+	if (!pMenuExt)
+		return E_OUTOFMEMORY;
+
+	const HRESULT hr = pMenuExt->QueryInterface(riid, ppObject);
+	if (FAILED(hr))
+		delete pMenuExt;
+	return hr;
+}
Fisheye: tag b79aca0d66b1084f230022efe39cc89307482e6d is not in file src/chext/MenuExtClassFactory.h
Index: src/chext/ShellExtControl.cpp
===================================================================
diff -u -rd9527df01ee91b35d9a5fdccb80ded25a9c8265f -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/chext/ShellExtControl.cpp	(.../ShellExtControl.cpp)	(revision d9527df01ee91b35d9a5fdccb80ded25a9c8265f)
+++ src/chext/ShellExtControl.cpp	(.../ShellExtControl.cpp)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -17,17 +17,14 @@
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
 #include "stdafx.h"
-#include "chext.h"
 #include <comutil.h>
 #include "ShellExtControl.h"
 #include "../common/version.h"
 #include "Logger.h"
 #include "../libchcore/TIpcMutexLock.h"
 
 CShellExtControl::CShellExtControl() :
-	m_hMemory(nullptr),
 	m_mutex(L"CHShellExtControlDataMutex"),
-	m_pShellExtData(nullptr),
 	m_spLog(GetLogger(L"ShellExtControl"))
 {
 	LOG_DEBUG(m_spLog) << L"Constructing CShellExtControl";
@@ -44,6 +41,40 @@
 	}
 }
 
+STDMETHODIMP CShellExtControl::QueryInterface(REFIID riid, LPVOID FAR *ppvObject)
+{
+	if (!ppvObject)
+		return E_POINTER;
+
+	*ppvObject = nullptr;
+
+	if (IsEqualIID(riid, IID_IUnknown))
+		*ppvObject = static_cast<IUnknown*>(this);
+	else if (IsEqualIID(riid, IID_IShellExtControl))
+		*ppvObject = static_cast<IShellExtControl*>(this);
+	else
+		return E_NOINTERFACE;
+
+	AddRef();
+	return S_OK;
+}
+
+STDMETHODIMP_(ULONG) CShellExtControl::AddRef()
+{
+	return InterlockedIncrement(&m_ulRefCnt);
+}
+
+STDMETHODIMP_(ULONG) CShellExtControl::Release()
+{
+	ULONG ulNewValue = InterlockedDecrement(&m_ulRefCnt);
+	if (ulNewValue)
+		return ulNewValue;
+
+	delete this;
+
+	return 0UL;
+}
+
 STDMETHODIMP CShellExtControl::GetVersion(LONG* plVersion, BSTR* pbstrVersion)
 {
 	try
Index: src/chext/ShellExtControl.h
===================================================================
diff -u -r134983cab6122e3fff73994a6f9c417aaeab3bc2 -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/chext/ShellExtControl.h	(.../ShellExtControl.h)	(revision 134983cab6122e3fff73994a6f9c417aaeab3bc2)
+++ src/chext/ShellExtControl.h	(.../ShellExtControl.h)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -20,47 +20,40 @@
 #define __SHELLEXTCONTROL_H_
 
 #include "resource.h"       // main symbols
+#include "guids.h"
 #include "../liblogger/TLogger.h"
 #include "../libchcore/TIpcMutex.h"
 #include "../libchcore/TSharedMemory.h"
+#include "IShellExtControl.h"
 
-/////////////////////////////////////////////////////////////////////////////
-// CDropMenuExt
-class ATL_NO_VTABLE CShellExtControl : 
-	public CComObjectRootEx<CComMultiThreadModel>,
-	public CComCoClass<CShellExtControl, &CLSID_CShellExtControl>,
-	public IDispatchImpl<IShellExtControl, &IID_IShellExtControl, &LIBID_CHEXTLib>
+class CShellExtControl : public IShellExtControl
 {
 public:
 	CShellExtControl();
 	~CShellExtControl();
 
+	STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *) override;
+	STDMETHODIMP_(ULONG) AddRef() override;
+	STDMETHODIMP_(ULONG) Release() override;
+
 	STDMETHOD(GetVersion)(LONG* plVersion, BSTR* pbstrVersion);
 	STDMETHOD(SetFlags)(LONG lFlags, LONG lMask);
 	STDMETHOD(GetFlags)(LONG* plFlags);
 
-DECLARE_REGISTRY_RESOURCEID(IDR_SHELLEXTCONTROL)
-
-DECLARE_PROTECT_FINAL_CONSTRUCT()
-
-BEGIN_COM_MAP(CShellExtControl)
-	COM_INTERFACE_ENTRY(IUnknown)
-	COM_INTERFACE_ENTRY(IShellExtControl)
-END_COM_MAP()
-
 private:
 	HRESULT Initialize();
 
 private:
+	volatile ULONG m_ulRefCnt = 0;
+
 	HANDLE m_hMemory = nullptr;
 	chcore::TIpcMutex m_mutex;
 
 	struct SHELLEXT_DATA
 	{
 		long m_lFlags = 0;
-	} *m_pShellExtData;
+	} *m_pShellExtData = nullptr;
 
-	CComAutoCriticalSection m_lock;
 	logger::TLoggerPtr m_spLog;
 	chcore::TSharedMemory m_shmConfiguration;
 	bool m_bInitialized = false;
Fisheye: Tag 6609ba39811176f4803f0556db3da30e9e457b9d refers to a dead (removed) revision in file `src/chext/ShellExtControl.rgs'.
Fisheye: No comparison available.  Pass `N' to diff?
Index: src/chext/ShellExtControlClassFactory.cpp
===================================================================
diff -u
--- src/chext/ShellExtControlClassFactory.cpp	(revision 0)
+++ src/chext/ShellExtControlClassFactory.cpp	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -0,0 +1,41 @@
+// ============================================================================
+//  Copyright (C) 2001-2019 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program 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 General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#include "stdafx.h"
+#include "ShellExtControlClassFactory.h"
+#include "ShellExtControl.h"
+#include <new.h>
+
+STDMETHODIMP ShellExtControlClassFactory::CreateInstance(LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject)
+{
+	if (!ppObject)
+		return E_POINTER;
+
+	*ppObject = nullptr;
+	if (pUnknown != nullptr)
+		return CLASS_E_NOAGGREGATION;
+
+	auto pShellExtControl = new (std::nothrow) CShellExtControl();
+	if (!pShellExtControl)
+		return E_OUTOFMEMORY;
+
+	const HRESULT hr = pShellExtControl->QueryInterface(riid, ppObject);
+	if (FAILED(hr))
+		delete pShellExtControl;
+	return hr;
+}
Fisheye: tag b79aca0d66b1084f230022efe39cc89307482e6d is not in file src/chext/ShellExtControlClassFactory.h
Fisheye: Tag 6609ba39811176f4803f0556db3da30e9e457b9d refers to a dead (removed) revision in file `src/chext/dllmain.h'.
Fisheye: No comparison available.  Pass `N' to diff?
Index: src/chext/ShellExtensionVerifier.h
===================================================================
diff -u -rd9527df01ee91b35d9a5fdccb80ded25a9c8265f -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/chext/ShellExtensionVerifier.h	(.../ShellExtensionVerifier.h)	(revision d9527df01ee91b35d9a5fdccb80ded25a9c8265f)
+++ src/chext/ShellExtensionVerifier.h	(.../ShellExtensionVerifier.h)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -19,7 +19,7 @@
 #ifndef __SHELLEXTENSIONVERIFIER_H__
 #define __SHELLEXTENSIONVERIFIER_H__
 
-#include "chext.h"
+#include "IShellExtControl.h"
 
 class TShellExtMenuConfig;
 
Index: src/chext/StdAfx.cpp
===================================================================
diff -u -rd5c3edd0d167db9b5d47d04248820fda49499a5e -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/chext/StdAfx.cpp	(.../StdAfx.cpp)	(revision d5c3edd0d167db9b5d47d04248820fda49499a5e)
+++ src/chext/StdAfx.cpp	(.../StdAfx.cpp)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -17,10 +17,3 @@
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
 #include "stdafx.h"
-
-#ifdef _ATL_STATIC_REGISTRY
-#include <statreg.h>
-//#include <statreg.cpp>
-#endif
-
-//#include <atlimpl.cpp>
Index: src/chext/StdAfx.h
===================================================================
diff -u -r2f696d06139af4d0fab14dd1613507b66f5169cb -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/chext/StdAfx.h	(.../StdAfx.h)	(revision 2f696d06139af4d0fab14dd1613507b66f5169cb)
+++ src/chext/StdAfx.h	(.../StdAfx.h)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -24,25 +24,14 @@
 
 #include "../common/targetver.h"
 
-#define _ATL_APARTMENT_THREADED
+#include <tchar.h>
 
-#include <comsvcs.h>
-
 #include "resource.h"
-#include <atlbase.h>
-#include <atlcom.h>
-#include <atlctl.h>
 #include <ShlObj.h>
-#include <comdef.h>
 
 #include <vector>
 #include <set>
 
-#pragma warning(push)
-#pragma warning(disable: 4985)
-
 #include <boost/thread/shared_mutex.hpp>
 
-#pragma warning(pop)
-
 #endif
Index: src/chext/chext.cpp
===================================================================
diff -u -re2054db3fa2be3652ca376a318d49dbaba8539ed -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/chext/chext.cpp	(.../chext.cpp)	(revision e2054db3fa2be3652ca376a318d49dbaba8539ed)
+++ src/chext/chext.cpp	(.../chext.cpp)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -16,77 +16,106 @@
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
-// Note: Proxy/Stub Information
-//      To build a separate proxy/stub DLL, 
-//      run nmake -f CopyHandlerShellExtps.mk in the project directory.
-
 #include "stdafx.h"
-#include "chext.h"
-#include "dllmain.h"
 #include "Logger.h"
+#include "guids.h"
+#include "MenuExtClassFactory.h"
+#include "DropMenuExtClassFactory.h"
+#include "ShellExtControlClassFactory.h"
+#include "../common/TRegistry.h"
+#include "DllRegistration.h"
 
+LONG g_DllRefCount = 0; // Reference count of this DLL.
+extern HINSTANCE g_hInstance;
+
+namespace
+{
+	template<class T>
+	HRESULT CreateFactory(REFIID riid, LPVOID* ppv)
+	{
+		auto classFactory = new (std::nothrow) T;
+		if (!classFactory)
+			return E_OUTOFMEMORY;
+
+		HRESULT hResult = classFactory->QueryInterface(riid, ppv);
+		if (hResult != S_OK)
+			delete classFactory;
+
+		return hResult;
+	}
+}
+
 /////////////////////////////////////////////////////////////////////////////
 // Used to determine whether the DLL can be unloaded by OLE
 
 STDAPI DllCanUnloadNow()
 {
-	HRESULT hResult = _AtlModule.DllCanUnloadNow();
-
-	return hResult;
+	return (g_DllRefCount == 0 ? S_OK : S_FALSE);
 }
 
 /////////////////////////////////////////////////////////////////////////////
 // Returns a class factory to create an object of the requested type
 
 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
 {
-	HRESULT hResult = _AtlModule.DllGetClassObject(rclsid, riid, ppv);
+	if (!ppv)
+		return E_POINTER;
 
-	return hResult;
+	*ppv = nullptr;
+
+	try
+	{
+		if (IsEqualIID(rclsid, CLSID_MenuExt))
+			return CreateFactory<MenuExtClassFactory>(riid, ppv);
+		else if (IsEqualIID(rclsid, CLSID_DropMenuExt))
+			return CreateFactory<DropMenuExtClassFactory>(riid, ppv);
+		else if (IsEqualIID(rclsid, CLSID_CShellExtControl))
+			return CreateFactory<ShellExtControlClassFactory>(riid, ppv);
+	}
+	catch (const std::exception& e)
+	{
+		OutputDebugStringA(e.what());
+		return E_FAIL;
+	}
+
+	return CLASS_E_CLASSNOTAVAILABLE;
 }
 
 /////////////////////////////////////////////////////////////////////////////
 // DllRegisterServer - Adds entries to the system registry
 
 STDAPI DllRegisterServer()
 {
-	// registers object, typelib and all interfaces in typelib
-	HRESULT hResult = _AtlModule.DllRegisterServer();
+	try
+	{
+		DllRegistration regDll(g_hInstance);
 
-	return hResult;
+		regDll.RegisterAll();
+	}
+	catch (const std::exception& e)
+	{
+		OutputDebugStringA(e.what());
+		return E_FAIL;
+	}
+
+	return S_OK;
 }
 
 /////////////////////////////////////////////////////////////////////////////
 // DllUnregisterServer - Removes entries from the system registry
 
 STDAPI DllUnregisterServer()
 {
-	HRESULT hResult = _AtlModule.DllUnregisterServer();
-
-	return hResult;
-}
-
-// DllInstall - Adds/Removes entries to the system registry per user
-//              per machine.	
-STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine)
-{
-	static const wchar_t szUserSwitch[] = _T("user");
-
-	if (pszCmdLine != nullptr)
+	try
 	{
-		if (_wcsnicmp(pszCmdLine, szUserSwitch, _countof(szUserSwitch)) == 0)
-			AtlSetPerUserRegistration(true);
+		DllRegistration regDll(g_hInstance);
+		regDll.UnregisterAll();
 	}
-
-	HRESULT hResult = E_FAIL;
-	if (bInstall)
+	catch (const std::exception& e)
 	{
-		hResult = DllRegisterServer();
-		if (FAILED(hResult))
-			DllUnregisterServer();
+		OutputDebugStringA(e.what());
+		return E_FAIL;
 	}
-	else
-		hResult = DllUnregisterServer();
 
-	return hResult;
+	return S_OK;
 }
Fisheye: Tag 47d0095dc08bfef8ff8f95e213b75016037f7398 refers to a dead (removed) revision in file `src/chext/chext.def'.
Fisheye: No comparison available.  Pass `N' to diff?
Fisheye: Tag 6609ba39811176f4803f0556db3da30e9e457b9d refers to a dead (removed) revision in file `src/chext/chext.idl'.
Fisheye: No comparison available.  Pass `N' to diff?
Index: src/chext/chext.rc
===================================================================
diff -u -r8163be49a92698ada689f27b2dbe0caae69a7d5c -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/chext/chext.rc	(.../chext.rc)	(revision 8163be49a92698ada689f27b2dbe0caae69a7d5c)
+++ src/chext/chext.rc	(.../chext.rc)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -40,12 +40,6 @@
 
 3 TEXTINCLUDE 
 BEGIN
-    "1 TYPELIB ""chext.tlb""\r\n"
-    "\0"
-END
-
-4 TEXTINCLUDE 
-BEGIN
     "#include ""res\\chext.rc2""\r\n"
     "\0"
 END
@@ -65,16 +59,6 @@
 #pragma code_page(1252)
 #endif //_WIN32
 
-/////////////////////////////////////////////////////////////////////////////
-//
-// REGISTRY
-//
-
-IDR_MENUEXT             REGISTRY                "MenuExt.rgs"
-IDR_DROPMENUEXT         REGISTRY                "DropMenuExt.rgs"
-IDR_SHELLEXTCONTROL     REGISTRY                "ShellExtControl.rgs"
-IDR_CHEXT				REGISTRY				"chext.rgs"
-
 #endif    // English (U.S.) resources
 /////////////////////////////////////////////////////////////////////////////
 
@@ -85,10 +69,8 @@
 //
 // Generated from the TEXTINCLUDE 3 resource.
 //
-1 TYPELIB "chext.tlb"
 
 #include "res\chext.rc2"
 
 /////////////////////////////////////////////////////////////////////////////
 #endif    // not APSTUDIO_INVOKED
-
Fisheye: Tag 6609ba39811176f4803f0556db3da30e9e457b9d refers to a dead (removed) revision in file `src/chext/chext.rgs'.
Fisheye: No comparison available.  Pass `N' to diff?
Index: src/chext/chext.vc140.vcxproj
===================================================================
diff -u -r0d5b67ee96b435d63f7bf075dc8e28603793b187 -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/chext/chext.vc140.vcxproj	(.../chext.vc140.vcxproj)	(revision 0d5b67ee96b435d63f7bf075dc8e28603793b187)
+++ src/chext/chext.vc140.vcxproj	(.../chext.vc140.vcxproj)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -214,7 +214,7 @@
     <Link>
       <RegisterOutput>false</RegisterOutput>
       <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <ModuleDefinitionFile>chext32.def</ModuleDefinitionFile>
+      <ModuleDefinitionFile>chext.def</ModuleDefinitionFile>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
@@ -250,7 +250,7 @@
     <Link>
       <RegisterOutput>false</RegisterOutput>
       <AdditionalDependencies>comctl32.lib;gmock32d.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <ModuleDefinitionFile>chext32.def</ModuleDefinitionFile>
+      <ModuleDefinitionFile>chext.def</ModuleDefinitionFile>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
@@ -301,7 +301,7 @@
     <Link>
       <RegisterOutput>false</RegisterOutput>
       <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <ModuleDefinitionFile>chext64.def</ModuleDefinitionFile>
+      <ModuleDefinitionFile>chext.def</ModuleDefinitionFile>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
@@ -338,7 +338,7 @@
     <Link>
       <RegisterOutput>false</RegisterOutput>
       <AdditionalDependencies>comctl32.lib;gmock64d.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <ModuleDefinitionFile>chext64.def</ModuleDefinitionFile>
+      <ModuleDefinitionFile>chext.def</ModuleDefinitionFile>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
@@ -389,7 +389,7 @@
     <Link>
       <RegisterOutput>false</RegisterOutput>
       <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <ModuleDefinitionFile>chext32.def</ModuleDefinitionFile>
+      <ModuleDefinitionFile>chext.def</ModuleDefinitionFile>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
@@ -426,7 +426,7 @@
     <Link>
       <RegisterOutput>false</RegisterOutput>
       <AdditionalDependencies>comctl32.lib;gmock32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <ModuleDefinitionFile>chext32.def</ModuleDefinitionFile>
+      <ModuleDefinitionFile>chext.def</ModuleDefinitionFile>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX86</TargetMachine>
@@ -477,7 +477,7 @@
     <Link>
       <RegisterOutput>false</RegisterOutput>
       <AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <ModuleDefinitionFile>chext64.def</ModuleDefinitionFile>
+      <ModuleDefinitionFile>chext.def</ModuleDefinitionFile>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
@@ -514,7 +514,7 @@
     <Link>
       <RegisterOutput>false</RegisterOutput>
       <AdditionalDependencies>comctl32.lib;gmock64.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <ModuleDefinitionFile>chext64.def</ModuleDefinitionFile>
+      <ModuleDefinitionFile>chext.def</ModuleDefinitionFile>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <SubSystem>Windows</SubSystem>
       <TargetMachine>MachineX64</TargetMachine>
@@ -553,12 +553,18 @@
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Testing Debug|x64'">NotUsing</PrecompiledHeader>
     </ClCompile>
+    <ClCompile Include="..\common\TRegistry.cpp" />
     <ClCompile Include="..\common\TShellExtIpcConfigDataConsumer.cpp" />
+    <ClCompile Include="ClassFactory.cpp" />
+    <ClCompile Include="DllRegistration.cpp" />
+    <ClCompile Include="DropMenuExtClassFactory.cpp" />
+    <ClCompile Include="MenuExtClassFactory.cpp" />
     <ClCompile Include="DropMenuExt.cpp" />
     <ClCompile Include="GuidFormatter.cpp" />
     <ClCompile Include="HResultFormatter.cpp" />
     <ClCompile Include="MenuExt.cpp" />
     <ClCompile Include="ShellExtControl.cpp" />
+    <ClCompile Include="ShellExtControlClassFactory.cpp" />
     <ClCompile Include="ShellExtensionVerifier.cpp" />
     <ClCompile Include="ShellPathsHelpers.cpp" />
     <ClCompile Include="TContextMenuHandler.cpp" />
@@ -577,40 +583,29 @@
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Testing Release|x64'">Create</PrecompiledHeader>
     </ClCompile>
-    <ClCompile Include="chext_i.c">
-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-      </PrecompiledHeader>
-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Testing Debug|Win32'">
-      </PrecompiledHeader>
-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-      </PrecompiledHeader>
-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Testing Debug|x64'">
-      </PrecompiledHeader>
-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-      </PrecompiledHeader>
-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Testing Release|Win32'">
-      </PrecompiledHeader>
-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-      </PrecompiledHeader>
-      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Testing Release|x64'">
-      </PrecompiledHeader>
-    </ClCompile>
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="..\common\TRegistry.h" />
     <ClInclude Include="..\common\TShellExtIpcConfigDataConsumer.h" />
+    <ClInclude Include="ClassFactory.h" />
+    <ClInclude Include="DllRegistration.h" />
+    <ClInclude Include="DropMenuExtClassFactory.h" />
+    <ClInclude Include="guids.h" />
+    <ClInclude Include="IShellExtControl.h" />
+    <ClInclude Include="MenuExtClassFactory.h" />
     <ClInclude Include="DropMenuExt.h" />
     <ClInclude Include="GuidFormatter.h" />
     <ClInclude Include="HResultFormatter.h" />
     <ClInclude Include="MenuExt.h" />
     <ClInclude Include="ShellExtControl.h" />
+    <ClInclude Include="ShellExtControlClassFactory.h" />
     <ClInclude Include="ShellExtensionVerifier.h" />
     <ClInclude Include="ShellPathsHelpers.h" />
     <ClInclude Include="TContextMenuHandler.h" />
     <ClInclude Include="Logger.h" />
     <ClInclude Include="TShellExtData.h" />
     <ClInclude Include="..\common\ipcstructs.h" />
     <ClInclude Include="..\common\TShellExtMenuConfig.h" />
-    <ClInclude Include="dllmain.h" />
     <ClInclude Include="StdAfx.h" />
     <ClInclude Include="..\common\targetver.h" />
     <ClInclude Include="resource.h" />
@@ -622,42 +617,6 @@
     <None Include="ShellExtControl.rgs" />
   </ItemGroup>
   <ItemGroup>
-    <Midl Include="chext.idl">
-      <GenerateStublessProxies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</GenerateStublessProxies>
-      <GenerateStublessProxies Condition="'$(Configuration)|$(Platform)'=='Testing Debug|Win32'">true</GenerateStublessProxies>
-      <TypeLibraryName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\chext.tlb</TypeLibraryName>
-      <TypeLibraryName Condition="'$(Configuration)|$(Platform)'=='Testing Debug|Win32'">.\chext.tlb</TypeLibraryName>
-      <HeaderFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">chext.h</HeaderFileName>
-      <HeaderFileName Condition="'$(Configuration)|$(Platform)'=='Testing Debug|Win32'">chext.h</HeaderFileName>
-      <InterfaceIdentifierFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">chext_i.c</InterfaceIdentifierFileName>
-      <InterfaceIdentifierFileName Condition="'$(Configuration)|$(Platform)'=='Testing Debug|Win32'">chext_i.c</InterfaceIdentifierFileName>
-      <GenerateStublessProxies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</GenerateStublessProxies>
-      <GenerateStublessProxies Condition="'$(Configuration)|$(Platform)'=='Testing Debug|x64'">true</GenerateStublessProxies>
-      <TypeLibraryName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\chext.tlb</TypeLibraryName>
-      <TypeLibraryName Condition="'$(Configuration)|$(Platform)'=='Testing Debug|x64'">.\chext.tlb</TypeLibraryName>
-      <HeaderFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">chext.h</HeaderFileName>
-      <HeaderFileName Condition="'$(Configuration)|$(Platform)'=='Testing Debug|x64'">chext.h</HeaderFileName>
-      <InterfaceIdentifierFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">chext_i.c</InterfaceIdentifierFileName>
-      <InterfaceIdentifierFileName Condition="'$(Configuration)|$(Platform)'=='Testing Debug|x64'">chext_i.c</InterfaceIdentifierFileName>
-      <GenerateStublessProxies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</GenerateStublessProxies>
-      <GenerateStublessProxies Condition="'$(Configuration)|$(Platform)'=='Testing Release|Win32'">true</GenerateStublessProxies>
-      <TypeLibraryName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\chext.tlb</TypeLibraryName>
-      <TypeLibraryName Condition="'$(Configuration)|$(Platform)'=='Testing Release|Win32'">.\chext.tlb</TypeLibraryName>
-      <HeaderFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">chext.h</HeaderFileName>
-      <HeaderFileName Condition="'$(Configuration)|$(Platform)'=='Testing Release|Win32'">chext.h</HeaderFileName>
-      <InterfaceIdentifierFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">chext_i.c</InterfaceIdentifierFileName>
-      <InterfaceIdentifierFileName Condition="'$(Configuration)|$(Platform)'=='Testing Release|Win32'">chext_i.c</InterfaceIdentifierFileName>
-      <GenerateStublessProxies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</GenerateStublessProxies>
-      <GenerateStublessProxies Condition="'$(Configuration)|$(Platform)'=='Testing Release|x64'">true</GenerateStublessProxies>
-      <TypeLibraryName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\chext.tlb</TypeLibraryName>
-      <TypeLibraryName Condition="'$(Configuration)|$(Platform)'=='Testing Release|x64'">.\chext.tlb</TypeLibraryName>
-      <HeaderFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">chext.h</HeaderFileName>
-      <HeaderFileName Condition="'$(Configuration)|$(Platform)'=='Testing Release|x64'">chext.h</HeaderFileName>
-      <InterfaceIdentifierFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">chext_i.c</InterfaceIdentifierFileName>
-      <InterfaceIdentifierFileName Condition="'$(Configuration)|$(Platform)'=='Testing Release|x64'">chext_i.c</InterfaceIdentifierFileName>
-    </Midl>
-  </ItemGroup>
-  <ItemGroup>
     <ResourceCompile Include="chext.rc" />
   </ItemGroup>
   <ItemGroup>
Index: src/chext/chext.vc140.vcxproj.filters
===================================================================
diff -u -r306fbe693c70290af9de9a5779084a697de22d75 -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/chext/chext.vc140.vcxproj.filters	(.../chext.vc140.vcxproj.filters)	(revision 306fbe693c70290af9de9a5779084a697de22d75)
+++ src/chext/chext.vc140.vcxproj.filters	(.../chext.vc140.vcxproj.filters)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -27,6 +27,9 @@
     <Filter Include="Tests">
       <UniqueIdentifier>{65a70a57-2fd2-49a6-90f2-e0597f13adfe}</UniqueIdentifier>
     </Filter>
+    <Filter Include="Source Files\Interfaces\ClassFactories">
+      <UniqueIdentifier>{4c68be3a-4d21-48ce-b3f0-e166072c66d3}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="DropMenuExt.cpp">
@@ -59,9 +62,6 @@
     <ClCompile Include="StdAfx.cpp">
       <Filter>Source Files\Main</Filter>
     </ClCompile>
-    <ClCompile Include="chext_i.c">
-      <Filter>Generated Files</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\tests\tests_shared\TestsExports.cpp">
       <Filter>Tests</Filter>
     </ClCompile>
@@ -80,6 +80,24 @@
     <ClCompile Include="..\common\TShellExtIpcConfigDataConsumer.cpp">
       <Filter>Source Files\Common</Filter>
     </ClCompile>
+    <ClCompile Include="..\common\TRegistry.cpp">
+      <Filter>Source Files\Common</Filter>
+    </ClCompile>
+    <ClCompile Include="DllRegistration.cpp">
+      <Filter>Source Files\Tools</Filter>
+    </ClCompile>
+    <ClCompile Include="ClassFactory.cpp">
+      <Filter>Source Files\Interfaces\ClassFactories</Filter>
+    </ClCompile>
+    <ClCompile Include="DropMenuExtClassFactory.cpp">
+      <Filter>Source Files\Interfaces\ClassFactories</Filter>
+    </ClCompile>
+    <ClCompile Include="MenuExtClassFactory.cpp">
+      <Filter>Source Files\Interfaces\ClassFactories</Filter>
+    </ClCompile>
+    <ClCompile Include="ShellExtControlClassFactory.cpp">
+      <Filter>Source Files\Interfaces\ClassFactories</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="DropMenuExt.h">
@@ -106,9 +124,6 @@
     <ClInclude Include="..\common\TShellExtMenuConfig.h">
       <Filter>Source Files\Common</Filter>
     </ClInclude>
-    <ClInclude Include="dllmain.h">
-      <Filter>Source Files\Main</Filter>
-    </ClInclude>
     <ClInclude Include="StdAfx.h">
       <Filter>Source Files\Main</Filter>
     </ClInclude>
@@ -133,6 +148,30 @@
     <ClInclude Include="..\common\TShellExtIpcConfigDataConsumer.h">
       <Filter>Source Files\Common</Filter>
     </ClInclude>
+    <ClInclude Include="guids.h">
+      <Filter>Source Files\Interfaces</Filter>
+    </ClInclude>
+    <ClInclude Include="IShellExtControl.h">
+      <Filter>Source Files\Interfaces</Filter>
+    </ClInclude>
+    <ClInclude Include="..\common\TRegistry.h">
+      <Filter>Source Files\Common</Filter>
+    </ClInclude>
+    <ClInclude Include="DllRegistration.h">
+      <Filter>Source Files\Tools</Filter>
+    </ClInclude>
+    <ClInclude Include="ClassFactory.h">
+      <Filter>Source Files\Interfaces\ClassFactories</Filter>
+    </ClInclude>
+    <ClInclude Include="DropMenuExtClassFactory.h">
+      <Filter>Source Files\Interfaces\ClassFactories</Filter>
+    </ClInclude>
+    <ClInclude Include="MenuExtClassFactory.h">
+      <Filter>Source Files\Interfaces\ClassFactories</Filter>
+    </ClInclude>
+    <ClInclude Include="ShellExtControlClassFactory.h">
+      <Filter>Source Files\Interfaces\ClassFactories</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="chext.def">
@@ -149,11 +188,6 @@
     </None>
   </ItemGroup>
   <ItemGroup>
-    <Midl Include="chext.idl">
-      <Filter>Source Files\Main</Filter>
-    </Midl>
-  </ItemGroup>
-  <ItemGroup>
     <ResourceCompile Include="chext.rc">
       <Filter>Resource Files</Filter>
     </ResourceCompile>
Fisheye: Tag 6609ba39811176f4803f0556db3da30e9e457b9d refers to a dead (removed) revision in file `src/chext/chext32.def'.
Fisheye: No comparison available.  Pass `N' to diff?
Fisheye: Tag 6609ba39811176f4803f0556db3da30e9e457b9d refers to a dead (removed) revision in file `src/chext/chext64.def'.
Fisheye: No comparison available.  Pass `N' to diff?
Fisheye: Tag 6609ba39811176f4803f0556db3da30e9e457b9d refers to a dead (removed) revision in file `src/chext/chextps.def'.
Fisheye: No comparison available.  Pass `N' to diff?
Fisheye: Tag 6609ba39811176f4803f0556db3da30e9e457b9d refers to a dead (removed) revision in file `src/chext/chextps.mk'.
Fisheye: No comparison available.  Pass `N' to diff?
Index: src/chext/dllmain.cpp
===================================================================
diff -u -rebc7fabbd2d59f9a0f723ea480b5374cc393ec12 -r6609ba39811176f4803f0556db3da30e9e457b9d
--- src/chext/dllmain.cpp	(.../dllmain.cpp)	(revision ebc7fabbd2d59f9a0f723ea480b5374cc393ec12)
+++ src/chext/dllmain.cpp	(.../dllmain.cpp)	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -1,21 +1,18 @@
 #include "stdafx.h"
-#include "chext.h"
-#include "dllmain.h"
 #include "MenuExt.h"
 #include "DropMenuExt.h"
 #include "ShellExtControl.h"
 
-CCHExtModule _AtlModule;
+HINSTANCE g_hInstance = nullptr;
 
-OBJECT_ENTRY_AUTO(CLSID_MenuExt, CMenuExt)
-OBJECT_ENTRY_AUTO(CLSID_DropMenuExt, CDropMenuExt)
-OBJECT_ENTRY_AUTO(CLSID_CShellExtControl, CShellExtControl)
-
 extern "C"
-BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
+BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
 {
 	if(dwReason == DLL_PROCESS_ATTACH)
+	{
 		DisableThreadLibraryCalls(hInstance);
+		g_hInstance = hInstance;
+	}
 
-	return _AtlModule.DllMain(dwReason, lpReserved);
+	return TRUE;
 }
Index: src/chext/guids.h
===================================================================
diff -u
--- src/chext/guids.h	(revision 0)
+++ src/chext/guids.h	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -0,0 +1,28 @@
+// ============================================================================
+//  Copyright (C) 2001-2019 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program 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 General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#pragma once
+
+#include <Guiddef.h>
+#include <initguid.h>
+
+DEFINE_GUID(IID_IShellExtControl, 0x317E503A, 0x9D2F, 0x4f42, 0x99, 0x5E, 0xD3, 0x14, 0xCB, 0x9D, 0x89, 0xB0);
+//DEFINE_GUID(LIBID_CHEXTLib, 0x68FAFC14, 0x8EB8, 0x4DA1, 0x90, 0xEB, 0x6B, 0x3D, 0x22, 0x01, 0x05, 0x05);
+DEFINE_GUID(CLSID_MenuExt, 0xE7A4C2DA, 0xF3AF, 0x4145, 0xAC, 0x19, 0xE3, 0xB2, 0x15, 0x30, 0x6A, 0x54);
+DEFINE_GUID(CLSID_DropMenuExt, 0xB46F8244, 0x86E6, 0x43CF, 0xB8, 0xAB, 0x8C, 0x3A, 0x89, 0x92, 0x8A, 0x48);
+DEFINE_GUID(CLSID_CShellExtControl, 0x3D855ACA, 0x8274, 0x4f1f, 0x94, 0xE9, 0x6B, 0xEF, 0x4F, 0xC2, 0xA2, 0xAF);
Index: src/common/TRegistry.cpp
===================================================================
diff -u
--- src/common/TRegistry.cpp	(revision 0)
+++ src/common/TRegistry.cpp	(revision 6609ba39811176f4803f0556db3da30e9e457b9d)
@@ -0,0 +1,126 @@
+// ============================================================================
+//  Copyright (C) 2001-2015 by Jozef Starosczyk
+//  ixen@copyhandler.com
+//
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU Library General Public License
+//  (version 2) as published by the Free Software Foundation;
+//
+//  This program 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 General Public License for more details.
+//
+//  You should have received a copy of the GNU Library General Public
+//  License along with this program; if not, write to the
+//  Free Software Foundation, Inc.,
+//  59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+// ============================================================================
+#include "stdafx.h"
+#include "TRegistry.h"
+#include <Shlwapi.h>
+
+TRegistry::TRegistry(HKEY key, const wchar_t* pszKey, bool bReadOnly)
+{
+	ReOpen(key, pszKey, bReadOnly);
+}
+
+TRegistry::~TRegistry()
+{
+	if(m_hKey)
+		RegCloseKey(m_hKey);
+}
+
+void TRegistry::ReOpen(HKEY key, const wchar_t* pszKey, bool bReadOnly /*= true*/)
+{
+	if (!pszKey)
+		throw std::invalid_argument("pszKey");
+
+	if (m_hKey)
+		RegCloseKey(m_hKey);
+
+	LSTATUS lStatus = RegOpenKeyEx(key, pszKey, 0, bReadOnly ? KEY_QUERY_VALUE : KEY_ALL_ACCESS, &m_hKey);
+	if (lStatus != ERROR_SUCCESS || m_hKey == nullptr)
+		throw std::runtime_error("Cannot open registry key");
+}
+
+void TRegistry::CreateSubKey(const wchar_t* pszKey)
+{
+	if (!pszKey)
+		throw std::invalid_argument("pszKey");
+
+	HKEY newKey = nullptr;
+	LSTATUS status = RegCreateKeyEx(m_hKey, pszKey, 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_CREATE_SUB_KEY, nullptr, &newKey, nullptr);
+	if(status != ERROR_SUCCESS)
+		throw std::runtime_error("Cannot create registry key");
+}
+
+void TRegistry::DeleteSubKey(const wchar_t* pszKey)
+{
+	if (!pszKey)
+		throw std::invalid_argument("pszKey");
+
+	LSTATUS status = SHDeleteKey(m_hKey, pszKey);
+	if (status != ERROR_SUCCESS && status != ERROR_FILE_NOT_FOUND)
+		throw std::runtime_error("Cannot delete registry key");
+}
+
+void TRegistry::DeleteValue(const wchar_t* pszValueKey)
+{
+	if (!pszValueKey)
+		throw std::invalid_argument("pszValueKey");
+
+	LSTATUS status = RegDeleteValue(m_hKey, pszValueKey);
+	if (status != ERROR_SUCCESS && status != ERROR_FILE_NOT_FOUND)
+		throw std::runtime_error("Cannot delete value");
+}
+
+bool TRegistry::QueryString(const wchar_t* pszValueKey, std::wstring& wstrValue)
+{
+	if (!pszValueKey)
+		throw std::invalid_argument("pszValueKey");
+
+	DWORD dwType = REG_SZ;
+	const DWORD stMaxBuffer = 1024;
+	std::unique_ptr<wchar_t[]> buf(new wchar_t[stMaxBuffer]);
+
+	DWORD dwCount = stMaxBuffer;
+	LSTATUS lStatus = RegQueryValueEx(m_hKey, pszValueKey, nullptr, &dwType, (BYTE*)buf.get(), &dwCount);
+	if (lStatus != ERROR_SUCCESS)
+		return false;
+
+	buf[dwCount / 2] = L'\0';
+	wstrValue = buf.get();
+
+	return true;
+}
+
+bool TRegistry::QueryDword(const wchar_t* pszValueKey, DWORD& dwOutValue)
+{
+	if (!pszValueKey)
+		throw std::invalid_argument("pszValueKey");
+
+	DWORD dwType = REG_DWORD;
+	DWORD dwCount = sizeof(DWORD);
+	DWORD dwValue = 0;
+	LSTATUS lStatus = RegQueryValueEx(m_hKey, pszValueKey, nullptr, &dwType, (BYTE*)&dwValue, &dwCount);
+	if (lStatus != ERROR_SUCCESS)
+		return false;
+
+	dwOutValue = dwValue;
+
+	return true;
+}
+
+void TRegistry::SetString(const wchar_t* pszValueKey, const wchar_t* pszValue)
+{
+	if (!pszValueKey)
+		throw std::invalid_argument("pszValueKey");
+	if (!pszValue)
+		throw std::invalid_argument("pszValue");
+
+	size_t stValueLen = wcslen(pszValue) + 1;
+	LSTATUS status = RegSetValueEx(m_hKey, pszValueKey, 0, REG_SZ, (const BYTE*)pszValue, boost::numeric_cast<DWORD>(stValueLen * sizeof(wchar_t)));
+	if (status != ERROR_SUCCESS)
+		throw std::runtime_error("Cannot set string value in registry");
+}
Fisheye: tag 62bf985594e79a03316e29434cbdcf446a64f369 is not in file src/common/TRegistry.h
Fisheye: Tag 6609ba39811176f4803f0556db3da30e9e457b9d refers to a dead (removed) revision in file `src/ch/TRegistry.h'.
Fisheye: No comparison available.  Pass `N' to diff?