1f8e2c85aSAndrew Rist /**************************************************************
2721a7f15Smseidel  *
3f8e2c85aSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4f8e2c85aSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5f8e2c85aSAndrew Rist  * distributed with this work for additional information
6f8e2c85aSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7f8e2c85aSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8f8e2c85aSAndrew Rist  * "License"); you may not use this file except in compliance
9f8e2c85aSAndrew Rist  * with the License.  You may obtain a copy of the License at
10721a7f15Smseidel  *
11f8e2c85aSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12721a7f15Smseidel  *
13f8e2c85aSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14f8e2c85aSAndrew Rist  * software distributed under the License is distributed on an
15f8e2c85aSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16f8e2c85aSAndrew Rist  * KIND, either express or implied.  See the License for the
17f8e2c85aSAndrew Rist  * specific language governing permissions and limitations
18f8e2c85aSAndrew Rist  * under the License.
19721a7f15Smseidel  *
20f8e2c85aSAndrew Rist  *************************************************************/
21f8e2c85aSAndrew Rist 
22f8e2c85aSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_shell.hxx"
26cdf0e10cSrcweir #include "internal/config.hxx"
27cdf0e10cSrcweir #include "internal/global.hxx"
28cdf0e10cSrcweir #include "internal/shlxthdl.hxx"
29cdf0e10cSrcweir #include "classfactory.hxx"
30cdf0e10cSrcweir #include "internal/registry.hxx"
31cdf0e10cSrcweir #include "internal/fileextensions.hxx"
32cdf0e10cSrcweir #include "internal/utilities.hxx"
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include <tchar.h>
35cdf0e10cSrcweir #include <string>
36cdf0e10cSrcweir #include <shlobj.h>
37cdf0e10cSrcweir 
38cdf0e10cSrcweir //---------------------------
39cdf0e10cSrcweir // Module global
40cdf0e10cSrcweir //---------------------------
41cdf0e10cSrcweir long g_DllRefCnt = 0;
42cdf0e10cSrcweir HINSTANCE g_hModule = NULL;
43721a7f15Smseidel 
44cdf0e10cSrcweir namespace /* private */
45cdf0e10cSrcweir {
46721a7f15Smseidel 	const char* GUID_PLACEHOLDER		= "{GUID}";
47721a7f15Smseidel 	const char* EXTENSION_PLACEHOLDER	= "{EXT}";
48721a7f15Smseidel 	const char* FORWARDKEY_PLACEHOLDER	= "{FWDKEY}";
49721a7f15Smseidel 
50721a7f15Smseidel 	const char* CLSID_ENTRY							= "CLSID\\{GUID}\\InProcServer32";
51721a7f15Smseidel 	const char* SHELLEX_IID_ENTRY					= "{EXT}\\shellex\\{GUID}";
52721a7f15Smseidel 	const char* SHELLEX_ENTRY						= "{EXT}\\shellex";
53721a7f15Smseidel 	const char* PROPSHEET_ENTRY						= "{EXT}\\CLSID\\{GUID}\\InProcServer32";
54721a7f15Smseidel 	const char* EXTENSION_CLSID						= "{EXT}\\CLSID";
55cdf0e10cSrcweir 	const char* EXTENSION_CLSID_GUID				= "{EXT}\\CLSID\\{GUID}";
56cdf0e10cSrcweir 	const char* FORWARD_PROPSHEET_MYPROPSHEET_ENTRY = "{FWDKEY}\\shellex\\PropertySheetHandlers\\MyPropSheet1";
57721a7f15Smseidel 	const char* FORWARD_PROPSHEET_ENTRY				= "{FWDKEY}\\shellex\\PropertySheetHandlers";
58cdf0e10cSrcweir 	const char* FORWARD_SHELLEX_ENTRY				= "{FWDKEY}\\shellex";
59cdf0e10cSrcweir 
60721a7f15Smseidel 	const char* SHELL_EXTENSION_APPROVED_KEY_NAME	= "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved";
61721a7f15Smseidel 
62721a7f15Smseidel 	//---------------------------
63721a7f15Smseidel 	// "String Placeholder" ->
64721a7f15Smseidel 	// "String Replacement"
65721a7f15Smseidel 	//---------------------------
SubstitutePlaceholder(std::string & String,const std::string & Placeholder,const std::string & Replacement)66721a7f15Smseidel 	void SubstitutePlaceholder(std::string& String, const std::string& Placeholder, const std::string& Replacement)
67721a7f15Smseidel 	{
68721a7f15Smseidel 		std::string::size_type idx = String.find(Placeholder);
69721a7f15Smseidel 		std::string::size_type len = Placeholder.length();
70721a7f15Smseidel 
71721a7f15Smseidel 		while (std::string::npos != idx)
72721a7f15Smseidel 		{
73721a7f15Smseidel 			String.replace(idx, len, Replacement);
74721a7f15Smseidel 			idx = String.find(Placeholder);
75721a7f15Smseidel 		}
76721a7f15Smseidel 	}
77721a7f15Smseidel 
78721a7f15Smseidel 	/* Make the registry entry
79721a7f15Smseidel 		HKCR\CLSID\{GUID}
80721a7f15Smseidel 			InProcServer32 = Path\shlxthdl.dll
81721a7f15Smseidel 				ThreadingModel = Apartment
82721a7f15Smseidel 	*/
RegisterComComponent(const char * FilePath,const CLSID & Guid)83721a7f15Smseidel 	HRESULT RegisterComComponent(const char* FilePath, const CLSID& Guid)
84721a7f15Smseidel 	{
85721a7f15Smseidel 		std::string ClsidEntry = CLSID_ENTRY;
86721a7f15Smseidel 		SubstitutePlaceholder(ClsidEntry, GUID_PLACEHOLDER, ClsidToString(Guid));
87721a7f15Smseidel 
88721a7f15Smseidel 		if (!SetRegistryKey(HKEY_CLASSES_ROOT, ClsidEntry.c_str(), "", FilePath))
89721a7f15Smseidel 			return E_FAIL;
90721a7f15Smseidel 
91721a7f15Smseidel 		if (!SetRegistryKey(HKEY_CLASSES_ROOT, ClsidEntry.c_str(), "ThreadingModel", "Apartment"))
92721a7f15Smseidel 			return E_FAIL;
93721a7f15Smseidel 
94721a7f15Smseidel 		return S_OK;
95721a7f15Smseidel 	}
96721a7f15Smseidel 
UnregisterComComponent(const CLSID & Guid)97721a7f15Smseidel 	HRESULT UnregisterComComponent(const CLSID& Guid)
98721a7f15Smseidel 	{
99721a7f15Smseidel 		std::string tmp = "CLSID\\";
100721a7f15Smseidel 		tmp += ClsidToString(Guid);
101721a7f15Smseidel 		return DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str()) ? S_OK : E_FAIL;
102721a7f15Smseidel 	}
103721a7f15Smseidel 
RegisterColumnHandler(const char * ModuleFileName)104721a7f15Smseidel 	HRESULT RegisterColumnHandler(const char* ModuleFileName)
105721a7f15Smseidel 	{
106721a7f15Smseidel 		if (FAILED(RegisterComComponent(ModuleFileName, CLSID_COLUMN_HANDLER)))
107721a7f15Smseidel 			return E_FAIL;
108721a7f15Smseidel 
109721a7f15Smseidel 		std::string tmp = "Folder\\shellex\\ColumnHandlers\\";
110721a7f15Smseidel 		tmp += ClsidToString(CLSID_COLUMN_HANDLER);
111721a7f15Smseidel 
112721a7f15Smseidel 		return SetRegistryKey(
113721a7f15Smseidel 			HKEY_CLASSES_ROOT,
114721a7f15Smseidel 			tmp.c_str(),
115721a7f15Smseidel 			"",
116cdf0e10cSrcweir 			WStringToString(COLUMN_HANDLER_DESCRIPTIVE_NAME).c_str()) ? S_OK : E_FAIL;
117721a7f15Smseidel 	}
118721a7f15Smseidel 
UnregisterColumnHandler()119721a7f15Smseidel 	HRESULT UnregisterColumnHandler()
120721a7f15Smseidel 	{
121721a7f15Smseidel 		std::string tmp = "Folder\\shellex\\ColumnHandlers\\";
122721a7f15Smseidel 		tmp += ClsidToString(CLSID_COLUMN_HANDLER);
123721a7f15Smseidel 
124721a7f15Smseidel 		if (!DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str()))
125721a7f15Smseidel 			return E_FAIL;
126721a7f15Smseidel 
127721a7f15Smseidel 		return UnregisterComComponent(CLSID_COLUMN_HANDLER);
128721a7f15Smseidel 	}
129721a7f15Smseidel 
RegisterInfotipHandler(const char * ModuleFileName)130721a7f15Smseidel 	HRESULT RegisterInfotipHandler(const char* ModuleFileName)
131721a7f15Smseidel 	{
132721a7f15Smseidel 		if (FAILED(RegisterComComponent(ModuleFileName, CLSID_INFOTIP_HANDLER)))
133721a7f15Smseidel 			return E_FAIL;
134721a7f15Smseidel 
135721a7f15Smseidel 		std::string iid = ClsidToString(IID_IQueryInfo);
136721a7f15Smseidel 		std::string tmp;
137721a7f15Smseidel 
138721a7f15Smseidel 		for(size_t i = 0; i < OOFileExtensionTableSize; i++)
139721a7f15Smseidel 		{
140721a7f15Smseidel 			tmp = SHELLEX_IID_ENTRY;
141721a7f15Smseidel 			SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
142721a7f15Smseidel 			SubstitutePlaceholder(tmp, GUID_PLACEHOLDER, iid);
143721a7f15Smseidel 
144721a7f15Smseidel 			if (!SetRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str(), "", ClsidToString(CLSID_INFOTIP_HANDLER).c_str()))
145721a7f15Smseidel 				return E_FAIL;
146721a7f15Smseidel 		}
147721a7f15Smseidel 		return S_OK;
148721a7f15Smseidel 	}
149721a7f15Smseidel 
UnregisterInfotipHandler()150721a7f15Smseidel 	HRESULT UnregisterInfotipHandler()
151721a7f15Smseidel 	{
152721a7f15Smseidel 		std::string iid = ClsidToString(IID_IQueryInfo);
153721a7f15Smseidel 		std::string tmp;
154721a7f15Smseidel 
155721a7f15Smseidel 		for (size_t i = 0; i < OOFileExtensionTableSize; i++)
156721a7f15Smseidel 		{
157721a7f15Smseidel 			tmp = SHELLEX_IID_ENTRY;
158721a7f15Smseidel 
159721a7f15Smseidel 			SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
160721a7f15Smseidel 			SubstitutePlaceholder(tmp, GUID_PLACEHOLDER, iid);
161721a7f15Smseidel 
162721a7f15Smseidel 			DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str());
163721a7f15Smseidel 
164721a7f15Smseidel 			// if there are no further subkey below .ext\\shellex
165721a7f15Smseidel 			// delete the whole subkey
166721a7f15Smseidel 			tmp = SHELLEX_ENTRY;
167721a7f15Smseidel 			SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
168721a7f15Smseidel 
169721a7f15Smseidel 			bool HasSubKeys = true;
170721a7f15Smseidel 			if (HasSubkeysRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str(), HasSubKeys) && !HasSubKeys)
171721a7f15Smseidel 				DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str());
172721a7f15Smseidel 		}
173721a7f15Smseidel 		return UnregisterComComponent(CLSID_INFOTIP_HANDLER);
174721a7f15Smseidel 	}
175721a7f15Smseidel 
RegisterPropSheetHandler(const char * ModuleFileName)176721a7f15Smseidel 	HRESULT RegisterPropSheetHandler(const char* ModuleFileName)
177721a7f15Smseidel 	{
178721a7f15Smseidel 		std::string ExtEntry;
179721a7f15Smseidel 		std::string FwdKeyEntry;
180721a7f15Smseidel 
181721a7f15Smseidel 		if (FAILED(RegisterComComponent(ModuleFileName, CLSID_PROPERTYSHEET_HANDLER)))
182721a7f15Smseidel 			return E_FAIL;
183721a7f15Smseidel 
184721a7f15Smseidel 		for (size_t i = 0; i < OOFileExtensionTableSize; i++)
185721a7f15Smseidel 		{
186721a7f15Smseidel 			FwdKeyEntry = FORWARD_PROPSHEET_MYPROPSHEET_ENTRY;
187721a7f15Smseidel 			SubstitutePlaceholder(FwdKeyEntry, FORWARDKEY_PLACEHOLDER, OOFileExtensionTable[i].RegistryForwardKey);
188721a7f15Smseidel 
189721a7f15Smseidel 			if (!SetRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str(), "", ClsidToString(CLSID_PROPERTYSHEET_HANDLER).c_str()))
190721a7f15Smseidel 				return E_FAIL;
191721a7f15Smseidel 		}
192721a7f15Smseidel 		return S_OK;
193721a7f15Smseidel 	}
194721a7f15Smseidel 
UnregisterPropSheetHandler()195721a7f15Smseidel 	HRESULT UnregisterPropSheetHandler()
196721a7f15Smseidel 	{
197721a7f15Smseidel 		std::string ExtEntry;
198721a7f15Smseidel 		std::string FwdKeyEntry;
199721a7f15Smseidel 
200721a7f15Smseidel 		for (size_t i = 0; i < OOFileExtensionTableSize; i++)
201721a7f15Smseidel 		{
202721a7f15Smseidel 			FwdKeyEntry = FORWARD_PROPSHEET_MYPROPSHEET_ENTRY;
203721a7f15Smseidel 			SubstitutePlaceholder(FwdKeyEntry, FORWARDKEY_PLACEHOLDER, OOFileExtensionTable[i].RegistryForwardKey);
204721a7f15Smseidel 
205721a7f15Smseidel 			DeleteRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str());
206721a7f15Smseidel 
207721a7f15Smseidel 			FwdKeyEntry = FORWARD_PROPSHEET_ENTRY;
208721a7f15Smseidel 			SubstitutePlaceholder(FwdKeyEntry, FORWARDKEY_PLACEHOLDER, OOFileExtensionTable[i].RegistryForwardKey);
209721a7f15Smseidel 
210721a7f15Smseidel 			bool HasSubKeys = true;
211721a7f15Smseidel 			if (HasSubkeysRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str(), HasSubKeys) && !HasSubKeys)
212721a7f15Smseidel 				DeleteRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str());
213721a7f15Smseidel 
214721a7f15Smseidel 			FwdKeyEntry = FORWARD_SHELLEX_ENTRY;
215721a7f15Smseidel 			SubstitutePlaceholder(FwdKeyEntry, FORWARDKEY_PLACEHOLDER, OOFileExtensionTable[i].RegistryForwardKey);
216721a7f15Smseidel 
217721a7f15Smseidel 			HasSubKeys = true;
218721a7f15Smseidel 			if (HasSubkeysRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str(), HasSubKeys) && !HasSubKeys)
219721a7f15Smseidel 				DeleteRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str());
220721a7f15Smseidel 		}
221721a7f15Smseidel 
222721a7f15Smseidel 		return UnregisterComComponent(CLSID_PROPERTYSHEET_HANDLER);
223721a7f15Smseidel 	}
224721a7f15Smseidel 
RegisterThumbviewerHandler(const char * ModuleFileName)225721a7f15Smseidel 	HRESULT RegisterThumbviewerHandler(const char* ModuleFileName)
226721a7f15Smseidel 	{
227721a7f15Smseidel 		if (FAILED(RegisterComComponent(ModuleFileName, CLSID_THUMBVIEWER_HANDLER)))
228721a7f15Smseidel 			return E_FAIL;
229721a7f15Smseidel 
230721a7f15Smseidel 		std::string iid = ClsidToString(IID_IExtractImage);
231721a7f15Smseidel 		std::string tmp;
232721a7f15Smseidel 
233721a7f15Smseidel 		for(size_t i = 0; i < OOFileExtensionTableSize; i++)
234721a7f15Smseidel 		{
235721a7f15Smseidel 			tmp = SHELLEX_IID_ENTRY;
236721a7f15Smseidel 
237721a7f15Smseidel 			SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
238721a7f15Smseidel 			SubstitutePlaceholder(tmp, GUID_PLACEHOLDER, iid);
239721a7f15Smseidel 
240721a7f15Smseidel 			if (!SetRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str(), "", ClsidToString(CLSID_THUMBVIEWER_HANDLER).c_str()))
241721a7f15Smseidel 				return E_FAIL;
242721a7f15Smseidel 		}
243721a7f15Smseidel 		return S_OK;
244721a7f15Smseidel 	}
245721a7f15Smseidel 
UnregisterThumbviewerHandler()246721a7f15Smseidel 	HRESULT UnregisterThumbviewerHandler()
247721a7f15Smseidel 	{
248721a7f15Smseidel 		std::string iid = ClsidToString(IID_IExtractImage);
249721a7f15Smseidel 		std::string tmp;
250721a7f15Smseidel 
251721a7f15Smseidel 		for (size_t i = 0; i < OOFileExtensionTableSize; i++)
252721a7f15Smseidel 		{
253721a7f15Smseidel 			tmp = SHELLEX_IID_ENTRY;
254721a7f15Smseidel 
255721a7f15Smseidel 			SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
256721a7f15Smseidel 			SubstitutePlaceholder(tmp, GUID_PLACEHOLDER, iid);
257721a7f15Smseidel 
258721a7f15Smseidel 			DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str());
259721a7f15Smseidel 
260721a7f15Smseidel 			// if there are no further subkey below .ext\\shellex
261721a7f15Smseidel 			// delete the whole subkey
262721a7f15Smseidel 			tmp = SHELLEX_ENTRY;
263721a7f15Smseidel 			SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
264721a7f15Smseidel 
265721a7f15Smseidel 			bool HasSubKeys = true;
266721a7f15Smseidel 			if (HasSubkeysRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str(), HasSubKeys) && !HasSubKeys)
267721a7f15Smseidel 				DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str());
268721a7f15Smseidel 		}
269721a7f15Smseidel 		return UnregisterComComponent(CLSID_THUMBVIEWER_HANDLER);
270721a7f15Smseidel 	}
271721a7f15Smseidel 
272721a7f15Smseidel 	/** Approving/Unapproving the Shell Extension, it's important under Windows
273cdf0e10cSrcweir 	    NT/2000/XP, see MSDN: Creating Shell Extension Handlers */
ApproveShellExtension(CLSID clsid,const std::wstring & Description)274721a7f15Smseidel 	HRESULT ApproveShellExtension(CLSID clsid, const std::wstring& Description)
275cdf0e10cSrcweir 	{
276cdf0e10cSrcweir 		bool bRet = SetRegistryKey(
277721a7f15Smseidel 			HKEY_LOCAL_MACHINE,
278cdf0e10cSrcweir 			SHELL_EXTENSION_APPROVED_KEY_NAME,
279cdf0e10cSrcweir 			ClsidToString(clsid).c_str(),
280cdf0e10cSrcweir 			WStringToString(Description).c_str());
281cdf0e10cSrcweir 
282cdf0e10cSrcweir 		return bRet ? S_OK : E_FAIL;
283cdf0e10cSrcweir 	}
284721a7f15Smseidel 
UnapproveShellExtension(CLSID Clsid)285cdf0e10cSrcweir 	HRESULT UnapproveShellExtension(CLSID Clsid)
286cdf0e10cSrcweir 	{
287cdf0e10cSrcweir 		HKEY hkey;
288cdf0e10cSrcweir 
289cdf0e10cSrcweir 		LONG rc = RegOpenKeyA(
290cdf0e10cSrcweir 			HKEY_LOCAL_MACHINE,
291cdf0e10cSrcweir 			SHELL_EXTENSION_APPROVED_KEY_NAME,
292cdf0e10cSrcweir 			&hkey);
293cdf0e10cSrcweir 
294cdf0e10cSrcweir 		if (ERROR_SUCCESS == rc)
295cdf0e10cSrcweir 		{
296cdf0e10cSrcweir 			rc = RegDeleteValueA(
297cdf0e10cSrcweir 				hkey,
298cdf0e10cSrcweir 				ClsidToString(Clsid).c_str());
299cdf0e10cSrcweir 
300cdf0e10cSrcweir 			rc = RegCloseKey(hkey);
301cdf0e10cSrcweir 		}
302cdf0e10cSrcweir 
303cdf0e10cSrcweir 		return rc == ERROR_SUCCESS ? S_OK : E_FAIL;
304cdf0e10cSrcweir 	}
305cdf0e10cSrcweir 
306cdf0e10cSrcweir } // namespace /* private */
307cdf0e10cSrcweir 
308cdf0e10cSrcweir 
309cdf0e10cSrcweir //---------------------
310cdf0e10cSrcweir // COM exports
311cdf0e10cSrcweir //---------------------
312cdf0e10cSrcweir 
DllRegisterServer()313cdf0e10cSrcweir extern "C" STDAPI DllRegisterServer()
314721a7f15Smseidel {
315cdf0e10cSrcweir 	TCHAR ModuleFileName[MAX_PATH];
316cdf0e10cSrcweir 
317cdf0e10cSrcweir 	GetModuleFileName(
318cdf0e10cSrcweir 		GetModuleHandle(MODULE_NAME),
319cdf0e10cSrcweir 		ModuleFileName,
320cdf0e10cSrcweir 		sizeof(ModuleFileName));
321721a7f15Smseidel 
322cdf0e10cSrcweir 	std::string module_path = WStringToString(ModuleFileName);
323cdf0e10cSrcweir 	HRESULT hr = S_OK;
324721a7f15Smseidel 
325721a7f15Smseidel 	if (SUCCEEDED(RegisterColumnHandler(module_path.c_str())))
326721a7f15Smseidel 		ApproveShellExtension(CLSID_COLUMN_HANDLER, COLUMN_HANDLER_DESCRIPTIVE_NAME);
327721a7f15Smseidel 	else
328721a7f15Smseidel 		hr = E_FAIL;
329721a7f15Smseidel 
330721a7f15Smseidel 	if (SUCCEEDED(RegisterInfotipHandler(module_path.c_str())))
331721a7f15Smseidel 		ApproveShellExtension(CLSID_INFOTIP_HANDLER, INFOTIP_HANDLER_DESCRIPTIVE_NAME);
332721a7f15Smseidel 	else
333721a7f15Smseidel 		hr = E_FAIL;
334721a7f15Smseidel 
335721a7f15Smseidel 	if (SUCCEEDED(RegisterPropSheetHandler(module_path.c_str())))
336721a7f15Smseidel 		ApproveShellExtension(CLSID_PROPERTYSHEET_HANDLER, PROPSHEET_HANDLER_DESCRIPTIVE_NAME);
337721a7f15Smseidel 	else
338721a7f15Smseidel 		hr = E_FAIL;
339721a7f15Smseidel 
340721a7f15Smseidel 	if (SUCCEEDED(RegisterThumbviewerHandler(module_path.c_str())))
341*49539899Smseidel 		ApproveShellExtension(CLSID_THUMBVIEWER_HANDLER, THUMBVIEWER_HANDLER_DESCRIPTIVE_NAME);
342721a7f15Smseidel 	else
343721a7f15Smseidel 		hr = E_FAIL;
344721a7f15Smseidel 
345cdf0e10cSrcweir 	// notify the Shell that something has changed
346cdf0e10cSrcweir 	SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
347cdf0e10cSrcweir 
348cdf0e10cSrcweir 	return hr;
349cdf0e10cSrcweir }
350cdf0e10cSrcweir 
DllUnregisterServer()351cdf0e10cSrcweir extern "C" STDAPI DllUnregisterServer()
352cdf0e10cSrcweir {
353cdf0e10cSrcweir 	HRESULT hr = S_OK;
354cdf0e10cSrcweir 
355cdf0e10cSrcweir 	if (FAILED(UnregisterColumnHandler()))
356cdf0e10cSrcweir 		hr = E_FAIL;
357cdf0e10cSrcweir 
358cdf0e10cSrcweir 	UnapproveShellExtension(CLSID_COLUMN_HANDLER);
359cdf0e10cSrcweir 
360cdf0e10cSrcweir 	if (FAILED(UnregisterInfotipHandler()))
361cdf0e10cSrcweir 		hr = E_FAIL;
362cdf0e10cSrcweir 
363cdf0e10cSrcweir 	UnapproveShellExtension(CLSID_INFOTIP_HANDLER);
364cdf0e10cSrcweir 
365cdf0e10cSrcweir 	if (FAILED(UnregisterPropSheetHandler()))
366cdf0e10cSrcweir 		hr = E_FAIL;
367cdf0e10cSrcweir 
368cdf0e10cSrcweir 	UnapproveShellExtension(CLSID_PROPERTYSHEET_HANDLER);
369cdf0e10cSrcweir 
370721a7f15Smseidel 	if (FAILED(UnregisterThumbviewerHandler()))
371721a7f15Smseidel 		hr = E_FAIL;
372721a7f15Smseidel 
373721a7f15Smseidel 	UnapproveShellExtension(CLSID_THUMBVIEWER_HANDLER);
374721a7f15Smseidel 
375cdf0e10cSrcweir 	// notify the Shell that something has changed
376cdf0e10cSrcweir 	SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
377cdf0e10cSrcweir 
378cdf0e10cSrcweir 	return hr;
379cdf0e10cSrcweir }
380cdf0e10cSrcweir 
DllGetClassObject(REFCLSID rclsid,REFIID riid,void ** ppv)381cdf0e10cSrcweir extern "C" STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void** ppv)
382cdf0e10cSrcweir {
383cdf0e10cSrcweir 	*ppv = 0;
384cdf0e10cSrcweir 
385721a7f15Smseidel 	if ((rclsid != CLSID_INFOTIP_HANDLER) &&
386721a7f15Smseidel 		(rclsid != CLSID_COLUMN_HANDLER) &&
387721a7f15Smseidel 		(rclsid != CLSID_PROPERTYSHEET_HANDLER) &&
388721a7f15Smseidel 		(rclsid != CLSID_THUMBVIEWER_HANDLER))
389cdf0e10cSrcweir 		return CLASS_E_CLASSNOTAVAILABLE;
390cdf0e10cSrcweir 
391cdf0e10cSrcweir 	if ((riid != IID_IUnknown) && (riid != IID_IClassFactory))
392cdf0e10cSrcweir 		return E_NOINTERFACE;
393cdf0e10cSrcweir 
394cdf0e10cSrcweir 	if ( rclsid == CLSID_INFOTIP_HANDLER )
395721a7f15Smseidel 		OutputDebugStringFormat( "DllGetClassObject: Create CLSID_INFOTIP_HANDLER\n" );
396cdf0e10cSrcweir 	else if ( rclsid == CLSID_COLUMN_HANDLER )
397721a7f15Smseidel 		OutputDebugStringFormat( "DllGetClassObject: Create CLSID_COLUMN_HANDLER\n" );
398cdf0e10cSrcweir 	else if ( rclsid == CLSID_PROPERTYSHEET_HANDLER )
399721a7f15Smseidel 		OutputDebugStringFormat( "DllGetClassObject: Create CLSID_PROPERTYSHEET_HANDLER\n" );
400cdf0e10cSrcweir 	else if ( rclsid == CLSID_THUMBVIEWER_HANDLER )
401721a7f15Smseidel 		OutputDebugStringFormat( "DllGetClassObject: Create CLSID_THUMBVIEWER_HANDLER\n" );
402cdf0e10cSrcweir 
403cdf0e10cSrcweir 	IUnknown* pUnk = new CClassFactory(rclsid);
404cdf0e10cSrcweir 	if (0 == pUnk)
405cdf0e10cSrcweir 		return E_OUTOFMEMORY;
406cdf0e10cSrcweir 
407cdf0e10cSrcweir 	*ppv = pUnk;
408cdf0e10cSrcweir 	return S_OK;
409cdf0e10cSrcweir }
410cdf0e10cSrcweir 
DllCanUnloadNow(void)411cdf0e10cSrcweir extern "C" STDAPI DllCanUnloadNow(void)
412cdf0e10cSrcweir {
413cdf0e10cSrcweir 	if (CClassFactory::IsLocked() || g_DllRefCnt > 0)
414cdf0e10cSrcweir 		return S_FALSE;
415cdf0e10cSrcweir 
416cdf0e10cSrcweir 	return S_OK;
417cdf0e10cSrcweir }
418cdf0e10cSrcweir 
DllMain(HINSTANCE hInst,ULONG,LPVOID)419cdf0e10cSrcweir BOOL WINAPI DllMain(HINSTANCE hInst, ULONG /*ul_reason_for_call*/, LPVOID /*lpReserved*/)
420cdf0e10cSrcweir {
421721a7f15Smseidel 	g_hModule = hInst;
422721a7f15Smseidel 	return TRUE;
423cdf0e10cSrcweir }
424721a7f15Smseidel 
425721a7f15Smseidel /* vim: set noet sw=4 ts=4: */
426