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