windows-nt/Source/XPSP1/NT/base/mspatch/api/samples/wpatch/wpatch.c
2020-09-26 16:20:57 +08:00

280 lines
6.2 KiB
C

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400
#endif
#ifndef WIN32
#define WIN32 0x0400
#endif
#pragma warning( disable: 4001 4035 4100 4115 4200 4201 4204 4209 4214 4514 4699 )
#include <windows.h>
#pragma warning( disable: 4001 4035 4100 4115 4200 4201 4204 4209 4214 4514 4699 )
#include <commctrl.h>
#include "wpatchid.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "patchapi.h"
#include "patchprv.h"
#include <ntverp.h>
#include <common.ver>
typedef struct {
HWND hwndProgress;
int iPercentLast;
} CALLBACK_CONTEXT;
void Usage( void ) {
MessageBox( NULL,
"WPATCH " VER_PRODUCTVERSION_STR " Patch Application Utility\n"
VER_LEGALCOPYRIGHT_STR
"\n\n"
"Usage: WPATCH PatchFile OldFile TargetNewFile",
"Patch Application Utility",
MB_OK
);
}
BOOL
CALLBACK
MyProgressCallback(
PVOID CallbackContext,
ULONG CurrentPosition,
ULONG MaximumPosition
)
{
int iPercent;
MSG msg;
CALLBACK_CONTEXT *pContext = CallbackContext;
if (pContext->hwndProgress != NULL) {
if ( CurrentPosition & 0xFF000000 ) {
CurrentPosition >>= 8;
MaximumPosition >>= 8;
}
if ( MaximumPosition != 0 ) {
iPercent = ( CurrentPosition * 100 ) / MaximumPosition;
if (pContext->iPercentLast != iPercent) {
pContext->iPercentLast = iPercent;
SendDlgItemMessage(pContext->hwndProgress, IDC_PROGRESS, PBM_SETPOS,
iPercent, 0);
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
DispatchMessage(&msg);
}
}
}
}
return TRUE;
}
INT_PTR CALLBACK ProgressWndProc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_INITDIALOG:
SendDlgItemMessage(hdlg, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, 99));
EnableMenuItem(GetSystemMenu(hdlg, FALSE), SC_CLOSE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
return TRUE;
}
return 0;
}
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
char *pchCommand;
char *argv[50];
int argc;
enum { WHITESPACE, UNQUOTED, QUOTED } eState = WHITESPACE;
LPSTR OldFileName = NULL;
LPSTR PatchFileName = NULL;
LPSTR NewFileName = NULL;
BOOL Success;
LPSTR arg;
int i;
int rc;
CALLBACK_CONTEXT Context;
int fWaitOnError = TRUE;
SetErrorMode( SEM_FAILCRITICALERRORS );
#ifndef DEBUG
SetErrorMode( SEM_NOALIGNMENTFAULTEXCEPT | SEM_FAILCRITICALERRORS );
#endif
Context.hwndProgress = NULL;
Context.iPercentLast = -1;
pchCommand = _strdup(lpCmdLine); /* work on a copy */
argv[0] = ""; /* no EXE name supplied */
argc = 1; /* that was one */
while (*pchCommand) /* walk the string */
{
switch (eState)
{
case WHITESPACE:
if (*pchCommand <= ' ')
{
/* ignore it */
}
else if (*pchCommand == '\"')
{
argv[argc++] = pchCommand + 1; /* skip quote */
eState = QUOTED;
}
else
{
argv[argc++] = pchCommand;
eState = UNQUOTED;
}
break;
case UNQUOTED:
if (*pchCommand <= ' ')
{
*pchCommand = '\0'; /* nul-terminate */
eState = WHITESPACE;
}
else
{
/* keep moving up */
}
break;
case QUOTED:
if (*pchCommand == '\"')
{
*pchCommand = '\0'; /* turn quote to a nul */
eState = WHITESPACE;
}
else
{
/* keep moving up */
}
break;
}
pchCommand++;
}
argv[argc] = NULL; /* NULL-terminate the list */
for ( i = 1; i < argc; i++ ) {
arg = argv[ i ];
if ( strchr( arg, '?' )) {
Usage();
rc = 1;
goto bail;
}
if ( lstrcmpi( arg, "-QUIET" ) == 0) {
nShowCmd = SW_HIDE;
}
else if ( lstrcmpi( arg, "-NOWAIT" ) == 0) {
fWaitOnError = FALSE;
}
else if ( PatchFileName == NULL ) {
PatchFileName = arg;
}
else if ( OldFileName == NULL ) {
OldFileName = arg;
}
else if ( NewFileName == NULL ) {
NewFileName = arg;
}
else {
Usage();
rc = 1;
goto bail;
}
}
if (( OldFileName == NULL ) || ( NewFileName == NULL ) || ( PatchFileName == NULL )) {
Usage();
rc = 1;
goto bail;
}
if (nShowCmd != SW_HIDE) {
InitCommonControls();
Context.hwndProgress = CreateDialog(hInstance,
MAKEINTRESOURCE(DLG_PROGRESS), NULL, ProgressWndProc);
ShowWindow( Context.hwndProgress, nShowCmd ); // might be ignored per spec
ShowWindow( Context.hwndProgress, nShowCmd ); // won't be ignored
}
DeleteFile( NewFileName );
Success = ApplyPatchToFileEx(
PatchFileName,
OldFileName,
NewFileName,
0,
MyProgressCallback,
&Context
);
if (Context.hwndProgress != NULL)
{
DestroyWindow(Context.hwndProgress);
}
if ( ! Success ) {
if (fWaitOnError) {
CHAR ErrorText[ 100 ];
ULONG ErrorCode = GetLastError();
wsprintf( ErrorText, "Failed to create file from patch (%X)", ErrorCode );
MessageBox(NULL,
ErrorText,
"WPATCH Failed",
MB_ICONERROR | MB_SYSTEMMODAL);
}
rc = 2;
goto bail;
}
rc = 0;
bail:
return(rc);
}