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 #define _WIN32_WINDOWS 0x0410 25 26 #ifdef _MSC_VER 27 #pragma warning(push, 1) /* disable warnings within system headers */ 28 #endif 29 #define WIN32_LEAN_AND_MEAN 30 #include <windows.h> 31 #include <msiquery.h> 32 #ifdef _MSC_VER 33 #pragma warning(pop) 34 #endif 35 36 #include <malloc.h> 37 #include <assert.h> 38 39 #ifdef UNICODE 40 #define _UNICODE 41 #define _tstring wstring 42 #else 43 #define _tstring string 44 #endif 45 #include <tchar.h> 46 #include <string> 47 #include <queue> 48 #include <stdio.h> 49 50 #include <systools/win32/uwinapi.h> 51 #include <../tools/seterror.hxx> 52 53 #define WININIT_FILENAME "wininit.ini" 54 #define RENAME_SECTION "rename" 55 56 #ifdef DEBUG 57 inline void OutputDebugStringFormat( LPCTSTR pFormat, ... ) 58 { 59 _TCHAR buffer[1024]; 60 va_list args; 61 62 va_start( args, pFormat ); 63 _vsntprintf( buffer, elementsof(buffer), pFormat, args ); 64 OutputDebugString( buffer ); 65 } 66 #else 67 static inline void OutputDebugStringFormat( LPCTSTR, ... ) 68 { 69 } 70 #endif 71 72 static std::_tstring GetMsiProperty( MSIHANDLE handle, const std::_tstring& sProperty ) 73 { 74 std::_tstring result; 75 TCHAR szDummy[1] = TEXT(""); 76 DWORD nChars = 0; 77 78 if ( MsiGetProperty( handle, sProperty.c_str(), szDummy, &nChars ) == ERROR_MORE_DATA ) 79 { 80 DWORD nBytes = ++nChars * sizeof(TCHAR); 81 LPTSTR buffer = reinterpret_cast<LPTSTR>(_alloca(nBytes)); 82 ZeroMemory( buffer, nBytes ); 83 MsiGetProperty(handle, sProperty.c_str(), buffer, &nChars); 84 result = buffer; 85 } 86 87 return result; 88 } 89 90 static inline bool IsSetMsiProperty(MSIHANDLE handle, const std::_tstring& sProperty) 91 { 92 std::_tstring value = GetMsiProperty(handle, sProperty); 93 return (value.length() > 0); 94 } 95 96 static inline void UnsetMsiProperty(MSIHANDLE handle, const std::_tstring& sProperty) 97 { 98 MsiSetProperty(handle, sProperty.c_str(), NULL); 99 } 100 101 static inline void SetMsiProperty(MSIHANDLE handle, const std::_tstring& sProperty) 102 { 103 MsiSetProperty(handle, sProperty.c_str(), TEXT("1")); 104 } 105 106 static BOOL MoveFileEx9x( LPCSTR lpExistingFileNameA, LPCSTR lpNewFileNameA, DWORD dwFlags ) 107 { 108 BOOL fSuccess = FALSE; // assume failure 109 110 // Windows 9x has a special mechanism to move files after reboot 111 112 if ( dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT ) 113 { 114 CHAR szExistingFileNameA[MAX_PATH]; 115 CHAR szNewFileNameA[MAX_PATH] = "NUL"; 116 117 // Path names in WININIT.INI must be in short path name form 118 119 if ( 120 GetShortPathNameA( lpExistingFileNameA, szExistingFileNameA, MAX_PATH ) && 121 (!lpNewFileNameA || GetShortPathNameA( lpNewFileNameA, szNewFileNameA, MAX_PATH )) 122 ) 123 { 124 CHAR szBuffer[32767]; // The buffer size must not exceed 32K 125 DWORD dwBufLen = GetPrivateProfileSectionA( RENAME_SECTION, szBuffer, elementsof(szBuffer), WININIT_FILENAME ); 126 127 CHAR szRename[MAX_PATH]; // This is enough for at most to times 67 chracters 128 strcpy( szRename, szNewFileNameA ); 129 strcat( szRename, "=" ); 130 strcat( szRename, szExistingFileNameA ); 131 size_t lnRename = strlen(szRename); 132 133 if ( dwBufLen + lnRename + 2 <= elementsof(szBuffer) ) 134 { 135 CopyMemory( &szBuffer[dwBufLen], szRename, lnRename ); 136 szBuffer[dwBufLen + lnRename ] = 0; 137 szBuffer[dwBufLen + lnRename + 1 ] = 0; 138 139 fSuccess = WritePrivateProfileSectionA( RENAME_SECTION, szBuffer, WININIT_FILENAME ); 140 } 141 else 142 SetLastError( ERROR_BUFFER_OVERFLOW ); 143 } 144 } 145 else 146 { 147 148 fSuccess = MoveFileA( lpExistingFileNameA, lpNewFileNameA ); 149 150 if ( !fSuccess && GetLastError() != ERROR_ACCESS_DENIED && 151 0 != (dwFlags & (MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING)) ) 152 { 153 BOOL bFailIfExist = 0 == (dwFlags & MOVEFILE_REPLACE_EXISTING); 154 155 fSuccess = CopyFileA( lpExistingFileNameA, lpNewFileNameA, bFailIfExist ); 156 157 if ( fSuccess ) 158 fSuccess = DeleteFileA( lpExistingFileNameA ); 159 } 160 161 } 162 163 return fSuccess; 164 } 165 166 static BOOL MoveFileExImpl( LPCSTR lpExistingFileNameA, LPCSTR lpNewFileNameA, DWORD dwFlags ) 167 { 168 if ( 0 > ((LONG)GetVersion())) // High order bit indicates Win 9x 169 return MoveFileEx9x( lpExistingFileNameA, lpNewFileNameA, dwFlags ); 170 else 171 return MoveFileExA( lpExistingFileNameA, lpNewFileNameA, dwFlags ); 172 } 173 174 extern "C" UINT __stdcall IsOfficeRunning( MSIHANDLE handle ) 175 { 176 std::_tstring sInstDir = GetMsiProperty( handle, TEXT("INSTALLLOCATION") ); 177 // std::_tstring sResourceDir = sInstDir + TEXT("Basis\\program\\resource\\"); 178 std::_tstring sResourceDir = sInstDir + TEXT("program\\resource\\"); 179 std::_tstring sPattern = sResourceDir + TEXT("vcl*.res"); 180 181 WIN32_FIND_DATA aFindFileData; 182 HANDLE hFind = FindFirstFile( sPattern.c_str(), &aFindFileData ); 183 184 if ( IsValidHandle(hFind) ) 185 { 186 BOOL fSuccess = false; 187 bool fRenameSucceeded; 188 189 do 190 { 191 std::_tstring sResourceFile = sResourceDir + aFindFileData.cFileName; 192 std::_tstring sIntermediate = sResourceFile + TEXT(".tmp"); 193 194 fRenameSucceeded = MoveFileExImpl( sResourceFile.c_str(), sIntermediate.c_str(), MOVEFILE_REPLACE_EXISTING ); 195 if ( fRenameSucceeded ) 196 { 197 MoveFileExImpl( sIntermediate.c_str(), sResourceFile.c_str(), 0 ); 198 fSuccess = FindNextFile( hFind, &aFindFileData ); 199 } 200 } while ( fSuccess && fRenameSucceeded ); 201 202 if ( !fRenameSucceeded ) 203 { 204 MsiSetProperty(handle, TEXT("OFFICERUNS"), TEXT("1")); 205 SetMsiErrorCode( MSI_ERROR_OFFICE_IS_RUNNING ); 206 } 207 208 FindClose( hFind ); 209 } 210 211 return ERROR_SUCCESS; 212 } 213 214 215 216