Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

279 lines
6.2 KiB

  1. #ifndef _WIN32_WINNT
  2. #define _WIN32_WINNT 0x0400
  3. #endif
  4. #ifndef WIN32
  5. #define WIN32 0x0400
  6. #endif
  7. #pragma warning( disable: 4001 4035 4100 4115 4200 4201 4204 4209 4214 4514 4699 )
  8. #include <windows.h>
  9. #pragma warning( disable: 4001 4035 4100 4115 4200 4201 4204 4209 4214 4514 4699 )
  10. #include <commctrl.h>
  11. #include "wpatchid.h"
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <stdio.h>
  15. #include "patchapi.h"
  16. #include "patchprv.h"
  17. #include <ntverp.h>
  18. #include <common.ver>
  19. typedef struct {
  20. HWND hwndProgress;
  21. int iPercentLast;
  22. } CALLBACK_CONTEXT;
  23. void Usage( void ) {
  24. MessageBox( NULL,
  25. "WPATCH " VER_PRODUCTVERSION_STR " Patch Application Utility\n"
  26. VER_LEGALCOPYRIGHT_STR
  27. "\n\n"
  28. "Usage: WPATCH PatchFile OldFile TargetNewFile",
  29. "Patch Application Utility",
  30. MB_OK
  31. );
  32. }
  33. BOOL
  34. CALLBACK
  35. MyProgressCallback(
  36. PVOID CallbackContext,
  37. ULONG CurrentPosition,
  38. ULONG MaximumPosition
  39. )
  40. {
  41. int iPercent;
  42. MSG msg;
  43. CALLBACK_CONTEXT *pContext = CallbackContext;
  44. if (pContext->hwndProgress != NULL) {
  45. if ( CurrentPosition & 0xFF000000 ) {
  46. CurrentPosition >>= 8;
  47. MaximumPosition >>= 8;
  48. }
  49. if ( MaximumPosition != 0 ) {
  50. iPercent = ( CurrentPosition * 100 ) / MaximumPosition;
  51. if (pContext->iPercentLast != iPercent) {
  52. pContext->iPercentLast = iPercent;
  53. SendDlgItemMessage(pContext->hwndProgress, IDC_PROGRESS, PBM_SETPOS,
  54. iPercent, 0);
  55. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  56. DispatchMessage(&msg);
  57. }
  58. }
  59. }
  60. }
  61. return TRUE;
  62. }
  63. INT_PTR CALLBACK ProgressWndProc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
  64. {
  65. switch (msg)
  66. {
  67. case WM_INITDIALOG:
  68. SendDlgItemMessage(hdlg, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0, 99));
  69. EnableMenuItem(GetSystemMenu(hdlg, FALSE), SC_CLOSE, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED);
  70. return TRUE;
  71. }
  72. return 0;
  73. }
  74. int WINAPI WinMain(
  75. HINSTANCE hInstance,
  76. HINSTANCE hPrevInstance,
  77. LPSTR lpCmdLine,
  78. int nShowCmd)
  79. {
  80. char *pchCommand;
  81. char *argv[50];
  82. int argc;
  83. enum { WHITESPACE, UNQUOTED, QUOTED } eState = WHITESPACE;
  84. LPSTR OldFileName = NULL;
  85. LPSTR PatchFileName = NULL;
  86. LPSTR NewFileName = NULL;
  87. BOOL Success;
  88. LPSTR arg;
  89. int i;
  90. int rc;
  91. CALLBACK_CONTEXT Context;
  92. int fWaitOnError = TRUE;
  93. SetErrorMode( SEM_FAILCRITICALERRORS );
  94. #ifndef DEBUG
  95. SetErrorMode( SEM_NOALIGNMENTFAULTEXCEPT | SEM_FAILCRITICALERRORS );
  96. #endif
  97. Context.hwndProgress = NULL;
  98. Context.iPercentLast = -1;
  99. pchCommand = _strdup(lpCmdLine); /* work on a copy */
  100. argv[0] = ""; /* no EXE name supplied */
  101. argc = 1; /* that was one */
  102. while (*pchCommand) /* walk the string */
  103. {
  104. switch (eState)
  105. {
  106. case WHITESPACE:
  107. if (*pchCommand <= ' ')
  108. {
  109. /* ignore it */
  110. }
  111. else if (*pchCommand == '\"')
  112. {
  113. argv[argc++] = pchCommand + 1; /* skip quote */
  114. eState = QUOTED;
  115. }
  116. else
  117. {
  118. argv[argc++] = pchCommand;
  119. eState = UNQUOTED;
  120. }
  121. break;
  122. case UNQUOTED:
  123. if (*pchCommand <= ' ')
  124. {
  125. *pchCommand = '\0'; /* nul-terminate */
  126. eState = WHITESPACE;
  127. }
  128. else
  129. {
  130. /* keep moving up */
  131. }
  132. break;
  133. case QUOTED:
  134. if (*pchCommand == '\"')
  135. {
  136. *pchCommand = '\0'; /* turn quote to a nul */
  137. eState = WHITESPACE;
  138. }
  139. else
  140. {
  141. /* keep moving up */
  142. }
  143. break;
  144. }
  145. pchCommand++;
  146. }
  147. argv[argc] = NULL; /* NULL-terminate the list */
  148. for ( i = 1; i < argc; i++ ) {
  149. arg = argv[ i ];
  150. if ( strchr( arg, '?' )) {
  151. Usage();
  152. rc = 1;
  153. goto bail;
  154. }
  155. if ( lstrcmpi( arg, "-QUIET" ) == 0) {
  156. nShowCmd = SW_HIDE;
  157. }
  158. else if ( lstrcmpi( arg, "-NOWAIT" ) == 0) {
  159. fWaitOnError = FALSE;
  160. }
  161. else if ( PatchFileName == NULL ) {
  162. PatchFileName = arg;
  163. }
  164. else if ( OldFileName == NULL ) {
  165. OldFileName = arg;
  166. }
  167. else if ( NewFileName == NULL ) {
  168. NewFileName = arg;
  169. }
  170. else {
  171. Usage();
  172. rc = 1;
  173. goto bail;
  174. }
  175. }
  176. if (( OldFileName == NULL ) || ( NewFileName == NULL ) || ( PatchFileName == NULL )) {
  177. Usage();
  178. rc = 1;
  179. goto bail;
  180. }
  181. if (nShowCmd != SW_HIDE) {
  182. InitCommonControls();
  183. Context.hwndProgress = CreateDialog(hInstance,
  184. MAKEINTRESOURCE(DLG_PROGRESS), NULL, ProgressWndProc);
  185. ShowWindow( Context.hwndProgress, nShowCmd ); // might be ignored per spec
  186. ShowWindow( Context.hwndProgress, nShowCmd ); // won't be ignored
  187. }
  188. DeleteFile( NewFileName );
  189. Success = ApplyPatchToFileEx(
  190. PatchFileName,
  191. OldFileName,
  192. NewFileName,
  193. 0,
  194. MyProgressCallback,
  195. &Context
  196. );
  197. if (Context.hwndProgress != NULL)
  198. {
  199. DestroyWindow(Context.hwndProgress);
  200. }
  201. if ( ! Success ) {
  202. if (fWaitOnError) {
  203. CHAR ErrorText[ 100 ];
  204. ULONG ErrorCode = GetLastError();
  205. wsprintf( ErrorText, "Failed to create file from patch (%X)", ErrorCode );
  206. MessageBox(NULL,
  207. ErrorText,
  208. "WPATCH Failed",
  209. MB_ICONERROR | MB_SYSTEMMODAL);
  210. }
  211. rc = 2;
  212. goto bail;
  213. }
  214. rc = 0;
  215. bail:
  216. return(rc);
  217. }