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.

470 lines
12 KiB

  1. //-----------------------------------------------------------------------//
  2. //
  3. // File: save.cpp
  4. // Created: March 1997
  5. // By: Martin Holladay (a-martih)
  6. // Purpose: Registry Save Support for REG.CPP
  7. // Modification History:
  8. // Copied from Copy.cpp and modificd - May 1997 (a-martih)
  9. // Aug 1997 - MartinHo
  10. // Fixed bug which didn't allow you to specify a ROOT key.
  11. // Example REG SAVE HKLM\Software didn't work - but should have
  12. // April 1999 Zeyong Xu: re-design, revision -> version 2.0
  13. //
  14. //------------------------------------------------------------------------//
  15. #include "stdafx.h"
  16. #include "reg.h"
  17. //-----------------------------------------------------------------------//
  18. //
  19. // SaveHive()
  20. //
  21. //-----------------------------------------------------------------------//
  22. LONG SaveHive(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
  23. {
  24. LONG nResult;
  25. HKEY hKey;
  26. //
  27. // Parse the cmd-line
  28. //
  29. nResult = ParseSaveCmdLine(pAppVars, argc, argv);
  30. if (nResult != ERROR_SUCCESS)
  31. {
  32. return nResult;
  33. }
  34. #ifndef REG_FOR_WIN2000 // ANSI version for Win98
  35. // because RegLoadKey() failed on remote Win98,
  36. // works local only on Win98, cancel SAVE for remote
  37. if(pAppVars->bUseRemoteMachine)
  38. return REG_STATUS_NONREMOTABLE;
  39. #endif
  40. //
  41. // Connect to the Remote Machine - if applicable
  42. //
  43. nResult = RegConnectMachine(pAppVars);
  44. if (nResult != ERROR_SUCCESS)
  45. {
  46. return nResult;
  47. }
  48. //
  49. // Open the key
  50. //
  51. if ((nResult = RegOpenKeyEx(pAppVars->hRootKey,
  52. pAppVars->szSubKey,
  53. 0,
  54. KEY_READ,
  55. &hKey)) == ERROR_SUCCESS)
  56. {
  57. //
  58. // Acquire the necessary privilages and call the API
  59. //
  60. nResult = RegAdjustTokenPrivileges(pAppVars->szMachineName,
  61. SE_BACKUP_NAME,
  62. SE_PRIVILEGE_ENABLED);
  63. if (nResult == ERROR_SUCCESS)
  64. {
  65. nResult = RegSaveKey(hKey, pAppVars->szValueName, NULL);
  66. }
  67. RegCloseKey(hKey);
  68. }
  69. #ifndef REG_FOR_WIN2000
  70. // since the newly created file has the hidden attibute on win98,
  71. // remove this hidden attribute (work for local machine only)
  72. if (nResult == ERROR_SUCCESS)
  73. SetFileAttributes(pAppVars->szValueName, FILE_ATTRIBUTE_ARCHIVE);
  74. #endif
  75. return nResult;
  76. }
  77. //-----------------------------------------------------------------------//
  78. //
  79. // RestoreHive()
  80. //
  81. //-----------------------------------------------------------------------//
  82. LONG RestoreHive(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
  83. {
  84. LONG nResult;
  85. HKEY hKey;
  86. //
  87. // Parse the cmd-line
  88. //
  89. nResult = ParseSaveCmdLine(pAppVars, argc, argv);
  90. if (nResult != ERROR_SUCCESS)
  91. {
  92. return nResult;
  93. }
  94. #ifndef REG_FOR_WIN2000 // ANSI version for Win98
  95. // because RegLoadKey() failed on remote Win98,
  96. // works local only on Win98
  97. if(pAppVars->bUseRemoteMachine)
  98. return REG_STATUS_NONREMOTABLE;
  99. #endif
  100. //
  101. // Connect to the Remote Machine(s) - if applicable
  102. //
  103. nResult = RegConnectMachine(pAppVars);
  104. if (nResult != ERROR_SUCCESS)
  105. {
  106. return nResult;
  107. }
  108. //
  109. // Open the Key
  110. //
  111. if ((nResult = RegOpenKeyEx(pAppVars->hRootKey,
  112. pAppVars->szSubKey,
  113. 0,
  114. KEY_ALL_ACCESS,
  115. &hKey)) == ERROR_SUCCESS)
  116. {
  117. #ifdef REG_FOR_WIN2000 // works on Win2000(unicode) only, not Win98(ansi)
  118. // Acquire the necessary privilages and call the API
  119. nResult = RegAdjustTokenPrivileges(pAppVars->szMachineName,
  120. SE_RESTORE_NAME,
  121. SE_PRIVILEGE_ENABLED);
  122. if (nResult == ERROR_SUCCESS)
  123. {
  124. nResult = RegRestoreKey(hKey, pAppVars->szValueName, 0);
  125. }
  126. RegCloseKey(hKey);
  127. #else // works on Win98(ansi) only, not Win2000(unicode)
  128. RegCloseKey(hKey);
  129. nResult = RegRestoreKeyWin98(pAppVars->hRootKey,
  130. pAppVars->szSubKey,
  131. pAppVars->szValueName);
  132. #endif
  133. }
  134. return nResult;
  135. }
  136. //-----------------------------------------------------------------------//
  137. //
  138. // LoadHive()
  139. //
  140. //-----------------------------------------------------------------------//
  141. LONG LoadHive(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
  142. {
  143. LONG nResult;
  144. //
  145. // Parse the cmd-line
  146. //
  147. nResult = ParseSaveCmdLine(pAppVars, argc, argv);
  148. if (nResult != ERROR_SUCCESS)
  149. {
  150. return nResult;
  151. }
  152. #ifndef REG_FOR_WIN2000 // ANSI version for Win98
  153. // because RegLoadKey() failed on remote Win98,
  154. // works local only on Win98
  155. if(pAppVars->bUseRemoteMachine)
  156. return REG_STATUS_NONREMOTABLE;
  157. #endif
  158. //
  159. // Connect to the Remote Machine(s) - if applicable
  160. //
  161. nResult = RegConnectMachine(pAppVars);
  162. if (nResult != ERROR_SUCCESS)
  163. {
  164. return nResult;
  165. }
  166. //
  167. // Acquire the necessary privilages and call the API
  168. //
  169. nResult = RegAdjustTokenPrivileges(pAppVars->szMachineName,
  170. SE_RESTORE_NAME,
  171. SE_PRIVILEGE_ENABLED);
  172. if (nResult == ERROR_SUCCESS)
  173. {
  174. nResult = RegLoadKey(pAppVars->hRootKey,
  175. pAppVars->szSubKey,
  176. pAppVars->szValueName);
  177. }
  178. return nResult;
  179. }
  180. //-----------------------------------------------------------------------//
  181. //
  182. // UnLoadHive()
  183. //
  184. //-----------------------------------------------------------------------//
  185. LONG UnLoadHive(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
  186. {
  187. LONG nResult;
  188. //
  189. // Parse the cmd-line
  190. //
  191. nResult = ParseUnLoadCmdLine(pAppVars, argc, argv);
  192. if (nResult != ERROR_SUCCESS)
  193. {
  194. return nResult;
  195. }
  196. #ifndef REG_FOR_WIN2000 // ANSI version for Win98
  197. // because RegUnLoadKey() failed on remote Win98,
  198. // works local only on Win98
  199. if(pAppVars->bUseRemoteMachine)
  200. return REG_STATUS_NONREMOTABLE;
  201. #endif
  202. //
  203. // Connect to the Remote Machine(s) - if applicable
  204. //
  205. nResult = RegConnectMachine(pAppVars);
  206. if (nResult != ERROR_SUCCESS)
  207. {
  208. return nResult;
  209. }
  210. //
  211. // Acquire the necessary privilages and call the API
  212. //
  213. nResult = RegAdjustTokenPrivileges(pAppVars->szMachineName,
  214. SE_RESTORE_NAME,
  215. SE_PRIVILEGE_ENABLED);
  216. if (nResult == ERROR_SUCCESS)
  217. {
  218. nResult = RegUnLoadKey(pAppVars->hRootKey, pAppVars->szSubKey);
  219. }
  220. return nResult;
  221. }
  222. //------------------------------------------------------------------------//
  223. //
  224. // ParseSaveCmdLine()
  225. //
  226. //------------------------------------------------------------------------//
  227. REG_STATUS ParseSaveCmdLine(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
  228. {
  229. REG_STATUS nResult = ERROR_SUCCESS;
  230. //
  231. // Do we have a *valid* number of cmd-line params
  232. //
  233. if (argc < 4)
  234. {
  235. return REG_STATUS_TOFEWPARAMS;
  236. }
  237. else if (argc > 4)
  238. {
  239. return REG_STATUS_TOMANYPARAMS;
  240. }
  241. // Machine Name and Registry key
  242. //
  243. nResult = BreakDownKeyString(argv[2], pAppVars);
  244. if(nResult != ERROR_SUCCESS)
  245. return nResult;
  246. //
  247. // Get the FileName - using the szValueName string field to hold it
  248. //
  249. pAppVars->szValueName = (TCHAR*) calloc(_tcslen(argv[3]) + 1,
  250. sizeof(TCHAR));
  251. if (!pAppVars->szValueName) {
  252. return ERROR_NOT_ENOUGH_MEMORY;
  253. }
  254. _tcscpy(pAppVars->szValueName, argv[3]);
  255. return nResult;
  256. }
  257. //------------------------------------------------------------------------//
  258. //
  259. // ParseUnLoadCmdLine()
  260. //
  261. //------------------------------------------------------------------------//
  262. REG_STATUS ParseUnLoadCmdLine(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
  263. {
  264. REG_STATUS nResult = ERROR_SUCCESS;
  265. //
  266. // Do we have a *valid* number of cmd-line params
  267. //
  268. if (argc < 3)
  269. {
  270. return REG_STATUS_TOFEWPARAMS;
  271. }
  272. else if (argc > 3)
  273. {
  274. return REG_STATUS_TOMANYPARAMS;
  275. }
  276. // Machine Name and Registry key
  277. //
  278. nResult = BreakDownKeyString(argv[2], pAppVars);
  279. return nResult;
  280. }
  281. //------------------------------------------------------------------------//
  282. //
  283. // AdjustTokenPrivileges()
  284. //
  285. //------------------------------------------------------------------------//
  286. LONG RegAdjustTokenPrivileges(TCHAR *szMachine,
  287. TCHAR *szPrivilege,
  288. LONG nAttribute)
  289. {
  290. // works on Win2000(unicode) only, not Win98(ansi)
  291. #ifdef REG_FOR_WIN2000
  292. HANDLE hToken;
  293. TOKEN_PRIVILEGES tkp;
  294. if(!OpenProcessToken(GetCurrentProcess(),
  295. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  296. &hToken))
  297. {
  298. return GetLastError();
  299. }
  300. if(!LookupPrivilegeValue(szMachine,
  301. szPrivilege,
  302. &tkp.Privileges[0].Luid))
  303. {
  304. return GetLastError();
  305. }
  306. tkp.PrivilegeCount = 1;
  307. tkp.Privileges[0].Attributes = nAttribute;
  308. if(!AdjustTokenPrivileges(hToken,
  309. FALSE,
  310. &tkp,
  311. 0,
  312. (PTOKEN_PRIVILEGES) NULL,
  313. NULL))
  314. {
  315. return GetLastError();
  316. }
  317. #endif
  318. return ERROR_SUCCESS;
  319. }
  320. //-----------------------------------------------------------------------//
  321. // RegRestoreKeyWin98() for Win98 only (ANSI version)
  322. // because RegRestoreKey() does not work on Win98
  323. //-----------------------------------------------------------------------//
  324. LONG RegRestoreKeyWin98(HKEY hRootKey, // handle to a root key
  325. TCHAR* szSubKey, // name of subkey
  326. TCHAR* szFile) // hive filename
  327. {
  328. LONG nResult;
  329. HKEY hKey;
  330. HKEY hTempKey;
  331. TCHAR szTempHive[50];
  332. LONG nRetUnload;
  333. // avoid key name conflict, reduce failed possibility
  334. _tcscpy(szTempHive, _T("TEMP_HIVE_FOR_RESTORE_0000"));
  335. if(_tcsicmp(szSubKey, szTempHive) == 0)
  336. _tcscpy(szTempHive, _T("TEMP_HIVE_FOR_RESTORE_1111"));
  337. nResult = RegOpenKeyEx(hRootKey,
  338. szTempHive,
  339. 0,
  340. KEY_READ,
  341. &hTempKey);
  342. if(nResult == ERROR_SUCCESS)
  343. {
  344. RegCloseKey(hTempKey);
  345. _tcscpy(szTempHive, _T("TEMP_HIVE_FOR_RESTORE_RETRY_0000"));
  346. }
  347. // load hive file to szTempHive key
  348. nResult = RegLoadKey(hRootKey,
  349. szTempHive,
  350. szFile);
  351. if(nResult != ERROR_SUCCESS)
  352. return nResult;
  353. nResult = RecursiveDeleteKey(hRootKey,
  354. szSubKey);
  355. if(nResult == ERROR_SUCCESS)
  356. {
  357. // Create the Key
  358. nResult = RegCreateKeyEx(hRootKey,
  359. szSubKey,
  360. 0,
  361. NULL,
  362. REG_OPTION_NON_VOLATILE,
  363. KEY_ALL_ACCESS,
  364. NULL,
  365. &hKey,
  366. NULL);
  367. if(nResult == ERROR_SUCCESS)
  368. {
  369. // Now open TempHive key
  370. nResult = RegOpenKeyEx(hRootKey,
  371. szTempHive,
  372. 0,
  373. KEY_READ,
  374. &hTempKey);
  375. if (nResult == ERROR_SUCCESS)
  376. {
  377. // Recursively copy the entire hive
  378. BOOL bOverWriteAll = TRUE;
  379. nResult = CopyEnumerateKey(hTempKey,
  380. szTempHive,
  381. hKey,
  382. szSubKey,
  383. &bOverWriteAll,
  384. TRUE);
  385. RegCloseKey(hTempKey);
  386. }
  387. RegCloseKey(hKey);
  388. }
  389. }
  390. // unload the temphive key
  391. nRetUnload = RegUnLoadKey(hRootKey, szTempHive);
  392. if(nResult == ERROR_SUCCESS)
  393. nResult = nRetUnload;
  394. return nResult;
  395. }