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.

966 lines
29 KiB

  1. #include <nt.h> // For shutdown privilege.
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include <windows.h>
  5. #include "getbin.h"
  6. #include <stdio.h>
  7. #include <conio.h>
  8. #include <stdlib.h>
  9. #include <locale.h>
  10. #include <process.h>
  11. #include <windows.h>
  12. #define MV_FLAGS (MOVEFILE_REPLACE_EXISTING | MOVEFILE_DELAY_UNTIL_REBOOT)
  13. #define CCH_BUF 512
  14. #define RES_DLGOPTIONS 1
  15. #define VerbosePrintf if (gbVerbose) printf
  16. char *gszVERSION = "16.1";
  17. INT_PTR CALLBACK OptionsDlgProc (HWND, UINT, WPARAM, LPARAM);
  18. CONST CHAR szDEFSAVEEXT[] = "lst";
  19. CONST CHAR szSAVEEXT[] = "SaveExtension";
  20. CONST CHAR szDEFCOPYEXT[] = "dll";
  21. CONST CHAR szJUNKEXT[] = "yuk";
  22. CONST CHAR szDEST[] = "Dest";
  23. CONST CHAR szSYMS[] = "Symbols";
  24. CONST CHAR szSOURCE[] = "Source";
  25. CONST CHAR szSYSTEM32[] = "SYSTEM32";
  26. CONST CHAR szSYMBOLS[] = "SYMBOLS";
  27. CONST CHAR szGETBIN[] = "Getbin";
  28. CONST CHAR szGETBINDIR[] = "GetbinSourceDir";
  29. CONST CHAR szWINDIR[] = "windir";
  30. CHAR szTRYRENAME[] = "TryRename";
  31. CHAR szTRYCOPY[] = "TryCopy";
  32. CHAR szPOLL[] = "Poll";
  33. CHAR szREBOOT[] = "Reboot";
  34. CHAR szSAVEPREVIOUS[] = "SavePrevious";
  35. CHAR szRESTORECMD[] = "Restore.Cmd";
  36. CHAR szCOPYDBGTOO[] = "CopyDbgToo";
  37. CHAR szCOPYSOURCETYPE[] = "CopySourceType";
  38. BOOL gbTryRename = TRUE;
  39. BOOL gbDelayCopy = FALSE;
  40. BOOL gbTryCopy = TRUE;
  41. BOOL gbPoll = FALSE;
  42. BOOL gbVerbose = FALSE;
  43. BOOL gbReboot = FALSE;
  44. BOOL gbSavePrevious = FALSE;
  45. BOOL gbRestoreCmd = FALSE;
  46. BOOL gbCopyDbgToo = FALSE;
  47. BOOL gbForceTempCopy = FALSE;
  48. HANDLE ghRestoreCmd = NULL; // file handle for Restore.Cmd
  49. BOOL giCopySourceType = IDD_COPY_COMMAND;
  50. CHAR gszDestDir[CCH_BUF]; // typically "c:\winnt\system32"
  51. CHAR gszDriverDestDir[CCH_BUF+8]; // typically "c:\winnt\system32\drivers"
  52. CHAR gszSymsDir[CCH_BUF];
  53. CHAR gszSourceDir[CCH_BUF];
  54. CHAR gszWinDir[CCH_BUF];
  55. CHAR gszSaveExtension[4];
  56. CHAR gszCopyExtension[4];
  57. #define GB_FILE_ITSELF 0
  58. #define GB_ASSOCIATED_DBG_FILE 1
  59. #define GB_ASSOCIATED_PDB_FILE 2
  60. BOOL DoGetbin(LPSTR szFileName, DWORD dwAssociatedFile);
  61. void PrintUsage(void) {
  62. printf("Getbin version %s\n", gszVERSION);
  63. printf("usage: getbin [-c] [-d] [-D] [-l] [-r] [-t] [-w] <filename> [[-w] <filename>]...\n");
  64. printf(" -c create Restore.Cmd\n");
  65. printf(" -d delay copy until reboot\n");
  66. printf(" -D copy DBG/PDB files too\n");
  67. printf(" -l copy old file to *.lst\n");
  68. printf(" -w <filename> : wait for <filename> to be updated\n");
  69. printf(" -r reboot after copy\n");
  70. printf(" -t copy when date of src is newer\n");
  71. printf(" -T Force temp copy when using -d\n");
  72. printf(" -v old-style verbose output\n");
  73. printf("usage: getbin -o\n");
  74. printf(" GUI biset options\n");
  75. }
  76. int __cdecl main (int argc, char *argv[])
  77. {
  78. DWORD dwRet;
  79. int iArg = 1;
  80. int nFiles = 0;
  81. UINT Codepage;
  82. char achCodepage[6] = ".OCP";
  83. if (argc <= 1) {
  84. PrintUsage();
  85. ActivateKeyboardLayout((HKL)(HKL_NEXT), KLF_SETFORPROCESS);
  86. exit(0);
  87. }
  88. /*
  89. * This is mainly here as a good example of how to set a character-mode
  90. * application's codepage.
  91. * This affects C-runtime routines such as mbtowc(), mbstowcs(), wctomb(),
  92. * wcstombs(), mblen(), _mbstrlen(), isprint(), isalpha() etc.
  93. * To make sure these C-runtimes come from msvcrt.dll, use TARGETLIBS in
  94. * the sources file, together with TARGETTYPE=PROGRAM (and not UMAPPL?)
  95. */
  96. if (Codepage = GetConsoleOutputCP()) {
  97. sprintf(achCodepage, ".%3.4d", Codepage);
  98. }
  99. setlocale(LC_ALL, achCodepage);
  100. /*
  101. * chcp to a different codepage and test what isalpha() determines.
  102. * cp437:d0 is not a char (Box Drawings Up Double And Horizontal Single)
  103. * cp850:d0 is a char (Latin Small Letter Eth)
  104. * cp852:d0 is a char (Latin Small Letter D With Stroke)
  105. * cp1251:d0 is a char (Cyrillic Capital Letter Er)
  106. * cp1252:d0 is a char (Latin Capital Letter Eth)
  107. */
  108. isalpha(0xd0);
  109. dwRet = GetEnvironmentVariable( szWINDIR, gszWinDir, sizeof(gszWinDir)/sizeof(gszWinDir[0]));
  110. if (!dwRet) {
  111. gszWinDir[0] = '\0';
  112. }
  113. /*
  114. * Get the defaults
  115. *
  116. * Destination Directory
  117. */
  118. if (GetProfileString(szGETBIN, szDEST, "", gszDestDir, sizeof(gszDestDir)) < 2) {
  119. if (gszWinDir[0] == '\0') {
  120. printf("Getbin: can not read environment string %s.\n", szWINDIR);
  121. exit(0);
  122. }
  123. sprintf(gszDestDir, "%s\\%s", gszWinDir, szSYSTEM32);
  124. }
  125. _strupr(gszDestDir);
  126. strcpy(gszDriverDestDir, gszDestDir);
  127. strcat(gszDriverDestDir, "\\drivers");
  128. if (GetProfileString(szGETBIN, szSYMS, "", gszSymsDir, sizeof(gszSymsDir)) < 2) {
  129. if (szWINDIR[0] == '\0') {
  130. printf("Getbin: can not read environment string %s.\n", szWINDIR);
  131. exit(0);
  132. }
  133. sprintf(gszSymsDir, "%s\\%s", gszWinDir, szSYMBOLS);
  134. }
  135. _strupr(gszSymsDir);
  136. GetProfileString(szGETBIN, szSOURCE, "", gszSourceDir, sizeof(gszSourceDir));
  137. gbTryRename = GetProfileInt(szGETBIN, szTRYRENAME, gbTryRename);
  138. gbTryCopy = GetProfileInt(szGETBIN, szTRYCOPY, gbTryCopy);
  139. gbPoll = GetProfileInt(szGETBIN, szPOLL, gbPoll);
  140. gbReboot = GetProfileInt(szGETBIN, szREBOOT, gbReboot);
  141. gbSavePrevious = GetProfileInt(szGETBIN, szSAVEPREVIOUS, gbSavePrevious);
  142. gbRestoreCmd = GetProfileInt(szGETBIN, szRESTORECMD, gbRestoreCmd);
  143. if (gbRestoreCmd) {
  144. gbSavePrevious = TRUE;
  145. }
  146. gbCopyDbgToo = GetProfileInt(szGETBIN, szCOPYDBGTOO, gbCopyDbgToo);
  147. giCopySourceType = GetProfileInt(szGETBIN, szCOPYSOURCETYPE, giCopySourceType);
  148. GetProfileString(szGETBIN, szSAVEEXT, szDEFSAVEEXT, gszSaveExtension, sizeof(gszSaveExtension));
  149. /*
  150. * Compute the flags
  151. */
  152. // printf("argc %lX %s %s %s\n", argc, argv[0], argv[1], argv[2] );
  153. for (iArg=1; iArg<argc; iArg++) {
  154. if (argv[iArg][0] == '-') {
  155. switch (argv[iArg][1]) {
  156. case 'c':
  157. gbRestoreCmd = TRUE;
  158. // need to save the previous files then!
  159. gbSavePrevious = TRUE;
  160. break;
  161. case 'D':
  162. gbCopyDbgToo = TRUE;
  163. break;
  164. case 'd':
  165. gbDelayCopy = TRUE;
  166. break;
  167. case 'r':
  168. gbReboot = TRUE;
  169. break;
  170. case 'l':
  171. gbSavePrevious = TRUE;
  172. break;
  173. case 't':
  174. giCopySourceType; //!!!
  175. break;
  176. case 'T':
  177. gbForceTempCopy = TRUE;
  178. break;
  179. case 'o':
  180. DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(RES_DLGOPTIONS), NULL, OptionsDlgProc);
  181. return 1;
  182. break;
  183. case 'v':
  184. gbVerbose = TRUE;
  185. break;
  186. case 'w':
  187. gbPoll = TRUE;
  188. break;
  189. default:
  190. printf("ERROR: Invalid flag %c\n", argv[iArg][1]);
  191. case '?':
  192. PrintUsage();
  193. exit(0);
  194. break;
  195. }
  196. } else {
  197. if (!DoGetbin(argv[iArg], GB_FILE_ITSELF)) {
  198. gbReboot = FALSE;
  199. } else if (gbCopyDbgToo) {
  200. // got the binary, so now get the DBG & PDB file
  201. BOOL bGotDbg, bGotPdb;
  202. bGotDbg = DoGetbin(argv[iArg], GB_ASSOCIATED_DBG_FILE);
  203. bGotPdb = DoGetbin(argv[iArg], GB_ASSOCIATED_PDB_FILE);
  204. if (!bGotDbg && !bGotPdb) {
  205. // if we didn't get either, then fail to reboot.
  206. gbReboot = FALSE;
  207. }
  208. }
  209. nFiles++;
  210. }
  211. }
  212. if (nFiles == 0) {
  213. printf("ERROR: No files specified\n");
  214. PrintUsage();
  215. exit(0);
  216. }
  217. /*
  218. * Reboot if requested
  219. */
  220. if (gbReboot) {
  221. BOOLEAN PreviousPriv;
  222. printf("\nRebooting system\n");
  223. Sleep(5000);
  224. RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &PreviousPriv);
  225. ExitWindowsEx(EWX_FORCE|EWX_REBOOT, 0);
  226. }
  227. CloseHandle(ghRestoreCmd);
  228. return 1;
  229. }
  230. #define ENTER 0x0d
  231. BOOL fConfirm(char *pszQuestion)
  232. {
  233. int ch, chLast;
  234. chLast = 0;
  235. printf ("%s [yn] ", pszQuestion);
  236. while ( TRUE ) {
  237. ch = _getch();
  238. ch = tolower( ch );
  239. if (ch == ENTER && (chLast == 'y' || chLast == 'n')) {
  240. putchar('\n');
  241. return (chLast == 'y');
  242. }
  243. if (ch != 0) {
  244. if (ch == 'y' || ch == 'n') {
  245. putchar(ch);
  246. putchar('\b');
  247. }
  248. }
  249. chLast = ch;
  250. }
  251. }
  252. #define F_TIME 0x01
  253. #define F_DATE 0x02
  254. LPWSTR DateTimeString(
  255. CONST FILETIME *pft,
  256. DWORD Flags)
  257. {
  258. SYSTEMTIME DateTime;
  259. FILETIME LocalFileTime;
  260. static WCHAR wszDateTime[80];
  261. int cch;
  262. FileTimeToLocalFileTime(pft, &LocalFileTime);
  263. FileTimeToSystemTime(&LocalFileTime, &DateTime);
  264. if (Flags == 0) {
  265. Flags = F_TIME;
  266. }
  267. if (Flags & F_DATE) {
  268. cch = GetDateFormatW(LOCALE_USER_DEFAULT,
  269. LOCALE_NOUSEROVERRIDE,
  270. &DateTime,
  271. NULL,
  272. wszDateTime,
  273. sizeof(wszDateTime)/sizeof(wszDateTime[0]) - 1);
  274. wszDateTime[cch-1] = '\t';
  275. } else {
  276. cch = 0;
  277. }
  278. if (Flags & F_TIME) {
  279. GetTimeFormatW(LOCALE_USER_DEFAULT,
  280. LOCALE_NOUSEROVERRIDE,
  281. &DateTime,
  282. NULL,
  283. &wszDateTime[cch],
  284. sizeof(wszDateTime)/sizeof(wszDateTime[0]) - cch);
  285. }
  286. return wszDateTime;
  287. }
  288. DWORD PrintFileSize(
  289. CONST LPSTR pszFile)
  290. {
  291. HANDLE hFindNext;
  292. WIN32_FIND_DATA FindFileData;
  293. hFindNext = FindFirstFile(pszFile, &FindFileData);
  294. if (hFindNext != INVALID_HANDLE_VALUE) {
  295. FindClose(hFindNext);
  296. }
  297. printf("Size %ld\n", FindFileData.nFileSizeLow);
  298. return FindFileData.nFileSizeLow;
  299. }
  300. /*
  301. * Poll for a file, returns TRUE when the file is ready to be fetched, FALSE if not
  302. */
  303. BOOL PollForFile(
  304. CONST LPSTR szSrc,
  305. CONST LPSTR szDest,
  306. CONST LPSTR szSourceFile) // just for re-printing the name when !gbVerbose
  307. {
  308. FILETIME ftLastWriteSrc = {0, 0};
  309. FILETIME ftLastWriteDest = {0, 0};
  310. HANDLE hFindNext;
  311. WIN32_FIND_DATA FindFileData;
  312. FILETIME ft;
  313. SYSTEMTIME DateTime;
  314. OFSTRUCT OpenBuff;
  315. /*
  316. * Get last write time of destination (ftLastWriteDest)
  317. */
  318. hFindNext = FindFirstFile(szDest, &FindFileData);
  319. if (hFindNext != INVALID_HANDLE_VALUE) {
  320. FindClose(hFindNext);
  321. ftLastWriteDest = FindFileData.ftLastWriteTime;
  322. printf("\n Time of destination = %ws\n",
  323. DateTimeString(&ftLastWriteDest, F_DATE|F_TIME));
  324. } else {
  325. printf("Can't find destination %s\n", szDest);
  326. }
  327. /*
  328. * Give the user a chance to pull down the current source if it is already
  329. * more recent than the destination.
  330. * If they want an even more recent source, Wait until the source file
  331. * starts getting updated.
  332. */
  333. while (TRUE) {
  334. hFindNext = FindFirstFile(szSrc, &FindFileData);
  335. if (hFindNext != INVALID_HANDLE_VALUE) {
  336. FindClose(hFindNext);
  337. if ((ftLastWriteSrc.dwHighDateTime | ftLastWriteSrc.dwLowDateTime) == 0) {
  338. ftLastWriteSrc = FindFileData.ftLastWriteTime;
  339. printf(" Time of source = %ws\n",
  340. DateTimeString(&ftLastWriteSrc, F_DATE|F_TIME));
  341. if (CompareFileTime(&ftLastWriteSrc, &ftLastWriteDest) > 0) {
  342. // Source is more recent!
  343. if (fConfirm(" Source is more recent, fetch it now?")) {
  344. return TRUE;
  345. }
  346. }
  347. printf(" Polling for a new %s", szSrc);
  348. fflush(stdout);
  349. } else {
  350. if (CompareFileTime(&FindFileData.ftLastWriteTime, &ftLastWriteSrc) > 0) {
  351. // it got updated!
  352. break;
  353. }
  354. }
  355. } else {
  356. /*
  357. * Source not there yet, we want to grab it as soon as it is ready
  358. */
  359. ftLastWriteSrc.dwLowDateTime = 1;
  360. }
  361. printf(".");
  362. Sleep(1000);
  363. }
  364. /*
  365. * The source is being written, so wait until the write stops
  366. * (When the write has finished, we will be able to open it exclusively)
  367. */
  368. do {
  369. HANDLE hTmp;
  370. #ifdef DBG_POLL
  371. /*
  372. * This debug stuff show if & how the source file's timestamps & size
  373. * vary each time we go around the loop.
  374. */
  375. DWORD dwSizeH, dwSizeL;
  376. FILETIME ftC, ftA, ftW;
  377. ftC = FindFileData.ftCreationTime;
  378. ftA = FindFileData.ftLastAccessTime;
  379. ftW = FindFileData.ftLastWriteTime;
  380. dwSizeH = FindFileData.nFileSizeHigh;
  381. dwSizeL = FindFileData.nFileSizeLow;
  382. hFindNext = FindFirstFile(szSrc, &FindFileData);
  383. if (hFindNext == INVALID_HANDLE_VALUE) {
  384. break;
  385. }
  386. FindClose(hFindNext);
  387. /*
  388. * Some debug output each time we see that the src file has
  389. * changed size or timestamps.
  390. */
  391. if ((CompareFileTime(&ftA, &FindFileData.ftLastAccessTime) != 0) ||
  392. (CompareFileTime(&ftW, &FindFileData.ftLastWriteTime) != 0) ||
  393. (CompareFileTime(&ftC, &FindFileData.ftCreationTime) != 0) ||
  394. (dwSizeH != FindFileData.nFileSizeHigh) ||
  395. (dwSizeL != FindFileData.nFileSizeLow)) {
  396. printf("Create %ws ",
  397. DateTimeString(&FindFileData.ftCreationTime, F_TIME));
  398. printf("Access %ws ",
  399. DateTimeString(&FindFileData.ftLastAccessTime, F_TIME));
  400. ft = FindFileData.ftLastWriteTime;
  401. printf("Write %ws ", DateTimeString(&ft, F_TIME));
  402. printf("Size %ld\n", dwSizeL);
  403. }
  404. #endif
  405. /*
  406. * If we can open the file for writing, no other process has it open
  407. */
  408. hTmp = CreateFileA(
  409. szSrc,
  410. GENERIC_READ | GENERIC_WRITE, // write access
  411. 0, // no sharing
  412. NULL, // no Security Attributes
  413. OPEN_EXISTING, // of course
  414. FILE_ATTRIBUTE_NORMAL | // whatever
  415. FILE_FLAG_NO_BUFFERING, // why not?
  416. NULL); // no template
  417. if (hTmp != INVALID_HANDLE_VALUE) {
  418. CloseHandle(hTmp);
  419. break;
  420. }
  421. /*
  422. * If the share is read-only, the trick above won't work so we wait
  423. * for 1 second and then take it.
  424. */
  425. if (GetLastError() == ERROR_ACCESS_DENIED) {
  426. int i;
  427. printf("\n %s is read-only, delay 5 seconds", szSrc);
  428. fflush(stdout);
  429. for (i = 0; i < 5; i++) {
  430. Sleep(1000);
  431. printf(".");
  432. }
  433. break;
  434. }
  435. printf("+");
  436. Sleep(500);
  437. } while (TRUE);
  438. /*
  439. * One last delay (for splitsym etc.)
  440. */
  441. Sleep(500);
  442. /*
  443. * Find out how big the file is now, just for the heck of it.
  444. */
  445. hFindNext = FindFirstFile(szSrc, &FindFileData);
  446. if (hFindNext != INVALID_HANDLE_VALUE) {
  447. FindClose(hFindNext);
  448. }
  449. VerbosePrintf(" Size %ld\n", FindFileData.nFileSizeLow);
  450. if (!gbVerbose) {
  451. printf("\n%s", szSourceFile);
  452. fflush(stdout);
  453. }
  454. return TRUE;
  455. }
  456. BOOL DoGetbin(
  457. LPSTR szFileName,
  458. DWORD dwAssociatedFile)
  459. {
  460. BOOL bNetDrive = FALSE;
  461. BOOL bRet;
  462. BOOL bSkipDebugFiles = FALSE;
  463. DWORD dwRet;
  464. CHAR szDest[CCH_BUF]; // !! to go
  465. CHAR szTempFile[CCH_BUF];
  466. CHAR szSrc[CCH_BUF];
  467. CHAR szBackup[CCH_BUF];
  468. CHAR szSourceFile[CCH_BUF];
  469. CHAR szExt[10];
  470. PCHAR pszSrc = szSrc;
  471. PCHAR pszDot;
  472. WIN32_FIND_DATA FindFileData;
  473. /*
  474. * Get the source and destination files
  475. */
  476. strcpy( szSourceFile, szFileName );
  477. /*
  478. * Add the default extension if no extension of this file
  479. */
  480. pszDot = strrchr(szSourceFile, '.');
  481. if (pszDot == NULL) {
  482. pszDot = szSourceFile + strlen(szSourceFile);
  483. *pszDot = '.';
  484. strcpy( pszDot+1, szDEFCOPYEXT);
  485. }
  486. strcpy( szExt, pszDot+1);
  487. if ((_stricmp(szSourceFile, "win32k.sys") == 0) ||
  488. (_stricmp(szSourceFile, "user.exe") == 0)) {
  489. bSkipDebugFiles = TRUE;
  490. }
  491. switch (dwAssociatedFile) {
  492. case GB_ASSOCIATED_DBG_FILE:
  493. strcpy(pszDot+1, "dbg");
  494. sprintf(szDest, "%s\\%s\\%s", gszSymsDir, szExt, szSourceFile);
  495. sprintf(szSrc, "%s\\symbols\\retail\\%s\\%s", gszSourceDir, szExt, szSourceFile);
  496. break;
  497. case GB_ASSOCIATED_PDB_FILE:
  498. strcpy(pszDot+1, "pdb");
  499. sprintf(szDest, "%s\\%s\\%s", gszSymsDir, szExt, szSourceFile);
  500. sprintf(szSrc, "%s\\symbols\\retail\\%s\\%s", gszSourceDir, szExt, szSourceFile);
  501. break;
  502. case GB_FILE_ITSELF:
  503. if ((_stricmp(szExt, "sys") == 0) && !bSkipDebugFiles) {
  504. // seems like it's a driver, but not win32k.sys
  505. sprintf(szDest, "%s\\%s", gszDriverDestDir, szSourceFile);
  506. } else {
  507. sprintf(szDest, "%s\\%s", gszDestDir, szSourceFile);
  508. }
  509. sprintf(szSrc, "%s\\%s", gszSourceDir, szSourceFile);
  510. break;
  511. default:
  512. printf("Internal error in Getbin() - bad dwAssociatedFile %d\n",
  513. dwAssociatedFile);
  514. return FALSE;
  515. }
  516. /*
  517. * Source -> Dest
  518. */
  519. if (gbVerbose) {
  520. printf("%s -> %s", szSrc, szDest);
  521. } else {
  522. printf("%s", szSourceFile);
  523. }
  524. fflush(stdout);
  525. if ((bSkipDebugFiles) && (dwAssociatedFile != GB_FILE_ITSELF)) {
  526. if (gbVerbose) {
  527. VerbosePrintf(" not copying %s\n", szSourceFile);
  528. return TRUE;
  529. } else {
  530. printf(" Skipped\n");
  531. return TRUE;
  532. }
  533. }
  534. /*
  535. * Backup the original if requested
  536. */
  537. if (gbSavePrevious) {
  538. PCHAR pch;
  539. strcpy(szBackup, szDest);
  540. // find LAST dot
  541. pch = strrchr(szBackup, '.');
  542. pch++;
  543. strcpy(pch, gszSaveExtension);
  544. if (pch) {
  545. bRet = CopyFile(szDest, szBackup, FALSE);
  546. if (!bRet) {
  547. dwRet = GetLastError();
  548. if (dwRet == ERROR_FILE_NOT_FOUND) {
  549. if (gbVerbose) {
  550. printf("\n No existing file to back up, continuing anyway\n");
  551. } else {
  552. printf(" [Can't backup]");
  553. }
  554. } else {
  555. printf("\n Unable to make backup copy %ld\n", dwRet);
  556. // don't worry about failing to back up DBG/PDB files
  557. if (dwAssociatedFile == GB_FILE_ITSELF) {
  558. printf("\n");
  559. return FALSE;
  560. }
  561. }
  562. } else {
  563. if (gbVerbose) {
  564. printf("\n Backed up to: %s", szBackup);
  565. } else {
  566. printf(" [Backed up]", szBackup);
  567. }
  568. }
  569. }
  570. fflush(stdout);
  571. }
  572. if (gbDelayCopy) {
  573. gbTryCopy = FALSE;
  574. gbTryRename = FALSE;
  575. }
  576. if (gbPoll) {
  577. PollForFile(szSrc, szDest, szSourceFile);
  578. gbPoll = FALSE;
  579. }
  580. /*
  581. * Try a regular copy
  582. */
  583. if (gbTryCopy) {
  584. VerbosePrintf("\n Try Reg copy... ");
  585. fflush(stdout);
  586. TryCopy:
  587. bRet = CopyFile(szSrc, szDest, FALSE);
  588. if (bRet) {
  589. if (gbVerbose) {
  590. PrintFileSize(szSrc);
  591. printf("\n ==== Succeeded ====\n");
  592. } else {
  593. printf(" COPIED\n");
  594. }
  595. return TRUE;
  596. } else {
  597. dwRet = GetLastError();
  598. switch (dwRet) {
  599. case ERROR_FILE_NOT_FOUND:
  600. printf(" ERROR: File not found\n");
  601. return FALSE;
  602. case ERROR_ACCESS_DENIED:
  603. case ERROR_SHARING_VIOLATION:
  604. // Need to do delay copy
  605. break;
  606. default:
  607. printf("\n ERROR: CopyFile(%s, %s, FALSE) Failed %ld\n",
  608. szSrc, szDest, dwRet);
  609. return FALSE;
  610. }
  611. }
  612. }
  613. /*
  614. * Try a rename copy
  615. */
  616. if (gbTryRename) {
  617. VerbosePrintf(" Try Rename");
  618. bRet = MoveFileEx(szDest, szJUNKEXT, MOVEFILE_REPLACE_EXISTING);
  619. if (bRet) {
  620. if (!gbVerbose) {
  621. printf("[Renamed]");
  622. }
  623. fflush(stdout);
  624. gbTryRename = FALSE;
  625. goto TryCopy;
  626. } else {
  627. VerbosePrintf("\n");
  628. dwRet = GetLastError();
  629. switch (dwRet) {
  630. case ERROR_FILE_NOT_FOUND:
  631. printf(" ERROR: File not found\n");
  632. return FALSE;
  633. case ERROR_ACCESS_DENIED:
  634. case ERROR_SHARING_VIOLATION:
  635. // Need to do delay copy
  636. break;
  637. default:
  638. printf("\n ERROR: Rename: MoveFileEx(%s, %s, MOVEFILE_REPLACE_EXISTING) failed %d\n",
  639. szDest, szJUNKEXT, dwRet);
  640. return FALSE;
  641. }
  642. }
  643. }
  644. VerbosePrintf("\n Trying delayed copy... ");
  645. if (_strnicmp(szFileName, "ntoskrnl", 8) == 0) {
  646. printf("\n"
  647. " ===================== WARNING =====================\n");
  648. printf(" !Delayed copy of ntoskrnl.exe requires TWO reboots!\n");
  649. printf(" ===================================================\n");
  650. }
  651. if (!gbForceTempCopy) {
  652. /*
  653. * Determine source drive type
  654. */
  655. if (szSrc[0] == '\\' && szSrc[0] == '\\') {
  656. bNetDrive = TRUE;
  657. } else if (szSrc[1] == ':') {
  658. CHAR szRoot[5];
  659. szRoot[0] = szSrc[0];
  660. szRoot[1] = ':';
  661. szRoot[1] = '\\';
  662. if (GetDriveType(szRoot) == DRIVE_REMOTE)
  663. bNetDrive = TRUE;
  664. }
  665. }
  666. /*
  667. * If the source is a network path then copy it locally to temp file
  668. */
  669. if (gbForceTempCopy || bNetDrive) {
  670. // if (!GetTempPath(sizeof(szTempPath)/sizeof(szTempPath[0]), szTempPath)) {
  671. // printf("ERROR; GetTempPath Failed %ld\n", GetLastError());
  672. // return FALSE;
  673. // }
  674. if (!GetTempFileName(gszDestDir, "upd", 0, szTempFile)) {
  675. printf("ERROR; GetTempFileName Failed %ld\n", GetLastError());
  676. return FALSE;
  677. }
  678. bRet = CopyFile(szSrc, szTempFile, FALSE);
  679. if (!bRet) {
  680. dwRet = GetLastError();
  681. switch (dwRet) {
  682. case ERROR_FILE_NOT_FOUND:
  683. printf(" ERROR: File not found\n");
  684. return FALSE;
  685. default:
  686. printf("\n ERROR: CopyFile(%s, %s, FALSE) failed %ld\n",
  687. szSrc, szTempFile, dwRet);
  688. return FALSE;
  689. }
  690. }
  691. pszSrc = szTempFile;
  692. VerbosePrintf(" (temp file: %s)\n", pszSrc);
  693. }
  694. bRet = MoveFileEx(pszSrc, szDest, MV_FLAGS);
  695. if (bRet) {
  696. if (gbVerbose) {
  697. printf(" ==== Succeeded ==== (file will be copied during reboot)\n");
  698. } else {
  699. printf(" COPIED\n");
  700. }
  701. } else {
  702. printf("\n ERROR: MoveFileEx(%s, %s, 0x%x) failed %ld\n",
  703. pszSrc, szDest, MV_FLAGS, GetLastError());
  704. return FALSE;
  705. }
  706. /*
  707. * Create the Restore.Cmd file if requested.
  708. */
  709. if (gbRestoreCmd) {
  710. char szBuff[CCH_BUF * 2];
  711. DWORD nb, nbWritten;
  712. if (ghRestoreCmd == NULL) {
  713. sprintf(szBuff, "%s\\%s", gszWinDir, szRESTORECMD);
  714. ghRestoreCmd = CreateFile(szBuff, GENERIC_WRITE, 0,
  715. (LPSECURITY_ATTRIBUTES)NULL, CREATE_ALWAYS,
  716. FILE_ATTRIBUTE_NORMAL,
  717. (HANDLE)NULL);
  718. if (ghRestoreCmd == INVALID_HANDLE_VALUE) {
  719. printf("ERROR: Create file failed: %ld\n", GetLastError());
  720. return FALSE;
  721. }
  722. }
  723. nb = sprintf(szBuff, "del %s\nmv %s %s\n", szDest, szBackup, szDest);
  724. bRet = WriteFile(ghRestoreCmd, szBuff, nb, &nbWritten, NULL);
  725. if (!bRet) {
  726. printf(" ERROR: WriteFile failed %ld\n", GetLastError());
  727. }
  728. }
  729. return bRet;
  730. }
  731. INT_PTR CALLBACK OptionsDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  732. {
  733. CHAR szNew[CCH_BUF];
  734. BOOL fRet;
  735. switch (msg) {
  736. case WM_INITDIALOG:
  737. SendDlgItemMessage( hDlg, IDD_DEST, WM_SETTEXT, 0, (LPARAM)gszDestDir);
  738. SetDlgItemText( hDlg, IDD_SOURCE, gszSourceDir);
  739. SetDlgItemText( hDlg, IDD_SYMS, gszSymsDir);
  740. if (gbTryRename)
  741. CheckDlgButton( hDlg, IDD_RENAME, TRUE);
  742. if (gbTryCopy)
  743. CheckDlgButton( hDlg, IDD_REG_COPY, TRUE);
  744. if (gbPoll)
  745. CheckDlgButton( hDlg, IDD_POLL, TRUE);
  746. if (gbReboot)
  747. CheckDlgButton( hDlg, IDD_REBOOT, TRUE);
  748. CheckDlgButton( hDlg, giCopySourceType, TRUE);
  749. SetDlgItemText( hDlg, IDD_SAVEEXTENSION, gszSaveExtension);
  750. SetDlgItemText( hDlg, IDD_COPYEXTENSION, szDEFCOPYEXT);
  751. if (gbSavePrevious) {
  752. if (gbRestoreCmd) {
  753. CheckDlgButton( hDlg, IDD_RESTORECMD, TRUE);
  754. }
  755. CheckDlgButton( hDlg, IDD_SAVEPREVIOUS, TRUE);
  756. } else {
  757. EnableWindow( GetDlgItem( hDlg, IDD_SAVEEXTENSION), FALSE);
  758. CheckDlgButton( hDlg, IDD_RESTORECMD, FALSE);
  759. EnableWindow( GetDlgItem( hDlg, IDD_RESTORECMD), FALSE);
  760. gbRestoreCmd = FALSE;
  761. }
  762. if (gbCopyDbgToo) {
  763. CheckDlgButton( hDlg, IDD_DBGTOO, TRUE);
  764. }
  765. SendDlgItemMessage( hDlg, IDD_SAVEEXTENSION, EM_LIMITTEXT, sizeof(gszSaveExtension)-1, 0);
  766. SendDlgItemMessage( hDlg, IDD_COPYEXTENSION, EM_LIMITTEXT, sizeof(gszCopyExtension)-1, 0);
  767. break;
  768. case WM_COMMAND:
  769. switch (LOWORD(wParam)) {
  770. CHAR szString[8];
  771. case IDOK:
  772. // Write out the new defaults
  773. if (GetDlgItemText(hDlg, IDD_SOURCE, szNew, sizeof(szNew))) {
  774. _strupr(szNew);
  775. WriteProfileString(szGETBIN, szSOURCE, szNew);
  776. }
  777. if (GetDlgItemText(hDlg, IDD_DEST, szNew, sizeof(szNew))) {
  778. _strupr(szNew);
  779. WriteProfileString(szGETBIN, szDEST, szNew);
  780. }
  781. if (GetDlgItemText(hDlg, IDD_SYMS, szNew, sizeof(szNew))) {
  782. _strupr(szNew);
  783. WriteProfileString(szGETBIN, szSYMS, szNew);
  784. }
  785. fRet = IsDlgButtonChecked( hDlg, IDD_RENAME);
  786. WriteProfileString(szGETBIN, szTRYRENAME, fRet ? "1" : "0");
  787. fRet = IsDlgButtonChecked( hDlg, IDD_REG_COPY);
  788. WriteProfileString(szGETBIN, szTRYCOPY, fRet ? "1" : "0");
  789. fRet = IsDlgButtonChecked( hDlg, IDD_POLL);
  790. WriteProfileString(szGETBIN, szPOLL, fRet ? "1" : "0");
  791. fRet = IsDlgButtonChecked( hDlg, IDD_REBOOT);
  792. WriteProfileString(szGETBIN, szREBOOT, fRet ? "1" : "0");
  793. fRet = IsDlgButtonChecked( hDlg, IDD_SAVEPREVIOUS);
  794. WriteProfileString(szGETBIN, szSAVEPREVIOUS, fRet ? "1" : "0");
  795. if (fRet && GetDlgItemText(hDlg, IDD_SAVEEXTENSION, szNew, sizeof(szNew))) {
  796. _strupr(szNew);
  797. WriteProfileString(szGETBIN, szSAVEEXT, szNew);
  798. }
  799. fRet = IsDlgButtonChecked( hDlg, IDD_RESTORECMD);
  800. WriteProfileString(szGETBIN, szRESTORECMD, fRet ? "1" : "0");
  801. fRet = IsDlgButtonChecked( hDlg, IDD_DBGTOO);
  802. WriteProfileString(szGETBIN, szCOPYDBGTOO, fRet ? "1" : "0");
  803. if (IsDlgButtonChecked( hDlg, IDD_COPY_DATE)) {
  804. giCopySourceType = IDD_COPY_DATE;
  805. } else if (IsDlgButtonChecked( hDlg, IDD_COPY_LIST)) {
  806. giCopySourceType = IDD_COPY_LIST;
  807. } else {
  808. giCopySourceType = IDD_COPY_COMMAND;
  809. }
  810. _itoa(giCopySourceType, szString, 10);
  811. WriteProfileString(szGETBIN, szCOPYSOURCETYPE, szString);
  812. // FALL THROUGH!
  813. case IDCANCEL:
  814. EndDialog(hDlg, FALSE);
  815. break;
  816. case IDD_SAVEPREVIOUS:
  817. if (HIWORD(wParam) == BN_CLICKED) {
  818. fRet = IsDlgButtonChecked( hDlg, IDD_SAVEPREVIOUS);
  819. EnableWindow( GetDlgItem( hDlg, IDD_SAVEEXTENSION), fRet);
  820. if (!fRet) {
  821. CheckDlgButton( hDlg, IDD_RESTORECMD, FALSE);
  822. }
  823. EnableWindow( GetDlgItem( hDlg, IDD_RESTORECMD), fRet);
  824. }
  825. break;
  826. default:
  827. return (FALSE);
  828. }
  829. break;
  830. break;
  831. }
  832. return FALSE;
  833. }