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