bump product version to 6.3.0.0.beta1
[LibreOffice.git] / extensions / source / activex / so_activex.cxx
blobd3899a4aa2050bd826170db5cd88847eeea503f3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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.
26 #include <stdio.h>
27 #include "StdAfx2.h"
28 #include "resource.h"
29 #include <initguid.h>
31 #if defined __clang__
32 #pragma clang diagnostic push
33 #pragma clang diagnostic ignored "-Wnon-virtual-dtor"
34 #endif
35 #include <so_activex.h>
36 #if defined __clang__
37 #pragma clang diagnostic pop
38 #endif
40 #if defined __clang__
41 #pragma clang diagnostic push
42 #pragma clang diagnostic ignored "-Wextra-tokens"
43 // "#endif !_MIDL_USE_GUIDDEF_" in midl-generated code
44 #endif
45 #include <so_activex_i.c>
46 #if defined __clang__
47 #pragma clang diagnostic pop
48 #endif
50 #include "SOActiveX.h"
52 #include <comphelper\documentconstants.hxx>
53 #include <exception>
55 CComModule _Module;
57 BEGIN_OBJECT_MAP(ObjectMap)
58 OBJECT_ENTRY(CLSID_SOActiveX, CSOActiveX)
59 #if defined __clang__
60 #pragma clang diagnostic push
61 #pragma clang diagnostic ignored "-Wmissing-field-initializers"
62 #endif
63 END_OBJECT_MAP()
64 #if defined __clang__
65 #pragma clang diagnostic pop
66 #endif
68 #define X64_LIB_NAME L"so_activex_x64.dll"
69 #define X32_LIB_NAME L"so_activex.dll"
71 // to provide windows xp as build systems for mingw we need to define KEY_WOW64_64KEY
72 // in mingw 3.13 KEY_WOW64_64KEY isn't available < Win2003 systems.
73 // Also defined in setup_native\source\win32\customactions\reg64\reg64.cxx,source\win32\customactions\shellextensions\shellextensions.cxx and
74 // extensions\source\activex\main\so_activex.cpp
75 #ifndef KEY_WOW64_64KEY
76 #define KEY_WOW64_64KEY (0x0100)
77 #endif
78 #ifndef KEY_WOW64_32KEY
79 #define KEY_WOW64_32KEY (0x0200)
80 #endif
82 const REGSAM n64KeyAccess = KEY_ALL_ACCESS | KEY_WOW64_64KEY;
83 const REGSAM n32KeyAccess = KEY_ALL_ACCESS;
85 #ifdef _AMD64_
86 const bool bX64 = true;
87 #define REG_DELETE_KEY_A( key, aPath, nKeyAccess ) RegDeleteKeyExA( key, aPath, nKeyAccess, 0 )
88 #else
89 const bool bX64 = false;
90 #define REG_DELETE_KEY_A( key, aPath, nKeyAccess ) RegDeleteKeyA( key, aPath )
91 #endif
93 // DLL Entry Point
95 extern "C"
96 BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
98 if (dwReason == DLL_PROCESS_ATTACH)
100 _Module.Init(ObjectMap, hInstance, &LIBID_SO_ACTIVEXLib);
101 DisableThreadLibraryCalls(hInstance);
103 else if (dwReason == DLL_PROCESS_DETACH)
104 _Module.Term();
105 return TRUE; // ok
109 // Used to determine whether the DLL can be unloaded by OLE
111 STDAPI DllCanUnloadNow()
113 return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
117 // Returns a class factory to create an object of the requested type
119 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
121 return _Module.GetClassObject(rclsid, riid, ppv);
125 // DllRegisterServer - Adds entries to the system registry
127 namespace
129 // Wraps an updatable Win32 error; keeps first incoming error.
130 // Ctor defines if upd will throw std::exception on error or
131 // return false.
132 class Status
134 public:
135 explicit Status(bool bTrow)
136 : m_bThrow(bTrow)
139 // used to check success of an operation, and update the status if it's still ERROR_SUCCESS
140 bool upd(LSTATUS nNewStatus)
142 if (m_nStatus == ERROR_SUCCESS)
143 m_nStatus = nNewStatus;
144 if (m_bThrow && nNewStatus != ERROR_SUCCESS)
145 throw std::exception();
146 return nNewStatus == ERROR_SUCCESS;
148 LSTATUS get() { return m_nStatus; }
149 operator bool() { return m_nStatus == ERROR_SUCCESS; }
151 private:
152 LSTATUS m_nStatus = ERROR_SUCCESS;
153 const bool m_bThrow;
156 class HRegKey
158 public:
159 ~HRegKey()
161 if (m_hkey)
162 RegCloseKey(m_hkey);
164 PHKEY operator&() { return &m_hkey; }
165 operator HKEY() { return m_hkey; }
167 private:
168 HKEY m_hkey = nullptr;
172 // for now database component and chart are always installed
173 #define SUPPORTED_EXT_NUM 30
174 const char* const aFileExt[] = { ".vor",
175 ".sds", ".sda", ".sdd", ".sdp", ".sdc", ".sdw", ".smf",
176 ".stw", ".stc", ".sti", ".std",
177 ".sxw", ".sxc", ".sxi", ".sxd", ".sxg", ".sxm",
178 ".ott", ".otg", ".otp", ".ots", ".otf",
179 ".odt", ".oth", ".odm", ".odg", ".odp", ".ods", ".odf"};
180 const char* const aMimeType[] = {
181 "application/vnd.stardivision.writer",
183 "application/vnd.stardivision.chart",
184 "application/vnd.stardivision.draw",
185 "application/vnd.stardivision.impress",
186 "application/vnd.stardivision.impress-packed",
187 "application/vnd.stardivision.calc",
188 "application/vnd.stardivision.writer",
189 "application/vnd.stardivision.math",
191 MIMETYPE_VND_SUN_XML_WRITER_TEMPLATE_ASCII,
192 MIMETYPE_VND_SUN_XML_CALC_TEMPLATE_ASCII,
193 MIMETYPE_VND_SUN_XML_IMPRESS_TEMPLATE_ASCII,
194 MIMETYPE_VND_SUN_XML_DRAW_TEMPLATE_ASCII,
196 MIMETYPE_VND_SUN_XML_WRITER_ASCII,
197 MIMETYPE_VND_SUN_XML_CALC_ASCII,
198 MIMETYPE_VND_SUN_XML_IMPRESS_ASCII,
199 MIMETYPE_VND_SUN_XML_DRAW_ASCII,
200 MIMETYPE_VND_SUN_XML_WRITER_GLOBAL_ASCII,
201 MIMETYPE_VND_SUN_XML_MATH_ASCII,
203 MIMETYPE_OASIS_OPENDOCUMENT_TEXT_TEMPLATE_ASCII,
204 MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_TEMPLATE_ASCII,
205 MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_TEMPLATE_ASCII,
206 MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE_ASCII,
207 MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_TEMPLATE_ASCII,
208 MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_TEMPLATE_ASCII,
210 MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII,
211 MIMETYPE_OASIS_OPENDOCUMENT_TEXT_WEB_ASCII,
212 MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_ASCII,
213 MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_ASCII,
214 MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII,
215 MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII,
216 MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_ASCII };
218 const int nForModes[] = { 16,
219 1, 2, 4, 4, 8, 16, 32,
220 16, 8, 4, 2,
221 16, 8, 4, 2, 16, 32,
222 16, 2, 4, 8, 32,
223 16, 16, 16, 2, 4, 8, 32 };
225 const char* const aClassID = "{67F2A879-82D5-4A6D-8CC5-FFB3C114B69D}";
226 const char* const aTypeLib = "{61FA3F13-8061-4796-B055-3697ED28CB38}";
228 // ISOComWindowPeer interface information
229 const char* const aInterIDWinPeer = "{BF5D10F3-8A10-4A0B-B150-2B6AA2D7E118}";
230 const char* const aProxyStubWinPeer = "{00020424-0000-0000-C000-000000000046}";
232 // ISODispatchInterceptor interface information
233 const char* const aInterIDDispInt = "{9337694C-B27D-4384-95A4-9D8E0EABC9E5}";
234 const char* const aProxyStubDispInt = "{00020424-0000-0000-C000-000000000046}";
236 // ISOActionsApproval interface information
237 const char* const aInterIDActApprove = "{029E9F1E-2B3F-4297-9160-8197DE7ED54F}";
238 const char* const aProxyStubActApprove = "{00020424-0000-0000-C000-000000000046}";
240 // The following prefix is required for HKEY_LOCAL_MACHINE and HKEY_CURRENT_USER ( not for HKEY_CLASSES_ROOT )
241 const char* const aLocalPrefix = "Software\\Classes\\";
243 static LSTATUS createKey( HKEY hkey,
244 const char* aKeyToCreate,
245 REGSAM nKeyAccess,
246 const char* aValue = nullptr,
247 const char* aChildName = nullptr,
248 const char* aChildValue = nullptr )
250 Status s(false); // no throw
251 HRegKey hkey1;
252 if (s.upd(RegCreateKeyExA(hkey, aKeyToCreate, 0, nullptr, REG_OPTION_NON_VOLATILE, nKeyAccess,
253 nullptr, &hkey1, nullptr)))
255 if (aValue)
256 s.upd(RegSetValueExA(hkey1, "", 0, REG_SZ, reinterpret_cast<const BYTE*>(aValue),
257 sal::static_int_cast<DWORD>(strlen(aValue))));
258 if (aChildName)
259 s.upd(RegSetValueExA(hkey1, aChildName, 0, REG_SZ,
260 reinterpret_cast<const BYTE*>(aChildValue),
261 sal::static_int_cast<DWORD>(strlen(aChildValue))));
263 return s.get();
266 static LSTATUS createKey(HKEY hkey,
267 const wchar_t* aKeyToCreate,
268 REGSAM nKeyAccess,
269 const wchar_t* aValue = nullptr,
270 const wchar_t* aChildName = nullptr,
271 const wchar_t* aChildValue = nullptr )
273 Status s(false); // no throw
274 HRegKey hkey1;
275 if (s.upd(RegCreateKeyExW(hkey, aKeyToCreate, 0, nullptr, REG_OPTION_NON_VOLATILE, nKeyAccess,
276 nullptr, &hkey1, nullptr)))
278 if (aValue)
279 s.upd(RegSetValueExW(hkey1, L"", 0, REG_SZ, reinterpret_cast<const BYTE*>(aValue),
280 sal::static_int_cast<DWORD>(wcslen(aValue) * sizeof(wchar_t))));
281 if (aChildName)
282 s.upd(RegSetValueExW(
283 hkey1, aChildName, 0, REG_SZ, reinterpret_cast<const BYTE*>(aChildValue),
284 sal::static_int_cast<DWORD>(wcslen(aChildValue) * sizeof(wchar_t))));
286 return s.get();
289 EXTERN_C __declspec(dllexport) HRESULT STDAPICALLTYPE DllUnregisterServerNative( int nMode, BOOL bForAllUsers, BOOL bFor64Bit );
290 static HRESULT DllRegisterServerNative_Impl( int nMode, BOOL bForAllUsers, REGSAM nKeyAccess, const wchar_t* pProgramPath, const wchar_t* pLibName )
292 char aSubKey[513];
293 int ind;
294 const char* aPrefix = aLocalPrefix; // bForAllUsers ? "" : aLocalPrefix;
296 // In case SO7 is installed for this user he can have local registry entries that will prevent him from
297 // using SO8 ActiveX control. The fix is just to clean up the local entries related to ActiveX control.
298 // Unfortunately it can be done only for the user who installs the office.
299 if ( bForAllUsers )
300 DllUnregisterServerNative( nMode, false, false );
302 Status s(true); // throw
305 if (pProgramPath && wcslen(pProgramPath) < 1024)
307 wchar_t pActiveXPath[1124];
308 wchar_t pActiveXPath101[1124];
310 swprintf(pActiveXPath, L"%s\\%s", pProgramPath, pLibName);
311 swprintf(pActiveXPath101, L"%s\\%s, 101", pProgramPath, pLibName);
314 wsprintfA(aSubKey, "%sCLSID\\%s", aPrefix, aClassID);
315 HRegKey hkey;
316 s.upd(RegCreateKeyExA(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
317 aSubKey, 0, nullptr, REG_OPTION_NON_VOLATILE, nKeyAccess,
318 nullptr, &hkey, nullptr));
319 s.upd(RegSetValueExA(hkey, "", 0, REG_SZ,
320 reinterpret_cast<const BYTE*>("SOActiveX Class"), 17));
321 s.upd(createKey(hkey, "Control", nKeyAccess));
322 s.upd(createKey(hkey, "EnableFullPage", nKeyAccess));
323 s.upd(createKey(hkey, L"InprocServer32", nKeyAccess, pActiveXPath,
324 L"ThreadingModel", L"Apartment"));
325 s.upd(createKey(hkey, "MiscStatus", nKeyAccess, "0"));
326 s.upd(createKey(hkey, "MiscStatus\\1", nKeyAccess, "131473"));
327 s.upd(createKey(hkey, "ProgID", nKeyAccess, "so_activex.SOActiveX.1"));
328 s.upd(createKey(hkey, "Programmable", nKeyAccess));
329 s.upd(createKey(hkey, L"ToolboxBitmap32", nKeyAccess, pActiveXPath101));
330 s.upd(createKey(hkey, "TypeLib", nKeyAccess, aTypeLib));
331 s.upd(createKey(hkey, "Version", nKeyAccess, "1.0"));
332 s.upd(createKey(hkey, "VersionIndependentProgID", nKeyAccess,
333 "so_activex.SOActiveX"));
336 HRegKey hkey;
337 s.upd(RegCreateKeyExA(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
338 aPrefix, 0, nullptr, REG_OPTION_NON_VOLATILE, nKeyAccess,
339 nullptr, &hkey, nullptr));
340 s.upd(createKey(hkey, "so_activex.SOActiveX", nKeyAccess, "SOActiveX Class"));
342 HRegKey hkey1;
343 s.upd(RegCreateKeyExA(hkey, "so_activex.SOActiveX", 0, nullptr,
344 REG_OPTION_NON_VOLATILE, nKeyAccess, nullptr, &hkey1,
345 nullptr));
346 s.upd(createKey(hkey1, "CLSID", nKeyAccess, aClassID));
347 s.upd(createKey(hkey1, "CurVer", nKeyAccess, "so_activex.SOActiveX.1"));
349 s.upd(createKey(hkey, "so_activex.SOActiveX.1", nKeyAccess, "SOActiveX Class"));
351 HRegKey hkey1;
352 s.upd(RegCreateKeyExA(hkey, "so_activex.SOActiveX.1", 0, nullptr,
353 REG_OPTION_NON_VOLATILE, nKeyAccess, nullptr, &hkey1,
354 nullptr));
355 s.upd(createKey(hkey1, "CLSID", nKeyAccess, aClassID));
358 HRegKey hkey1;
359 s.upd(RegCreateKeyExA(hkey, "TypeLib", 0, nullptr, REG_OPTION_NON_VOLATILE,
360 nKeyAccess, nullptr, &hkey1, nullptr));
362 HRegKey hkey2;
363 s.upd(RegCreateKeyExA(hkey1, aTypeLib, 0, nullptr, REG_OPTION_NON_VOLATILE,
364 nKeyAccess, nullptr, &hkey2, nullptr));
365 s.upd(createKey(hkey2, "1.0", nKeyAccess, "wrap_activex 1.0 Type Library"));
367 HRegKey hkey3;
368 s.upd(RegCreateKeyExA(hkey2, "1.0", 0, nullptr, REG_OPTION_NON_VOLATILE,
369 nKeyAccess, nullptr, &hkey3, nullptr));
371 HRegKey hkey4;
372 s.upd(RegCreateKeyExA(hkey3, "0", 0, nullptr,
373 REG_OPTION_NON_VOLATILE, nKeyAccess, nullptr,
374 &hkey4, nullptr));
375 s.upd(createKey(hkey4, L"win32", nKeyAccess, pActiveXPath));
377 s.upd(createKey(hkey3, "FLAGS", nKeyAccess, "0"));
378 s.upd(createKey(hkey3, L"HELPDIR", nKeyAccess, pProgramPath));
383 HRegKey hkey1;
384 s.upd(RegCreateKeyExA(hkey, "Interface", 0, nullptr, REG_OPTION_NON_VOLATILE,
385 nKeyAccess, nullptr, &hkey1, nullptr));
386 s.upd(createKey(hkey1, aInterIDWinPeer, nKeyAccess, "ISOComWindowPeer"));
388 HRegKey hkey2;
389 s.upd(RegCreateKeyExA(hkey1, aInterIDWinPeer, 0, nullptr,
390 REG_OPTION_NON_VOLATILE, nKeyAccess, nullptr, &hkey2,
391 nullptr));
392 s.upd(createKey(hkey2, "ProxyStubClsid", nKeyAccess, aProxyStubWinPeer));
393 s.upd(createKey(hkey2, "ProxyStubClsid32", nKeyAccess, aProxyStubWinPeer));
394 s.upd(createKey(hkey2, "TypeLib", nKeyAccess, aTypeLib, "Version", "1.0"));
396 s.upd(createKey(hkey1, aInterIDActApprove, nKeyAccess, "ISOActionsApproval"));
398 HRegKey hkey2;
399 s.upd(RegCreateKeyExA(hkey1, aInterIDActApprove, 0, nullptr,
400 REG_OPTION_NON_VOLATILE, nKeyAccess, nullptr, &hkey2,
401 nullptr));
402 s.upd(createKey(hkey2, "ProxyStubClsid", nKeyAccess, aProxyStubActApprove));
403 s.upd(
404 createKey(hkey2, "ProxyStubClsid32", nKeyAccess, aProxyStubActApprove));
405 s.upd(createKey(hkey2, "TypeLib", nKeyAccess, aTypeLib, "Version", "1.0"));
407 s.upd(createKey(hkey1, aInterIDDispInt, nKeyAccess, "ISODispatchInterceptor"));
409 HRegKey hkey2;
410 s.upd(RegCreateKeyExA(hkey1, aInterIDDispInt, 0, nullptr,
411 REG_OPTION_NON_VOLATILE, nKeyAccess, nullptr, &hkey2,
412 nullptr));
413 s.upd(createKey(hkey2, "ProxyStubClsid", nKeyAccess, aProxyStubDispInt));
414 s.upd(createKey(hkey2, "ProxyStubClsid32", nKeyAccess, aProxyStubDispInt));
415 s.upd(createKey(hkey2, "TypeLib", nKeyAccess, aTypeLib, "Version", "1.0"));
421 for (ind = 0; ind < SUPPORTED_EXT_NUM; ind++)
423 if (nForModes[ind] & nMode)
425 wsprintfA(aSubKey, "%sMIME\\DataBase\\Content Type\\%s", aPrefix, aMimeType[ind]);
426 HRegKey hkey;
427 s.upd(RegCreateKeyExA(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
428 aSubKey, 0, nullptr, REG_OPTION_NON_VOLATILE, nKeyAccess,
429 nullptr, &hkey, nullptr));
430 s.upd(RegSetValueExA(hkey, "CLSID", 0, REG_SZ,
431 reinterpret_cast<const BYTE*>(aClassID),
432 sal::static_int_cast<DWORD>(strlen(aClassID))));
437 wsprintfA(aSubKey, "%sCLSID\\%s", aPrefix, aClassID);
438 HRegKey hkey;
439 s.upd(RegOpenKeyExA(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, aSubKey, 0,
440 nKeyAccess, &hkey));
441 for (ind = 0; ind < SUPPORTED_EXT_NUM; ind++)
443 wsprintfA(aSubKey, "EnableFullPage\\%s", aFileExt[ind]);
444 HRegKey hkey1;
445 s.upd(RegCreateKeyExA(hkey, aSubKey, 0, nullptr, REG_OPTION_NON_VOLATILE,
446 nKeyAccess, nullptr, &hkey1, nullptr));
450 catch (const std::exception&) {}
452 return HRESULT_FROM_WIN32(s.get());
455 EXTERN_C __declspec(dllexport) HRESULT STDAPICALLTYPE DllRegisterServerNative( int nMode, BOOL bForAllUsers, BOOL bFor64Bit, const wchar_t* pProgramPath )
457 HRESULT hr = S_OK;
458 if ( bFor64Bit )
459 hr = DllRegisterServerNative_Impl( nMode, bForAllUsers, n64KeyAccess, pProgramPath, X64_LIB_NAME );
461 if ( SUCCEEDED( hr ) )
462 hr = DllRegisterServerNative_Impl( nMode, bForAllUsers, n32KeyAccess, pProgramPath, X32_LIB_NAME );
464 return hr;
468 // DllUnregisterServer - Removes entries from the system registry
469 static HRESULT DeleteKeyTree( HKEY hkey, const char* pPath, REGSAM nKeyAccess )
471 char pSubKeyName[256];
472 // first delete the subkeys
473 while (true)
475 HRegKey hkey1;
476 if (ERROR_SUCCESS != RegOpenKeyExA(hkey, pPath, 0, nKeyAccess, &hkey1)
477 || ERROR_SUCCESS != RegEnumKeyA(hkey1, 0, pSubKeyName, 256)
478 || ERROR_SUCCESS != DeleteKeyTree(hkey1, pSubKeyName, nKeyAccess))
479 break;
482 // delete the key itself
483 return REG_DELETE_KEY_A( hkey, pPath, nKeyAccess & ( KEY_WOW64_64KEY | KEY_WOW64_32KEY ) );
486 static HRESULT DllUnregisterServerNative_Impl( int nMode, BOOL bForAllUsers, REGSAM nKeyAccess )
488 char aSubKey[513];
489 const char* aPrefix = aLocalPrefix; // bForAllUsers ? "" : aLocalPrefix;
491 Status s(false); // no throw
492 for( int ind = 0; ind < SUPPORTED_EXT_NUM; ind++ )
494 if( nForModes[ind] & nMode )
496 DWORD nSubKeys = 0, nValues = 0;
497 wsprintfA(aSubKey, "%sMIME\\DataBase\\Content Type\\%s", aPrefix, aMimeType[ind]);
498 Status s1(false); // no throw
500 HRegKey hkey;
501 if (s1.upd(RegCreateKeyExA(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
502 aSubKey, 0, nullptr, REG_OPTION_NON_VOLATILE, nKeyAccess,
503 nullptr, &hkey, nullptr)))
505 s1.upd(RegDeleteValueA(hkey, "CLSID"));
506 s1.upd(RegQueryInfoKeyA(hkey, nullptr, nullptr, nullptr, &nSubKeys, nullptr,
507 nullptr, &nValues, nullptr, nullptr, nullptr, nullptr));
510 if (s1 && !nSubKeys && !nValues)
511 DeleteKeyTree(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, aSubKey,
512 nKeyAccess);
513 s.upd(s1.get());
515 wsprintfA(aSubKey, "%s%s", aPrefix, aFileExt[ind]);
516 Status s2(false); // no throw
518 HRegKey hkey;
519 if (s2.upd(RegCreateKeyExA(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
520 aSubKey, 0, nullptr, REG_OPTION_NON_VOLATILE, nKeyAccess,
521 nullptr, &hkey, nullptr)))
523 s2.upd(RegQueryInfoKeyA(hkey, nullptr, nullptr, nullptr, &nSubKeys, nullptr,
524 nullptr, &nValues, nullptr, nullptr, nullptr, nullptr));
527 if (s2 && !nSubKeys && !nValues)
528 DeleteKeyTree(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, aSubKey,
529 nKeyAccess);
530 s.upd(s2.get());
534 wsprintfA(aSubKey, "%sCLSID\\%s", aPrefix, aClassID);
535 s.upd(DeleteKeyTree(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, aSubKey,
536 nKeyAccess));
538 wsprintfA(aSubKey, "%sso_activex.SOActiveX", aPrefix);
539 s.upd(DeleteKeyTree(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, aSubKey,
540 nKeyAccess));
542 wsprintfA(aSubKey, "%sso_activex.SOActiveX.1", aPrefix);
543 s.upd(DeleteKeyTree(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, aSubKey,
544 nKeyAccess));
546 wsprintfA(aSubKey, "%s\\TypeLib\\%s", aPrefix, aTypeLib);
547 s.upd(DeleteKeyTree(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, aSubKey,
548 nKeyAccess));
550 wsprintfA(aSubKey, "%s\\Interface\\%s", aPrefix, aInterIDWinPeer);
551 s.upd(DeleteKeyTree(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, aSubKey,
552 nKeyAccess));
554 wsprintfA(aSubKey, "%s\\Interface\\%s", aPrefix, aInterIDDispInt);
555 s.upd(DeleteKeyTree(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, aSubKey,
556 nKeyAccess));
558 wsprintfA(aSubKey, "%s\\Interface\\%s", aPrefix, aInterIDActApprove);
559 s.upd(DeleteKeyTree(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, aSubKey,
560 nKeyAccess));
562 return HRESULT_FROM_WIN32(s.get());
565 STDAPI DllUnregisterServerNative( int nMode, BOOL bForAllUsers, BOOL bFor64Bit )
567 HRESULT hr = DllUnregisterServerNative_Impl( nMode, bForAllUsers, n32KeyAccess );
568 if ( SUCCEEDED( hr ) && bFor64Bit )
569 hr = DllUnregisterServerNative_Impl( nMode, bForAllUsers, n64KeyAccess );
571 return hr;
575 // DllRegisterServerDoc - Adds entries to the system registry
577 #define SUPPORTED_MSEXT_NUM 7
578 const char* const aMSFileExt[] = { ".dot", ".doc", ".xlt", ".xls", ".pot", ".ppt", ".pps" };
579 const char* const aMSMimeType[] = { "application/msword",
580 "application/msword",
581 "application/vnd.ms-excel",
582 "application/vnd.ms-excel",
583 "application/vnd.ms-powerpoint",
584 "application/vnd.ms-powerpoint",
585 "application/vnd.ms-powerpoint" };
586 const int nForMSModes[] = { 1, 1, 2, 2, 4, 4, 4 };
588 EXTERN_C __declspec(dllexport) HRESULT STDAPICALLTYPE DllUnregisterServerDoc( int nMode, BOOL bForAllUsers, BOOL bFor64Bit );
589 static HRESULT DllRegisterServerDoc_Impl( int nMode, BOOL bForAllUsers, REGSAM nKeyAccess )
591 char aSubKey[513];
592 int ind;
593 const char* aPrefix = aLocalPrefix; // bForAllUsers ? "" : aLocalPrefix;
595 // In case SO7 is installed for this user he can have local registry entries that will prevent him from
596 // using SO8 ActiveX control. The fix is just to clean up the local entries related to ActiveX control.
597 // Unfortunately it can be done only for the user who installs the office.
598 if ( bForAllUsers )
599 DllUnregisterServerDoc( nMode, false, false );
601 Status s(true); // throw
604 for (ind = 0; ind < SUPPORTED_MSEXT_NUM; ind++)
606 if (nForMSModes[ind] & nMode)
609 wsprintfA(aSubKey, "%sMIME\\DataBase\\Content Type\\%s", aPrefix,
610 aMSMimeType[ind]);
611 HRegKey hkey;
612 s.upd(RegCreateKeyExA(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
613 aSubKey, 0, nullptr, REG_OPTION_NON_VOLATILE, nKeyAccess,
614 nullptr, &hkey, nullptr));
615 s.upd(RegSetValueExA(hkey, "Extension", 0, REG_SZ,
616 reinterpret_cast<const BYTE*>(aMSFileExt[ind]),
617 sal::static_int_cast<DWORD>(strlen(aMSFileExt[ind]))));
618 s.upd(RegSetValueExA(hkey, "CLSID", 0, REG_SZ,
619 reinterpret_cast<const BYTE*>(aClassID),
620 sal::static_int_cast<DWORD>(strlen(aClassID))));
623 wsprintfA(aSubKey, "%s%s", aPrefix, aMSFileExt[ind]);
624 HRegKey hkey;
625 s.upd(RegCreateKeyExA(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
626 aSubKey, 0, nullptr, REG_OPTION_NON_VOLATILE, nKeyAccess,
627 nullptr, &hkey, nullptr));
628 s.upd(RegSetValueExA(hkey, "Content Type", 0, REG_SZ,
629 reinterpret_cast<const BYTE*>(aMSMimeType[ind]),
630 sal::static_int_cast<DWORD>(strlen(aMSMimeType[ind]))));
635 wsprintfA(aSubKey, "%sCLSID\\%s", aPrefix, aClassID);
636 HRegKey hkey;
637 s.upd(RegCreateKeyExA(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, aSubKey, 0,
638 nullptr, REG_OPTION_NON_VOLATILE, nKeyAccess, nullptr, &hkey,
639 nullptr));
640 s.upd(createKey(hkey, "EnableFullPage", nKeyAccess));
641 for (ind = 0; ind < SUPPORTED_MSEXT_NUM; ind++)
643 if (nForMSModes[ind] & nMode)
645 wsprintfA(aSubKey, "EnableFullPage\\%s", aMSFileExt[ind]);
646 HRegKey hkey1;
647 s.upd(RegCreateKeyExA(hkey, aSubKey, 0, nullptr, REG_OPTION_NON_VOLATILE,
648 nKeyAccess, nullptr, &hkey1, nullptr));
652 catch (const std::exception&) {}
654 return HRESULT_FROM_WIN32(s.get());
657 EXTERN_C __declspec(dllexport) HRESULT STDAPICALLTYPE DllRegisterServerDoc( int nMode, BOOL bForAllUsers, BOOL bFor64Bit )
659 HRESULT hr = S_OK;
660 if ( bFor64Bit )
661 hr = DllRegisterServerDoc_Impl( nMode, bForAllUsers, n64KeyAccess );
663 if ( SUCCEEDED( hr ) )
664 hr = DllRegisterServerDoc_Impl( nMode, bForAllUsers, n32KeyAccess );
666 return hr;
670 // DllUnregisterServerDoc - Removes entries from the system registry
672 static HRESULT DllUnregisterServerDoc_Impl( int nMode, BOOL bForAllUsers, REGSAM nKeyAccess )
674 char aSubKey[513];
675 const char* aPrefix = aLocalPrefix; // bForAllUsers ? "" : aLocalPrefix;
677 Status s(false); // no throw
678 for (int ind = 0; ind < SUPPORTED_MSEXT_NUM; ind++)
680 if (nForMSModes[ind] & nMode)
682 DWORD nSubKeys = 0, nValues = 0;
683 Status s1(false); // no throw
685 wsprintfA(aSubKey, "%sMIME\\DataBase\\Content Type\\%s", aPrefix, aMSMimeType[ind]);
686 HRegKey hkey;
687 if (s1.upd(RegCreateKeyExA(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
688 aSubKey, 0, nullptr, REG_OPTION_NON_VOLATILE, nKeyAccess,
689 nullptr, &hkey, nullptr)))
691 s.upd(RegDeleteValueA(hkey, "Extension"));
692 s.upd(RegDeleteValueA(hkey, "CLSID"));
693 s1.upd(RegQueryInfoKeyA(hkey, nullptr, nullptr, nullptr, &nSubKeys, nullptr,
694 nullptr, &nValues, nullptr, nullptr, nullptr, nullptr));
697 if (s1 && !nSubKeys && !nValues)
698 DeleteKeyTree(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, aSubKey,
699 nKeyAccess);
700 s.upd(s1.get());
702 Status s2(false); // no throw
704 wsprintfA(aSubKey, "%s%s", aPrefix, aMSFileExt[ind]);
705 HRegKey hkey;
706 if (s2.upd(RegCreateKeyExA(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
707 aSubKey, 0, nullptr, REG_OPTION_NON_VOLATILE, nKeyAccess,
708 nullptr, &hkey, nullptr)))
710 s.upd(RegDeleteValueA(hkey, "Content Type"));
711 s2.upd(RegQueryInfoKeyA(hkey, nullptr, nullptr, nullptr, &nSubKeys, nullptr,
712 nullptr, &nValues, nullptr, nullptr, nullptr, nullptr));
715 if (s2 && !nSubKeys && !nValues)
716 DeleteKeyTree(bForAllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, aSubKey,
717 nKeyAccess);
718 s.upd(s2.get());
722 return HRESULT_FROM_WIN32(s.get());
725 STDAPI DllUnregisterServerDoc( int nMode, BOOL bForAllUsers, BOOL bFor64Bit )
727 HRESULT hr = S_OK;
728 if ( bFor64Bit )
729 hr = DllUnregisterServerDoc_Impl( nMode, bForAllUsers, n64KeyAccess );
731 if ( SUCCEEDED( hr ) )
732 hr = DllUnregisterServerDoc_Impl( nMode, bForAllUsers, n32KeyAccess );
734 return hr;
738 // DllRegisterServer - regsvr32 entry point
740 STDAPI DllRegisterServer()
742 HRESULT aResult = E_FAIL;
744 HMODULE aCurModule = GetModuleHandleW( bX64 ? X64_LIB_NAME : X32_LIB_NAME );
745 DWORD nLibNameLen = sal::static_int_cast<DWORD>(
746 wcslen(bX64 ? X64_LIB_NAME : X32_LIB_NAME));
748 if( aCurModule )
750 wchar_t pProgramPath[1024];
751 DWORD nLen = GetModuleFileNameW( aCurModule, pProgramPath, 1024 );
752 if ( nLen && nLen > nLibNameLen + 1 )
754 pProgramPath[ nLen - nLibNameLen - 1 ] = 0;
755 aResult = DllRegisterServerNative( 31, TRUE, bX64, pProgramPath );
756 if( SUCCEEDED( aResult ) )
757 aResult = DllRegisterServerDoc( 31, TRUE, bX64 );
758 else
760 aResult = DllRegisterServerNative( 31, FALSE, bX64, pProgramPath );
761 if( SUCCEEDED( aResult ) )
762 aResult = DllRegisterServerDoc( 31, FALSE, bX64 );
767 return aResult;
771 // DllUnregisterServer - regsvr32 entry point
773 STDAPI DllUnregisterServer()
775 DllUnregisterServerDoc( 63, FALSE, bX64 );
776 DllUnregisterServerNative( 63, FALSE, bX64 );
777 DllUnregisterServerDoc( 63, TRUE, bX64 );
778 return DllUnregisterServerNative( 63, TRUE, bX64 );
781 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */