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 #define WIN32_LEAN_AND_MEAN
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
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
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
76 inline void OutputDebugStringFormatW( LPCWSTR pFormat
, ... )
81 va_start( args
, pFormat
);
82 StringCchVPrintfW( buffer
, sizeof(buffer
)/sizeof(*buffer
), pFormat
, args
);
83 OutputDebugStringW( buffer
);
87 static void OutputDebugStringFormatW( LPCWSTR
, ... )
92 static bool CheckExtensionInRegistry( LPCWSTR lpSubKey
)
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
113 else if ( wcsncmp( szBuffer
, L
"LibreOffice.", 12 ) == 0 )
114 { // We will replace registration for our own types, too
117 else if ( wcsncmp( szBuffer
, L
"lostub.", 7 ) == 0 )
118 { // We will replace registration for lostub, too
121 else // we have a default value -> do not register, see fdo#39791
124 else // no default value found -> return TRUE to register for that key
129 else // no key found -> return TRUE to register for that key
135 static bool GetMsiPropW( MSIHANDLE handle
, LPCWSTR name
, /*out*/std::wstring
& value
)
138 LPWSTR dummy
= const_cast<LPWSTR
>(L
"");
139 if (MsiGetPropertyW(handle
, name
, dummy
, &sz
) == ERROR_MORE_DATA
)
142 DWORD nbytes
= sz
* sizeof(WCHAR
);
143 LPWSTR buff
= static_cast<LPWSTR
>(_alloca(nbytes
));
144 ZeroMemory(buff
, nbytes
);
145 MsiGetPropertyW(handle
, name
, buff
, &sz
);
152 static bool IsSetMsiPropW( MSIHANDLE handle
, LPCWSTR name
)
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 );
167 MsiSetPropertyW( handle
, sPropName
, L
"1" );
168 OutputDebugStringFormatW( L
"Set MSI property %s.\n", sPropName
);
170 MsiSetPropertyW( handle
, sPropName
, L
"0" );
171 OutputDebugStringFormatW( L
"Unset MSI property %s.\n", sPropName
);
175 static void saveOldRegistration( LPCWSTR lpSubKey
)
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
);
219 static void registerForExtensions( MSIHANDLE handle
, bool bRegisterAll
)
220 { // Check all file extensions
222 while ( g_Extensions
[nIndex
] != nullptr )
224 saveOldRegistration( g_Extensions
[nIndex
] );
226 bool bRegister
= bRegisterAll
|| CheckExtensionInRegistry( g_Extensions
[nIndex
] );
228 registerForExtension( handle
, nIndex
, true );
233 static bool checkSomeExtensionInRegistry( const int nStart
, const int nEnd
)
234 { // Check all file extensions
238 while ( !bFound
&& (nIndex
< nEnd
) && (g_Extensions
[nIndex
] != nullptr) )
240 bFound
= ! CheckExtensionInRegistry( g_Extensions
[nIndex
] );
243 OutputDebugStringFormatW( L
"Found registration for [%s].\n", g_Extensions
[nIndex
] );
250 static void registerSomeExtensions( MSIHANDLE handle
, const int nStart
, const int nEnd
, bool bRegister
)
251 { // Check all file extensions
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", ¤t_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" );
281 OutputDebugStringFormatW( L
"LookForRegisteredExtensions: Writer is NOT enabled" );
283 if ( ( ERROR_SUCCESS
== MsiGetFeatureStateW( handle
, L
"gm_p_Calc", ¤t_state
, &future_state
) ) &&
284 ( (future_state
== INSTALLSTATE_LOCAL
) || ((current_state
== INSTALLSTATE_LOCAL
) && (future_state
== INSTALLSTATE_UNKNOWN
) ) ) )
287 OutputDebugStringFormatW( L
"LookForRegisteredExtensions: Install state Calc is [%d], will be [%d]", current_state
, future_state
);
289 OutputDebugStringFormatW( L
"LookForRegisteredExtensions: Calc is enabled" );
291 OutputDebugStringFormatW( L
"LookForRegisteredExtensions: Calc is NOT enabled" );
293 if ( ( ERROR_SUCCESS
== MsiGetFeatureStateW( handle
, L
"gm_p_Impress", ¤t_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" );
301 OutputDebugStringFormatW( L
"LookForRegisteredExtensions: Impress is NOT enabled" );
303 if ( ( ERROR_SUCCESS
== MsiGetFeatureStateW( handle
, L
"gm_p_Draw", ¤t_state
, &future_state
) ) &&
304 ( (future_state
== INSTALLSTATE_LOCAL
) || ((current_state
== INSTALLSTATE_LOCAL
) && (future_state
== INSTALLSTATE_UNKNOWN
) ) ) )
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" );
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" );
325 MsiSetPropertyW( handle
, L
"SELECT_EXCEL", L
"1" );
326 if ( bImpressEnabled
)
327 MsiSetPropertyW( handle
, L
"SELECT_POWERPOINT", L
"1" );
329 MsiSetPropertyW( handle
, L
"SELECT_VISIO", L
"1" );
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" );
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" );
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" );
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" );
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" );
435 OutputDebugStringFormatW( L
"FindRegisteredExtensions: " );
437 // setting the msi properties SELECT_* will force registering for all corresponding
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
)
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" );
504 extern "C" __declspec(dllexport
) UINT __stdcall
RestoreRegAllMSDoc( MSIHANDLE
/*handle*/ )
506 OutputDebugStringFormatW( L
"RestoreRegAllMSDoc\n" );
509 while ( g_Extensions
[nIndex
] != nullptr )
511 restoreOldRegistration( g_Extensions
[nIndex
] );
516 return ERROR_SUCCESS
;
519 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */