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
getInstallerLocation(void)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 */
aoo_msi_load(LPCSTR lpProcName)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 );
aoo_MsiDllGetVersion(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 );
aoo_MsiGetPatchInfo(LPCTSTR szPatch,LPCTSTR szAttribute,LPTSTR lpValueBuf,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 );
aoo_MsiGetSummaryInformation(MSIHANDLE hDatabase,LPCTSTR szDatabasePath,UINT uiUpdateCount,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 );
aoo_MsiQueryProductState(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 );
aoo_MsiSummaryInfoGetProperty(MSIHANDLE hSummaryInfo,UINT uiProperty,PUINT puiDataType,LPINT piValue,FILETIME * pftValue,LPTSTR szValueBuf,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 );
aoo_MsiCloseHandle(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" {
MsiCloseHandle(MSIHANDLE hAny)235 UINT WINAPI MsiCloseHandle( MSIHANDLE hAny )
236 {
237 return aoo_MsiCloseHandle( hAny );
238 }
239 }
240