1*f8e2c85aSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*f8e2c85aSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*f8e2c85aSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*f8e2c85aSAndrew Rist  * distributed with this work for additional information
6*f8e2c85aSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*f8e2c85aSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*f8e2c85aSAndrew Rist  * "License"); you may not use this file except in compliance
9*f8e2c85aSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*f8e2c85aSAndrew Rist  *
11*f8e2c85aSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*f8e2c85aSAndrew Rist  *
13*f8e2c85aSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*f8e2c85aSAndrew Rist  * software distributed under the License is distributed on an
15*f8e2c85aSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*f8e2c85aSAndrew Rist  * KIND, either express or implied.  See the License for the
17*f8e2c85aSAndrew Rist  * specific language governing permissions and limitations
18*f8e2c85aSAndrew Rist  * under the License.
19*f8e2c85aSAndrew Rist  *
20*f8e2c85aSAndrew Rist  *************************************************************/
21*f8e2c85aSAndrew Rist 
22*f8e2c85aSAndrew 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;
43cdf0e10cSrcweir 
44cdf0e10cSrcweir namespace /* private */
45cdf0e10cSrcweir {
46cdf0e10cSrcweir 	const char* GUID_PLACEHOLDER       = "{GUID}";
47cdf0e10cSrcweir 	const char* EXTENSION_PLACEHOLDER  = "{EXT}";
48cdf0e10cSrcweir 	const char* FORWARDKEY_PLACEHOLDER = "{FWDKEY}";
49cdf0e10cSrcweir 
50cdf0e10cSrcweir 	const char* CLSID_ENTRY                         = "CLSID\\{GUID}\\InProcServer32";
51cdf0e10cSrcweir 	const char* SHELLEX_IID_ENTRY                   = "{EXT}\\shellex\\{GUID}";
52cdf0e10cSrcweir 	const char* SHELLEX_ENTRY			            = "{EXT}\\shellex";
53cdf0e10cSrcweir 	const char* PROPSHEET_ENTRY                     = "{EXT}\\CLSID\\{GUID}\\InProcServer32";
54cdf0e10cSrcweir 	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";
57cdf0e10cSrcweir 	const char* FORWARD_PROPSHEET_ENTRY             = "{FWDKEY}\\shellex\\PropertySheetHandlers";
58cdf0e10cSrcweir 	const char* FORWARD_SHELLEX_ENTRY				= "{FWDKEY}\\shellex";
59cdf0e10cSrcweir 
60cdf0e10cSrcweir 	const char* SHELL_EXTENSION_APPROVED_KEY_NAME   = "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved";
61cdf0e10cSrcweir 
62cdf0e10cSrcweir     //---------------------------
63cdf0e10cSrcweir     // "String Placeholder" ->
64cdf0e10cSrcweir     // "String Replacement"
65cdf0e10cSrcweir     //---------------------------
66cdf0e10cSrcweir     void SubstitutePlaceholder(std::string& String, const std::string& Placeholder, const std::string& Replacement)
67cdf0e10cSrcweir     {
68cdf0e10cSrcweir         std::string::size_type idx = String.find(Placeholder);
69cdf0e10cSrcweir         std::string::size_type len = Placeholder.length();
70cdf0e10cSrcweir 
71cdf0e10cSrcweir         while (std::string::npos != idx)
72cdf0e10cSrcweir         {
73cdf0e10cSrcweir             String.replace(idx, len, Replacement);
74cdf0e10cSrcweir             idx = String.find(Placeholder);
75cdf0e10cSrcweir         }
76cdf0e10cSrcweir     }
77cdf0e10cSrcweir 
78cdf0e10cSrcweir     /* Make the registry entry
79cdf0e10cSrcweir        HKCR\CLSID\{GUID}
80cdf0e10cSrcweir     		InProcServer32 = Path\shlxthdl.dll
81cdf0e10cSrcweir     			ThreadingModel = Apartment
82cdf0e10cSrcweir     */
83cdf0e10cSrcweir     HRESULT RegisterComComponent(const char* FilePath, const CLSID& Guid)
84cdf0e10cSrcweir     {
85cdf0e10cSrcweir         std::string ClsidEntry = CLSID_ENTRY;
86cdf0e10cSrcweir         SubstitutePlaceholder(ClsidEntry, GUID_PLACEHOLDER, ClsidToString(Guid));
87cdf0e10cSrcweir 
88cdf0e10cSrcweir         if (!SetRegistryKey(HKEY_CLASSES_ROOT, ClsidEntry.c_str(), "", FilePath))
89cdf0e10cSrcweir             return E_FAIL;
90cdf0e10cSrcweir 
91cdf0e10cSrcweir         if (!SetRegistryKey(HKEY_CLASSES_ROOT, ClsidEntry.c_str(), "ThreadingModel", "Apartment"))
92cdf0e10cSrcweir             return E_FAIL;
93cdf0e10cSrcweir 
94cdf0e10cSrcweir         return S_OK;
95cdf0e10cSrcweir     }
96cdf0e10cSrcweir 
97cdf0e10cSrcweir     HRESULT UnregisterComComponent(const CLSID& Guid)
98cdf0e10cSrcweir     {
99cdf0e10cSrcweir         std::string tmp = "CLSID\\";
100cdf0e10cSrcweir         tmp += ClsidToString(Guid);
101cdf0e10cSrcweir         return DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str()) ? S_OK : E_FAIL;
102cdf0e10cSrcweir     }
103cdf0e10cSrcweir 
104cdf0e10cSrcweir     HRESULT RegisterColumnHandler(const char* ModuleFileName)
105cdf0e10cSrcweir     {
106cdf0e10cSrcweir         if (FAILED(RegisterComComponent(ModuleFileName, CLSID_COLUMN_HANDLER)))
107cdf0e10cSrcweir             return E_FAIL;
108cdf0e10cSrcweir 
109cdf0e10cSrcweir         std::string tmp = "Folder\\shellex\\ColumnHandlers\\";
110cdf0e10cSrcweir         tmp += ClsidToString(CLSID_COLUMN_HANDLER);
111cdf0e10cSrcweir 
112cdf0e10cSrcweir         return SetRegistryKey(
113cdf0e10cSrcweir 			HKEY_CLASSES_ROOT,
114cdf0e10cSrcweir 			tmp.c_str(),
115cdf0e10cSrcweir 			"",
116cdf0e10cSrcweir 			WStringToString(COLUMN_HANDLER_DESCRIPTIVE_NAME).c_str()) ? S_OK : E_FAIL;
117cdf0e10cSrcweir     }
118cdf0e10cSrcweir 
119cdf0e10cSrcweir     HRESULT UnregisterColumnHandler()
120cdf0e10cSrcweir     {
121cdf0e10cSrcweir         std::string tmp = "Folder\\shellex\\ColumnHandlers\\";
122cdf0e10cSrcweir         tmp += ClsidToString(CLSID_COLUMN_HANDLER);
123cdf0e10cSrcweir 
124cdf0e10cSrcweir         if (!DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str()))
125cdf0e10cSrcweir             return E_FAIL;
126cdf0e10cSrcweir 
127cdf0e10cSrcweir         return UnregisterComComponent(CLSID_COLUMN_HANDLER);
128cdf0e10cSrcweir     }
129cdf0e10cSrcweir 
130cdf0e10cSrcweir     HRESULT RegisterInfotipHandler(const char* ModuleFileName)
131cdf0e10cSrcweir     {
132cdf0e10cSrcweir         if (FAILED(RegisterComComponent(ModuleFileName, CLSID_INFOTIP_HANDLER)))
133cdf0e10cSrcweir             return E_FAIL;
134cdf0e10cSrcweir 
135cdf0e10cSrcweir         std::string iid = ClsidToString(IID_IQueryInfo);
136cdf0e10cSrcweir         std::string tmp;
137cdf0e10cSrcweir 
138cdf0e10cSrcweir         for(size_t i = 0; i < OOFileExtensionTableSize; i++)
139cdf0e10cSrcweir         {
140cdf0e10cSrcweir             tmp = SHELLEX_IID_ENTRY;
141cdf0e10cSrcweir             SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
142cdf0e10cSrcweir             SubstitutePlaceholder(tmp, GUID_PLACEHOLDER, iid);
143cdf0e10cSrcweir 
144cdf0e10cSrcweir             if (!SetRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str(), "", ClsidToString(CLSID_INFOTIP_HANDLER).c_str()))
145cdf0e10cSrcweir                 return E_FAIL;
146cdf0e10cSrcweir         }
147cdf0e10cSrcweir         return S_OK;
148cdf0e10cSrcweir     }
149cdf0e10cSrcweir 
150cdf0e10cSrcweir     HRESULT UnregisterInfotipHandler()
151cdf0e10cSrcweir     {
152cdf0e10cSrcweir         std::string iid = ClsidToString(IID_IQueryInfo);
153cdf0e10cSrcweir         std::string tmp;
154cdf0e10cSrcweir 
155cdf0e10cSrcweir         for (size_t i = 0; i < OOFileExtensionTableSize; i++)
156cdf0e10cSrcweir         {
157cdf0e10cSrcweir             tmp = SHELLEX_IID_ENTRY;
158cdf0e10cSrcweir 
159cdf0e10cSrcweir             SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
160cdf0e10cSrcweir             SubstitutePlaceholder(tmp, GUID_PLACEHOLDER, iid);
161cdf0e10cSrcweir 
162cdf0e10cSrcweir             DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str());
163cdf0e10cSrcweir 
164cdf0e10cSrcweir             // if there are no further subkey below .ext\\shellex
165cdf0e10cSrcweir             // delete the whole subkey
166cdf0e10cSrcweir             tmp = SHELLEX_ENTRY;
167cdf0e10cSrcweir             SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
168cdf0e10cSrcweir 
169cdf0e10cSrcweir             bool HasSubKeys = true;
170cdf0e10cSrcweir             if (HasSubkeysRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str(), HasSubKeys) && !HasSubKeys)
171cdf0e10cSrcweir                 DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str());
172cdf0e10cSrcweir         }
173cdf0e10cSrcweir         return UnregisterComComponent(CLSID_INFOTIP_HANDLER);
174cdf0e10cSrcweir     }
175cdf0e10cSrcweir 
176cdf0e10cSrcweir     HRESULT RegisterPropSheetHandler(const char* ModuleFileName)
177cdf0e10cSrcweir     {
178cdf0e10cSrcweir         std::string ExtEntry;
179cdf0e10cSrcweir         std::string FwdKeyEntry;
180cdf0e10cSrcweir 
181cdf0e10cSrcweir         if (FAILED(RegisterComComponent(ModuleFileName, CLSID_PROPERTYSHEET_HANDLER)))
182cdf0e10cSrcweir             return E_FAIL;
183cdf0e10cSrcweir 
184cdf0e10cSrcweir         for (size_t i = 0; i < OOFileExtensionTableSize; i++)
185cdf0e10cSrcweir         {
186cdf0e10cSrcweir             FwdKeyEntry = FORWARD_PROPSHEET_MYPROPSHEET_ENTRY;
187cdf0e10cSrcweir             SubstitutePlaceholder(FwdKeyEntry, FORWARDKEY_PLACEHOLDER, OOFileExtensionTable[i].RegistryForwardKey);
188cdf0e10cSrcweir 
189cdf0e10cSrcweir             if (!SetRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str(), "", ClsidToString(CLSID_PROPERTYSHEET_HANDLER).c_str()))
190cdf0e10cSrcweir                 return E_FAIL;
191cdf0e10cSrcweir         }
192cdf0e10cSrcweir         return S_OK;
193cdf0e10cSrcweir     }
194cdf0e10cSrcweir 
195cdf0e10cSrcweir     HRESULT UnregisterPropSheetHandler()
196cdf0e10cSrcweir     {
197cdf0e10cSrcweir         std::string ExtEntry;
198cdf0e10cSrcweir         std::string FwdKeyEntry;
199cdf0e10cSrcweir 
200cdf0e10cSrcweir         for (size_t i = 0; i < OOFileExtensionTableSize; i++)
201cdf0e10cSrcweir         {
202cdf0e10cSrcweir             FwdKeyEntry = FORWARD_PROPSHEET_MYPROPSHEET_ENTRY;
203cdf0e10cSrcweir             SubstitutePlaceholder(FwdKeyEntry, FORWARDKEY_PLACEHOLDER, OOFileExtensionTable[i].RegistryForwardKey);
204cdf0e10cSrcweir 
205cdf0e10cSrcweir             DeleteRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str());
206cdf0e10cSrcweir 
207cdf0e10cSrcweir             FwdKeyEntry = FORWARD_PROPSHEET_ENTRY;
208cdf0e10cSrcweir             SubstitutePlaceholder(FwdKeyEntry, FORWARDKEY_PLACEHOLDER, OOFileExtensionTable[i].RegistryForwardKey);
209cdf0e10cSrcweir 
210cdf0e10cSrcweir             bool HasSubKeys = true;
211cdf0e10cSrcweir             if (HasSubkeysRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str(), HasSubKeys) && !HasSubKeys)
212cdf0e10cSrcweir                 DeleteRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str());
213cdf0e10cSrcweir 
214cdf0e10cSrcweir             FwdKeyEntry = FORWARD_SHELLEX_ENTRY;
215cdf0e10cSrcweir             SubstitutePlaceholder(FwdKeyEntry, FORWARDKEY_PLACEHOLDER, OOFileExtensionTable[i].RegistryForwardKey);
216cdf0e10cSrcweir 
217cdf0e10cSrcweir             HasSubKeys = true;
218cdf0e10cSrcweir             if (HasSubkeysRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str(), HasSubKeys) && !HasSubKeys)
219cdf0e10cSrcweir                 DeleteRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str());
220cdf0e10cSrcweir         }
221cdf0e10cSrcweir 
222cdf0e10cSrcweir         return UnregisterComComponent(CLSID_PROPERTYSHEET_HANDLER);
223cdf0e10cSrcweir     }
224cdf0e10cSrcweir 
225cdf0e10cSrcweir     HRESULT RegisterThumbviewerHandler(const char* ModuleFileName)
226cdf0e10cSrcweir     {
227cdf0e10cSrcweir         if (FAILED(RegisterComComponent(ModuleFileName, CLSID_THUMBVIEWER_HANDLER)))
228cdf0e10cSrcweir             return E_FAIL;
229cdf0e10cSrcweir 
230cdf0e10cSrcweir         std::string iid = ClsidToString(IID_IExtractImage);
231cdf0e10cSrcweir         std::string tmp;
232cdf0e10cSrcweir 
233cdf0e10cSrcweir         for(size_t i = 0; i < OOFileExtensionTableSize; i++)
234cdf0e10cSrcweir         {
235cdf0e10cSrcweir             tmp = SHELLEX_IID_ENTRY;
236cdf0e10cSrcweir 
237cdf0e10cSrcweir             SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
238cdf0e10cSrcweir             SubstitutePlaceholder(tmp, GUID_PLACEHOLDER, iid);
239cdf0e10cSrcweir 
240cdf0e10cSrcweir             if (!SetRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str(), "", ClsidToString(CLSID_THUMBVIEWER_HANDLER).c_str()))
241cdf0e10cSrcweir                 return E_FAIL;
242cdf0e10cSrcweir         }
243cdf0e10cSrcweir         return S_OK;
244cdf0e10cSrcweir     }
245cdf0e10cSrcweir 
246cdf0e10cSrcweir     HRESULT UnregisterThumbviewerHandler()
247cdf0e10cSrcweir     {
248cdf0e10cSrcweir         std::string iid = ClsidToString(IID_IExtractImage);
249cdf0e10cSrcweir         std::string tmp;
250cdf0e10cSrcweir 
251cdf0e10cSrcweir         for (size_t i = 0; i < OOFileExtensionTableSize; i++)
252cdf0e10cSrcweir         {
253cdf0e10cSrcweir             tmp = SHELLEX_IID_ENTRY;
254cdf0e10cSrcweir 
255cdf0e10cSrcweir             SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
256cdf0e10cSrcweir             SubstitutePlaceholder(tmp, GUID_PLACEHOLDER, iid);
257cdf0e10cSrcweir 
258cdf0e10cSrcweir             DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str());
259cdf0e10cSrcweir 
260cdf0e10cSrcweir             // if there are no further subkey below .ext\\shellex
261cdf0e10cSrcweir             // delete the whole subkey
262cdf0e10cSrcweir             tmp = SHELLEX_ENTRY;
263cdf0e10cSrcweir             SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
264cdf0e10cSrcweir 
265cdf0e10cSrcweir             bool HasSubKeys = true;
266cdf0e10cSrcweir             if (HasSubkeysRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str(), HasSubKeys) && !HasSubKeys)
267cdf0e10cSrcweir                 DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str());
268cdf0e10cSrcweir         }
269cdf0e10cSrcweir         return UnregisterComComponent(CLSID_THUMBVIEWER_HANDLER);
270cdf0e10cSrcweir     }
271cdf0e10cSrcweir 
272cdf0e10cSrcweir 	/** Approving/Unapproving the Shell Extension, it's important under Windows
273cdf0e10cSrcweir 	    NT/2000/XP, see MSDN: Creating Shell Extension Handlers */
274cdf0e10cSrcweir 	HRESULT ApproveShellExtension(CLSID clsid, const std::wstring& Description)
275cdf0e10cSrcweir 	{
276cdf0e10cSrcweir 		bool bRet = SetRegistryKey(
277cdf0e10cSrcweir 			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 	}
284cdf0e10cSrcweir 
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 
313cdf0e10cSrcweir extern "C" STDAPI DllRegisterServer()
314cdf0e10cSrcweir {
315cdf0e10cSrcweir 	TCHAR ModuleFileName[MAX_PATH];
316cdf0e10cSrcweir 
317cdf0e10cSrcweir 	GetModuleFileName(
318cdf0e10cSrcweir 		GetModuleHandle(MODULE_NAME),
319cdf0e10cSrcweir 		ModuleFileName,
320cdf0e10cSrcweir 		sizeof(ModuleFileName));
321cdf0e10cSrcweir 
322cdf0e10cSrcweir 	std::string module_path = WStringToString(ModuleFileName);
323cdf0e10cSrcweir 	HRESULT hr = S_OK;
324cdf0e10cSrcweir 
325cdf0e10cSrcweir 	if (SUCCEEDED(RegisterColumnHandler(module_path.c_str())))
326cdf0e10cSrcweir 	    ApproveShellExtension(CLSID_COLUMN_HANDLER, COLUMN_HANDLER_DESCRIPTIVE_NAME);
327cdf0e10cSrcweir     else
328cdf0e10cSrcweir         hr = E_FAIL;
329cdf0e10cSrcweir 
330cdf0e10cSrcweir 	if (SUCCEEDED(RegisterInfotipHandler(module_path.c_str())))
331cdf0e10cSrcweir 	    ApproveShellExtension(CLSID_INFOTIP_HANDLER, INFOTIP_HANDLER_DESCRIPTIVE_NAME);
332cdf0e10cSrcweir     else
333cdf0e10cSrcweir         hr = E_FAIL;
334cdf0e10cSrcweir 
335cdf0e10cSrcweir 	if (SUCCEEDED(RegisterPropSheetHandler(module_path.c_str())))
336cdf0e10cSrcweir 	    ApproveShellExtension(CLSID_PROPERTYSHEET_HANDLER, PROPSHEET_HANDLER_DESCRIPTIVE_NAME);
337cdf0e10cSrcweir     else
338cdf0e10cSrcweir         hr = E_FAIL;
339cdf0e10cSrcweir 
340cdf0e10cSrcweir     if (SUCCEEDED(RegisterThumbviewerHandler(module_path.c_str())))
341cdf0e10cSrcweir         ApproveShellExtension(CLSID_THUMBVIEWER_HANDLER, THUMBVIEWER_HANDLER_DESCRIPTIVAE_NAME);
342cdf0e10cSrcweir     else
343cdf0e10cSrcweir         hr = E_FAIL;
344cdf0e10cSrcweir 
345cdf0e10cSrcweir 	// notify the Shell that something has changed
346cdf0e10cSrcweir 	SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
347cdf0e10cSrcweir 
348cdf0e10cSrcweir 	return hr;
349cdf0e10cSrcweir }
350cdf0e10cSrcweir 
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 
370cdf0e10cSrcweir     if (FAILED(UnregisterThumbviewerHandler()))
371cdf0e10cSrcweir         hr = E_FAIL;
372cdf0e10cSrcweir 
373cdf0e10cSrcweir     UnapproveShellExtension(CLSID_THUMBVIEWER_HANDLER);
374cdf0e10cSrcweir 
375cdf0e10cSrcweir 	// notify the Shell that something has changed
376cdf0e10cSrcweir 	SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
377cdf0e10cSrcweir 
378cdf0e10cSrcweir 	return hr;
379cdf0e10cSrcweir }
380cdf0e10cSrcweir 
381cdf0e10cSrcweir extern "C" STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void** ppv)
382cdf0e10cSrcweir {
383cdf0e10cSrcweir 	*ppv = 0;
384cdf0e10cSrcweir 
385cdf0e10cSrcweir 	if ((rclsid != CLSID_INFOTIP_HANDLER) &&
386cdf0e10cSrcweir 	    (rclsid != CLSID_COLUMN_HANDLER) &&
387cdf0e10cSrcweir 	    (rclsid != CLSID_PROPERTYSHEET_HANDLER) &&
388cdf0e10cSrcweir 	    (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 )
395cdf0e10cSrcweir 	    OutputDebugStringFormat( "DllGetClassObject: Create CLSID_INFOTIP_HANDLER\n" );
396cdf0e10cSrcweir 	else if ( rclsid == CLSID_COLUMN_HANDLER )
397cdf0e10cSrcweir 	    OutputDebugStringFormat( "DllGetClassObject: Create CLSID_COLUMN_HANDLER\n" );
398cdf0e10cSrcweir 	else if ( rclsid == CLSID_PROPERTYSHEET_HANDLER )
399cdf0e10cSrcweir 	    OutputDebugStringFormat( "DllGetClassObject: Create CLSID_PROPERTYSHEET_HANDLER\n" );
400cdf0e10cSrcweir 	else if ( rclsid == CLSID_THUMBVIEWER_HANDLER )
401cdf0e10cSrcweir 	    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 
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 
419cdf0e10cSrcweir BOOL WINAPI DllMain(HINSTANCE hInst, ULONG /*ul_reason_for_call*/, LPVOID /*lpReserved*/)
420cdf0e10cSrcweir {
421cdf0e10cSrcweir     g_hModule = hInst;
422cdf0e10cSrcweir     return TRUE;
423cdf0e10cSrcweir }
424