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.

496 lines
13 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. NTSTATUS Status;
  49. BOOLEAN savedBackup;
  50. //
  51. // First try and give ourselves enough priviledge
  52. //
  53. if (!RTEnableBackupRestorePrivilege()) {
  54. return(GetLastError());
  55. }
  56. //
  57. // Now attach to the registry
  58. //
  59. Error = RTConnectToRegistry(MachineName,
  60. HiveFileName,
  61. HiveRootName,
  62. NULL,
  63. &RegistryContext
  64. );
  65. if (Error != NO_ERROR) {
  66. RTDisableBackupRestorePrivilege();
  67. return Error;
  68. }
  69. //
  70. // Get handle to hivelist key
  71. //
  72. KeyName = L"HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Hivelist";
  73. Error = RTOpenKey(&RegistryContext,
  74. NULL,
  75. KeyName,
  76. MAXIMUM_ALLOWED,
  77. 0,
  78. &HiveListKey
  79. );
  80. if (Error != NO_ERROR) {
  81. RTDisconnectFromRegistry(&RegistryContext);
  82. return Error;
  83. }
  84. //
  85. // get path data for system hive, which will allow us to compute
  86. // path name to config dir in form that hivelist uses.
  87. // (an NT internal form of path) this is NOT the way the path to
  88. // the config directory should generally be computed.
  89. //
  90. ValueDataLength = sizeof(ConfigPath);
  91. Error = RTQueryValueKey(&RegistryContext,
  92. HiveListKey,
  93. L"\\Registry\\Machine\\System",
  94. &ValueType,
  95. &ValueDataLength,
  96. ConfigPath
  97. );
  98. if (Error != NO_ERROR) {
  99. RTDisconnectFromRegistry(&RegistryContext);
  100. return Error;
  101. }
  102. w = wcsrchr(ConfigPath, L'\\');
  103. if( w ) {
  104. *w = UNICODE_NULL;
  105. }
  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. //
  240. // get a handle to the hive. use special create call what will
  241. // use privileges
  242. //
  243. Error = RTCreateKey(&RegistryContext,
  244. HiveRoot,
  245. HiveName,
  246. KEY_READ,
  247. REG_OPTION_BACKUP_RESTORE,
  248. NULL,
  249. &HiveKey,
  250. &Disposition
  251. );
  252. if (Error == NO_ERROR) {
  253. Error = RegSaveKey(HiveKey, HivePath, NULL);
  254. RTCloseKey(&RegistryContext, HiveKey);
  255. }
  256. return Error;
  257. }
  258. DWORD
  259. GetRegistryFileList(
  260. PLIST_ENTRY ListHead
  261. )
  262. /*++
  263. Routine Description:
  264. This routine stores all registry file names to a list.
  265. Arguments:
  266. None.
  267. Return Value:
  268. NO_ERROR if everything was backed up properly, else the appropriate error code.
  269. --*/
  270. {
  271. LONG Error;
  272. HKEY HiveListKey;
  273. PWSTR KeyName;
  274. PWSTR FileName;
  275. DWORD ValueIndex;
  276. DWORD ValueType;
  277. DWORD ValueNameLength;
  278. DWORD ValueDataLength;
  279. WCHAR HiveName[ MAX_PATH ];
  280. WCHAR HivePath[ MAX_PATH ];
  281. PIMIRROR_IGNORE_FILE_LIST entry;
  282. //
  283. // enter all hardcoded files that we don't want to mirror here...
  284. //
  285. FileName = L"System Volume Information\\tracking.log";
  286. entry = IMirrorAllocMem(sizeof(IMIRROR_IGNORE_FILE_LIST) +
  287. ((lstrlenW(FileName) + 1) * sizeof(WCHAR)));
  288. if (entry != NULL) {
  289. lstrcpyW( &entry->FileName[0], FileName );
  290. entry->FileNameLength = (USHORT) lstrlenW( FileName );
  291. InsertHeadList( ListHead, &entry->ListEntry );
  292. } else {
  293. return(ERROR_OUTOFMEMORY);
  294. }
  295. //
  296. // Now attach to the registry
  297. //
  298. Error = RTConnectToRegistry(MachineName,
  299. HiveFileName,
  300. HiveRootName,
  301. NULL,
  302. &RegistryContext
  303. );
  304. if (Error != NO_ERROR) {
  305. return Error;
  306. }
  307. //
  308. // Get handle to hivelist key
  309. //
  310. KeyName = L"HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Hivelist";
  311. Error = RTOpenKey(&RegistryContext,
  312. NULL,
  313. KeyName,
  314. MAXIMUM_ALLOWED,
  315. 0,
  316. &HiveListKey
  317. );
  318. if (Error != NO_ERROR) {
  319. RTDisconnectFromRegistry(&RegistryContext);
  320. return Error;
  321. }
  322. //
  323. // ennumerate entries in hivelist. for each entry, find it's hive file
  324. // path then save it.
  325. //
  326. for (ValueIndex = 0; TRUE; ValueIndex++) {
  327. ValueType = REG_NONE;
  328. ValueNameLength = ARRAYSIZE( HiveName );
  329. ValueDataLength = sizeof( HivePath );
  330. Error = RTEnumerateValueKey(&RegistryContext,
  331. HiveListKey,
  332. ValueIndex,
  333. &ValueType,
  334. &ValueNameLength,
  335. HiveName,
  336. &ValueDataLength,
  337. HivePath
  338. );
  339. if (Error != NO_ERROR) {
  340. if (Error == ERROR_NO_MORE_ITEMS) {
  341. Error = NO_ERROR;
  342. }
  343. break;
  344. }
  345. if ((ValueType == REG_SZ) && (ValueDataLength > sizeof(UNICODE_NULL))) {
  346. //
  347. // Extract the path name from HivePath
  348. //
  349. if (_wcsicmp(HivePath, L"\\Device")) {
  350. FileName = HivePath + 1;
  351. FileName = wcsstr(FileName, L"\\");
  352. FileName++;
  353. FileName = wcsstr(FileName, L"\\");
  354. FileName++; // now points to L"\winnt\system32\config\sam"
  355. } else if (*(HivePath + 1) == L':') {
  356. FileName = HivePath + 2;
  357. } else {
  358. FileName = HivePath;
  359. }
  360. entry = IMirrorAllocMem(sizeof(IMIRROR_IGNORE_FILE_LIST) +
  361. ((lstrlenW(FileName) + 1) * sizeof(WCHAR)));
  362. if (entry != NULL) {
  363. lstrcpyW( &entry->FileName[0], FileName );
  364. entry->FileNameLength = (USHORT) lstrlenW( FileName );
  365. InsertHeadList( ListHead, &entry->ListEntry );
  366. }
  367. }
  368. }
  369. RTCloseKey(&RegistryContext, HiveListKey);
  370. RTDisconnectFromRegistry(&RegistryContext);
  371. return Error;
  372. }