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.

497 lines
12 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. regcopy.c
  5. Abstract:
  6. This is for supporting copying and munging the registry files.
  7. Author:
  8. Sean Selitrennikoff - 4/5/98
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. typedef BOOL (*PFNGETPROFILESDIRECTORYW)(LPWSTR lpProfile, LPDWORD dwSize);
  14. PWSTR HivePath;
  15. HKEY HiveRoot;
  16. PWSTR HiveName;
  17. REG_CONTEXT RegistryContext;
  18. PWSTR MachineName;
  19. PWSTR HiveFileName;
  20. PWSTR HiveRootName;
  21. DWORD
  22. DoFullRegBackup(
  23. PWCHAR MirrorRoot
  24. )
  25. /*++
  26. Routine Description:
  27. This routine copies all the registries to the given server path.
  28. Arguments:
  29. None.
  30. Return Value:
  31. NO_ERROR if everything was backed up properly, else the appropriate error code.
  32. --*/
  33. {
  34. PWSTR w;
  35. LONG Error;
  36. HKEY HiveListKey;
  37. PWSTR KeyName;
  38. PWSTR FileName;
  39. PWSTR Name;
  40. DWORD ValueIndex;
  41. DWORD ValueType;
  42. DWORD ValueNameLength;
  43. DWORD ValueDataLength;
  44. WCHAR ConfigPath[ MAX_PATH ];
  45. WCHAR HiveName[ MAX_PATH ];
  46. WCHAR HivePath[ MAX_PATH ];
  47. WCHAR FilePath[ MAX_PATH ];
  48. HANDLE hInstDll;
  49. PFNGETPROFILESDIRECTORYW pfnGetProfilesDirectory;
  50. NTSTATUS Status;
  51. BOOLEAN savedBackup;
  52. //
  53. // First try and give ourselves enough priviledge
  54. //
  55. if (!RTEnableBackupRestorePrivilege()) {
  56. return(GetLastError());
  57. }
  58. //
  59. // Now attach to the registry
  60. //
  61. Error = RTConnectToRegistry(MachineName,
  62. HiveFileName,
  63. HiveRootName,
  64. NULL,
  65. &RegistryContext
  66. );
  67. if (Error != NO_ERROR) {
  68. RTDisableBackupRestorePrivilege();
  69. return Error;
  70. }
  71. //
  72. // Get handle to hivelist key
  73. //
  74. KeyName = L"HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Hivelist";
  75. Error = RTOpenKey(&RegistryContext,
  76. NULL,
  77. KeyName,
  78. MAXIMUM_ALLOWED,
  79. 0,
  80. &HiveListKey
  81. );
  82. if (Error != NO_ERROR) {
  83. RTDisconnectFromRegistry(&RegistryContext);
  84. return Error;
  85. }
  86. //
  87. // get path data for system hive, which will allow us to compute
  88. // path name to config dir in form that hivelist uses.
  89. // (an NT internal form of path) this is NOT the way the path to
  90. // the config directory should generally be computed.
  91. //
  92. ValueDataLength = sizeof(ConfigPath);
  93. Error = RTQueryValueKey(&RegistryContext,
  94. HiveListKey,
  95. L"\\Registry\\Machine\\System",
  96. &ValueType,
  97. &ValueDataLength,
  98. ConfigPath
  99. );
  100. if (Error != NO_ERROR) {
  101. RTDisconnectFromRegistry(&RegistryContext);
  102. return Error;
  103. }
  104. w = wcsrchr(ConfigPath, L'\\');
  105. *w = UNICODE_NULL;
  106. //
  107. // ennumerate entries in hivelist. for each entry, find it's hive file
  108. // path then save it.
  109. //
  110. for (ValueIndex = 0; TRUE; ValueIndex++) {
  111. savedBackup = FALSE;
  112. ValueType = REG_NONE;
  113. ValueNameLength = ARRAYSIZE( HiveName );
  114. ValueDataLength = sizeof( HivePath );
  115. Error = RTEnumerateValueKey(&RegistryContext,
  116. HiveListKey,
  117. ValueIndex,
  118. &ValueType,
  119. &ValueNameLength,
  120. HiveName,
  121. &ValueDataLength,
  122. HivePath
  123. );
  124. if (Error == ERROR_NO_MORE_ITEMS) {
  125. break;
  126. } else if (Error != NO_ERROR) {
  127. RTDisconnectFromRegistry(&RegistryContext);
  128. return Error;
  129. }
  130. if ((ValueType == REG_SZ) && (ValueDataLength > sizeof(UNICODE_NULL))) {
  131. //
  132. // there's a file, compute it's path, hive branch, etc
  133. //
  134. if (w = wcsrchr( HivePath, L'\\' )) {
  135. *w++ = UNICODE_NULL;
  136. }
  137. FileName = w;
  138. if (w = wcsrchr( HiveName, L'\\' )) {
  139. *w++ = UNICODE_NULL;
  140. }
  141. Name = w;
  142. HiveRoot = NULL;
  143. if (w = wcsrchr( HiveName, L'\\' )) {
  144. w += 1;
  145. if (!_wcsicmp( w, L"MACHINE" )) {
  146. HiveRoot = HKEY_LOCAL_MACHINE;
  147. } else if (!_wcsicmp( w, L"USER" )) {
  148. HiveRoot = HKEY_USERS;
  149. } else {
  150. Status = IMirrorRegSaveError(w, ERROR_PATH_NOT_FOUND);
  151. if (Status == STATUS_RETRY) {
  152. continue;
  153. }
  154. if (!NT_SUCCESS(Status)) {
  155. return Error;
  156. }
  157. }
  158. }
  159. if (FileName != NULL && Name != NULL && HiveRoot != NULL) {
  160. //
  161. // Extract the path name from HivePath
  162. //
  163. if (_wcsicmp(HivePath, L"\\Device")) {
  164. w = HivePath + 1;
  165. w = wcsstr(w, L"\\");
  166. w++;
  167. w = wcsstr(w, L"\\");
  168. w++;
  169. } else if (*(HivePath + 1) == L':') {
  170. w = HivePath + 2;
  171. } else {
  172. Status = IMirrorRegSaveError(HivePath, ERROR_PATH_NOT_FOUND);
  173. if (Status == STATUS_RETRY) {
  174. continue;
  175. }
  176. if (!NT_SUCCESS(Status)) {
  177. return Error;
  178. }
  179. }
  180. //
  181. // Do the save
  182. //
  183. swprintf( FilePath, L"%ws\\UserData\\%ws\\%ws", MirrorRoot, w, FileName );
  184. IMirrorNowDoing(CopyRegistry, FileName);
  185. //
  186. // if the file already exists, rename it to a backup name
  187. // so that if it fails, we'll restore it.
  188. //
  189. lstrcpyW( (PWCHAR) TmpBuffer, FilePath );
  190. lstrcatW( (PWCHAR) TmpBuffer, L".old" );
  191. if (MoveFileEx( FilePath, (PWCHAR) TmpBuffer, MOVEFILE_REPLACE_EXISTING)) {
  192. savedBackup = TRUE;
  193. }
  194. RetrySave:
  195. Error = DoSpecificRegBackup(FilePath,
  196. HiveRoot,
  197. Name
  198. );
  199. if (Error != NO_ERROR) {
  200. Status = IMirrorRegSaveError(Name, Error);
  201. if (Status == STATUS_RETRY) {
  202. goto RetrySave;
  203. }
  204. if (!NT_SUCCESS(Status)) {
  205. if (savedBackup) {
  206. if (MoveFileEx( (PWCHAR) TmpBuffer, FilePath, MOVEFILE_REPLACE_EXISTING)) {
  207. savedBackup = FALSE;
  208. }
  209. }
  210. return Error;
  211. }
  212. }
  213. }
  214. }
  215. }
  216. RTDisconnectFromRegistry(&RegistryContext);
  217. return NO_ERROR;
  218. }
  219. DWORD
  220. DoSpecificRegBackup(
  221. PWSTR HivePath,
  222. HKEY HiveRoot,
  223. PWSTR HiveName
  224. )
  225. /*++
  226. Routine Description:
  227. This routine copies all the registries to the given server path.
  228. Arguments:
  229. HivePath - file name to pass directly to OS
  230. HiveRoot - HKEY_LOCAL_MACHINE or HKEY_USERS
  231. HiveName - 1st level subkey under machine or users
  232. Return Value:
  233. NO_ERROR if everything was backed up properly, else the appropriate error code.
  234. --*/
  235. {
  236. HKEY HiveKey;
  237. ULONG Disposition;
  238. LONG Error;
  239. char *Reason;
  240. //
  241. // get a handle to the hive. use special create call what will
  242. // use privileges
  243. //
  244. Reason = "accessing";
  245. Error = RTCreateKey(&RegistryContext,
  246. HiveRoot,
  247. HiveName,
  248. KEY_READ,
  249. REG_OPTION_BACKUP_RESTORE,
  250. NULL,
  251. &HiveKey,
  252. &Disposition
  253. );
  254. if (Error == NO_ERROR) {
  255. Reason = "saving";
  256. Error = RegSaveKey(HiveKey, HivePath, NULL);
  257. RTCloseKey(&RegistryContext, HiveKey);
  258. }
  259. return Error;
  260. }
  261. DWORD
  262. GetRegistryFileList(
  263. PLIST_ENTRY ListHead
  264. )
  265. /*++
  266. Routine Description:
  267. This routine stores all registry file names to a list.
  268. Arguments:
  269. None.
  270. Return Value:
  271. NO_ERROR if everything was backed up properly, else the appropriate error code.
  272. --*/
  273. {
  274. LONG Error;
  275. HKEY HiveListKey;
  276. PWSTR KeyName;
  277. PWSTR FileName;
  278. PWSTR Name;
  279. DWORD ValueIndex;
  280. DWORD ValueType;
  281. DWORD ValueNameLength;
  282. DWORD ValueDataLength;
  283. WCHAR HiveName[ MAX_PATH ];
  284. WCHAR HivePath[ MAX_PATH ];
  285. NTSTATUS Status;
  286. PIMIRROR_IGNORE_FILE_LIST entry;
  287. //
  288. // enter all hardcoded files that we don't want to mirror here...
  289. //
  290. FileName = L"System Volume Information\\tracking.log";
  291. entry = IMirrorAllocMem(sizeof(IMIRROR_IGNORE_FILE_LIST) +
  292. ((lstrlenW(FileName) + 1) * sizeof(WCHAR)));
  293. if (entry != NULL) {
  294. lstrcpyW( &entry->FileName[0], FileName );
  295. entry->FileNameLength = (USHORT) lstrlenW( FileName );
  296. InsertHeadList( ListHead, &entry->ListEntry );
  297. }
  298. //
  299. // Now attach to the registry
  300. //
  301. Error = RTConnectToRegistry(MachineName,
  302. HiveFileName,
  303. HiveRootName,
  304. NULL,
  305. &RegistryContext
  306. );
  307. if (Error != NO_ERROR) {
  308. return Error;
  309. }
  310. //
  311. // Get handle to hivelist key
  312. //
  313. KeyName = L"HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Hivelist";
  314. Error = RTOpenKey(&RegistryContext,
  315. NULL,
  316. KeyName,
  317. MAXIMUM_ALLOWED,
  318. 0,
  319. &HiveListKey
  320. );
  321. if (Error != NO_ERROR) {
  322. RTDisconnectFromRegistry(&RegistryContext);
  323. return Error;
  324. }
  325. //
  326. // ennumerate entries in hivelist. for each entry, find it's hive file
  327. // path then save it.
  328. //
  329. for (ValueIndex = 0; TRUE; ValueIndex++) {
  330. ValueType = REG_NONE;
  331. ValueNameLength = ARRAYSIZE( HiveName );
  332. ValueDataLength = sizeof( HivePath );
  333. Error = RTEnumerateValueKey(&RegistryContext,
  334. HiveListKey,
  335. ValueIndex,
  336. &ValueType,
  337. &ValueNameLength,
  338. HiveName,
  339. &ValueDataLength,
  340. HivePath
  341. );
  342. if (Error != NO_ERROR) {
  343. if (Error == ERROR_NO_MORE_ITEMS) {
  344. Error = NO_ERROR;
  345. }
  346. break;
  347. }
  348. if ((ValueType == REG_SZ) && (ValueDataLength > sizeof(UNICODE_NULL))) {
  349. //
  350. // Extract the path name from HivePath
  351. //
  352. if (_wcsicmp(HivePath, L"\\Device")) {
  353. FileName = HivePath + 1;
  354. FileName = wcsstr(FileName, L"\\");
  355. FileName++;
  356. FileName = wcsstr(FileName, L"\\");
  357. FileName++; // now points to L"\winnt\system32\config\sam"
  358. } else if (*(HivePath + 1) == L':') {
  359. FileName = HivePath + 2;
  360. } else {
  361. FileName = HivePath;
  362. }
  363. entry = IMirrorAllocMem(sizeof(IMIRROR_IGNORE_FILE_LIST) +
  364. ((lstrlenW(FileName) + 1) * sizeof(WCHAR)));
  365. if (entry != NULL) {
  366. lstrcpyW( &entry->FileName[0], FileName );
  367. entry->FileNameLength = (USHORT) lstrlenW( FileName );
  368. InsertHeadList( ListHead, &entry->ListEntry );
  369. }
  370. }
  371. }
  372. RTDisconnectFromRegistry(&RegistryContext);
  373. return Error;
  374. }