132b1fd08SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 332b1fd08SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 432b1fd08SAndrew Rist * or more contributor license agreements. See the NOTICE file 532b1fd08SAndrew Rist * distributed with this work for additional information 632b1fd08SAndrew Rist * regarding copyright ownership. The ASF licenses this file 732b1fd08SAndrew Rist * to you under the Apache License, Version 2.0 (the 832b1fd08SAndrew Rist * "License"); you may not use this file except in compliance 932b1fd08SAndrew Rist * with the License. You may obtain a copy of the License at 1032b1fd08SAndrew Rist * 1132b1fd08SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 1232b1fd08SAndrew Rist * 1332b1fd08SAndrew Rist * Unless required by applicable law or agreed to in writing, 1432b1fd08SAndrew Rist * software distributed under the License is distributed on an 1532b1fd08SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 1632b1fd08SAndrew Rist * KIND, either express or implied. See the License for the 1732b1fd08SAndrew Rist * specific language governing permissions and limitations 1832b1fd08SAndrew Rist * under the License. 1932b1fd08SAndrew Rist * 2032b1fd08SAndrew Rist *************************************************************/ 2132b1fd08SAndrew Rist 2232b1fd08SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #define _WIN32_WINDOWS 0x0410 25cdf0e10cSrcweir 26cdf0e10cSrcweir #ifdef _MSC_VER 27cdf0e10cSrcweir #pragma warning(push, 1) /* disable warnings within system headers */ 28cdf0e10cSrcweir #endif 29cdf0e10cSrcweir #define WIN32_LEAN_AND_MEAN 30cdf0e10cSrcweir #include <windows.h> 31cdf0e10cSrcweir #include <msiquery.h> 32cdf0e10cSrcweir #ifdef _MSC_VER 33cdf0e10cSrcweir #pragma warning(pop) 34cdf0e10cSrcweir #endif 35cdf0e10cSrcweir 36cdf0e10cSrcweir #include <malloc.h> 37cdf0e10cSrcweir #include <assert.h> 38cdf0e10cSrcweir 39cdf0e10cSrcweir #ifdef UNICODE 40cdf0e10cSrcweir #define _UNICODE 41cdf0e10cSrcweir #define _tstring wstring 42cdf0e10cSrcweir #else 43cdf0e10cSrcweir #define _tstring string 44cdf0e10cSrcweir #endif 45cdf0e10cSrcweir #include <tchar.h> 46cdf0e10cSrcweir #include <string> 47cdf0e10cSrcweir #include <queue> 48cdf0e10cSrcweir #include <stdio.h> 49cdf0e10cSrcweir 50cdf0e10cSrcweir #include <systools/win32/uwinapi.h> 51cdf0e10cSrcweir #include <../tools/seterror.hxx> 52cdf0e10cSrcweir 53cdf0e10cSrcweir #define WININIT_FILENAME "wininit.ini" 54cdf0e10cSrcweir #define RENAME_SECTION "rename" 55cdf0e10cSrcweir 56cdf0e10cSrcweir #ifdef DEBUG 57cdf0e10cSrcweir inline void OutputDebugStringFormat( LPCTSTR pFormat, ... ) 58cdf0e10cSrcweir { 59cdf0e10cSrcweir _TCHAR buffer[1024]; 60cdf0e10cSrcweir va_list args; 61cdf0e10cSrcweir 62cdf0e10cSrcweir va_start( args, pFormat ); 63cdf0e10cSrcweir _vsntprintf( buffer, elementsof(buffer), pFormat, args ); 64cdf0e10cSrcweir OutputDebugString( buffer ); 65cdf0e10cSrcweir } 66cdf0e10cSrcweir #else 67cdf0e10cSrcweir static inline void OutputDebugStringFormat( LPCTSTR, ... ) 68cdf0e10cSrcweir { 69cdf0e10cSrcweir } 70cdf0e10cSrcweir #endif 71cdf0e10cSrcweir 72cdf0e10cSrcweir static std::_tstring GetMsiProperty( MSIHANDLE handle, const std::_tstring& sProperty ) 73cdf0e10cSrcweir { 74cdf0e10cSrcweir std::_tstring result; 75cdf0e10cSrcweir TCHAR szDummy[1] = TEXT(""); 76cdf0e10cSrcweir DWORD nChars = 0; 77cdf0e10cSrcweir 78cdf0e10cSrcweir if ( MsiGetProperty( handle, sProperty.c_str(), szDummy, &nChars ) == ERROR_MORE_DATA ) 79cdf0e10cSrcweir { 80cdf0e10cSrcweir DWORD nBytes = ++nChars * sizeof(TCHAR); 81cdf0e10cSrcweir LPTSTR buffer = reinterpret_cast<LPTSTR>(_alloca(nBytes)); 82cdf0e10cSrcweir ZeroMemory( buffer, nBytes ); 83cdf0e10cSrcweir MsiGetProperty(handle, sProperty.c_str(), buffer, &nChars); 84cdf0e10cSrcweir result = buffer; 85cdf0e10cSrcweir } 86cdf0e10cSrcweir 87cdf0e10cSrcweir return result; 88cdf0e10cSrcweir } 89cdf0e10cSrcweir 90cdf0e10cSrcweir // The provided GUID must be without surounding '{}' 91cdf0e10cSrcweir static std::_tstring GetGuidPart(const std::_tstring& guid, int index) 92cdf0e10cSrcweir { 93cdf0e10cSrcweir assert((guid.length() == 36) && "No GUID or wrong format!"); 94cdf0e10cSrcweir assert(((index > -1) && (index < 5)) && "Out of range!"); 95cdf0e10cSrcweir 96cdf0e10cSrcweir if (index == 0) return std::_tstring(guid.c_str(), 8); 97cdf0e10cSrcweir if (index == 1) return std::_tstring(guid.c_str() + 9, 4); 98cdf0e10cSrcweir if (index == 2) return std::_tstring(guid.c_str() + 14, 4); 99cdf0e10cSrcweir if (index == 3) return std::_tstring(guid.c_str() + 19, 4); 100cdf0e10cSrcweir if (index == 4) return std::_tstring(guid.c_str() + 24, 12); 101cdf0e10cSrcweir 102cdf0e10cSrcweir return std::_tstring(); 103cdf0e10cSrcweir } 104cdf0e10cSrcweir 105cdf0e10cSrcweir static void Swap(char* p1, char* p2) 106cdf0e10cSrcweir { 107cdf0e10cSrcweir char tmp = *p1; 108cdf0e10cSrcweir *p1 = *p2; 109cdf0e10cSrcweir *p2 = tmp; 110cdf0e10cSrcweir } 111cdf0e10cSrcweir 112cdf0e10cSrcweir static std::_tstring Invert(const std::_tstring& str) 113cdf0e10cSrcweir { 114cdf0e10cSrcweir char* buff = reinterpret_cast<char*>(_alloca(str.length())); 115cdf0e10cSrcweir strncpy(buff, str.c_str(), str.length()); 116cdf0e10cSrcweir 117cdf0e10cSrcweir char* front = buff; 118cdf0e10cSrcweir char* back = buff + str.length() - 1; 119cdf0e10cSrcweir 120cdf0e10cSrcweir while (front < back) 121cdf0e10cSrcweir Swap(front++, back--); 122cdf0e10cSrcweir 123cdf0e10cSrcweir return std::_tstring(buff, str.length()); 124cdf0e10cSrcweir } 125cdf0e10cSrcweir 126cdf0e10cSrcweir // Convert the upgrade code (which is a GUID) according 127cdf0e10cSrcweir // to the way the windows installer does when writing it 128cdf0e10cSrcweir // to the registry 129cdf0e10cSrcweir // The first 8 bytes will be inverted, from the the last 130cdf0e10cSrcweir // 8 bytes always the nibbles will be inverted for further 131cdf0e10cSrcweir // details look in the MSDN under compressed registry keys 132cdf0e10cSrcweir static std::_tstring ConvertGuid(const std::_tstring& guid) 133cdf0e10cSrcweir { 134cdf0e10cSrcweir std::_tstring convertedGuid; 135cdf0e10cSrcweir 136cdf0e10cSrcweir std::_tstring part = GetGuidPart(guid, 0); 137cdf0e10cSrcweir convertedGuid = Invert(part); 138cdf0e10cSrcweir 139cdf0e10cSrcweir part = GetGuidPart(guid, 1); 140cdf0e10cSrcweir convertedGuid += Invert(part); 141cdf0e10cSrcweir 142cdf0e10cSrcweir part = GetGuidPart(guid, 2); 143cdf0e10cSrcweir convertedGuid += Invert(part); 144cdf0e10cSrcweir 145cdf0e10cSrcweir part = GetGuidPart(guid, 3); 146cdf0e10cSrcweir convertedGuid += Invert(std::_tstring(part.c_str(), 2)); 147cdf0e10cSrcweir convertedGuid += Invert(std::_tstring(part.c_str() + 2, 2)); 148cdf0e10cSrcweir 149cdf0e10cSrcweir part = GetGuidPart(guid, 4); 150cdf0e10cSrcweir int pos = 0; 151cdf0e10cSrcweir for (int i = 0; i < 6; i++) 152cdf0e10cSrcweir { 153cdf0e10cSrcweir convertedGuid += Invert(std::_tstring(part.c_str() + pos, 2)); 154cdf0e10cSrcweir pos += 2; 155cdf0e10cSrcweir } 156cdf0e10cSrcweir return convertedGuid; 157cdf0e10cSrcweir } 158cdf0e10cSrcweir 159cdf0e10cSrcweir static inline bool IsSetMsiProperty(MSIHANDLE handle, const std::_tstring& sProperty) 160cdf0e10cSrcweir { 161cdf0e10cSrcweir std::_tstring value = GetMsiProperty(handle, sProperty); 162cdf0e10cSrcweir return (value.length() > 0); 163cdf0e10cSrcweir } 164cdf0e10cSrcweir 165cdf0e10cSrcweir static inline void UnsetMsiProperty(MSIHANDLE handle, const std::_tstring& sProperty) 166cdf0e10cSrcweir { 167cdf0e10cSrcweir MsiSetProperty(handle, sProperty.c_str(), NULL); 168cdf0e10cSrcweir } 169cdf0e10cSrcweir 170cdf0e10cSrcweir static inline void SetMsiProperty(MSIHANDLE handle, const std::_tstring& sProperty) 171cdf0e10cSrcweir { 172cdf0e10cSrcweir MsiSetProperty(handle, sProperty.c_str(), TEXT("1")); 173cdf0e10cSrcweir } 174cdf0e10cSrcweir 175cdf0e10cSrcweir static BOOL MoveFileEx9x( LPCSTR lpExistingFileNameA, LPCSTR lpNewFileNameA, DWORD dwFlags ) 176cdf0e10cSrcweir { 177cdf0e10cSrcweir BOOL fSuccess = FALSE; // assume failure 178cdf0e10cSrcweir 179cdf0e10cSrcweir // Windows 9x has a special mechanism to move files after reboot 180cdf0e10cSrcweir 181cdf0e10cSrcweir if ( dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT ) 182cdf0e10cSrcweir { 183cdf0e10cSrcweir CHAR szExistingFileNameA[MAX_PATH]; 184cdf0e10cSrcweir CHAR szNewFileNameA[MAX_PATH] = "NUL"; 185cdf0e10cSrcweir 186cdf0e10cSrcweir // Path names in WININIT.INI must be in short path name form 187cdf0e10cSrcweir 188cdf0e10cSrcweir if ( 189cdf0e10cSrcweir GetShortPathNameA( lpExistingFileNameA, szExistingFileNameA, MAX_PATH ) && 190cdf0e10cSrcweir (!lpNewFileNameA || GetShortPathNameA( lpNewFileNameA, szNewFileNameA, MAX_PATH )) 191cdf0e10cSrcweir ) 192cdf0e10cSrcweir { 193cdf0e10cSrcweir CHAR szBuffer[32767]; // The buffer size must not exceed 32K 194cdf0e10cSrcweir DWORD dwBufLen = GetPrivateProfileSectionA( RENAME_SECTION, szBuffer, elementsof(szBuffer), WININIT_FILENAME ); 195cdf0e10cSrcweir 196cdf0e10cSrcweir CHAR szRename[MAX_PATH]; // This is enough for at most to times 67 chracters 197cdf0e10cSrcweir strcpy( szRename, szNewFileNameA ); 198cdf0e10cSrcweir strcat( szRename, "=" ); 199cdf0e10cSrcweir strcat( szRename, szExistingFileNameA ); 200cdf0e10cSrcweir size_t lnRename = strlen(szRename); 201cdf0e10cSrcweir 202cdf0e10cSrcweir if ( dwBufLen + lnRename + 2 <= elementsof(szBuffer) ) 203cdf0e10cSrcweir { 204cdf0e10cSrcweir CopyMemory( &szBuffer[dwBufLen], szRename, lnRename ); 205cdf0e10cSrcweir szBuffer[dwBufLen + lnRename ] = 0; 206cdf0e10cSrcweir szBuffer[dwBufLen + lnRename + 1 ] = 0; 207cdf0e10cSrcweir 208cdf0e10cSrcweir fSuccess = WritePrivateProfileSectionA( RENAME_SECTION, szBuffer, WININIT_FILENAME ); 209cdf0e10cSrcweir } 210cdf0e10cSrcweir else 211cdf0e10cSrcweir SetLastError( ERROR_BUFFER_OVERFLOW ); 212cdf0e10cSrcweir } 213cdf0e10cSrcweir } 214cdf0e10cSrcweir else 215cdf0e10cSrcweir { 216cdf0e10cSrcweir 217cdf0e10cSrcweir fSuccess = MoveFileA( lpExistingFileNameA, lpNewFileNameA ); 218cdf0e10cSrcweir 219cdf0e10cSrcweir if ( !fSuccess && GetLastError() != ERROR_ACCESS_DENIED && 220cdf0e10cSrcweir 0 != (dwFlags & (MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING)) ) 221cdf0e10cSrcweir { 222cdf0e10cSrcweir BOOL bFailIfExist = 0 == (dwFlags & MOVEFILE_REPLACE_EXISTING); 223cdf0e10cSrcweir 224cdf0e10cSrcweir fSuccess = CopyFileA( lpExistingFileNameA, lpNewFileNameA, bFailIfExist ); 225cdf0e10cSrcweir 226cdf0e10cSrcweir if ( fSuccess ) 227cdf0e10cSrcweir fSuccess = DeleteFileA( lpExistingFileNameA ); 228cdf0e10cSrcweir } 229cdf0e10cSrcweir 230cdf0e10cSrcweir } 231cdf0e10cSrcweir 232cdf0e10cSrcweir return fSuccess; 233cdf0e10cSrcweir } 234cdf0e10cSrcweir 235cdf0e10cSrcweir static BOOL MoveFileExImpl( LPCSTR lpExistingFileNameA, LPCSTR lpNewFileNameA, DWORD dwFlags ) 236cdf0e10cSrcweir { 237cdf0e10cSrcweir if ( 0 > ((LONG)GetVersion())) // High order bit indicates Win 9x 238cdf0e10cSrcweir return MoveFileEx9x( lpExistingFileNameA, lpNewFileNameA, dwFlags ); 239cdf0e10cSrcweir else 240cdf0e10cSrcweir return MoveFileExA( lpExistingFileNameA, lpNewFileNameA, dwFlags ); 241cdf0e10cSrcweir } 242cdf0e10cSrcweir 243cdf0e10cSrcweir static bool SwapFiles( const std::_tstring& sFileName1, const std::_tstring& sFileName2 ) 244cdf0e10cSrcweir { 245cdf0e10cSrcweir std::_tstring sTempFileName = sFileName1 + TEXT(".tmp"); 246cdf0e10cSrcweir 247cdf0e10cSrcweir bool fSuccess = true; 248cdf0e10cSrcweir 249cdf0e10cSrcweir //Try to move the original file to a temp file 250cdf0e10cSrcweir fSuccess = MoveFileExImpl( sFileName1.c_str(), sTempFileName.c_str(), MOVEFILE_REPLACE_EXISTING); 251cdf0e10cSrcweir 252cdf0e10cSrcweir std::_tstring mystr; 253cdf0e10cSrcweir 254cdf0e10cSrcweir if ( fSuccess ) 255cdf0e10cSrcweir { 256cdf0e10cSrcweir fSuccess = MoveFileExImpl( sFileName2.c_str(), sFileName1.c_str(), MOVEFILE_REPLACE_EXISTING ); 257cdf0e10cSrcweir 258cdf0e10cSrcweir if ( fSuccess ) 259cdf0e10cSrcweir { 260cdf0e10cSrcweir fSuccess = MoveFileExImpl( sTempFileName.c_str(), sFileName2.c_str(), 261cdf0e10cSrcweir MOVEFILE_REPLACE_EXISTING ); 262cdf0e10cSrcweir if ( !fSuccess ) 263cdf0e10cSrcweir { 264cdf0e10cSrcweir MoveFileExImpl( sFileName1.c_str(), sFileName2.c_str(), MOVEFILE_REPLACE_EXISTING ); 265cdf0e10cSrcweir } 266cdf0e10cSrcweir } 267cdf0e10cSrcweir else 268cdf0e10cSrcweir { 269cdf0e10cSrcweir MoveFileExImpl( sTempFileName.c_str(), sFileName1.c_str(), MOVEFILE_REPLACE_EXISTING ); 270cdf0e10cSrcweir } 271cdf0e10cSrcweir } 272cdf0e10cSrcweir else 273cdf0e10cSrcweir { 274cdf0e10cSrcweir //It could be that there is no original file and therefore copying the original to a temp 275cdf0e10cSrcweir // file failed. Examine if there is no original and if so then move file2 to file1 276cdf0e10cSrcweir 277cdf0e10cSrcweir WIN32_FIND_DATA data; 278cdf0e10cSrcweir HANDLE hdl = FindFirstFile(sFileName1.c_str(), &data); 279cdf0e10cSrcweir if (hdl == INVALID_HANDLE_VALUE) 280cdf0e10cSrcweir { 281cdf0e10cSrcweir fSuccess = MoveFileExImpl( sFileName2.c_str(), sFileName1.c_str(), MOVEFILE_REPLACE_EXISTING ); 282cdf0e10cSrcweir 283cdf0e10cSrcweir // if ( fSuccess ) 284cdf0e10cSrcweir // { 285cdf0e10cSrcweir // mystr = "Success"; 286cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "Titel", MB_OK ); 287cdf0e10cSrcweir // } 288cdf0e10cSrcweir // else 289cdf0e10cSrcweir // { 290cdf0e10cSrcweir // char buff[256]; 291cdf0e10cSrcweir // wsprintf(buff, "Failure %d", GetLastError()); 292cdf0e10cSrcweir // MessageBox( NULL, buff, "Titel", MB_OK ); 293cdf0e10cSrcweir // } 294cdf0e10cSrcweir } 295cdf0e10cSrcweir else 296cdf0e10cSrcweir { 297cdf0e10cSrcweir FindClose(hdl); 298cdf0e10cSrcweir } 299cdf0e10cSrcweir } 300cdf0e10cSrcweir 301cdf0e10cSrcweir OutputDebugStringFormat( TEXT("%s <-> %s: %s"), sFileName1.c_str(), sFileName2.c_str(), fSuccess ? TEXT("OK") : TEXT("FAILED") ); 302cdf0e10cSrcweir 303cdf0e10cSrcweir if (!fSuccess ) 304cdf0e10cSrcweir { 305cdf0e10cSrcweir DWORD dwError = GetLastError(); 306cdf0e10cSrcweir LPVOID lpMsgBuf; 307cdf0e10cSrcweir if ( FormatMessage( 308cdf0e10cSrcweir FORMAT_MESSAGE_ALLOCATE_BUFFER | 309cdf0e10cSrcweir FORMAT_MESSAGE_FROM_SYSTEM | 310cdf0e10cSrcweir FORMAT_MESSAGE_IGNORE_INSERTS, 311cdf0e10cSrcweir NULL, 312cdf0e10cSrcweir GetLastError(), 313cdf0e10cSrcweir MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language 314cdf0e10cSrcweir (LPTSTR) &lpMsgBuf, 315cdf0e10cSrcweir 0, 316cdf0e10cSrcweir NULL )) 317cdf0e10cSrcweir { 318cdf0e10cSrcweir OutputDebugStringFormat( TEXT("Error Code %d: %s"), dwError, lpMsgBuf ); 319cdf0e10cSrcweir LocalFree( lpMsgBuf ); 320cdf0e10cSrcweir } 321cdf0e10cSrcweir else 322cdf0e10cSrcweir OutputDebugStringFormat( TEXT("Error Code %d: Unknown"), dwError ); 323cdf0e10cSrcweir SetMsiErrorCode( dwError ); 324cdf0e10cSrcweir } 325cdf0e10cSrcweir 326cdf0e10cSrcweir return fSuccess; 327cdf0e10cSrcweir } 328cdf0e10cSrcweir 329cdf0e10cSrcweir static std::_tstring strip( const std::_tstring& s, _TCHAR c ) 330cdf0e10cSrcweir { 331cdf0e10cSrcweir std::_tstring result = s; 332cdf0e10cSrcweir 333cdf0e10cSrcweir std::_tstring::size_type f; 334cdf0e10cSrcweir 335cdf0e10cSrcweir do 336cdf0e10cSrcweir { 337cdf0e10cSrcweir f = result.find( c ); 338cdf0e10cSrcweir if ( f != std::_tstring::npos ) 339cdf0e10cSrcweir result.erase( f, 1 ); 340cdf0e10cSrcweir } while ( f != std::_tstring::npos ); 341cdf0e10cSrcweir 342cdf0e10cSrcweir return result; 343cdf0e10cSrcweir } 344cdf0e10cSrcweir 345cdf0e10cSrcweir static std::_tstring trim( const std::_tstring& rString ) 346cdf0e10cSrcweir { 347cdf0e10cSrcweir std::_tstring temp = rString; 348cdf0e10cSrcweir 349cdf0e10cSrcweir while ( temp.length() && temp[0] == ' ' || temp[0] == '\t' ) 350cdf0e10cSrcweir temp.erase( 0, 1 ); 351cdf0e10cSrcweir 352cdf0e10cSrcweir std::_tstring::size_type len = temp.length(); 353cdf0e10cSrcweir 354cdf0e10cSrcweir while ( len && temp[len-1] == ' ' || temp[len-1] == '\t' ) 355cdf0e10cSrcweir { 356cdf0e10cSrcweir temp.erase( len - 1, 1 ); 357cdf0e10cSrcweir len = temp.length(); 358cdf0e10cSrcweir } 359cdf0e10cSrcweir 360cdf0e10cSrcweir return temp; 361cdf0e10cSrcweir } 362cdf0e10cSrcweir 363cdf0e10cSrcweir static bool readLine( FILE *fp, std::_tstring& rLine ) 364cdf0e10cSrcweir { 365cdf0e10cSrcweir _TCHAR szBuffer[1024]; 366cdf0e10cSrcweir bool bSuccess = false; 367cdf0e10cSrcweir bool bEOL = false; 368cdf0e10cSrcweir std::_tstring line; 369cdf0e10cSrcweir 370cdf0e10cSrcweir 371cdf0e10cSrcweir while ( !bEOL && _fgetts( szBuffer, sizeof(szBuffer), fp ) ) 372cdf0e10cSrcweir { 373cdf0e10cSrcweir int len = _tcslen(szBuffer); 374cdf0e10cSrcweir 375cdf0e10cSrcweir bSuccess = true; 376cdf0e10cSrcweir 377cdf0e10cSrcweir while ( len && szBuffer[len - 1] == '\n' ) 378cdf0e10cSrcweir { 379cdf0e10cSrcweir szBuffer[--len] = 0; 380cdf0e10cSrcweir bEOL = true; 381cdf0e10cSrcweir } 382cdf0e10cSrcweir 383cdf0e10cSrcweir line.append( szBuffer ); 384cdf0e10cSrcweir } 385cdf0e10cSrcweir 386cdf0e10cSrcweir rLine = line; 387cdf0e10cSrcweir return bSuccess; 388cdf0e10cSrcweir } 389cdf0e10cSrcweir 390cdf0e10cSrcweir 391cdf0e10cSrcweir static std::_tstring getProfileString( 392cdf0e10cSrcweir const std::_tstring& aFileName, 393cdf0e10cSrcweir const std::_tstring& aSectionName, 394cdf0e10cSrcweir const std::_tstring& aKeyName, 395cdf0e10cSrcweir const std::_tstring& aDefault = _T("") ) 396cdf0e10cSrcweir { 397cdf0e10cSrcweir FILE *fp = _tfopen( aFileName.c_str(), _T("r") ); 398cdf0e10cSrcweir std::_tstring retValue = aDefault.length() ? aDefault : _T(""); 399cdf0e10cSrcweir 400cdf0e10cSrcweir if ( fp ) 401cdf0e10cSrcweir { 402cdf0e10cSrcweir std::_tstring line; 403cdf0e10cSrcweir std::_tstring section; 404cdf0e10cSrcweir 405cdf0e10cSrcweir while ( readLine( fp, line ) ) 406cdf0e10cSrcweir { 407cdf0e10cSrcweir line = trim( line ); 408cdf0e10cSrcweir 409cdf0e10cSrcweir if ( line.length() && line[0] == '[' ) 410cdf0e10cSrcweir { 411cdf0e10cSrcweir line.erase( 0, 1 ); 412cdf0e10cSrcweir std::_tstring::size_type end = line.find( ']', 0 ); 413cdf0e10cSrcweir 414cdf0e10cSrcweir if ( std::_tstring::npos != end ) 415cdf0e10cSrcweir section = trim( line.substr( 0, end ) ); 416cdf0e10cSrcweir } 417cdf0e10cSrcweir else 418cdf0e10cSrcweir { 419cdf0e10cSrcweir 420cdf0e10cSrcweir std::_tstring::size_type iEqualSign = line.find( '=', 0 ); 421cdf0e10cSrcweir 422cdf0e10cSrcweir if ( iEqualSign != std::_tstring::npos ) 423cdf0e10cSrcweir { 424cdf0e10cSrcweir std::_tstring keyname = line.substr( 0, iEqualSign ); 425cdf0e10cSrcweir keyname = trim( keyname ); 426cdf0e10cSrcweir 427cdf0e10cSrcweir std::_tstring value = line.substr( iEqualSign + 1 /*, std::_tstring::npos */ ); 428cdf0e10cSrcweir value = trim( value ); 429cdf0e10cSrcweir 430cdf0e10cSrcweir if ( 431cdf0e10cSrcweir 0 == _tcsicmp( section.c_str(), aSectionName.c_str() ) && 432cdf0e10cSrcweir 0 == _tcsicmp( keyname.c_str(), aKeyName.c_str() ) 433cdf0e10cSrcweir ) 434cdf0e10cSrcweir { 435cdf0e10cSrcweir retValue = value; 436cdf0e10cSrcweir break; 437cdf0e10cSrcweir } 438cdf0e10cSrcweir } 439cdf0e10cSrcweir } 440cdf0e10cSrcweir } 441cdf0e10cSrcweir 442cdf0e10cSrcweir fclose( fp ); 443cdf0e10cSrcweir } 444cdf0e10cSrcweir 445cdf0e10cSrcweir return retValue; 446cdf0e10cSrcweir } 447cdf0e10cSrcweir 448cdf0e10cSrcweir static std::queue< std::_tstring > getProfileSections( const std::_tstring& aFileName ) 449cdf0e10cSrcweir { 450cdf0e10cSrcweir FILE *fp = _tfopen( aFileName.c_str(), _T("r") ); 451cdf0e10cSrcweir std::queue< std::_tstring > aResult; 452cdf0e10cSrcweir 453cdf0e10cSrcweir OutputDebugStringFormat( TEXT("*** Retrieving Section Names ****") ); 454cdf0e10cSrcweir 455cdf0e10cSrcweir if ( fp ) 456cdf0e10cSrcweir { 457cdf0e10cSrcweir std::_tstring line; 458cdf0e10cSrcweir std::_tstring section; 459cdf0e10cSrcweir 460cdf0e10cSrcweir while ( readLine( fp, line ) ) 461cdf0e10cSrcweir { 462cdf0e10cSrcweir line = trim( line ); 463cdf0e10cSrcweir 464cdf0e10cSrcweir if ( line.length() && line[0] == '[' ) 465cdf0e10cSrcweir { 466cdf0e10cSrcweir line.erase( 0, 1 ); 467cdf0e10cSrcweir std::_tstring::size_type end = line.find( ']', 0 ); 468cdf0e10cSrcweir 469cdf0e10cSrcweir if ( std::_tstring::npos != end ) 470cdf0e10cSrcweir section = trim( line.substr( 0, end ) ); 471cdf0e10cSrcweir 472cdf0e10cSrcweir aResult.push( section ); 473cdf0e10cSrcweir 474cdf0e10cSrcweir OutputDebugStringFormat( TEXT("Section: %s"), section.c_str() ); 475cdf0e10cSrcweir 476cdf0e10cSrcweir } 477cdf0e10cSrcweir } 478cdf0e10cSrcweir 479cdf0e10cSrcweir fclose( fp ); 480cdf0e10cSrcweir } 481cdf0e10cSrcweir 482cdf0e10cSrcweir OutputDebugStringFormat( TEXT("*** Done Section Names ***") ); 483cdf0e10cSrcweir 484cdf0e10cSrcweir return aResult; 485cdf0e10cSrcweir } 486cdf0e10cSrcweir 487cdf0e10cSrcweir static std::queue< std::_tstring > getProfileKeys( const std::_tstring& aFileName, const std::_tstring& aSectionName ) 488cdf0e10cSrcweir { 489cdf0e10cSrcweir FILE *fp = _tfopen( aFileName.c_str(), _T("r") ); 490cdf0e10cSrcweir std::queue< std::_tstring > aResult; 491cdf0e10cSrcweir 492cdf0e10cSrcweir OutputDebugStringFormat( TEXT("*** Retrieving Key Names for [%s] ***"), aSectionName.c_str() ); 493cdf0e10cSrcweir 494cdf0e10cSrcweir if ( fp ) 495cdf0e10cSrcweir { 496cdf0e10cSrcweir std::_tstring line; 497cdf0e10cSrcweir std::_tstring section; 498cdf0e10cSrcweir 499cdf0e10cSrcweir while ( readLine( fp, line ) ) 500cdf0e10cSrcweir { 501cdf0e10cSrcweir line = trim( line ); 502cdf0e10cSrcweir 503cdf0e10cSrcweir if ( line.length() && line[0] == '[' ) 504cdf0e10cSrcweir { 505cdf0e10cSrcweir line.erase( 0, 1 ); 506cdf0e10cSrcweir std::_tstring::size_type end = line.find( ']', 0 ); 507cdf0e10cSrcweir 508cdf0e10cSrcweir if ( std::_tstring::npos != end ) 509cdf0e10cSrcweir section = trim( line.substr( 0, end ) ); 510cdf0e10cSrcweir } 511cdf0e10cSrcweir else 512cdf0e10cSrcweir { 513cdf0e10cSrcweir 514cdf0e10cSrcweir std::_tstring::size_type iEqualSign = line.find( '=', 0 ); 515cdf0e10cSrcweir 516cdf0e10cSrcweir if ( iEqualSign != std::_tstring::npos ) 517cdf0e10cSrcweir { 518cdf0e10cSrcweir std::_tstring keyname = line.substr( 0, iEqualSign ); 519cdf0e10cSrcweir keyname = trim( keyname ); 520cdf0e10cSrcweir 521cdf0e10cSrcweir if ( 0 == _tcsicmp( section.c_str(), aSectionName.c_str() ) ) 522cdf0e10cSrcweir { 523cdf0e10cSrcweir aResult.push( keyname ); 524cdf0e10cSrcweir 525cdf0e10cSrcweir OutputDebugStringFormat( keyname.c_str() ); 526cdf0e10cSrcweir 527cdf0e10cSrcweir } 528cdf0e10cSrcweir } 529cdf0e10cSrcweir } 530cdf0e10cSrcweir } 531cdf0e10cSrcweir 532cdf0e10cSrcweir fclose( fp ); 533cdf0e10cSrcweir } 534cdf0e10cSrcweir 535cdf0e10cSrcweir OutputDebugStringFormat( TEXT("*** Done Key Names for [%s] ***"), aSectionName.c_str() ); 536cdf0e10cSrcweir 537cdf0e10cSrcweir return aResult; 538cdf0e10cSrcweir } 539cdf0e10cSrcweir 540cdf0e10cSrcweir extern "C" UINT __stdcall InstallPatchedFiles( MSIHANDLE handle ) 541cdf0e10cSrcweir { 542cdf0e10cSrcweir std::_tstring sInstDir = GetMsiProperty( handle, TEXT("INSTALLLOCATION") ); 543*910823aeSJürgen Schmidt // std::_tstring sProgramDir = sInstDir + TEXT("Basis\\program\\"); 544*910823aeSJürgen Schmidt std::_tstring sProgramDir = sInstDir + TEXT("program\\"); 545cdf0e10cSrcweir std::_tstring sPatchFile = sProgramDir + TEXT("patchlist.txt"); 546cdf0e10cSrcweir 547cdf0e10cSrcweir std::queue< std::_tstring > aSectionNames; 548cdf0e10cSrcweir std::queue< std::_tstring > aKeyNames; 549cdf0e10cSrcweir 550cdf0e10cSrcweir OutputDebugStringA( "Starting Custom Action" ); 551cdf0e10cSrcweir 552cdf0e10cSrcweir // std::_tstring mystr; 553cdf0e10cSrcweir // mystr = "Patchfile: " + sPatchFile; 554cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "Patchfile", MB_OK ); 555cdf0e10cSrcweir 556cdf0e10cSrcweir aSectionNames = getProfileSections( sPatchFile ); 557cdf0e10cSrcweir while ( !aSectionNames.empty() ) 558cdf0e10cSrcweir { 559cdf0e10cSrcweir std::_tstring sSectionName = aSectionNames.front(); 560cdf0e10cSrcweir if ( std::_tstring(TEXT("_root")) == sSectionName ) { sSectionName = TEXT(""); } 561cdf0e10cSrcweir // mystr = "Section: " + sSectionName; 562cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "Titel", MB_OK ); 563cdf0e10cSrcweir 564cdf0e10cSrcweir aKeyNames = getProfileKeys( sPatchFile, sSectionName ); 565cdf0e10cSrcweir while ( !aKeyNames.empty() ) 566cdf0e10cSrcweir { 567cdf0e10cSrcweir std::_tstring sKeyName = aKeyNames.front(); 568cdf0e10cSrcweir std::_tstring sValue = getProfileString( sPatchFile, sSectionName, sKeyName ); 569cdf0e10cSrcweir 570cdf0e10cSrcweir if ( sValue.length() ) 571cdf0e10cSrcweir { 572cdf0e10cSrcweir std::_tstring sFileName1 = sKeyName; 573cdf0e10cSrcweir std::_tstring sExtension = sValue; 574cdf0e10cSrcweir std::_tstring sFileName2; 575cdf0e10cSrcweir 576cdf0e10cSrcweir sFileName1 = strip( sFileName1, '\"' ); 577cdf0e10cSrcweir sExtension = strip( sExtension, '\"' ); 578cdf0e10cSrcweir 579cdf0e10cSrcweir sFileName1 = sInstDir + sSectionName + sFileName1; 580cdf0e10cSrcweir sFileName2 = sFileName1 + sExtension; 581cdf0e10cSrcweir 582cdf0e10cSrcweir // mystr = "Convert: " + sFileName1 + " to " + sFileName2; 583cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "Titel", MB_OK ); 584cdf0e10cSrcweir 585cdf0e10cSrcweir SwapFiles( sFileName1, sFileName2 ); 586cdf0e10cSrcweir } 587cdf0e10cSrcweir 588cdf0e10cSrcweir aKeyNames.pop(); 589cdf0e10cSrcweir } 590cdf0e10cSrcweir 591cdf0e10cSrcweir aSectionNames.pop(); 592cdf0e10cSrcweir } 593cdf0e10cSrcweir 594cdf0e10cSrcweir return ERROR_SUCCESS; 595cdf0e10cSrcweir } 596cdf0e10cSrcweir 597cdf0e10cSrcweir extern "C" UINT __stdcall UninstallPatchedFiles( MSIHANDLE handle ) 598cdf0e10cSrcweir { 599cdf0e10cSrcweir TCHAR szValue[8192]; 600cdf0e10cSrcweir DWORD nValueSize = sizeof(szValue); 601cdf0e10cSrcweir HKEY hKey; 602cdf0e10cSrcweir 603cdf0e10cSrcweir std::_tstring sInstDir; 604cdf0e10cSrcweir 605cdf0e10cSrcweir std::_tstring sProductKey = GetMsiProperty( handle, TEXT("FINDPRODUCT") ); 606cdf0e10cSrcweir 607cdf0e10cSrcweir if ( ERROR_SUCCESS == RegOpenKey( HKEY_CURRENT_USER, sProductKey.c_str(), &hKey ) ) 608cdf0e10cSrcweir { 609cdf0e10cSrcweir if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("INSTALLLOCATION"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) ) 610cdf0e10cSrcweir { 611cdf0e10cSrcweir sInstDir = szValue; 612cdf0e10cSrcweir } 613cdf0e10cSrcweir RegCloseKey( hKey ); 614cdf0e10cSrcweir } 615cdf0e10cSrcweir else if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, sProductKey.c_str(), &hKey ) ) 616cdf0e10cSrcweir { 617cdf0e10cSrcweir if ( ERROR_SUCCESS == RegQueryValueEx( hKey, TEXT("INSTALLLOCATION"), NULL, NULL, (LPBYTE)szValue, &nValueSize ) ) 618cdf0e10cSrcweir { 619cdf0e10cSrcweir sInstDir = szValue; 620cdf0e10cSrcweir } 621cdf0e10cSrcweir RegCloseKey( hKey ); 622cdf0e10cSrcweir } 623cdf0e10cSrcweir else 624cdf0e10cSrcweir return ERROR_SUCCESS; 625cdf0e10cSrcweir 626cdf0e10cSrcweir std::_tstring sProgramDir = sInstDir + TEXT("Basis\\program\\"); 627cdf0e10cSrcweir std::_tstring sPatchFile = sProgramDir + TEXT("patchlist.txt"); 628cdf0e10cSrcweir 629cdf0e10cSrcweir std::queue< std::_tstring > aSectionNames; 630cdf0e10cSrcweir std::queue< std::_tstring > aKeyNames; 631cdf0e10cSrcweir 632cdf0e10cSrcweir // std::_tstring mystr; 633cdf0e10cSrcweir // mystr = "Patchfile: " + sPatchFile; 634cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "Titel", MB_OK ); 635cdf0e10cSrcweir 636cdf0e10cSrcweir aSectionNames = getProfileSections( sPatchFile ); 637cdf0e10cSrcweir while ( !aSectionNames.empty() ) 638cdf0e10cSrcweir { 639cdf0e10cSrcweir std::_tstring sSectionName = aSectionNames.front(); 640cdf0e10cSrcweir if ( std::_tstring(TEXT("_root")) == sSectionName ) { sSectionName = TEXT(""); } 641cdf0e10cSrcweir // mystr = "Section: " + sSectionName; 642cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "Titel", MB_OK ); 643cdf0e10cSrcweir 644cdf0e10cSrcweir aKeyNames = getProfileKeys( sPatchFile, sSectionName ); 645cdf0e10cSrcweir while( !aKeyNames.empty() ) 646cdf0e10cSrcweir { 647cdf0e10cSrcweir std::_tstring sKeyName = aKeyNames.front(); 648cdf0e10cSrcweir std::_tstring sValue = getProfileString( sPatchFile, sSectionName, sKeyName ); 649cdf0e10cSrcweir 650cdf0e10cSrcweir if ( sValue.length() ) 651cdf0e10cSrcweir { 652cdf0e10cSrcweir std::_tstring sFileName1 = sKeyName; 653cdf0e10cSrcweir std::_tstring sExtension = sValue; 654cdf0e10cSrcweir std::_tstring sFileName2; 655cdf0e10cSrcweir 656cdf0e10cSrcweir sFileName1 = strip( sFileName1, '\"' ); 657cdf0e10cSrcweir sExtension = strip( sExtension, '\"' ); 658cdf0e10cSrcweir 659cdf0e10cSrcweir sFileName1 = sInstDir + sSectionName + sFileName1; 660cdf0e10cSrcweir sFileName2 = sFileName1 + sExtension; 661cdf0e10cSrcweir 662cdf0e10cSrcweir // mystr = "Convert: " + sFileName1 + " to " + sFileName2; 663cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "Titel", MB_OK ); 664cdf0e10cSrcweir 665cdf0e10cSrcweir SwapFiles( sFileName2, sFileName1 ); 666cdf0e10cSrcweir } 667cdf0e10cSrcweir 668cdf0e10cSrcweir aKeyNames.pop(); 669cdf0e10cSrcweir } 670cdf0e10cSrcweir 671cdf0e10cSrcweir aSectionNames.pop(); 672cdf0e10cSrcweir } 673cdf0e10cSrcweir 674cdf0e10cSrcweir return ERROR_SUCCESS; 675cdf0e10cSrcweir } 676cdf0e10cSrcweir 677cdf0e10cSrcweir extern "C" UINT __stdcall IsOfficeRunning( MSIHANDLE handle ) 678cdf0e10cSrcweir { 679cdf0e10cSrcweir std::_tstring sInstDir = GetMsiProperty( handle, TEXT("INSTALLLOCATION") ); 680cdf0e10cSrcweir std::_tstring sResourceDir = sInstDir + TEXT("Basis\\program\\resource\\"); 681cdf0e10cSrcweir std::_tstring sPattern = sResourceDir + TEXT("vcl*.res"); 682cdf0e10cSrcweir 683cdf0e10cSrcweir WIN32_FIND_DATA aFindFileData; 684cdf0e10cSrcweir HANDLE hFind = FindFirstFile( sPattern.c_str(), &aFindFileData ); 685cdf0e10cSrcweir 686cdf0e10cSrcweir if ( IsValidHandle(hFind) ) 687cdf0e10cSrcweir { 688cdf0e10cSrcweir BOOL fSuccess = false; 689cdf0e10cSrcweir bool fRenameSucceeded; 690cdf0e10cSrcweir 691cdf0e10cSrcweir do 692cdf0e10cSrcweir { 693cdf0e10cSrcweir std::_tstring sResourceFile = sResourceDir + aFindFileData.cFileName; 694cdf0e10cSrcweir std::_tstring sIntermediate = sResourceFile + TEXT(".tmp"); 695cdf0e10cSrcweir 696cdf0e10cSrcweir fRenameSucceeded = MoveFileExImpl( sResourceFile.c_str(), sIntermediate.c_str(), MOVEFILE_REPLACE_EXISTING ); 697cdf0e10cSrcweir if ( fRenameSucceeded ) 698cdf0e10cSrcweir { 699cdf0e10cSrcweir MoveFileExImpl( sIntermediate.c_str(), sResourceFile.c_str(), 0 ); 700cdf0e10cSrcweir fSuccess = FindNextFile( hFind, &aFindFileData ); 701cdf0e10cSrcweir } 702cdf0e10cSrcweir } while ( fSuccess && fRenameSucceeded ); 703cdf0e10cSrcweir 704cdf0e10cSrcweir if ( !fRenameSucceeded ) 705cdf0e10cSrcweir { 706cdf0e10cSrcweir MsiSetProperty(handle, TEXT("OFFICERUNS"), TEXT("1")); 707cdf0e10cSrcweir SetMsiErrorCode( MSI_ERROR_OFFICE_IS_RUNNING ); 708cdf0e10cSrcweir } 709cdf0e10cSrcweir 710cdf0e10cSrcweir FindClose( hFind ); 711cdf0e10cSrcweir } 712cdf0e10cSrcweir 713cdf0e10cSrcweir 714cdf0e10cSrcweir return ERROR_SUCCESS; 715cdf0e10cSrcweir } 716cdf0e10cSrcweir 717cdf0e10cSrcweir extern "C" UINT __stdcall SetFeatureState( MSIHANDLE handle ) 718cdf0e10cSrcweir { 719cdf0e10cSrcweir std::_tstring mystr; 720cdf0e10cSrcweir 721cdf0e10cSrcweir // 1. Reading Product Code from setup.ini of installed Office 722cdf0e10cSrcweir 723cdf0e10cSrcweir std::_tstring sInstallPath = GetMsiProperty(handle, TEXT("INSTALLLOCATION")); 724cdf0e10cSrcweir // MessageBox(NULL, sInstallPath.c_str(), "INSTALLLOCATION", MB_OK); 725cdf0e10cSrcweir std::_tstring sSetupiniPath = sInstallPath + TEXT("program\\setup.ini"); 726cdf0e10cSrcweir 727cdf0e10cSrcweir TCHAR szProductCode[32767]; 728cdf0e10cSrcweir 729cdf0e10cSrcweir GetPrivateProfileString( 730cdf0e10cSrcweir TEXT("Bootstrap"), 731cdf0e10cSrcweir TEXT("ProductCode"), 732cdf0e10cSrcweir TEXT("NOTFOUND"), 733cdf0e10cSrcweir szProductCode, 734cdf0e10cSrcweir elementsof(szProductCode), 735cdf0e10cSrcweir sSetupiniPath.c_str() 736cdf0e10cSrcweir ); 737cdf0e10cSrcweir 738cdf0e10cSrcweir if ( !_tcsicmp( szProductCode, TEXT("NOTFOUND") ) ) 739cdf0e10cSrcweir { 740cdf0e10cSrcweir // No setup.ini or no "ProductCode" in setup.ini. This is an invalid directory. 741cdf0e10cSrcweir // MessageBox(NULL, "NOTFOUND set", "DEBUG", MB_OK); 742cdf0e10cSrcweir return ERROR_SUCCESS; 743cdf0e10cSrcweir } 744cdf0e10cSrcweir 745cdf0e10cSrcweir // 2. Converting Product code 746cdf0e10cSrcweir 747cdf0e10cSrcweir std::_tstring productCode = TEXT(szProductCode); 748cdf0e10cSrcweir productCode = ConvertGuid(std::_tstring(productCode.c_str() + 1, productCode.length() - 2)); 749cdf0e10cSrcweir mystr = TEXT("Changed product code: ") + productCode; 750cdf0e10cSrcweir // MessageBox(NULL, mystr.c_str(), "ProductCode", MB_OK); 751cdf0e10cSrcweir 752cdf0e10cSrcweir // 3. Setting path in the Windows registry to find installed features 753cdf0e10cSrcweir 754cdf0e10cSrcweir std::_tstring registryKey; 755cdf0e10cSrcweir HKEY registryRoot; 756cdf0e10cSrcweir 757cdf0e10cSrcweir if ( IsSetMsiProperty(handle, TEXT("ALLUSERS")) ) 758cdf0e10cSrcweir { 759cdf0e10cSrcweir registryRoot = HKEY_LOCAL_MACHINE; 760cdf0e10cSrcweir registryKey = TEXT("Software\\Classes\\Installer\\Features\\") + productCode; 761cdf0e10cSrcweir mystr = registryKey; 762cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "ALLUSERS", MB_OK ); 763cdf0e10cSrcweir } 764cdf0e10cSrcweir else 765cdf0e10cSrcweir { 766cdf0e10cSrcweir registryRoot = HKEY_CURRENT_USER; 767cdf0e10cSrcweir registryKey = TEXT("Software\\Microsoft\\Installer\\Features\\") + productCode; 768cdf0e10cSrcweir mystr = registryKey; 769cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "ALLUSERS", MB_OK ); 770cdf0e10cSrcweir } 771cdf0e10cSrcweir 772cdf0e10cSrcweir // 4. Collecting all installed features from Windows registry 773cdf0e10cSrcweir 774cdf0e10cSrcweir HKEY hKey; 775cdf0e10cSrcweir if (RegOpenKey(registryRoot, registryKey.c_str(), &hKey) == ERROR_SUCCESS) 776cdf0e10cSrcweir { 777cdf0e10cSrcweir int counter = 0; 778cdf0e10cSrcweir // DWORD counter = 0; 779cdf0e10cSrcweir LONG lEnumResult; 780cdf0e10cSrcweir 781cdf0e10cSrcweir do 782cdf0e10cSrcweir { 783cdf0e10cSrcweir TCHAR szValueName[8192]; 784cdf0e10cSrcweir DWORD nValueNameSize = sizeof(szValueName); 785cdf0e10cSrcweir LPDWORD pValueNameSize = &nValueNameSize; 786cdf0e10cSrcweir TCHAR szValueData[8192]; 787cdf0e10cSrcweir DWORD nValueDataSize = sizeof(szValueData); 788cdf0e10cSrcweir 789cdf0e10cSrcweir lEnumResult = RegEnumValue( hKey, counter, szValueName, pValueNameSize, NULL, NULL, (LPBYTE)szValueData, &nValueDataSize); 790cdf0e10cSrcweir 791cdf0e10cSrcweir if ( ERROR_SUCCESS == lEnumResult ) 792cdf0e10cSrcweir { 793cdf0e10cSrcweir std::_tstring sValueName = szValueName; 794cdf0e10cSrcweir std::_tstring sValueData = szValueData; 795cdf0e10cSrcweir 796cdf0e10cSrcweir // mystr = sValueName; 797cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "ValueName", MB_OK ); 798cdf0e10cSrcweir // mystr = sValueData; 799cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "ValueData", MB_OK ); 800cdf0e10cSrcweir 801cdf0e10cSrcweir // Does this feature exist in this patch? 802cdf0e10cSrcweir if ( IsSetMsiProperty(handle, sValueName) ) 803cdf0e10cSrcweir { 804cdf0e10cSrcweir // Feature is not installed, if szValueData starts with a "square" (ascii 6) 805cdf0e10cSrcweir if ( 6 == szValueData[0] ) 806cdf0e10cSrcweir { 807cdf0e10cSrcweir MsiSetFeatureState(handle,sValueName.c_str(),INSTALLSTATE_ABSENT); // do not install this feature 808cdf0e10cSrcweir // mystr = TEXT("Do NOT install: ") + sValueName; 809cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "ValueName", MB_OK ); 810cdf0e10cSrcweir } 811cdf0e10cSrcweir else 812cdf0e10cSrcweir { 813cdf0e10cSrcweir MsiSetFeatureState(handle,sValueName.c_str(),INSTALLSTATE_LOCAL); // do install this feature 814cdf0e10cSrcweir // mystr = TEXT("Do install: ") + sValueName; 815cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "ValueName", MB_OK ); 816cdf0e10cSrcweir } 817cdf0e10cSrcweir } 818cdf0e10cSrcweir } 819cdf0e10cSrcweir 820cdf0e10cSrcweir counter = counter + 1; 821cdf0e10cSrcweir 822cdf0e10cSrcweir } while ( ERROR_SUCCESS == lEnumResult ); 823cdf0e10cSrcweir 824cdf0e10cSrcweir RegCloseKey( hKey ); 825cdf0e10cSrcweir } 826cdf0e10cSrcweir 827cdf0e10cSrcweir return ERROR_SUCCESS; 828cdf0e10cSrcweir } 829cdf0e10cSrcweir 830cdf0e10cSrcweir extern "C" UINT __stdcall SetNewFeatureState( MSIHANDLE handle ) 831cdf0e10cSrcweir { 832cdf0e10cSrcweir std::_tstring mystr; 833cdf0e10cSrcweir std::_tstring sValueName; 834cdf0e10cSrcweir 835cdf0e10cSrcweir sValueName = TEXT("gm_o_Onlineupdate"); 836cdf0e10cSrcweir 837cdf0e10cSrcweir if (IsSetMsiProperty(handle, TEXT("SELECT_OU_FEATURE"))) 838cdf0e10cSrcweir { 839cdf0e10cSrcweir MsiSetFeatureState(handle,sValueName.c_str(),INSTALLSTATE_LOCAL); // do install this feature 840cdf0e10cSrcweir // mystr = TEXT("OnlineUpdate wird installiert!"); 841cdf0e10cSrcweir // MessageBox(NULL, mystr.c_str(), "INSTALLSTATE_LOCAL", MB_OK); 842cdf0e10cSrcweir } 843cdf0e10cSrcweir else 844cdf0e10cSrcweir { 845cdf0e10cSrcweir MsiSetFeatureState(handle,sValueName.c_str(),INSTALLSTATE_ABSENT); // do not install this feature 846cdf0e10cSrcweir // mystr = TEXT("OnlineUpdate wird NICHT installiert!"); 847cdf0e10cSrcweir // MessageBox(NULL, mystr.c_str(), "INSTALLSTATE_ABSENT", MB_OK); 848cdf0e10cSrcweir } 849cdf0e10cSrcweir 850cdf0e10cSrcweir return ERROR_SUCCESS; 851cdf0e10cSrcweir } 852cdf0e10cSrcweir 853cdf0e10cSrcweir extern "C" UINT __stdcall ShowOnlineUpdateDialog( MSIHANDLE handle ) 854cdf0e10cSrcweir { 855cdf0e10cSrcweir // Checking existence of file "updchk.uno.dll", which shows, that 856cdf0e10cSrcweir // Online Update functionality is always available. Then the dialog 857cdf0e10cSrcweir // that offers the Online Update is superfluous. 858cdf0e10cSrcweir 859cdf0e10cSrcweir std::_tstring sInstDir = GetMsiProperty( handle, TEXT("INSTALLLOCATION") ); 860cdf0e10cSrcweir std::_tstring sProgramDir = sInstDir + TEXT("Basis\\program\\"); 861cdf0e10cSrcweir std::_tstring sSearchFile = sProgramDir + TEXT("updchk.uno.dll"); 862cdf0e10cSrcweir 863cdf0e10cSrcweir WIN32_FIND_DATA data; 864cdf0e10cSrcweir HANDLE hdl = FindFirstFile(sSearchFile.c_str(), &data); 865cdf0e10cSrcweir if (hdl != INVALID_HANDLE_VALUE) // the file exists 866cdf0e10cSrcweir { 867cdf0e10cSrcweir // std::_tstring mystr; 868cdf0e10cSrcweir // mystr = "Found file: " + sSearchFile; 869cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "Found file", MB_OK ); 870cdf0e10cSrcweir 871cdf0e10cSrcweir // And finally setting property SHOW_ONLINEUPDATE_DIALOG 872cdf0e10cSrcweir // to hide this dialog 873cdf0e10cSrcweir UnsetMsiProperty(handle, TEXT("SHOW_ONLINEUPDATE_DIALOG")); 874cdf0e10cSrcweir 875cdf0e10cSrcweir // Setting SELECT_OU_FEATURE to 1, which is probably superfluous 876cdf0e10cSrcweir // because this is already the default value. But only this 877cdf0e10cSrcweir // guarantees, that CustomAction SetNewFeatureState always sets 878cdf0e10cSrcweir // the correct FeatureState for "gm_o_Onlineupdate", if it is 879cdf0e10cSrcweir // already installed. 880cdf0e10cSrcweir SetMsiProperty(handle, TEXT("SELECT_OU_FEATURE")); 881cdf0e10cSrcweir } 882cdf0e10cSrcweir else 883cdf0e10cSrcweir { 884cdf0e10cSrcweir // std::_tstring mystr; 885cdf0e10cSrcweir // mystr = "Did not find file: " + sSearchFile; 886cdf0e10cSrcweir // MessageBox( NULL, mystr.c_str(), "File not found", MB_OK ); 887cdf0e10cSrcweir 888cdf0e10cSrcweir // If the file does not exist, the Online Update dialog 889cdf0e10cSrcweir // has to be shown. 890cdf0e10cSrcweir SetMsiProperty(handle, TEXT("SHOW_ONLINEUPDATE_DIALOG")); 891cdf0e10cSrcweir FindClose(hdl); 892cdf0e10cSrcweir } 893cdf0e10cSrcweir 894cdf0e10cSrcweir return ERROR_SUCCESS; 895cdf0e10cSrcweir } 896