1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 // so_activex.cpp : Implementation of DLL Exports.
22 // Note: Proxy/Stub Information
23 // To build a separate proxy/stub DLL,
24 // run nmake -f so_activexps.mk in the project directory.
30 #include <so_activex.h>
33 #pragma clang diagnostic push
34 #pragma clang diagnostic ignored "-Wextra-tokens"
35 // "#endif !_MIDL_USE_GUIDDEF_" in midl-generated code
37 #include <so_activex_i.c>
39 #pragma clang diagnostic pop
42 #include "SOActiveX.h"
44 #include <comphelper\documentconstants.hxx>
45 #include <sal/types.h>
50 BEGIN_OBJECT_MAP(ObjectMap
)
51 OBJECT_ENTRY(CLSID_SOActiveX
, CSOActiveX
)
53 #pragma clang diagnostic push
54 #pragma clang diagnostic ignored "-Wmissing-field-initializers"
58 #pragma clang diagnostic pop
61 #define X64_LIB_NAME L"so_activex_x64.dll"
62 #define X32_LIB_NAME L"so_activex.dll"
64 const REGSAM n64KeyAccess
= KEY_ALL_ACCESS
| KEY_WOW64_64KEY
;
65 const REGSAM n32KeyAccess
= KEY_ALL_ACCESS
;
68 const bool bX64
= true;
69 #define REG_DELETE_KEY_A( key, aPath, nKeyAccess ) RegDeleteKeyExA( key, aPath, nKeyAccess, 0 )
71 const bool bX64
= false;
72 #define REG_DELETE_KEY_A( key, aPath, nKeyAccess ) RegDeleteKeyA( key, aPath )
78 BOOL WINAPI
DllMain(HINSTANCE hInstance
, DWORD dwReason
, LPVOID
/*lpReserved*/)
80 if (dwReason
== DLL_PROCESS_ATTACH
)
82 _Module
.Init(ObjectMap
, hInstance
, &LIBID_SO_ACTIVEXLib
);
83 DisableThreadLibraryCalls(hInstance
);
85 else if (dwReason
== DLL_PROCESS_DETACH
)
91 // Used to determine whether the DLL can be unloaded by OLE
93 STDAPI
DllCanUnloadNow()
95 return (_Module
.GetLockCount()==0) ? S_OK
: S_FALSE
;
99 // Returns a class factory to create an object of the requested type
101 STDAPI
DllGetClassObject(REFCLSID rclsid
, REFIID riid
, LPVOID
* ppv
)
103 return _Module
.GetClassObject(rclsid
, riid
, ppv
);
107 // DllRegisterServer - Adds entries to the system registry
111 // Wraps an updatable Win32 error; keeps first incoming error.
112 // Ctor defines if upd will throw std::exception on error or
117 explicit Status(bool bTrow
)
121 // used to check success of an operation, and update the status if it's still ERROR_SUCCESS
122 bool upd(LSTATUS nNewStatus
)
124 if (m_nStatus
== ERROR_SUCCESS
)
125 m_nStatus
= nNewStatus
;
126 if (m_bThrow
&& nNewStatus
!= ERROR_SUCCESS
)
127 throw std::exception();
128 return nNewStatus
== ERROR_SUCCESS
;
130 LSTATUS
get() { return m_nStatus
; }
131 operator bool() { return m_nStatus
== ERROR_SUCCESS
; }
134 LSTATUS m_nStatus
= ERROR_SUCCESS
;
146 PHKEY
operator&() { return &m_hkey
; }
147 operator HKEY() { return m_hkey
; }
150 HKEY m_hkey
= nullptr;
154 // for now database component and chart are always installed
155 #define SUPPORTED_EXT_NUM 30
156 const char* const aFileExt
[] = { ".vor",
157 ".sds", ".sda", ".sdd", ".sdp", ".sdc", ".sdw", ".smf",
158 ".stw", ".stc", ".sti", ".std",
159 ".sxw", ".sxc", ".sxi", ".sxd", ".sxg", ".sxm",
160 ".ott", ".otg", ".otp", ".ots", ".otf",
161 ".odt", ".oth", ".odm", ".odg", ".odp", ".ods", ".odf"};
162 const sal_Unicode
* const aMimeType
[] = {
163 u
"application/vnd.stardivision.writer",
165 u
"application/vnd.stardivision.chart",
166 u
"application/vnd.stardivision.draw",
167 u
"application/vnd.stardivision.impress",
168 u
"application/vnd.stardivision.impress-packed",
169 u
"application/vnd.stardivision.calc",
170 u
"application/vnd.stardivision.writer",
171 u
"application/vnd.stardivision.math",
173 MIMETYPE_VND_SUN_XML_WRITER_TEMPLATE_ASCII
.getStr(),
174 MIMETYPE_VND_SUN_XML_CALC_TEMPLATE_ASCII
.getStr(),
175 MIMETYPE_VND_SUN_XML_IMPRESS_TEMPLATE_ASCII
.getStr(),
176 MIMETYPE_VND_SUN_XML_DRAW_TEMPLATE_ASCII
.getStr(),
178 MIMETYPE_VND_SUN_XML_WRITER_ASCII
.getStr(),
179 MIMETYPE_VND_SUN_XML_CALC_ASCII
.getStr(),
180 MIMETYPE_VND_SUN_XML_IMPRESS_ASCII
.getStr(),
181 MIMETYPE_VND_SUN_XML_DRAW_ASCII
.getStr(),
182 MIMETYPE_VND_SUN_XML_WRITER_GLOBAL_ASCII
.getStr(),
183 MIMETYPE_VND_SUN_XML_MATH_ASCII
.getStr(),
185 MIMETYPE_OASIS_OPENDOCUMENT_TEXT_TEMPLATE_ASCII
.getStr(),
186 MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_TEMPLATE_ASCII
.getStr(),
187 MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_TEMPLATE_ASCII
.getStr(),
188 MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE_ASCII
.getStr(),
189 MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_TEMPLATE_ASCII
.getStr(),
190 MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_TEMPLATE_ASCII
.getStr(),
192 MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII
.getStr(),
193 MIMETYPE_OASIS_OPENDOCUMENT_TEXT_WEB_ASCII
.getStr(),
194 MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_ASCII
.getStr(),
195 MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_ASCII
.getStr(),
196 MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII
.getStr(),
197 MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII
.getStr(),
198 MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_ASCII
.getStr() };
200 const int nForModes
[] = { 16,
201 1, 2, 4, 4, 8, 16, 32,
205 16, 16, 16, 2, 4, 8, 32 };
207 const char* const aClassID
= "{67F2A879-82D5-4A6D-8CC5-FFB3C114B69D}";
208 const char* const aTypeLib
= "{61FA3F13-8061-4796-B055-3697ED28CB38}";
210 // ISOComWindowPeer interface information
211 const char* const aInterIDWinPeer
= "{BF5D10F3-8A10-4A0B-B150-2B6AA2D7E118}";
212 const char* const aProxyStubWinPeer
= "{00020424-0000-0000-C000-000000000046}";
214 // ISODispatchInterceptor interface information
215 const char* const aInterIDDispInt
= "{9337694C-B27D-4384-95A4-9D8E0EABC9E5}";
216 const char* const aProxyStubDispInt
= "{00020424-0000-0000-C000-000000000046}";
218 // ISOActionsApproval interface information
219 const char* const aInterIDActApprove
= "{029E9F1E-2B3F-4297-9160-8197DE7ED54F}";
220 const char* const aProxyStubActApprove
= "{00020424-0000-0000-C000-000000000046}";
222 // The following prefix is required for HKEY_LOCAL_MACHINE and HKEY_CURRENT_USER ( not for HKEY_CLASSES_ROOT )
223 const char* const aLocalPrefix
= "Software\\Classes\\";
225 static LSTATUS
createKey( HKEY hkey
,
226 const char* aKeyToCreate
,
228 const char* aValue
= nullptr,
229 const char* aChildName
= nullptr,
230 const char* aChildValue
= nullptr )
232 Status
s(false); // no throw
234 if (s
.upd(RegCreateKeyExA(hkey
, aKeyToCreate
, 0, nullptr, REG_OPTION_NON_VOLATILE
, nKeyAccess
,
235 nullptr, &hkey1
, nullptr)))
238 s
.upd(RegSetValueExA(hkey1
, "", 0, REG_SZ
, reinterpret_cast<const BYTE
*>(aValue
),
239 sal::static_int_cast
<DWORD
>(strlen(aValue
))));
241 s
.upd(RegSetValueExA(hkey1
, aChildName
, 0, REG_SZ
,
242 reinterpret_cast<const BYTE
*>(aChildValue
),
243 sal::static_int_cast
<DWORD
>(strlen(aChildValue
))));
248 static LSTATUS
createKey(HKEY hkey
,
249 const wchar_t* aKeyToCreate
,
251 const wchar_t* aValue
= nullptr,
252 const wchar_t* aChildName
= nullptr,
253 const wchar_t* aChildValue
= nullptr )
255 Status
s(false); // no throw
257 if (s
.upd(RegCreateKeyExW(hkey
, aKeyToCreate
, 0, nullptr, REG_OPTION_NON_VOLATILE
, nKeyAccess
,
258 nullptr, &hkey1
, nullptr)))
261 s
.upd(RegSetValueExW(hkey1
, L
"", 0, REG_SZ
, reinterpret_cast<const BYTE
*>(aValue
),
262 sal::static_int_cast
<DWORD
>(wcslen(aValue
) * sizeof(wchar_t))));
264 s
.upd(RegSetValueExW(
265 hkey1
, aChildName
, 0, REG_SZ
, reinterpret_cast<const BYTE
*>(aChildValue
),
266 sal::static_int_cast
<DWORD
>(wcslen(aChildValue
) * sizeof(wchar_t))));
271 EXTERN_C
__declspec(dllexport
) HRESULT STDAPICALLTYPE
DllUnregisterServerNative( int nMode
, BOOL bForAllUsers
, BOOL bFor64Bit
);
272 static HRESULT
DllRegisterServerNative_Impl( int nMode
, bool bForAllUsers
, REGSAM nKeyAccess
, const wchar_t* pProgramPath
, const wchar_t* pLibName
)
276 const char* aPrefix
= aLocalPrefix
; // bForAllUsers ? "" : aLocalPrefix;
278 // In case SO7 is installed for this user he can have local registry entries that will prevent him from
279 // using SO8 ActiveX control. The fix is just to clean up the local entries related to ActiveX control.
280 // Unfortunately it can be done only for the user who installs the office.
282 DllUnregisterServerNative( nMode
, false, false );
284 Status
s(true); // throw
287 if (pProgramPath
&& wcslen(pProgramPath
) < 1024)
289 wchar_t pActiveXPath
[1124];
290 wchar_t pActiveXPath101
[1124];
292 swprintf(pActiveXPath
, L
"%s\\%s", pProgramPath
, pLibName
);
293 swprintf(pActiveXPath101
, L
"%s\\%s, 101", pProgramPath
, pLibName
);
296 wsprintfA(aSubKey
, "%sCLSID\\%s", aPrefix
, aClassID
);
298 s
.upd(RegCreateKeyExA(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
299 aSubKey
, 0, nullptr, REG_OPTION_NON_VOLATILE
, nKeyAccess
,
300 nullptr, &hkey
, nullptr));
301 s
.upd(RegSetValueExA(hkey
, "", 0, REG_SZ
,
302 reinterpret_cast<const BYTE
*>("SOActiveX Class"), 17));
303 s
.upd(createKey(hkey
, "Control", nKeyAccess
));
304 s
.upd(createKey(hkey
, "EnableFullPage", nKeyAccess
));
305 s
.upd(createKey(hkey
, L
"InprocServer32", nKeyAccess
, pActiveXPath
,
306 L
"ThreadingModel", L
"Apartment"));
307 s
.upd(createKey(hkey
, "MiscStatus", nKeyAccess
, "0"));
308 s
.upd(createKey(hkey
, "MiscStatus\\1", nKeyAccess
, "131473"));
309 s
.upd(createKey(hkey
, "ProgID", nKeyAccess
, "so_activex.SOActiveX.1"));
310 s
.upd(createKey(hkey
, "Programmable", nKeyAccess
));
311 s
.upd(createKey(hkey
, L
"ToolboxBitmap32", nKeyAccess
, pActiveXPath101
));
312 s
.upd(createKey(hkey
, "TypeLib", nKeyAccess
, aTypeLib
));
313 s
.upd(createKey(hkey
, "Version", nKeyAccess
, "1.0"));
314 s
.upd(createKey(hkey
, "VersionIndependentProgID", nKeyAccess
,
315 "so_activex.SOActiveX"));
319 s
.upd(RegCreateKeyExA(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
320 aPrefix
, 0, nullptr, REG_OPTION_NON_VOLATILE
, nKeyAccess
,
321 nullptr, &hkey
, nullptr));
322 s
.upd(createKey(hkey
, "so_activex.SOActiveX", nKeyAccess
, "SOActiveX Class"));
325 s
.upd(RegCreateKeyExA(hkey
, "so_activex.SOActiveX", 0, nullptr,
326 REG_OPTION_NON_VOLATILE
, nKeyAccess
, nullptr, &hkey1
,
328 s
.upd(createKey(hkey1
, "CLSID", nKeyAccess
, aClassID
));
329 s
.upd(createKey(hkey1
, "CurVer", nKeyAccess
, "so_activex.SOActiveX.1"));
331 s
.upd(createKey(hkey
, "so_activex.SOActiveX.1", nKeyAccess
, "SOActiveX Class"));
334 s
.upd(RegCreateKeyExA(hkey
, "so_activex.SOActiveX.1", 0, nullptr,
335 REG_OPTION_NON_VOLATILE
, nKeyAccess
, nullptr, &hkey1
,
337 s
.upd(createKey(hkey1
, "CLSID", nKeyAccess
, aClassID
));
341 s
.upd(RegCreateKeyExA(hkey
, "TypeLib", 0, nullptr, REG_OPTION_NON_VOLATILE
,
342 nKeyAccess
, nullptr, &hkey1
, nullptr));
345 s
.upd(RegCreateKeyExA(hkey1
, aTypeLib
, 0, nullptr, REG_OPTION_NON_VOLATILE
,
346 nKeyAccess
, nullptr, &hkey2
, nullptr));
347 s
.upd(createKey(hkey2
, "1.0", nKeyAccess
, "wrap_activex 1.0 Type Library"));
350 s
.upd(RegCreateKeyExA(hkey2
, "1.0", 0, nullptr, REG_OPTION_NON_VOLATILE
,
351 nKeyAccess
, nullptr, &hkey3
, nullptr));
354 s
.upd(RegCreateKeyExA(hkey3
, "0", 0, nullptr,
355 REG_OPTION_NON_VOLATILE
, nKeyAccess
, nullptr,
357 s
.upd(createKey(hkey4
, L
"win32", nKeyAccess
, pActiveXPath
));
359 s
.upd(createKey(hkey3
, "FLAGS", nKeyAccess
, "0"));
360 s
.upd(createKey(hkey3
, L
"HELPDIR", nKeyAccess
, pProgramPath
));
366 s
.upd(RegCreateKeyExA(hkey
, "Interface", 0, nullptr, REG_OPTION_NON_VOLATILE
,
367 nKeyAccess
, nullptr, &hkey1
, nullptr));
368 s
.upd(createKey(hkey1
, aInterIDWinPeer
, nKeyAccess
, "ISOComWindowPeer"));
371 s
.upd(RegCreateKeyExA(hkey1
, aInterIDWinPeer
, 0, nullptr,
372 REG_OPTION_NON_VOLATILE
, nKeyAccess
, nullptr, &hkey2
,
374 s
.upd(createKey(hkey2
, "ProxyStubClsid", nKeyAccess
, aProxyStubWinPeer
));
375 s
.upd(createKey(hkey2
, "ProxyStubClsid32", nKeyAccess
, aProxyStubWinPeer
));
376 s
.upd(createKey(hkey2
, "TypeLib", nKeyAccess
, aTypeLib
, "Version", "1.0"));
378 s
.upd(createKey(hkey1
, aInterIDActApprove
, nKeyAccess
, "ISOActionsApproval"));
381 s
.upd(RegCreateKeyExA(hkey1
, aInterIDActApprove
, 0, nullptr,
382 REG_OPTION_NON_VOLATILE
, nKeyAccess
, nullptr, &hkey2
,
384 s
.upd(createKey(hkey2
, "ProxyStubClsid", nKeyAccess
, aProxyStubActApprove
));
386 createKey(hkey2
, "ProxyStubClsid32", nKeyAccess
, aProxyStubActApprove
));
387 s
.upd(createKey(hkey2
, "TypeLib", nKeyAccess
, aTypeLib
, "Version", "1.0"));
389 s
.upd(createKey(hkey1
, aInterIDDispInt
, nKeyAccess
, "ISODispatchInterceptor"));
392 s
.upd(RegCreateKeyExA(hkey1
, aInterIDDispInt
, 0, nullptr,
393 REG_OPTION_NON_VOLATILE
, nKeyAccess
, nullptr, &hkey2
,
395 s
.upd(createKey(hkey2
, "ProxyStubClsid", nKeyAccess
, aProxyStubDispInt
));
396 s
.upd(createKey(hkey2
, "ProxyStubClsid32", nKeyAccess
, aProxyStubDispInt
));
397 s
.upd(createKey(hkey2
, "TypeLib", nKeyAccess
, aTypeLib
, "Version", "1.0"));
403 for (ind
= 0; ind
< SUPPORTED_EXT_NUM
; ind
++)
405 if (nForModes
[ind
] & nMode
)
407 wsprintfA(aSubKey
, "%sMIME\\DataBase\\Content Type\\%ls", aPrefix
, aMimeType
[ind
]);
409 s
.upd(RegCreateKeyExA(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
410 aSubKey
, 0, nullptr, REG_OPTION_NON_VOLATILE
, nKeyAccess
,
411 nullptr, &hkey
, nullptr));
412 s
.upd(RegSetValueExA(hkey
, "CLSID", 0, REG_SZ
,
413 reinterpret_cast<const BYTE
*>(aClassID
),
414 sal::static_int_cast
<DWORD
>(strlen(aClassID
))));
419 wsprintfA(aSubKey
, "%sCLSID\\%s", aPrefix
, aClassID
);
421 s
.upd(RegOpenKeyExA(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
, aSubKey
, 0,
423 for (ind
= 0; ind
< SUPPORTED_EXT_NUM
; ind
++)
425 wsprintfA(aSubKey
, "EnableFullPage\\%s", aFileExt
[ind
]);
427 s
.upd(RegCreateKeyExA(hkey
, aSubKey
, 0, nullptr, REG_OPTION_NON_VOLATILE
,
428 nKeyAccess
, nullptr, &hkey1
, nullptr));
432 catch (const std::exception
&) {}
434 return HRESULT_FROM_WIN32(s
.get());
437 EXTERN_C
__declspec(dllexport
) HRESULT STDAPICALLTYPE
DllRegisterServerNative( int nMode
, BOOL bForAllUsers
, BOOL bFor64Bit
, const wchar_t* pProgramPath
)
441 hr
= DllRegisterServerNative_Impl( nMode
, bForAllUsers
, n64KeyAccess
, pProgramPath
, X64_LIB_NAME
);
443 if ( SUCCEEDED( hr
) )
444 hr
= DllRegisterServerNative_Impl( nMode
, bForAllUsers
, n32KeyAccess
, pProgramPath
, X32_LIB_NAME
);
450 // DllUnregisterServer - Removes entries from the system registry
451 static HRESULT
DeleteKeyTree( HKEY hkey
, const char* pPath
, REGSAM nKeyAccess
)
453 char pSubKeyName
[256];
454 // first delete the subkeys
458 if (ERROR_SUCCESS
!= RegOpenKeyExA(hkey
, pPath
, 0, nKeyAccess
, &hkey1
)
459 || ERROR_SUCCESS
!= RegEnumKeyA(hkey1
, 0, pSubKeyName
, 256)
460 || ERROR_SUCCESS
!= DeleteKeyTree(hkey1
, pSubKeyName
, nKeyAccess
))
464 // delete the key itself
465 return REG_DELETE_KEY_A( hkey
, pPath
, nKeyAccess
& ( KEY_WOW64_64KEY
| KEY_WOW64_32KEY
) );
468 static HRESULT
DllUnregisterServerNative_Impl( int nMode
, bool bForAllUsers
, REGSAM nKeyAccess
)
471 const char* aPrefix
= aLocalPrefix
; // bForAllUsers ? "" : aLocalPrefix;
473 Status
s(false); // no throw
474 for( int ind
= 0; ind
< SUPPORTED_EXT_NUM
; ind
++ )
476 if( nForModes
[ind
] & nMode
)
478 DWORD nSubKeys
= 0, nValues
= 0;
479 wsprintfA(aSubKey
, "%sMIME\\DataBase\\Content Type\\%ls", aPrefix
, aMimeType
[ind
]);
480 Status
s1(false); // no throw
483 if (s1
.upd(RegCreateKeyExA(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
484 aSubKey
, 0, nullptr, REG_OPTION_NON_VOLATILE
, nKeyAccess
,
485 nullptr, &hkey
, nullptr)))
487 s1
.upd(RegDeleteValueA(hkey
, "CLSID"));
488 s1
.upd(RegQueryInfoKeyA(hkey
, nullptr, nullptr, nullptr, &nSubKeys
, nullptr,
489 nullptr, &nValues
, nullptr, nullptr, nullptr, nullptr));
492 if (s1
&& !nSubKeys
&& !nValues
)
493 DeleteKeyTree(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
, aSubKey
,
497 wsprintfA(aSubKey
, "%s%s", aPrefix
, aFileExt
[ind
]);
498 Status
s2(false); // no throw
501 if (s2
.upd(RegCreateKeyExA(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
502 aSubKey
, 0, nullptr, REG_OPTION_NON_VOLATILE
, nKeyAccess
,
503 nullptr, &hkey
, nullptr)))
505 s2
.upd(RegQueryInfoKeyA(hkey
, nullptr, nullptr, nullptr, &nSubKeys
, nullptr,
506 nullptr, &nValues
, nullptr, nullptr, nullptr, nullptr));
509 if (s2
&& !nSubKeys
&& !nValues
)
510 DeleteKeyTree(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
, aSubKey
,
516 wsprintfA(aSubKey
, "%sCLSID\\%s", aPrefix
, aClassID
);
517 s
.upd(DeleteKeyTree(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
, aSubKey
,
520 wsprintfA(aSubKey
, "%sso_activex.SOActiveX", aPrefix
);
521 s
.upd(DeleteKeyTree(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
, aSubKey
,
524 wsprintfA(aSubKey
, "%sso_activex.SOActiveX.1", aPrefix
);
525 s
.upd(DeleteKeyTree(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
, aSubKey
,
528 wsprintfA(aSubKey
, "%s\\TypeLib\\%s", aPrefix
, aTypeLib
);
529 s
.upd(DeleteKeyTree(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
, aSubKey
,
532 wsprintfA(aSubKey
, "%s\\Interface\\%s", aPrefix
, aInterIDWinPeer
);
533 s
.upd(DeleteKeyTree(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
, aSubKey
,
536 wsprintfA(aSubKey
, "%s\\Interface\\%s", aPrefix
, aInterIDDispInt
);
537 s
.upd(DeleteKeyTree(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
, aSubKey
,
540 wsprintfA(aSubKey
, "%s\\Interface\\%s", aPrefix
, aInterIDActApprove
);
541 s
.upd(DeleteKeyTree(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
, aSubKey
,
544 return HRESULT_FROM_WIN32(s
.get());
547 STDAPI
DllUnregisterServerNative( int nMode
, BOOL bForAllUsers
, BOOL bFor64Bit
)
549 HRESULT hr
= DllUnregisterServerNative_Impl( nMode
, bForAllUsers
, n32KeyAccess
);
550 if ( SUCCEEDED( hr
) && bFor64Bit
)
551 hr
= DllUnregisterServerNative_Impl( nMode
, bForAllUsers
, n64KeyAccess
);
557 // DllRegisterServerDoc - Adds entries to the system registry
559 #define SUPPORTED_MSEXT_NUM 7
560 const char* const aMSFileExt
[] = { ".dot", ".doc", ".xlt", ".xls", ".pot", ".ppt", ".pps" };
561 const char* const aMSMimeType
[] = { "application/msword",
562 "application/msword",
563 "application/vnd.ms-excel",
564 "application/vnd.ms-excel",
565 "application/vnd.ms-powerpoint",
566 "application/vnd.ms-powerpoint",
567 "application/vnd.ms-powerpoint" };
568 const int nForMSModes
[] = { 1, 1, 2, 2, 4, 4, 4 };
570 EXTERN_C
__declspec(dllexport
) HRESULT STDAPICALLTYPE
DllUnregisterServerDoc( int nMode
, BOOL bForAllUsers
, BOOL bFor64Bit
);
571 static HRESULT
DllRegisterServerDoc_Impl( int nMode
, bool bForAllUsers
, REGSAM nKeyAccess
)
575 const char* aPrefix
= aLocalPrefix
; // bForAllUsers ? "" : aLocalPrefix;
577 // In case SO7 is installed for this user he can have local registry entries that will prevent him from
578 // using SO8 ActiveX control. The fix is just to clean up the local entries related to ActiveX control.
579 // Unfortunately it can be done only for the user who installs the office.
581 DllUnregisterServerDoc( nMode
, false, false );
583 Status
s(true); // throw
586 for (ind
= 0; ind
< SUPPORTED_MSEXT_NUM
; ind
++)
588 if (nForMSModes
[ind
] & nMode
)
591 wsprintfA(aSubKey
, "%sMIME\\DataBase\\Content Type\\%s", aPrefix
,
594 s
.upd(RegCreateKeyExA(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
595 aSubKey
, 0, nullptr, REG_OPTION_NON_VOLATILE
, nKeyAccess
,
596 nullptr, &hkey
, nullptr));
597 s
.upd(RegSetValueExA(hkey
, "Extension", 0, REG_SZ
,
598 reinterpret_cast<const BYTE
*>(aMSFileExt
[ind
]),
599 sal::static_int_cast
<DWORD
>(strlen(aMSFileExt
[ind
]))));
600 s
.upd(RegSetValueExA(hkey
, "CLSID", 0, REG_SZ
,
601 reinterpret_cast<const BYTE
*>(aClassID
),
602 sal::static_int_cast
<DWORD
>(strlen(aClassID
))));
605 wsprintfA(aSubKey
, "%s%s", aPrefix
, aMSFileExt
[ind
]);
607 s
.upd(RegCreateKeyExA(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
608 aSubKey
, 0, nullptr, REG_OPTION_NON_VOLATILE
, nKeyAccess
,
609 nullptr, &hkey
, nullptr));
610 s
.upd(RegSetValueExA(hkey
, "Content Type", 0, REG_SZ
,
611 reinterpret_cast<const BYTE
*>(aMSMimeType
[ind
]),
612 sal::static_int_cast
<DWORD
>(strlen(aMSMimeType
[ind
]))));
617 wsprintfA(aSubKey
, "%sCLSID\\%s", aPrefix
, aClassID
);
619 s
.upd(RegCreateKeyExA(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
, aSubKey
, 0,
620 nullptr, REG_OPTION_NON_VOLATILE
, nKeyAccess
, nullptr, &hkey
,
622 s
.upd(createKey(hkey
, "EnableFullPage", nKeyAccess
));
623 for (ind
= 0; ind
< SUPPORTED_MSEXT_NUM
; ind
++)
625 if (nForMSModes
[ind
] & nMode
)
627 wsprintfA(aSubKey
, "EnableFullPage\\%s", aMSFileExt
[ind
]);
629 s
.upd(RegCreateKeyExA(hkey
, aSubKey
, 0, nullptr, REG_OPTION_NON_VOLATILE
,
630 nKeyAccess
, nullptr, &hkey1
, nullptr));
634 catch (const std::exception
&) {}
636 return HRESULT_FROM_WIN32(s
.get());
639 EXTERN_C
__declspec(dllexport
) HRESULT STDAPICALLTYPE
DllRegisterServerDoc( int nMode
, BOOL bForAllUsers
, BOOL bFor64Bit
)
643 hr
= DllRegisterServerDoc_Impl( nMode
, bForAllUsers
, n64KeyAccess
);
645 if ( SUCCEEDED( hr
) )
646 hr
= DllRegisterServerDoc_Impl( nMode
, bForAllUsers
, n32KeyAccess
);
652 // DllUnregisterServerDoc - Removes entries from the system registry
654 static HRESULT
DllUnregisterServerDoc_Impl( int nMode
, bool bForAllUsers
, REGSAM nKeyAccess
)
657 const char* aPrefix
= aLocalPrefix
; // bForAllUsers ? "" : aLocalPrefix;
659 Status
s(false); // no throw
660 for (int ind
= 0; ind
< SUPPORTED_MSEXT_NUM
; ind
++)
662 if (nForMSModes
[ind
] & nMode
)
664 DWORD nSubKeys
= 0, nValues
= 0;
665 Status
s1(false); // no throw
667 wsprintfA(aSubKey
, "%sMIME\\DataBase\\Content Type\\%s", aPrefix
, aMSMimeType
[ind
]);
669 if (s1
.upd(RegCreateKeyExA(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
670 aSubKey
, 0, nullptr, REG_OPTION_NON_VOLATILE
, nKeyAccess
,
671 nullptr, &hkey
, nullptr)))
673 s
.upd(RegDeleteValueA(hkey
, "Extension"));
674 s
.upd(RegDeleteValueA(hkey
, "CLSID"));
675 s1
.upd(RegQueryInfoKeyA(hkey
, nullptr, nullptr, nullptr, &nSubKeys
, nullptr,
676 nullptr, &nValues
, nullptr, nullptr, nullptr, nullptr));
679 if (s1
&& !nSubKeys
&& !nValues
)
680 DeleteKeyTree(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
, aSubKey
,
684 Status
s2(false); // no throw
686 wsprintfA(aSubKey
, "%s%s", aPrefix
, aMSFileExt
[ind
]);
688 if (s2
.upd(RegCreateKeyExA(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
689 aSubKey
, 0, nullptr, REG_OPTION_NON_VOLATILE
, nKeyAccess
,
690 nullptr, &hkey
, nullptr)))
692 s
.upd(RegDeleteValueA(hkey
, "Content Type"));
693 s2
.upd(RegQueryInfoKeyA(hkey
, nullptr, nullptr, nullptr, &nSubKeys
, nullptr,
694 nullptr, &nValues
, nullptr, nullptr, nullptr, nullptr));
697 if (s2
&& !nSubKeys
&& !nValues
)
698 DeleteKeyTree(bForAllUsers
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
, aSubKey
,
704 return HRESULT_FROM_WIN32(s
.get());
707 STDAPI
DllUnregisterServerDoc( int nMode
, BOOL bForAllUsers
, BOOL bFor64Bit
)
711 hr
= DllUnregisterServerDoc_Impl( nMode
, bForAllUsers
, n64KeyAccess
);
713 if ( SUCCEEDED( hr
) )
714 hr
= DllUnregisterServerDoc_Impl( nMode
, bForAllUsers
, n32KeyAccess
);
720 // DllRegisterServer - regsvr32 entry point
722 STDAPI
DllRegisterServer()
724 HRESULT aResult
= E_FAIL
;
726 HMODULE aCurModule
{};
727 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
728 | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
,
729 reinterpret_cast<LPCWSTR
>(&DllRegisterServer
), &aCurModule
);
732 wchar_t pProgramPath
[1024];
733 wchar_t* pPathEnd
= nullptr;
734 DWORD nLen
= GetModuleFileNameW( aCurModule
, pProgramPath
, SAL_N_ELEMENTS(pProgramPath
) );
735 if ( nLen
&& nLen
< SAL_N_ELEMENTS(pProgramPath
) )
736 pPathEnd
= wcsrchr(pProgramPath
, '\\');
740 aResult
= DllRegisterServerNative( 31, TRUE
, bX64
, pProgramPath
);
741 if( SUCCEEDED( aResult
) )
742 aResult
= DllRegisterServerDoc( 31, TRUE
, bX64
);
745 aResult
= DllRegisterServerNative( 31, FALSE
, bX64
, pProgramPath
);
746 if( SUCCEEDED( aResult
) )
747 aResult
= DllRegisterServerDoc( 31, FALSE
, bX64
);
756 // DllUnregisterServer - regsvr32 entry point
758 STDAPI
DllUnregisterServer()
760 DllUnregisterServerDoc( 63, FALSE
, bX64
);
761 DllUnregisterServerNative( 63, FALSE
, bX64
);
762 DllUnregisterServerDoc( 63, TRUE
, bX64
);
763 return DllUnregisterServerNative( 63, TRUE
, bX64
);
766 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */