blob: 35fa59b4bce41f339c5bb7ccfa9be9c85b8147e0 [file]
/**************************************************************
*
* 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 <strsafe.h>
/// 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 );
}
}