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.

380 lines
9.9 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. snapshot.c
  5. Abstract:
  6. Implements a memdb-based snapshot of all files, directories, registry keys and
  7. registry values.
  8. Author:
  9. Jim Schmidt (jimschm) 13-Mar-1998
  10. Revision History:
  11. <alias> <date> <comments>
  12. --*/
  13. #include "pch.h"
  14. #define S_SNAPSHOT_A "Snapshot"
  15. BOOL
  16. pGetFullKeyA (
  17. IN OUT PSTR Object
  18. )
  19. {
  20. MEMDB_ENUMA e;
  21. CHAR Pattern[MEMDB_MAX];
  22. PSTR p;
  23. wsprintfA (Pattern, "%s*", Object);
  24. if (MemDbEnumFirstValue (&e, Pattern, MEMDB_THIS_LEVEL_ONLY, MEMDB_ENDPOINTS_ONLY)) {
  25. p = _mbsrchr (Object, TEXT('\\'));
  26. if (p) {
  27. p = _mbsinc (p);
  28. } else {
  29. p = Object;
  30. }
  31. StringCopyA (p, e.szName);
  32. return TRUE;
  33. } else {
  34. return FALSE;
  35. }
  36. }
  37. VOID
  38. pSnapDirsA (
  39. IN PCSTR Drive,
  40. IN BOOL DiffMode,
  41. IN HANDLE DiffHandle OPTIONAL
  42. )
  43. {
  44. TREE_ENUMA FileEnum;
  45. CHAR Node[MEMDB_MAX];
  46. DWORD Value;
  47. //
  48. // Enumerate the file system
  49. //
  50. if (EnumFirstFileInTreeA (&FileEnum, Drive, NULL, TRUE)) {
  51. do {
  52. wsprintfA (
  53. Node,
  54. "%s\\%s\\%u\\%u%u",
  55. S_SNAPSHOT_A,
  56. FileEnum.FullPath,
  57. FileEnum.FindData->nFileSizeLow,
  58. FileEnum.FindData->ftLastWriteTime.dwHighDateTime,
  59. FileEnum.FindData->ftLastWriteTime.dwLowDateTime
  60. );
  61. if (!DiffMode) {
  62. MemDbSetValueA (Node, SNAP_RESULT_DELETED);
  63. } else {
  64. Value = SNAP_RESULT_UNCHANGED;
  65. if (!MemDbGetValueA (Node, NULL)) {
  66. if (DiffHandle) {
  67. WriteFileStringA (DiffHandle, FileEnum.FullPath);
  68. WriteFileStringA (DiffHandle, "\r\n");
  69. }
  70. wsprintfA (Node, "%s\\%s,", S_SNAPSHOT_A, FileEnum.FullPath);
  71. Value = SNAP_RESULT_CHANGED;
  72. if (!pGetFullKeyA (Node)) {
  73. wsprintfA (
  74. Node,
  75. "%s\\%s\\%u\\%u%u",
  76. S_SNAPSHOT_A,
  77. FileEnum.FullPath,
  78. FileEnum.FindData->nFileSizeLow,
  79. FileEnum.FindData->ftLastWriteTime.dwHighDateTime,
  80. FileEnum.FindData->ftLastWriteTime.dwLowDateTime
  81. );
  82. Value = SNAP_RESULT_ADDED;
  83. }
  84. }
  85. MemDbSetValueA (Node, Value);
  86. }
  87. } while (EnumNextFileInTreeA (&FileEnum));
  88. }
  89. }
  90. VOID
  91. pSnapAllDrivesA (
  92. IN BOOL DiffMode,
  93. IN HANDLE DiffHandle OPTIONAL
  94. )
  95. {
  96. CHAR Drives[256];
  97. MULTISZ_ENUMA e;
  98. if (GetLogicalDriveStringsA (256, Drives)) {
  99. if (EnumFirstMultiSzA (&e, Drives)) {
  100. do {
  101. if (DRIVE_FIXED == GetDriveTypeA (e.CurrentString)) {
  102. pSnapDirsA (e.CurrentString, DiffMode, DiffHandle);
  103. break;
  104. }
  105. } while (EnumNextMultiSzA (&e));
  106. }
  107. }
  108. }
  109. VOID
  110. pSnapRegistryHiveA (
  111. IN PCSTR Hive,
  112. IN BOOL DiffMode,
  113. IN HANDLE DiffHandle OPTIONAL
  114. )
  115. {
  116. REGTREE_ENUMA RegEnum;
  117. REGVALUE_ENUMA RegValue;
  118. CHAR Node[MEMDB_MAX];
  119. PBYTE Data;
  120. DWORD Checksum;
  121. PBYTE p;
  122. UINT Count;
  123. DWORD Value;
  124. if (EnumFirstRegKeyInTreeA (&RegEnum, Hive)) {
  125. do {
  126. wsprintfA (
  127. Node,
  128. "%s\\%s",
  129. S_SNAPSHOT_A,
  130. RegEnum.FullKeyName
  131. );
  132. if (!DiffMode) {
  133. MemDbSetValueA (Node, SNAP_RESULT_DELETED);
  134. } else {
  135. if (!MemDbGetValueA (Node, NULL)) {
  136. if (DiffHandle) {
  137. WriteFileStringA (DiffHandle, RegEnum.FullKeyName);
  138. WriteFileStringA (DiffHandle, "\r\n");
  139. }
  140. } else {
  141. MemDbSetValueA (Node, SNAP_RESULT_UNCHANGED);
  142. }
  143. }
  144. if (EnumFirstRegValueA (&RegValue, RegEnum.CurrentKey->KeyHandle)) {
  145. do {
  146. Data = GetRegValueData (RegValue.KeyHandle, RegValue.ValueName);
  147. if (!Data) {
  148. continue;
  149. }
  150. Checksum = RegValue.Type;
  151. p = Data;
  152. for (Count = 0 ; Count < RegValue.DataSize ; Count++) {
  153. Checksum = (Checksum << 1) | (Checksum >> 31) | *p;
  154. p++;
  155. }
  156. MemFree (g_hHeap, 0, Data);
  157. wsprintfA (
  158. Node,
  159. "%s\\%s\\[%s],%u",
  160. S_SNAPSHOT_A,
  161. RegEnum.FullKeyName,
  162. RegValue.ValueName,
  163. Checksum
  164. );
  165. if (!DiffMode) {
  166. MemDbSetValueA (Node, SNAP_RESULT_DELETED);
  167. } else {
  168. Value = SNAP_RESULT_UNCHANGED;
  169. if (!MemDbGetValueA (Node, NULL)) {
  170. WriteFileStringA (DiffHandle, RegEnum.FullKeyName);
  171. WriteFileStringA (DiffHandle, " [");
  172. WriteFileStringA (DiffHandle, RegValue.ValueName);
  173. WriteFileStringA (DiffHandle, "]\r\n");
  174. wsprintfA (
  175. Node,
  176. "%s\\%s\\[%s],",
  177. S_SNAPSHOT_A,
  178. RegEnum.FullKeyName,
  179. RegValue.ValueName
  180. );
  181. Value = SNAP_RESULT_CHANGED;
  182. if (!pGetFullKeyA (Node)) {
  183. wsprintfA (
  184. Node,
  185. "%s\\%s\\[%s],%u",
  186. S_SNAPSHOT_A,
  187. RegEnum.FullKeyName,
  188. RegValue.ValueName,
  189. Checksum
  190. );
  191. Value = SNAP_RESULT_ADDED;
  192. }
  193. }
  194. MemDbSetValueA (Node, Value);
  195. }
  196. } while (EnumNextRegValueA (&RegValue));
  197. }
  198. } while (EnumNextRegKeyInTreeA (&RegEnum));
  199. }
  200. }
  201. VOID
  202. pSnapRegistryA (
  203. IN BOOL DiffMode,
  204. IN HANDLE DiffHandle OPTIONAL
  205. )
  206. {
  207. pSnapRegistryHiveA (TEXT("HKLM"), DiffMode, DiffHandle);
  208. pSnapRegistryHiveA (TEXT("HKU"), DiffMode, DiffHandle);
  209. }
  210. VOID
  211. TakeSnapShotEx (
  212. IN DWORD SnapFlags
  213. )
  214. {
  215. MemDbCreateTemporaryKeyA (S_SNAPSHOT_A);
  216. if (SnapFlags & SNAP_FILES) {
  217. pSnapAllDrivesA (FALSE, NULL);
  218. }
  219. if (SnapFlags & SNAP_REGISTRY) {
  220. pSnapRegistryA (FALSE, NULL);
  221. }
  222. }
  223. BOOL
  224. GenerateDiffOutputExA (
  225. IN PCSTR FileName,
  226. IN PCSTR Comment, OPTIONAL
  227. IN BOOL Append,
  228. IN DWORD SnapFlags
  229. )
  230. {
  231. HANDLE File = NULL;
  232. MEMDB_ENUMA e;
  233. if (FileName) {
  234. File = CreateFileA (
  235. FileName,
  236. GENERIC_WRITE,
  237. 0,
  238. NULL,
  239. Append ? OPEN_ALWAYS : CREATE_ALWAYS,
  240. FILE_ATTRIBUTE_NORMAL,
  241. NULL
  242. );
  243. if (File == INVALID_HANDLE_VALUE) {
  244. DEBUGMSG ((DBG_ERROR, "Can't open %s for output", FileName));
  245. return FALSE;
  246. }
  247. if (Append) {
  248. SetFilePointer (File, 0, NULL, FILE_END);
  249. }
  250. if (Comment) {
  251. WriteFileStringA (File, Comment);
  252. WriteFileStringA (File, "\r\n");
  253. }
  254. WriteFileStringA (File, "Changes:\r\n");
  255. }
  256. if (SnapFlags & SNAP_FILES) {
  257. pSnapAllDrivesA (TRUE, File);
  258. }
  259. if (SnapFlags & SNAP_REGISTRY) {
  260. pSnapRegistryA (TRUE, File);
  261. }
  262. if (File) {
  263. WriteFileStringA (File, "\r\nDeleted Settings:\r\n");
  264. if (MemDbGetValueExA (&e, S_SNAPSHOT_A, NULL, NULL)) {
  265. do {
  266. if (e.dwValue == SNAP_RESULT_DELETED) {
  267. WriteFileStringA (File, e.szName);
  268. WriteFileStringA (File, "\r\n");
  269. }
  270. } while (MemDbEnumNextValue (&e));
  271. }
  272. WriteFileStringA (File, "\r\nEnd.\r\n\r\n");
  273. CloseHandle (File);
  274. }
  275. return TRUE;
  276. }
  277. BOOL
  278. EnumFirstSnapFileA (
  279. IN OUT PSNAP_FILE_ENUMA e,
  280. IN PCSTR FilePattern, OPTIONAL
  281. IN DWORD SnapStatus
  282. )
  283. {
  284. CHAR node[MEMDB_MAX];
  285. e->FilePattern = FilePattern;
  286. e->SnapStatus = SnapStatus;
  287. e->FirstCall = TRUE;
  288. MemDbBuildKeyA (node, S_SNAPSHOT_A, "*", NULL, NULL);
  289. if (!MemDbEnumFirstValue (&(e->mEnum), node, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
  290. return FALSE;
  291. }
  292. return EnumNextSnapFileA (e);
  293. }
  294. BOOL
  295. EnumNextSnapFileA (
  296. IN OUT PSNAP_FILE_ENUMA e
  297. )
  298. {
  299. PSTR lastWack;
  300. while (e->FirstCall?(e->FirstCall = FALSE, TRUE):MemDbEnumNextValue (&(e->mEnum))) {
  301. StringCopyA (e->FileName, e->mEnum.szName);
  302. lastWack = _mbsrchr (e->FileName, '\\');
  303. if (lastWack) {
  304. *lastWack = 0;
  305. lastWack = _mbsrchr (e->FileName, '\\');
  306. if (lastWack) {
  307. *lastWack = 0;
  308. }
  309. }
  310. if (e->FilePattern && (!IsPatternMatch (e->FilePattern, e->FileName))) {
  311. continue;
  312. }
  313. if ((e->SnapStatus & e->mEnum.dwValue) == 0) {
  314. continue;
  315. }
  316. return TRUE;
  317. }
  318. return FALSE;
  319. }