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
23
24 #define UNICODE
25
26 #ifdef _MSC_VER
27 #pragma warning(push, 1) /* disable warnings within system headers */
28 #endif
29 #include <windows.h>
30 #include <msiquery.h>
31 #ifdef _MSC_VER
32 #pragma warning(pop)
33 #endif
34
35 #include <string.h>
36 #include <malloc.h>
37
38 #define CHART_COMPONENT 1
39 #define DRAW_COMPONENT 2
40 #define IMPRESS_COMPONENT 4
41 #define CALC_COMPONENT 8
42 #define WRITER_COMPONENT 16
43 #define MATH_COMPONENT 32
44
45 // #define OWN_DEBUG_PRINT
46
47 typedef int ( __stdcall * DllNativeRegProc ) ( int, BOOL, BOOL, const char* );
48 typedef int ( __stdcall * DllNativeUnregProc ) ( int, BOOL, BOOL );
49
UnicodeEquals(wchar_t * pStr1,wchar_t * pStr2)50 BOOL UnicodeEquals( wchar_t* pStr1, wchar_t* pStr2 )
51 {
52 if ( pStr1 == NULL && pStr2 == NULL )
53 return TRUE;
54 else if ( pStr1 == NULL || pStr2 == NULL )
55 return FALSE;
56
57 while( *pStr1 == *pStr2 && *pStr1 && *pStr2 )
58 pStr1++, pStr2++;
59
60 return ( *pStr1 == 0 && *pStr2 == 0 );
61 }
62
63 //----------------------------------------------------------
UnicodeToAnsiString(wchar_t * pUniString)64 char* UnicodeToAnsiString( wchar_t* pUniString )
65 {
66 int len = WideCharToMultiByte(
67 CP_ACP, 0, pUniString, -1, 0, 0, 0, 0 );
68
69 char* buff = reinterpret_cast<char*>( malloc( len ) );
70
71 WideCharToMultiByte(
72 CP_ACP, 0, pUniString, -1, buff, len, 0, 0 );
73
74 return buff;
75 }
76
77 #ifdef OWN_DEBUG_PRINT
WarningMessageInt(wchar_t * pWarning,unsigned int nValue)78 void WarningMessageInt( wchar_t* pWarning, unsigned int nValue )
79 {
80 wchar_t pStr[5] = { nValue%10000/1000 + 48, nValue%1000/100 + 48, nValue%100/10 + 48, nValue%10 + 48, 0 };
81 MessageBox(NULL, pStr, pWarning, MB_OK | MB_ICONINFORMATION);
82 }
83 #endif
84
85 //----------------------------------------------------------
RegisterActiveXNative(const char * pActiveXPath,int nMode,BOOL InstallForAllUser,BOOL InstallFor64Bit)86 void RegisterActiveXNative( const char* pActiveXPath, int nMode, BOOL InstallForAllUser, BOOL InstallFor64Bit )
87 {
88 #ifdef OWN_DEBUG_PRINT
89 MessageBoxW(NULL, L"RegisterActiveXNative", L"Information", MB_OK | MB_ICONINFORMATION);
90 MessageBoxA(NULL, pActiveXPath, "Library Path", MB_OK | MB_ICONINFORMATION);
91 #endif
92
93 // For Win98/WinME the values should be written to the local machine
94 OSVERSIONINFO aVerInfo;
95 aVerInfo.dwOSVersionInfoSize = sizeof( aVerInfo );
96 if ( GetVersionEx( &aVerInfo ) && aVerInfo.dwPlatformId != VER_PLATFORM_WIN32_NT )
97 InstallForAllUser = TRUE;
98
99 HINSTANCE hModule = LoadLibraryExA( pActiveXPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
100 if( !( hModule <= ( HINSTANCE )HINSTANCE_ERROR ) )
101 {
102 DllNativeRegProc pNativeProc = ( DllNativeRegProc )GetProcAddress( hModule, "DllRegisterServerNative" );
103 if( pNativeProc!=NULL )
104 {
105 #ifdef OWN_DEBUG_PRINT
106 MessageBoxA(NULL, pActiveXPath, "Library Path", MB_OK | MB_ICONINFORMATION);
107 #endif
108 int nLen = strlen( pActiveXPath );
109 int nRemoveLen = strlen( "\\so_activex.dll" );
110 if ( nLen > nRemoveLen )
111 {
112 char* pProgramPath = reinterpret_cast<char*>( malloc( nLen - nRemoveLen + 1 ) );
113 strncpy( pProgramPath, pActiveXPath, nLen - nRemoveLen );
114 pProgramPath[ nLen - nRemoveLen ] = 0;
115
116 ( *pNativeProc )( nMode, InstallForAllUser, InstallFor64Bit, pProgramPath );
117
118 free( pProgramPath );
119 }
120 }
121
122 FreeLibrary( hModule );
123 }
124 }
125
126 //----------------------------------------------------------
UnregisterActiveXNative(const char * pActiveXPath,int nMode,BOOL InstallForAllUser,BOOL InstallFor64Bit)127 void UnregisterActiveXNative( const char* pActiveXPath, int nMode, BOOL InstallForAllUser, BOOL InstallFor64Bit )
128 {
129 // For Win98/WinME the values should be written to the local machine
130 OSVERSIONINFO aVerInfo;
131 aVerInfo.dwOSVersionInfoSize = sizeof( aVerInfo );
132 if ( GetVersionEx( &aVerInfo ) && aVerInfo.dwPlatformId != VER_PLATFORM_WIN32_NT )
133 InstallForAllUser = TRUE;
134
135 HINSTANCE hModule = LoadLibraryExA( pActiveXPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
136 if( !( hModule <= ( HINSTANCE )HINSTANCE_ERROR ) )
137 {
138 DllNativeUnregProc pNativeProc = ( DllNativeUnregProc )GetProcAddress( hModule, "DllUnregisterServerNative" );
139 if( pNativeProc!=NULL )
140 ( *pNativeProc )( nMode, InstallForAllUser, InstallFor64Bit );
141
142 FreeLibrary( hModule );
143 }
144 }
145
146 //----------------------------------------------------------
GetMsiProp(MSIHANDLE hMSI,const wchar_t * pPropName,wchar_t ** ppValue)147 BOOL GetMsiProp( MSIHANDLE hMSI, const wchar_t* pPropName, wchar_t** ppValue )
148 {
149 DWORD sz = 0;
150 if ( MsiGetProperty( hMSI, pPropName, L"", &sz ) == ERROR_MORE_DATA )
151 {
152 sz++;
153 DWORD nbytes = sz * sizeof( wchar_t );
154 wchar_t* buff = reinterpret_cast<wchar_t*>( malloc( nbytes ) );
155 ZeroMemory( buff, nbytes );
156 MsiGetProperty( hMSI, pPropName, buff, &sz );
157 *ppValue = buff;
158
159 return TRUE;
160 }
161
162 return FALSE;
163 }
164
165 //----------------------------------------------------------
GetActiveXControlPath(MSIHANDLE hMSI,char ** ppActiveXPath)166 BOOL GetActiveXControlPath( MSIHANDLE hMSI, char** ppActiveXPath )
167 {
168 wchar_t* pProgPath = NULL;
169 if ( GetMsiProp( hMSI, L"INSTALLLOCATION", &pProgPath ) && pProgPath )
170 {
171 char* pCharProgPath = UnicodeToAnsiString( pProgPath );
172 #ifdef OWN_DEBUG_PRINT
173 MessageBox(NULL, pProgPath, L"Basis Installation Path", MB_OK | MB_ICONINFORMATION);
174 MessageBoxA(NULL, pCharProgPath, "Basis Installation Path( char )", MB_OK | MB_ICONINFORMATION);
175 #endif
176
177 if ( pCharProgPath )
178 {
179 int nLen = strlen( pCharProgPath );
180 *ppActiveXPath = reinterpret_cast<char*>( malloc( nLen + 23 ) );
181 strncpy( *ppActiveXPath, pCharProgPath, nLen );
182 strncpy( (*ppActiveXPath) + nLen, "program\\so_activex.dll", 22 );
183 (*ppActiveXPath)[nLen+22] = 0;
184
185 free( pCharProgPath );
186
187 return TRUE;
188 }
189
190 free( pProgPath );
191 }
192
193 return FALSE;
194 }
195
196 //----------------------------------------------------------
GetDelta(MSIHANDLE hMSI,int & nOldInstallMode,int & nInstallMode,int & nDeinstallMode)197 BOOL GetDelta( MSIHANDLE hMSI, int& nOldInstallMode, int& nInstallMode, int& nDeinstallMode )
198 {
199 // for now the chart is always installed
200 nOldInstallMode = CHART_COMPONENT;
201 nInstallMode = CHART_COMPONENT;
202 nDeinstallMode = 0;
203
204 INSTALLSTATE current_state;
205 INSTALLSTATE future_state;
206
207 if ( ERROR_SUCCESS == MsiGetFeatureState( hMSI, L"gm_p_Wrt_Bin", ¤t_state, &future_state ) )
208 {
209 #ifdef OWN_DEBUG_PRINT
210 WarningMessageInt( L"writer current_state = ", current_state );
211 WarningMessageInt( L"writer future_state = ", future_state );
212 #endif
213
214 // analyze writer installation mode
215 if ( current_state == INSTALLSTATE_LOCAL )
216 nOldInstallMode |= WRITER_COMPONENT;
217
218 if ( future_state == INSTALLSTATE_LOCAL
219 || ( current_state == INSTALLSTATE_LOCAL && future_state == INSTALLSTATE_UNKNOWN ) )
220 nInstallMode |= WRITER_COMPONENT;
221 else if ( current_state == INSTALLSTATE_LOCAL && future_state == INSTALLSTATE_ABSENT )
222 nDeinstallMode |= WRITER_COMPONENT;
223 }
224 else
225 {
226 // assert( FALSE );
227 }
228
229 if ( ERROR_SUCCESS == MsiGetFeatureState( hMSI, L"gm_p_Calc_Bin", ¤t_state, &future_state ) )
230 {
231 #ifdef OWN_DEBUG_PRINT
232 WarningMessageInt( L"calc current_state = ", current_state );
233 WarningMessageInt( L"calc future_state = ", future_state );
234 #endif
235
236 // analyze calc installation mode
237 if ( current_state == INSTALLSTATE_LOCAL )
238 nOldInstallMode |= CALC_COMPONENT;
239
240 if ( future_state == INSTALLSTATE_LOCAL
241 || ( current_state == INSTALLSTATE_LOCAL && future_state == INSTALLSTATE_UNKNOWN ) )
242 nInstallMode |= CALC_COMPONENT;
243 else if ( current_state == INSTALLSTATE_LOCAL && future_state == INSTALLSTATE_ABSENT )
244 nDeinstallMode |= CALC_COMPONENT;
245 }
246 else
247 {
248 // assert( FALSE );
249 }
250
251 if ( ERROR_SUCCESS == MsiGetFeatureState( hMSI, L"gm_p_Draw_Bin", ¤t_state, &future_state ) )
252 {
253 // analyze draw installation mode
254 if ( current_state == INSTALLSTATE_LOCAL )
255 nOldInstallMode |= DRAW_COMPONENT;
256
257 if ( future_state == INSTALLSTATE_LOCAL
258 || ( current_state == INSTALLSTATE_LOCAL && future_state == INSTALLSTATE_UNKNOWN ) )
259 nInstallMode |= DRAW_COMPONENT;
260 else if ( current_state == INSTALLSTATE_LOCAL && future_state == INSTALLSTATE_ABSENT )
261 nDeinstallMode |= DRAW_COMPONENT;
262 }
263 else
264 {
265 // assert( FALSE );
266 }
267
268 if ( ERROR_SUCCESS == MsiGetFeatureState( hMSI, L"gm_p_Impress_Bin", ¤t_state, &future_state ) )
269 {
270 // analyze impress installation mode
271 if ( current_state == INSTALLSTATE_LOCAL )
272 nOldInstallMode |= IMPRESS_COMPONENT;
273
274 if ( future_state == INSTALLSTATE_LOCAL
275 || ( current_state == INSTALLSTATE_LOCAL && future_state == INSTALLSTATE_UNKNOWN ) )
276 nInstallMode |= IMPRESS_COMPONENT;
277 else if ( current_state == INSTALLSTATE_LOCAL && future_state == INSTALLSTATE_ABSENT )
278 nDeinstallMode |= IMPRESS_COMPONENT;
279 }
280 else
281 {
282 // assert( FALSE );
283 }
284
285 if ( ERROR_SUCCESS == MsiGetFeatureState( hMSI, L"gm_p_Math_Bin", ¤t_state, &future_state ) )
286 {
287 // analyze math installation mode
288 if ( current_state == INSTALLSTATE_LOCAL )
289 nOldInstallMode |= MATH_COMPONENT;
290
291 if ( future_state == INSTALLSTATE_LOCAL
292 || ( current_state == INSTALLSTATE_LOCAL && future_state == INSTALLSTATE_UNKNOWN ) )
293 nInstallMode |= MATH_COMPONENT;
294 else if ( current_state == INSTALLSTATE_LOCAL && future_state == INSTALLSTATE_ABSENT )
295 nDeinstallMode |= MATH_COMPONENT;
296 }
297 else
298 {
299 // assert( FALSE );
300 }
301
302 return TRUE;
303 }
304
305 //----------------------------------------------------------
MakeInstallForAllUsers(MSIHANDLE hMSI)306 BOOL MakeInstallForAllUsers( MSIHANDLE hMSI )
307 {
308 BOOL bResult = FALSE;
309 wchar_t* pVal = NULL;
310 if ( GetMsiProp( hMSI, L"ALLUSERS", &pVal ) && pVal )
311 {
312 bResult = UnicodeEquals( pVal , L"1" );
313 free( pVal );
314 }
315
316 return bResult;
317 }
318
319 //----------------------------------------------------------
MakeInstallFor64Bit(MSIHANDLE hMSI)320 BOOL MakeInstallFor64Bit( MSIHANDLE hMSI )
321 {
322 BOOL bResult = FALSE;
323 wchar_t* pVal = NULL;
324 if ( GetMsiProp( hMSI, L"VersionNT64", &pVal ) && pVal )
325 {
326 bResult = TRUE;
327 free( pVal );
328 }
329
330 return bResult;
331 }
332 //----------------------------------------------------------
InstallActiveXControl(MSIHANDLE hMSI)333 extern "C" UINT __stdcall InstallActiveXControl( MSIHANDLE hMSI )
334 {
335 int nOldInstallMode = 0;
336 int nInstallMode = 0;
337 int nDeinstallMode = 0;
338
339 #ifdef OWN_DEBUG_PRINT
340 MessageBox(NULL, L"InstallActiveXControl", L"Information", MB_OK | MB_ICONINFORMATION);
341 #endif
342
343 INSTALLSTATE current_state;
344 INSTALLSTATE future_state;
345
346 if ( ERROR_SUCCESS == MsiGetFeatureState( hMSI, L"gm_o_Activexcontrol", ¤t_state, &future_state ) )
347 {
348 #ifdef OWN_DEBUG_PRINT
349 MessageBox(NULL, L"InstallActiveXControl Step2", L"Information", MB_OK | MB_ICONINFORMATION);
350 #endif
351
352 BOOL bInstallForAllUser = MakeInstallForAllUsers( hMSI );
353 BOOL bInstallFor64Bit = MakeInstallFor64Bit( hMSI );
354
355 char* pActiveXPath = NULL;
356 if ( GetActiveXControlPath( hMSI, &pActiveXPath ) && pActiveXPath
357 && GetDelta( hMSI, nOldInstallMode, nInstallMode, nDeinstallMode ) )
358 {
359 #ifdef OWN_DEBUG_PRINT
360 MessageBox(NULL, L"InstallActiveXControl Step3", L"Information", MB_OK | MB_ICONINFORMATION);
361 #endif
362
363 if ( future_state == INSTALLSTATE_LOCAL
364 || ( current_state == INSTALLSTATE_LOCAL && future_state == INSTALLSTATE_UNKNOWN ) )
365 {
366 #ifdef OWN_DEBUG_PRINT
367 MessageBox(NULL, L"InstallActiveXControl, adjusting", L"Information", MB_OK | MB_ICONINFORMATION);
368 WarningMessageInt( L"nInstallMode = ", nInstallMode );
369 #endif
370 // the control is installed in the new selected configuration
371
372 if ( current_state == INSTALLSTATE_LOCAL && nDeinstallMode )
373 UnregisterActiveXNative( pActiveXPath, nDeinstallMode, bInstallForAllUser, bInstallFor64Bit );
374
375 if ( nInstallMode )
376 RegisterActiveXNative( pActiveXPath, nInstallMode, bInstallForAllUser, bInstallFor64Bit );
377 }
378 else if ( current_state == INSTALLSTATE_LOCAL && future_state == INSTALLSTATE_ABSENT )
379 {
380 #ifdef OWN_DEBUG_PRINT
381 MessageBox(NULL, L"InstallActiveXControl, removing", L"Information", MB_OK | MB_ICONINFORMATION);
382 #endif
383 if ( nOldInstallMode )
384 UnregisterActiveXNative( pActiveXPath, nOldInstallMode, bInstallForAllUser, bInstallFor64Bit );
385 }
386 }
387
388 if ( pActiveXPath )
389 free( pActiveXPath );
390 }
391 else
392 {
393 // assert( FALSE );
394 }
395
396 return ERROR_SUCCESS;
397 }
398
399 //----------------------------------------------------------
DeinstallActiveXControl(MSIHANDLE hMSI)400 extern "C" UINT __stdcall DeinstallActiveXControl( MSIHANDLE hMSI )
401 {
402 INSTALLSTATE current_state;
403 INSTALLSTATE future_state;
404
405 #ifdef OWN_DEBUG_PRINT
406 MessageBox(NULL, L"DeinstallActiveXControl", L"Information", MB_OK | MB_ICONINFORMATION);
407 #endif
408
409 if ( ERROR_SUCCESS == MsiGetFeatureState( hMSI, L"gm_o_Activexcontrol", ¤t_state, &future_state ) )
410 {
411 char* pActiveXPath = NULL;
412 if ( current_state == INSTALLSTATE_LOCAL && GetActiveXControlPath( hMSI, &pActiveXPath ) && pActiveXPath )
413 {
414 BOOL bInstallForAllUser = MakeInstallForAllUsers( hMSI );
415 BOOL bInstallFor64Bit = MakeInstallFor64Bit( hMSI );
416
417 {
418 UnregisterActiveXNative( pActiveXPath,
419 CHART_COMPONENT
420 | DRAW_COMPONENT
421 | IMPRESS_COMPONENT
422 | CALC_COMPONENT
423 | WRITER_COMPONENT
424 | MATH_COMPONENT,
425 bInstallForAllUser,
426 bInstallFor64Bit );
427 }
428
429 free( pActiveXPath );
430 }
431 }
432
433 return ERROR_SUCCESS;
434 }
435