mirror of https://github.com/lianthony/NT4.0
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.
376 lines
8.8 KiB
376 lines
8.8 KiB
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// Define thread parameters that get passed to the drive snapshot thread
|
|
// (ThreadSnapDrives()).
|
|
//
|
|
typedef struct _SNAPDRIVES_THREAD_PARAMS {
|
|
//
|
|
// Name of output file
|
|
//
|
|
WCHAR OutputFile[MAX_PATH];
|
|
//
|
|
// Receives number of bytes written into output file
|
|
//
|
|
DWORD BytesWritten;
|
|
|
|
} SNAPDRIVES_THREAD_PARAMS, *PSNAPDRIVES_THREAD_PARAMS;
|
|
|
|
//
|
|
// Define thread parameters that get passed to the registry snapshot thread
|
|
// (ThreadSnapRegistry()).
|
|
//
|
|
typedef struct _SNAPREG_THREAD_PARAMS {
|
|
//
|
|
// Name of output file
|
|
//
|
|
WCHAR OutputFile[MAX_PATH];
|
|
//
|
|
// Receives number of bytes written into output file
|
|
//
|
|
DWORD BytesWritten;
|
|
//
|
|
// Thread handle of the drive snapshotter thread.
|
|
// The registry snapshotter thread resumes that thread after it
|
|
// has added all of its temp files to the file exclude list.
|
|
//
|
|
HANDLE DrivesThread;
|
|
|
|
} SNAPREG_THREAD_PARAMS, *PSNAPREG_THREAD_PARAMS;
|
|
|
|
|
|
DWORD
|
|
ThreadSnapDrives(
|
|
IN PVOID ThreadParam
|
|
)
|
|
{
|
|
PSNAPDRIVES_THREAD_PARAMS Params = ThreadParam;
|
|
DWORD d;
|
|
|
|
d = SnapshotDrives(Params->OutputFile,&Params->BytesWritten);
|
|
|
|
//
|
|
// This kills the ini file snapshot thread.
|
|
//
|
|
QueueIniFile(NULL);
|
|
|
|
return(d);
|
|
}
|
|
|
|
|
|
DWORD
|
|
ThreadSnapRegistry(
|
|
IN PVOID ThreadParam
|
|
)
|
|
{
|
|
PSNAPREG_THREAD_PARAMS Params = ThreadParam;
|
|
DWORD d;
|
|
|
|
d = SnapshotRegistry(Params->OutputFile,&Params->BytesWritten,Params->DrivesThread);
|
|
|
|
return(d);
|
|
}
|
|
|
|
|
|
DWORD
|
|
SnapshotSystem(
|
|
IN PCWSTR OutputFile
|
|
)
|
|
{
|
|
SNAPDRIVES_THREAD_PARAMS DrivesThreadParams;
|
|
SNAPREG_THREAD_PARAMS RegThreadParams;
|
|
HANDLE Threads[3];
|
|
WCHAR IniFileSnapOutFile[MAX_PATH];
|
|
DWORD DontCare;
|
|
DWORD rc;
|
|
WCHAR Path[MAX_PATH];
|
|
PWCHAR p;
|
|
SYSDIFF_FILE FileHeader;
|
|
HANDLE hFile;
|
|
HANDLE LogFile;
|
|
HANDLE IniSnapThreadHandle;
|
|
WIN32_FIND_DATA FindData;
|
|
DWORD junk;
|
|
HWND Billboard = NULL;
|
|
|
|
//
|
|
// Create the log file. If this fails put up a message box but
|
|
// keep going.
|
|
//
|
|
if(CmdLineLogFile) {
|
|
|
|
LogFile = CreateFile(
|
|
CmdLineLogFile,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
|
|
NULL
|
|
);
|
|
|
|
if(LogFile == INVALID_HANDLE_VALUE) {
|
|
|
|
MessageOut(
|
|
MdiFrameWindow,
|
|
MSG_CANT_CREATE_LOG,
|
|
MB_OK | MB_APPLMODAL | MB_ICONEXCLAMATION,
|
|
CmdLineLogFile,
|
|
GetLastError()
|
|
);
|
|
|
|
LogFile = NULL;
|
|
} else {
|
|
if(UnicodeTextFiles) {
|
|
WriteUnicodeMark(LogFile);
|
|
}
|
|
}
|
|
} else {
|
|
LogFile = NULL;
|
|
}
|
|
|
|
//
|
|
// Create temporary filenames for the output of the subprocesses.
|
|
//
|
|
if(!GetFullPathName(OutputFile,MAX_PATH,Path,&p)) {
|
|
rc = GetLastError();
|
|
goto c0;
|
|
}
|
|
|
|
//
|
|
// Isolate the path part and get temp filenames for output.
|
|
//
|
|
*(--p) = 0;
|
|
if(!GetTempFileName(Path,L"SD",0,DrivesThreadParams.OutputFile)) {
|
|
rc = GetLastError();
|
|
goto c0;
|
|
}
|
|
if(!GetTempFileName(Path,L"SR",0,RegThreadParams.OutputFile)) {
|
|
rc = GetLastError();
|
|
goto c1;
|
|
}
|
|
|
|
if(!GetTempFileName(Path,L"SI",0,IniFileSnapOutFile)) {
|
|
rc = GetLastError();
|
|
goto c2;
|
|
}
|
|
|
|
rc = InitializeIniFileSnapOrDiff(IniFileSnapOutFile,&IniSnapThreadHandle, &junk);
|
|
if(rc != NO_ERROR) {
|
|
goto c3;
|
|
}
|
|
|
|
//
|
|
// Create threads to go off and do the work.
|
|
//
|
|
Threads[0] = CreateThread(
|
|
NULL,
|
|
0, // default initial stack size
|
|
ThreadSnapRegistry,
|
|
&RegThreadParams,
|
|
CREATE_SUSPENDED,
|
|
&DontCare
|
|
);
|
|
|
|
if(!Threads[0]) {
|
|
rc = GetLastError();
|
|
goto c4;
|
|
}
|
|
|
|
Threads[1] = CreateThread(
|
|
NULL,
|
|
0, // default initial stack size
|
|
ThreadSnapDrives,
|
|
&DrivesThreadParams,
|
|
CREATE_SUSPENDED,
|
|
&DontCare
|
|
);
|
|
|
|
|
|
if(!Threads[1]) {
|
|
Cancel = TRUE;
|
|
SetEvent(CancelEvent);
|
|
rc = GetLastError();
|
|
goto c5;
|
|
}
|
|
|
|
RegThreadParams.DrivesThread = Threads[1];
|
|
ResumeThread(Threads[0]);
|
|
|
|
Threads[2] = IniSnapThreadHandle;
|
|
|
|
//
|
|
// Wait for the threads to finish working.
|
|
//
|
|
WaitForMultipleObjects(
|
|
sizeof(Threads)/sizeof(Threads[0]),
|
|
Threads,
|
|
TRUE, // wait for all
|
|
INFINITE
|
|
);
|
|
|
|
//
|
|
// See if there was an error. Take the first one we encounter
|
|
// among the threads.
|
|
//
|
|
GetExitCodeThread(Threads[0],&rc);
|
|
if(rc == NO_ERROR) {
|
|
GetExitCodeThread(Threads[1],&rc);
|
|
if(rc == NO_ERROR) {
|
|
GetExitCodeThread(Threads[2],&rc);
|
|
}
|
|
}
|
|
|
|
if(rc != NO_ERROR) {
|
|
goto c6;
|
|
}
|
|
|
|
//
|
|
// Put up a billboard so the user knows not to exit.
|
|
//
|
|
Billboard = DisplayBillboard(MdiFrameWindow,MSG_WORKING);
|
|
|
|
//
|
|
// Get the size of the ini file snapshot output.
|
|
//
|
|
if(!FileExists(IniFileSnapOutFile,&FindData)) {
|
|
//
|
|
// Strange case.
|
|
//
|
|
rc = ERROR_INVALID_DATA;
|
|
goto c6;
|
|
}
|
|
|
|
//
|
|
// Create the output file, which consists of a small header
|
|
// followed by the 2 temporary files, appended together.
|
|
//
|
|
hFile = CreateFile(
|
|
OutputFile,
|
|
GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
|
|
if(hFile == INVALID_HANDLE_VALUE) {
|
|
rc = GetLastError();
|
|
goto c6;
|
|
}
|
|
|
|
ZeroMemory(&FileHeader,sizeof(SYSDIFF_FILE));
|
|
|
|
//
|
|
// Remember sysroot and user profile root.
|
|
//
|
|
GetWindowsDirectory(
|
|
FileHeader.Sysroot,
|
|
sizeof(FileHeader.Sysroot)/sizeof(FileHeader.Sysroot[0])
|
|
);
|
|
|
|
ExpandEnvironmentStrings(
|
|
L"%USERPROFILE%",
|
|
FileHeader.UserProfileRoot,
|
|
sizeof(FileHeader.UserProfileRoot)/sizeof(FileHeader.UserProfileRoot[0])
|
|
);
|
|
|
|
if(FileHeader.UserProfileRoot[0] == L'%') {
|
|
FileHeader.UserProfileRoot[0] = 0;
|
|
FileHeader.UserProfileRootSFN[0] = 0;
|
|
} else {
|
|
if(!GetShortPathName(FileHeader.UserProfileRoot,FileHeader.UserProfileRootSFN,MAX_PATH)) {
|
|
lstrcpy(FileHeader.UserProfileRootSFN,FileHeader.UserProfileRoot);
|
|
}
|
|
}
|
|
|
|
FileHeader.Signature = SYSDIFF_SIGNATURE;
|
|
FileHeader.Type = SysdiffModeSnap;
|
|
FileHeader.Version = SYSDIFF_VERSION;
|
|
FileHeader.TotalSize = sizeof(SYSDIFF_FILE)
|
|
+ DrivesThreadParams.BytesWritten
|
|
+ RegThreadParams.BytesWritten
|
|
+ FindData.nFileSizeLow;
|
|
|
|
FileHeader.u.Snapshot.RegistrySnapOffset = sizeof(SYSDIFF_FILE);
|
|
|
|
FileHeader.u.Snapshot.DirAndFileSnapOffset = sizeof(SYSDIFF_FILE)
|
|
+ RegThreadParams.BytesWritten;
|
|
|
|
FileHeader.u.Snapshot.IniFileSnapOffset = sizeof(SYSDIFF_FILE)
|
|
+ RegThreadParams.BytesWritten
|
|
+ DrivesThreadParams.BytesWritten;
|
|
|
|
if(!WriteFile(hFile,&FileHeader,sizeof(SYSDIFF_FILE),&DontCare,NULL)) {
|
|
rc= GetLastError();
|
|
goto c7;
|
|
}
|
|
|
|
rc = AppendFile(hFile,RegThreadParams.OutputFile,FALSE,&DontCare);
|
|
if(rc != NO_ERROR) {
|
|
goto c7;
|
|
}
|
|
|
|
rc = AppendFile(hFile,DrivesThreadParams.OutputFile,FALSE,&DontCare);
|
|
if(rc != NO_ERROR) {
|
|
goto c7;
|
|
}
|
|
|
|
rc = AppendFile(hFile,IniFileSnapOutFile,FALSE,&DontCare);
|
|
if(rc != NO_ERROR) {
|
|
goto c7;
|
|
}
|
|
|
|
//
|
|
// Success.
|
|
//
|
|
|
|
c7:
|
|
CloseHandle(hFile);
|
|
if(rc != NO_ERROR) {
|
|
DeleteFile(OutputFile);
|
|
}
|
|
c6:
|
|
CloseHandle(Threads[1]);
|
|
c5:
|
|
CloseHandle(Threads[0]);
|
|
c4:
|
|
CloseHandle(IniSnapThreadHandle);
|
|
c3:
|
|
DeleteFile(IniFileSnapOutFile);
|
|
c2:
|
|
DeleteFile(RegThreadParams.OutputFile);
|
|
c1:
|
|
DeleteFile(DrivesThreadParams.OutputFile);
|
|
c0:
|
|
if(LogFile) {
|
|
DumpStatusLogWindowsToFile(LogFile);
|
|
CloseHandle(LogFile);
|
|
}
|
|
|
|
KillBillboard(Billboard);
|
|
|
|
if(rc == NO_ERROR) {
|
|
|
|
MessageAndLog(
|
|
MdiFrameWindow,
|
|
LogFile,
|
|
MSG_SNAPSHOT_SUCCESS,
|
|
MB_OK | MB_TASKMODAL | MB_ICONINFORMATION,
|
|
OutputFile
|
|
);
|
|
|
|
} else {
|
|
|
|
MessageAndLog(
|
|
MdiFrameWindow,
|
|
LogFile,
|
|
MSG_SNAPSHOT_FAILED,
|
|
MB_OK | MB_TASKMODAL | MB_ICONERROR,
|
|
rc
|
|
);
|
|
}
|
|
return(rc);
|
|
}
|