659 lines
18 KiB
C++
659 lines
18 KiB
C++
#include <windows.h>
|
|
#include <stdio.h>
|
|
|
|
#include "patchapi.h"
|
|
#include "const.h"
|
|
#include "ansparse.h"
|
|
#include "dirwak2a.h"
|
|
#include "filetree.h"
|
|
|
|
// the log file handle
|
|
HANDLE g_hDebugFile = INVALID_HANDLE_VALUE;
|
|
// is log required?
|
|
BOOL g_blnDebugFile = FALSE;
|
|
// is the logfile a new file?
|
|
BOOL g_blnDebugNewFile = FALSE;
|
|
// guard for the logfile access
|
|
CRITICAL_SECTION g_CSLogFile;
|
|
// multi thread support, default number of threads
|
|
ULONG g_iNumberOfThreads = 1;
|
|
|
|
// some patching options
|
|
DWORD g_iBestMethod = (PATCH_OPTION_USE_LZX_A | PATCH_OPTION_NO_TIMESTAMP);
|
|
BOOL g_blnCollectStat = FALSE;
|
|
BOOL g_blnFullLog = FALSE;
|
|
|
|
// some local function declarations
|
|
VOID DisplayHelpMessage(VOID);
|
|
VOID DisplayHelp(VOID);
|
|
VOID GenerateAnswerFile(VOID);
|
|
BOOL ParseCommandLine(IN INT argc, IN WCHAR* argv[]);
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// wmain, the unicode command line parameter entry point for this patching
|
|
// tool, it parses the commandline first, then reads the answerfile for
|
|
// what to do, and then creates the filetrees for languages that are to
|
|
// to matched and patched
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
extern "C" int __cdecl wmain(int argc, WCHAR *argv[])
|
|
{
|
|
INT rc = PREP_NO_ERROR;
|
|
FileTree* pBaseTree = NULL;
|
|
FileTree* pLocTree = NULL;
|
|
AnswerParser* pParse = NULL;
|
|
PPATCH_LANGUAGE pBase = NULL;
|
|
PPATCH_LANGUAGE pLanguage = NULL;
|
|
|
|
InitializeCriticalSection(&g_CSLogFile);
|
|
|
|
DisplayDebugMessage(TRUE, TRUE, FALSE, TRUE,
|
|
L"Microsoft (R) OEMPatch Version %d.%.3d\nCopyright (C) Microsoft Corp 1999-2000. All rights reserved.",
|
|
g_iMajorVersion, g_iMinorVersion);
|
|
|
|
// parse command line
|
|
if(!ParseCommandLine(argc, argv))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, FALSE,
|
|
L"OEMPatch has finished parsing command line parameters.");
|
|
|
|
// create the parser for parsing the answer file
|
|
pParse = new AnswerParser;
|
|
if(pParse == NULL)
|
|
{
|
|
rc = PREP_NO_MEMORY;
|
|
goto CLEANUP;
|
|
}
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, FALSE,
|
|
L"Creating the parser for OEMPatch.ans.");
|
|
|
|
// parsing the answer file
|
|
if(!pParse->Parse(ANS_FILE_NAME))
|
|
{
|
|
delete pParse;
|
|
pParse = NULL;
|
|
rc = PREP_INPUT_FILE_ERROR;
|
|
goto CLEANUP;
|
|
}
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, FALSE,
|
|
L"Parsing answer file completed.");
|
|
|
|
DisplayDebugMessage(TRUE, TRUE, FALSE, TRUE,
|
|
L"Starting a new OEMPatch session.");
|
|
|
|
// call for filetree objects
|
|
// base language, any error causes the process to terminate, cannot go on without a base language
|
|
pBase = pParse->GetBaseLanguage();
|
|
if(pBase)
|
|
{
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, FALSE,
|
|
L"Retrieved the base language.");
|
|
DisplayDebugMessage(TRUE, TRUE, FALSE, TRUE,
|
|
L"Creating base tree...");
|
|
rc = FileTree::Create(pBase, pParse, &pBaseTree, TRUE,
|
|
g_iBestMethod, g_blnCollectStat, g_blnFullLog);
|
|
if(rc != PREP_NO_ERROR)
|
|
{
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"error, CreateFileTree(\"%ls\") returned %d",
|
|
pBase->s_wszLanguage, rc);
|
|
goto CLEANUP;
|
|
}
|
|
DisplayDebugMessage(TRUE, FALSE, FALSE, TRUE,
|
|
L"Done creating base tree.");
|
|
|
|
// create the multi-thread structs, done only once by the base tree
|
|
if(!pBaseTree->CreateMultiThreadStruct(g_iNumberOfThreads))
|
|
{
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"error, cannot create the patch thread(s)");
|
|
goto CLEANUP;
|
|
}
|
|
|
|
DisplayDebugMessage(TRUE, TRUE, FALSE, TRUE,
|
|
L"Loading base tree...");
|
|
rc = pBaseTree->Load(NULL);
|
|
if(rc != PREP_NO_ERROR)
|
|
{
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"error, LoadFileTree(\"%ls\") returned %d",
|
|
pBase->s_wszLanguage, rc);
|
|
goto CLEANUP;
|
|
}
|
|
DisplayDebugMessage(TRUE, FALSE, FALSE, TRUE,
|
|
L"Done loading base tree.");
|
|
}
|
|
else
|
|
{
|
|
rc = PREP_INPUT_FILE_ERROR;
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"error, there is no base lanugage to load");
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// none-base languages, errors are just recorded, continue to the next language
|
|
while((pLanguage = pParse->GetNextLanguage()) != NULL)
|
|
{
|
|
// none-base tree
|
|
DisplayDebugMessage(TRUE, TRUE, FALSE, TRUE,
|
|
L"Creating localized (\"%ls\") tree...",
|
|
pLanguage->s_wszDirectory);
|
|
rc = FileTree::Create(pLanguage, pParse, &pLocTree, FALSE,
|
|
g_iBestMethod, g_blnCollectStat, g_blnFullLog);
|
|
if(rc == PREP_NO_ERROR)
|
|
{
|
|
DisplayDebugMessage(TRUE, FALSE, FALSE, TRUE,
|
|
L"Done creating localized (\"%ls\") tree.",
|
|
pLanguage->s_wszDirectory);
|
|
DisplayDebugMessage(TRUE, TRUE, FALSE, TRUE,
|
|
L"Loading and patching localized (\"%ls\") tree...", pLanguage->s_wszDirectory);
|
|
// load and match it
|
|
rc = pLocTree->Load(pBaseTree);
|
|
if(rc == PREP_NO_ERROR)
|
|
{
|
|
DisplayDebugMessage(TRUE, FALSE, FALSE, TRUE,
|
|
L"Done loading and patching localized (\"%ls\") tree.", pLanguage->s_wszDirectory);
|
|
}
|
|
else
|
|
{
|
|
DisplayDebugMessage(TRUE, FALSE, FALSE, TRUE,
|
|
L"warning, error in matching localized (\"%ls\") tree.", pLanguage->s_wszDirectory);
|
|
}
|
|
|
|
// remove for the next language
|
|
delete pLocTree;
|
|
pLocTree = NULL;
|
|
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, FALSE,
|
|
L"Localized tree is removed from memory.");
|
|
}
|
|
else
|
|
{
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"error, creating localized (\"%ls\") tree.",
|
|
pLanguage->s_wszDirectory);
|
|
}
|
|
}
|
|
|
|
CLEANUP:
|
|
|
|
if(pBaseTree)
|
|
{
|
|
// remove the multi-thread struct here, done only once
|
|
pBaseTree->DeleteMultiThreadStruct();
|
|
delete pBaseTree;
|
|
pBaseTree = NULL;
|
|
}
|
|
if(pLocTree)
|
|
{
|
|
delete pLocTree;
|
|
pLocTree = NULL;
|
|
}
|
|
if(pParse)
|
|
{
|
|
delete pParse;
|
|
pParse = NULL;
|
|
}
|
|
|
|
if(rc != PREP_NO_ERROR)
|
|
{
|
|
switch(rc)
|
|
{
|
|
case PREP_NO_MEMORY:
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"More memory is needed on this system to run.");
|
|
break;
|
|
case PREP_BAD_PATH_ERROR:
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"Directory for some files are invalid, please check for valid directories.");
|
|
break;
|
|
case PREP_UNKNOWN_ERROR:
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"Unknown error, contact support.");
|
|
break;
|
|
case PREP_DEPTH_ERROR:
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"File tree is too deep, contact support.");
|
|
break;
|
|
case PREP_BAD_COMMAND:
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"Bad command, try again.");
|
|
break;
|
|
case PREP_HASH_ERROR:
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"Internal hashing error, contact support.");
|
|
break;
|
|
case PREP_BUFFER_OVERFLOW:
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"Internal buffer overflow, contact support.");
|
|
break;
|
|
case PREP_NOT_PATCHABLE:
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"Patching error, try again or contact support");
|
|
break;
|
|
case PREP_INPUT_FILE_ERROR:
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"Input file error, please check for valid OEMPatch.ans.");
|
|
break;
|
|
case PREP_SCRIPT_FILE_ERROR:
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"Cannot save infomation to scipt file, try again or contact support.");
|
|
break;
|
|
case PREP_PATCH_FILE_ERROR:
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"Patch file error, try again or contact support.");
|
|
break;
|
|
case PREP_DIRECTORY_ERROR:
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"Directory error, try again or contact support.");
|
|
break;
|
|
case PREP_COPY_FILE_ERROR:
|
|
DisplayDebugMessage(FALSE, FALSE, FALSE, TRUE,
|
|
L"File cannot be copied, check for available space and file permission.");
|
|
break;
|
|
}
|
|
}
|
|
|
|
DisplayDebugMessage(TRUE, TRUE, FALSE, TRUE,
|
|
L"OEMPatch has finished.");
|
|
DisplayDebugMessage(FALSE, FALSE, TRUE, FALSE, NULL);
|
|
|
|
if(g_hDebugFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(g_hDebugFile);
|
|
}
|
|
|
|
DeleteCriticalSection(&g_CSLogFile);
|
|
|
|
return(rc);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ParseCommandLine, this function attempts to parse the commandline parameters
|
|
// and saves them into global variables for easy access
|
|
//
|
|
// Parameters:
|
|
//
|
|
// argc, the number of parameter in the command line
|
|
// argv[], the command line buffer, holds all the command line parameters
|
|
//
|
|
// Return:
|
|
//
|
|
// TRUE for correct command line parameters, FALSE for invalid parameters
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL ParseCommandLine(IN INT argc, IN WCHAR* argv[])
|
|
{
|
|
BOOL blnReturn = TRUE;
|
|
|
|
// parse commandline parameters
|
|
for(INT i = 1; i < argc && blnReturn; i++)
|
|
{
|
|
if(argv[i][0] == L'/')
|
|
{
|
|
switch(argv[i][1])
|
|
{
|
|
case L'm':
|
|
// multi thread
|
|
if(argv[i][2] >= L'1' && argv[i][2] <= '9')
|
|
{
|
|
g_iNumberOfThreads = argv[i][2] - L'0';
|
|
}
|
|
break;
|
|
case L's':
|
|
// collect all stats
|
|
g_blnCollectStat = TRUE;
|
|
break;
|
|
case L'b':
|
|
// best patch
|
|
g_iBestMethod |= PATCH_OPTION_FAIL_IF_BIGGER;
|
|
break;
|
|
case L'L':
|
|
// log a new file
|
|
g_blnDebugNewFile = TRUE;
|
|
case L'l':
|
|
// log a old file
|
|
g_blnDebugFile = TRUE;
|
|
if(g_blnDebugNewFile)
|
|
{
|
|
// new logfile
|
|
ULONG iWriteByte = 0;
|
|
g_hDebugFile = CreateFileW(LOG_FILE_NAME,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
(LPSECURITY_ATTRIBUTES)NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
(HANDLE)NULL);
|
|
if(g_hDebugFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
WriteFile(g_hDebugFile, &UNICODE_HEAD, sizeof(WCHAR),
|
|
&iWriteByte, NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// append to old logfile
|
|
g_hDebugFile = CreateFileW(LOG_FILE_NAME,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
(LPSECURITY_ATTRIBUTES)NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
(HANDLE)NULL);
|
|
if(g_hDebugFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
SetFilePointer(g_hDebugFile, 0, NULL, FILE_END);
|
|
}
|
|
else
|
|
{
|
|
ULONG iWriteByte = 0;
|
|
g_hDebugFile = CreateFileW(LOG_FILE_NAME,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
(LPSECURITY_ATTRIBUTES)NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
(HANDLE)NULL);
|
|
if(g_hDebugFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
WriteFile(g_hDebugFile, &UNICODE_HEAD,
|
|
sizeof(WCHAR), &iWriteByte, NULL);
|
|
}
|
|
}
|
|
}
|
|
if(g_hDebugFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
printf("warning, Logfile error, failed to open OEMPatch.log.\n");
|
|
printf("warning, there is no log file\n");
|
|
}
|
|
if(argv[i][2] == L'C')
|
|
{
|
|
g_blnFullLog = TRUE;
|
|
}
|
|
break;
|
|
case L'g':
|
|
// generate a sample answerfile
|
|
GenerateAnswerFile();
|
|
blnReturn = FALSE;
|
|
break;
|
|
case L'?':
|
|
// show help
|
|
DisplayHelp();
|
|
blnReturn = FALSE;
|
|
break;
|
|
default:
|
|
// show the message for help
|
|
DisplayHelpMessage();
|
|
blnReturn = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DisplayHelpMessage();
|
|
blnReturn = FALSE;
|
|
}
|
|
}
|
|
|
|
return(blnReturn);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DisplayDebugMessage, show the message to the logfile is possible, else if
|
|
// the message is intended as print, output to stdout.
|
|
// The function will buffer all the messages up until
|
|
// either flushed or the buffer overflows, the reason
|
|
// being is to reduce io to disk
|
|
//
|
|
// Note, all message in pwszWhat should not contain any endoflinec char,
|
|
// when blnFlush is TRUE, all other parameter are ignored
|
|
//
|
|
// Parameters:
|
|
//
|
|
// blnTime, time included in the message?
|
|
// blnBanner, create a banner around the message?
|
|
// blnFlush, write the buffer to file
|
|
// blnPrint, show this message to stdout?
|
|
// pwszWhat, the format string
|
|
// ..., parameters for the format string
|
|
//
|
|
// Return:
|
|
//
|
|
// none
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
VOID DisplayDebugMessage(IN BOOL blnTime,
|
|
IN BOOL blnBanner,
|
|
IN BOOL blnFlush,
|
|
IN BOOL blnPrint,
|
|
IN WCHAR* pwszWhat,
|
|
...)
|
|
{
|
|
static WCHAR strWriteBuffer[SUPER_LENGTH];
|
|
static ULONG iSize;
|
|
|
|
WCHAR msg[STRING_LENGTH];
|
|
ZeroMemory(msg, STRING_LENGTH * sizeof(WCHAR));
|
|
ULONG iBegin = 0;
|
|
ULONG iLength = 0;
|
|
ULONG iWriteBytes = 0;
|
|
va_list arglist;
|
|
|
|
if(pwszWhat)
|
|
{
|
|
va_start(arglist, pwszWhat);
|
|
vswprintf(msg, pwszWhat, arglist);
|
|
va_end(arglist);
|
|
}
|
|
|
|
__try
|
|
{
|
|
EnterCriticalSection(&g_CSLogFile);
|
|
if(g_hDebugFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
if(!blnFlush && pwszWhat)
|
|
{
|
|
// 2 for endofline and carriage return
|
|
iLength = wcslen(msg) + 2;
|
|
if(blnTime)
|
|
{
|
|
// 1 for space
|
|
iLength += 1 + TIME_LENGTH;
|
|
}
|
|
if(blnBanner)
|
|
{
|
|
iLength += BANNER_LENGTH * 2;
|
|
}
|
|
iBegin = iSize;
|
|
iSize += iLength;
|
|
if(iSize + 1 < SUPER_LENGTH)
|
|
{
|
|
// buffer the message up
|
|
if(blnBanner)
|
|
{
|
|
wcscat(strWriteBuffer, BANNER);
|
|
}
|
|
if(blnTime)
|
|
{
|
|
WCHAR strDate[LANGUAGE_LENGTH];
|
|
WCHAR strTime[LANGUAGE_LENGTH];
|
|
SYSTEMTIME SystemTime;
|
|
GetLocalTime(&SystemTime);
|
|
GetDateFormatW(LOCALE_USER_DEFAULT, 0, &SystemTime,
|
|
L"MMddyy", strDate, LANGUAGE_LENGTH);
|
|
GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &SystemTime,
|
|
L"HHmmss", strTime, LANGUAGE_LENGTH);
|
|
wcscat(strWriteBuffer, strDate);
|
|
wcscat(strWriteBuffer, strTime);
|
|
wcscat(strWriteBuffer, SPACE);
|
|
}
|
|
wcscat(strWriteBuffer, msg);
|
|
wcscat(strWriteBuffer, ENDOFLINE);
|
|
wcscat(strWriteBuffer, CRETURN);
|
|
if(blnBanner)
|
|
{
|
|
wcscat(strWriteBuffer, BANNER);
|
|
}
|
|
strWriteBuffer[iSize] = 0;
|
|
}
|
|
else
|
|
{
|
|
// overflow
|
|
WriteFile(g_hDebugFile, strWriteBuffer,
|
|
iBegin * sizeof(WCHAR), &iWriteBytes, NULL);
|
|
ZeroMemory(strWriteBuffer, SUPER_LENGTH * sizeof(WCHAR));
|
|
if(blnBanner)
|
|
{
|
|
wcscat(strWriteBuffer, BANNER);
|
|
}
|
|
if(blnTime)
|
|
{
|
|
WCHAR strDate[LANGUAGE_LENGTH];
|
|
WCHAR strTime[LANGUAGE_LENGTH];
|
|
SYSTEMTIME SystemTime;
|
|
GetLocalTime(&SystemTime);
|
|
GetDateFormatW(LOCALE_USER_DEFAULT, 0,
|
|
&SystemTime, L"MMddyy", strDate, LANGUAGE_LENGTH);
|
|
GetTimeFormatW(LOCALE_USER_DEFAULT,
|
|
0, &SystemTime, L"HHmmss", strTime,
|
|
LANGUAGE_LENGTH);
|
|
wcscat(strWriteBuffer, strDate);
|
|
wcscat(strWriteBuffer, strTime);
|
|
wcscat(strWriteBuffer, SPACE);
|
|
}
|
|
wcscat(strWriteBuffer, msg);
|
|
wcscat(strWriteBuffer, ENDOFLINE);
|
|
wcscat(strWriteBuffer, CRETURN);
|
|
if(blnBanner)
|
|
{
|
|
wcscat(strWriteBuffer, BANNER);
|
|
}
|
|
iSize = iLength;
|
|
}
|
|
}
|
|
else if(blnFlush && iSize > 0)
|
|
{
|
|
// flush the buffer to file
|
|
WriteFile(g_hDebugFile, strWriteBuffer, iSize * sizeof(WCHAR), &iWriteBytes, NULL);
|
|
iSize = 0;
|
|
}
|
|
if(blnPrint)
|
|
{
|
|
wprintf(L"%ls\n", msg);
|
|
}
|
|
}
|
|
else if(msg && blnPrint)
|
|
{
|
|
wprintf(L"%ls\n", msg);
|
|
}
|
|
}
|
|
__finally
|
|
{
|
|
LeaveCriticalSection(&g_CSLogFile);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DisplayHelpMessage, shows what to do if the user if confused
|
|
//
|
|
// Parameters:
|
|
//
|
|
// none
|
|
//
|
|
// Return:
|
|
//
|
|
// none
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
VOID DisplayHelpMessage(VOID)
|
|
{
|
|
printf("\nFor help try /?.\n");
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DisplayHelp, shows what oempatch is cabable of
|
|
//
|
|
// Parameters:
|
|
//
|
|
// none
|
|
//
|
|
// Return:
|
|
//
|
|
// none
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
VOID DisplayHelp(VOID)
|
|
{
|
|
printf("\nOEMPatch %d.%.3d - Help\n", g_iMajorVersion, g_iMinorVersion);
|
|
printf("Usage: oempatch [/m#] [/s] [/b] [/l | /L [C] ] [/g | /?]\n");
|
|
printf("(no switch):\trun patch, single thread\n");
|
|
printf("/m#:\t\trun multi-threaded patch, maximum # is 9, minimum is 1\n");
|
|
printf("/s:\t\tcollect patching stats when running patch, slows down patching\n");
|
|
printf("/b:\t\tchoose best patching methods, slows down patching\n");
|
|
printf("/l:\t\trun patch with append to the log file OEMPatch.log\n");
|
|
printf("/L:\t\trun patch with a new log file OEMPatch.log\n");
|
|
printf("/lC, /LC:\tevery file status is logged\n");
|
|
printf("/g:\t\tgenerate a new sample answer file if there is no such file\n");
|
|
printf("/?:\t\tdisplay help\n");
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DisplayHelp, creates a sample answer file, so that the user can modifie
|
|
// according to needs
|
|
//
|
|
// Parameters:
|
|
//
|
|
// none
|
|
//
|
|
// Return:
|
|
//
|
|
// none
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
VOID GenerateAnswerFile(VOID)
|
|
{
|
|
HANDLE hAnsFile = INVALID_HANDLE_VALUE;
|
|
ULONG iWriteByte = 0;
|
|
ULONG i = 0;
|
|
|
|
hAnsFile = CreateFileW(ANS_FILE_NAME,
|
|
GENERIC_WRITE,
|
|
0,
|
|
(LPSECURITY_ATTRIBUTES)NULL,
|
|
CREATE_NEW,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
(HANDLE)NULL);
|
|
if(hAnsFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
// construct the answer file
|
|
WriteFile(hAnsFile, &UNICODE_HEAD, sizeof(WCHAR), &iWriteByte, NULL);
|
|
// SAMPLEFILE is defined in ansparse.h
|
|
while(SAMPLEFILE[i][0] &&
|
|
WriteFile(hAnsFile, SAMPLEFILE[i],
|
|
wcslen(SAMPLEFILE[i]) * sizeof(WCHAR), &iWriteByte, NULL))
|
|
{
|
|
i++;
|
|
}
|
|
CloseHandle(hAnsFile);
|
|
if(SAMPLEFILE[i][0])
|
|
{
|
|
printf("Warning:OEMPatch.ans may contain errors, needs regeneration.\n");
|
|
}
|
|
else
|
|
{
|
|
printf("OEMPatch.ans generated, needs to be manually completed and saved as UNICODE.\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("OEMPatch.ans already exists, no new file created.\n");
|
|
}
|
|
} |