update dev300-m58
[ooovba.git] / shell / source / win32 / shlxthandler / shlxthdl.cxx
blob95d7f59d0206faafeff93d988f7bb53d44500c31
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: shlxthdl.cxx,v $
10 * $Revision: 1.9 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_shell.hxx"
33 #include "internal/config.hxx"
34 #include "internal/global.hxx"
35 #include "internal/shlxthdl.hxx"
36 #include "classfactory.hxx"
37 #include "internal/registry.hxx"
38 #include "internal/fileextensions.hxx"
39 #include "internal/utilities.hxx"
41 #include <tchar.h>
42 #include <string>
43 #include <shlobj.h>
45 //---------------------------
46 // Module global
47 //---------------------------
48 long g_DllRefCnt = 0;
49 HINSTANCE g_hModule = NULL;
51 namespace /* private */
53 const char* GUID_PLACEHOLDER = "{GUID}";
54 const char* EXTENSION_PLACEHOLDER = "{EXT}";
55 const char* FORWARDKEY_PLACEHOLDER = "{FWDKEY}";
57 const char* CLSID_ENTRY = "CLSID\\{GUID}\\InProcServer32";
58 const char* SHELLEX_IID_ENTRY = "{EXT}\\shellex\\{GUID}";
59 const char* SHELLEX_ENTRY = "{EXT}\\shellex";
60 const char* PROPSHEET_ENTRY = "{EXT}\\CLSID\\{GUID}\\InProcServer32";
61 const char* EXTENSION_CLSID = "{EXT}\\CLSID";
62 const char* EXTENSION_CLSID_GUID = "{EXT}\\CLSID\\{GUID}";
63 const char* FORWARD_PROPSHEET_MYPROPSHEET_ENTRY = "{FWDKEY}\\shellex\\PropertySheetHandlers\\MyPropSheet1";
64 const char* FORWARD_PROPSHEET_ENTRY = "{FWDKEY}\\shellex\\PropertySheetHandlers";
65 const char* FORWARD_SHELLEX_ENTRY = "{FWDKEY}\\shellex";
67 const char* SHELL_EXTENSION_APPROVED_KEY_NAME = "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved";
69 //---------------------------
70 // "String Placeholder" ->
71 // "String Replacement"
72 //---------------------------
73 void SubstitutePlaceholder(std::string& String, const std::string& Placeholder, const std::string& Replacement)
75 std::string::size_type idx = String.find(Placeholder);
76 std::string::size_type len = Placeholder.length();
78 while (std::string::npos != idx)
80 String.replace(idx, len, Replacement);
81 idx = String.find(Placeholder);
85 /* Make the registry entry
86 HKCR\CLSID\{GUID}
87 InProcServer32 = Path\shlxthdl.dll
88 ThreadingModel = Apartment
89 */
90 HRESULT RegisterComComponent(const char* FilePath, const CLSID& Guid)
92 std::string ClsidEntry = CLSID_ENTRY;
93 SubstitutePlaceholder(ClsidEntry, GUID_PLACEHOLDER, ClsidToString(Guid));
95 if (!SetRegistryKey(HKEY_CLASSES_ROOT, ClsidEntry.c_str(), "", FilePath))
96 return E_FAIL;
98 if (!SetRegistryKey(HKEY_CLASSES_ROOT, ClsidEntry.c_str(), "ThreadingModel", "Apartment"))
99 return E_FAIL;
101 return S_OK;
104 HRESULT UnregisterComComponent(const CLSID& Guid)
106 std::string tmp = "CLSID\\";
107 tmp += ClsidToString(Guid);
108 return DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str()) ? S_OK : E_FAIL;
111 HRESULT RegisterColumnHandler(const char* ModuleFileName)
113 if (FAILED(RegisterComComponent(ModuleFileName, CLSID_COLUMN_HANDLER)))
114 return E_FAIL;
116 std::string tmp = "Folder\\shellex\\ColumnHandlers\\";
117 tmp += ClsidToString(CLSID_COLUMN_HANDLER);
119 return SetRegistryKey(
120 HKEY_CLASSES_ROOT,
121 tmp.c_str(),
122 "",
123 WStringToString(COLUMN_HANDLER_DESCRIPTIVE_NAME).c_str()) ? S_OK : E_FAIL;
126 HRESULT UnregisterColumnHandler()
128 std::string tmp = "Folder\\shellex\\ColumnHandlers\\";
129 tmp += ClsidToString(CLSID_COLUMN_HANDLER);
131 if (!DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str()))
132 return E_FAIL;
134 return UnregisterComComponent(CLSID_COLUMN_HANDLER);
137 HRESULT RegisterInfotipHandler(const char* ModuleFileName)
139 if (FAILED(RegisterComComponent(ModuleFileName, CLSID_INFOTIP_HANDLER)))
140 return E_FAIL;
142 std::string iid = ClsidToString(IID_IQueryInfo);
143 std::string tmp;
145 for(size_t i = 0; i < OOFileExtensionTableSize; i++)
147 tmp = SHELLEX_IID_ENTRY;
148 SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
149 SubstitutePlaceholder(tmp, GUID_PLACEHOLDER, iid);
151 if (!SetRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str(), "", ClsidToString(CLSID_INFOTIP_HANDLER).c_str()))
152 return E_FAIL;
154 return S_OK;
157 HRESULT UnregisterInfotipHandler()
159 std::string iid = ClsidToString(IID_IQueryInfo);
160 std::string tmp;
162 for (size_t i = 0; i < OOFileExtensionTableSize; i++)
164 tmp = SHELLEX_IID_ENTRY;
166 SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
167 SubstitutePlaceholder(tmp, GUID_PLACEHOLDER, iid);
169 DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str());
171 // if there are no further subkey below .ext\\shellex
172 // delete the whole subkey
173 tmp = SHELLEX_ENTRY;
174 SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
176 bool HasSubKeys = true;
177 if (HasSubkeysRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str(), HasSubKeys) && !HasSubKeys)
178 DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str());
180 return UnregisterComComponent(CLSID_INFOTIP_HANDLER);
183 HRESULT RegisterPropSheetHandler(const char* ModuleFileName)
185 std::string ExtEntry;
186 std::string FwdKeyEntry;
188 if (FAILED(RegisterComComponent(ModuleFileName, CLSID_PROPERTYSHEET_HANDLER)))
189 return E_FAIL;
191 for (size_t i = 0; i < OOFileExtensionTableSize; i++)
193 FwdKeyEntry = FORWARD_PROPSHEET_MYPROPSHEET_ENTRY;
194 SubstitutePlaceholder(FwdKeyEntry, FORWARDKEY_PLACEHOLDER, OOFileExtensionTable[i].RegistryForwardKey);
196 if (!SetRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str(), "", ClsidToString(CLSID_PROPERTYSHEET_HANDLER).c_str()))
197 return E_FAIL;
199 return S_OK;
202 HRESULT UnregisterPropSheetHandler()
204 std::string ExtEntry;
205 std::string FwdKeyEntry;
207 for (size_t i = 0; i < OOFileExtensionTableSize; i++)
209 FwdKeyEntry = FORWARD_PROPSHEET_MYPROPSHEET_ENTRY;
210 SubstitutePlaceholder(FwdKeyEntry, FORWARDKEY_PLACEHOLDER, OOFileExtensionTable[i].RegistryForwardKey);
212 DeleteRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str());
214 FwdKeyEntry = FORWARD_PROPSHEET_ENTRY;
215 SubstitutePlaceholder(FwdKeyEntry, FORWARDKEY_PLACEHOLDER, OOFileExtensionTable[i].RegistryForwardKey);
217 bool HasSubKeys = true;
218 if (HasSubkeysRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str(), HasSubKeys) && !HasSubKeys)
219 DeleteRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str());
221 FwdKeyEntry = FORWARD_SHELLEX_ENTRY;
222 SubstitutePlaceholder(FwdKeyEntry, FORWARDKEY_PLACEHOLDER, OOFileExtensionTable[i].RegistryForwardKey);
224 HasSubKeys = true;
225 if (HasSubkeysRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str(), HasSubKeys) && !HasSubKeys)
226 DeleteRegistryKey(HKEY_CLASSES_ROOT, FwdKeyEntry.c_str());
229 return UnregisterComComponent(CLSID_PROPERTYSHEET_HANDLER);
232 HRESULT RegisterThumbviewerHandler(const char* ModuleFileName)
234 if (FAILED(RegisterComComponent(ModuleFileName, CLSID_THUMBVIEWER_HANDLER)))
235 return E_FAIL;
237 std::string iid = ClsidToString(IID_IExtractImage);
238 std::string tmp;
240 for(size_t i = 0; i < OOFileExtensionTableSize; i++)
242 tmp = SHELLEX_IID_ENTRY;
244 SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
245 SubstitutePlaceholder(tmp, GUID_PLACEHOLDER, iid);
247 if (!SetRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str(), "", ClsidToString(CLSID_THUMBVIEWER_HANDLER).c_str()))
248 return E_FAIL;
250 return S_OK;
253 HRESULT UnregisterThumbviewerHandler()
255 std::string iid = ClsidToString(IID_IExtractImage);
256 std::string tmp;
258 for (size_t i = 0; i < OOFileExtensionTableSize; i++)
260 tmp = SHELLEX_IID_ENTRY;
262 SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
263 SubstitutePlaceholder(tmp, GUID_PLACEHOLDER, iid);
265 DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str());
267 // if there are no further subkey below .ext\\shellex
268 // delete the whole subkey
269 tmp = SHELLEX_ENTRY;
270 SubstitutePlaceholder(tmp, EXTENSION_PLACEHOLDER, OOFileExtensionTable[i].ExtensionAnsi);
272 bool HasSubKeys = true;
273 if (HasSubkeysRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str(), HasSubKeys) && !HasSubKeys)
274 DeleteRegistryKey(HKEY_CLASSES_ROOT, tmp.c_str());
276 return UnregisterComComponent(CLSID_THUMBVIEWER_HANDLER);
279 /** Approving/Unapproving the Shell Extension, it's important under Windows
280 NT/2000/XP, see MSDN: Creating Shell Extension Handlers */
281 HRESULT ApproveShellExtension(CLSID clsid, const std::wstring& Description)
283 bool bRet = SetRegistryKey(
284 HKEY_LOCAL_MACHINE,
285 SHELL_EXTENSION_APPROVED_KEY_NAME,
286 ClsidToString(clsid).c_str(),
287 WStringToString(Description).c_str());
289 return bRet ? S_OK : E_FAIL;
292 HRESULT UnapproveShellExtension(CLSID Clsid)
294 HKEY hkey;
296 LONG rc = RegOpenKeyA(
297 HKEY_LOCAL_MACHINE,
298 SHELL_EXTENSION_APPROVED_KEY_NAME,
299 &hkey);
301 if (ERROR_SUCCESS == rc)
303 rc = RegDeleteValueA(
304 hkey,
305 ClsidToString(Clsid).c_str());
307 rc = RegCloseKey(hkey);
310 return rc == ERROR_SUCCESS ? S_OK : E_FAIL;
313 } // namespace /* private */
316 //---------------------
317 // COM exports
318 //---------------------
320 extern "C" STDAPI DllRegisterServer()
322 TCHAR ModuleFileName[MAX_PATH];
324 GetModuleFileName(
325 GetModuleHandle(MODULE_NAME),
326 ModuleFileName,
327 sizeof(ModuleFileName));
329 std::string module_path = WStringToString(ModuleFileName);
330 HRESULT hr = S_OK;
332 if (SUCCEEDED(RegisterColumnHandler(module_path.c_str())))
333 ApproveShellExtension(CLSID_COLUMN_HANDLER, COLUMN_HANDLER_DESCRIPTIVE_NAME);
334 else
335 hr = E_FAIL;
337 if (SUCCEEDED(RegisterInfotipHandler(module_path.c_str())))
338 ApproveShellExtension(CLSID_INFOTIP_HANDLER, INFOTIP_HANDLER_DESCRIPTIVE_NAME);
339 else
340 hr = E_FAIL;
342 if (SUCCEEDED(RegisterPropSheetHandler(module_path.c_str())))
343 ApproveShellExtension(CLSID_PROPERTYSHEET_HANDLER, PROPSHEET_HANDLER_DESCRIPTIVE_NAME);
344 else
345 hr = E_FAIL;
347 if (SUCCEEDED(RegisterThumbviewerHandler(module_path.c_str())))
348 ApproveShellExtension(CLSID_THUMBVIEWER_HANDLER, THUMBVIEWER_HANDLER_DESCRIPTIVAE_NAME);
349 else
350 hr = E_FAIL;
352 // notify the Shell that something has changed
353 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
355 return hr;
358 extern "C" STDAPI DllUnregisterServer()
360 HRESULT hr = S_OK;
362 if (FAILED(UnregisterColumnHandler()))
363 hr = E_FAIL;
365 UnapproveShellExtension(CLSID_COLUMN_HANDLER);
367 if (FAILED(UnregisterInfotipHandler()))
368 hr = E_FAIL;
370 UnapproveShellExtension(CLSID_INFOTIP_HANDLER);
372 if (FAILED(UnregisterPropSheetHandler()))
373 hr = E_FAIL;
375 UnapproveShellExtension(CLSID_PROPERTYSHEET_HANDLER);
377 if (FAILED(UnregisterThumbviewerHandler()))
378 hr = E_FAIL;
380 UnapproveShellExtension(CLSID_THUMBVIEWER_HANDLER);
382 // notify the Shell that something has changed
383 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
385 return hr;
388 extern "C" STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void** ppv)
390 *ppv = 0;
392 if ((rclsid != CLSID_INFOTIP_HANDLER) &&
393 (rclsid != CLSID_COLUMN_HANDLER) &&
394 (rclsid != CLSID_PROPERTYSHEET_HANDLER) &&
395 (rclsid != CLSID_THUMBVIEWER_HANDLER))
396 return CLASS_E_CLASSNOTAVAILABLE;
398 if ((riid != IID_IUnknown) && (riid != IID_IClassFactory))
399 return E_NOINTERFACE;
401 IUnknown* pUnk = new CClassFactory(rclsid);
402 if (0 == pUnk)
403 return E_OUTOFMEMORY;
405 *ppv = pUnk;
406 return S_OK;
409 extern "C" STDAPI DllCanUnloadNow(void)
411 if (CClassFactory::IsLocked() || g_DllRefCnt > 0)
412 return S_FALSE;
414 return S_OK;
417 BOOL WINAPI DllMain(HINSTANCE hInst, ULONG /*ul_reason_for_call*/, LPVOID /*lpReserved*/)
419 g_hModule = hInst;
420 return TRUE;