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 1 23 #define _UNICODE 1 24 25 #include "aoo_msi.hxx" 26 27 #include <strsafe.h> 28 29 /// Handle to MSI.DLL 30 static HMODULE hMsi = NULL; 31 32 33 TCHAR *getInstallerLocation( void ) 34 { 35 static const TCHAR sInstKey[] = TEXT( "Software\\Microsoft\\Windows\\CurrentVersion\\Installer" ); 36 static const TCHAR sInstLocValue[] = TEXT( "InstallerLocation" ); 37 38 HKEY hInstKey = NULL; 39 TCHAR *sMsiFolder = new TCHAR[ MAX_PATH + 1 ]; 40 sMsiFolder[0] = '\0'; 41 42 // find registered location of Msi.dll 43 if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, sInstKey, 0, KEY_READ, &hInstKey ) ) 44 { 45 long nRet = ERROR_SUCCESS; 46 DWORD dwMsiFolderSize = MAX_PATH + 1; 47 DWORD dwType = 0; 48 49 if ( ERROR_MORE_DATA == ( nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, 50 &dwType, (BYTE*)sMsiFolder, &dwMsiFolderSize ) ) ) 51 { 52 // try again with larger buffer 53 delete [] sMsiFolder; 54 sMsiFolder = new TCHAR[ dwMsiFolderSize ]; 55 nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, &dwType, 56 (BYTE*)sMsiFolder, &dwMsiFolderSize ); 57 } 58 59 if ( ( ERROR_SUCCESS == nRet) && 60 ( dwType == REG_SZ ) && ( dwMsiFolderSize ) ) { 61 // Make sure the string is null-terminated 62 sMsiFolder[dwMsiFolderSize / sizeof ( TCHAR ) + 1] = 0; 63 } else { 64 sMsiFolder[0] = '\0'; 65 } 66 } 67 return sMsiFolder; 68 } 69 70 /** Load MSI.DLL and a symbol from it 71 * 72 * @return the requested symbol, or NULL in case of error. 73 */ 74 static FARPROC aoo_msi_load( LPCSTR lpProcName ) 75 { 76 static const TCHAR sMsiDll[] = TEXT( "\\msi.dll" ); 77 if ( !hMsi ) // use the default location 78 { 79 TCHAR *sInstallerLocation = getInstallerLocation(); 80 if ( sInstallerLocation[0] ) 81 { 82 // load Msi.dll from registered location 83 int nLength = lstrlen( sMsiDll ) + lstrlen( sInstallerLocation ) + 1; // use StringCchLength ? 84 TCHAR *pMsiLocation = new TCHAR[ nLength ]; 85 86 if ( SUCCEEDED( StringCchCopy( pMsiLocation, nLength, sInstallerLocation ) ) && 87 SUCCEEDED( StringCchCat( pMsiLocation, nLength, sMsiDll ) ) ) 88 { 89 hMsi = LoadLibrary( pMsiLocation ); 90 } 91 delete[] pMsiLocation; 92 } 93 delete[] sInstallerLocation; 94 } 95 if ( !hMsi ) 96 { 97 return NULL; 98 } 99 return GetProcAddress( hMsi, lpProcName ); 100 } 101 102 103 typedef HRESULT (CALLBACK* PFnDllGetVersion)( DLLVERSIONINFO *pdvi ); 104 HRESULT aoo_MsiDllGetVersion( DLLVERSIONINFO *pdvi ) { 105 static PFnDllGetVersion f = NULL; 106 if ( f == NULL ) 107 f = (PFnDllGetVersion) aoo_msi_load( "DllGetVersion" ); 108 if ( f == NULL ) 109 return HRESULT_FROM_WIN32( GetLastError() ); 110 return f( pdvi ); 111 } 112 113 typedef UINT (WINAPI* PFnMsiGetPatchInfo)( LPCTSTR szPatch, 114 LPCTSTR szAttribute, 115 LPTSTR lpValueBuf, 116 LPDWORD pcchValueBuf ); 117 UINT WINAPI aoo_MsiGetPatchInfo( LPCTSTR szPatch, 118 LPCTSTR szAttribute, 119 LPTSTR lpValueBuf, 120 LPDWORD pcchValueBuf ) 121 { 122 static PFnMsiGetPatchInfo f = NULL; 123 if ( f == NULL ) 124 { 125 #ifdef UNICODE 126 f = (PFnMsiGetPatchInfo) aoo_msi_load( "MsiGetPatchInfoW" ); 127 #else 128 f = (PFnMsiGetPatchInfo) aoo_msi_load( "MsiGetPatchInfoA" ); 129 #endif 130 } 131 if ( !f ) 132 { 133 return ERROR_BAD_CONFIGURATION; 134 } 135 return f( szPatch, szAttribute, lpValueBuf, pcchValueBuf ); 136 } 137 138 typedef UINT (WINAPI* PFnMsiGetSummaryInformation)( MSIHANDLE hDatabase, 139 LPCTSTR szDatabasePath, 140 UINT uiUpdateCount, 141 MSIHANDLE *phSummaryInfo ); 142 UINT WINAPI aoo_MsiGetSummaryInformation( MSIHANDLE hDatabase, 143 LPCTSTR szDatabasePath, 144 UINT uiUpdateCount, 145 MSIHANDLE *phSummaryInfo ) 146 { 147 static PFnMsiGetSummaryInformation f = NULL; 148 if ( f == NULL ) 149 { 150 #ifdef UNICODE 151 f = (PFnMsiGetSummaryInformation) aoo_msi_load( "MsiGetSummaryInformationW" ); 152 #else 153 f = (PFnMsiGetSummaryInformation) aoo_msi_load( "MsiGetSummaryInformationA" ); 154 #endif 155 } 156 if ( f == NULL ) 157 { 158 return ERROR_BAD_CONFIGURATION; 159 } 160 return f( hDatabase, szDatabasePath, uiUpdateCount, phSummaryInfo ); 161 } 162 163 typedef INSTALLSTATE (WINAPI* PFnMsiQueryProductState)( LPCTSTR szProduct ); 164 INSTALLSTATE WINAPI aoo_MsiQueryProductState( LPCTSTR szProduct ) 165 { 166 static PFnMsiQueryProductState f = NULL; 167 if ( f == NULL ) 168 { 169 #ifdef UNICODE 170 f = (PFnMsiQueryProductState) aoo_msi_load( "MsiQueryProductStateW" ); 171 #else 172 f = (PFnMsiQueryProductState) aoo_msi_load( "MsiQueryProductStateA" ); 173 #endif 174 } 175 if ( f == NULL ) 176 { 177 return INSTALLSTATE_INVALIDARG; 178 } 179 return f( szProduct ); 180 } 181 182 typedef UINT (WINAPI* PFnMsiSummaryInfoGetProperty)( MSIHANDLE hSummaryInfo, 183 UINT uiProperty, 184 PUINT puiDataType, 185 LPINT piValue, 186 FILETIME *pftValue, 187 LPTSTR szValueBuf, 188 LPDWORD pcchValueBuf ); 189 UINT WINAPI aoo_MsiSummaryInfoGetProperty( MSIHANDLE hSummaryInfo, 190 UINT uiProperty, 191 PUINT puiDataType, 192 LPINT piValue, 193 FILETIME *pftValue, 194 LPTSTR szValueBuf, 195 LPDWORD pcchValueBuf ) 196 { 197 static PFnMsiSummaryInfoGetProperty f = NULL; 198 if ( f == NULL ) 199 { 200 #ifdef UNICODE 201 f = (PFnMsiSummaryInfoGetProperty) aoo_msi_load( "MsSummaryInfoGetPropertyW" ); 202 #else 203 f = (PFnMsiSummaryInfoGetProperty) aoo_msi_load( "MsSummaryInfoGetPropertyA" ); 204 #endif 205 } 206 if ( f == NULL ) 207 { 208 return ERROR_INVALID_FUNCTION; 209 } 210 return f( hSummaryInfo, uiProperty, puiDataType, piValue, pftValue, 211 szValueBuf, pcchValueBuf ); 212 } 213 214 215 typedef UINT (WINAPI *PFnMsiCloseHandle)( MSIHANDLE hAny ); 216 UINT WINAPI aoo_MsiCloseHandle( MSIHANDLE hAny ) 217 { 218 static PFnMsiCloseHandle f = NULL; 219 if ( f == NULL ) 220 { 221 f = (PFnMsiCloseHandle) aoo_msi_load( "MsiCloseHandle" ); 222 } 223 if ( f == NULL ) 224 { 225 return ERROR_INVALID_FUNCTION; 226 } 227 return f( hAny ); 228 } 229 230 /* 231 * MsiCloseHandle() must be defined because it is required by the 232 * destructor of class PMSIHANDLE, defined in Msi.h. 233 */ 234 extern "C" { 235 UINT WINAPI MsiCloseHandle( MSIHANDLE hAny ) 236 { 237 return aoo_MsiCloseHandle( hAny ); 238 } 239 } 240