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 WIN32_LEAN_AND_MEAN 23 24 #ifdef _MSC_VER 25 #pragma warning(disable:4668 4917) // disable warnings for system headers 26 #endif 27 28 #include <windows.h> 29 #include <windowsx.h> 30 #include <shellapi.h> 31 #include <shlobj.h> 32 #include <tchar.h> 33 34 #include <stdio.h> 35 36 #define elementsof(buf) (sizeof(buf) / sizeof(buf[0])) 37 38 enum PathResult 39 { 40 PATHRESULT_OK, 41 PATHRESULT_API_NOT_SUPPORTED, 42 PATHRESULT_EXE_NOT_FOUND 43 }; 44 45 const int MAXCMDLINELEN = 32768; 46 47 static TCHAR g_szSTInstallationPath[MAX_PATH] = TEXT(""); 48 static TCHAR g_szOperatingSystem[256] = TEXT(""); 49 50 static const TCHAR g_szSTExecutable[256] = TEXT("stclient.exe"); 51 52 //*************************************************************************** 53 54 LONG RegReadValue( HKEY hBaseKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, LPVOID lpData, DWORD cbData ) 55 { 56 HKEY hKey = NULL; 57 LONG lResult( 0 ); 58 59 lResult = RegOpenKeyEx( hBaseKey, lpSubKey, 0, KEY_QUERY_VALUE, &hKey ); 60 61 if ( ERROR_SUCCESS == lResult ) 62 { 63 lResult = RegQueryValueEx( hKey, lpValueName, NULL, NULL, (LPBYTE)lpData, &cbData ); 64 RegCloseKey( hKey ); 65 } 66 67 return lResult; 68 } 69 70 //*************************************************************************** 71 72 static LPTSTR *GetCommandArgs( int *pArgc ) 73 { 74 #ifdef UNICODE 75 return CommandLineToArgvW( GetCommandLineW(), pArgc ); 76 #else 77 *pArgc = __argc; 78 return __argv; 79 #endif 80 } 81 82 //*************************************************************************** 83 84 static bool IsSupportedPlatform() 85 { 86 OSVERSIONINFO aOsVersion; 87 88 ZeroMemory( &aOsVersion, sizeof( OSVERSIONINFO )); 89 aOsVersion.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); 90 91 // Try to determine OS version 92 if ( GetVersionEx( &aOsVersion )) 93 { 94 switch ( aOsVersion.dwPlatformId ) 95 { 96 case VER_PLATFORM_WIN32_NT: // Windows NT based 97 return true; 98 99 case VER_PLATFORM_WIN32_WINDOWS: // Windows Me/98/95. 100 case VER_PLATFORM_WIN32s: // Win32s 101 return false; 102 103 default: 104 return false; 105 } 106 } 107 108 return false; 109 } 110 111 //*************************************************************************** 112 113 static LPCTSTR GetOperatingSystemString() 114 { 115 OSVERSIONINFO aOsVersion; 116 117 ZeroMemory( &aOsVersion, sizeof( OSVERSIONINFO )); 118 aOsVersion.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); 119 120 _tcscpy( g_szOperatingSystem, TEXT( "Microsoft Windows" )); 121 122 // Try to determine OS version 123 if ( GetVersionEx( &aOsVersion )) 124 { 125 switch ( aOsVersion.dwPlatformId ) 126 { 127 // Test for the Windows NT product family. 128 case VER_PLATFORM_WIN32_NT: 129 { 130 if ( aOsVersion.dwMajorVersion == 3 ) 131 { 132 _tcscat( g_szOperatingSystem, TEXT( " NT 3." )); 133 if ( aOsVersion.dwMinorVersion == 0 ) 134 _tcscat( g_szOperatingSystem, TEXT( "0" )); 135 else if ( aOsVersion.dwMinorVersion == 5 ) 136 _tcscat( g_szOperatingSystem, TEXT( "5" )); 137 else if ( aOsVersion.dwMinorVersion == 51 ) 138 _tcscat( g_szOperatingSystem, TEXT( "51" )); 139 } 140 else if ( aOsVersion.dwMajorVersion == 4 ) 141 _tcscat( g_szOperatingSystem, TEXT( " NT 4.0" )); 142 else if ( aOsVersion.dwMajorVersion == 5 ) 143 { 144 if ( aOsVersion.dwMinorVersion == 0 ) 145 _tcscat( g_szOperatingSystem, TEXT( " 2000" )); 146 else if ( aOsVersion.dwMinorVersion == 1 ) 147 _tcscat( g_szOperatingSystem, TEXT( " XP" )); 148 else if ( aOsVersion.dwMinorVersion == 2 ) 149 _tcscat( g_szOperatingSystem, TEXT( " Server 2003" )); 150 } 151 else if ( aOsVersion.dwMajorVersion == 6 ) 152 { 153 if ( aOsVersion.dwMinorVersion == 0 ) 154 _tcscat( g_szOperatingSystem, " Vista" ); 155 } 156 } 157 break; 158 159 // Test for the Windows Me/98/95. 160 case VER_PLATFORM_WIN32_WINDOWS: 161 { 162 if ( aOsVersion.dwMinorVersion == 0 ) 163 _tcscat( g_szOperatingSystem, TEXT( " 95" )); 164 else if ( aOsVersion.dwMinorVersion == 10 ) 165 _tcscat( g_szOperatingSystem, TEXT( " 98" )); 166 else if ( aOsVersion.dwMinorVersion == 90 ) 167 _tcscat( g_szOperatingSystem, TEXT( " Me" )); 168 } 169 break; 170 } 171 } 172 173 return g_szOperatingSystem; 174 } 175 176 //*************************************************************************** 177 178 static bool FileExists( LPCTSTR lpPathToFile ) 179 { 180 bool bResult = false; 181 HANDLE hFind; 182 WIN32_FIND_DATA FindFileData; 183 184 hFind = FindFirstFile( lpPathToFile, &FindFileData ); 185 186 if ( hFind != INVALID_HANDLE_VALUE ) 187 { 188 FindClose( hFind ); 189 bResult = true; 190 } 191 192 return bResult; 193 } 194 195 //*************************************************************************** 196 197 static bool GetProgramFilesFolder( LPTSTR strPath ) 198 { 199 bool bRet = false; 200 HINSTANCE hLibrary; 201 202 if (( hLibrary = LoadLibrary( "shell32.dll" )) != NULL ) 203 { 204 BOOL (WINAPI *pSHGetSpecialFolderPathA)( HWND, LPSTR, int, BOOL ); 205 206 pSHGetSpecialFolderPathA = (BOOL (WINAPI *)(HWND, LPSTR, int, BOOL))GetProcAddress( hLibrary, "SHGetSpecialFolderPathA" ); 207 208 if ( pSHGetSpecialFolderPathA ) 209 { 210 if ( pSHGetSpecialFolderPathA( NULL, strPath, CSIDL_PROGRAM_FILES, TRUE )) 211 bRet = true; 212 } 213 } 214 215 FreeLibrary( hLibrary ); 216 217 return ( bRet ); 218 } 219 220 //*************************************************************************** 221 222 static PathResult RetrieveExecutablePath( LPTSTR szExecutablePath ) 223 { 224 PathResult eRet = PATHRESULT_API_NOT_SUPPORTED; 225 TCHAR szProgramFilesFolder[MAX_PATH]; 226 227 if ( GetProgramFilesFolder( szProgramFilesFolder )) 228 { 229 size_t nLen = _tcslen( szProgramFilesFolder ); 230 if ( nLen > 0 ) 231 { 232 _tcscpy( szExecutablePath, szProgramFilesFolder ); 233 if ( szProgramFilesFolder[nLen-1] != '\\' ) 234 _tcscat( szExecutablePath, TEXT( "\\" )); 235 _tcscat( szExecutablePath, TEXT( "Sun\\servicetag\\" )); 236 _tcscat( szExecutablePath, g_szSTExecutable ); 237 eRet = FileExists( szExecutablePath ) ? PATHRESULT_OK : PATHRESULT_EXE_NOT_FOUND; 238 } 239 } 240 241 return eRet; 242 } 243 244 //*************************************************************************** 245 246 static void SafeCopy( LPTSTR lpTarget, LPCSTR lpSource, size_t nMaxLen ) 247 { 248 size_t nLen = _tcslen( lpSource ); 249 size_t nCopy = ( nLen < size_t( nMaxLen-1 )) ? nLen : nMaxLen-1; 250 _tcsncpy( lpTarget, lpSource, nMaxLen-1 ); 251 *(lpTarget+nCopy) = 0; 252 } 253 254 //*************************************************************************** 255 256 int WINAPI _tWinMain( HINSTANCE /*hInstance*/, HINSTANCE, LPTSTR, int ) 257 { 258 const DWORD ERR_NO_RECORDS_FOUND = 225; 259 const DWORD ERR_DUP_RECORD = 226; 260 261 DWORD dwExitCode = (DWORD)1; 262 263 int nArgs = 0; 264 LPTSTR* lpArgs = GetCommandArgs( &nArgs ); 265 266 if ( !IsSupportedPlatform() ) 267 { 268 // Return 0 for a successful run on not supported platforms 269 // We don't want that the Office tries to start us forever. 270 return 0; 271 } 272 273 if ( nArgs >= 11 ) 274 { 275 TCHAR szTargetURN[1024] = {0}; 276 TCHAR szProductName[1024] = {0}; 277 TCHAR szProductVersion[1024] = {0}; 278 TCHAR szParentProductName[1024] = {0}; 279 TCHAR szProductSource[1024] = {0}; 280 TCHAR szInstanceURN[1024] = {0}; 281 282 // -i) INSTANCE_URN="$2"; shift;; 283 // -t) TARGET_URN="$2"; shift;; 284 // -p) PRODUCT_NAME="$2"; shift;; 285 // -e) PRODUCT_VERSION="$2"; shift;; 286 // -P) PARENT_PRODUCT_NAME="$2"; shift;; 287 // -S) PRODUCT_SOURCE="$2"; shift;; 288 // "usage: $0 [-i <instance urn>] -p <product name> -e <product version> -t <urn> -S <source> -P <parent product name>" 289 290 int i = 1; 291 while ( i < nArgs ) 292 { 293 LPTSTR lpArg = lpArgs[i]; 294 if ( _tcslen( lpArg ) >= 2 ) 295 { 296 if ( lpArg[0] == '-' ) 297 { 298 switch ( lpArg[1] ) 299 { 300 case 'i': 301 { 302 if ( i < nArgs ) 303 ++i; 304 SafeCopy( szInstanceURN, lpArgs[i], elementsof( szInstanceURN )); 305 break; 306 } 307 308 case 't': 309 { 310 if ( i < nArgs ) 311 ++i; 312 SafeCopy( szTargetURN, lpArgs[i], elementsof( szTargetURN )); 313 break; 314 } 315 case 'p': 316 { 317 if ( i < nArgs ) 318 ++i; 319 SafeCopy( szProductName, lpArgs[i], elementsof( szProductName )); 320 break; 321 } 322 case 'e': 323 { 324 if ( i < nArgs ) 325 ++i; 326 SafeCopy( szProductVersion, lpArgs[i], elementsof( szProductVersion )); 327 break; 328 } 329 case 'P': 330 { 331 if ( i < nArgs ) 332 ++i; 333 SafeCopy( szParentProductName, lpArgs[i], elementsof( szParentProductName )); 334 break; 335 } 336 case 'S': 337 { 338 if ( i < nArgs ) 339 ++i; 340 SafeCopy( szProductSource, lpArgs[i], elementsof( szProductSource )); 341 break; 342 } 343 344 default: 345 break; 346 } // switch 347 } 348 } 349 350 ++i; 351 } 352 353 if ( RetrieveExecutablePath( g_szSTInstallationPath ) == PATHRESULT_OK ) 354 { 355 BOOL bSuccess = TRUE; 356 BOOL bProcessStarted = FALSE; 357 358 STARTUPINFO aStartupInfo; 359 PROCESS_INFORMATION aProcessInfo; 360 LPTSTR lpCommandLine = 0; 361 362 ZeroMemory( &aStartupInfo, sizeof( aStartupInfo )); 363 aStartupInfo.cb = sizeof( aStartupInfo ); 364 ZeroMemory( &aProcessInfo, sizeof( aProcessInfo )); 365 366 if ( _tcslen( szInstanceURN ) == 0 ) 367 { 368 // TEST=`${STCLIENT} -f -t ${TARGET_URN}` 369 lpCommandLine = new TCHAR[MAXCMDLINELEN]; 370 371 _tcscpy( lpCommandLine, TEXT( "\"" )); 372 _tcscat( lpCommandLine, g_szSTInstallationPath ); 373 _tcscat( lpCommandLine, TEXT( "\"" )); 374 _tcscat( lpCommandLine, TEXT( " -f" )); 375 _tcscat( lpCommandLine, TEXT( " -t ")); 376 _tcscat( lpCommandLine, TEXT( "\"" )); 377 _tcscat( lpCommandLine, szTargetURN ); 378 _tcscat( lpCommandLine, TEXT( "\"" )); 379 380 bSuccess = CreateProcess( 381 NULL, 382 lpCommandLine, 383 NULL, 384 NULL, 385 TRUE, 386 CREATE_NO_WINDOW, 387 NULL, 388 NULL, 389 &aStartupInfo, 390 &aProcessInfo ); 391 392 bProcessStarted = TRUE; 393 394 // wait until process ends to receive exit code 395 WaitForSingleObject( aProcessInfo.hProcess, INFINITE ); 396 397 delete []lpCommandLine; 398 } 399 400 if ( bSuccess ) 401 { 402 DWORD dwSTClientExitCode( ERR_NO_RECORDS_FOUND ); 403 if ( bProcessStarted ) 404 { 405 GetExitCodeProcess( aProcessInfo.hProcess, &dwSTClientExitCode ); 406 dwSTClientExitCode &= 0x000000ff; 407 408 CloseHandle( aProcessInfo.hProcess ); 409 CloseHandle( aProcessInfo.hThread ); 410 } 411 412 if ( dwSTClientExitCode == ERR_NO_RECORDS_FOUND ) 413 { 414 // output=`${STCLIENT} -a [-i "${INSTANCE_URN}"] -p "${PRODUCT_NAME}" -e "${PRODUCT_VERSION}" -t "${TARGET_URN}" -S "${PRODUCT_SOURCE}" -P "${PARENT_PRODUCT_NAME}" -m "Sun Microsystems, Inc." -A ${uname} -z global` 415 lpCommandLine = new TCHAR[MAXCMDLINELEN]; 416 417 _tcscpy( lpCommandLine, TEXT( "\"" )); 418 _tcscat( lpCommandLine, g_szSTInstallationPath ); 419 _tcscat( lpCommandLine, TEXT( "\"" )); 420 _tcscat( lpCommandLine, TEXT( " -a" )); 421 if ( _tcslen( szInstanceURN ) > 0 ) 422 { 423 _tcscat( lpCommandLine, TEXT( " -i " )); 424 _tcscat( lpCommandLine, TEXT( "\"" )); 425 _tcscat( lpCommandLine, szInstanceURN ); 426 _tcscat( lpCommandLine, TEXT( "\"" )); 427 } 428 _tcscat( lpCommandLine, TEXT( " -p " )); 429 _tcscat( lpCommandLine, TEXT( "\"" )); 430 _tcscat( lpCommandLine, szProductName ); 431 _tcscat( lpCommandLine, TEXT( "\"" )); 432 _tcscat( lpCommandLine, TEXT( " -e " )); 433 _tcscat( lpCommandLine, TEXT( "\"" )); 434 _tcscat( lpCommandLine, szProductVersion ); 435 _tcscat( lpCommandLine, TEXT( "\"" )); 436 _tcscat( lpCommandLine, TEXT( " -t " )); 437 _tcscat( lpCommandLine, TEXT( "\"" )); 438 _tcscat( lpCommandLine, szTargetURN ); 439 _tcscat( lpCommandLine, TEXT( "\"" )); 440 _tcscat( lpCommandLine, TEXT( " -S " )); 441 _tcscat( lpCommandLine, TEXT( "\"" )); 442 _tcscat( lpCommandLine, szProductSource ); 443 _tcscat( lpCommandLine, TEXT( "\"" )); 444 _tcscat( lpCommandLine, TEXT( " -P " )); 445 _tcscat( lpCommandLine, TEXT( "\"" )); 446 _tcscat( lpCommandLine, szParentProductName ); 447 _tcscat( lpCommandLine, TEXT( "\"" )); 448 _tcscat( lpCommandLine, TEXT( " -m \"Sun Microsystems, Inc.\"" )); 449 _tcscat( lpCommandLine, TEXT( " -A " )); 450 _tcscat( lpCommandLine, TEXT( "\"" )); 451 _tcscat( lpCommandLine, GetOperatingSystemString() ); 452 _tcscat( lpCommandLine, TEXT( "\"" )); 453 _tcscat( lpCommandLine, TEXT( " -z global" )); 454 455 ZeroMemory( &aStartupInfo, sizeof( aStartupInfo )); 456 aStartupInfo.cb = sizeof(aStartupInfo); 457 ZeroMemory( &aProcessInfo, sizeof( aProcessInfo )); 458 459 bSuccess = CreateProcess( 460 NULL, 461 lpCommandLine, 462 NULL, 463 NULL, 464 TRUE, 465 CREATE_NO_WINDOW, 466 NULL, 467 NULL, 468 &aStartupInfo, 469 &aProcessInfo ); 470 471 delete []lpCommandLine; 472 473 // wait until process ends to receive exit code 474 WaitForSingleObject( aProcessInfo.hProcess, INFINITE ); 475 476 dwSTClientExitCode = 0; 477 GetExitCodeProcess( aProcessInfo.hProcess, &dwSTClientExitCode ); 478 dwSTClientExitCode &= 0x000000ff; 479 480 CloseHandle( aProcessInfo.hProcess ); 481 CloseHandle( aProcessInfo.hThread ); 482 483 if ( !bSuccess ) 484 dwExitCode = 1; // couldn't start stclient process 485 else 486 { 487 if ( _tcslen( szInstanceURN ) > 0 ) 488 { 489 // don't register again if we registered in a previous run 490 // or we called stclient successfully. 491 if (( dwSTClientExitCode == ERR_DUP_RECORD ) || 492 ( dwSTClientExitCode == 0 )) 493 dwExitCode = 0; 494 else 495 dwExitCode = 1; // other errors 496 } 497 else 498 dwExitCode = ( dwSTClientExitCode == 0 ) ? 0 : 1; 499 } 500 } 501 else if ( dwSTClientExitCode == 0 ) 502 dwExitCode = 0; // already registered 503 else 504 dwExitCode = 1; // other errors 505 } 506 else 507 dwExitCode = 1; // couldn't start stclient 508 } 509 else 510 dwExitCode = 1; // no executable found 511 } 512 else 513 dwExitCode = 0; // wrong number of arguments 514 515 return dwExitCode; 516 } 517