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.

1013 lines
27 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. cpinit.c
  5. Abstract:
  6. Initialization and shutdown code for the Checkpoint Manager (CP)
  7. Author:
  8. John Vert (jvert) 1/14/1997
  9. Revision History:
  10. --*/
  11. #include "cpp.h"
  12. BOOL
  13. CppCopyCheckpointCallback(
  14. IN LPWSTR ValueName,
  15. IN LPVOID ValueData,
  16. IN DWORD ValueType,
  17. IN DWORD ValueSize,
  18. IN PCP_CALLBACK_CONTEXT Context
  19. );
  20. BOOL
  21. CpckCopyCheckpointCallback(
  22. IN LPWSTR ValueName,
  23. IN LPVOID ValueData,
  24. IN DWORD ValueType,
  25. IN DWORD ValueSize,
  26. IN PCP_CALLBACK_CONTEXT Context
  27. );
  28. BOOL
  29. CppEnumResourceCallback(
  30. IN PCP_CALLBACK_CONTEXT pCbContext,
  31. IN PVOID Context2,
  32. IN PFM_RESOURCE Resource,
  33. IN LPCWSTR Name
  34. );
  35. BOOL
  36. CpckEnumResourceCallback(
  37. IN PCP_CALLBACK_CONTEXT pCbContext,
  38. IN PVOID Context2,
  39. IN PFM_RESOURCE Resource,
  40. IN LPCWSTR Name
  41. );
  42. VOID
  43. CppResourceNotify(
  44. IN PVOID Context,
  45. IN PFM_RESOURCE Resource,
  46. IN DWORD NotifyCode
  47. )
  48. /*++
  49. Routine Description:
  50. Resource notification callback for hooking resource state
  51. changes. This allows to to register/deregister our registry
  52. notifications for that resource.
  53. Arguments:
  54. Context - Supplies the context. Not used
  55. Resource - Supplies the resource that is going online or
  56. has been taken offline.
  57. NotifyCode - Supplies the type of notification, either
  58. NOTIFY_RESOURCE_PREONLINE or NOTIFY_RESOURCE_POSTOFFLINE
  59. /NOTIFY_RESOURCE_FAILED.
  60. Return Value:
  61. ERROR_SUCCESS if successful
  62. Win32 error code otherwise
  63. --*/
  64. {
  65. DWORD Status;
  66. ClRtlLogPrint(LOG_NOISE,
  67. "[CP] CppResourceNotify for resource %1!ws!\n",
  68. OmObjectName(Resource));
  69. if ( Resource->QuorumResource ) {
  70. return;
  71. }
  72. if (NotifyCode == NOTIFY_RESOURCE_PREONLINE) {
  73. //
  74. // Restore any checkpointed registry state for this resource
  75. // This will also start the registry notification thread.
  76. //
  77. Resource->CheckpointState = 0;
  78. Status = CppWatchRegistry(Resource);
  79. if (Status != ERROR_SUCCESS) {
  80. ClRtlLogPrint(LOG_CRITICAL,
  81. "[CP] CppWatchRegistry for resource %1!ws! failed %2!d!\n",
  82. OmObjectName(Resource),
  83. Status);
  84. }
  85. Status = CpckReplicateCryptoKeys(Resource);
  86. if (Status != ERROR_SUCCESS) {
  87. ClRtlLogPrint(LOG_CRITICAL,
  88. "[CP] CpckReplicateCryptoKeys for resource %1!ws! failed %2!d!\n",
  89. OmObjectName(Resource),
  90. Status);
  91. }
  92. } else {
  93. CL_ASSERT(NotifyCode == NOTIFY_RESOURCE_POSTOFFLINE ||
  94. NotifyCode == NOTIFY_RESOURCE_FAILED);
  95. //
  96. // Remove any posted registry notification for this resource
  97. //
  98. Status = CppRundownCheckpoints(Resource);
  99. if (Status != ERROR_SUCCESS) {
  100. ClRtlLogPrint(LOG_CRITICAL,
  101. "[CP] CppUnWatchRegistry for resource %1!ws! failed %2!d!\n",
  102. OmObjectName(Resource),
  103. Status);
  104. }
  105. }
  106. }
  107. DWORD
  108. CpInitialize(
  109. VOID
  110. )
  111. /*++
  112. Routine Description:
  113. Initializes the checkpoint manager
  114. Arguments:
  115. None
  116. Return Value:
  117. ERROR_SUCCESS if successful
  118. Win32 error code otherwise
  119. --*/
  120. {
  121. DWORD Status;
  122. InitializeCriticalSection(&CppNotifyLock);
  123. InitializeListHead(&CpNotifyListHead);
  124. //
  125. // Register for resource online/offline notifications
  126. //
  127. Status = OmRegisterTypeNotify(ObjectTypeResource,
  128. NULL,
  129. NOTIFY_RESOURCE_PREONLINE |
  130. NOTIFY_RESOURCE_POSTOFFLINE|
  131. NOTIFY_RESOURCE_FAILED,
  132. CppResourceNotify);
  133. return(ERROR_SUCCESS);
  134. }
  135. DWORD
  136. CpShutdown(
  137. VOID
  138. )
  139. /*++
  140. Routine Description:
  141. Shuts down the Checkpoint Manager
  142. Arguments:
  143. None
  144. Return Value:
  145. ERROR_SUCCESS if successful
  146. Win32 error code otherwise
  147. --*/
  148. {
  149. DeleteCriticalSection(&CppNotifyLock);
  150. return(ERROR_SUCCESS);
  151. }
  152. DWORD
  153. CpCompleteQuorumChange(
  154. IN LPCWSTR lpszOldQuorumPath
  155. )
  156. /*++
  157. Routine Description:
  158. Completes a change of the quorum disk. This involves deleting
  159. all the checkpoint files on the old quorum disk.
  160. Simple algorithm used here is to enumerate all the resources.
  161. For each resource, enumerate all its checkpoints and delete the
  162. checkpoint files.
  163. Arguments:
  164. lpszNewQuorumPath - Supplies the new quorum path.
  165. Return Value:
  166. ERROR_SUCCESS if successful
  167. Win32 error code otherwise
  168. --*/
  169. {
  170. CP_CALLBACK_CONTEXT CbContext;
  171. CbContext.lpszPathName = lpszOldQuorumPath;
  172. OmEnumObjects(ObjectTypeResource,
  173. CppEnumResourceCallback,
  174. (PVOID)&CbContext,
  175. CppRemoveCheckpointFileCallback);
  176. OmEnumObjects(ObjectTypeResource,
  177. CpckEnumResourceCallback,
  178. (PVOID)&CbContext,
  179. CpckRemoveCheckpointFileCallback);
  180. return(ERROR_SUCCESS);
  181. }
  182. DWORD
  183. CpCopyCheckpointFiles(
  184. IN LPCWSTR lpszPathName,
  185. IN BOOL IsChangeFileAttribute
  186. )
  187. /*++
  188. Routine Description:
  189. Copies all the checkpoint files from the quorum disk to the supplied
  190. directory path. This function is invoked whenever the quorum disk
  191. changes or when the user wants to make a backup of the cluster DB
  192. on the quorum disk.
  193. Simple algorithm used here is to enumerate all the resources.
  194. For each resource, enumerate all its checkpoints and copy the
  195. checkpoint files from the quorum disk to the supplied path.
  196. Arguments:
  197. lpszPathName - Supplies the destination path name.
  198. Return Value:
  199. ERROR_SUCCESS if successful
  200. Win32 error code otherwise
  201. --*/
  202. {
  203. CP_CALLBACK_CONTEXT CbContext;
  204. CbContext.lpszPathName = lpszPathName;
  205. CbContext.IsChangeFileAttribute = IsChangeFileAttribute;
  206. OmEnumObjects(ObjectTypeResource,
  207. CppEnumResourceCallback,
  208. (PVOID)&CbContext,
  209. CppCopyCheckpointCallback);
  210. OmEnumObjects(ObjectTypeResource,
  211. CpckEnumResourceCallback,
  212. (PVOID)&CbContext,
  213. CpckCopyCheckpointCallback);
  214. return(ERROR_SUCCESS);
  215. }
  216. BOOL
  217. CppEnumResourceCallback(
  218. IN PCP_CALLBACK_CONTEXT pCbContext,
  219. IN PENUM_VALUE_CALLBACK lpValueEnumRoutine,
  220. IN PFM_RESOURCE Resource,
  221. IN LPCWSTR Name
  222. )
  223. /*++
  224. Routine Description:
  225. Resource enumeration callback for copying or deleting checkpoints
  226. when the quorum resource changes or when the user is making
  227. a backup of the cluster DB on the quorum disk.
  228. Arguments:
  229. lpszPathName - Supplies the new quorum path to be passed to lpValueEnumRoutine.
  230. lpValueEnumRoutine - Supplies the value enumeration callback to
  231. be called if checkpoints exist.
  232. Resource - Supplies the resource object.
  233. Name - Supplies the resource name
  234. Return Value:
  235. TRUE to continue enumeration
  236. --*/
  237. {
  238. DWORD Status;
  239. HDMKEY ResourceKey;
  240. HDMKEY RegSyncKey;
  241. CP_CALLBACK_CONTEXT Context;
  242. //
  243. // Open up the resource's key
  244. //
  245. ResourceKey = DmOpenKey(DmResourcesKey,
  246. OmObjectId(Resource),
  247. KEY_READ);
  248. if (ResourceKey != NULL) {
  249. //
  250. // Open up the RegSync key
  251. //
  252. RegSyncKey = DmOpenKey(ResourceKey,
  253. L"RegSync",
  254. KEY_READ);
  255. DmCloseKey(ResourceKey);
  256. if (RegSyncKey != NULL) {
  257. Context.lpszPathName = pCbContext->lpszPathName;
  258. Context.Resource = Resource;
  259. Context.IsChangeFileAttribute = pCbContext->IsChangeFileAttribute;
  260. DmEnumValues(RegSyncKey,
  261. lpValueEnumRoutine,
  262. &Context);
  263. DmCloseKey(RegSyncKey);
  264. }
  265. }
  266. return(TRUE);
  267. }
  268. BOOL
  269. CppCopyCheckpointCallback(
  270. IN LPWSTR ValueName,
  271. IN LPVOID ValueData,
  272. IN DWORD ValueType,
  273. IN DWORD ValueSize,
  274. IN PCP_CALLBACK_CONTEXT Context
  275. )
  276. /*++
  277. Routine Description:
  278. Registry value enumeration callback used when the quorum resource
  279. is changing or when the user is making a backup of the cluster DB
  280. on the quorum disk. Copies the specified checkpoint file from the
  281. current quorum directory to the supplied path (in the Context parameter).
  282. Arguments:
  283. ValueName - Supplies the name of the value (this is the checkpoint ID)
  284. ValueData - Supplies the value data (this is the registry subtree)
  285. ValueType - Supplies the value type (must be REG_SZ)
  286. ValueSize - Supplies the size of ValueData
  287. Context - Supplies the quorum change context (new path and resource)
  288. Return Value:
  289. TRUE to continue enumeration
  290. --*/
  291. {
  292. WCHAR OldCheckpointFile[MAX_PATH+1];
  293. LPWSTR NewCheckpointDir;
  294. LPWSTR NewCheckpointFile;
  295. DWORD Status;
  296. DWORD Id;
  297. Id = wcstol(ValueName, NULL, 16);
  298. if (Id == 0) {
  299. ClRtlLogPrint(LOG_UNUSUAL,
  300. "[CP] CppCopyCheckpointCallback invalid checkpoint ID %1!ws! for resource %2!ws!\n",
  301. ValueName,
  302. OmObjectName(Context->Resource));
  303. return(TRUE);
  304. }
  305. //
  306. // Get a temporary file name for saving the old checkpoint file
  307. //
  308. Status = DmCreateTempFileName(OldCheckpointFile);
  309. if (Status != ERROR_SUCCESS) {
  310. ClRtlLogPrint(LOG_CRITICAL,
  311. "[CP] CppCopyCheckpointCallback - DmCreateTempFileName for old file failed with status %1!d! for resource %2!ws!...\n",
  312. Status,
  313. OmObjectName(Context->Resource));
  314. return(TRUE);
  315. }
  316. //
  317. // Get the old checkpoint file from the node hosting the quorum resource
  318. //
  319. Status = CpGetDataFile(Context->Resource,
  320. Id,
  321. OldCheckpointFile,
  322. FALSE);
  323. if (Status != ERROR_SUCCESS) {
  324. ClRtlLogPrint(LOG_CRITICAL,
  325. "[CP] CppCopyCheckpointCallback - CpGetDataFile for checkpoint ID %2!d! failed with status %1!d! for resource %3!ws!...\n",
  326. Status,
  327. Id,
  328. OmObjectName(Context->Resource));
  329. return(TRUE);
  330. }
  331. //
  332. // Get the new checkpoint file and directory
  333. //
  334. Status = CppGetCheckpointFile(Context->Resource,
  335. Id,
  336. &NewCheckpointDir,
  337. &NewCheckpointFile,
  338. Context->lpszPathName,
  339. FALSE);
  340. if (Status != ERROR_SUCCESS) {
  341. ClRtlLogPrint(LOG_CRITICAL,
  342. "[CP] CppCopyCheckpointCallback - CppGetCheckpointFile for new file failed %1!d!\n",
  343. Status);
  344. return(TRUE);
  345. }
  346. //
  347. // If necessary, try to change the file attributes to NORMAL
  348. //
  349. if (Context->IsChangeFileAttribute == TRUE) {
  350. SetFileAttributes(NewCheckpointFile, FILE_ATTRIBUTE_NORMAL);
  351. SetFileAttributes(NewCheckpointDir, FILE_ATTRIBUTE_NORMAL);
  352. }
  353. //
  354. // Create the new directory.
  355. //
  356. if (!CreateDirectory(NewCheckpointDir, NULL)) {
  357. Status = GetLastError();
  358. if (Status != ERROR_ALREADY_EXISTS) {
  359. ClRtlLogPrint(LOG_CRITICAL,
  360. "[CP] CppCopyCheckpointCallback unable to create directory %1!ws!, error %2!d!\n",
  361. NewCheckpointDir,
  362. Status);
  363. LocalFree(NewCheckpointFile);
  364. LocalFree(NewCheckpointDir);
  365. return(TRUE);
  366. }
  367. Status = ERROR_SUCCESS;
  368. }
  369. //
  370. // Copy the old file to the new file
  371. //
  372. if (!CopyFile(OldCheckpointFile, NewCheckpointFile, FALSE)) {
  373. Status = GetLastError();
  374. ClRtlLogPrint(LOG_CRITICAL,
  375. "[CP] CppCopyCheckpointCallback unable to copy file %1!ws! to %2!ws!, error %3!d!\n",
  376. OldCheckpointFile,
  377. NewCheckpointFile,
  378. Status);
  379. }
  380. //
  381. // If necessary, change the file attributes to READONLY
  382. //
  383. if ((Status == ERROR_SUCCESS) && (Context->IsChangeFileAttribute == TRUE)) {
  384. if (!SetFileAttributes(NewCheckpointFile, FILE_ATTRIBUTE_READONLY)
  385. ||
  386. !SetFileAttributes(NewCheckpointDir, FILE_ATTRIBUTE_READONLY)) {
  387. Status = GetLastError();
  388. ClRtlLogPrint(LOG_CRITICAL,
  389. "[CP] CppCopyCheckpointCallback unable to change file attributes in %1!ws!, error %2!d!\n",
  390. NewCheckpointDir,
  391. Status);
  392. }
  393. }
  394. LocalFree(NewCheckpointFile);
  395. LocalFree(NewCheckpointDir);
  396. return(TRUE);
  397. }
  398. BOOL
  399. CppRemoveCheckpointFileCallback(
  400. IN LPWSTR ValueName,
  401. IN LPVOID ValueData,
  402. IN DWORD ValueType,
  403. IN DWORD ValueSize,
  404. IN PCP_CALLBACK_CONTEXT Context
  405. )
  406. /*++
  407. Routine Description:
  408. Registry value enumeration callback used when the quorum resource
  409. is changing. Deletes the specified checkpoint file from the old
  410. quorum directory.
  411. Arguments:
  412. ValueName - Supplies the name of the value (this is the checkpoint ID)
  413. ValueData - Supplies the value data (this is the registry subtree)
  414. ValueType - Supplies the value type (must be REG_SZ)
  415. ValueSize - Supplies the size of ValueData
  416. Context - Supplies the quorum change context (old path and resource)
  417. Return Value:
  418. TRUE to continue enumeration
  419. --*/
  420. {
  421. DWORD Status;
  422. DWORD Id;
  423. Id = wcstol(ValueName, NULL, 16);
  424. if (Id == 0) {
  425. ClRtlLogPrint(LOG_UNUSUAL,
  426. "[CP] CppRemoveCheckpointFileCallback invalid checkpoint ID %1!ws! for resource %2!ws!\n",
  427. ValueName,
  428. OmObjectName(Context->Resource));
  429. return(TRUE);
  430. }
  431. Status = CppDeleteFile(Context->Resource, Id, Context->lpszPathName);
  432. return(TRUE);
  433. }
  434. BOOL
  435. CpckEnumResourceCallback(
  436. IN PCP_CALLBACK_CONTEXT pCbContext,
  437. IN PENUM_VALUE_CALLBACK lpValueEnumRoutine,
  438. IN PFM_RESOURCE Resource,
  439. IN LPCWSTR Name
  440. )
  441. /*++
  442. Routine Description:
  443. Resource enumeration callback for copying or deleting crypto checkpoints
  444. when the quorum resource changes or when the user is making
  445. a backup of the cluster DB on the quorum disk.
  446. Arguments:
  447. lpszPathName - Supplies the new quorum path to be passed to lpValueEnumRoutine.
  448. lpValueEnumRoutine - Supplies the value enumeration callback to
  449. be called if checkpoints exist.
  450. Resource - Supplies the resource object.
  451. Name - Supplies the resource name
  452. Return Value:
  453. TRUE to continue enumeration
  454. --*/
  455. {
  456. DWORD Status;
  457. HDMKEY ResourceKey;
  458. HDMKEY CryptoSyncKey;
  459. CP_CALLBACK_CONTEXT Context;
  460. //
  461. // Open up the resource's key
  462. //
  463. ResourceKey = DmOpenKey(DmResourcesKey,
  464. OmObjectId(Resource),
  465. KEY_READ);
  466. if (ResourceKey != NULL) {
  467. //
  468. // Open up the CryptoSyncKey key
  469. //
  470. CryptoSyncKey = DmOpenKey(ResourceKey,
  471. L"CryptoSync",
  472. KEY_READ);
  473. DmCloseKey(ResourceKey);
  474. if (CryptoSyncKey != NULL) {
  475. Context.lpszPathName = pCbContext->lpszPathName;
  476. Context.Resource = Resource;
  477. Context.IsChangeFileAttribute = pCbContext->IsChangeFileAttribute;
  478. DmEnumValues(CryptoSyncKey,
  479. lpValueEnumRoutine,
  480. &Context);
  481. DmCloseKey(CryptoSyncKey);
  482. }
  483. }
  484. return(TRUE);
  485. }
  486. BOOL
  487. CpckCopyCheckpointCallback(
  488. IN LPWSTR ValueName,
  489. IN LPVOID ValueData,
  490. IN DWORD ValueType,
  491. IN DWORD ValueSize,
  492. IN PCP_CALLBACK_CONTEXT Context
  493. )
  494. /*++
  495. Routine Description:
  496. Crypto key enumeration callback used when the quorum resource
  497. is changing or when the user is making a backup of the cluster DB
  498. on the quorum disk. Copies the specified checkpoint file from the
  499. current quorum directory to the supplied path (in the Context parameter).
  500. Arguments:
  501. ValueName - Supplies the name of the value (this is the checkpoint ID)
  502. ValueData - Supplies the value data (this is the crypto info)
  503. ValueType - Supplies the value type (must be REG_BINARY)
  504. ValueSize - Supplies the size of ValueData
  505. Context - Supplies the quorum change context (new path and resource)
  506. Return Value:
  507. TRUE to continue enumeration
  508. --*/
  509. {
  510. WCHAR OldCheckpointFile[MAX_PATH+1];
  511. LPWSTR NewCheckpointDir;
  512. LPWSTR NewCheckpointFile;
  513. DWORD Status;
  514. DWORD Id;
  515. Id = wcstol(ValueName, NULL, 16);
  516. if (Id == 0) {
  517. ClRtlLogPrint(LOG_UNUSUAL,
  518. "[CPCK] CpckCopyCheckpointCallback invalid checkpoint ID %1!ws! for resource %2!ws!\n",
  519. ValueName,
  520. OmObjectName(Context->Resource));
  521. return(TRUE);
  522. }
  523. //
  524. // Get a temporary file name for saving the old checkpoint file
  525. //
  526. Status = DmCreateTempFileName(OldCheckpointFile);
  527. if (Status != ERROR_SUCCESS) {
  528. ClRtlLogPrint(LOG_CRITICAL,
  529. "[CP] CpckCopyCheckpointCallback - DmCreateTempFileName for old file failed with status %1!d! for resource %2!ws!...\n",
  530. Status,
  531. OmObjectName(Context->Resource));
  532. return(TRUE);
  533. }
  534. //
  535. // Get the old checkpoint file from the node hosting the quorum resource
  536. //
  537. Status = CpGetDataFile(Context->Resource,
  538. Id,
  539. OldCheckpointFile,
  540. TRUE);
  541. if (Status != ERROR_SUCCESS) {
  542. ClRtlLogPrint(LOG_CRITICAL,
  543. "[CP] CpckCopyCheckpointCallback - CpGetDataFile for checkpoint ID %2!d! failed with status %1!d! for resource %3!ws!...\n",
  544. Status,
  545. Id,
  546. OmObjectName(Context->Resource));
  547. return(TRUE);
  548. }
  549. //
  550. // Get the new checkpoint file and directory
  551. //
  552. Status = CppGetCheckpointFile(Context->Resource,
  553. Id,
  554. &NewCheckpointDir,
  555. &NewCheckpointFile,
  556. Context->lpszPathName,
  557. TRUE);
  558. if (Status != ERROR_SUCCESS) {
  559. ClRtlLogPrint(LOG_CRITICAL,
  560. "[CPCK] CpckCopyCheckpointCallback - CppGetCheckpointFile for new file failed %1!d!\n",
  561. Status);
  562. return(TRUE);
  563. }
  564. //
  565. // If necessary, try to change the file attributes to NORMAL
  566. //
  567. if (Context->IsChangeFileAttribute == TRUE) {
  568. SetFileAttributes(NewCheckpointFile, FILE_ATTRIBUTE_NORMAL);
  569. SetFileAttributes(NewCheckpointDir, FILE_ATTRIBUTE_NORMAL);
  570. }
  571. //
  572. // Create the new directory.
  573. //
  574. if (!CreateDirectory(NewCheckpointDir, NULL)) {
  575. Status = GetLastError();
  576. if (Status != ERROR_ALREADY_EXISTS) {
  577. ClRtlLogPrint(LOG_CRITICAL,
  578. "[CPCK] CpckCopyCheckpointCallback unable to create directory %1!ws!, error %2!d!\n",
  579. NewCheckpointDir,
  580. Status);
  581. LocalFree(NewCheckpointFile);
  582. LocalFree(NewCheckpointDir);
  583. return(TRUE);
  584. }
  585. Status = ERROR_SUCCESS;
  586. }
  587. //
  588. // Copy the old file to the new file
  589. //
  590. if (!CopyFile(OldCheckpointFile, NewCheckpointFile, FALSE)) {
  591. Status = GetLastError();
  592. ClRtlLogPrint(LOG_CRITICAL,
  593. "[CPCK] CpckCopyCheckpointCallback unable to copy file %1!ws! to %2!ws!, error %3!d!\n",
  594. OldCheckpointFile,
  595. NewCheckpointFile,
  596. Status);
  597. }
  598. //
  599. // If necessary, change the file attributes to READONLY
  600. //
  601. if ((Status == ERROR_SUCCESS) && (Context->IsChangeFileAttribute == TRUE)) {
  602. if (!SetFileAttributes(NewCheckpointFile, FILE_ATTRIBUTE_READONLY)
  603. ||
  604. !SetFileAttributes(NewCheckpointDir, FILE_ATTRIBUTE_READONLY)) {
  605. Status = GetLastError();
  606. ClRtlLogPrint(LOG_CRITICAL,
  607. "[CPCK] CpckCopyCheckpointCallback unable to change file attributes in %1!ws!, error %2!d!\n",
  608. NewCheckpointDir,
  609. Status);
  610. }
  611. }
  612. LocalFree(NewCheckpointFile);
  613. LocalFree(NewCheckpointDir);
  614. return(TRUE);
  615. }
  616. /****
  617. @func DWORD | CpRestoreCheckpointFiles | Create a directory if necessary
  618. and copy all the resource checkpoint files from the backup
  619. directory to the quorum disk
  620. @parm IN LPWSTR | lpszSourcePathName | The name of the source path
  621. where the files are backed up.
  622. @parm IN LPWSTR | lpszSubDirName | The name of the sub-directory under
  623. the source path which can be a possible candidate for
  624. containing the resource checkpoint files.
  625. @parm IN LPCWSTR | lpszQuoLogPathName | The name of the quorum disk
  626. path where the files will be restored.
  627. @rdesc Returns a Win32 error code on failure. ERROR_SUCCESS on success.
  628. @xref <f DmpRestoreClusterDatabase>
  629. ****/
  630. DWORD CpRestoreCheckpointFiles(
  631. IN LPWSTR lpszSourcePathName,
  632. IN LPWSTR lpszSubDirName,
  633. IN LPCWSTR lpszQuoLogPathName )
  634. {
  635. LPWSTR szSourcePathName = NULL;
  636. LPWSTR szSourceFileName = NULL;
  637. WCHAR szDestPathName[MAX_PATH];
  638. WCHAR szDestFileName[MAX_PATH];
  639. DWORD dwLen;
  640. HANDLE hFindFile = INVALID_HANDLE_VALUE;
  641. WIN32_FIND_DATA FindData;
  642. WCHAR szTempCpFileNameExtn[10];
  643. DWORD status;
  644. //
  645. // Chittur Subbaraman (chitturs) - 10/20/98
  646. //
  647. dwLen = lstrlenW( lpszSourcePathName );
  648. dwLen += lstrlenW( lpszSubDirName );
  649. //
  650. // It is safer to use dynamic memory allocation for user-supplied
  651. // path since we don't want to put restrictions on the user
  652. // on the length of the path that can be supplied. However, as
  653. // far as our own quorum disk path is concerned, it is system-dependent
  654. // and static memory allocation for that would suffice.
  655. //
  656. szSourcePathName = (LPWSTR) LocalAlloc ( LMEM_FIXED,
  657. ( dwLen + 15 ) *
  658. sizeof ( WCHAR ) );
  659. if ( szSourcePathName == NULL )
  660. {
  661. status = GetLastError();
  662. ClRtlLogPrint(LOG_NOISE,
  663. "[CP] CpRestoreCheckpointFiles: Error %1!d! in allocating memory for %2!ws! !!!\n",
  664. status,
  665. lpszSourcePathName);
  666. CL_LOGFAILURE( status );
  667. goto FnExit;
  668. }
  669. lstrcpyW( szSourcePathName, lpszSourcePathName );
  670. lstrcatW( szSourcePathName, lpszSubDirName );
  671. if ( szSourcePathName[dwLen-1] != L'\\' )
  672. {
  673. szSourcePathName[dwLen++] = L'\\';
  674. szSourcePathName[dwLen] = L'\0';
  675. }
  676. mbstowcs ( szTempCpFileNameExtn, "*.CP*", 6 );
  677. lstrcatW ( szSourcePathName, szTempCpFileNameExtn );
  678. //
  679. // Try to find the first file in the directory
  680. //
  681. hFindFile = FindFirstFile( szSourcePathName, &FindData );
  682. //
  683. // Reuse the source path name variable
  684. //
  685. szSourcePathName[dwLen] = L'\0';
  686. if ( hFindFile == INVALID_HANDLE_VALUE )
  687. {
  688. status = GetLastError();
  689. if ( status != ERROR_FILE_NOT_FOUND )
  690. {
  691. ClRtlLogPrint(LOG_NOISE,
  692. "[CP] CpRestoreCheckpointFiles: No file can be found in the supplied path %1!ws! Error = %2!%d! !!!\n",
  693. szSourcePathName,
  694. status);
  695. CL_LOGFAILURE( status );
  696. } else
  697. {
  698. status = ERROR_SUCCESS;
  699. }
  700. goto FnExit;
  701. }
  702. dwLen = lstrlenW( szSourcePathName );
  703. szSourceFileName = (LPWSTR) LocalAlloc ( LMEM_FIXED,
  704. ( dwLen + 1 + LOG_MAX_FILENAME_LENGTH ) *
  705. sizeof ( WCHAR ) );
  706. if ( szSourceFileName == NULL )
  707. {
  708. status = GetLastError();
  709. ClRtlLogPrint(LOG_NOISE,
  710. "[CP] CpRestoreCheckpointFiles: Error %1!d! in allocating memory for %2!ws! !!!\n",
  711. status,
  712. szSourcePathName);
  713. CL_LOGFAILURE( status );
  714. goto FnExit;
  715. }
  716. lstrcpyW( szDestPathName, lpszQuoLogPathName );
  717. lstrcatW( szDestPathName, lpszSubDirName );
  718. dwLen = lstrlenW( szDestPathName );
  719. if ( szDestPathName[dwLen-1] != L'\\' )
  720. {
  721. szDestPathName[dwLen++] = L'\\';
  722. szDestPathName[dwLen] = L'\0';
  723. }
  724. //
  725. // Create the new directory, if necessary
  726. //
  727. if ( !CreateDirectory ( szDestPathName, NULL ) )
  728. {
  729. status = GetLastError();
  730. if ( status != ERROR_ALREADY_EXISTS )
  731. {
  732. ClRtlLogPrint(LOG_CRITICAL,
  733. "[CP] CpRestoreCheckpointFiles: Unable to create directory %1!ws!, error %2!d!\n",
  734. szDestPathName,
  735. status);
  736. CL_LOGFAILURE( status );
  737. goto FnExit;
  738. }
  739. }
  740. status = ERROR_SUCCESS;
  741. while ( status == ERROR_SUCCESS )
  742. {
  743. //
  744. // Copy the checkpoint file to the destination
  745. //
  746. lstrcpyW( szSourceFileName, szSourcePathName );
  747. lstrcatW( szSourceFileName, FindData.cFileName );
  748. lstrcpyW( szDestFileName, szDestPathName );
  749. lstrcatW( szDestFileName, FindData.cFileName );
  750. status = CopyFileW( szSourceFileName, szDestFileName, FALSE );
  751. if ( !status )
  752. {
  753. status = GetLastError();
  754. ClRtlLogPrint(LOG_UNUSUAL,
  755. "[CP] CpRestoreCheckpointFiles: Unable to copy file %1!ws! to %2!ws!, Error = %3!d!\n",
  756. szSourceFileName,
  757. szDestFileName,
  758. status);
  759. CL_LOGFAILURE( status );
  760. goto FnExit;
  761. }
  762. //
  763. // Set the file attribute to normal. Continue even if you
  764. // fail in this step but log an error.
  765. //
  766. if ( !SetFileAttributes( szDestFileName, FILE_ATTRIBUTE_NORMAL ) )
  767. {
  768. ClRtlLogPrint(LOG_UNUSUAL,
  769. "[CP] CpRestoreCheckpointFiles::Error in changing %1!ws! attribute to NORMAL\n",
  770. szDestFileName);
  771. }
  772. if ( FindNextFile( hFindFile, &FindData ) )
  773. {
  774. status = ERROR_SUCCESS;
  775. } else
  776. {
  777. status = GetLastError();
  778. }
  779. }
  780. if ( status == ERROR_NO_MORE_FILES )
  781. {
  782. status = ERROR_SUCCESS;
  783. } else
  784. {
  785. ClRtlLogPrint(LOG_UNUSUAL,
  786. "[CP] CpRestoreCheckpointFiles: FindNextFile failed !!!\n");
  787. }
  788. FnExit:
  789. LocalFree( szSourcePathName );
  790. LocalFree( szSourceFileName );
  791. if ( hFindFile != INVALID_HANDLE_VALUE )
  792. {
  793. FindClose( hFindFile );
  794. }
  795. return(status);
  796. }