967 lines
29 KiB
C
967 lines
29 KiB
C
|
#include <nt.h> // For shutdown privilege.
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include "getbin.h"
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <conio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <locale.h>
|
||
|
#include <process.h>
|
||
|
#include <windows.h>
|
||
|
|
||
|
#define MV_FLAGS (MOVEFILE_REPLACE_EXISTING | MOVEFILE_DELAY_UNTIL_REBOOT)
|
||
|
|
||
|
#define CCH_BUF 512
|
||
|
#define RES_DLGOPTIONS 1
|
||
|
|
||
|
#define VerbosePrintf if (gbVerbose) printf
|
||
|
|
||
|
char *gszVERSION = "16.1";
|
||
|
INT_PTR CALLBACK OptionsDlgProc (HWND, UINT, WPARAM, LPARAM);
|
||
|
|
||
|
|
||
|
CONST CHAR szDEFSAVEEXT[] = "lst";
|
||
|
CONST CHAR szSAVEEXT[] = "SaveExtension";
|
||
|
CONST CHAR szDEFCOPYEXT[] = "dll";
|
||
|
CONST CHAR szJUNKEXT[] = "yuk";
|
||
|
CONST CHAR szDEST[] = "Dest";
|
||
|
CONST CHAR szSYMS[] = "Symbols";
|
||
|
CONST CHAR szSOURCE[] = "Source";
|
||
|
CONST CHAR szSYSTEM32[] = "SYSTEM32";
|
||
|
CONST CHAR szSYMBOLS[] = "SYMBOLS";
|
||
|
CONST CHAR szGETBIN[] = "Getbin";
|
||
|
CONST CHAR szGETBINDIR[] = "GetbinSourceDir";
|
||
|
CONST CHAR szWINDIR[] = "windir";
|
||
|
|
||
|
CHAR szTRYRENAME[] = "TryRename";
|
||
|
CHAR szTRYCOPY[] = "TryCopy";
|
||
|
CHAR szPOLL[] = "Poll";
|
||
|
CHAR szREBOOT[] = "Reboot";
|
||
|
CHAR szSAVEPREVIOUS[] = "SavePrevious";
|
||
|
CHAR szRESTORECMD[] = "Restore.Cmd";
|
||
|
CHAR szCOPYDBGTOO[] = "CopyDbgToo";
|
||
|
CHAR szCOPYSOURCETYPE[] = "CopySourceType";
|
||
|
|
||
|
BOOL gbTryRename = TRUE;
|
||
|
BOOL gbDelayCopy = FALSE;
|
||
|
BOOL gbTryCopy = TRUE;
|
||
|
BOOL gbPoll = FALSE;
|
||
|
BOOL gbVerbose = FALSE;
|
||
|
BOOL gbReboot = FALSE;
|
||
|
BOOL gbSavePrevious = FALSE;
|
||
|
BOOL gbRestoreCmd = FALSE;
|
||
|
BOOL gbCopyDbgToo = FALSE;
|
||
|
BOOL gbForceTempCopy = FALSE;
|
||
|
HANDLE ghRestoreCmd = NULL; // file handle for Restore.Cmd
|
||
|
|
||
|
BOOL giCopySourceType = IDD_COPY_COMMAND;
|
||
|
|
||
|
CHAR gszDestDir[CCH_BUF]; // typically "c:\winnt\system32"
|
||
|
CHAR gszDriverDestDir[CCH_BUF+8]; // typically "c:\winnt\system32\drivers"
|
||
|
CHAR gszSymsDir[CCH_BUF];
|
||
|
CHAR gszSourceDir[CCH_BUF];
|
||
|
CHAR gszWinDir[CCH_BUF];
|
||
|
CHAR gszSaveExtension[4];
|
||
|
CHAR gszCopyExtension[4];
|
||
|
|
||
|
#define GB_FILE_ITSELF 0
|
||
|
#define GB_ASSOCIATED_DBG_FILE 1
|
||
|
#define GB_ASSOCIATED_PDB_FILE 2
|
||
|
|
||
|
BOOL DoGetbin(LPSTR szFileName, DWORD dwAssociatedFile);
|
||
|
|
||
|
void PrintUsage(void) {
|
||
|
printf("Getbin version %s\n", gszVERSION);
|
||
|
printf("usage: getbin [-c] [-d] [-D] [-l] [-r] [-t] [-w] <filename> [[-w] <filename>]...\n");
|
||
|
printf(" -c create Restore.Cmd\n");
|
||
|
printf(" -d delay copy until reboot\n");
|
||
|
printf(" -D copy DBG/PDB files too\n");
|
||
|
printf(" -l copy old file to *.lst\n");
|
||
|
printf(" -w <filename> : wait for <filename> to be updated\n");
|
||
|
printf(" -r reboot after copy\n");
|
||
|
printf(" -t copy when date of src is newer\n");
|
||
|
printf(" -T Force temp copy when using -d\n");
|
||
|
printf(" -v old-style verbose output\n");
|
||
|
printf("usage: getbin -o\n");
|
||
|
printf(" GUI biset options\n");
|
||
|
|
||
|
}
|
||
|
|
||
|
int __cdecl main (int argc, char *argv[])
|
||
|
{
|
||
|
DWORD dwRet;
|
||
|
int iArg = 1;
|
||
|
int nFiles = 0;
|
||
|
UINT Codepage;
|
||
|
char achCodepage[6] = ".OCP";
|
||
|
|
||
|
|
||
|
if (argc <= 1) {
|
||
|
PrintUsage();
|
||
|
ActivateKeyboardLayout((HKL)(HKL_NEXT), KLF_SETFORPROCESS);
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* This is mainly here as a good example of how to set a character-mode
|
||
|
* application's codepage.
|
||
|
* This affects C-runtime routines such as mbtowc(), mbstowcs(), wctomb(),
|
||
|
* wcstombs(), mblen(), _mbstrlen(), isprint(), isalpha() etc.
|
||
|
* To make sure these C-runtimes come from msvcrt.dll, use TARGETLIBS in
|
||
|
* the sources file, together with TARGETTYPE=PROGRAM (and not UMAPPL?)
|
||
|
*/
|
||
|
if (Codepage = GetConsoleOutputCP()) {
|
||
|
sprintf(achCodepage, ".%3.4d", Codepage);
|
||
|
}
|
||
|
setlocale(LC_ALL, achCodepage);
|
||
|
|
||
|
/*
|
||
|
* chcp to a different codepage and test what isalpha() determines.
|
||
|
* cp437:d0 is not a char (Box Drawings Up Double And Horizontal Single)
|
||
|
* cp850:d0 is a char (Latin Small Letter Eth)
|
||
|
* cp852:d0 is a char (Latin Small Letter D With Stroke)
|
||
|
* cp1251:d0 is a char (Cyrillic Capital Letter Er)
|
||
|
* cp1252:d0 is a char (Latin Capital Letter Eth)
|
||
|
*/
|
||
|
isalpha(0xd0);
|
||
|
|
||
|
dwRet = GetEnvironmentVariable( szWINDIR, gszWinDir, sizeof(gszWinDir)/sizeof(gszWinDir[0]));
|
||
|
if (!dwRet) {
|
||
|
gszWinDir[0] = '\0';
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Get the defaults
|
||
|
*
|
||
|
* Destination Directory
|
||
|
*/
|
||
|
if (GetProfileString(szGETBIN, szDEST, "", gszDestDir, sizeof(gszDestDir)) < 2) {
|
||
|
if (gszWinDir[0] == '\0') {
|
||
|
printf("Getbin: can not read environment string %s.\n", szWINDIR);
|
||
|
exit(0);
|
||
|
}
|
||
|
sprintf(gszDestDir, "%s\\%s", gszWinDir, szSYSTEM32);
|
||
|
}
|
||
|
_strupr(gszDestDir);
|
||
|
strcpy(gszDriverDestDir, gszDestDir);
|
||
|
strcat(gszDriverDestDir, "\\drivers");
|
||
|
|
||
|
if (GetProfileString(szGETBIN, szSYMS, "", gszSymsDir, sizeof(gszSymsDir)) < 2) {
|
||
|
if (szWINDIR[0] == '\0') {
|
||
|
printf("Getbin: can not read environment string %s.\n", szWINDIR);
|
||
|
exit(0);
|
||
|
}
|
||
|
sprintf(gszSymsDir, "%s\\%s", gszWinDir, szSYMBOLS);
|
||
|
}
|
||
|
_strupr(gszSymsDir);
|
||
|
|
||
|
GetProfileString(szGETBIN, szSOURCE, "", gszSourceDir, sizeof(gszSourceDir));
|
||
|
|
||
|
gbTryRename = GetProfileInt(szGETBIN, szTRYRENAME, gbTryRename);
|
||
|
gbTryCopy = GetProfileInt(szGETBIN, szTRYCOPY, gbTryCopy);
|
||
|
gbPoll = GetProfileInt(szGETBIN, szPOLL, gbPoll);
|
||
|
gbReboot = GetProfileInt(szGETBIN, szREBOOT, gbReboot);
|
||
|
gbSavePrevious = GetProfileInt(szGETBIN, szSAVEPREVIOUS, gbSavePrevious);
|
||
|
gbRestoreCmd = GetProfileInt(szGETBIN, szRESTORECMD, gbRestoreCmd);
|
||
|
if (gbRestoreCmd) {
|
||
|
gbSavePrevious = TRUE;
|
||
|
}
|
||
|
|
||
|
gbCopyDbgToo = GetProfileInt(szGETBIN, szCOPYDBGTOO, gbCopyDbgToo);
|
||
|
giCopySourceType = GetProfileInt(szGETBIN, szCOPYSOURCETYPE, giCopySourceType);
|
||
|
GetProfileString(szGETBIN, szSAVEEXT, szDEFSAVEEXT, gszSaveExtension, sizeof(gszSaveExtension));
|
||
|
|
||
|
/*
|
||
|
* Compute the flags
|
||
|
*/
|
||
|
|
||
|
// printf("argc %lX %s %s %s\n", argc, argv[0], argv[1], argv[2] );
|
||
|
for (iArg=1; iArg<argc; iArg++) {
|
||
|
if (argv[iArg][0] == '-') {
|
||
|
switch (argv[iArg][1]) {
|
||
|
case 'c':
|
||
|
gbRestoreCmd = TRUE;
|
||
|
// need to save the previous files then!
|
||
|
gbSavePrevious = TRUE;
|
||
|
break;
|
||
|
case 'D':
|
||
|
gbCopyDbgToo = TRUE;
|
||
|
break;
|
||
|
case 'd':
|
||
|
gbDelayCopy = TRUE;
|
||
|
break;
|
||
|
case 'r':
|
||
|
gbReboot = TRUE;
|
||
|
break;
|
||
|
case 'l':
|
||
|
gbSavePrevious = TRUE;
|
||
|
break;
|
||
|
case 't':
|
||
|
giCopySourceType; //!!!
|
||
|
break;
|
||
|
case 'T':
|
||
|
gbForceTempCopy = TRUE;
|
||
|
break;
|
||
|
case 'o':
|
||
|
DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(RES_DLGOPTIONS), NULL, OptionsDlgProc);
|
||
|
return 1;
|
||
|
break;
|
||
|
case 'v':
|
||
|
gbVerbose = TRUE;
|
||
|
break;
|
||
|
case 'w':
|
||
|
gbPoll = TRUE;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
printf("ERROR: Invalid flag %c\n", argv[iArg][1]);
|
||
|
case '?':
|
||
|
PrintUsage();
|
||
|
exit(0);
|
||
|
break;
|
||
|
}
|
||
|
} else {
|
||
|
if (!DoGetbin(argv[iArg], GB_FILE_ITSELF)) {
|
||
|
gbReboot = FALSE;
|
||
|
} else if (gbCopyDbgToo) {
|
||
|
// got the binary, so now get the DBG & PDB file
|
||
|
BOOL bGotDbg, bGotPdb;
|
||
|
|
||
|
bGotDbg = DoGetbin(argv[iArg], GB_ASSOCIATED_DBG_FILE);
|
||
|
bGotPdb = DoGetbin(argv[iArg], GB_ASSOCIATED_PDB_FILE);
|
||
|
if (!bGotDbg && !bGotPdb) {
|
||
|
// if we didn't get either, then fail to reboot.
|
||
|
gbReboot = FALSE;
|
||
|
}
|
||
|
}
|
||
|
nFiles++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (nFiles == 0) {
|
||
|
printf("ERROR: No files specified\n");
|
||
|
PrintUsage();
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Reboot if requested
|
||
|
*/
|
||
|
if (gbReboot) {
|
||
|
BOOLEAN PreviousPriv;
|
||
|
|
||
|
printf("\nRebooting system\n");
|
||
|
Sleep(5000);
|
||
|
RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &PreviousPriv);
|
||
|
ExitWindowsEx(EWX_FORCE|EWX_REBOOT, 0);
|
||
|
}
|
||
|
|
||
|
CloseHandle(ghRestoreCmd);
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
#define ENTER 0x0d
|
||
|
|
||
|
BOOL fConfirm(char *pszQuestion)
|
||
|
{
|
||
|
int ch, chLast;
|
||
|
|
||
|
chLast = 0;
|
||
|
printf ("%s [yn] ", pszQuestion);
|
||
|
while ( TRUE ) {
|
||
|
|
||
|
ch = _getch();
|
||
|
ch = tolower( ch );
|
||
|
|
||
|
if (ch == ENTER && (chLast == 'y' || chLast == 'n')) {
|
||
|
putchar('\n');
|
||
|
return (chLast == 'y');
|
||
|
}
|
||
|
|
||
|
if (ch != 0) {
|
||
|
if (ch == 'y' || ch == 'n') {
|
||
|
putchar(ch);
|
||
|
putchar('\b');
|
||
|
}
|
||
|
}
|
||
|
chLast = ch;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#define F_TIME 0x01
|
||
|
#define F_DATE 0x02
|
||
|
|
||
|
LPWSTR DateTimeString(
|
||
|
CONST FILETIME *pft,
|
||
|
DWORD Flags)
|
||
|
{
|
||
|
SYSTEMTIME DateTime;
|
||
|
FILETIME LocalFileTime;
|
||
|
static WCHAR wszDateTime[80];
|
||
|
int cch;
|
||
|
|
||
|
FileTimeToLocalFileTime(pft, &LocalFileTime);
|
||
|
FileTimeToSystemTime(&LocalFileTime, &DateTime);
|
||
|
|
||
|
if (Flags == 0) {
|
||
|
Flags = F_TIME;
|
||
|
}
|
||
|
if (Flags & F_DATE) {
|
||
|
cch = GetDateFormatW(LOCALE_USER_DEFAULT,
|
||
|
LOCALE_NOUSEROVERRIDE,
|
||
|
&DateTime,
|
||
|
NULL,
|
||
|
wszDateTime,
|
||
|
sizeof(wszDateTime)/sizeof(wszDateTime[0]) - 1);
|
||
|
wszDateTime[cch-1] = '\t';
|
||
|
} else {
|
||
|
cch = 0;
|
||
|
}
|
||
|
|
||
|
if (Flags & F_TIME) {
|
||
|
GetTimeFormatW(LOCALE_USER_DEFAULT,
|
||
|
LOCALE_NOUSEROVERRIDE,
|
||
|
&DateTime,
|
||
|
NULL,
|
||
|
&wszDateTime[cch],
|
||
|
sizeof(wszDateTime)/sizeof(wszDateTime[0]) - cch);
|
||
|
}
|
||
|
return wszDateTime;
|
||
|
}
|
||
|
|
||
|
DWORD PrintFileSize(
|
||
|
CONST LPSTR pszFile)
|
||
|
{
|
||
|
HANDLE hFindNext;
|
||
|
WIN32_FIND_DATA FindFileData;
|
||
|
|
||
|
hFindNext = FindFirstFile(pszFile, &FindFileData);
|
||
|
if (hFindNext != INVALID_HANDLE_VALUE) {
|
||
|
FindClose(hFindNext);
|
||
|
}
|
||
|
printf("Size %ld\n", FindFileData.nFileSizeLow);
|
||
|
return FindFileData.nFileSizeLow;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Poll for a file, returns TRUE when the file is ready to be fetched, FALSE if not
|
||
|
*/
|
||
|
BOOL PollForFile(
|
||
|
CONST LPSTR szSrc,
|
||
|
CONST LPSTR szDest,
|
||
|
CONST LPSTR szSourceFile) // just for re-printing the name when !gbVerbose
|
||
|
{
|
||
|
FILETIME ftLastWriteSrc = {0, 0};
|
||
|
FILETIME ftLastWriteDest = {0, 0};
|
||
|
HANDLE hFindNext;
|
||
|
WIN32_FIND_DATA FindFileData;
|
||
|
FILETIME ft;
|
||
|
SYSTEMTIME DateTime;
|
||
|
OFSTRUCT OpenBuff;
|
||
|
|
||
|
/*
|
||
|
* Get last write time of destination (ftLastWriteDest)
|
||
|
*/
|
||
|
hFindNext = FindFirstFile(szDest, &FindFileData);
|
||
|
if (hFindNext != INVALID_HANDLE_VALUE) {
|
||
|
FindClose(hFindNext);
|
||
|
ftLastWriteDest = FindFileData.ftLastWriteTime;
|
||
|
printf("\n Time of destination = %ws\n",
|
||
|
DateTimeString(&ftLastWriteDest, F_DATE|F_TIME));
|
||
|
} else {
|
||
|
printf("Can't find destination %s\n", szDest);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Give the user a chance to pull down the current source if it is already
|
||
|
* more recent than the destination.
|
||
|
* If they want an even more recent source, Wait until the source file
|
||
|
* starts getting updated.
|
||
|
*/
|
||
|
while (TRUE) {
|
||
|
hFindNext = FindFirstFile(szSrc, &FindFileData);
|
||
|
if (hFindNext != INVALID_HANDLE_VALUE) {
|
||
|
FindClose(hFindNext);
|
||
|
if ((ftLastWriteSrc.dwHighDateTime | ftLastWriteSrc.dwLowDateTime) == 0) {
|
||
|
ftLastWriteSrc = FindFileData.ftLastWriteTime;
|
||
|
printf(" Time of source = %ws\n",
|
||
|
DateTimeString(&ftLastWriteSrc, F_DATE|F_TIME));
|
||
|
if (CompareFileTime(&ftLastWriteSrc, &ftLastWriteDest) > 0) {
|
||
|
// Source is more recent!
|
||
|
if (fConfirm(" Source is more recent, fetch it now?")) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
printf(" Polling for a new %s", szSrc);
|
||
|
fflush(stdout);
|
||
|
} else {
|
||
|
if (CompareFileTime(&FindFileData.ftLastWriteTime, &ftLastWriteSrc) > 0) {
|
||
|
// it got updated!
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
/*
|
||
|
* Source not there yet, we want to grab it as soon as it is ready
|
||
|
*/
|
||
|
ftLastWriteSrc.dwLowDateTime = 1;
|
||
|
}
|
||
|
printf(".");
|
||
|
Sleep(1000);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* The source is being written, so wait until the write stops
|
||
|
* (When the write has finished, we will be able to open it exclusively)
|
||
|
*/
|
||
|
do {
|
||
|
HANDLE hTmp;
|
||
|
#ifdef DBG_POLL
|
||
|
/*
|
||
|
* This debug stuff show if & how the source file's timestamps & size
|
||
|
* vary each time we go around the loop.
|
||
|
*/
|
||
|
DWORD dwSizeH, dwSizeL;
|
||
|
FILETIME ftC, ftA, ftW;
|
||
|
ftC = FindFileData.ftCreationTime;
|
||
|
ftA = FindFileData.ftLastAccessTime;
|
||
|
ftW = FindFileData.ftLastWriteTime;
|
||
|
dwSizeH = FindFileData.nFileSizeHigh;
|
||
|
dwSizeL = FindFileData.nFileSizeLow;
|
||
|
|
||
|
hFindNext = FindFirstFile(szSrc, &FindFileData);
|
||
|
if (hFindNext == INVALID_HANDLE_VALUE) {
|
||
|
break;
|
||
|
}
|
||
|
FindClose(hFindNext);
|
||
|
|
||
|
/*
|
||
|
* Some debug output each time we see that the src file has
|
||
|
* changed size or timestamps.
|
||
|
*/
|
||
|
if ((CompareFileTime(&ftA, &FindFileData.ftLastAccessTime) != 0) ||
|
||
|
(CompareFileTime(&ftW, &FindFileData.ftLastWriteTime) != 0) ||
|
||
|
(CompareFileTime(&ftC, &FindFileData.ftCreationTime) != 0) ||
|
||
|
(dwSizeH != FindFileData.nFileSizeHigh) ||
|
||
|
(dwSizeL != FindFileData.nFileSizeLow)) {
|
||
|
printf("Create %ws ",
|
||
|
DateTimeString(&FindFileData.ftCreationTime, F_TIME));
|
||
|
printf("Access %ws ",
|
||
|
DateTimeString(&FindFileData.ftLastAccessTime, F_TIME));
|
||
|
ft = FindFileData.ftLastWriteTime;
|
||
|
printf("Write %ws ", DateTimeString(&ft, F_TIME));
|
||
|
printf("Size %ld\n", dwSizeL);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
* If we can open the file for writing, no other process has it open
|
||
|
*/
|
||
|
hTmp = CreateFileA(
|
||
|
szSrc,
|
||
|
GENERIC_READ | GENERIC_WRITE, // write access
|
||
|
0, // no sharing
|
||
|
NULL, // no Security Attributes
|
||
|
OPEN_EXISTING, // of course
|
||
|
FILE_ATTRIBUTE_NORMAL | // whatever
|
||
|
FILE_FLAG_NO_BUFFERING, // why not?
|
||
|
NULL); // no template
|
||
|
if (hTmp != INVALID_HANDLE_VALUE) {
|
||
|
CloseHandle(hTmp);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* If the share is read-only, the trick above won't work so we wait
|
||
|
* for 1 second and then take it.
|
||
|
*/
|
||
|
if (GetLastError() == ERROR_ACCESS_DENIED) {
|
||
|
int i;
|
||
|
printf("\n %s is read-only, delay 5 seconds", szSrc);
|
||
|
fflush(stdout);
|
||
|
for (i = 0; i < 5; i++) {
|
||
|
Sleep(1000);
|
||
|
printf(".");
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
printf("+");
|
||
|
Sleep(500);
|
||
|
} while (TRUE);
|
||
|
|
||
|
/*
|
||
|
* One last delay (for splitsym etc.)
|
||
|
*/
|
||
|
Sleep(500);
|
||
|
|
||
|
/*
|
||
|
* Find out how big the file is now, just for the heck of it.
|
||
|
*/
|
||
|
hFindNext = FindFirstFile(szSrc, &FindFileData);
|
||
|
if (hFindNext != INVALID_HANDLE_VALUE) {
|
||
|
FindClose(hFindNext);
|
||
|
}
|
||
|
VerbosePrintf(" Size %ld\n", FindFileData.nFileSizeLow);
|
||
|
if (!gbVerbose) {
|
||
|
printf("\n%s", szSourceFile);
|
||
|
fflush(stdout);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL DoGetbin(
|
||
|
LPSTR szFileName,
|
||
|
DWORD dwAssociatedFile)
|
||
|
{
|
||
|
BOOL bNetDrive = FALSE;
|
||
|
BOOL bRet;
|
||
|
BOOL bSkipDebugFiles = FALSE;
|
||
|
DWORD dwRet;
|
||
|
CHAR szDest[CCH_BUF]; // !! to go
|
||
|
CHAR szTempFile[CCH_BUF];
|
||
|
CHAR szSrc[CCH_BUF];
|
||
|
CHAR szBackup[CCH_BUF];
|
||
|
CHAR szSourceFile[CCH_BUF];
|
||
|
CHAR szExt[10];
|
||
|
PCHAR pszSrc = szSrc;
|
||
|
PCHAR pszDot;
|
||
|
WIN32_FIND_DATA FindFileData;
|
||
|
|
||
|
/*
|
||
|
* Get the source and destination files
|
||
|
*/
|
||
|
strcpy( szSourceFile, szFileName );
|
||
|
|
||
|
/*
|
||
|
* Add the default extension if no extension of this file
|
||
|
*/
|
||
|
pszDot = strrchr(szSourceFile, '.');
|
||
|
if (pszDot == NULL) {
|
||
|
pszDot = szSourceFile + strlen(szSourceFile);
|
||
|
*pszDot = '.';
|
||
|
strcpy( pszDot+1, szDEFCOPYEXT);
|
||
|
}
|
||
|
strcpy( szExt, pszDot+1);
|
||
|
|
||
|
if ((_stricmp(szSourceFile, "win32k.sys") == 0) ||
|
||
|
(_stricmp(szSourceFile, "user.exe") == 0)) {
|
||
|
bSkipDebugFiles = TRUE;
|
||
|
}
|
||
|
|
||
|
switch (dwAssociatedFile) {
|
||
|
case GB_ASSOCIATED_DBG_FILE:
|
||
|
strcpy(pszDot+1, "dbg");
|
||
|
sprintf(szDest, "%s\\%s\\%s", gszSymsDir, szExt, szSourceFile);
|
||
|
sprintf(szSrc, "%s\\symbols\\retail\\%s\\%s", gszSourceDir, szExt, szSourceFile);
|
||
|
break;
|
||
|
|
||
|
case GB_ASSOCIATED_PDB_FILE:
|
||
|
strcpy(pszDot+1, "pdb");
|
||
|
sprintf(szDest, "%s\\%s\\%s", gszSymsDir, szExt, szSourceFile);
|
||
|
sprintf(szSrc, "%s\\symbols\\retail\\%s\\%s", gszSourceDir, szExt, szSourceFile);
|
||
|
break;
|
||
|
|
||
|
case GB_FILE_ITSELF:
|
||
|
if ((_stricmp(szExt, "sys") == 0) && !bSkipDebugFiles) {
|
||
|
// seems like it's a driver, but not win32k.sys
|
||
|
sprintf(szDest, "%s\\%s", gszDriverDestDir, szSourceFile);
|
||
|
} else {
|
||
|
sprintf(szDest, "%s\\%s", gszDestDir, szSourceFile);
|
||
|
}
|
||
|
sprintf(szSrc, "%s\\%s", gszSourceDir, szSourceFile);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
printf("Internal error in Getbin() - bad dwAssociatedFile %d\n",
|
||
|
dwAssociatedFile);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Source -> Dest
|
||
|
*/
|
||
|
if (gbVerbose) {
|
||
|
printf("%s -> %s", szSrc, szDest);
|
||
|
} else {
|
||
|
printf("%s", szSourceFile);
|
||
|
}
|
||
|
fflush(stdout);
|
||
|
|
||
|
if ((bSkipDebugFiles) && (dwAssociatedFile != GB_FILE_ITSELF)) {
|
||
|
if (gbVerbose) {
|
||
|
VerbosePrintf(" not copying %s\n", szSourceFile);
|
||
|
return TRUE;
|
||
|
} else {
|
||
|
printf(" Skipped\n");
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Backup the original if requested
|
||
|
*/
|
||
|
if (gbSavePrevious) {
|
||
|
PCHAR pch;
|
||
|
|
||
|
strcpy(szBackup, szDest);
|
||
|
// find LAST dot
|
||
|
pch = strrchr(szBackup, '.');
|
||
|
pch++;
|
||
|
|
||
|
strcpy(pch, gszSaveExtension);
|
||
|
|
||
|
if (pch) {
|
||
|
bRet = CopyFile(szDest, szBackup, FALSE);
|
||
|
if (!bRet) {
|
||
|
dwRet = GetLastError();
|
||
|
if (dwRet == ERROR_FILE_NOT_FOUND) {
|
||
|
if (gbVerbose) {
|
||
|
printf("\n No existing file to back up, continuing anyway\n");
|
||
|
} else {
|
||
|
printf(" [Can't backup]");
|
||
|
}
|
||
|
} else {
|
||
|
printf("\n Unable to make backup copy %ld\n", dwRet);
|
||
|
|
||
|
// don't worry about failing to back up DBG/PDB files
|
||
|
if (dwAssociatedFile == GB_FILE_ITSELF) {
|
||
|
printf("\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
if (gbVerbose) {
|
||
|
printf("\n Backed up to: %s", szBackup);
|
||
|
} else {
|
||
|
printf(" [Backed up]", szBackup);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
fflush(stdout);
|
||
|
}
|
||
|
|
||
|
|
||
|
if (gbDelayCopy) {
|
||
|
gbTryCopy = FALSE;
|
||
|
gbTryRename = FALSE;
|
||
|
}
|
||
|
|
||
|
if (gbPoll) {
|
||
|
PollForFile(szSrc, szDest, szSourceFile);
|
||
|
gbPoll = FALSE;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Try a regular copy
|
||
|
*/
|
||
|
if (gbTryCopy) {
|
||
|
VerbosePrintf("\n Try Reg copy... ");
|
||
|
fflush(stdout);
|
||
|
TryCopy:
|
||
|
|
||
|
bRet = CopyFile(szSrc, szDest, FALSE);
|
||
|
|
||
|
if (bRet) {
|
||
|
if (gbVerbose) {
|
||
|
PrintFileSize(szSrc);
|
||
|
printf("\n ==== Succeeded ====\n");
|
||
|
} else {
|
||
|
printf(" COPIED\n");
|
||
|
}
|
||
|
return TRUE;
|
||
|
} else {
|
||
|
dwRet = GetLastError();
|
||
|
|
||
|
switch (dwRet) {
|
||
|
case ERROR_FILE_NOT_FOUND:
|
||
|
printf(" ERROR: File not found\n");
|
||
|
return FALSE;
|
||
|
|
||
|
case ERROR_ACCESS_DENIED:
|
||
|
case ERROR_SHARING_VIOLATION:
|
||
|
// Need to do delay copy
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
printf("\n ERROR: CopyFile(%s, %s, FALSE) Failed %ld\n",
|
||
|
szSrc, szDest, dwRet);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Try a rename copy
|
||
|
*/
|
||
|
if (gbTryRename) {
|
||
|
VerbosePrintf(" Try Rename");
|
||
|
bRet = MoveFileEx(szDest, szJUNKEXT, MOVEFILE_REPLACE_EXISTING);
|
||
|
if (bRet) {
|
||
|
if (!gbVerbose) {
|
||
|
printf("[Renamed]");
|
||
|
}
|
||
|
fflush(stdout);
|
||
|
gbTryRename = FALSE;
|
||
|
goto TryCopy;
|
||
|
} else {
|
||
|
VerbosePrintf("\n");
|
||
|
dwRet = GetLastError();
|
||
|
|
||
|
switch (dwRet) {
|
||
|
case ERROR_FILE_NOT_FOUND:
|
||
|
printf(" ERROR: File not found\n");
|
||
|
return FALSE;
|
||
|
|
||
|
case ERROR_ACCESS_DENIED:
|
||
|
case ERROR_SHARING_VIOLATION:
|
||
|
// Need to do delay copy
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
printf("\n ERROR: Rename: MoveFileEx(%s, %s, MOVEFILE_REPLACE_EXISTING) failed %d\n",
|
||
|
szDest, szJUNKEXT, dwRet);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VerbosePrintf("\n Trying delayed copy... ");
|
||
|
if (_strnicmp(szFileName, "ntoskrnl", 8) == 0) {
|
||
|
printf("\n"
|
||
|
" ===================== WARNING =====================\n");
|
||
|
printf(" !Delayed copy of ntoskrnl.exe requires TWO reboots!\n");
|
||
|
printf(" ===================================================\n");
|
||
|
}
|
||
|
|
||
|
if (!gbForceTempCopy) {
|
||
|
/*
|
||
|
* Determine source drive type
|
||
|
*/
|
||
|
if (szSrc[0] == '\\' && szSrc[0] == '\\') {
|
||
|
bNetDrive = TRUE;
|
||
|
} else if (szSrc[1] == ':') {
|
||
|
CHAR szRoot[5];
|
||
|
|
||
|
szRoot[0] = szSrc[0];
|
||
|
szRoot[1] = ':';
|
||
|
szRoot[1] = '\\';
|
||
|
|
||
|
if (GetDriveType(szRoot) == DRIVE_REMOTE)
|
||
|
bNetDrive = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* If the source is a network path then copy it locally to temp file
|
||
|
*/
|
||
|
if (gbForceTempCopy || bNetDrive) {
|
||
|
// if (!GetTempPath(sizeof(szTempPath)/sizeof(szTempPath[0]), szTempPath)) {
|
||
|
// printf("ERROR; GetTempPath Failed %ld\n", GetLastError());
|
||
|
// return FALSE;
|
||
|
// }
|
||
|
|
||
|
if (!GetTempFileName(gszDestDir, "upd", 0, szTempFile)) {
|
||
|
printf("ERROR; GetTempFileName Failed %ld\n", GetLastError());
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
bRet = CopyFile(szSrc, szTempFile, FALSE);
|
||
|
if (!bRet) {
|
||
|
dwRet = GetLastError();
|
||
|
|
||
|
switch (dwRet) {
|
||
|
case ERROR_FILE_NOT_FOUND:
|
||
|
printf(" ERROR: File not found\n");
|
||
|
return FALSE;
|
||
|
|
||
|
default:
|
||
|
printf("\n ERROR: CopyFile(%s, %s, FALSE) failed %ld\n",
|
||
|
szSrc, szTempFile, dwRet);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
pszSrc = szTempFile;
|
||
|
VerbosePrintf(" (temp file: %s)\n", pszSrc);
|
||
|
}
|
||
|
|
||
|
bRet = MoveFileEx(pszSrc, szDest, MV_FLAGS);
|
||
|
|
||
|
if (bRet) {
|
||
|
if (gbVerbose) {
|
||
|
printf(" ==== Succeeded ==== (file will be copied during reboot)\n");
|
||
|
} else {
|
||
|
printf(" COPIED\n");
|
||
|
}
|
||
|
} else {
|
||
|
printf("\n ERROR: MoveFileEx(%s, %s, 0x%x) failed %ld\n",
|
||
|
pszSrc, szDest, MV_FLAGS, GetLastError());
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Create the Restore.Cmd file if requested.
|
||
|
*/
|
||
|
if (gbRestoreCmd) {
|
||
|
char szBuff[CCH_BUF * 2];
|
||
|
DWORD nb, nbWritten;
|
||
|
|
||
|
if (ghRestoreCmd == NULL) {
|
||
|
sprintf(szBuff, "%s\\%s", gszWinDir, szRESTORECMD);
|
||
|
ghRestoreCmd = CreateFile(szBuff, GENERIC_WRITE, 0,
|
||
|
(LPSECURITY_ATTRIBUTES)NULL, CREATE_ALWAYS,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
(HANDLE)NULL);
|
||
|
if (ghRestoreCmd == INVALID_HANDLE_VALUE) {
|
||
|
printf("ERROR: Create file failed: %ld\n", GetLastError());
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
nb = sprintf(szBuff, "del %s\nmv %s %s\n", szDest, szBackup, szDest);
|
||
|
bRet = WriteFile(ghRestoreCmd, szBuff, nb, &nbWritten, NULL);
|
||
|
if (!bRet) {
|
||
|
printf(" ERROR: WriteFile failed %ld\n", GetLastError());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
INT_PTR CALLBACK OptionsDlgProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
CHAR szNew[CCH_BUF];
|
||
|
BOOL fRet;
|
||
|
|
||
|
switch (msg) {
|
||
|
case WM_INITDIALOG:
|
||
|
SendDlgItemMessage( hDlg, IDD_DEST, WM_SETTEXT, 0, (LPARAM)gszDestDir);
|
||
|
SetDlgItemText( hDlg, IDD_SOURCE, gszSourceDir);
|
||
|
SetDlgItemText( hDlg, IDD_SYMS, gszSymsDir);
|
||
|
|
||
|
if (gbTryRename)
|
||
|
CheckDlgButton( hDlg, IDD_RENAME, TRUE);
|
||
|
if (gbTryCopy)
|
||
|
CheckDlgButton( hDlg, IDD_REG_COPY, TRUE);
|
||
|
if (gbPoll)
|
||
|
CheckDlgButton( hDlg, IDD_POLL, TRUE);
|
||
|
if (gbReboot)
|
||
|
CheckDlgButton( hDlg, IDD_REBOOT, TRUE);
|
||
|
|
||
|
CheckDlgButton( hDlg, giCopySourceType, TRUE);
|
||
|
|
||
|
SetDlgItemText( hDlg, IDD_SAVEEXTENSION, gszSaveExtension);
|
||
|
SetDlgItemText( hDlg, IDD_COPYEXTENSION, szDEFCOPYEXT);
|
||
|
if (gbSavePrevious) {
|
||
|
if (gbRestoreCmd) {
|
||
|
CheckDlgButton( hDlg, IDD_RESTORECMD, TRUE);
|
||
|
}
|
||
|
CheckDlgButton( hDlg, IDD_SAVEPREVIOUS, TRUE);
|
||
|
} else {
|
||
|
EnableWindow( GetDlgItem( hDlg, IDD_SAVEEXTENSION), FALSE);
|
||
|
CheckDlgButton( hDlg, IDD_RESTORECMD, FALSE);
|
||
|
EnableWindow( GetDlgItem( hDlg, IDD_RESTORECMD), FALSE);
|
||
|
gbRestoreCmd = FALSE;
|
||
|
}
|
||
|
if (gbCopyDbgToo) {
|
||
|
CheckDlgButton( hDlg, IDD_DBGTOO, TRUE);
|
||
|
}
|
||
|
SendDlgItemMessage( hDlg, IDD_SAVEEXTENSION, EM_LIMITTEXT, sizeof(gszSaveExtension)-1, 0);
|
||
|
SendDlgItemMessage( hDlg, IDD_COPYEXTENSION, EM_LIMITTEXT, sizeof(gszCopyExtension)-1, 0);
|
||
|
|
||
|
break;
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
|
||
|
switch (LOWORD(wParam)) {
|
||
|
CHAR szString[8];
|
||
|
|
||
|
case IDOK:
|
||
|
|
||
|
// Write out the new defaults
|
||
|
if (GetDlgItemText(hDlg, IDD_SOURCE, szNew, sizeof(szNew))) {
|
||
|
_strupr(szNew);
|
||
|
WriteProfileString(szGETBIN, szSOURCE, szNew);
|
||
|
}
|
||
|
|
||
|
if (GetDlgItemText(hDlg, IDD_DEST, szNew, sizeof(szNew))) {
|
||
|
_strupr(szNew);
|
||
|
WriteProfileString(szGETBIN, szDEST, szNew);
|
||
|
}
|
||
|
|
||
|
if (GetDlgItemText(hDlg, IDD_SYMS, szNew, sizeof(szNew))) {
|
||
|
_strupr(szNew);
|
||
|
WriteProfileString(szGETBIN, szSYMS, szNew);
|
||
|
}
|
||
|
|
||
|
fRet = IsDlgButtonChecked( hDlg, IDD_RENAME);
|
||
|
WriteProfileString(szGETBIN, szTRYRENAME, fRet ? "1" : "0");
|
||
|
|
||
|
fRet = IsDlgButtonChecked( hDlg, IDD_REG_COPY);
|
||
|
WriteProfileString(szGETBIN, szTRYCOPY, fRet ? "1" : "0");
|
||
|
|
||
|
fRet = IsDlgButtonChecked( hDlg, IDD_POLL);
|
||
|
WriteProfileString(szGETBIN, szPOLL, fRet ? "1" : "0");
|
||
|
|
||
|
fRet = IsDlgButtonChecked( hDlg, IDD_REBOOT);
|
||
|
WriteProfileString(szGETBIN, szREBOOT, fRet ? "1" : "0");
|
||
|
|
||
|
fRet = IsDlgButtonChecked( hDlg, IDD_SAVEPREVIOUS);
|
||
|
WriteProfileString(szGETBIN, szSAVEPREVIOUS, fRet ? "1" : "0");
|
||
|
if (fRet && GetDlgItemText(hDlg, IDD_SAVEEXTENSION, szNew, sizeof(szNew))) {
|
||
|
_strupr(szNew);
|
||
|
WriteProfileString(szGETBIN, szSAVEEXT, szNew);
|
||
|
}
|
||
|
|
||
|
fRet = IsDlgButtonChecked( hDlg, IDD_RESTORECMD);
|
||
|
WriteProfileString(szGETBIN, szRESTORECMD, fRet ? "1" : "0");
|
||
|
|
||
|
|
||
|
fRet = IsDlgButtonChecked( hDlg, IDD_DBGTOO);
|
||
|
WriteProfileString(szGETBIN, szCOPYDBGTOO, fRet ? "1" : "0");
|
||
|
|
||
|
|
||
|
if (IsDlgButtonChecked( hDlg, IDD_COPY_DATE)) {
|
||
|
giCopySourceType = IDD_COPY_DATE;
|
||
|
} else if (IsDlgButtonChecked( hDlg, IDD_COPY_LIST)) {
|
||
|
giCopySourceType = IDD_COPY_LIST;
|
||
|
} else {
|
||
|
giCopySourceType = IDD_COPY_COMMAND;
|
||
|
}
|
||
|
|
||
|
_itoa(giCopySourceType, szString, 10);
|
||
|
WriteProfileString(szGETBIN, szCOPYSOURCETYPE, szString);
|
||
|
|
||
|
// FALL THROUGH!
|
||
|
|
||
|
case IDCANCEL:
|
||
|
EndDialog(hDlg, FALSE);
|
||
|
break;
|
||
|
|
||
|
case IDD_SAVEPREVIOUS:
|
||
|
if (HIWORD(wParam) == BN_CLICKED) {
|
||
|
fRet = IsDlgButtonChecked( hDlg, IDD_SAVEPREVIOUS);
|
||
|
EnableWindow( GetDlgItem( hDlg, IDD_SAVEEXTENSION), fRet);
|
||
|
|
||
|
if (!fRet) {
|
||
|
CheckDlgButton( hDlg, IDD_RESTORECMD, FALSE);
|
||
|
}
|
||
|
EnableWindow( GetDlgItem( hDlg, IDD_RESTORECMD), fRet);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return (FALSE);
|
||
|
}
|
||
|
break;
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|