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 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 //---------------------------------------------------------- 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 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 //---------------------------------------------------------- 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 //---------------------------------------------------------- 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 //---------------------------------------------------------- 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 //---------------------------------------------------------- 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 //---------------------------------------------------------- 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 //---------------------------------------------------------- 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 //---------------------------------------------------------- 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 //---------------------------------------------------------- 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 //---------------------------------------------------------- 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