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", &current_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", &current_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", &current_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", &current_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", &current_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", &current_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", &current_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