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.

545 lines
15 KiB

  1. //-----------------------------------------------------------------------//
  2. //
  3. // File: copy.cpp
  4. // Created: April 1997
  5. // By: Martin Holladay (a-martih)
  6. // Purpose: Registry Copy Support for REG.CPP
  7. // Modification History:
  8. // Copied from Update.cpp and modificd - April 1997 (a-martih)
  9. // April 1999 Zeyong Xu: re-design, revision -> version 2.0
  10. //
  11. //------------------------------------------------------------------------//
  12. #include "stdafx.h"
  13. #include "reg.h"
  14. //-----------------------------------------------------------------------//
  15. //
  16. // CopyRegistry()
  17. //
  18. //-----------------------------------------------------------------------//
  19. LONG CopyRegistry(PAPPVARS pAppVars,
  20. PAPPVARS pDstVars,
  21. UINT argc,
  22. TCHAR *argv[])
  23. {
  24. LONG nResult;
  25. HKEY hKey;
  26. HKEY hDstKey;
  27. DWORD dwDisposition;
  28. BOOL bOverWriteAll = FALSE;
  29. //
  30. // Parse the cmd-line
  31. //
  32. nResult = ParseCopyCmdLine(pAppVars, pDstVars, argc, argv);
  33. if (nResult != ERROR_SUCCESS)
  34. {
  35. return nResult;
  36. }
  37. //
  38. // Connect to the Remote Machine(s) - if applicable
  39. //
  40. nResult = RegConnectMachine(pAppVars);
  41. if (nResult != ERROR_SUCCESS)
  42. {
  43. return nResult;
  44. }
  45. nResult = RegConnectMachine(pDstVars);
  46. if (nResult != ERROR_SUCCESS)
  47. {
  48. return nResult;
  49. }
  50. //
  51. // Now implement the body of the Copy Operation
  52. //
  53. nResult = RegOpenKeyEx(pAppVars->hRootKey,
  54. pAppVars->szSubKey,
  55. 0,
  56. KEY_READ,
  57. &hKey);
  58. if (nResult != ERROR_SUCCESS)
  59. {
  60. return nResult;
  61. }
  62. if (pAppVars->hRootKey == pDstVars->hRootKey &&
  63. _tcsicmp(pAppVars->szFullKey, pDstVars->szFullKey) == 0)
  64. {
  65. RegCloseKey(hKey);
  66. return REG_STATUS_COPYTOSELF;
  67. }
  68. else
  69. {
  70. //
  71. // Different Key or Different Root or Different Machine
  72. // So Create/Open it
  73. //
  74. nResult = RegCreateKeyEx(pDstVars->hRootKey,
  75. pDstVars->szSubKey,
  76. 0,
  77. NULL,
  78. REG_OPTION_NON_VOLATILE,
  79. KEY_ALL_ACCESS,
  80. NULL,
  81. &hDstKey,
  82. &dwDisposition);
  83. if (nResult != ERROR_SUCCESS)
  84. {
  85. RegCloseKey(hKey);
  86. return nResult;
  87. }
  88. }
  89. //
  90. // Recursively copy all subkeys and values
  91. //
  92. bOverWriteAll = pAppVars->bForce;
  93. nResult = CopyEnumerateKey(hKey,
  94. pAppVars->szSubKey,
  95. hDstKey,
  96. pDstVars->szSubKey,
  97. &bOverWriteAll,
  98. pAppVars->bRecurseSubKeys);
  99. //
  100. // lets clean up
  101. //
  102. RegCloseKey(hDstKey);
  103. RegCloseKey(hKey);
  104. return nResult;
  105. }
  106. REG_STATUS ParseCopyCmdLine(PAPPVARS pAppVars,
  107. PAPPVARS pDstVars,
  108. UINT argc,
  109. TCHAR *argv[])
  110. {
  111. UINT i;
  112. REG_STATUS nResult = ERROR_SUCCESS;
  113. //
  114. // Do we have a *valid* number of cmd-line params
  115. //
  116. if(argc < 4)
  117. {
  118. return REG_STATUS_TOFEWPARAMS;
  119. }
  120. else if(argc > 6)
  121. {
  122. return REG_STATUS_TOMANYPARAMS;
  123. }
  124. //
  125. // Source Machine Name and Registry key
  126. //
  127. nResult = BreakDownKeyString(argv[2], pAppVars);
  128. if(nResult != ERROR_SUCCESS)
  129. return nResult;
  130. //
  131. // Destination Machine Name and Registry key
  132. //
  133. nResult = BreakDownKeyString(argv[3], pDstVars);
  134. if(nResult != ERROR_SUCCESS)
  135. return nResult;
  136. // parsing
  137. for(i=4; i<argc; i++)
  138. {
  139. if(!_tcsicmp(argv[i], _T("/f")))
  140. {
  141. pAppVars->bForce = TRUE;
  142. }
  143. else if(!_tcsicmp(argv[i], _T("/s")))
  144. {
  145. pAppVars->bRecurseSubKeys = TRUE;
  146. }
  147. else
  148. {
  149. nResult = REG_STATUS_INVALIDPARAMS;
  150. }
  151. }
  152. return nResult;
  153. }
  154. //-----------------------------------------------------------------------//
  155. //
  156. // QueryValue()
  157. //
  158. //-----------------------------------------------------------------------//
  159. LONG CopyValue(HKEY hKey,
  160. TCHAR* szValueName,
  161. HKEY hDstKey,
  162. TCHAR* szDstValueName,
  163. BOOL *pbOverWriteAll)
  164. {
  165. LONG nResult;
  166. DWORD dwType, dwTmpType;
  167. DWORD dwSize, dwTmpSize;
  168. BYTE *pBuff;
  169. TCHAR ch;
  170. PTSTR PromptBuffer,PromptBufferFmt;
  171. DWORD PromptBufferSize;
  172. //
  173. // First find out how much memory to allocate.
  174. //
  175. nResult = RegQueryValueEx(hKey,
  176. szValueName,
  177. 0,
  178. &dwType,
  179. NULL,
  180. &dwSize);
  181. if (nResult != ERROR_SUCCESS)
  182. {
  183. return nResult;
  184. }
  185. pBuff = (BYTE*) calloc(dwSize + 1, sizeof(BYTE));
  186. if (!pBuff)
  187. return ERROR_NOT_ENOUGH_MEMORY;
  188. //
  189. // Now get the data
  190. //
  191. nResult = RegQueryValueEx(hKey,
  192. szValueName,
  193. 0,
  194. &dwType,
  195. (LPBYTE) pBuff,
  196. &dwSize);
  197. if (nResult != ERROR_SUCCESS)
  198. {
  199. return nResult;
  200. }
  201. //
  202. // Copy it to the destination
  203. //
  204. if (!*pbOverWriteAll)
  205. {
  206. //
  207. // See if it already exists
  208. //
  209. nResult = RegQueryValueEx(hDstKey,
  210. szDstValueName,
  211. 0,
  212. &dwTmpType,
  213. NULL,
  214. &dwTmpSize);
  215. if (nResult == ERROR_SUCCESS)
  216. {
  217. BOOL bGoodResponse = FALSE;
  218. //
  219. // allocate and fill in the prompt message
  220. //
  221. PromptBufferSize = 100;
  222. PromptBufferSize += _tcslen(
  223. szDstValueName
  224. ? szDstValueName
  225. : g_NoName);
  226. PromptBuffer = calloc(PromptBufferSize, sizeof(TCHAR));
  227. if (!PromptBuffer) {
  228. return ERROR_SUCCESS;
  229. }
  230. PromptBufferFmt = calloc(PromptBufferSize, sizeof(TCHAR));
  231. if (!PromptBufferFmt) {
  232. free(PromptBuffer);
  233. return ERROR_SUCCESS;
  234. }
  235. LoadString( NULL, IDS_OVERWRITE, PromptBufferFmt, PromptBufferSize);
  236. wsprintf(
  237. PromptBuffer,
  238. PromptBufferFmt,
  239. szDstValueName
  240. ? szDstValueName
  241. : g_NoName );
  242. free( PromptBufferFmt);
  243. while (!bGoodResponse) {
  244. MyTPrintf(stdout,PromptBuffer);
  245. ch = _gettchar();
  246. _flushall();
  247. switch (ch) {
  248. case _T('a'): //fall through
  249. case _T('y'): //fall through
  250. case _T('n'):
  251. bGoodResponse = TRUE;
  252. break;
  253. default:
  254. //
  255. // keep scanning.
  256. //
  257. ;
  258. }
  259. }
  260. free(PromptBuffer);
  261. MyTPrintf(stdout,_T("\r\n"));
  262. if (ch == _T('a') || ch == _T('A'))
  263. {
  264. *pbOverWriteAll = TRUE;
  265. bGoodResponse = TRUE;
  266. }
  267. else if (ch == _T('y') || ch == _T('Y'))
  268. {
  269. bGoodResponse = TRUE;
  270. }
  271. else if (ch == _T('n') || ch == _T('N'))
  272. {
  273. return ERROR_SUCCESS;
  274. }
  275. }
  276. }
  277. //
  278. // Write the Value
  279. //
  280. nResult = RegSetValueEx(hDstKey,
  281. szDstValueName,
  282. 0,
  283. dwType,
  284. (PBYTE) pBuff,
  285. dwSize);
  286. if(pBuff)
  287. free(pBuff);
  288. return nResult;
  289. }
  290. //-----------------------------------------------------------------------//
  291. //
  292. // EnumerateKey() - Recursive
  293. //
  294. //-----------------------------------------------------------------------//
  295. LONG CopyEnumerateKey(HKEY hKey,
  296. TCHAR* szSubKey,
  297. HKEY hDstKey,
  298. TCHAR* szDstSubKey,
  299. BOOL *pbOverWriteAll,
  300. BOOL bRecurseSubKeys)
  301. {
  302. DWORD nResult;
  303. UINT i;
  304. DWORD dwSize;
  305. DWORD dwDisposition;
  306. HKEY hSubKey;
  307. HKEY hDstSubKey;
  308. TCHAR* szNameBuf;
  309. TCHAR* szTempName;
  310. TCHAR* szDstTempName;
  311. // query source key info
  312. DWORD dwLenOfKeyName;
  313. DWORD dwLenOfValueName;
  314. nResult = RegQueryInfoKey(hKey,
  315. NULL,
  316. NULL,
  317. NULL,
  318. NULL,
  319. &dwLenOfKeyName,
  320. NULL,
  321. NULL,
  322. &dwLenOfValueName,
  323. NULL,
  324. NULL,
  325. NULL);
  326. if (nResult != ERROR_SUCCESS)
  327. {
  328. return nResult;
  329. }
  330. #ifndef REG_FOR_WIN2000 // ansi version for win98
  331. // fix API bugs: RegQueryInfoKey() returns non-correct length values
  332. // on remote Win98
  333. if(dwLenOfKeyName < MAX_PATH)
  334. dwLenOfKeyName = MAX_PATH;
  335. if(dwLenOfValueName < MAX_PATH)
  336. dwLenOfValueName = MAX_PATH;
  337. #endif
  338. //
  339. // First enumerate all of the values
  340. //
  341. dwLenOfValueName++;
  342. szNameBuf = (TCHAR*) calloc(dwLenOfValueName, sizeof(TCHAR));
  343. if (!szNameBuf) {
  344. return ERROR_NOT_ENOUGH_MEMORY;
  345. }
  346. i = 0;
  347. do
  348. {
  349. dwSize = dwLenOfValueName;
  350. nResult = RegEnumValue(hKey,
  351. i,
  352. szNameBuf,
  353. &dwSize,
  354. NULL,
  355. NULL,
  356. NULL,
  357. NULL);
  358. if (nResult == ERROR_SUCCESS)
  359. {
  360. nResult = CopyValue(hKey,
  361. szNameBuf,
  362. hDstKey,
  363. szNameBuf,
  364. pbOverWriteAll);
  365. }
  366. i++;
  367. } while (nResult == ERROR_SUCCESS);
  368. if(szNameBuf)
  369. free(szNameBuf);
  370. if (nResult == ERROR_NO_MORE_ITEMS)
  371. nResult = ERROR_SUCCESS;
  372. if( !bRecurseSubKeys ||
  373. nResult != ERROR_SUCCESS )
  374. return nResult;
  375. //
  376. // Now Enumerate all of the keys
  377. //
  378. dwLenOfKeyName++;
  379. szNameBuf = (TCHAR*) calloc(dwLenOfKeyName, sizeof(TCHAR));
  380. if (!szNameBuf) {
  381. return ERROR_NOT_ENOUGH_MEMORY;
  382. }
  383. i = 0;
  384. do
  385. {
  386. dwSize = dwLenOfKeyName;
  387. nResult = RegEnumKeyEx(hKey,
  388. i,
  389. szNameBuf,
  390. &dwSize,
  391. NULL,
  392. NULL,
  393. NULL,
  394. NULL);
  395. //
  396. // Else open up the subkey, create the destination key
  397. // and enumerate it
  398. //
  399. if (nResult == ERROR_SUCCESS)
  400. {
  401. nResult = RegOpenKeyEx(hKey,
  402. szNameBuf,
  403. 0,
  404. KEY_READ,
  405. &hSubKey);
  406. }
  407. if (nResult == ERROR_SUCCESS)
  408. {
  409. nResult = RegCreateKeyEx(hDstKey,
  410. szNameBuf,
  411. 0,
  412. NULL,
  413. REG_OPTION_NON_VOLATILE,
  414. KEY_ALL_ACCESS,
  415. NULL,
  416. &hDstSubKey,
  417. &dwDisposition);
  418. if (nResult == ERROR_SUCCESS)
  419. {
  420. //
  421. // Build up the needed string and go to town enumerating again
  422. //
  423. szTempName = (TCHAR*) calloc(_tcslen(szSubKey) +
  424. _tcslen(szNameBuf) +
  425. 3,
  426. sizeof(TCHAR));
  427. if (!szTempName) {
  428. nResult = ERROR_NOT_ENOUGH_MEMORY;
  429. goto Cleanup;
  430. }
  431. if(_tcslen(szSubKey) > 0)
  432. {
  433. _tcscpy(szTempName, szSubKey);
  434. _tcscat(szTempName, _T("\\"));
  435. }
  436. _tcscat(szTempName, szNameBuf);
  437. szDstTempName = (TCHAR*) calloc(_tcslen(szDstSubKey) +
  438. _tcslen(szNameBuf) +
  439. 3,
  440. sizeof(TCHAR));
  441. if (!szDstTempName) {
  442. free (szTempName);
  443. nResult = ERROR_NOT_ENOUGH_MEMORY;
  444. goto Cleanup;
  445. }
  446. if(_tcslen(szDstSubKey) > 0)
  447. {
  448. _tcscpy(szDstTempName, szDstSubKey);
  449. _tcscat(szDstTempName, _T("\\"));
  450. }
  451. _tcscat(szDstTempName, szNameBuf);
  452. // recursive copy
  453. nResult = CopyEnumerateKey(hSubKey,
  454. szTempName,
  455. hDstSubKey,
  456. szDstTempName,
  457. pbOverWriteAll,
  458. bRecurseSubKeys);
  459. RegCloseKey(hSubKey);
  460. RegCloseKey(hDstSubKey);
  461. if(szTempName)
  462. free(szTempName);
  463. if(szDstTempName)
  464. free(szDstTempName);
  465. }
  466. }
  467. i++;
  468. } while (nResult == ERROR_SUCCESS);
  469. Cleanup:
  470. if(szNameBuf)
  471. free(szNameBuf);
  472. if (nResult == ERROR_NO_MORE_ITEMS)
  473. nResult = ERROR_SUCCESS;
  474. return nResult;
  475. }