/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ #define UNICODE 1 #define _UNICODE 1 #include "aoo_msi.hxx" #include /// Handle to MSI.DLL static HMODULE hMsi = NULL; TCHAR *getInstallerLocation( void ) { static const TCHAR sInstKey[] = TEXT( "Software\\Microsoft\\Windows\\CurrentVersion\\Installer" ); static const TCHAR sInstLocValue[] = TEXT( "InstallerLocation" ); HKEY hInstKey = NULL; TCHAR *sMsiFolder = new TCHAR[ MAX_PATH + 1 ]; sMsiFolder[0] = '\0'; // find registered location of Msi.dll if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, sInstKey, 0, KEY_READ, &hInstKey ) ) { long nRet = ERROR_SUCCESS; DWORD dwMsiFolderSize = MAX_PATH + 1; DWORD dwType = 0; if ( ERROR_MORE_DATA == ( nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, &dwType, (BYTE*)sMsiFolder, &dwMsiFolderSize ) ) ) { // try again with larger buffer delete [] sMsiFolder; sMsiFolder = new TCHAR[ dwMsiFolderSize ]; nRet = RegQueryValueEx( hInstKey, sInstLocValue, NULL, &dwType, (BYTE*)sMsiFolder, &dwMsiFolderSize ); } if ( ( ERROR_SUCCESS == nRet) && ( dwType == REG_SZ ) && ( dwMsiFolderSize ) ) { // Make sure the string is null-terminated sMsiFolder[dwMsiFolderSize / sizeof ( TCHAR ) + 1] = 0; } else { sMsiFolder[0] = '\0'; } } return sMsiFolder; } /** Load MSI.DLL and a symbol from it * * @return the requested symbol, or NULL in case of error. */ static FARPROC aoo_msi_load( LPCSTR lpProcName ) { static const TCHAR sMsiDll[] = TEXT( "\\msi.dll" ); if ( !hMsi ) // use the default location { TCHAR *sInstallerLocation = getInstallerLocation(); if ( sInstallerLocation[0] ) { // load Msi.dll from registered location int nLength = lstrlen( sMsiDll ) + lstrlen( sInstallerLocation ) + 1; // use StringCchLength ? TCHAR *pMsiLocation = new TCHAR[ nLength ]; if ( SUCCEEDED( StringCchCopy( pMsiLocation, nLength, sInstallerLocation ) ) && SUCCEEDED( StringCchCat( pMsiLocation, nLength, sMsiDll ) ) ) { hMsi = LoadLibrary( pMsiLocation ); } delete[] pMsiLocation; } delete[] sInstallerLocation; } if ( !hMsi ) { return NULL; } return GetProcAddress( hMsi, lpProcName ); } typedef HRESULT (CALLBACK* PFnDllGetVersion)( DLLVERSIONINFO *pdvi ); HRESULT aoo_MsiDllGetVersion( DLLVERSIONINFO *pdvi ) { static PFnDllGetVersion f = NULL; if ( f == NULL ) f = (PFnDllGetVersion) aoo_msi_load( "DllGetVersion" ); if ( f == NULL ) return HRESULT_FROM_WIN32( GetLastError() ); return f( pdvi ); } typedef UINT (WINAPI* PFnMsiGetPatchInfo)( LPCTSTR szPatch, LPCTSTR szAttribute, LPTSTR lpValueBuf, LPDWORD pcchValueBuf ); UINT WINAPI aoo_MsiGetPatchInfo( LPCTSTR szPatch, LPCTSTR szAttribute, LPTSTR lpValueBuf, LPDWORD pcchValueBuf ) { static PFnMsiGetPatchInfo f = NULL; if ( f == NULL ) { #ifdef UNICODE f = (PFnMsiGetPatchInfo) aoo_msi_load( "MsiGetPatchInfoW" ); #else f = (PFnMsiGetPatchInfo) aoo_msi_load( "MsiGetPatchInfoA" ); #endif } if ( !f ) { return ERROR_BAD_CONFIGURATION; } return f( szPatch, szAttribute, lpValueBuf, pcchValueBuf ); } typedef UINT (WINAPI* PFnMsiGetSummaryInformation)( MSIHANDLE hDatabase, LPCTSTR szDatabasePath, UINT uiUpdateCount, MSIHANDLE *phSummaryInfo ); UINT WINAPI aoo_MsiGetSummaryInformation( MSIHANDLE hDatabase, LPCTSTR szDatabasePath, UINT uiUpdateCount, MSIHANDLE *phSummaryInfo ) { static PFnMsiGetSummaryInformation f = NULL; if ( f == NULL ) { #ifdef UNICODE f = (PFnMsiGetSummaryInformation) aoo_msi_load( "MsiGetSummaryInformationW" ); #else f = (PFnMsiGetSummaryInformation) aoo_msi_load( "MsiGetSummaryInformationA" ); #endif } if ( f == NULL ) { return ERROR_BAD_CONFIGURATION; } return f( hDatabase, szDatabasePath, uiUpdateCount, phSummaryInfo ); } typedef INSTALLSTATE (WINAPI* PFnMsiQueryProductState)( LPCTSTR szProduct ); INSTALLSTATE WINAPI aoo_MsiQueryProductState( LPCTSTR szProduct ) { static PFnMsiQueryProductState f = NULL; if ( f == NULL ) { #ifdef UNICODE f = (PFnMsiQueryProductState) aoo_msi_load( "MsiQueryProductStateW" ); #else f = (PFnMsiQueryProductState) aoo_msi_load( "MsiQueryProductStateA" ); #endif } if ( f == NULL ) { return INSTALLSTATE_INVALIDARG; } return f( szProduct ); } typedef UINT (WINAPI* PFnMsiSummaryInfoGetProperty)( MSIHANDLE hSummaryInfo, UINT uiProperty, PUINT puiDataType, LPINT piValue, FILETIME *pftValue, LPTSTR szValueBuf, LPDWORD pcchValueBuf ); UINT WINAPI aoo_MsiSummaryInfoGetProperty( MSIHANDLE hSummaryInfo, UINT uiProperty, PUINT puiDataType, LPINT piValue, FILETIME *pftValue, LPTSTR szValueBuf, LPDWORD pcchValueBuf ) { static PFnMsiSummaryInfoGetProperty f = NULL; if ( f == NULL ) { #ifdef UNICODE f = (PFnMsiSummaryInfoGetProperty) aoo_msi_load( "MsSummaryInfoGetPropertyW" ); #else f = (PFnMsiSummaryInfoGetProperty) aoo_msi_load( "MsSummaryInfoGetPropertyA" ); #endif } if ( f == NULL ) { return ERROR_INVALID_FUNCTION; } return f( hSummaryInfo, uiProperty, puiDataType, piValue, pftValue, szValueBuf, pcchValueBuf ); } typedef UINT (WINAPI *PFnMsiCloseHandle)( MSIHANDLE hAny ); UINT WINAPI aoo_MsiCloseHandle( MSIHANDLE hAny ) { static PFnMsiCloseHandle f = NULL; if ( f == NULL ) { f = (PFnMsiCloseHandle) aoo_msi_load( "MsiCloseHandle" ); } if ( f == NULL ) { return ERROR_INVALID_FUNCTION; } return f( hAny ); } /* * MsiCloseHandle() must be defined because it is required by the * destructor of class PMSIHANDLE, defined in Msi.h. */ extern "C" { UINT WINAPI MsiCloseHandle( MSIHANDLE hAny ) { return aoo_MsiCloseHandle( hAny ); } }