windows-nt/Source/XPSP1/NT/base/ntsetup/win95upg/common/snapshot/snapshot.c
2020-09-26 16:20:57 +08:00

381 lines
9.9 KiB
C

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
snapshot.c
Abstract:
Implements a memdb-based snapshot of all files, directories, registry keys and
registry values.
Author:
Jim Schmidt (jimschm) 13-Mar-1998
Revision History:
<alias> <date> <comments>
--*/
#include "pch.h"
#define S_SNAPSHOT_A "Snapshot"
BOOL
pGetFullKeyA (
IN OUT PSTR Object
)
{
MEMDB_ENUMA e;
CHAR Pattern[MEMDB_MAX];
PSTR p;
wsprintfA (Pattern, "%s*", Object);
if (MemDbEnumFirstValue (&e, Pattern, MEMDB_THIS_LEVEL_ONLY, MEMDB_ENDPOINTS_ONLY)) {
p = _mbsrchr (Object, TEXT('\\'));
if (p) {
p = _mbsinc (p);
} else {
p = Object;
}
StringCopyA (p, e.szName);
return TRUE;
} else {
return FALSE;
}
}
VOID
pSnapDirsA (
IN PCSTR Drive,
IN BOOL DiffMode,
IN HANDLE DiffHandle OPTIONAL
)
{
TREE_ENUMA FileEnum;
CHAR Node[MEMDB_MAX];
DWORD Value;
//
// Enumerate the file system
//
if (EnumFirstFileInTreeA (&FileEnum, Drive, NULL, TRUE)) {
do {
wsprintfA (
Node,
"%s\\%s\\%u\\%u%u",
S_SNAPSHOT_A,
FileEnum.FullPath,
FileEnum.FindData->nFileSizeLow,
FileEnum.FindData->ftLastWriteTime.dwHighDateTime,
FileEnum.FindData->ftLastWriteTime.dwLowDateTime
);
if (!DiffMode) {
MemDbSetValueA (Node, SNAP_RESULT_DELETED);
} else {
Value = SNAP_RESULT_UNCHANGED;
if (!MemDbGetValueA (Node, NULL)) {
if (DiffHandle) {
WriteFileStringA (DiffHandle, FileEnum.FullPath);
WriteFileStringA (DiffHandle, "\r\n");
}
wsprintfA (Node, "%s\\%s,", S_SNAPSHOT_A, FileEnum.FullPath);
Value = SNAP_RESULT_CHANGED;
if (!pGetFullKeyA (Node)) {
wsprintfA (
Node,
"%s\\%s\\%u\\%u%u",
S_SNAPSHOT_A,
FileEnum.FullPath,
FileEnum.FindData->nFileSizeLow,
FileEnum.FindData->ftLastWriteTime.dwHighDateTime,
FileEnum.FindData->ftLastWriteTime.dwLowDateTime
);
Value = SNAP_RESULT_ADDED;
}
}
MemDbSetValueA (Node, Value);
}
} while (EnumNextFileInTreeA (&FileEnum));
}
}
VOID
pSnapAllDrivesA (
IN BOOL DiffMode,
IN HANDLE DiffHandle OPTIONAL
)
{
CHAR Drives[256];
MULTISZ_ENUMA e;
if (GetLogicalDriveStringsA (256, Drives)) {
if (EnumFirstMultiSzA (&e, Drives)) {
do {
if (DRIVE_FIXED == GetDriveTypeA (e.CurrentString)) {
pSnapDirsA (e.CurrentString, DiffMode, DiffHandle);
break;
}
} while (EnumNextMultiSzA (&e));
}
}
}
VOID
pSnapRegistryHiveA (
IN PCSTR Hive,
IN BOOL DiffMode,
IN HANDLE DiffHandle OPTIONAL
)
{
REGTREE_ENUMA RegEnum;
REGVALUE_ENUMA RegValue;
CHAR Node[MEMDB_MAX];
PBYTE Data;
DWORD Checksum;
PBYTE p;
UINT Count;
DWORD Value;
if (EnumFirstRegKeyInTreeA (&RegEnum, Hive)) {
do {
wsprintfA (
Node,
"%s\\%s",
S_SNAPSHOT_A,
RegEnum.FullKeyName
);
if (!DiffMode) {
MemDbSetValueA (Node, SNAP_RESULT_DELETED);
} else {
if (!MemDbGetValueA (Node, NULL)) {
if (DiffHandle) {
WriteFileStringA (DiffHandle, RegEnum.FullKeyName);
WriteFileStringA (DiffHandle, "\r\n");
}
} else {
MemDbSetValueA (Node, SNAP_RESULT_UNCHANGED);
}
}
if (EnumFirstRegValueA (&RegValue, RegEnum.CurrentKey->KeyHandle)) {
do {
Data = GetRegValueData (RegValue.KeyHandle, RegValue.ValueName);
if (!Data) {
continue;
}
Checksum = RegValue.Type;
p = Data;
for (Count = 0 ; Count < RegValue.DataSize ; Count++) {
Checksum = (Checksum << 1) | (Checksum >> 31) | *p;
p++;
}
MemFree (g_hHeap, 0, Data);
wsprintfA (
Node,
"%s\\%s\\[%s],%u",
S_SNAPSHOT_A,
RegEnum.FullKeyName,
RegValue.ValueName,
Checksum
);
if (!DiffMode) {
MemDbSetValueA (Node, SNAP_RESULT_DELETED);
} else {
Value = SNAP_RESULT_UNCHANGED;
if (!MemDbGetValueA (Node, NULL)) {
WriteFileStringA (DiffHandle, RegEnum.FullKeyName);
WriteFileStringA (DiffHandle, " [");
WriteFileStringA (DiffHandle, RegValue.ValueName);
WriteFileStringA (DiffHandle, "]\r\n");
wsprintfA (
Node,
"%s\\%s\\[%s],",
S_SNAPSHOT_A,
RegEnum.FullKeyName,
RegValue.ValueName
);
Value = SNAP_RESULT_CHANGED;
if (!pGetFullKeyA (Node)) {
wsprintfA (
Node,
"%s\\%s\\[%s],%u",
S_SNAPSHOT_A,
RegEnum.FullKeyName,
RegValue.ValueName,
Checksum
);
Value = SNAP_RESULT_ADDED;
}
}
MemDbSetValueA (Node, Value);
}
} while (EnumNextRegValueA (&RegValue));
}
} while (EnumNextRegKeyInTreeA (&RegEnum));
}
}
VOID
pSnapRegistryA (
IN BOOL DiffMode,
IN HANDLE DiffHandle OPTIONAL
)
{
pSnapRegistryHiveA (TEXT("HKLM"), DiffMode, DiffHandle);
pSnapRegistryHiveA (TEXT("HKU"), DiffMode, DiffHandle);
}
VOID
TakeSnapShotEx (
IN DWORD SnapFlags
)
{
MemDbCreateTemporaryKeyA (S_SNAPSHOT_A);
if (SnapFlags & SNAP_FILES) {
pSnapAllDrivesA (FALSE, NULL);
}
if (SnapFlags & SNAP_REGISTRY) {
pSnapRegistryA (FALSE, NULL);
}
}
BOOL
GenerateDiffOutputExA (
IN PCSTR FileName,
IN PCSTR Comment, OPTIONAL
IN BOOL Append,
IN DWORD SnapFlags
)
{
HANDLE File = NULL;
MEMDB_ENUMA e;
if (FileName) {
File = CreateFileA (
FileName,
GENERIC_WRITE,
0,
NULL,
Append ? OPEN_ALWAYS : CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (File == INVALID_HANDLE_VALUE) {
DEBUGMSG ((DBG_ERROR, "Can't open %s for output", FileName));
return FALSE;
}
if (Append) {
SetFilePointer (File, 0, NULL, FILE_END);
}
if (Comment) {
WriteFileStringA (File, Comment);
WriteFileStringA (File, "\r\n");
}
WriteFileStringA (File, "Changes:\r\n");
}
if (SnapFlags & SNAP_FILES) {
pSnapAllDrivesA (TRUE, File);
}
if (SnapFlags & SNAP_REGISTRY) {
pSnapRegistryA (TRUE, File);
}
if (File) {
WriteFileStringA (File, "\r\nDeleted Settings:\r\n");
if (MemDbGetValueExA (&e, S_SNAPSHOT_A, NULL, NULL)) {
do {
if (e.dwValue == SNAP_RESULT_DELETED) {
WriteFileStringA (File, e.szName);
WriteFileStringA (File, "\r\n");
}
} while (MemDbEnumNextValue (&e));
}
WriteFileStringA (File, "\r\nEnd.\r\n\r\n");
CloseHandle (File);
}
return TRUE;
}
BOOL
EnumFirstSnapFileA (
IN OUT PSNAP_FILE_ENUMA e,
IN PCSTR FilePattern, OPTIONAL
IN DWORD SnapStatus
)
{
CHAR node[MEMDB_MAX];
e->FilePattern = FilePattern;
e->SnapStatus = SnapStatus;
e->FirstCall = TRUE;
MemDbBuildKeyA (node, S_SNAPSHOT_A, "*", NULL, NULL);
if (!MemDbEnumFirstValue (&(e->mEnum), node, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
return FALSE;
}
return EnumNextSnapFileA (e);
}
BOOL
EnumNextSnapFileA (
IN OUT PSNAP_FILE_ENUMA e
)
{
PSTR lastWack;
while (e->FirstCall?(e->FirstCall = FALSE, TRUE):MemDbEnumNextValue (&(e->mEnum))) {
StringCopyA (e->FileName, e->mEnum.szName);
lastWack = _mbsrchr (e->FileName, '\\');
if (lastWack) {
*lastWack = 0;
lastWack = _mbsrchr (e->FileName, '\\');
if (lastWack) {
*lastWack = 0;
}
}
if (e->FilePattern && (!IsPatternMatch (e->FilePattern, e->FileName))) {
continue;
}
if ((e->SnapStatus & e->mEnum.dwValue) == 0) {
continue;
}
return TRUE;
}
return FALSE;
}