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.

1182 lines
33 KiB

  1. //-----------------------------------------------------------------------//
  2. //
  3. // File: compare.cpp
  4. // Created: April 1999
  5. // By: Zeyong Xu
  6. // Purpose: Compare two registry key
  7. //
  8. //------------------------------------------------------------------------//
  9. #include "stdafx.h"
  10. #include "reg.h"
  11. #include "compare.h"
  12. BOOL g_bHasDifference = FALSE;
  13. //-----------------------------------------------------------------------//
  14. //
  15. // CompareRegistry()
  16. //
  17. //-----------------------------------------------------------------------//
  18. LONG CompareRegistry(PAPPVARS pAppVars,
  19. PAPPVARS pDstVars,
  20. UINT argc,
  21. TCHAR *argv[])
  22. {
  23. LONG nResult;
  24. HKEY hLeftKey;
  25. HKEY hRightKey;
  26. //
  27. // Parse the cmd-line
  28. //
  29. nResult = ParseCompareCmdLine(pAppVars, pDstVars, argc, argv);
  30. if (nResult != ERROR_SUCCESS)
  31. {
  32. return nResult;
  33. }
  34. //
  35. // Connect to the Remote Machine(s) - if applicable
  36. //
  37. nResult = RegConnectMachine(pAppVars);
  38. if (nResult != ERROR_SUCCESS)
  39. {
  40. return nResult;
  41. }
  42. nResult = RegConnectMachine(pDstVars);
  43. if (nResult != ERROR_SUCCESS)
  44. {
  45. return nResult;
  46. }
  47. //
  48. // Now implement the body of the Compare Operation
  49. //
  50. nResult = RegOpenKeyEx(pAppVars->hRootKey,
  51. pAppVars->szSubKey,
  52. 0,
  53. KEY_READ,
  54. &hLeftKey);
  55. if (nResult != ERROR_SUCCESS)
  56. {
  57. return nResult;
  58. }
  59. nResult = RegOpenKeyEx(pDstVars->hRootKey,
  60. pDstVars->szSubKey,
  61. 0,
  62. KEY_READ,
  63. &hRightKey);
  64. if (nResult != ERROR_SUCCESS)
  65. {
  66. return nResult;
  67. }
  68. // if try to compare the same keys
  69. if (pAppVars->hRootKey == pDstVars->hRootKey &&
  70. _tcsicmp(pAppVars->szFullKey, pDstVars->szFullKey) == 0)
  71. {
  72. RegCloseKey(hLeftKey);
  73. RegCloseKey(hRightKey);
  74. return REG_STATUS_COMPARESELF;
  75. }
  76. //
  77. // compare a single value if pAppVars->szValueName is not NULL
  78. //
  79. if(pAppVars->szValueName)
  80. {
  81. nResult = CompareValues(hLeftKey,
  82. pAppVars->szFullKey,
  83. hRightKey,
  84. pDstVars->szFullKey,
  85. pAppVars->szValueName,
  86. pAppVars->nOutputType);
  87. }
  88. else
  89. {
  90. //
  91. // Recursively compare if pAppVars->bRecurseSubKeys is true
  92. //
  93. nResult = CompareEnumerateKey(hLeftKey,
  94. pAppVars->szFullKey,
  95. hRightKey,
  96. pDstVars->szFullKey,
  97. pAppVars->nOutputType,
  98. pAppVars->bRecurseSubKeys);
  99. }
  100. if(nResult == ERROR_SUCCESS)
  101. {
  102. pAppVars->bHasDifference = g_bHasDifference;
  103. if(g_bHasDifference)
  104. MyTPrintf(stdout,_T("\r\nResult Compared: Different\r\n"));
  105. else
  106. MyTPrintf(stdout,_T("\r\nResult Compared: Identical\r\n"));
  107. }
  108. //
  109. // lets clean up
  110. //
  111. RegCloseKey(hLeftKey);
  112. RegCloseKey(hRightKey);
  113. return nResult;
  114. }
  115. REG_STATUS ParseCompareCmdLine(PAPPVARS pAppVars,
  116. PAPPVARS pDstVars,
  117. UINT argc,
  118. TCHAR *argv[])
  119. {
  120. UINT i;
  121. REG_STATUS nResult = ERROR_SUCCESS;
  122. BOOL bInvalidParams = FALSE;
  123. //
  124. // Do we have a *valid* number of cmd-line params
  125. //
  126. if(argc < 4)
  127. {
  128. return REG_STATUS_TOFEWPARAMS;
  129. }
  130. else if(argc > 8)
  131. {
  132. return REG_STATUS_TOMANYPARAMS;
  133. }
  134. //
  135. // Left Machine Name and Registry key
  136. //
  137. nResult = BreakDownKeyString(argv[2], pAppVars);
  138. if(nResult != ERROR_SUCCESS)
  139. return nResult;
  140. //
  141. // Right Machine Name and Registry key
  142. //
  143. nResult = BreakDownKeyString(argv[3], pDstVars);
  144. if(nResult == REG_STATUS_NOKEYNAME)
  145. {
  146. // if no keyname for right side is specified,
  147. // they are comparing the same key name
  148. nResult = CopyKeyNameFromLeftToRight(pAppVars, pDstVars);
  149. }
  150. if( nResult != ERROR_SUCCESS)
  151. return nResult;
  152. // parsing
  153. for(i=4; i<argc; i++)
  154. {
  155. if(!_tcsicmp(argv[i], _T("/v")))
  156. {
  157. if(bInvalidParams || pAppVars->bRecurseSubKeys)
  158. return REG_STATUS_INVALIDPARAMS;
  159. bInvalidParams = TRUE;
  160. i++;
  161. if(i<argc)
  162. {
  163. pAppVars->szValueName = (TCHAR*) calloc(_tcslen(argv[i]) + 1,
  164. sizeof(TCHAR));
  165. if (!pAppVars->szValueName) {
  166. return ERROR_NOT_ENOUGH_MEMORY;
  167. }
  168. _tcscpy(pAppVars->szValueName, argv[i]);
  169. }
  170. else
  171. return REG_STATUS_TOFEWPARAMS;
  172. }
  173. else if(!_tcsicmp(argv[i], _T("/ve")))
  174. {
  175. if(bInvalidParams || pAppVars->bRecurseSubKeys)
  176. return REG_STATUS_INVALIDPARAMS;
  177. bInvalidParams = TRUE;
  178. pAppVars->szValueName = (TCHAR*) calloc(1, sizeof(TCHAR));
  179. if (!pAppVars->szValueName) {
  180. return ERROR_NOT_ENOUGH_MEMORY;
  181. }
  182. }
  183. else if(!_tcsicmp(argv[i], _T("/oa")))
  184. {
  185. if(bInvalidParams)
  186. return REG_STATUS_INVALIDPARAMS;
  187. bInvalidParams = TRUE;
  188. pAppVars->nOutputType = OUTPUTTYPE_ALL;
  189. }
  190. else if(!_tcsicmp(argv[i], _T("/od")))
  191. {
  192. if(bInvalidParams)
  193. return REG_STATUS_INVALIDPARAMS;
  194. bInvalidParams = TRUE;
  195. pAppVars->nOutputType = OUTPUTTYPE_DIFF;
  196. }
  197. else if(!_tcsicmp(argv[i], _T("/os")))
  198. {
  199. if(bInvalidParams)
  200. return REG_STATUS_INVALIDPARAMS;
  201. bInvalidParams = TRUE;
  202. pAppVars->nOutputType = OUTPUTTYPE_SAME;
  203. }
  204. else if(!_tcsicmp(argv[i], _T("/on")))
  205. {
  206. if(bInvalidParams)
  207. return REG_STATUS_INVALIDPARAMS;
  208. bInvalidParams = TRUE;
  209. pAppVars->nOutputType = OUTPUTTYPE_NONE;
  210. }
  211. else if(!_tcsicmp(argv[i], _T("/s")))
  212. {
  213. if(pAppVars->szValueName)
  214. return REG_STATUS_INVALIDPARAMS;
  215. pAppVars->bRecurseSubKeys = TRUE;
  216. }
  217. else
  218. {
  219. nResult = REG_STATUS_INVALIDPARAMS;
  220. }
  221. }
  222. return nResult;
  223. }
  224. REG_STATUS CopyKeyNameFromLeftToRight(APPVARS* pAppVars, APPVARS* pDstVars)
  225. {
  226. // check if rootkey is remotable for right side
  227. if( pDstVars->bUseRemoteMachine &&
  228. !(pAppVars->hRootKey == HKEY_USERS ||
  229. pAppVars->hRootKey == HKEY_LOCAL_MACHINE) )
  230. {
  231. return REG_STATUS_NONREMOTABLEROOT;
  232. }
  233. pDstVars->szFullKey = (TCHAR*) calloc(_tcslen(pAppVars->szFullKey) + 1,
  234. sizeof(TCHAR));
  235. if (!pDstVars->szFullKey)
  236. return ERROR_NOT_ENOUGH_MEMORY;
  237. pDstVars->szSubKey = (TCHAR*) calloc(_tcslen(pAppVars->szSubKey) + 1,
  238. sizeof(TCHAR));
  239. if (!pDstVars->szSubKey) {
  240. free (pDstVars->szFullKey);
  241. return ERROR_NOT_ENOUGH_MEMORY;
  242. }
  243. _tcscpy(pDstVars->szFullKey, pAppVars->szFullKey);
  244. pDstVars->hRootKey = pAppVars->hRootKey;
  245. _tcscpy(pDstVars->szSubKey, pAppVars->szSubKey);
  246. return ERROR_SUCCESS;
  247. }
  248. //-----------------------------------------------------------------------//
  249. //
  250. // EnumerateKey() - Recursive
  251. //
  252. //-----------------------------------------------------------------------//
  253. LONG CompareEnumerateKey(HKEY hLeftKey,
  254. TCHAR* szLeftFullKeyName,
  255. HKEY hRightKey,
  256. TCHAR* szRightFullKeyName,
  257. int nOutputType,
  258. BOOL bRecurseSubKeys)
  259. {
  260. DWORD nResult;
  261. DWORD dwSize;
  262. TCHAR* pszLeftNameBuf;
  263. TCHAR* pszRightNameBuf;
  264. TCHAR** pLeftArray;
  265. TCHAR** pRightArray;
  266. DWORD dwIndex;
  267. DWORD dwNumOfLeftKeyName;
  268. DWORD dwLenOfLeftKeyName;
  269. DWORD dwNumOfRightKeyName;
  270. DWORD dwLenOfRightKeyName;
  271. DWORD dw;
  272. HKEY hLeftSubKey;
  273. HKEY hRightSubKey;
  274. // enumerate all values under current key
  275. nResult = CompareEnumerateValueName(hLeftKey,
  276. szLeftFullKeyName,
  277. hRightKey,
  278. szRightFullKeyName,
  279. nOutputType);
  280. if(!bRecurseSubKeys || nResult != ERROR_SUCCESS)
  281. return nResult;
  282. // enum all subkeys
  283. // query left key info
  284. nResult = RegQueryInfoKey(hLeftKey,
  285. NULL,
  286. NULL,
  287. NULL,
  288. &dwNumOfLeftKeyName,
  289. &dwLenOfLeftKeyName,
  290. NULL,
  291. NULL,
  292. NULL,
  293. NULL,
  294. NULL,
  295. NULL);
  296. if (nResult != ERROR_SUCCESS)
  297. {
  298. return nResult;
  299. }
  300. // query right key info
  301. nResult = RegQueryInfoKey(hRightKey,
  302. NULL,
  303. NULL,
  304. NULL,
  305. &dwNumOfRightKeyName,
  306. &dwLenOfRightKeyName,
  307. NULL,
  308. NULL,
  309. NULL,
  310. NULL,
  311. NULL,
  312. NULL);
  313. if (nResult != ERROR_SUCCESS)
  314. {
  315. return nResult;
  316. }
  317. #ifndef REG_FOR_WIN2000 // ansi version for win98
  318. // fix API bugs: RegQueryInfoKey() returns non-correct length values
  319. // on remote Win98
  320. if(dwLenOfLeftKeyName < MAX_PATH)
  321. dwLenOfLeftKeyName = MAX_PATH;
  322. if(dwLenOfRightKeyName < MAX_PATH)
  323. dwLenOfRightKeyName = MAX_PATH;
  324. #endif
  325. //
  326. // enumerate all of the subkeys in left key
  327. //
  328. dwLenOfLeftKeyName++;
  329. pszLeftNameBuf = (TCHAR*) calloc(dwNumOfLeftKeyName *
  330. dwLenOfLeftKeyName,
  331. sizeof(TCHAR));
  332. if (!pszLeftNameBuf) {
  333. nResult = ERROR_NOT_ENOUGH_MEMORY;
  334. goto Cleanup;
  335. }
  336. // index array of name buffer for compare
  337. pLeftArray = (TCHAR**) calloc(dwNumOfLeftKeyName, sizeof(TCHAR*));
  338. if (!pLeftArray) {
  339. nResult = ERROR_NOT_ENOUGH_MEMORY;
  340. goto Cleanup;
  341. }
  342. dwIndex = 0;
  343. while(dwIndex < dwNumOfLeftKeyName && nResult == ERROR_SUCCESS)
  344. {
  345. pLeftArray[dwIndex] = pszLeftNameBuf +
  346. (dwIndex * dwLenOfLeftKeyName);
  347. dwSize = dwLenOfLeftKeyName;
  348. nResult = RegEnumKeyEx(hLeftKey,
  349. dwIndex,
  350. pLeftArray[dwIndex],
  351. &dwSize,
  352. NULL,
  353. NULL,
  354. NULL,
  355. NULL);
  356. dwIndex++;
  357. }
  358. if (nResult != ERROR_SUCCESS)
  359. {
  360. if(pszLeftNameBuf)
  361. free(pszLeftNameBuf);
  362. if(pLeftArray)
  363. free(pLeftArray);
  364. return nResult;
  365. }
  366. //
  367. // enumerate all of the subkeys in right key
  368. //
  369. dwLenOfRightKeyName++;
  370. pszRightNameBuf = (TCHAR*) calloc(dwNumOfRightKeyName *
  371. dwLenOfRightKeyName,
  372. sizeof(TCHAR));
  373. if (!pszRightNameBuf) {
  374. nResult = ERROR_NOT_ENOUGH_MEMORY;
  375. goto Cleanup;
  376. }
  377. // index array of name buffer for compare
  378. pRightArray = (TCHAR**) calloc(dwNumOfRightKeyName, sizeof(TCHAR*));
  379. if (!pRightArray) {
  380. nResult = ERROR_NOT_ENOUGH_MEMORY;
  381. goto Cleanup;
  382. }
  383. dwIndex = 0;
  384. while(dwIndex < dwNumOfRightKeyName && nResult == ERROR_SUCCESS)
  385. {
  386. pRightArray[dwIndex] = pszRightNameBuf +
  387. (dwIndex * dwLenOfRightKeyName);
  388. dwSize = dwLenOfRightKeyName;
  389. nResult = RegEnumKeyEx(hRightKey,
  390. dwIndex,
  391. pRightArray[dwIndex],
  392. &dwSize,
  393. NULL,
  394. NULL,
  395. NULL,
  396. NULL);
  397. dwIndex++;
  398. }
  399. if (nResult != ERROR_SUCCESS)
  400. {
  401. if(pszLeftNameBuf)
  402. free(pszLeftNameBuf);
  403. if(pLeftArray)
  404. free(pLeftArray);
  405. if(pszRightNameBuf)
  406. free(pszRightNameBuf);
  407. if(pRightArray)
  408. free(pRightArray);
  409. return nResult;
  410. }
  411. // compare two subkey name array to find the same subkey
  412. for(dwIndex = 0;
  413. dwIndex < dwNumOfLeftKeyName && nResult == ERROR_SUCCESS;
  414. dwIndex++)
  415. {
  416. if(pLeftArray[dwIndex] == NULL)
  417. continue;
  418. for(dw = 0;
  419. dw < dwNumOfRightKeyName && nResult == ERROR_SUCCESS;
  420. dw++)
  421. {
  422. if(pRightArray[dw] == NULL)
  423. continue;
  424. // if same subey name, recusive
  425. if(_tcsicmp(pLeftArray[dwIndex], pRightArray[dw]) == 0)
  426. {
  427. TCHAR* szTempLeft;
  428. TCHAR* szTempRight;
  429. // print out key
  430. if( nOutputType == OUTPUTTYPE_SAME ||
  431. nOutputType == OUTPUTTYPE_ALL )
  432. {
  433. nResult = PrintKey(hLeftKey,
  434. szLeftFullKeyName,
  435. pLeftArray[dwIndex],
  436. PRINTTYPE_SAME);
  437. if(nResult != ERROR_SUCCESS)
  438. break;
  439. }
  440. //
  441. // Now implement the body of the Compare Operation
  442. //
  443. nResult = RegOpenKeyEx(hLeftKey,
  444. pLeftArray[dwIndex],
  445. 0,
  446. KEY_READ,
  447. &hLeftSubKey);
  448. if (nResult != ERROR_SUCCESS)
  449. break;
  450. nResult = RegOpenKeyEx(hRightKey,
  451. pLeftArray[dwIndex],
  452. 0,
  453. KEY_READ,
  454. &hRightSubKey);
  455. if (nResult != ERROR_SUCCESS)
  456. break;
  457. // create left full subkey
  458. szTempLeft = (TCHAR*) calloc(_tcslen(szLeftFullKeyName) +
  459. _tcslen(pLeftArray[dwIndex]) +
  460. 2,
  461. sizeof(TCHAR));
  462. if (!szTempLeft) {
  463. nResult = ERROR_NOT_ENOUGH_MEMORY;
  464. goto Cleanup;
  465. }
  466. _tcscpy(szTempLeft, szLeftFullKeyName);
  467. _tcscat(szTempLeft, _T("\\"));
  468. _tcscat(szTempLeft, pLeftArray[dwIndex]);
  469. // create right full subkey
  470. szTempRight = (TCHAR*) calloc(_tcslen(szRightFullKeyName) +
  471. _tcslen(pLeftArray[dwIndex]) +
  472. 2,
  473. sizeof(TCHAR));
  474. if (!szTempRight) {
  475. free (szTempLeft);
  476. nResult = ERROR_NOT_ENOUGH_MEMORY;
  477. goto Cleanup;
  478. }
  479. _tcscpy(szTempRight, szRightFullKeyName);
  480. _tcscat(szTempRight, _T("\\"));
  481. _tcscat(szTempRight, pLeftArray[dwIndex]);
  482. // recursive to compare subkeys
  483. nResult = CompareEnumerateKey(hLeftSubKey,
  484. szLeftFullKeyName,
  485. hRightSubKey,
  486. szRightFullKeyName,
  487. nOutputType,
  488. bRecurseSubKeys);
  489. if(szTempLeft) {
  490. free(szTempLeft);
  491. }
  492. if(szTempRight) {
  493. free(szTempRight);
  494. }
  495. RegCloseKey(hLeftSubKey);
  496. RegCloseKey(hRightSubKey);
  497. pLeftArray[dwIndex] = NULL;
  498. pRightArray[dw] = NULL;
  499. break;
  500. }
  501. }
  502. }
  503. // Output subkey name in left key
  504. for(dwIndex = 0;
  505. dwIndex < dwNumOfLeftKeyName && nResult == ERROR_SUCCESS;
  506. dwIndex++)
  507. {
  508. if(pLeftArray[dwIndex] == NULL)
  509. continue;
  510. if( nOutputType == OUTPUTTYPE_DIFF ||
  511. nOutputType == OUTPUTTYPE_ALL )
  512. {
  513. nResult = PrintKey(hLeftKey,
  514. szLeftFullKeyName,
  515. pLeftArray[dwIndex],
  516. PRINTTYPE_LEFT);
  517. }
  518. g_bHasDifference = TRUE;
  519. }
  520. // Output subkey name in right key
  521. for(dwIndex = 0;
  522. dwIndex < dwNumOfRightKeyName && nResult == ERROR_SUCCESS;
  523. dwIndex++)
  524. {
  525. if(pRightArray[dwIndex] == NULL)
  526. continue;
  527. if( nOutputType == OUTPUTTYPE_DIFF ||
  528. nOutputType == OUTPUTTYPE_ALL )
  529. {
  530. nResult = PrintKey(hRightKey,
  531. szRightFullKeyName,
  532. pRightArray[dwIndex],
  533. PRINTTYPE_RIGHT);
  534. }
  535. g_bHasDifference = TRUE;
  536. }
  537. Cleanup:
  538. if(pszLeftNameBuf)
  539. free(pszLeftNameBuf);
  540. if(pLeftArray)
  541. free(pLeftArray);
  542. if(pszRightNameBuf)
  543. free(pszRightNameBuf);
  544. if(pRightArray)
  545. free(pRightArray);
  546. return nResult;
  547. }
  548. LONG CompareEnumerateValueName(HKEY hLeftKey,
  549. TCHAR* szLeftFullKeyName,
  550. HKEY hRightKey,
  551. TCHAR* szRightFullKeyName,
  552. int nOutputType)
  553. {
  554. DWORD nResult = ERROR_SUCCESS;
  555. DWORD dwSize;
  556. TCHAR* pszLeftNameBuf = NULL;
  557. TCHAR* pszRightNameBuf = NULL;
  558. TCHAR** pLeftArray = NULL;
  559. TCHAR** pRightArray = NULL;
  560. DWORD dwIndex;
  561. DWORD dwNumOfRightValueName;
  562. DWORD dwLenOfRightValueName;
  563. DWORD dw;
  564. // query left key info
  565. DWORD dwNumOfLeftValueName;
  566. DWORD dwLenOfLeftValueName;
  567. nResult = RegQueryInfoKey(hLeftKey,
  568. NULL,
  569. NULL,
  570. NULL,
  571. NULL,
  572. NULL,
  573. NULL,
  574. &dwNumOfLeftValueName,
  575. &dwLenOfLeftValueName,
  576. NULL,
  577. NULL,
  578. NULL);
  579. if (nResult != ERROR_SUCCESS)
  580. {
  581. return nResult;
  582. }
  583. // query right key info
  584. nResult = RegQueryInfoKey(hRightKey,
  585. NULL,
  586. NULL,
  587. NULL,
  588. NULL,
  589. NULL,
  590. NULL,
  591. &dwNumOfRightValueName,
  592. &dwLenOfRightValueName,
  593. NULL,
  594. NULL,
  595. NULL);
  596. if (nResult != ERROR_SUCCESS)
  597. {
  598. return nResult;
  599. }
  600. #ifndef REG_FOR_WIN2000 // ansi version for win98
  601. // fix API bugs: RegQueryInfoKey() returns non-correct length values
  602. // on remote Win98
  603. if(dwLenOfLeftValueName < MAX_PATH)
  604. dwLenOfLeftValueName = MAX_PATH;
  605. if(dwLenOfRightValueName < MAX_PATH)
  606. dwLenOfRightValueName = MAX_PATH;
  607. #endif
  608. //
  609. // enumerate all of the values in left key
  610. //
  611. dwLenOfLeftValueName++;
  612. pszLeftNameBuf = (TCHAR*) calloc(dwNumOfLeftValueName *
  613. dwLenOfLeftValueName,
  614. sizeof(TCHAR));
  615. if (!pszLeftNameBuf) {
  616. nResult = ERROR_NOT_ENOUGH_MEMORY;
  617. goto Cleanup;
  618. }
  619. // index array of name buffer for compare
  620. pLeftArray = (TCHAR**) calloc(dwNumOfLeftValueName, sizeof(TCHAR*));
  621. if (!pLeftArray) {
  622. nResult = ERROR_NOT_ENOUGH_MEMORY;
  623. goto Cleanup;
  624. }
  625. dwIndex = 0;
  626. while(dwIndex < dwNumOfLeftValueName && nResult == ERROR_SUCCESS)
  627. {
  628. pLeftArray[dwIndex] = pszLeftNameBuf +
  629. (dwIndex * dwLenOfLeftValueName);
  630. dwSize = dwLenOfLeftValueName;
  631. nResult = RegEnumValue(hLeftKey,
  632. dwIndex,
  633. pLeftArray[dwIndex],
  634. &dwSize,
  635. NULL,
  636. NULL,
  637. NULL,
  638. NULL);
  639. dwIndex++;
  640. }
  641. if (nResult != ERROR_SUCCESS)
  642. {
  643. if(pszLeftNameBuf)
  644. free(pszLeftNameBuf);
  645. if(pLeftArray)
  646. free(pLeftArray);
  647. return nResult;
  648. }
  649. //
  650. // enumerate all of the values in right key
  651. //
  652. dwLenOfRightValueName++;
  653. pszRightNameBuf = (TCHAR*) calloc(dwNumOfRightValueName *
  654. dwLenOfRightValueName,
  655. sizeof(TCHAR));
  656. if (!pszRightNameBuf) {
  657. nResult = ERROR_NOT_ENOUGH_MEMORY;
  658. goto Cleanup;
  659. }
  660. // index array of name buffer for compare
  661. pRightArray = (TCHAR**) calloc(dwNumOfRightValueName, sizeof(TCHAR*));
  662. if (!pRightArray) {
  663. nResult = ERROR_NOT_ENOUGH_MEMORY;
  664. goto Cleanup;
  665. }
  666. dwIndex = 0;
  667. while(dwIndex < dwNumOfRightValueName && nResult == ERROR_SUCCESS)
  668. {
  669. pRightArray[dwIndex] = pszRightNameBuf +
  670. (dwIndex * dwLenOfRightValueName);
  671. dwSize = dwLenOfRightValueName;
  672. nResult = RegEnumValue(hRightKey,
  673. dwIndex,
  674. pRightArray[dwIndex],
  675. &dwSize,
  676. NULL,
  677. NULL,
  678. NULL,
  679. NULL);
  680. dwIndex++;
  681. }
  682. if (nResult != ERROR_SUCCESS)
  683. {
  684. if(pszLeftNameBuf)
  685. free(pszLeftNameBuf);
  686. if(pLeftArray)
  687. free(pLeftArray);
  688. if(pszRightNameBuf)
  689. free(pszRightNameBuf);
  690. if(pRightArray)
  691. free(pRightArray);
  692. return nResult;
  693. }
  694. // compare two valuename array to find the same valuename
  695. for(dwIndex = 0;
  696. dwIndex < dwNumOfLeftValueName && nResult == ERROR_SUCCESS;
  697. dwIndex++)
  698. {
  699. if(pLeftArray[dwIndex] == NULL)
  700. continue;
  701. for(dw = 0;
  702. dw < dwNumOfRightValueName && nResult == ERROR_SUCCESS;
  703. dw++)
  704. {
  705. if(pRightArray[dw] == NULL)
  706. continue;
  707. // same valuename
  708. if(_tcsicmp(pLeftArray[dwIndex], pRightArray[dw]) == 0)
  709. {
  710. nResult = CompareValues(hLeftKey,
  711. szLeftFullKeyName,
  712. hRightKey,
  713. szRightFullKeyName,
  714. pLeftArray[dwIndex],
  715. nOutputType);
  716. pLeftArray[dwIndex] = NULL;
  717. pRightArray[dw] = NULL;
  718. break;
  719. }
  720. }
  721. }
  722. // Output different valuename in left key
  723. for(dwIndex = 0;
  724. dwIndex < dwNumOfLeftValueName && nResult == ERROR_SUCCESS;
  725. dwIndex++)
  726. {
  727. if(pLeftArray[dwIndex] == NULL)
  728. continue;
  729. if( nOutputType == OUTPUTTYPE_DIFF ||
  730. nOutputType == OUTPUTTYPE_ALL )
  731. {
  732. nResult = OutputValue(hLeftKey,
  733. szLeftFullKeyName,
  734. pLeftArray[dwIndex],
  735. PRINTTYPE_LEFT);
  736. }
  737. g_bHasDifference = TRUE;
  738. }
  739. // Output different valuename in right key
  740. for(dwIndex = 0;
  741. dwIndex < dwNumOfRightValueName && nResult == ERROR_SUCCESS;
  742. dwIndex++)
  743. {
  744. if(pRightArray[dwIndex] == NULL)
  745. continue;
  746. if( nOutputType == OUTPUTTYPE_DIFF ||
  747. nOutputType == OUTPUTTYPE_ALL )
  748. {
  749. nResult = OutputValue(hRightKey,
  750. szRightFullKeyName,
  751. pRightArray[dwIndex],
  752. PRINTTYPE_RIGHT);
  753. }
  754. g_bHasDifference = TRUE;
  755. }
  756. Cleanup:
  757. if(pszLeftNameBuf)
  758. free(pszLeftNameBuf);
  759. if(pLeftArray)
  760. free(pLeftArray);
  761. if(pszRightNameBuf)
  762. free(pszRightNameBuf);
  763. if(pRightArray)
  764. free(pRightArray);
  765. return nResult;
  766. }
  767. //-----------------------------------------------------------------------//
  768. //
  769. // CompareValues()
  770. //
  771. //-----------------------------------------------------------------------//
  772. LONG CompareValues(HKEY hLeftKey,
  773. TCHAR* szLeftFullKeyName,
  774. HKEY hRightKey,
  775. TCHAR* szRightFullKeyName,
  776. TCHAR* szValueName,
  777. int nOutputType)
  778. {
  779. LONG nResult;
  780. DWORD dwTypeLeft;
  781. DWORD dwTypeRight;
  782. DWORD dwSizeLeft;
  783. DWORD dwSizeRight;
  784. BYTE* pDataBuffLeft = NULL;
  785. BYTE* pDataBuffRight = NULL;
  786. //
  787. // First find out how much memory to allocate
  788. //
  789. nResult = RegQueryValueEx(hLeftKey,
  790. szValueName,
  791. 0,
  792. &dwTypeLeft,
  793. NULL,
  794. &dwSizeLeft);
  795. if (nResult != ERROR_SUCCESS)
  796. {
  797. return nResult;
  798. }
  799. nResult = RegQueryValueEx(hRightKey,
  800. szValueName,
  801. 0,
  802. &dwTypeRight,
  803. NULL,
  804. &dwSizeRight);
  805. if (nResult != ERROR_SUCCESS)
  806. {
  807. return nResult;
  808. }
  809. pDataBuffLeft = (BYTE*) calloc(dwSizeLeft + 1, sizeof(BYTE));
  810. if (!pDataBuffLeft) {
  811. nResult = ERROR_NOT_ENOUGH_MEMORY;
  812. goto Cleanup;
  813. }
  814. pDataBuffRight = (BYTE*) calloc(dwSizeRight + 1, sizeof(BYTE));
  815. if (!pDataBuffRight) {
  816. nResult = ERROR_NOT_ENOUGH_MEMORY;
  817. goto Cleanup;
  818. }
  819. //
  820. // Now get the data
  821. //
  822. nResult = RegQueryValueEx(hLeftKey,
  823. szValueName,
  824. 0,
  825. &dwTypeLeft,
  826. (LPBYTE) pDataBuffLeft,
  827. &dwSizeLeft);
  828. if (nResult == ERROR_SUCCESS)
  829. {
  830. nResult = RegQueryValueEx(hRightKey,
  831. szValueName,
  832. 0,
  833. &dwTypeRight,
  834. (LPBYTE) pDataBuffRight,
  835. &dwSizeRight);
  836. }
  837. if(nResult != ERROR_SUCCESS)
  838. {
  839. if(pDataBuffLeft)
  840. free(pDataBuffLeft);
  841. if(pDataBuffRight)
  842. free(pDataBuffRight);
  843. return nResult;
  844. }
  845. if( dwTypeLeft != dwTypeRight ||
  846. dwSizeLeft != dwSizeRight ||
  847. CompareByteData(pDataBuffLeft, pDataBuffRight, dwSizeLeft) )
  848. {
  849. if( nOutputType == OUTPUTTYPE_DIFF ||
  850. nOutputType == OUTPUTTYPE_ALL )
  851. {
  852. // print left and right
  853. PrintValue(szLeftFullKeyName,
  854. szValueName,
  855. dwTypeLeft,
  856. pDataBuffLeft,
  857. dwSizeLeft,
  858. PRINTTYPE_LEFT);
  859. PrintValue(szRightFullKeyName,
  860. szValueName,
  861. dwTypeRight,
  862. pDataBuffRight,
  863. dwSizeRight,
  864. PRINTTYPE_RIGHT);
  865. }
  866. g_bHasDifference = TRUE;
  867. }
  868. else // they are the same
  869. {
  870. if( nOutputType == OUTPUTTYPE_SAME ||
  871. nOutputType == OUTPUTTYPE_ALL )
  872. {
  873. PrintValue(szLeftFullKeyName,
  874. szValueName,
  875. dwTypeLeft,
  876. pDataBuffLeft,
  877. dwSizeLeft,
  878. PRINTTYPE_SAME);
  879. }
  880. }
  881. Cleanup:
  882. if(pDataBuffLeft)
  883. free(pDataBuffLeft);
  884. if(pDataBuffRight)
  885. free(pDataBuffRight);
  886. return nResult;
  887. }
  888. LONG PrintKey(HKEY hKey,
  889. TCHAR* szFullKeyName,
  890. TCHAR* szSubKeyName,
  891. int nPrintType)
  892. {
  893. LONG nResult;
  894. HKEY hSubKey;
  895. // make sure key is there
  896. nResult = RegOpenKeyEx(hKey,
  897. szSubKeyName,
  898. 0,
  899. KEY_READ,
  900. &hSubKey);
  901. if (nResult != ERROR_SUCCESS)
  902. return nResult;
  903. RegCloseKey(hSubKey);
  904. // print type
  905. if(nPrintType == PRINTTYPE_LEFT)
  906. MyTPrintf(stdout,_T("< "));
  907. else if(nPrintType == PRINTTYPE_RIGHT)
  908. MyTPrintf(stdout,_T("> "));
  909. else if(nPrintType == PRINTTYPE_SAME)
  910. MyTPrintf(stdout,_T("= "));
  911. MyTPrintf(stdout,_T("Key: %s\\%s\r\n"), szFullKeyName, szSubKeyName);
  912. return nResult;
  913. }
  914. LONG OutputValue(HKEY hKey,
  915. TCHAR* szFullKeyName,
  916. TCHAR* szValueName,
  917. int nPrintType)
  918. {
  919. LONG nResult = ERROR_SUCCESS;
  920. DWORD dwType;
  921. DWORD dwSize;
  922. BYTE* pDataBuff;
  923. //
  924. // First find out how much memory to allocate
  925. //
  926. nResult = RegQueryValueEx(hKey,
  927. szValueName,
  928. 0,
  929. &dwType,
  930. NULL,
  931. &dwSize);
  932. if (nResult != ERROR_SUCCESS)
  933. {
  934. return nResult;
  935. }
  936. pDataBuff = (BYTE*) calloc(dwSize + 1, sizeof(BYTE));
  937. if (!pDataBuff) {
  938. return ERROR_NOT_ENOUGH_MEMORY;
  939. }
  940. //
  941. // Now get the data
  942. //
  943. nResult = RegQueryValueEx(hKey,
  944. szValueName,
  945. 0,
  946. &dwType,
  947. (LPBYTE) pDataBuff,
  948. &dwSize);
  949. if(nResult == ERROR_SUCCESS)
  950. {
  951. PrintValue(szFullKeyName,
  952. szValueName,
  953. dwType,
  954. pDataBuff,
  955. dwSize,
  956. nPrintType);
  957. }
  958. if(pDataBuff)
  959. free(pDataBuff);
  960. return nResult;
  961. }
  962. void PrintValue(TCHAR* szFullKeyName,
  963. TCHAR* szValueName,
  964. DWORD dwType,
  965. BYTE* pData,
  966. DWORD dwSize,
  967. int nPrintType)
  968. {
  969. DWORD i;
  970. TCHAR szTypeStr[25];
  971. // print type
  972. if(nPrintType == PRINTTYPE_LEFT)
  973. MyTPrintf(stdout,_T("< "));
  974. else if(nPrintType == PRINTTYPE_RIGHT)
  975. MyTPrintf(stdout,_T("> "));
  976. else if(nPrintType == PRINTTYPE_SAME)
  977. MyTPrintf(stdout,_T("= "));
  978. // first Print Key
  979. MyTPrintf(stdout,_T("Value: %s"), szFullKeyName);
  980. // then print ValueName Type Data
  981. GetTypeStrFromType(szTypeStr, dwType);
  982. if(_tcslen(szValueName) == 0) // no name
  983. {
  984. MyTPrintf(stdout,_T(" <NO NAME> %s "), szTypeStr);
  985. }
  986. else
  987. {
  988. MyTPrintf(stdout,_T(" %s %s "), szValueName, szTypeStr);
  989. }
  990. switch (dwType)
  991. {
  992. case REG_BINARY:
  993. for(i=0; i<dwSize; i++)
  994. {
  995. MyTPrintf(stdout,_T("%02X"),pData[i]);
  996. }
  997. break;
  998. case REG_DWORD:
  999. case REG_DWORD_BIG_ENDIAN:
  1000. MyTPrintf(stdout,_T("0x%x"), *((DWORD*)pData) );
  1001. break;
  1002. case REG_MULTI_SZ:
  1003. {
  1004. //
  1005. // Replace '\0' with "\0" for MULTI_SZ
  1006. //
  1007. TCHAR* pEnd = (TCHAR*) pData;
  1008. while( (BYTE*)pEnd < pData + dwSize )
  1009. {
  1010. if(*pEnd == 0)
  1011. {
  1012. MyTPrintf(stdout,_T("\\0"));
  1013. pEnd++;
  1014. }
  1015. else
  1016. {
  1017. MyTPrintf(stdout,_T("%s"), pEnd);
  1018. pEnd += _tcslen(pEnd);
  1019. }
  1020. }
  1021. }
  1022. break;
  1023. default:
  1024. MyTPrintf(stdout,_T("%s"), (TCHAR*) pData);
  1025. break;
  1026. }
  1027. MyTPrintf(stdout,_T("\r\n"));
  1028. }
  1029. BOOL CompareByteData(BYTE* pDataBuffLeft, BYTE* pDataBuffRight, DWORD dwSize)
  1030. {
  1031. BOOL bDiff = FALSE;
  1032. DWORD dw;
  1033. for(dw=0; dw<dwSize; dw++)
  1034. {
  1035. if(pDataBuffLeft[dw] != pDataBuffRight[dw])
  1036. {
  1037. bDiff = TRUE;
  1038. break;
  1039. }
  1040. }
  1041. return bDiff;
  1042. }