721 lines
20 KiB
C
721 lines
20 KiB
C
|
|
||
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#include "tchar.h"
|
||
|
#include "shlwapi.h"
|
||
|
|
||
|
|
||
|
LPTSTR pszTitle = _T("Microsoft Debugging Tools");
|
||
|
|
||
|
#define MSI_BUILD_VER_X86 1029 // Latest MSI version for Win2K x86
|
||
|
#define WIN2K_MIN_BUILD_X86 2183 // Win2K RC3
|
||
|
|
||
|
typedef struct _CommandArgs {
|
||
|
BOOL QuietInstall;
|
||
|
BOOL StressInstall;
|
||
|
BOOL UIStressInstall;
|
||
|
TCHAR szInstDir[ _MAX_PATH*sizeof(TCHAR) ];
|
||
|
TCHAR szMsiName[ _MAX_PATH*sizeof(TCHAR) ];
|
||
|
TCHAR szProductRegKey[ _MAX_PATH*sizeof(TCHAR) ];
|
||
|
} COMMAND_ARGS, *PCOMMAND_ARGS;
|
||
|
|
||
|
|
||
|
// Function prototypes
|
||
|
|
||
|
BOOL
|
||
|
RunCommand(
|
||
|
PTCHAR szCommandLine,
|
||
|
HINSTANCE hInst
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
GetCommandLineArgs(
|
||
|
LPTSTR szCmdLine,
|
||
|
PCOMMAND_ARGS pComArgs
|
||
|
);
|
||
|
|
||
|
|
||
|
TCHAR szMSIInstFile[_MAX_PATH*sizeof(TCHAR)];
|
||
|
TCHAR szPkgInstFile[_MAX_PATH*sizeof(TCHAR)];
|
||
|
TCHAR szPkgInstCommand[_MAX_PATH*2*sizeof(TCHAR)];
|
||
|
|
||
|
|
||
|
// For stress installs, this command will be used to
|
||
|
// remove the current package but don't remove its
|
||
|
// files, if the current package with the same
|
||
|
// product ID is already installed.
|
||
|
|
||
|
TCHAR szPkgRemoveCommand[_MAX_PATH*2*sizeof(TCHAR)];
|
||
|
TCHAR szPkgRemoveCommand2[_MAX_PATH*2*sizeof(TCHAR)];
|
||
|
|
||
|
// If the first install fails, stress tries again without
|
||
|
// the quiet switch before giving a pop-up
|
||
|
TCHAR szPkgInstCommandNoQuiet[_MAX_PATH*2*sizeof(TCHAR)];
|
||
|
|
||
|
TCHAR szCommandFullPath[_MAX_PATH*sizeof(TCHAR)];
|
||
|
|
||
|
|
||
|
int WINAPI WinMain(
|
||
|
HINSTANCE hInstance,
|
||
|
HINSTANCE hPrevInstance,
|
||
|
LPTSTR lpszCmdLine,
|
||
|
int nCmdShow
|
||
|
)
|
||
|
|
||
|
{
|
||
|
OSVERSIONINFO VersionInfo;
|
||
|
SYSTEM_INFO SystemInfo;
|
||
|
BOOL rc;
|
||
|
BOOL MSIIsInstalled;
|
||
|
PTCHAR ch;
|
||
|
TCHAR szBuf[1000];
|
||
|
TCHAR szSystemDirectory[_MAX_PATH];
|
||
|
|
||
|
COMMAND_ARGS ComArgs;
|
||
|
HKEY hKey;
|
||
|
DWORD dwrc;
|
||
|
DWORD dwSizeValue;
|
||
|
DWORD dwType;
|
||
|
|
||
|
HANDLE hFile;
|
||
|
WIN32_FIND_DATA FindFileData;
|
||
|
|
||
|
MSIIsInstalled=FALSE;
|
||
|
|
||
|
// Get this info for later use
|
||
|
VersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
|
||
|
GetVersionEx( &VersionInfo );
|
||
|
GetSystemInfo( &SystemInfo );
|
||
|
|
||
|
// Parse through the command line for the various arguments
|
||
|
|
||
|
rc = GetCommandLineArgs(lpszCmdLine, &ComArgs );
|
||
|
|
||
|
if (!rc) {
|
||
|
_stprintf( szBuf, _T("%s%s%s%s%s"),
|
||
|
_T(" Usage: \n\n"),
|
||
|
_T(" setup.exe [ /q [ /i <InstDir> ] ]\n\n"),
|
||
|
_T(" /q\tGive pop-ups only for errors\n\n"),
|
||
|
_T(" /i\tInstall to <Instdir>\n\n"),
|
||
|
_T(" /n\tInstall <msi package Name>\n\n")
|
||
|
);
|
||
|
MessageBox( NULL, szBuf, pszTitle, 0 );
|
||
|
return (1);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Set the full path to this setup.exe
|
||
|
//
|
||
|
|
||
|
if (GetModuleFileName( NULL, szCommandFullPath, MAX_PATH ) == 0) {
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
// Put an end of string after the directory that this was
|
||
|
// started from
|
||
|
|
||
|
ch = szCommandFullPath + _tcslen(szCommandFullPath);
|
||
|
while ( *ch != _T('\\') && ( ch > szCommandFullPath ) ) ch--;
|
||
|
*ch=_T('\0');
|
||
|
|
||
|
// This will become the full path and name of the MSI file to install
|
||
|
_tcscpy( szMSIInstFile, szCommandFullPath);
|
||
|
|
||
|
// Set the full path and name of the msi package
|
||
|
_tcscpy( szPkgInstFile, szCommandFullPath);
|
||
|
_tcscat( szPkgInstFile, _T("\\") );
|
||
|
_tcscat( szPkgInstFile, ComArgs.szMsiName );
|
||
|
|
||
|
// See if the package exists
|
||
|
hFile = FindFirstFile( szPkgInstFile, &FindFileData );
|
||
|
if ( hFile == INVALID_HANDLE_VALUE ) {
|
||
|
|
||
|
_stprintf( szBuf, _T("%s%s%s%s"),
|
||
|
_T("The Microsoft Debugging Tools package "),
|
||
|
szPkgInstFile,
|
||
|
_T(" does not exist.\n\nSetup cannot contine"),
|
||
|
_T(" for this platform.")
|
||
|
);
|
||
|
MessageBox(NULL, szBuf, pszTitle, 0);
|
||
|
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
FindClose(hFile);
|
||
|
|
||
|
// Set the command for installing the package
|
||
|
_tcscpy( szPkgInstCommand, _T("msiexec /i ") );
|
||
|
_tcscat( szPkgInstCommand, szPkgInstFile );
|
||
|
|
||
|
// Set the command for removing the current package
|
||
|
// that is installed.
|
||
|
|
||
|
_tcscpy( szBuf, _T("") );
|
||
|
dwrc = RegOpenKeyEx( HKEY_CURRENT_USER,
|
||
|
ComArgs.szProductRegKey,
|
||
|
0,
|
||
|
KEY_QUERY_VALUE,
|
||
|
&hKey
|
||
|
);
|
||
|
|
||
|
if ( dwrc == ERROR_SUCCESS ) {
|
||
|
|
||
|
_tcscpy( szBuf, _T("") );
|
||
|
dwSizeValue=sizeof(szBuf);
|
||
|
RegQueryValueEx ( hKey,
|
||
|
_T("ProductCode"),
|
||
|
0,
|
||
|
&dwType,
|
||
|
(PBYTE)szBuf,
|
||
|
&dwSizeValue
|
||
|
);
|
||
|
|
||
|
RegCloseKey(hKey);
|
||
|
}
|
||
|
|
||
|
// Set the command to remove the current package
|
||
|
// that has an Add/Remove link in the start menu
|
||
|
_tcscpy(szPkgRemoveCommand2, _T("") );
|
||
|
if ( _tcslen(szBuf) > 0 ) {
|
||
|
_tcscpy(szPkgRemoveCommand2, _T("msiexec /x ") );
|
||
|
_tcscat(szPkgRemoveCommand2, szBuf);
|
||
|
_tcscat(szPkgRemoveCommand2, _T(" REMOVETHEFILES=0 /qn") );
|
||
|
}
|
||
|
|
||
|
// Set the command to remove the current package so that
|
||
|
// this program works like it used to.
|
||
|
_tcscpy(szPkgRemoveCommand, _T("msiexec /x ") );
|
||
|
_tcscat(szPkgRemoveCommand, szPkgInstFile );
|
||
|
_tcscat(szPkgRemoveCommand, _T(" REMOVETHEFILES=0 /qn") );
|
||
|
|
||
|
// Add a user override installation directory
|
||
|
if ( _tcslen(ComArgs.szInstDir) > 0 ) {
|
||
|
_tcscat( szPkgInstCommand, _T(" INSTDIR=") );
|
||
|
_tcscat( szPkgInstCommand, ComArgs.szInstDir );
|
||
|
} else if ( ComArgs.UIStressInstall ) {
|
||
|
GetSystemDirectory( szSystemDirectory, _MAX_PATH );
|
||
|
_tcscat( szPkgInstCommand, _T(" INSTDIR=") );
|
||
|
_tcscat( szPkgInstCommand, szSystemDirectory );
|
||
|
}
|
||
|
|
||
|
// If this is an "undocumented" stress install
|
||
|
// don't remove the files of the previous install
|
||
|
// when you upgrade
|
||
|
// FEATURESTOREMOVE should never actually need to be used, unless
|
||
|
// the user has something screwed up on his system where the registry
|
||
|
// key and products installed don't agree, or MSI thinks there's more
|
||
|
// products installed than the registry key we look at.
|
||
|
|
||
|
if ( ComArgs.StressInstall ) {
|
||
|
_tcscat( szPkgInstCommand, _T(" FEATURESTOREMOVE=\"\"") );
|
||
|
}
|
||
|
|
||
|
// If this is an "undocumented" UI stress install
|
||
|
// only install the private extensions
|
||
|
if ( ComArgs.UIStressInstall ) {
|
||
|
_tcscat( szPkgInstCommand,
|
||
|
_T(" ADDLOCAL=DBG.DbgExts.Internal,DBG.NtsdFix.Internal") );
|
||
|
}
|
||
|
|
||
|
// Add the quiet switch
|
||
|
// Save the command without a quiet switch
|
||
|
_tcscpy( szPkgInstCommandNoQuiet, szPkgInstCommand);
|
||
|
if ( ComArgs.QuietInstall ) {
|
||
|
_tcscat( szPkgInstCommand, _T(" /qn") );
|
||
|
}
|
||
|
|
||
|
// Do version checks for whether msi is already installed
|
||
|
//
|
||
|
// If this is Windows 2000 and build number is >=
|
||
|
// WIN2K_MIN_BUILD_X86 then MSI is installed
|
||
|
// Don't try to run instmsi.exe on Windows 2000 because
|
||
|
// you will get file system protection pop-ups.
|
||
|
//
|
||
|
|
||
|
if ( (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
|
||
|
(VersionInfo.dwMajorVersion >= 5.0 ) ) {
|
||
|
|
||
|
switch (SystemInfo.wProcessorArchitecture) {
|
||
|
|
||
|
case PROCESSOR_ARCHITECTURE_INTEL:
|
||
|
|
||
|
if (VersionInfo.dwBuildNumber < WIN2K_MIN_BUILD_X86 ) {
|
||
|
|
||
|
// The version of MSI that is on early builds of Windows
|
||
|
// 2000 shouldn't be trusted for installs.
|
||
|
|
||
|
MessageBox(NULL,
|
||
|
_T("The Debugging Tools does not install on ")
|
||
|
_T("this version of Windows 2000. Please upgrade ")
|
||
|
_T("your system to a retail version of Windows ")
|
||
|
_T("2000 before trying to install this package."),
|
||
|
pszTitle,
|
||
|
0);
|
||
|
return(1);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case PROCESSOR_ARCHITECTURE_AMD64:
|
||
|
case PROCESSOR_ARCHITECTURE_IA64:
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
|
||
|
MessageBox(NULL, _T("Unknown computer architecture."), pszTitle ,0);
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
MSIIsInstalled = TRUE;
|
||
|
|
||
|
} else if ( SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) {
|
||
|
|
||
|
//
|
||
|
// For Intel OS's prior to Windows 2000, run instmsi.exe
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// NT4 X86
|
||
|
//
|
||
|
if ( VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ) {
|
||
|
_tcscat( szMSIInstFile,
|
||
|
_T("\\setup\\winnt\\i386\\instmsi.exe /q") );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Win9x
|
||
|
//
|
||
|
else if ( VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) {
|
||
|
_tcscat( szMSIInstFile,
|
||
|
_T("\\setup\\win9x\\instmsi.exe /q") );
|
||
|
} else {
|
||
|
|
||
|
MessageBox(NULL,
|
||
|
_T("The Microsoft Debugging Tools does not install")
|
||
|
_T(" on this system."),
|
||
|
pszTitle,
|
||
|
0);
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
MessageBox(NULL,
|
||
|
_T("The Microsoft Debugging Tools cannot be installed")
|
||
|
_T(" on this system."),
|
||
|
pszTitle,
|
||
|
0);
|
||
|
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
|
||
|
// Install MSI if it is not already installed
|
||
|
|
||
|
if ( !MSIIsInstalled ) {
|
||
|
|
||
|
if ( RunCommand( szMSIInstFile, hInstance ) ) {
|
||
|
MSIIsInstalled = TRUE;
|
||
|
}
|
||
|
if (!MSIIsInstalled) {
|
||
|
|
||
|
MessageBox(NULL,
|
||
|
_T("The Windows Installer could not be installed on ")
|
||
|
_T("this system. This is required before installing")
|
||
|
_T(" the Microsoft Debugging Tools package. Try ")
|
||
|
_T("logging in as an administrator and try again."),
|
||
|
pszTitle,
|
||
|
0);
|
||
|
return(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now, if this is a stress install,
|
||
|
// Try to remove the current package in case it is installed
|
||
|
//
|
||
|
|
||
|
if ( ComArgs.StressInstall ) {
|
||
|
if ( _tcslen(szPkgRemoveCommand2) > 0 ) {
|
||
|
RunCommand( szPkgRemoveCommand2, hInstance);
|
||
|
}
|
||
|
RunCommand( szPkgRemoveCommand, hInstance );
|
||
|
if ( !RunCommand( szPkgInstCommand, hInstance ) ) {
|
||
|
|
||
|
// Try again without the quiet switch, so that the user will get
|
||
|
// a pop-up from dbg.msi and quit calling us
|
||
|
|
||
|
MessageBox(NULL,
|
||
|
_T("There were errors when trying to install the ")
|
||
|
_T("debuggers.\nClick OK to attempt an install of the")
|
||
|
_T(" debuggers with\n the GUI and you will see the")
|
||
|
_T(" correct error message."),
|
||
|
pszTitle,
|
||
|
0);
|
||
|
|
||
|
if ( !RunCommand( szPkgInstCommandNoQuiet, hInstance ) ) {
|
||
|
MessageBox(NULL,
|
||
|
_T("There were still errors in the install.\n")
|
||
|
_T("Please see http://dbg/top10.html ")
|
||
|
_T("for more help."),
|
||
|
pszTitle,
|
||
|
0);
|
||
|
return(1);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now, install the package dbg.msi
|
||
|
//
|
||
|
|
||
|
if ( !RunCommand( szPkgInstCommand, hInstance ) ) {
|
||
|
if (ComArgs.QuietInstall) {
|
||
|
_stprintf( szBuf, _T("%s %s %s %s"),
|
||
|
_T("There were errors in the Debugging Tools install."),
|
||
|
_T(" Please run "),
|
||
|
szPkgInstFile,
|
||
|
_T("to receive more detailed error information.")
|
||
|
);
|
||
|
MessageBox( NULL, szBuf, pszTitle,0);
|
||
|
}
|
||
|
return(1);
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
return(0);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// RunCommand
|
||
|
//
|
||
|
// Purpose: Install MSI
|
||
|
//
|
||
|
// Return Values:
|
||
|
// 0 error
|
||
|
// 1 successful
|
||
|
|
||
|
BOOL
|
||
|
RunCommand( PTCHAR szCommandLine,
|
||
|
HINSTANCE hInst)
|
||
|
{
|
||
|
BOOL rc;
|
||
|
DWORD dwRet;
|
||
|
PROCESS_INFORMATION ProcInfo = {0};
|
||
|
STARTUPINFO SI= {0};
|
||
|
|
||
|
|
||
|
// Spawn the command line specified by szCommandLine
|
||
|
rc = CreateProcess(NULL,
|
||
|
szCommandLine,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
FALSE,
|
||
|
CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&SI,
|
||
|
&ProcInfo );
|
||
|
|
||
|
if ( (!rc) || (!ProcInfo.hProcess) ) {
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Wait for command to complete ... Give it 20 minutes
|
||
|
//
|
||
|
|
||
|
dwRet = WaitForSingleObject(ProcInfo.hProcess, 1200000);
|
||
|
|
||
|
if (dwRet != WAIT_OBJECT_0) {
|
||
|
rc = FALSE;
|
||
|
goto cleanup;
|
||
|
|
||
|
}
|
||
|
|
||
|
// Get the process exit code
|
||
|
|
||
|
rc = GetExitCodeProcess( ProcInfo.hProcess, &dwRet);
|
||
|
|
||
|
if (dwRet == ERROR_SUCCESS ) {
|
||
|
rc = 1;
|
||
|
} else {
|
||
|
rc = 0;
|
||
|
}
|
||
|
|
||
|
cleanup:
|
||
|
|
||
|
if (ProcInfo.hProcess)
|
||
|
CloseHandle(ProcInfo.hProcess);
|
||
|
|
||
|
return (rc);
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
GetCommandLineArgs(
|
||
|
LPTSTR szCmdLine,
|
||
|
PCOMMAND_ARGS pComArgs
|
||
|
)
|
||
|
{
|
||
|
|
||
|
ULONG length;
|
||
|
ULONG i,cur;
|
||
|
BOOL SkippingSpaces=FALSE;
|
||
|
BOOL QuotedString=FALSE;
|
||
|
BOOL NeedSecond=FALSE;
|
||
|
BOOL rc=TRUE;
|
||
|
LPTSTR *argv;
|
||
|
ULONG argc=0;
|
||
|
LPTSTR szCmdLineTmp;
|
||
|
TCHAR c;
|
||
|
|
||
|
ZeroMemory(pComArgs, sizeof(COMMAND_ARGS));
|
||
|
|
||
|
|
||
|
// Create a line to use for temporary marking
|
||
|
length=_tcslen(szCmdLine);
|
||
|
|
||
|
szCmdLineTmp= (LPTSTR)malloc( (_tcslen(szCmdLine) + 1) * sizeof(TCHAR) );
|
||
|
if (szCmdLineTmp==NULL)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
_tcscpy(szCmdLineTmp, szCmdLine);
|
||
|
|
||
|
// Count the number of arguments
|
||
|
// Create a argv and argc
|
||
|
|
||
|
SkippingSpaces=TRUE;
|
||
|
QuotedString=FALSE;
|
||
|
argc=0;
|
||
|
for ( i=0; i<length; i++ )
|
||
|
{
|
||
|
c=szCmdLineTmp[i];
|
||
|
switch (szCmdLineTmp[i]) {
|
||
|
case _T(' '):
|
||
|
case _T('\t'): if (QuotedString)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
if (!SkippingSpaces)
|
||
|
{
|
||
|
SkippingSpaces=TRUE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case _T('\"'): if (QuotedString)
|
||
|
{
|
||
|
// This is the end of a quoted string
|
||
|
// The next character to read in is a space
|
||
|
QuotedString=FALSE;
|
||
|
SkippingSpaces=TRUE;
|
||
|
if ( i < (length-1) &&
|
||
|
szCmdLineTmp[i+1] != _T(' ') &&
|
||
|
szCmdLineTmp[i+1] != _T('\t') )
|
||
|
{
|
||
|
// This is the end of a quote and its not
|
||
|
// followed by a space
|
||
|
rc=FALSE;
|
||
|
goto CommandLineFinish;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (SkippingSpaces) {
|
||
|
|
||
|
// This is the beginning of a quoted string
|
||
|
// Its a new argument and it follows spaces
|
||
|
argc++;
|
||
|
SkippingSpaces=FALSE;
|
||
|
QuotedString=TRUE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// This is an error -- This is a quote in the middle of a string
|
||
|
rc=FALSE;
|
||
|
goto CommandLineFinish;
|
||
|
break;
|
||
|
|
||
|
default: if (QuotedString) {
|
||
|
break;
|
||
|
}
|
||
|
if (SkippingSpaces) {
|
||
|
argc++;
|
||
|
SkippingSpaces=FALSE;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (QuotedString)
|
||
|
{
|
||
|
// Make sure that all the quotes got a finished pair
|
||
|
rc=FALSE;
|
||
|
goto CommandLineFinish;
|
||
|
}
|
||
|
|
||
|
// Now, create argv with the correct number of entries
|
||
|
|
||
|
argv=(LPTSTR*)malloc(argc * sizeof(LPTSTR) );
|
||
|
if (argv==NULL)
|
||
|
{
|
||
|
free(szCmdLineTmp);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Set argv to point to the correct place on szCmdLineTmp
|
||
|
// and put '\0' after each token.
|
||
|
|
||
|
SkippingSpaces=TRUE;
|
||
|
QuotedString=FALSE;
|
||
|
argc=0;
|
||
|
for ( i=0; i<length; i++ )
|
||
|
{
|
||
|
c=szCmdLineTmp[i];
|
||
|
switch (szCmdLineTmp[i]) {
|
||
|
case _T(' '):
|
||
|
case _T('\t'): if (QuotedString)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
if (!SkippingSpaces)
|
||
|
{
|
||
|
szCmdLineTmp[i]='\0';
|
||
|
SkippingSpaces=TRUE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case _T('\"'): if (QuotedString)
|
||
|
{
|
||
|
// This is the end of a quoted string
|
||
|
// The next character to read in is a space
|
||
|
QuotedString=FALSE;
|
||
|
SkippingSpaces=TRUE;
|
||
|
szCmdLineTmp[i+1]=_T('\0');
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (SkippingSpaces) {
|
||
|
|
||
|
// This is the beginning of a quoted string
|
||
|
// Its a new argument and it follows spaces
|
||
|
|
||
|
argv[argc]=szCmdLineTmp+i;
|
||
|
argc++;
|
||
|
SkippingSpaces=FALSE;
|
||
|
QuotedString=TRUE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// This is an error -- This is a quote in the middle of a string
|
||
|
rc=FALSE;
|
||
|
goto CommandLineFinish;
|
||
|
break;
|
||
|
|
||
|
|
||
|
|
||
|
default: if (QuotedString)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
if (SkippingSpaces) {
|
||
|
argv[argc]=szCmdLineTmp+i;
|
||
|
argc++;
|
||
|
SkippingSpaces=FALSE;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Now, parse the arguments
|
||
|
|
||
|
NeedSecond=FALSE;
|
||
|
|
||
|
for (i=0; i<argc; i++) {
|
||
|
|
||
|
if (!NeedSecond)
|
||
|
{
|
||
|
if ( (argv[i][0] != '/') && (argv[i][0] != '-') )
|
||
|
{
|
||
|
rc=FALSE;
|
||
|
goto CommandLineFinish;
|
||
|
}
|
||
|
|
||
|
if ( _tcslen(argv[i]) != 2 )
|
||
|
{
|
||
|
rc=FALSE;
|
||
|
goto CommandLineFinish;
|
||
|
}
|
||
|
|
||
|
c=argv[i][1];
|
||
|
switch ( c )
|
||
|
{
|
||
|
case 'q':
|
||
|
case 'Q': pComArgs->QuietInstall=TRUE;
|
||
|
break;
|
||
|
case 'i':
|
||
|
case 'I': NeedSecond=TRUE;;
|
||
|
break;
|
||
|
case 'n':
|
||
|
case 'N': NeedSecond=TRUE;
|
||
|
break;
|
||
|
case 'z':
|
||
|
case 'Z': pComArgs->StressInstall=TRUE;
|
||
|
break;
|
||
|
case 'u':
|
||
|
case 'U': pComArgs->UIStressInstall=TRUE;
|
||
|
pComArgs->StressInstall=TRUE;
|
||
|
break;
|
||
|
default: {
|
||
|
rc=FALSE;
|
||
|
goto CommandLineFinish;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
|
||
|
NeedSecond = FALSE;
|
||
|
switch ( c )
|
||
|
{
|
||
|
case 'i':
|
||
|
case 'I': _tcscpy(pComArgs->szInstDir,argv[i]);
|
||
|
break;
|
||
|
case 'n':
|
||
|
case 'N': _tcscpy(pComArgs->szMsiName,argv[i]);
|
||
|
break;
|
||
|
default: {
|
||
|
rc=FALSE;
|
||
|
goto CommandLineFinish;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if (pComArgs->szMsiName[0] == 0)
|
||
|
{
|
||
|
#ifdef BUILD_X86
|
||
|
_tcscpy(pComArgs->szMsiName, _T("dbg_x86.msi") );
|
||
|
_tcscpy(pComArgs->szProductRegKey, _T("Software\\Microsoft\\DebuggingTools\\AddRemove") );
|
||
|
#elif defined(BUILD_IA64)
|
||
|
_tcscpy(pComArgs->szMsiName, _T("dbg_ia64.msi") );
|
||
|
_tcscpy(pComArgs->szProductRegKey, _T("Software\\Microsoft\\DebuggingTools64\\AddRemove") );
|
||
|
#elif defined(BUILD_AMD64)
|
||
|
_tcscpy(pComArgs->szMsiName, _T("dbg_amd64.msi") );
|
||
|
_tcscpy(pComArgs->szProductRegKey, _T("Software\\Microsoft\\DebuggingTools64\\AddRemove") );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
CommandLineFinish:
|
||
|
|
||
|
free(szCmdLineTmp);
|
||
|
free(argv);
|
||
|
|
||
|
return (rc);
|
||
|
|
||
|
}
|