377 lines
9.3 KiB
C
377 lines
9.3 KiB
C
|
|
/****************************************************************************\
|
|
|
|
MAIN.C / Mass Storage Device Installer Tool (MSDINST.EXE)
|
|
|
|
Microsoft Confidential
|
|
Copyright (c) Microsoft Corporation 2001
|
|
All rights reserved
|
|
|
|
Main source file for the MSD Installation stand alone tool.
|
|
|
|
07/2001 - Jason Cohen (JCOHEN)
|
|
|
|
Added this new source file for the new MSD Isntallation project.
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
//
|
|
// Include File(s):
|
|
//
|
|
|
|
#include "pch.h"
|
|
#include "res.h"
|
|
#include <winbom.h>
|
|
#include <msdinst.h>
|
|
#include <spapip.h>
|
|
|
|
//
|
|
// Local Define(s):
|
|
//
|
|
|
|
#define REG_KEY_WINPE _T("SYSTEM\\CurrentControlSet\\Control\\MiniNT")
|
|
#define STR_MUTEX_MSDINST _T("{97e6e509-16e5-40b8-91fd-c767306853a9}")
|
|
|
|
//
|
|
// Local Type Definition(s):
|
|
//
|
|
typedef struct _GAPP
|
|
{
|
|
TCHAR szInfPath[MAX_PATH];
|
|
TCHAR szWinDir[MAX_PATH];
|
|
}
|
|
GAPP, *LPGAPP;
|
|
|
|
//
|
|
// Internal Global Variable(s):
|
|
//
|
|
GAPP g_App = {0};
|
|
|
|
//
|
|
// Local Prototype(s):
|
|
//
|
|
|
|
static BOOL
|
|
ParseCmdLine(
|
|
LPGAPP lpgApp
|
|
);
|
|
|
|
//
|
|
// Internal function(s):
|
|
//
|
|
|
|
static BOOL
|
|
ParseCmdLine(
|
|
LPGAPP lpgApp
|
|
)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
DWORD dwArgs,
|
|
dwArg,
|
|
dwOption,
|
|
dwOther = 0;
|
|
LPTSTR *lpArgs,
|
|
lpArg,
|
|
lpOption,
|
|
lpOptions[] =
|
|
{
|
|
_T("FORCE") // 0
|
|
};
|
|
|
|
// Call our function to process the command line and put it
|
|
// into a nice list we can go through.
|
|
//
|
|
if ( (dwArgs = GetCommandLineArgs(&lpArgs) ) && lpArgs )
|
|
{
|
|
// We want to skip over the first argument (it is the path
|
|
// to the command being executed).
|
|
//
|
|
if ( dwArgs > 1 )
|
|
{
|
|
dwArg = 1;
|
|
lpArg = *(lpArgs + dwArg);
|
|
}
|
|
else
|
|
{
|
|
lpArg = NULL;
|
|
}
|
|
|
|
// Loop through all the arguments.
|
|
//
|
|
while ( lpArg && bRet )
|
|
{
|
|
// Now we check to see if the first char is a dash/slash or not.
|
|
//
|
|
if ( ( _T('-') == *lpArg ) ||
|
|
( _T('/') == *lpArg ) )
|
|
{
|
|
lpOption = CharNext(lpArg);
|
|
for ( dwOption = 0;
|
|
( ( dwOption < AS(lpOptions) ) &&
|
|
( 0 != lstrcmpi(lpOption, lpOptions[dwOption]) ) );
|
|
dwOption++ );
|
|
|
|
// This is where you add command line options that start
|
|
// with a dash (-) or a slash (/). You add them in the static
|
|
// array of pointers at the top of the function declaration and
|
|
// you case off the index it is in the array (0 for the first one,
|
|
// 1 for the second and so on).
|
|
//
|
|
switch ( dwOption )
|
|
{
|
|
case 0: // -FORCE
|
|
//
|
|
// If the force switch is specified... set the flag.
|
|
//
|
|
SetOfflineInstallFlags( GetOfflineInstallFlags() | INSTALL_FLAG_FORCE );
|
|
break;
|
|
|
|
default:
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
// Otherwise if there is something there it is just another argument.
|
|
//
|
|
else if ( *lpArg )
|
|
{
|
|
// This is where you add any command line options that don't
|
|
// start with anything special. We keep track of how many of
|
|
// these guys we find, so just add a case for each one you want
|
|
// to handle starting with 0.
|
|
//
|
|
switch ( dwOther++ )
|
|
{
|
|
case 0:
|
|
|
|
lstrcpyn(lpgApp->szInfPath, lpArg, AS(lpgApp->szInfPath));
|
|
break;
|
|
|
|
case 1:
|
|
|
|
lstrcpyn(lpgApp->szWinDir, lpArg, AS(lpgApp->szWinDir));
|
|
break;
|
|
|
|
default:
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
|
|
// Setup the pointer to the next argument in the command line.
|
|
//
|
|
if ( ++dwArg < dwArgs )
|
|
{
|
|
lpArg = *(lpArgs + dwArg);
|
|
}
|
|
else
|
|
{
|
|
lpArg = NULL;
|
|
}
|
|
}
|
|
|
|
// Make sure to free the two buffers allocated by the GetCommandLineArgs() function.
|
|
//
|
|
FREE(*lpArgs);
|
|
FREE(lpArgs);
|
|
}
|
|
|
|
// If there were no unrecognized arguments, then we return TRUE. Otherwise
|
|
// we return FALSE.
|
|
//
|
|
return bRet;
|
|
}
|
|
|
|
|
|
//
|
|
// Main Fuction:
|
|
//
|
|
|
|
int __cdecl wmain(DWORD dwArgs, LPTSTR lpszArgs[])
|
|
{
|
|
int nErr = 0;
|
|
HANDLE hMutex;
|
|
TCHAR szInfFile[MAX_PATH] = NULLSTR,
|
|
szWindows[MAX_PATH] = NULLSTR;
|
|
LPTSTR lpDontCare,
|
|
lpszErr;
|
|
HKEY hkeySoftware,
|
|
hkeySystem;
|
|
DWORD dwRet;
|
|
|
|
// Initialize logging library.
|
|
//
|
|
OpkInitLogging(NULL, _T("MSDINST") );
|
|
|
|
// Allways start with a line feed.
|
|
//
|
|
_tprintf(_T("\n"));
|
|
|
|
// This tool is current only supported on WinPE.
|
|
//
|
|
if ( !RegExists(HKLM, REG_KEY_WINPE, NULL) )
|
|
{
|
|
if ( lpszErr = AllocateString(NULL, IDS_ERR_WINPE) )
|
|
{
|
|
_putts(lpszErr);
|
|
_tprintf(_T("\n\n"));
|
|
FREE(lpszErr);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
// Need to have two args, the full path to the inf file
|
|
// with the controlers to install, and the path to the
|
|
// windows direcotry of the offline image.
|
|
//
|
|
if ( (dwArgs < 3) || !ParseCmdLine( &g_App) )
|
|
{
|
|
if ( lpszErr = AllocateString(NULL, IDS_ARGS) )
|
|
{
|
|
_putts(lpszErr);
|
|
_tprintf(_T("\n\n"));
|
|
FREE(lpszErr);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
// Copy the command line parameters to our own buffers.
|
|
//
|
|
if ( !( GetFullPathName(g_App.szInfPath, AS(szInfFile), szInfFile, &lpDontCare) && szInfFile[0] ) ||
|
|
!( GetFullPathName(g_App.szWinDir, AS(szWindows), szWindows, &lpDontCare) && szWindows[0] ) )
|
|
{
|
|
//
|
|
// Get the system text for "The specified path is invalid."
|
|
//
|
|
lpszErr = NULL;
|
|
dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
|
NULL,
|
|
ERROR_BAD_PATHNAME,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
(LPTSTR) &lpszErr,
|
|
0,
|
|
NULL );
|
|
|
|
//
|
|
// If the string was formatted, then let the user know something went wrong...
|
|
//
|
|
if ( dwRet && lpszErr )
|
|
{
|
|
_putts( lpszErr );
|
|
_tprintf(_T("\n\n"));
|
|
LocalFree( lpszErr );
|
|
lpszErr = NULL;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
// Make sure the inf file exists.
|
|
//
|
|
if ( !FileExists(szInfFile) )
|
|
{
|
|
if ( lpszErr = AllocateString(NULL, IDS_ERR_MISSING_INF_FILE) )
|
|
{
|
|
_tprintf(lpszErr, szInfFile);
|
|
_tprintf(_T("\n\n"));
|
|
FREE(lpszErr);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
// Make sure the inf file contains the section we need.
|
|
//
|
|
if ( !IniSettingExists(szInfFile, INI_SEC_WBOM_SYSPREP_MSD, NULL, NULL) )
|
|
{
|
|
if ( lpszErr = AllocateString(NULL, IDS_ERR_MISSING_INF_SECTION) )
|
|
{
|
|
_tprintf(lpszErr, szInfFile, INI_SEC_WBOM_SYSPREP_MSD);
|
|
_tprintf(_T("\n\n"));
|
|
FREE(lpszErr);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
// Make sure the image directory exists.
|
|
//
|
|
if ( !DirectoryExists(szWindows) )
|
|
{
|
|
if ( lpszErr = AllocateString(NULL, IDS_ERR_NOWINDOWS) )
|
|
{
|
|
_tprintf(lpszErr, szWindows);
|
|
_tprintf(_T("\n\n"));
|
|
FREE(lpszErr);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
// Only let one of this guy run.
|
|
//
|
|
hMutex = CreateMutex(NULL, FALSE, STR_MUTEX_MSDINST);
|
|
if ( hMutex == NULL )
|
|
{
|
|
if ( lpszErr = AllocateString(NULL, IDS_ERR_ONEONLY) )
|
|
{
|
|
_putts(lpszErr);
|
|
_tprintf(_T("\n\n"));
|
|
FREE(lpszErr);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
// We have to be able to load the offline image to do anything.
|
|
//
|
|
if ( !RegLoadOfflineImage(szWindows, &hkeySoftware, &hkeySystem) )
|
|
{
|
|
if ( lpszErr = AllocateString(NULL, IDS_ERR_LOADIMAGE) )
|
|
{
|
|
_tprintf(lpszErr, szWindows);
|
|
_tprintf(_T("\n\n"));
|
|
FREE(lpszErr);
|
|
}
|
|
|
|
CloseHandle(hMutex);
|
|
return 1;
|
|
}
|
|
|
|
// Now try to install the MSD into the offline image.
|
|
//
|
|
if ( !SetupCriticalDevices(szInfFile, hkeySoftware, hkeySystem, szWindows) )
|
|
{
|
|
if ( lpszErr = AllocateString(NULL, IDS_ERR_CDD) )
|
|
{
|
|
_putts(lpszErr);
|
|
_tprintf(_T("\n\n"));
|
|
FREE(lpszErr);
|
|
}
|
|
|
|
nErr = 1;
|
|
}
|
|
|
|
// Unload the offline image.
|
|
//
|
|
RegUnloadOfflineImage(hkeySoftware, hkeySystem);
|
|
|
|
|
|
// Release the mutex.
|
|
//
|
|
CloseHandle(hMutex);
|
|
|
|
|
|
if ( 0 == nErr )
|
|
{
|
|
if ( lpszErr = AllocateString(NULL, IDS_ERR_SUCCESS) )
|
|
{
|
|
_putts(lpszErr);
|
|
_tprintf(_T("\n\n"));
|
|
FREE(lpszErr);
|
|
}
|
|
}
|
|
|
|
return nErr;
|
|
} |