xref: /trunk/main/desktop/win32/source/setup/aoo_msi.cxx (revision a2971faee62b678751866b8308f86df85c7eacbd)
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