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, ¤t_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 }