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