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