1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: shlxthdl.cxx,v $
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"
45 //---------------------------
47 //---------------------------
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
87 InProcServer32 = Path\shlxthdl.dll
88 ThreadingModel = Apartment
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
))
98 if (!SetRegistryKey(HKEY_CLASSES_ROOT
, ClsidEntry
.c_str(), "ThreadingModel", "Apartment"))
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
)))
116 std::string tmp
= "Folder\\shellex\\ColumnHandlers\\";
117 tmp
+= ClsidToString(CLSID_COLUMN_HANDLER
);
119 return SetRegistryKey(
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()))
134 return UnregisterComComponent(CLSID_COLUMN_HANDLER
);
137 HRESULT
RegisterInfotipHandler(const char* ModuleFileName
)
139 if (FAILED(RegisterComComponent(ModuleFileName
, CLSID_INFOTIP_HANDLER
)))
142 std::string iid
= ClsidToString(IID_IQueryInfo
);
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()))
157 HRESULT
UnregisterInfotipHandler()
159 std::string iid
= ClsidToString(IID_IQueryInfo
);
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
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
)))
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()))
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
);
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
)))
237 std::string iid
= ClsidToString(IID_IExtractImage
);
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()))
253 HRESULT
UnregisterThumbviewerHandler()
255 std::string iid
= ClsidToString(IID_IExtractImage
);
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
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(
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
)
296 LONG rc
= RegOpenKeyA(
298 SHELL_EXTENSION_APPROVED_KEY_NAME
,
301 if (ERROR_SUCCESS
== rc
)
303 rc
= RegDeleteValueA(
305 ClsidToString(Clsid
).c_str());
307 rc
= RegCloseKey(hkey
);
310 return rc
== ERROR_SUCCESS
? S_OK
: E_FAIL
;
313 } // namespace /* private */
316 //---------------------
318 //---------------------
320 extern "C" STDAPI
DllRegisterServer()
322 TCHAR ModuleFileName
[MAX_PATH
];
325 GetModuleHandle(MODULE_NAME
),
327 sizeof(ModuleFileName
));
329 std::string module_path
= WStringToString(ModuleFileName
);
332 if (SUCCEEDED(RegisterColumnHandler(module_path
.c_str())))
333 ApproveShellExtension(CLSID_COLUMN_HANDLER
, COLUMN_HANDLER_DESCRIPTIVE_NAME
);
337 if (SUCCEEDED(RegisterInfotipHandler(module_path
.c_str())))
338 ApproveShellExtension(CLSID_INFOTIP_HANDLER
, INFOTIP_HANDLER_DESCRIPTIVE_NAME
);
342 if (SUCCEEDED(RegisterPropSheetHandler(module_path
.c_str())))
343 ApproveShellExtension(CLSID_PROPERTYSHEET_HANDLER
, PROPSHEET_HANDLER_DESCRIPTIVE_NAME
);
347 if (SUCCEEDED(RegisterThumbviewerHandler(module_path
.c_str())))
348 ApproveShellExtension(CLSID_THUMBVIEWER_HANDLER
, THUMBVIEWER_HANDLER_DESCRIPTIVAE_NAME
);
352 // notify the Shell that something has changed
353 SHChangeNotify(SHCNE_ASSOCCHANGED
, SHCNF_IDLIST
, 0, 0);
358 extern "C" STDAPI
DllUnregisterServer()
362 if (FAILED(UnregisterColumnHandler()))
365 UnapproveShellExtension(CLSID_COLUMN_HANDLER
);
367 if (FAILED(UnregisterInfotipHandler()))
370 UnapproveShellExtension(CLSID_INFOTIP_HANDLER
);
372 if (FAILED(UnregisterPropSheetHandler()))
375 UnapproveShellExtension(CLSID_PROPERTYSHEET_HANDLER
);
377 if (FAILED(UnregisterThumbviewerHandler()))
380 UnapproveShellExtension(CLSID_THUMBVIEWER_HANDLER
);
382 // notify the Shell that something has changed
383 SHChangeNotify(SHCNE_ASSOCCHANGED
, SHCNF_IDLIST
, 0, 0);
388 extern "C" STDAPI
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, void** ppv
)
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
);
403 return E_OUTOFMEMORY
;
409 extern "C" STDAPI
DllCanUnloadNow(void)
411 if (CClassFactory::IsLocked() || g_DllRefCnt
> 0)
417 BOOL WINAPI
DllMain(HINSTANCE hInst
, ULONG
/*ul_reason_for_call*/, LPVOID
/*lpReserved*/)