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
RegReadValue(HKEY hBaseKey,LPCTSTR lpSubKey,LPCTSTR lpValueName,LPVOID lpData,DWORD cbData)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
GetCommandArgs(int * pArgc)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
IsSupportedPlatform()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
GetOperatingSystemString()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
FileExists(LPCTSTR lpPathToFile)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
GetProgramFilesFolder(LPTSTR strPath)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
RetrieveExecutablePath(LPTSTR szExecutablePath)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
SafeCopy(LPTSTR lpTarget,LPCSTR lpSource,size_t nMaxLen)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
_tWinMain(HINSTANCE,HINSTANCE,LPTSTR,int)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