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.

470 lines
9.7 KiB

  1. // RegAnalyzer.cpp: implementation of the RegAnalyzer class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "precomp.h"
  5. #include "RegAnalyzer.h"
  6. #include "RegDiffFile.h"
  7. #include "RegInfFile.h"
  8. #define BUFSIZE 1024
  9. //#include "MemDeleteQueue.h"
  10. //////////////////////////////////////////////////////////////////////
  11. // Construction/Destruction
  12. //////////////////////////////////////////////////////////////////////
  13. CRegAnalyzer::CRegAnalyzer()
  14. :m_SA(500,200), m_pData(9000), m_pOutputLine(500), m_KeysToSave(3), m_KeysToExclude(3)
  15. {
  16. }
  17. CRegAnalyzer::~CRegAnalyzer()
  18. {
  19. }
  20. bool CRegAnalyzer::SaveKeyToFile(
  21. IN HKEY hKey,
  22. IN LPCTSTR KeyName,
  23. IN CRegFile* RegFile,
  24. IN SectionType section,
  25. IN OUT PDWORD NodesSoFar, OPTIONAL
  26. IN PFNSNAPSHOTPROGRESS ProgressCallback,
  27. IN PVOID Context,
  28. IN INT MaxLevels
  29. )
  30. {
  31. DWORD rc;
  32. if (m_KeysToExclude.FindElement(KeyName))
  33. {
  34. if (NodesSoFar && ProgressCallback && MaxLevels > 0)
  35. {
  36. ++(*NodesSoFar);
  37. rc = ProgressCallback (Context, *NodesSoFar);
  38. if (rc) {
  39. SetLastError (rc);
  40. return false;
  41. }
  42. }
  43. return true;
  44. }
  45. DWORD SubKeyNameSize = MAX_PATH+1;
  46. DWORD NumSubKeys;
  47. TCHAR newPath[BUFSIZE];
  48. ///added
  49. CRegDataItemPtr key(new CRegDataItem);
  50. key->m_KeyName = KeyName;
  51. key->m_bIsEmpty = false;
  52. RegFile->WriteDataItem(section, key);
  53. ///
  54. //**
  55. SaveValuesToFile(hKey, KeyName, RegFile, section);
  56. //**
  57. //////
  58. if (RegQueryInfoKey(hKey, 0,0,0,&NumSubKeys,0,0,0,0,0,0,0) == ERROR_SUCCESS)
  59. {
  60. if (NumSubKeys > 0)
  61. {
  62. CRegStringBuffer SA(NumSubKeys, SubKeyNameSize);
  63. TCHAR** nameArray = SA.Access(NumSubKeys, SubKeyNameSize);
  64. if (nameArray == NULL)
  65. return false;
  66. DWORD i=0;
  67. while (i < NumSubKeys && RegEnumKey(hKey, i, nameArray[i], SubKeyNameSize) == ERROR_SUCCESS)
  68. {
  69. i++;
  70. }
  71. SA.Sort(NumSubKeys);
  72. for (i=0; i<NumSubKeys; i++)
  73. {
  74. _stprintf(newPath, TEXT("%s\\%s"), KeyName, nameArray[i]);
  75. HKEY hSubKey;
  76. if (RegOpenKeyEx(hKey,nameArray[i],0,KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE,&hSubKey) == ERROR_SUCCESS)
  77. {
  78. if (!SaveKeyToFile(hSubKey, newPath, RegFile, section, NodesSoFar, ProgressCallback, Context, MaxLevels - 1)) {
  79. return false;
  80. }
  81. RegCloseKey(hSubKey);
  82. }
  83. }
  84. }
  85. }
  86. if (NodesSoFar && ProgressCallback && MaxLevels > 0)
  87. {
  88. ++(*NodesSoFar);
  89. rc = ProgressCallback (Context, *NodesSoFar);
  90. if (rc) {
  91. SetLastError (rc);
  92. return false;
  93. }
  94. }
  95. return true;
  96. }
  97. bool CRegAnalyzer::SaveValuesToFile(HKEY hKey, LPCTSTR KeyName, CRegFile* RegFile, SectionType section)
  98. {
  99. BYTE* valueData;
  100. TCHAR** nameArray;
  101. DWORD valueNameLen, maxValueNameLen=1000;
  102. DWORD valueDataLen, maxValueDataLen=4000;
  103. DWORD numValues=4;
  104. DWORD status;
  105. DWORD valueType;
  106. if (RegQueryInfoKey(hKey, 0,0,0,0,0,0,&numValues,&maxValueNameLen,&maxValueDataLen,0,0) == ERROR_SUCCESS)
  107. {
  108. maxValueNameLen += 1; //must be at least 1 to include null terminator
  109. valueData = m_pData.Allocate(maxValueDataLen);//new BYTE[maxValueLen];
  110. if (numValues >0)
  111. {
  112. nameArray = m_SA.Access(numValues,maxValueNameLen);
  113. if (nameArray == NULL)
  114. {
  115. LOG0(LOG_ERROR, "Could not access string array in CRegAnalyzer::SaveValuesToFile");
  116. return false;
  117. }
  118. valueNameLen = maxValueNameLen;
  119. DWORD i=0;
  120. while (((status = RegEnumValue(hKey, i, nameArray[i], &valueNameLen,0,0,0,0)) == ERROR_SUCCESS)
  121. || (status == ERROR_MORE_DATA))
  122. {
  123. i++;
  124. valueNameLen = maxValueNameLen;
  125. }
  126. m_SA.Sort(numValues);
  127. for (i=0; i<numValues; i++)
  128. {
  129. valueDataLen = maxValueDataLen;
  130. int code = RegQueryValueEx(hKey, nameArray[i], 0, &valueType, valueData, &valueDataLen);
  131. CRegDataItemPtr temp(new CRegDataItem);
  132. temp->m_bIsEmpty = false;
  133. temp->m_Name = nameArray[i];
  134. temp->m_NameLen = _tcsclen(nameArray[i]);
  135. temp->m_Type = valueType;
  136. temp->m_DataLen = valueDataLen;
  137. if (RegFile->NeedStorageOfValueData())
  138. {
  139. temp->m_pDataBuf = new BYTE[temp->m_DataLen];
  140. memcpy(temp->m_pDataBuf, valueData, temp->m_DataLen);
  141. temp->m_bDontDeleteData = false;
  142. }
  143. else
  144. {
  145. temp->m_pDataBuf = valueData;
  146. temp->m_bDontDeleteData = true;
  147. }
  148. temp->m_KeyName = KeyName;
  149. ///added
  150. RegFile->WriteDataItem(section,temp);
  151. }
  152. }
  153. }
  154. return true;
  155. }
  156. bool IsKeyName(LPCTSTR str)
  157. {
  158. return ((str != NULL) && (str[0] == TEXT('H')));
  159. }
  160. bool CRegAnalyzer::ComputeDifferences1(LPCTSTR RegFile1, LPCTSTR RegFile2, LPCTSTR OutputFile)
  161. {
  162. CRegFile f1,f2;
  163. CRegDiffFile out;
  164. f1.Init(RegFile1, TRUE);
  165. f2.Init(RegFile2, TRUE);
  166. out.Init(OutputFile, FALSE);
  167. while (true)
  168. {
  169. LPCTSTR Key1 = f1.GetNextLine();
  170. LPCTSTR Key2 = f2.GetNextLine();
  171. if (IsKeyName(Key1) && IsKeyName(Key2))
  172. {
  173. CompareRegKeys(Key1, Key2, f1, f2, out);
  174. //delete[] Key1;
  175. //delete[] Key2;
  176. g_DelQueue.DeleteArray((TCHAR*)Key1);
  177. g_DelQueue.DeleteArray((TCHAR*)Key2);
  178. }
  179. else
  180. {
  181. //delete[] Key1;
  182. //delete[] Key2;
  183. g_DelQueue.DeleteArray((TCHAR*)Key1);
  184. g_DelQueue.DeleteArray((TCHAR*)Key2);
  185. break;
  186. }
  187. }
  188. out.WriteStoredSectionsToFile();
  189. g_DelQueue.Flush();
  190. return true;
  191. }
  192. int MyStrCmp(LPCTSTR s1, LPCTSTR s2)
  193. {
  194. if (s1 == s2)
  195. return 0;
  196. else if ((s1 == NULL) && (s2 != NULL))
  197. return 1;
  198. else if ((s1 != NULL) && (s2 == NULL))
  199. return -1;
  200. else
  201. return _tcscmp(s1, s2);
  202. }
  203. void CRegAnalyzer::CompareDataItems(LPCTSTR KeyName, CRegFile &f1, CRegFile &f2, CRegDiffFile &out)
  204. {
  205. CRegDataItemPtr r1 = f1.GetNextDataItem();
  206. CRegDataItemPtr r2 = f2.GetNextDataItem();
  207. while ((!r1->m_bIsEmpty) || (!r2->m_bIsEmpty))
  208. {
  209. int code = r1->CompareTo(*r2);
  210. if (code < 0) //r1.name < r2.name
  211. {
  212. CRegDataItemPtr temp(new CRegDataItem);
  213. temp->m_bIsEmpty = false;
  214. temp->m_KeyName = KeyName;
  215. temp->m_Name = r1->m_Name;
  216. temp->m_NameLen = r1->m_NameLen;
  217. out.WriteDataItem(SECTION_DELREG, temp);
  218. r1 = f1.GetNextDataItem();
  219. }
  220. else if (code == 0) //r1 == r2
  221. {
  222. r1 = f1.GetNextDataItem();
  223. r2 = f2.GetNextDataItem();
  224. }
  225. else if (code == 1) //r1.name == r2.name, but other changes in item's data
  226. {
  227. r2->m_KeyName = KeyName;
  228. out.WriteDataItem(SECTION_ADDREG, r2);
  229. r1 = f1.GetNextDataItem();
  230. r2 = f2.GetNextDataItem();
  231. }
  232. else //r1.name > r2.name
  233. {
  234. r2->m_KeyName = KeyName;
  235. out.WriteDataItem(SECTION_ADDREG, r2);
  236. r2 = f2.GetNextDataItem();
  237. }
  238. }
  239. }
  240. int CRegAnalyzer::CompareRegKeys(LPCTSTR Key1, LPCTSTR Key2, CRegFile& f1, CRegFile& f2, CRegDiffFile& out)
  241. {
  242. CRegFile blank1;
  243. CRegDiffFile blank2;
  244. CRegDataItemPtr r;
  245. if ((Key1 == NULL) && (Key2 == NULL))
  246. return 0;
  247. int code = MyStrCmp(Key1, Key2);
  248. if (code < 0) //Key1 < Key2
  249. {
  250. r= CRegDataItemPtr(new CRegDataItem);
  251. r->m_KeyName = Key1;
  252. r->m_bIsEmpty = false;
  253. out.WriteDataItem(SECTION_DELREG, r);
  254. CompareDataItems(Key1, f1, blank1, blank2);
  255. CompareSubKeys(Key1, f1, blank1, blank2);
  256. }
  257. else if (code == 0) //Key1 == Key2
  258. {
  259. CompareDataItems(Key1, f1, f2, out);
  260. CompareSubKeys(Key1, f1, f2, out);
  261. }
  262. else //Key1 > Key2
  263. {
  264. r= CRegDataItemPtr(new CRegDataItem);
  265. r->m_KeyName = Key2;
  266. r->m_bIsEmpty = false;
  267. out.WriteDataItem(SECTION_ADDREG, r);
  268. CompareDataItems(Key2, blank1, f2, out);
  269. CompareSubKeys(Key2, blank1, f2, out);
  270. }
  271. return code;
  272. }
  273. void CRegAnalyzer::CompareSubKeys(LPCTSTR Key, CRegFile& f1, CRegFile& f2, CRegDiffFile& out)
  274. {
  275. LPCTSTR SubKey1=NULL, SubKey2=NULL;
  276. int result = 0;
  277. while (true)
  278. {
  279. if (result == 0)
  280. {
  281. // g_DelQueue.DeleteArray((TCHAR*)SubKey1);
  282. // g_DelQueue.DeleteArray((TCHAR*)SubKey2);
  283. delete[] SubKey1;
  284. delete[] SubKey2;
  285. SubKey1 = f1.GetNextSubKey(Key);
  286. SubKey2 = f2.GetNextSubKey(Key);
  287. }
  288. else if (result < 0)
  289. {
  290. delete[] SubKey1;
  291. // g_DelQueue.DeleteArray((TCHAR*)SubKey1);
  292. SubKey1 = f1.GetNextSubKey(Key);
  293. }
  294. else
  295. {
  296. delete[] SubKey2;
  297. //g_DelQueue.DeleteArray((TCHAR*)SubKey2);
  298. SubKey2 = f2.GetNextSubKey(Key);
  299. }
  300. if ((SubKey1 != NULL) || (SubKey2 != NULL))
  301. {
  302. result = CompareRegKeys(SubKey1, SubKey2, f1, f2, out);
  303. }
  304. else
  305. break;
  306. }
  307. }
  308. BOOL CRegAnalyzer::AddKey(LPCTSTR RootKey, LPCTSTR SubKey, bool bExclude)
  309. {
  310. CRegKey k;
  311. k.m_hKey = GetRootKey (RootKey);
  312. if (!k.m_hKey) {
  313. return FALSE;
  314. }
  315. // CStr root(RootKey);
  316. CStr subkey(SubKey);
  317. k.m_KeyName += RootKey;
  318. if (!(subkey == TEXT("")))
  319. {
  320. HKEY res;
  321. RegOpenKey(k.m_hKey, subkey, &res);
  322. k.m_hKey = res;
  323. k.m_KeyName += TEXT("\\");
  324. k.m_KeyName += SubKey;
  325. }
  326. if (bExclude)
  327. {
  328. RegCloseKey(k.m_hKey);
  329. m_KeysToExclude.AddElement(k.m_KeyName);
  330. }
  331. else
  332. m_KeysToSave.AddElement(k);
  333. return TRUE;
  334. }
  335. BOOL CRegAnalyzer::SaveKeysToFile(
  336. IN LPCTSTR FileName,
  337. IN PFNSNAPSHOTPROGRESS ProgressCallback,
  338. IN PVOID Context,
  339. IN DWORD MaxLevels
  340. )
  341. {
  342. CRegFile file;
  343. BOOL b = FALSE;
  344. if (file.Init(FileName))
  345. {
  346. DWORD nodesSoFar = 0;
  347. for (int i=0; i<m_KeysToSave.GetNumElementsStored(); i++)
  348. {
  349. if (!SaveKeyToFile(m_KeysToSave.Access()[i].m_hKey,
  350. m_KeysToSave.Access()[i].m_KeyName,
  351. &file, SECTION_NONE, &nodesSoFar, ProgressCallback, Context, MaxLevels)) {
  352. break;
  353. }
  354. }
  355. if (i == m_KeysToSave.GetNumElementsStored()) {
  356. b = TRUE;
  357. }
  358. }
  359. return b;
  360. }