tdf#133368: update extensions website URLs and use https
[LibreOffice.git] / setup_native / source / win32 / customactions / reg4allmsdoc / reg4allmsi.cxx
blob70ba1cc5246c59de49fcc98ba47c6725d52ea1a5
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 #define WIN32_LEAN_AND_MEAN
21 #include <windows.h>
22 #include <msiquery.h>
24 #include <malloc.h>
25 #include <string>
26 #include <strsafe.h>
28 static const WCHAR* g_Extensions[] =
30 L".doc", // Microsoft Word Text [0]
31 L".dot", // Microsoft Word Template
32 L".wps", // Kingsoft Writer Document
33 L".wpt", // Kingsoft Writer Template
34 L".rtf", // rtf text
35 L".docx", // Office Word 2007 XML document
36 L".docm", // Office Word 2007 XML macro-enabled document
37 L".dotx", // Office Word 2007 XML template
38 L".dotm", // Office Word 2007 XML macro-enabled template
39 L".xlw", // Microsoft Excel
40 L".xls", // Microsoft Excel
41 L".xlt", // Microsoft Excel Template
42 L".xlsx", // Office Excel 2007 XML workbook
43 L".xlsm", // Office Excel 2007 XML macro-enabled workbook
44 L".xltx", // Office Excel 2007 XML template
45 L".xltm", // Office Excel 2007 XML macro-enabled template
46 L".xlsb", // Office Excel 2007 binary workbook (BIFF12)
47 L".iqy", // Microsoft Excel Web Query File
48 L".et", // Kingsoft Spreadsheet
49 L".ett", // Kingsoft SpreadSheet Template
50 L".ppt", // Microsoft Powerpoint
51 L".pps", // Microsoft Powerpoint
52 L".pot", // Microsoft Powerpoint Template
53 L".pptx", // Office PowerPoint 2007 XML presentation
54 L".pptm", // Office PowerPoint 2007 macro-enabled XML presentation
55 L".potx", // Office PowerPoint 2007 XML template
56 L".potm", // Office PowerPoint 2007 macro-enabled XML template
57 L".ppsx", // Office PowerPoint 2007 XML show
58 L".dps", // Kingsoft Presentation
59 L".dpt", // Kingsoft Presentation Template
60 L".vsd", // Visio 2000/XP/2003 document
61 L".vst", // Visio 2000/XP/2003 template
62 nullptr
65 const int WORD_START = 0;
66 const int EXCEL_START = 9;
67 const int POWERPOINT_START = 20;
68 const int VISIO_START = 30;
69 const int VISIO_END = 32;
71 // ".xlam", // Office Excel 2007 XML macro-enabled add-in
72 // ".ppam", // Office PowerPoint 2007 macro-enabled XML add-in
73 // ".ppsm", // Office PowerPoint 2007 macro-enabled XML show
75 #ifdef DEBUG
76 inline void OutputDebugStringFormatW( LPCWSTR pFormat, ... )
78 WCHAR buffer[1024];
79 va_list args;
81 va_start( args, pFormat );
82 StringCchVPrintfW( buffer, sizeof(buffer)/sizeof(*buffer), pFormat, args );
83 OutputDebugStringW( buffer );
84 va_end(args);
86 #else
87 static void OutputDebugStringFormatW( LPCWSTR, ... )
90 #endif
92 static bool CheckExtensionInRegistry( LPCWSTR lpSubKey )
94 bool bRet = false;
95 HKEY hKey = nullptr;
96 LONG lResult = RegOpenKeyExW( HKEY_CLASSES_ROOT, lpSubKey, 0, KEY_QUERY_VALUE, &hKey );
98 if ( ERROR_SUCCESS == lResult )
100 WCHAR szBuffer[1024];
101 DWORD nSize = sizeof( szBuffer );
103 lResult = RegQueryValueExW( hKey, L"", nullptr, nullptr, reinterpret_cast<LPBYTE>(szBuffer), &nSize );
104 if ( ERROR_SUCCESS == lResult && nSize > 0 )
106 szBuffer[nSize/sizeof(*szBuffer)] = L'\0';
107 OutputDebugStringFormatW( L"Found value [%s] for key [%s].\n", szBuffer, lpSubKey );
109 if ( wcsncmp( szBuffer, L"WordPad.Document.1", 18 ) == 0 )
110 { // We will replace registration for WordPad (alas, on XP only) FIXME
111 bRet = true;
113 else if ( wcsncmp( szBuffer, L"LibreOffice.", 12 ) == 0 )
114 { // We will replace registration for our own types, too
115 bRet = true;
117 else if ( wcsncmp( szBuffer, L"lostub.", 7 ) == 0 )
118 { // We will replace registration for lostub, too
119 bRet = true;
121 else // we have a default value -> do not register, see fdo#39791
122 bRet = false;
124 else // no default value found -> return TRUE to register for that key
125 bRet = true;
127 RegCloseKey( hKey );
129 else // no key found -> return TRUE to register for that key
130 bRet = true;
132 return bRet;
135 static bool GetMsiPropW( MSIHANDLE handle, LPCWSTR name, /*out*/std::wstring& value )
137 DWORD sz = 0;
138 LPWSTR dummy = const_cast<LPWSTR>(L"");
139 if (MsiGetPropertyW(handle, name, dummy, &sz) == ERROR_MORE_DATA)
141 sz++;
142 DWORD nbytes = sz * sizeof(WCHAR);
143 LPWSTR buff = static_cast<LPWSTR>(_alloca(nbytes));
144 ZeroMemory(buff, nbytes);
145 MsiGetPropertyW(handle, name, buff, &sz);
146 value = buff;
147 return true;
149 return false;
152 static bool IsSetMsiPropW( MSIHANDLE handle, LPCWSTR name )
154 std::wstring val;
155 GetMsiPropW( handle, name, val );
156 return (val == L"1");
159 static void registerForExtension( MSIHANDLE handle, const int nIndex, bool bRegister )
161 WCHAR sPropName[256];
162 StringCchCopyW( sPropName, 256, L"REGISTER_" );
163 StringCchCatW( sPropName, 256, (g_Extensions[nIndex])+1 );
164 CharUpperBuffW( sPropName+9, 4 );
166 if ( bRegister ) {
167 MsiSetPropertyW( handle, sPropName, L"1" );
168 OutputDebugStringFormatW( L"Set MSI property %s.\n", sPropName );
169 } else {
170 MsiSetPropertyW( handle, sPropName, L"0" );
171 OutputDebugStringFormatW( L"Unset MSI property %s.\n", sPropName );
175 static void saveOldRegistration( LPCWSTR lpSubKey )
177 HKEY hKey = nullptr;
178 LONG lResult = RegOpenKeyExW( HKEY_CLASSES_ROOT, lpSubKey, 0,
179 KEY_QUERY_VALUE|KEY_SET_VALUE, &hKey );
181 if ( ERROR_SUCCESS == lResult )
183 WCHAR szBuffer[1024];
184 DWORD nSize = sizeof( szBuffer );
186 lResult = RegQueryValueExW( hKey, L"", nullptr, nullptr, reinterpret_cast<LPBYTE>(szBuffer), &nSize );
187 if ( ERROR_SUCCESS == lResult )
189 szBuffer[nSize/sizeof(*szBuffer)] = L'\0';
191 // No need to save associations for our own types
192 if ( wcsncmp( szBuffer, L"LibreOffice.", 12 ) != 0 )
194 // Save the old association
195 RegSetValueExW( hKey, L"LOBackupAssociation", 0,
196 REG_SZ, reinterpret_cast<LPBYTE>(szBuffer), nSize );
197 // Also save what the old association means, just so we can try to verify
198 // if/when restoring it that the old application still exists
199 HKEY hKey2 = nullptr;
200 lResult = RegOpenKeyExW( HKEY_CLASSES_ROOT, szBuffer, 0,
201 KEY_QUERY_VALUE, &hKey2 );
202 if ( ERROR_SUCCESS == lResult )
204 nSize = sizeof( szBuffer );
205 lResult = RegQueryValueExW( hKey2, L"", nullptr, nullptr, reinterpret_cast<LPBYTE>(szBuffer), &nSize );
206 if ( ERROR_SUCCESS == lResult )
208 RegSetValueExW( hKey, L"LOBackupAssociationDeref", 0,
209 REG_SZ, reinterpret_cast<LPBYTE>(szBuffer), nSize );
211 RegCloseKey( hKey2 );
215 RegCloseKey( hKey );
219 static void registerForExtensions( MSIHANDLE handle, bool bRegisterAll )
220 { // Check all file extensions
221 int nIndex = 0;
222 while ( g_Extensions[nIndex] != nullptr )
224 saveOldRegistration( g_Extensions[nIndex] );
226 bool bRegister = bRegisterAll || CheckExtensionInRegistry( g_Extensions[nIndex] );
227 if ( bRegister )
228 registerForExtension( handle, nIndex, true );
229 ++nIndex;
233 static bool checkSomeExtensionInRegistry( const int nStart, const int nEnd )
234 { // Check all file extensions
235 int nIndex = nStart;
236 bool bFound = false;
238 while ( !bFound && (nIndex < nEnd) && (g_Extensions[nIndex] != nullptr) )
240 bFound = ! CheckExtensionInRegistry( g_Extensions[nIndex] );
242 if ( bFound )
243 OutputDebugStringFormatW( L"Found registration for [%s].\n", g_Extensions[nIndex] );
245 ++nIndex;
247 return bFound;
250 static void registerSomeExtensions( MSIHANDLE handle, const int nStart, const int nEnd, bool bRegister )
251 { // Check all file extensions
252 int nIndex = nStart;
254 while ( (nIndex < nEnd) && (g_Extensions[nIndex] != nullptr) )
256 registerForExtension( handle, nIndex++, bRegister );
260 extern "C" __declspec(dllexport) UINT __stdcall LookForRegisteredExtensions( MSIHANDLE handle )
262 OutputDebugStringFormatW( L"LookForRegisteredExtensions: " );
264 INSTALLSTATE current_state;
265 INSTALLSTATE future_state;
267 bool bWriterEnabled = false;
268 bool bCalcEnabled = false;
269 bool bImpressEnabled = false;
270 bool bDrawEnabled = false;
271 bool bRegisterNone = IsSetMsiPropW( handle, L"REGISTER_NO_MSO_TYPES" );
273 if ( ( ERROR_SUCCESS == MsiGetFeatureStateW( handle, L"gm_p_Wrt", &current_state, &future_state ) ) &&
274 ( (future_state == INSTALLSTATE_LOCAL) || ((current_state == INSTALLSTATE_LOCAL) && (future_state == INSTALLSTATE_UNKNOWN) ) ) )
275 bWriterEnabled = true;
277 OutputDebugStringFormatW( L"LookForRegisteredExtensions: Install state Writer is [%d], will be [%d]", current_state, future_state );
278 if ( bWriterEnabled )
279 OutputDebugStringFormatW( L"LookForRegisteredExtensions: Writer is enabled" );
280 else
281 OutputDebugStringFormatW( L"LookForRegisteredExtensions: Writer is NOT enabled" );
283 if ( ( ERROR_SUCCESS == MsiGetFeatureStateW( handle, L"gm_p_Calc", &current_state, &future_state ) ) &&
284 ( (future_state == INSTALLSTATE_LOCAL) || ((current_state == INSTALLSTATE_LOCAL) && (future_state == INSTALLSTATE_UNKNOWN) ) ) )
285 bCalcEnabled = true;
287 OutputDebugStringFormatW( L"LookForRegisteredExtensions: Install state Calc is [%d], will be [%d]", current_state, future_state );
288 if ( bCalcEnabled )
289 OutputDebugStringFormatW( L"LookForRegisteredExtensions: Calc is enabled" );
290 else
291 OutputDebugStringFormatW( L"LookForRegisteredExtensions: Calc is NOT enabled" );
293 if ( ( ERROR_SUCCESS == MsiGetFeatureStateW( handle, L"gm_p_Impress", &current_state, &future_state ) ) &&
294 ( (future_state == INSTALLSTATE_LOCAL) || ((current_state == INSTALLSTATE_LOCAL) && (future_state == INSTALLSTATE_UNKNOWN) ) ) )
295 bImpressEnabled = true;
297 OutputDebugStringFormatW( L"LookForRegisteredExtensions: Install state Impress is [%d], will be [%d]", current_state, future_state );
298 if ( bImpressEnabled )
299 OutputDebugStringFormatW( L"LookForRegisteredExtensions: Impress is enabled" );
300 else
301 OutputDebugStringFormatW( L"LookForRegisteredExtensions: Impress is NOT enabled" );
303 if ( ( ERROR_SUCCESS == MsiGetFeatureStateW( handle, L"gm_p_Draw", &current_state, &future_state ) ) &&
304 ( (future_state == INSTALLSTATE_LOCAL) || ((current_state == INSTALLSTATE_LOCAL) && (future_state == INSTALLSTATE_UNKNOWN) ) ) )
305 bDrawEnabled = true;
307 OutputDebugStringFormatW( L"LookForRegisteredExtensions: Install state Draw is [%d], will be [%d]", current_state, future_state );
308 if ( bImpressEnabled )
309 OutputDebugStringFormatW( L"LookForRegisteredExtensions: Draw is enabled" );
310 else
311 OutputDebugStringFormatW( L"LookForRegisteredExtensions: Draw is NOT enabled" );
313 MsiSetPropertyW( handle, L"SELECT_WORD", L"" );
314 MsiSetPropertyW( handle, L"SELECT_EXCEL", L"" );
315 MsiSetPropertyW( handle, L"SELECT_POWERPOINT", L"" );
316 MsiSetPropertyW( handle, L"SELECT_VISIO", L"" );
318 if ( ! bRegisterNone )
320 if ( IsSetMsiPropW( handle, L"REGISTER_ALL_MSO_TYPES" ) )
322 if ( bWriterEnabled )
323 MsiSetPropertyW( handle, L"SELECT_WORD", L"1" );
324 if ( bCalcEnabled )
325 MsiSetPropertyW( handle, L"SELECT_EXCEL", L"1" );
326 if ( bImpressEnabled )
327 MsiSetPropertyW( handle, L"SELECT_POWERPOINT", L"1" );
328 if ( bDrawEnabled )
329 MsiSetPropertyW( handle, L"SELECT_VISIO", L"1" );
331 else
333 if ( bWriterEnabled && ! checkSomeExtensionInRegistry( WORD_START, EXCEL_START ) )
335 MsiSetPropertyW( handle, L"SELECT_WORD", L"1" );
336 OutputDebugStringFormatW( L"LookForRegisteredExtensions: Register for Microsoft Word" );
338 if ( bCalcEnabled && ! checkSomeExtensionInRegistry( EXCEL_START, POWERPOINT_START ) )
340 MsiSetPropertyW( handle, L"SELECT_EXCEL", L"1" );
341 OutputDebugStringFormatW( L"LookForRegisteredExtensions: Register for Microsoft Excel" );
343 if ( bImpressEnabled && ! checkSomeExtensionInRegistry( POWERPOINT_START, VISIO_START ) )
345 MsiSetPropertyW( handle, L"SELECT_POWERPOINT", L"1" );
346 OutputDebugStringFormatW( L"LookForRegisteredExtensions: Register for Microsoft PowerPoint" );
348 if ( bImpressEnabled && ! checkSomeExtensionInRegistry( VISIO_START, VISIO_END ) )
350 MsiSetPropertyW( handle, L"SELECT_VISIO", L"1" );
351 OutputDebugStringFormatW( L"LookForRegisteredExtensions: Register for Microsoft Visio" );
356 MsiSetPropertyW( handle, L"FILETYPEDIALOGUSED", L"1" );
358 return ERROR_SUCCESS;
361 extern "C" __declspec(dllexport) UINT __stdcall RegisterSomeExtensions( MSIHANDLE handle )
363 OutputDebugStringFormatW( L"RegisterSomeExtensions: " );
365 if ( IsSetMsiPropW( handle, L"SELECT_WORD" ) )
367 registerSomeExtensions( handle, WORD_START, EXCEL_START, true );
368 MsiSetFeatureStateW( handle, L"gm_p_Wrt_MSO_Reg", INSTALLSTATE_LOCAL );
369 OutputDebugStringFormatW( L"RegisterSomeExtensions: Register for Microsoft Word" );
371 else
373 registerSomeExtensions( handle, WORD_START, EXCEL_START, false );
374 MsiSetFeatureStateW( handle, L"gm_p_Wrt_MSO_Reg", INSTALLSTATE_ABSENT );
377 if ( IsSetMsiPropW( handle, L"SELECT_EXCEL" ) )
379 registerSomeExtensions( handle, EXCEL_START, POWERPOINT_START, true );
380 MsiSetFeatureStateW( handle, L"gm_p_Calc_MSO_Reg", INSTALLSTATE_LOCAL );
381 OutputDebugStringFormatW( L"RegisterSomeExtensions: Register for Microsoft Excel" );
383 else
385 registerSomeExtensions( handle, EXCEL_START, POWERPOINT_START, false );
386 MsiSetFeatureStateW( handle, L"gm_p_Calc_MSO_Reg", INSTALLSTATE_ABSENT );
389 if ( IsSetMsiPropW( handle, L"SELECT_POWERPOINT" ) )
391 registerSomeExtensions( handle, POWERPOINT_START, VISIO_START, true );
392 MsiSetFeatureStateW( handle, L"gm_p_Impress_MSO_Reg", INSTALLSTATE_LOCAL );
393 OutputDebugStringFormatW( L"RegisterSomeExtensions: Register for Microsoft PowerPoint" );
395 else
397 registerSomeExtensions( handle, POWERPOINT_START, VISIO_START, false );
398 MsiSetFeatureStateW( handle, L"gm_p_Impress_MSO_Reg", INSTALLSTATE_ABSENT );
401 if ( IsSetMsiPropW( handle, L"SELECT_VISIO" ) )
403 registerSomeExtensions( handle, VISIO_START, VISIO_END, true );
404 MsiSetFeatureStateW( handle, L"gm_p_Draw_MSO_Reg", INSTALLSTATE_LOCAL );
405 OutputDebugStringFormatW( L"RegisterSomeExtensions: Register for Microsoft Visio" );
407 else
409 registerSomeExtensions( handle, VISIO_START, VISIO_END, false );
410 MsiSetFeatureStateW( handle, L"gm_p_Draw_MSO_Reg", INSTALLSTATE_ABSENT );
412 return ERROR_SUCCESS;
415 extern "C" __declspec(dllexport) UINT __stdcall FindRegisteredExtensions( MSIHANDLE handle )
417 if ( IsSetMsiPropW( handle, L"FILETYPEDIALOGUSED" ) )
419 OutputDebugStringFormatW( L"FindRegisteredExtensions: FILETYPEDIALOGUSED!" );
420 return ERROR_SUCCESS;
423 OutputDebugStringFormatW( L"FindRegisteredExtensions:" );
425 bool bRegisterAll = IsSetMsiPropW( handle, L"REGISTER_ALL_MSO_TYPES" );
427 if ( IsSetMsiPropW( handle, L"REGISTER_NO_MSO_TYPES" ) )
429 OutputDebugStringFormatW( L"FindRegisteredExtensions: Register none!" );
430 return ERROR_SUCCESS;
432 else if ( bRegisterAll )
433 OutputDebugStringFormatW( L"FindRegisteredExtensions: Force all on" );
434 else
435 OutputDebugStringFormatW( L"FindRegisteredExtensions: " );
437 // setting the msi properties SELECT_* will force registering for all corresponding
438 // file types
439 if ( IsSetMsiPropW( handle, L"SELECT_WORD" ) )
440 registerSomeExtensions( handle, WORD_START, EXCEL_START, true );
441 if ( IsSetMsiPropW( handle, L"SELECT_EXCEL" ) )
442 registerSomeExtensions( handle, EXCEL_START, POWERPOINT_START, true );
443 if ( IsSetMsiPropW( handle, L"SELECT_POWERPOINT" ) )
444 registerSomeExtensions( handle, POWERPOINT_START, VISIO_START, true );
445 if ( IsSetMsiPropW( handle, L"SELECT_VISIO" ) )
446 registerSomeExtensions( handle, VISIO_START, VISIO_END, true );
448 registerForExtensions( handle, bRegisterAll );
450 return ERROR_SUCCESS;
453 static void restoreOldRegistration( LPCWSTR lpSubKey )
455 HKEY hKey = nullptr;
456 LONG lResult = RegOpenKeyExW( HKEY_CLASSES_ROOT, lpSubKey, 0,
457 KEY_QUERY_VALUE|KEY_SET_VALUE, &hKey );
459 if ( ERROR_SUCCESS == lResult )
461 WCHAR szBuffer[1024];
462 DWORD nSize = sizeof( szBuffer );
464 lResult = RegQueryValueExW( hKey, L"LOBackupAssociation", nullptr, nullptr,
465 reinterpret_cast<LPBYTE>(szBuffer), &nSize );
466 if ( ERROR_SUCCESS == lResult )
468 szBuffer[nSize/sizeof(*szBuffer)] = L'\0';
469 HKEY hKey2 = nullptr;
470 lResult = RegOpenKeyExW( HKEY_CLASSES_ROOT, szBuffer, 0,
471 KEY_QUERY_VALUE, &hKey2 );
472 if ( ERROR_SUCCESS == lResult )
474 WCHAR szBuffer2[1024];
475 DWORD nSize2 = sizeof( szBuffer2 );
477 lResult = RegQueryValueExW( hKey2, L"", nullptr, nullptr, reinterpret_cast<LPBYTE>(szBuffer2), &nSize2 );
478 if ( ERROR_SUCCESS == lResult )
480 WCHAR szBuffer3[1024];
481 DWORD nSize3 = sizeof( szBuffer3 );
483 // Try to verify that the old association is OK to restore
484 lResult = RegQueryValueExW( hKey, L"LOBackupAssociationDeref", nullptr, nullptr,
485 reinterpret_cast<LPBYTE>(szBuffer3), &nSize3 );
486 if ( ERROR_SUCCESS == lResult )
488 if ( nSize2 == nSize3 && wcsncmp (szBuffer2, szBuffer3, nSize2/sizeof(*szBuffer2)) == 0)
490 // Yep. So restore it
491 RegSetValueExW( hKey, L"", 0, REG_SZ, reinterpret_cast<LPBYTE>(szBuffer), nSize );
495 RegCloseKey( hKey2 );
497 RegDeleteValueW( hKey, L"LOBackupAssociation" );
499 RegDeleteValueW( hKey, L"LOBackupAssociationDeref" );
500 RegCloseKey( hKey );
504 extern "C" __declspec(dllexport) UINT __stdcall RestoreRegAllMSDoc( MSIHANDLE /*handle*/ )
506 OutputDebugStringFormatW( L"RestoreRegAllMSDoc\n" );
508 int nIndex = 0;
509 while ( g_Extensions[nIndex] != nullptr )
511 restoreOldRegistration( g_Extensions[nIndex] );
512 ++nIndex;
516 return ERROR_SUCCESS;
519 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */