1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_shell.hxx"
26*b1cdbd2cSJim Jagielski #include "internal/config.hxx"
27*b1cdbd2cSJim Jagielski #include "internal/global.hxx"
28*b1cdbd2cSJim Jagielski #include "internal/shlxthdl.hxx"
29*b1cdbd2cSJim Jagielski #include "classfactory.hxx"
30*b1cdbd2cSJim Jagielski #include "internal/registry.hxx"
31*b1cdbd2cSJim Jagielski #include "internal/fileextensions.hxx"
32*b1cdbd2cSJim Jagielski #include "internal/utilities.hxx"
33*b1cdbd2cSJim Jagielski 
34*b1cdbd2cSJim Jagielski #include <tchar.h>
35*b1cdbd2cSJim Jagielski #include <string>
36*b1cdbd2cSJim Jagielski #include <shlobj.h>
37*b1cdbd2cSJim Jagielski 
38*b1cdbd2cSJim Jagielski //---------------------------
39*b1cdbd2cSJim Jagielski // Module global
40*b1cdbd2cSJim Jagielski //---------------------------
41*b1cdbd2cSJim Jagielski long g_DllRefCnt = 0;
42*b1cdbd2cSJim Jagielski HINSTANCE g_hModule = NULL;
43*b1cdbd2cSJim Jagielski 
44*b1cdbd2cSJim Jagielski namespace /* private */
45*b1cdbd2cSJim Jagielski {
46*b1cdbd2cSJim Jagielski 	const char* GUID_PLACEHOLDER       = "{GUID}";
47*b1cdbd2cSJim Jagielski 	const char* EXTENSION_PLACEHOLDER  = "{EXT}";
48*b1cdbd2cSJim Jagielski 	const char* FORWARDKEY_PLACEHOLDER = "{FWDKEY}";
49*b1cdbd2cSJim Jagielski 
50*b1cdbd2cSJim Jagielski 	const char* CLSID_ENTRY                         = "CLSID\\{GUID}\\InProcServer32";
51*b1cdbd2cSJim Jagielski 	const char* SHELLEX_IID_ENTRY                   = "{EXT}\\shellex\\{GUID}";
52*b1cdbd2cSJim Jagielski 	const char* SHELLEX_ENTRY			            = "{EXT}\\shellex";
53*b1cdbd2cSJim Jagielski 	const char* PROPSHEET_ENTRY                     = "{EXT}\\CLSID\\{GUID}\\InProcServer32";
54*b1cdbd2cSJim Jagielski 	const char* EXTENSION_CLSID			            = "{EXT}\\CLSID";
55*b1cdbd2cSJim Jagielski 	const char* EXTENSION_CLSID_GUID				= "{EXT}\\CLSID\\{GUID}";
56*b1cdbd2cSJim Jagielski 	const char* FORWARD_PROPSHEET_MYPROPSHEET_ENTRY = "{FWDKEY}\\shellex\\PropertySheetHandlers\\MyPropSheet1";
57*b1cdbd2cSJim Jagielski 	const char* FORWARD_PROPSHEET_ENTRY             = "{FWDKEY}\\shellex\\PropertySheetHandlers";
58*b1cdbd2cSJim Jagielski 	const char* FORWARD_SHELLEX_ENTRY				= "{FWDKEY}\\shellex";
59*b1cdbd2cSJim Jagielski 
60*b1cdbd2cSJim Jagielski 	const char* SHELL_EXTENSION_APPROVED_KEY_NAME   = "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved";
61*b1cdbd2cSJim Jagielski 
62*b1cdbd2cSJim Jagielski     //---------------------------
63*b1cdbd2cSJim Jagielski     // "String Placeholder" ->
64*b1cdbd2cSJim Jagielski     // "String Replacement"
65*b1cdbd2cSJim Jagielski     //---------------------------
SubstitutePlaceholder(std::string & String,const std::string & Placeholder,const std::string & Replacement)66*b1cdbd2cSJim Jagielski     void SubstitutePlaceholder(std::string& String, const std::string& Placeholder, const std::string& Replacement)
67*b1cdbd2cSJim Jagielski     {
68*b1cdbd2cSJim Jagielski         std::string::size_type idx = String.find(Placeholder);
69*b1cdbd2cSJim Jagielski         std::string::size_type len = Placeholder.length();
70*b1cdbd2cSJim Jagielski 
71*b1cdbd2cSJim Jagielski         while (std::string::npos != idx)
72*b1cdbd2cSJim Jagielski         {
73*b1cdbd2cSJim Jagielski             String.replace(idx, len, Replacement);
74*b1cdbd2cSJim Jagielski             idx = String.find(Placeholder);
75*b1cdbd2cSJim Jagielski         }
76*b1cdbd2cSJim Jagielski     }
77*b1cdbd2cSJim Jagielski 
78*b1cdbd2cSJim Jagielski     /* Make the registry entry
79*b1cdbd2cSJim Jagielski        HKCR\CLSID\{GUID}
80*b1cdbd2cSJim Jagielski     		InProcServer32 = Path\shlxthdl.dll
81*b1cdbd2cSJim Jagielski     			ThreadingModel = Apartment
82*b1cdbd2cSJim Jagielski     */
RegisterComComponent(const char * FilePath,const CLSID & Guid)83*b1cdbd2cSJim Jagielski     HRESULT RegisterComComponent(const char* FilePath, const CLSID& Guid)
84*b1cdbd2cSJim Jagielski     {
85*b1cdbd2cSJim Jagielski         std::string ClsidEntry = CLSID_ENTRY;
86*b1cdbd2cSJim Jagielski         SubstitutePlaceholder(ClsidEntry, GUID_PLACEHOLDER, ClsidToString(Guid));
87*b1cdbd2cSJim Jagielski 
88*b1cdbd2cSJim Jagielski         if (!SetRegistryKey(HKEY_CLASSES_ROOT, ClsidEntry.c_str(), "", FilePath))
89*b1cdbd2cSJim Jagielski             return E_FAIL;
90*b1cdbd2cSJim Jagielski 
91*b1cdbd2cSJim Jagielski         if (!SetRegistryKey(HKEY_CLASSES_ROOT, ClsidEntry.c_str(), "ThreadingModel", "Apartment"))
92*b1cdbd2cSJim Jagielski             return E_FAIL;
93*b1cdbd2cSJim Jagielski 
94*b1cdbd2cSJim Jagielski         return S_OK;
95*b1cdbd2cSJim Jagielski     }
96*b1cdbd2cSJim Jagielski 
UnregisterComComponent(const CLSID & Guid)97*b1cdbd2cSJim Jagielski     HRESULT UnregisterComComponent(const CLSID& Guid)
98*b1cdbd2cSJim Jagielski     {
99*b1cdbd2cSJim Jagielski         std::string tmp = "CLSID\\";
100*b1cdbd2cSJim Jagielski         tmp += ClsidToString(Guid);
101*b1cdbd2cSJim Jagielski         return DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str()) ? S_OK : E_FAIL;
102*b1cdbd2cSJim Jagielski     }
103*b1cdbd2cSJim Jagielski 
RegisterColumnHandler(const char * ModuleFileName)104*b1cdbd2cSJim Jagielski     HRESULT RegisterColumnHandler(const char* ModuleFileName)
105*b1cdbd2cSJim Jagielski     {
106*b1cdbd2cSJim Jagielski         if (FAILED(RegisterComComponent(ModuleFileName, CLSID_COLUMN_HANDLER)))
107*b1cdbd2cSJim Jagielski             return E_FAIL;
108*b1cdbd2cSJim Jagielski 
109*b1cdbd2cSJim Jagielski         std::string tmp = "Folder\\shellex\\ColumnHandlers\\";
110*b1cdbd2cSJim Jagielski         tmp += ClsidToString(CLSID_COLUMN_HANDLER);
111*b1cdbd2cSJim Jagielski 
112*b1cdbd2cSJim Jagielski         return SetRegistryKey(
113*b1cdbd2cSJim Jagielski 			HKEY_CLASSES_ROOT,
114*b1cdbd2cSJim Jagielski 			tmp.c_str(),
115*b1cdbd2cSJim Jagielski 			"",
116*b1cdbd2cSJim Jagielski 			WStringToString(COLUMN_HANDLER_DESCRIPTIVE_NAME).c_str()) ? S_OK : E_FAIL;
117*b1cdbd2cSJim Jagielski     }
118*b1cdbd2cSJim Jagielski 
UnregisterColumnHandler()119*b1cdbd2cSJim Jagielski     HRESULT UnregisterColumnHandler()
120*b1cdbd2cSJim Jagielski     {
121*b1cdbd2cSJim Jagielski         std::string tmp = "Folder\\shellex\\ColumnHandlers\\";
122*b1cdbd2cSJim Jagielski         tmp += ClsidToString(CLSID_COLUMN_HANDLER);
123*b1cdbd2cSJim Jagielski 
124*b1cdbd2cSJim Jagielski         if (!DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str()))
125*b1cdbd2cSJim Jagielski             return E_FAIL;
126*b1cdbd2cSJim Jagielski 
127*b1cdbd2cSJim Jagielski         return UnregisterComComponent(CLSID_COLUMN_HANDLER);
128*b1cdbd2cSJim Jagielski     }
129*b1cdbd2cSJim Jagielski 
RegisterInfotipHandler(const char * ModuleFileName)130*b1cdbd2cSJim Jagielski     HRESULT RegisterInfotipHandler(const char* ModuleFileName)
131*b1cdbd2cSJim Jagielski     {
132*b1cdbd2cSJim Jagielski         if (FAILED(RegisterComComponent(ModuleFileName, CLSID_INFOTIP_HANDLER)))
133*b1cdbd2cSJim Jagielski             return E_FAIL;
134*b1cdbd2cSJim Jagielski 
135*b1cdbd2cSJim Jagielski         std::string iid = ClsidToString(IID_IQueryInfo);
136*b1cdbd2cSJim Jagielski         std::string tmp;
137*b1cdbd2cSJim Jagielski 
138*b1cdbd2cSJim Jagielski         for(size_t i = 0; i < OOFileExtensionTableSize; i++)
139*b1cdbd2cSJim Jagielski         {
140*b1cdbd2cSJim Jagielski             tmp = SHELLEX_IID_ENTRY;
141*b1cdbd2cSJim Jagielski             SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
142*b1cdbd2cSJim Jagielski             SubstitutePlaceholder(tmp, GUID_PLACEHOLDER, iid);
143*b1cdbd2cSJim Jagielski 
144*b1cdbd2cSJim Jagielski             if (!SetRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str(), "", ClsidToString(CLSID_INFOTIP_HANDLER).c_str()))
145*b1cdbd2cSJim Jagielski                 return E_FAIL;
146*b1cdbd2cSJim Jagielski         }
147*b1cdbd2cSJim Jagielski         return S_OK;
148*b1cdbd2cSJim Jagielski     }
149*b1cdbd2cSJim Jagielski 
UnregisterInfotipHandler()150*b1cdbd2cSJim Jagielski     HRESULT UnregisterInfotipHandler()
151*b1cdbd2cSJim Jagielski     {
152*b1cdbd2cSJim Jagielski         std::string iid = ClsidToString(IID_IQueryInfo);
153*b1cdbd2cSJim Jagielski         std::string tmp;
154*b1cdbd2cSJim Jagielski 
155*b1cdbd2cSJim Jagielski         for (size_t i = 0; i < OOFileExtensionTableSize; i++)
156*b1cdbd2cSJim Jagielski         {
157*b1cdbd2cSJim Jagielski             tmp = SHELLEX_IID_ENTRY;
158*b1cdbd2cSJim Jagielski 
159*b1cdbd2cSJim Jagielski             SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
160*b1cdbd2cSJim Jagielski             SubstitutePlaceholder(tmp, GUID_PLACEHOLDER, iid);
161*b1cdbd2cSJim Jagielski 
162*b1cdbd2cSJim Jagielski             DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str());
163*b1cdbd2cSJim Jagielski 
164*b1cdbd2cSJim Jagielski             // if there are no further subkey below .ext\\shellex
165*b1cdbd2cSJim Jagielski             // delete the whole subkey
166*b1cdbd2cSJim Jagielski             tmp = SHELLEX_ENTRY;
167*b1cdbd2cSJim Jagielski             SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
168*b1cdbd2cSJim Jagielski 
169*b1cdbd2cSJim Jagielski             bool HasSubKeys = true;
170*b1cdbd2cSJim Jagielski             if (HasSubkeysRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str(), HasSubKeys) && !HasSubKeys)
171*b1cdbd2cSJim Jagielski                 DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str());
172*b1cdbd2cSJim Jagielski         }
173*b1cdbd2cSJim Jagielski         return UnregisterComComponent(CLSID_INFOTIP_HANDLER);
174*b1cdbd2cSJim Jagielski     }
175*b1cdbd2cSJim Jagielski 
RegisterPropSheetHandler(const char * ModuleFileName)176*b1cdbd2cSJim Jagielski     HRESULT RegisterPropSheetHandler(const char* ModuleFileName)
177*b1cdbd2cSJim Jagielski     {
178*b1cdbd2cSJim Jagielski         std::string ExtEntry;
179*b1cdbd2cSJim Jagielski         std::string FwdKeyEntry;
180*b1cdbd2cSJim Jagielski 
181*b1cdbd2cSJim Jagielski         if (FAILED(RegisterComComponent(ModuleFileName, CLSID_PROPERTYSHEET_HANDLER)))
182*b1cdbd2cSJim Jagielski             return E_FAIL;
183*b1cdbd2cSJim Jagielski 
184*b1cdbd2cSJim Jagielski         for (size_t i = 0; i < OOFileExtensionTableSize; i++)
185*b1cdbd2cSJim Jagielski         {
186*b1cdbd2cSJim Jagielski             FwdKeyEntry = FORWARD_PROPSHEET_MYPROPSHEET_ENTRY;
187*b1cdbd2cSJim Jagielski             SubstitutePlaceholder(FwdKeyEntry, FORWARDKEY_PLACEHOLDER, OOFileExtensionTable[i].RegistryForwardKey);
188*b1cdbd2cSJim Jagielski 
189*b1cdbd2cSJim Jagielski             if (!SetRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str(), "", ClsidToString(CLSID_PROPERTYSHEET_HANDLER).c_str()))
190*b1cdbd2cSJim Jagielski                 return E_FAIL;
191*b1cdbd2cSJim Jagielski         }
192*b1cdbd2cSJim Jagielski         return S_OK;
193*b1cdbd2cSJim Jagielski     }
194*b1cdbd2cSJim Jagielski 
UnregisterPropSheetHandler()195*b1cdbd2cSJim Jagielski     HRESULT UnregisterPropSheetHandler()
196*b1cdbd2cSJim Jagielski     {
197*b1cdbd2cSJim Jagielski         std::string ExtEntry;
198*b1cdbd2cSJim Jagielski         std::string FwdKeyEntry;
199*b1cdbd2cSJim Jagielski 
200*b1cdbd2cSJim Jagielski         for (size_t i = 0; i < OOFileExtensionTableSize; i++)
201*b1cdbd2cSJim Jagielski         {
202*b1cdbd2cSJim Jagielski             FwdKeyEntry = FORWARD_PROPSHEET_MYPROPSHEET_ENTRY;
203*b1cdbd2cSJim Jagielski             SubstitutePlaceholder(FwdKeyEntry, FORWARDKEY_PLACEHOLDER, OOFileExtensionTable[i].RegistryForwardKey);
204*b1cdbd2cSJim Jagielski 
205*b1cdbd2cSJim Jagielski             DeleteRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str());
206*b1cdbd2cSJim Jagielski 
207*b1cdbd2cSJim Jagielski             FwdKeyEntry = FORWARD_PROPSHEET_ENTRY;
208*b1cdbd2cSJim Jagielski             SubstitutePlaceholder(FwdKeyEntry, FORWARDKEY_PLACEHOLDER, OOFileExtensionTable[i].RegistryForwardKey);
209*b1cdbd2cSJim Jagielski 
210*b1cdbd2cSJim Jagielski             bool HasSubKeys = true;
211*b1cdbd2cSJim Jagielski             if (HasSubkeysRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str(), HasSubKeys) && !HasSubKeys)
212*b1cdbd2cSJim Jagielski                 DeleteRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str());
213*b1cdbd2cSJim Jagielski 
214*b1cdbd2cSJim Jagielski             FwdKeyEntry = FORWARD_SHELLEX_ENTRY;
215*b1cdbd2cSJim Jagielski             SubstitutePlaceholder(FwdKeyEntry, FORWARDKEY_PLACEHOLDER, OOFileExtensionTable[i].RegistryForwardKey);
216*b1cdbd2cSJim Jagielski 
217*b1cdbd2cSJim Jagielski             HasSubKeys = true;
218*b1cdbd2cSJim Jagielski             if (HasSubkeysRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str(), HasSubKeys) && !HasSubKeys)
219*b1cdbd2cSJim Jagielski                 DeleteRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str());
220*b1cdbd2cSJim Jagielski         }
221*b1cdbd2cSJim Jagielski 
222*b1cdbd2cSJim Jagielski         return UnregisterComComponent(CLSID_PROPERTYSHEET_HANDLER);
223*b1cdbd2cSJim Jagielski     }
224*b1cdbd2cSJim Jagielski 
RegisterThumbviewerHandler(const char * ModuleFileName)225*b1cdbd2cSJim Jagielski     HRESULT RegisterThumbviewerHandler(const char* ModuleFileName)
226*b1cdbd2cSJim Jagielski     {
227*b1cdbd2cSJim Jagielski         if (FAILED(RegisterComComponent(ModuleFileName, CLSID_THUMBVIEWER_HANDLER)))
228*b1cdbd2cSJim Jagielski             return E_FAIL;
229*b1cdbd2cSJim Jagielski 
230*b1cdbd2cSJim Jagielski         std::string iid = ClsidToString(IID_IExtractImage);
231*b1cdbd2cSJim Jagielski         std::string tmp;
232*b1cdbd2cSJim Jagielski 
233*b1cdbd2cSJim Jagielski         for(size_t i = 0; i < OOFileExtensionTableSize; i++)
234*b1cdbd2cSJim Jagielski         {
235*b1cdbd2cSJim Jagielski             tmp = SHELLEX_IID_ENTRY;
236*b1cdbd2cSJim Jagielski 
237*b1cdbd2cSJim Jagielski             SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
238*b1cdbd2cSJim Jagielski             SubstitutePlaceholder(tmp, GUID_PLACEHOLDER, iid);
239*b1cdbd2cSJim Jagielski 
240*b1cdbd2cSJim Jagielski             if (!SetRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str(), "", ClsidToString(CLSID_THUMBVIEWER_HANDLER).c_str()))
241*b1cdbd2cSJim Jagielski                 return E_FAIL;
242*b1cdbd2cSJim Jagielski         }
243*b1cdbd2cSJim Jagielski         return S_OK;
244*b1cdbd2cSJim Jagielski     }
245*b1cdbd2cSJim Jagielski 
UnregisterThumbviewerHandler()246*b1cdbd2cSJim Jagielski     HRESULT UnregisterThumbviewerHandler()
247*b1cdbd2cSJim Jagielski     {
248*b1cdbd2cSJim Jagielski         std::string iid = ClsidToString(IID_IExtractImage);
249*b1cdbd2cSJim Jagielski         std::string tmp;
250*b1cdbd2cSJim Jagielski 
251*b1cdbd2cSJim Jagielski         for (size_t i = 0; i < OOFileExtensionTableSize; i++)
252*b1cdbd2cSJim Jagielski         {
253*b1cdbd2cSJim Jagielski             tmp = SHELLEX_IID_ENTRY;
254*b1cdbd2cSJim Jagielski 
255*b1cdbd2cSJim Jagielski             SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
256*b1cdbd2cSJim Jagielski             SubstitutePlaceholder(tmp, GUID_PLACEHOLDER, iid);
257*b1cdbd2cSJim Jagielski 
258*b1cdbd2cSJim Jagielski             DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str());
259*b1cdbd2cSJim Jagielski 
260*b1cdbd2cSJim Jagielski             // if there are no further subkey below .ext\\shellex
261*b1cdbd2cSJim Jagielski             // delete the whole subkey
262*b1cdbd2cSJim Jagielski             tmp = SHELLEX_ENTRY;
263*b1cdbd2cSJim Jagielski             SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
264*b1cdbd2cSJim Jagielski 
265*b1cdbd2cSJim Jagielski             bool HasSubKeys = true;
266*b1cdbd2cSJim Jagielski             if (HasSubkeysRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str(), HasSubKeys) && !HasSubKeys)
267*b1cdbd2cSJim Jagielski                 DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str());
268*b1cdbd2cSJim Jagielski         }
269*b1cdbd2cSJim Jagielski         return UnregisterComComponent(CLSID_THUMBVIEWER_HANDLER);
270*b1cdbd2cSJim Jagielski     }
271*b1cdbd2cSJim Jagielski 
272*b1cdbd2cSJim Jagielski 	/** Approving/Unapproving the Shell Extension, it's important under Windows
273*b1cdbd2cSJim Jagielski 	    NT/2000/XP, see MSDN: Creating Shell Extension Handlers */
ApproveShellExtension(CLSID clsid,const std::wstring & Description)274*b1cdbd2cSJim Jagielski 	HRESULT ApproveShellExtension(CLSID clsid, const std::wstring& Description)
275*b1cdbd2cSJim Jagielski 	{
276*b1cdbd2cSJim Jagielski 		bool bRet = SetRegistryKey(
277*b1cdbd2cSJim Jagielski 			HKEY_LOCAL_MACHINE,
278*b1cdbd2cSJim Jagielski 			SHELL_EXTENSION_APPROVED_KEY_NAME,
279*b1cdbd2cSJim Jagielski 			ClsidToString(clsid).c_str(),
280*b1cdbd2cSJim Jagielski 			WStringToString(Description).c_str());
281*b1cdbd2cSJim Jagielski 
282*b1cdbd2cSJim Jagielski 		return bRet ? S_OK : E_FAIL;
283*b1cdbd2cSJim Jagielski 	}
284*b1cdbd2cSJim Jagielski 
UnapproveShellExtension(CLSID Clsid)285*b1cdbd2cSJim Jagielski 	HRESULT UnapproveShellExtension(CLSID Clsid)
286*b1cdbd2cSJim Jagielski 	{
287*b1cdbd2cSJim Jagielski 		HKEY hkey;
288*b1cdbd2cSJim Jagielski 
289*b1cdbd2cSJim Jagielski 		LONG rc = RegOpenKeyA(
290*b1cdbd2cSJim Jagielski 			HKEY_LOCAL_MACHINE,
291*b1cdbd2cSJim Jagielski 			SHELL_EXTENSION_APPROVED_KEY_NAME,
292*b1cdbd2cSJim Jagielski 			&hkey);
293*b1cdbd2cSJim Jagielski 
294*b1cdbd2cSJim Jagielski 		if (ERROR_SUCCESS == rc)
295*b1cdbd2cSJim Jagielski 		{
296*b1cdbd2cSJim Jagielski 			rc = RegDeleteValueA(
297*b1cdbd2cSJim Jagielski 				hkey,
298*b1cdbd2cSJim Jagielski 				ClsidToString(Clsid).c_str());
299*b1cdbd2cSJim Jagielski 
300*b1cdbd2cSJim Jagielski 			rc = RegCloseKey(hkey);
301*b1cdbd2cSJim Jagielski 		}
302*b1cdbd2cSJim Jagielski 
303*b1cdbd2cSJim Jagielski 		return rc == ERROR_SUCCESS ? S_OK : E_FAIL;
304*b1cdbd2cSJim Jagielski 	}
305*b1cdbd2cSJim Jagielski 
306*b1cdbd2cSJim Jagielski } // namespace /* private */
307*b1cdbd2cSJim Jagielski 
308*b1cdbd2cSJim Jagielski 
309*b1cdbd2cSJim Jagielski //---------------------
310*b1cdbd2cSJim Jagielski // COM exports
311*b1cdbd2cSJim Jagielski //---------------------
312*b1cdbd2cSJim Jagielski 
DllRegisterServer()313*b1cdbd2cSJim Jagielski extern "C" STDAPI DllRegisterServer()
314*b1cdbd2cSJim Jagielski {
315*b1cdbd2cSJim Jagielski 	TCHAR ModuleFileName[MAX_PATH];
316*b1cdbd2cSJim Jagielski 
317*b1cdbd2cSJim Jagielski 	GetModuleFileName(
318*b1cdbd2cSJim Jagielski 		GetModuleHandle(MODULE_NAME),
319*b1cdbd2cSJim Jagielski 		ModuleFileName,
320*b1cdbd2cSJim Jagielski 		sizeof(ModuleFileName));
321*b1cdbd2cSJim Jagielski 
322*b1cdbd2cSJim Jagielski 	std::string module_path = WStringToString(ModuleFileName);
323*b1cdbd2cSJim Jagielski 	HRESULT hr = S_OK;
324*b1cdbd2cSJim Jagielski 
325*b1cdbd2cSJim Jagielski 	if (SUCCEEDED(RegisterColumnHandler(module_path.c_str())))
326*b1cdbd2cSJim Jagielski 	    ApproveShellExtension(CLSID_COLUMN_HANDLER, COLUMN_HANDLER_DESCRIPTIVE_NAME);
327*b1cdbd2cSJim Jagielski     else
328*b1cdbd2cSJim Jagielski         hr = E_FAIL;
329*b1cdbd2cSJim Jagielski 
330*b1cdbd2cSJim Jagielski 	if (SUCCEEDED(RegisterInfotipHandler(module_path.c_str())))
331*b1cdbd2cSJim Jagielski 	    ApproveShellExtension(CLSID_INFOTIP_HANDLER, INFOTIP_HANDLER_DESCRIPTIVE_NAME);
332*b1cdbd2cSJim Jagielski     else
333*b1cdbd2cSJim Jagielski         hr = E_FAIL;
334*b1cdbd2cSJim Jagielski 
335*b1cdbd2cSJim Jagielski 	if (SUCCEEDED(RegisterPropSheetHandler(module_path.c_str())))
336*b1cdbd2cSJim Jagielski 	    ApproveShellExtension(CLSID_PROPERTYSHEET_HANDLER, PROPSHEET_HANDLER_DESCRIPTIVE_NAME);
337*b1cdbd2cSJim Jagielski     else
338*b1cdbd2cSJim Jagielski         hr = E_FAIL;
339*b1cdbd2cSJim Jagielski 
340*b1cdbd2cSJim Jagielski     if (SUCCEEDED(RegisterThumbviewerHandler(module_path.c_str())))
341*b1cdbd2cSJim Jagielski         ApproveShellExtension(CLSID_THUMBVIEWER_HANDLER, THUMBVIEWER_HANDLER_DESCRIPTIVAE_NAME);
342*b1cdbd2cSJim Jagielski     else
343*b1cdbd2cSJim Jagielski         hr = E_FAIL;
344*b1cdbd2cSJim Jagielski 
345*b1cdbd2cSJim Jagielski 	// notify the Shell that something has changed
346*b1cdbd2cSJim Jagielski 	SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
347*b1cdbd2cSJim Jagielski 
348*b1cdbd2cSJim Jagielski 	return hr;
349*b1cdbd2cSJim Jagielski }
350*b1cdbd2cSJim Jagielski 
DllUnregisterServer()351*b1cdbd2cSJim Jagielski extern "C" STDAPI DllUnregisterServer()
352*b1cdbd2cSJim Jagielski {
353*b1cdbd2cSJim Jagielski 	HRESULT hr = S_OK;
354*b1cdbd2cSJim Jagielski 
355*b1cdbd2cSJim Jagielski 	if (FAILED(UnregisterColumnHandler()))
356*b1cdbd2cSJim Jagielski 		hr = E_FAIL;
357*b1cdbd2cSJim Jagielski 
358*b1cdbd2cSJim Jagielski 	UnapproveShellExtension(CLSID_COLUMN_HANDLER);
359*b1cdbd2cSJim Jagielski 
360*b1cdbd2cSJim Jagielski 	if (FAILED(UnregisterInfotipHandler()))
361*b1cdbd2cSJim Jagielski 		hr = E_FAIL;
362*b1cdbd2cSJim Jagielski 
363*b1cdbd2cSJim Jagielski 	UnapproveShellExtension(CLSID_INFOTIP_HANDLER);
364*b1cdbd2cSJim Jagielski 
365*b1cdbd2cSJim Jagielski 	if (FAILED(UnregisterPropSheetHandler()))
366*b1cdbd2cSJim Jagielski 		hr = E_FAIL;
367*b1cdbd2cSJim Jagielski 
368*b1cdbd2cSJim Jagielski 	UnapproveShellExtension(CLSID_PROPERTYSHEET_HANDLER);
369*b1cdbd2cSJim Jagielski 
370*b1cdbd2cSJim Jagielski     if (FAILED(UnregisterThumbviewerHandler()))
371*b1cdbd2cSJim Jagielski         hr = E_FAIL;
372*b1cdbd2cSJim Jagielski 
373*b1cdbd2cSJim Jagielski     UnapproveShellExtension(CLSID_THUMBVIEWER_HANDLER);
374*b1cdbd2cSJim Jagielski 
375*b1cdbd2cSJim Jagielski 	// notify the Shell that something has changed
376*b1cdbd2cSJim Jagielski 	SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
377*b1cdbd2cSJim Jagielski 
378*b1cdbd2cSJim Jagielski 	return hr;
379*b1cdbd2cSJim Jagielski }
380*b1cdbd2cSJim Jagielski 
DllGetClassObject(REFCLSID rclsid,REFIID riid,void ** ppv)381*b1cdbd2cSJim Jagielski extern "C" STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void** ppv)
382*b1cdbd2cSJim Jagielski {
383*b1cdbd2cSJim Jagielski 	*ppv = 0;
384*b1cdbd2cSJim Jagielski 
385*b1cdbd2cSJim Jagielski 	if ((rclsid != CLSID_INFOTIP_HANDLER) &&
386*b1cdbd2cSJim Jagielski 	    (rclsid != CLSID_COLUMN_HANDLER) &&
387*b1cdbd2cSJim Jagielski 	    (rclsid != CLSID_PROPERTYSHEET_HANDLER) &&
388*b1cdbd2cSJim Jagielski 	    (rclsid != CLSID_THUMBVIEWER_HANDLER))
389*b1cdbd2cSJim Jagielski 		return CLASS_E_CLASSNOTAVAILABLE;
390*b1cdbd2cSJim Jagielski 
391*b1cdbd2cSJim Jagielski 	if ((riid != IID_IUnknown) && (riid != IID_IClassFactory))
392*b1cdbd2cSJim Jagielski 		return E_NOINTERFACE;
393*b1cdbd2cSJim Jagielski 
394*b1cdbd2cSJim Jagielski 	if ( rclsid == CLSID_INFOTIP_HANDLER )
395*b1cdbd2cSJim Jagielski 	    OutputDebugStringFormat( "DllGetClassObject: Create CLSID_INFOTIP_HANDLER\n" );
396*b1cdbd2cSJim Jagielski 	else if ( rclsid == CLSID_COLUMN_HANDLER )
397*b1cdbd2cSJim Jagielski 	    OutputDebugStringFormat( "DllGetClassObject: Create CLSID_COLUMN_HANDLER\n" );
398*b1cdbd2cSJim Jagielski 	else if ( rclsid == CLSID_PROPERTYSHEET_HANDLER )
399*b1cdbd2cSJim Jagielski 	    OutputDebugStringFormat( "DllGetClassObject: Create CLSID_PROPERTYSHEET_HANDLER\n" );
400*b1cdbd2cSJim Jagielski 	else if ( rclsid == CLSID_THUMBVIEWER_HANDLER )
401*b1cdbd2cSJim Jagielski 	    OutputDebugStringFormat( "DllGetClassObject: Create CLSID_THUMBVIEWER_HANDLER\n" );
402*b1cdbd2cSJim Jagielski 
403*b1cdbd2cSJim Jagielski 	IUnknown* pUnk = new CClassFactory(rclsid);
404*b1cdbd2cSJim Jagielski 	if (0 == pUnk)
405*b1cdbd2cSJim Jagielski 		return E_OUTOFMEMORY;
406*b1cdbd2cSJim Jagielski 
407*b1cdbd2cSJim Jagielski 	*ppv = pUnk;
408*b1cdbd2cSJim Jagielski 	return S_OK;
409*b1cdbd2cSJim Jagielski }
410*b1cdbd2cSJim Jagielski 
DllCanUnloadNow(void)411*b1cdbd2cSJim Jagielski extern "C" STDAPI DllCanUnloadNow(void)
412*b1cdbd2cSJim Jagielski {
413*b1cdbd2cSJim Jagielski 	if (CClassFactory::IsLocked() || g_DllRefCnt > 0)
414*b1cdbd2cSJim Jagielski 		return S_FALSE;
415*b1cdbd2cSJim Jagielski 
416*b1cdbd2cSJim Jagielski 	return S_OK;
417*b1cdbd2cSJim Jagielski }
418*b1cdbd2cSJim Jagielski 
DllMain(HINSTANCE hInst,ULONG,LPVOID)419*b1cdbd2cSJim Jagielski BOOL WINAPI DllMain(HINSTANCE hInst, ULONG /*ul_reason_for_call*/, LPVOID /*lpReserved*/)
420*b1cdbd2cSJim Jagielski {
421*b1cdbd2cSJim Jagielski     g_hModule = hInst;
422*b1cdbd2cSJim Jagielski     return TRUE;
423*b1cdbd2cSJim Jagielski }
424