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 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 77 static inline void OutputDebugStringFormat( const wchar_t*, ... ) 78 { 79 } 80 #endif 81 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 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 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 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 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 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 //--------------------------------------- 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 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 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 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 451 extern "C" UINT __stdcall InstallReg64(MSIHANDLE hMSI) 452 { 453 OutputDebugStringFormat(L"InstallReg64\n" ); 454 Reg64(hMSI, SET); 455 return ERROR_SUCCESS; 456 } 457 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