Leaked source code of windows server 2003
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.

328 lines
7.5 KiB

  1. #include "precomp.h"
  2. #include "RegAnalyzer.h"
  3. #include "RegDiffFile.h"
  4. #include <process.h>
  5. HREGANL
  6. CreateRegAnalyzer (
  7. VOID
  8. )
  9. {
  10. HREGANL regAnalyzer = (HREGANL) new CRegAnalyzer;
  11. return regAnalyzer;
  12. }
  13. BOOL
  14. CloseRegAnalyzer (
  15. IN HREGANL RegAnalyzer
  16. )
  17. {
  18. delete (CRegAnalyzer*) RegAnalyzer;
  19. return TRUE;
  20. }
  21. BOOL
  22. AddRegistryKey (
  23. IN HREGANL RegAnalyzer,
  24. IN PCTSTR RootKeyName,
  25. IN PCTSTR SubKeyName
  26. )
  27. {
  28. CRegAnalyzer* pRA = (CRegAnalyzer*)RegAnalyzer;
  29. return pRA->AddKey(RootKeyName, SubKeyName);
  30. }
  31. BOOL
  32. ExcludeRegistryKey (
  33. IN HREGANL RegAnalyzer,
  34. IN PCTSTR RootKeyName,
  35. IN PCTSTR SubKeyName
  36. )
  37. {
  38. CRegAnalyzer* pRA = (CRegAnalyzer*)RegAnalyzer;
  39. return pRA->AddKey(RootKeyName, SubKeyName, true);
  40. }
  41. //////////////////////////////////////////////////////////////////////////////////////
  42. struct TakeSnapshotParams
  43. {
  44. HREGANL RegAnalyzer;
  45. PCTSTR SnapshotFile;
  46. PFNSNAPSHOTPROGRESS ProgressCallback;
  47. PVOID Context;
  48. DWORD MaxLevel;
  49. HANDLE hEvent;
  50. };
  51. void __cdecl TakeSnapshotThread(void* pParams)
  52. {
  53. TakeSnapshotParams* pp = (TakeSnapshotParams*)pParams;
  54. if (pp != NULL)
  55. {
  56. CRegAnalyzer* pRA = (CRegAnalyzer*)pp->RegAnalyzer;
  57. pRA->SaveKeysToFile(pp->SnapshotFile, pp->ProgressCallback, pp->Context, pp->MaxLevel);
  58. SetEvent(pp->hEvent);
  59. delete pp;
  60. }
  61. return;
  62. }
  63. BOOL
  64. TakeSnapshot (
  65. IN HREGANL RegAnalyzer,
  66. IN PCTSTR SnapshotFile,
  67. IN PFNSNAPSHOTPROGRESS ProgressCallback,
  68. IN PVOID Context,
  69. IN DWORD MaxLevel,
  70. IN HANDLE hEvent
  71. )
  72. {
  73. CRegAnalyzer* pRA = (CRegAnalyzer*)RegAnalyzer;
  74. if (hEvent == NULL)
  75. return pRA->SaveKeysToFile(SnapshotFile, ProgressCallback, Context, MaxLevel);
  76. else
  77. {
  78. TakeSnapshotParams* pParams = new TakeSnapshotParams;
  79. if (pParams != NULL)
  80. {
  81. pParams->RegAnalyzer=RegAnalyzer;
  82. pParams->SnapshotFile=SnapshotFile;
  83. pParams->ProgressCallback=ProgressCallback;
  84. pParams->Context=Context;
  85. pParams->MaxLevel=MaxLevel;
  86. pParams->hEvent=hEvent;
  87. _beginthread(TakeSnapshotThread, 0, (void*)pParams);
  88. return TRUE;
  89. }
  90. else
  91. return FALSE;
  92. }
  93. }
  94. //////////////////////////////////////////////////////////////////////////////////////
  95. struct ComputeDifferencesParams
  96. {
  97. HREGANL RegAnalyzer;
  98. PCTSTR Snapshot1;
  99. PCTSTR Snapshot2;
  100. PCTSTR DiffFile;
  101. HANDLE hEvent;
  102. };
  103. void __cdecl ComputeDifferencesThread(void* pParams)
  104. {
  105. ComputeDifferencesParams* pp = (ComputeDifferencesParams*)pParams;
  106. if (pp != NULL)
  107. {
  108. CRegAnalyzer* pRA = (CRegAnalyzer*)pp->RegAnalyzer;
  109. pRA->ComputeDifferences1(pp->Snapshot1, pp->Snapshot2, pp->DiffFile);
  110. SetEvent(pp->hEvent);
  111. delete pp;
  112. }
  113. return;
  114. }
  115. BOOL
  116. ComputeDifferences (
  117. IN HREGANL RegAnalyzer,
  118. IN PCTSTR Snapshot1,
  119. IN PCTSTR Snapshot2,
  120. IN PCTSTR DiffFile,
  121. IN HANDLE hEvent
  122. )
  123. {
  124. CRegAnalyzer* pRA = (CRegAnalyzer*)RegAnalyzer;
  125. //
  126. // BUGBUG - ISSUE - what about security settings associated with each registry key?
  127. //
  128. if (hEvent == NULL)
  129. return pRA->ComputeDifferences1(Snapshot1, Snapshot2, DiffFile);
  130. else
  131. {
  132. ComputeDifferencesParams* pParams = new ComputeDifferencesParams;
  133. if (pParams != NULL)
  134. {
  135. pParams->RegAnalyzer=RegAnalyzer;
  136. pParams->Snapshot1=Snapshot1;
  137. pParams->Snapshot2=Snapshot2;
  138. pParams->DiffFile=DiffFile;
  139. pParams->hEvent=hEvent;
  140. _beginthread(ComputeDifferencesThread, 0, (void*)pParams);
  141. return TRUE;
  142. }
  143. else
  144. return FALSE;
  145. }
  146. }
  147. //////////////////////////////////////////////////////////////////////////////////////
  148. BOOL
  149. InstallDifferences (
  150. IN PCTSTR DiffFile,
  151. IN PCTSTR UndoFile
  152. )
  153. {
  154. CRegDiffFile diff;
  155. if (!diff.Init(DiffFile, TRUE)) {
  156. return FALSE;
  157. }
  158. return diff.ApplyToRegistry(UndoFile);
  159. }
  160. BOOL
  161. CountRegSubkeysInternal (
  162. IN HKEY RootKey,
  163. IN PCTSTR SubKey,
  164. IN DWORD MaxLevels,
  165. OUT PDWORD Nodes
  166. )
  167. {
  168. MYASSERT (MaxLevels > 0);
  169. HKEY parentKey;
  170. DWORD rc = RegOpenKeyEx (RootKey, SubKey, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &parentKey);
  171. if (rc != ERROR_SUCCESS) {
  172. SetLastError (rc);
  173. LOG3 (LOG_ERROR, "Failed to open reg subkey (%x,%s) (rc=%u)", RootKey, SubKey, rc);
  174. return FALSE;
  175. }
  176. BOOL b = FALSE;
  177. PTSTR subKeyBuffer = NULL;
  178. __try {
  179. DWORD subKeys;
  180. DWORD subKeyMaxLen;
  181. rc = RegQueryInfoKey (parentKey, NULL, NULL, NULL, &subKeys, &subKeyMaxLen, NULL, NULL, NULL, NULL, NULL, NULL);
  182. if (rc != ERROR_SUCCESS) {
  183. SetLastError (rc);
  184. LOG3 (LOG_ERROR, "Failed to query reg subkey (%x,%s) (rc=%u)", RootKey, SubKey, rc);
  185. __leave;
  186. }
  187. subKeyMaxLen++;
  188. subKeyBuffer = new TCHAR[subKeyMaxLen];
  189. if (!subKeyBuffer) {
  190. OOM();
  191. __leave;
  192. }
  193. if (MaxLevels > 1) {
  194. for (DWORD index = 0; index < subKeys; index++) {
  195. DWORD len = subKeyMaxLen;
  196. rc = RegEnumKeyEx (parentKey, index, subKeyBuffer, &len, NULL, NULL, NULL, NULL);
  197. if (rc == ERROR_NO_MORE_ITEMS) {
  198. break;
  199. }
  200. if (rc != ERROR_SUCCESS) {
  201. SetLastError (rc);
  202. LOG4 (LOG_ERROR, "Failed to enum reg subkey (%x,%s) at index %u (rc=%u)", RootKey, SubKey, index, rc);
  203. __leave;
  204. }
  205. if (!CountRegSubkeysInternal (parentKey, subKeyBuffer, MaxLevels - 1, Nodes)) {
  206. __leave;
  207. }
  208. }
  209. }
  210. *Nodes += subKeys;
  211. delete []subKeyBuffer;
  212. subKeyBuffer = NULL;
  213. b = TRUE;
  214. }
  215. __finally {
  216. if (!b) {
  217. rc = GetLastError ();
  218. }
  219. if (subKeyBuffer) {
  220. delete []subKeyBuffer;
  221. }
  222. RegCloseKey (parentKey);
  223. if (!b) {
  224. SetLastError (rc);
  225. }
  226. }
  227. return b;
  228. }
  229. BOOL
  230. CountRegSubkeys (
  231. IN PCTSTR Root,
  232. IN PCTSTR SubKey,
  233. IN DWORD MaxLevels,
  234. OUT PDWORD Nodes
  235. )
  236. {
  237. HKEY rootKey = GetRootKey (Root);
  238. if (!rootKey) {
  239. LOG1 (LOG_ERROR, "Invalid root key (%s)", Root);
  240. return FALSE;
  241. }
  242. HKEY parentKey;
  243. DWORD rc = RegOpenKeyEx (rootKey, SubKey, 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &parentKey);
  244. if (rc != ERROR_SUCCESS) {
  245. SetLastError (rc);
  246. LOG3 (LOG_ERROR, "Failed to open reg key (%s\\%s) (rc=%u)", Root, SubKey, rc);
  247. return FALSE;
  248. }
  249. RegCloseKey (parentKey);
  250. *Nodes = 1; // the root itself
  251. return MaxLevels ? CountRegSubkeysInternal (rootKey, SubKey, MaxLevels, Nodes) : TRUE;
  252. }
  253. HKEY
  254. GetRootKey (
  255. IN PCTSTR RootStr
  256. )
  257. {
  258. static struct {
  259. PCTSTR RootStr;
  260. HKEY RootKey;
  261. } map[] = {
  262. { TEXT("HKLM"), HKEY_LOCAL_MACHINE },
  263. { TEXT("HKCU"), HKEY_CURRENT_USER },
  264. { TEXT("HKCR"), HKEY_CLASSES_ROOT },
  265. { TEXT("HKU"), HKEY_USERS },
  266. { TEXT("HKCC"), HKEY_CURRENT_CONFIG },
  267. { NULL, 0 }
  268. }, *entry;
  269. for (entry = map; entry->RootStr; entry++) {
  270. if (_tcsicmp (RootStr, entry->RootStr) == 0) {
  271. return entry->RootKey;
  272. }
  273. }
  274. SetLastError (ERROR_INVALID_PARAMETER);
  275. return 0;
  276. }