xref: /AOO42X/main/setup_native/source/win32/customactions/reg64/reg64.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3) !
1 /*************************************************************************
2 *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26 ************************************************************************/
27 
28 /*
29 
30 */
31 
32 
33 #define UNICODE
34 
35 #ifdef _MSC_VER
36 #pragma warning(push, 1) /* disable warnings within system headers */
37 #endif
38 #define WIN32_LEAN_AND_MEAN
39 #include <windows.h>
40 #include <msiquery.h>
41 #ifdef _MSC_VER
42 #pragma warning(pop)
43 #endif
44 
45 #include <malloc.h>
46 //#include <string>
47 //#include <map>
48 #include <strsafe.h>
49 
50 // 10.11.2009 tkr: MinGW doesn't know anything about RegDeleteKeyExW if WINVER < 0x0502.
51 extern "C" {
52 WINADVAPI LONG WINAPI RegDeleteKeyExW(HKEY,LPCWSTR,REGSAM,DWORD);
53 }
54 
55 // 06.11.2009 tkr: to provide windows xp as build systems for mingw we need to define KEY_WOW64_64KEY
56 // in mingw 3.13 KEY_WOW64_64KEY isn't available < Win2003 systems.
57 // Also defined in setup_native\source\win32\customactions\reg64\reg64.cxx,source\win32\customactions\shellextensions\shellextensions.cxx and
58 // extensions\source\activex\main\so_activex.cpp
59 
60 #ifndef KEY_WOW64_64KEY
61     #define KEY_WOW64_64KEY (0x0100)
62 #endif
63 
64 
65 #define TABLE_NAME L"Reg64"
66 #define INSTALLLOCATION L"[INSTALLLOCATION]"
67 
68 bool isInstall4AllUsers;
69 wchar_t * sBasisInstallLocation;
70 
71 
72 enum OPERATION {
73     SET,
74     REMOVE
75 };
76 
77 #ifdef DEBUG
78 inline void OutputDebugStringFormat( const wchar_t* pFormat, ... )
79 {
80     wchar_t    buffer[1024];
81     va_list args;
82 
83     va_start( args, pFormat );
84     StringCchVPrintf( buffer, sizeof(buffer), pFormat, args );
85     OutputDebugString( buffer );
86 }
87 #else
88 static inline void OutputDebugStringFormat( const wchar_t*, ... )
89 {
90 }
91 #endif
92 
93 bool WriteRegistry( MSIHANDLE & hMSI, OPERATION op, const wchar_t* componentName)
94 {
95     INSTALLSTATE current_state;
96     INSTALLSTATE comp_state;
97     UINT ret = MsiGetComponentState( hMSI, componentName, &current_state, &comp_state );
98     if ( ERROR_SUCCESS == ret )
99     {
100         if (current_state == INSTALLSTATE_ABSENT)
101             OutputDebugStringFormat(L"WriteRegistry - current_state: INSTALLSTATE_ABSENT");
102         else if (current_state == INSTALLSTATE_DEFAULT)
103             OutputDebugStringFormat(L"WriteRegistry - current_state: INSTALLSTATE_DEFAULT");
104         else if (current_state == INSTALLSTATE_LOCAL)
105             OutputDebugStringFormat(L"WriteRegistry - current_state: INSTALLSTATE_LOCAL");
106         else if (current_state == INSTALLSTATE_REMOVED)
107             OutputDebugStringFormat(L"WriteRegistry - current_state: INSTALLSTATE_REMOVED");
108         else if (current_state == INSTALLSTATE_SOURCE)
109             OutputDebugStringFormat(L"WriteRegistry - current_state: INSTALLSTATE_SOURCE");
110         else if (current_state == INSTALLSTATE_UNKNOWN)
111             OutputDebugStringFormat(L"WriteRegistry - current_state: INSTALLSTATE_UNKNOWN");
112 
113         if (comp_state == INSTALLSTATE_ABSENT)
114             OutputDebugStringFormat(L"WriteRegistry - comp_state: INSTALLSTATE_ABSENT");
115         else if (comp_state == INSTALLSTATE_DEFAULT)
116             OutputDebugStringFormat(L"WriteRegistry - comp_state: INSTALLSTATE_DEFAULT");
117         else if (comp_state == INSTALLSTATE_LOCAL)
118             OutputDebugStringFormat(L"WriteRegistry - comp_state: INSTALLSTATE_LOCAL");
119         else if (comp_state == INSTALLSTATE_REMOVED)
120             OutputDebugStringFormat(L"WriteRegistry - comp_state: INSTALLSTATE_REMOVED");
121         else if (comp_state == INSTALLSTATE_SOURCE)
122             OutputDebugStringFormat(L"WriteRegistry - comp_state: INSTALLSTATE_SOURCE");
123         else if (comp_state == INSTALLSTATE_UNKNOWN)
124             OutputDebugStringFormat(L"WriteRegistry - comp_state: INSTALLSTATE_UNKNOWN");
125 
126         switch (op)
127         {
128             case SET :
129                 if ( comp_state == INSTALLSTATE_LOCAL || ( current_state == INSTALLSTATE_LOCAL && comp_state == INSTALLSTATE_UNKNOWN ) )
130                 {
131                     return true;
132                 }
133                 break;
134             case REMOVE:
135                 OutputDebugStringFormat(L"WriteRegistry - Remove\n" );
136                 if ( current_state == INSTALLSTATE_LOCAL && (comp_state == INSTALLSTATE_ABSENT || comp_state == INSTALLSTATE_REMOVED) )
137                 {
138                     OutputDebugStringFormat(L"WriteRegistry - To be removed\n" );
139                     return true;
140                 }
141         }
142     } else
143     {
144         if (ERROR_INVALID_HANDLE == ret) OutputDebugStringFormat(L"WriteRegistry - Invalid handle");
145         if (ERROR_UNKNOWN_FEATURE  == ret) OutputDebugStringFormat(L"WriteRegistry - Unknown feature");
146     }
147 
148     return false;
149 }
150 
151 BOOL UnicodeEquals( wchar_t* pStr1, wchar_t* pStr2 )
152 {
153     if ( pStr1 == NULL && pStr2 == NULL )
154         return TRUE;
155     else if ( pStr1 == NULL || pStr2 == NULL )
156         return FALSE;
157 
158     while( *pStr1 == *pStr2 && *pStr1 && *pStr2 )
159         pStr1++, pStr2++;
160 
161     return ( *pStr1 == 0 && *pStr2 == 0 );
162 }
163 
164 BOOL GetMsiProp( MSIHANDLE hMSI, const wchar_t* pPropName, wchar_t** ppValue )
165 {
166     OutputDebugStringFormat(L"GetMsiProp - START\n" );
167     DWORD sz = 0;
168     UINT ret = MsiGetProperty( hMSI, pPropName, L"", &sz );
169     if ( ret == ERROR_MORE_DATA )
170     {
171         sz++;
172         DWORD nbytes = sz * sizeof( wchar_t );
173         wchar_t* buff = reinterpret_cast<wchar_t*>( malloc( nbytes ) );
174         ZeroMemory( buff, nbytes );
175         MsiGetProperty( hMSI, pPropName, buff, &sz );
176 
177         OutputDebugStringFormat(L"GetMsiProp - Value" );
178         OutputDebugStringFormat( buff );
179         *ppValue = buff;
180 
181         return TRUE;
182     } else if (ret  == ERROR_INVALID_HANDLE)
183     {
184         OutputDebugStringFormat(L"GetMsiProp - ERROR_INVALID_HANDLE" );
185     } else if (ret == ERROR_INVALID_PARAMETER)
186     {
187         OutputDebugStringFormat(L"GetMsiProp - ERROR_INVALID_PARAMETER" );
188     } else if (ret == ERROR_SUCCESS)
189     {
190         OutputDebugStringFormat(L"GetMsiProp - ERROR_SUCCESS" );
191     }
192 
193 
194     OutputDebugStringFormat(L"GetMsiProp - ENDE\n" );
195     return FALSE;
196 }
197 
198 bool IsInstallForAllUsers( MSIHANDLE hMSI )
199 {
200     OutputDebugStringFormat(L"IsInstallForAllUsers - START\n" );
201     bool bResult = FALSE;
202     wchar_t* pVal = NULL;
203     if ( GetMsiProp( hMSI, L"ALLUSERS", &pVal ) && pVal )
204     {
205         bResult = UnicodeEquals( pVal , L"1" );
206         free( pVal );
207     }
208 
209     OutputDebugStringFormat(L"IsInstallForAllUsers - ENDE\n" );
210     return bResult;
211 }
212 
213 wchar_t* GetBasisInstallLocation( MSIHANDLE hMSI )
214 {
215     OutputDebugStringFormat(L"GetBasisInstallLocation - START\n" );
216     bool bResult = FALSE;
217     wchar_t* pVal = NULL;
218     GetMsiProp( hMSI, L"INSTALLLOCATION", &pVal);
219 
220     OutputDebugStringFormat(L"GetBasisInstallLocation - ENDE\n" );
221 
222     return pVal;
223 }
224 
225 
226 bool QueryReg64Table(MSIHANDLE& rhDatabase, MSIHANDLE& rhView)
227 {
228     OutputDebugStringFormat(L"QueryReg64Table - START\n" );
229     int const arraysize = 400;
230     wchar_t szSelect[arraysize];
231     StringCbPrintfW(szSelect, arraysize * sizeof(wchar_t), L"SELECT * FROM %s",TABLE_NAME);
232     OutputDebugStringFormat( szSelect );
233 
234     UINT ret = MsiDatabaseOpenView(rhDatabase,szSelect,&rhView);
235     if (ret != ERROR_SUCCESS)
236     {
237         if ( ret == ERROR_BAD_QUERY_SYNTAX)
238             OutputDebugStringFormat(L"QueryReg64Table - MsiDatabaseOpenView - FAILED - ERROR_BAD_QUERY_SYNTAX\n" );
239         if ( ret == ERROR_INVALID_HANDLE)
240             OutputDebugStringFormat(L"QueryReg64Table - MsiDatabaseOpenView - FAILED - ERROR_INVALID_HANDLE\n" );
241         return false;
242     }
243     // execute query - not a parameter query so second parameter is NULL.
244     if (MsiViewExecute(rhView,NULL) != ERROR_SUCCESS)
245     {
246         OutputDebugStringFormat(L"QueryReg64Table - MsiViewExecute - FAILED\n" );
247         return false;
248     }
249 
250     OutputDebugStringFormat(L"QueryReg64Table - ENDE\n" );
251     return true;
252 }
253 
254 //---------------------------------------
255 bool DeleteRegistryKey(HKEY RootKey, const wchar_t* KeyName)
256 {
257     int rc = RegDeleteKeyExW(
258         RootKey, KeyName, KEY_WOW64_64KEY, 0);
259 
260     return (ERROR_SUCCESS == rc);
261 }
262 
263 
264 
265 
266 //---------------------------------------
267 //
268 //---------------------------------------
269 
270 bool SetRegistryKey(HKEY RootKey, const wchar_t* KeyName, const wchar_t* ValueName, const wchar_t* Value)
271 {
272     HKEY hSubKey;
273 
274     // open or create the desired key
275     int rc = RegCreateKeyEx(
276         RootKey, KeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_WOW64_64KEY, 0, &hSubKey, 0);
277 
278     if (ERROR_SUCCESS == rc)
279     {
280         OutputDebugStringFormat(L"SetRegistryKey - Created\n" );
281         rc = RegSetValueEx(
282             hSubKey, ValueName, 0, REG_SZ, reinterpret_cast<const BYTE*>(Value), (wcslen(Value) + 1) * sizeof(wchar_t));
283 
284         RegCloseKey(hSubKey);
285     } else {
286         OutputDebugStringFormat(L"SetRegistryKey - FAILED\n" );
287     }
288 
289 
290     return (ERROR_SUCCESS == rc);
291 }
292 
293 bool DoRegEntries( MSIHANDLE& rhMSI, OPERATION op, MSIHANDLE& rhView)
294 {
295     OutputDebugStringFormat(L"DoRegEntries - START\n" );
296 
297     MSIHANDLE hRecord;
298 
299     long lRoot;
300     wchar_t  szKey[255];
301     wchar_t  szName[255];
302     wchar_t  szValue[1024];
303     wchar_t  szComponent[255];
304 
305     /// read records until there are no more records
306     while (MsiViewFetch(rhView,&hRecord) == ERROR_SUCCESS)
307     {
308         DWORD    dwKey = 255;
309         DWORD    dwName = 255;
310         DWORD    dwValue = 1024;
311         DWORD    dwComponent = 255;
312 
313         szKey[0] = '\0';
314         szName[0] = '\0';
315         szValue[0] = '\0';
316         szComponent[0] = '\0';
317 
318         lRoot = MsiRecordGetInteger(hRecord,2);
319         MsiRecordGetString(hRecord,3,szKey,&dwKey);
320 
321         if (!MsiRecordIsNull(hRecord, 4))
322             MsiRecordGetString(hRecord,4,szName,&dwName);
323 
324         if (!MsiRecordIsNull(hRecord, 5))
325         {
326             MsiRecordGetString(hRecord,5,szValue,&dwValue);
327 
328 
329 
330             wchar_t* nPos = wcsstr(szValue , INSTALLLOCATION);
331             if ( NULL != nPos)
332             {
333 
334                 DWORD nPrefixSize = nPos - szValue;
335 
336                 DWORD nPropSize = wcslen(sBasisInstallLocation);
337                 DWORD nPostfixSize = dwValue - wcslen( INSTALLLOCATION );
338 
339                 DWORD nNewValueBytes = (nPropSize + nPostfixSize + 1) * sizeof( wchar_t );
340                 wchar_t* newValue = reinterpret_cast<wchar_t*>( malloc( nNewValueBytes ) );
341                 ZeroMemory( newValue, nNewValueBytes );
342 
343                 // prefix
344                 wcsncpy(newValue, szValue, nPrefixSize);
345 
346                 // basis location
347                 wcsncat(newValue, sBasisInstallLocation, nPropSize * sizeof( wchar_t ));
348 
349                 // postfix
350                 wcsncat(newValue, nPos + ( wcslen( INSTALLLOCATION ) ), nPropSize * sizeof( wchar_t ));
351 
352                 wcsncpy(szValue, newValue, nNewValueBytes <=1024? nNewValueBytes: 1024);
353 
354                 free(newValue);
355             }
356 
357         }
358 
359 
360         MsiRecordGetString(hRecord,6,szComponent,&dwComponent);
361 
362         OutputDebugStringFormat(L"****** DoRegEntries *******" );
363         OutputDebugStringFormat(L"Root:" );
364         HKEY key = HKEY_CURRENT_USER;
365         switch (lRoot)
366         {
367             case(-1):
368                     if (isInstall4AllUsers)
369                     {
370                         key = HKEY_LOCAL_MACHINE;
371                         OutputDebugStringFormat(L"HKEY_LOCAL_MACHINE" );
372                     }
373                     else
374                     {
375                         key = HKEY_CURRENT_USER;
376                         OutputDebugStringFormat(L"HKEY_CURRENT_USER" );
377                     }
378                 break;
379             case(0):
380                     key = HKEY_CLASSES_ROOT;
381                     OutputDebugStringFormat(L"HKEY_CLASSES_ROOT" );
382                 break;
383             case(1):
384                     key = HKEY_CURRENT_USER;
385                     OutputDebugStringFormat(L"HKEY_CURRENT_USER" );
386                 break;
387             case(2):
388                     key = HKEY_LOCAL_MACHINE;
389                     OutputDebugStringFormat(L"HKEY_LOCAL_MACHINE" );
390                 break;
391             case(3):
392                     key = HKEY_USERS;
393                     OutputDebugStringFormat(L"HKEY_USERS" );
394                 break;
395             default:
396                     OutputDebugStringFormat(L"Unknown Root!" );
397                 break;
398         }
399 
400         OutputDebugStringFormat(L"Key:");
401         OutputDebugStringFormat( szKey );
402         OutputDebugStringFormat(L"Name:");
403         OutputDebugStringFormat( szName );
404         OutputDebugStringFormat(L"Value:");
405         OutputDebugStringFormat( szValue);
406         OutputDebugStringFormat(L"Component:");
407         OutputDebugStringFormat( szComponent );
408         OutputDebugStringFormat(L"*******************" );
409         switch (op)
410         {
411             case SET:
412 
413                     if (WriteRegistry(rhMSI, SET, szComponent))
414                     {
415                         OutputDebugStringFormat(L"DoRegEntries - Write\n" );
416                         SetRegistryKey(key, szKey, szName, szValue);
417                     }
418                 break;
419             case REMOVE:
420                     OutputDebugStringFormat(L"DoRegEntries - PreRemove\n" );
421                     if (WriteRegistry(rhMSI, REMOVE, szComponent))
422                     {
423                         OutputDebugStringFormat(L"DoRegEntries - Remove\n" );
424                         DeleteRegistryKey(key, szKey);
425                     }
426                 break;
427         }
428     }
429 
430     MsiCloseHandle(rhView);
431 
432 
433     OutputDebugStringFormat(L"DoRegEntries - ENDE\n" );
434 
435     return true;
436 }
437 
438 
439 bool Reg64(MSIHANDLE& rhMSI, OPERATION op)
440 {
441     isInstall4AllUsers = IsInstallForAllUsers(rhMSI);
442     sBasisInstallLocation = GetBasisInstallLocation(rhMSI);
443 
444     if (NULL == sBasisInstallLocation)
445     {
446         OutputDebugStringFormat(L"BASISINSTALLLOCATION is NULL\n" );
447         return false;
448     }
449 
450     MSIHANDLE hView;
451     MSIHANDLE hDatabase = MsiGetActiveDatabase(rhMSI);
452 
453     QueryReg64Table(hDatabase, hView);
454     OutputDebugStringFormat(L"Do something\n" );
455     DoRegEntries( rhMSI, op, hView);
456     OutputDebugStringFormat(L"Something done\n" );
457 
458     MsiCloseHandle(hView);
459     MsiCloseHandle(hDatabase);
460     free(sBasisInstallLocation);
461 
462     return true;
463 }
464 
465 extern "C" UINT __stdcall InstallReg64(MSIHANDLE hMSI)
466 {
467     OutputDebugStringFormat(L"InstallReg64\n" );
468     Reg64(hMSI, SET);
469     return ERROR_SUCCESS;
470 }
471 
472 extern "C" UINT __stdcall DeinstallReg64(MSIHANDLE hMSI)
473 {
474     OutputDebugStringFormat(L"DeinstallReg64\n" );
475     Reg64(hMSI, REMOVE);
476     return ERROR_SUCCESS;
477 }