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