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.

595 lines
14 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. receive.c
  5. Abstract:
  6. APIs for the server-side RPC support for the Checkpoint Manager
  7. Author:
  8. John Vert (jvert) 1/14/1997
  9. Revision History:
  10. --*/
  11. #include "cpp.h"
  12. error_status_t
  13. CppDepositCheckpoint(
  14. handle_t IDL_handle,
  15. LPCWSTR ResourceId,
  16. DWORD dwCheckpointId,
  17. BYTE_PIPE CheckpointData,
  18. BOOLEAN fCryptoCheckpoint
  19. )
  20. /*++
  21. Routine Description:
  22. Server side RPC to allow other nodes to checkpoint data to the
  23. quorum disk.
  24. Arguments:
  25. IDL_handle - RPC binding handle, not used.
  26. ResourceId - Name of the resource whose data is being checkpointed
  27. dwCheckpointId - Unique identifier of the checkpoint
  28. CheckpointData - pipe through which checkpoint data can be retrieved.
  29. fCryptoCheckpoint - Indicates if the checkpoint is a crypto checkpoint
  30. Return Value:
  31. ERROR_SUCCESS if successful
  32. Win32 error code otherwise
  33. --*/
  34. {
  35. DWORD Status = ERROR_SUCCESS;
  36. LPWSTR FileName = NULL;
  37. LPWSTR DirectoryName = NULL;
  38. BOOL Success;
  39. PFM_RESOURCE Resource;
  40. HANDLE hDirectory = INVALID_HANDLE_VALUE;
  41. ACQUIRE_SHARED_LOCK(gQuoLock);
  42. Resource = OmReferenceObjectById(ObjectTypeResource, ResourceId);
  43. if (Resource == NULL)
  44. {
  45. Status = ERROR_FILE_NOT_FOUND;
  46. goto FnExit;
  47. }
  48. Status = CppGetCheckpointFile(Resource,
  49. dwCheckpointId,
  50. &DirectoryName,
  51. &FileName,
  52. NULL,
  53. fCryptoCheckpoint);
  54. OmDereferenceObject(Resource);
  55. if (Status != ERROR_SUCCESS)
  56. {
  57. ClRtlLogPrint(LOG_CRITICAL,
  58. "[CP] CppDepositCheckpoint - CppGetCheckpointFile failed %1!d!\n",
  59. Status);
  60. goto FnExit;
  61. }
  62. ClRtlLogPrint(LOG_NOISE,
  63. "[CP] CppDepositCheckpoint checkpointing data to file %1!ws!\n",
  64. FileName);
  65. //
  66. // Create the directory.
  67. //
  68. if (!CreateDirectory(DirectoryName, NULL))
  69. {
  70. Status = GetLastError();
  71. if (Status != ERROR_ALREADY_EXISTS)
  72. {
  73. ClRtlLogPrint(LOG_CRITICAL,
  74. "[CP] CppDepositCheckpoint unable to create directory %1!ws!, error %2!d!\n",
  75. DirectoryName,
  76. Status);
  77. goto FnExit;
  78. }
  79. else
  80. {
  81. //the directory exists, set Status to ERROR_SUCCESS
  82. Status = ERROR_SUCCESS;
  83. }
  84. }
  85. else
  86. {
  87. //
  88. // The directory was newly created. Put the appropriate ACL on it
  89. // so that only ADMINs can read it.
  90. //
  91. hDirectory = CreateFile(DirectoryName,
  92. GENERIC_READ | WRITE_DAC | READ_CONTROL,
  93. 0,
  94. NULL,
  95. OPEN_ALWAYS,
  96. FILE_FLAG_BACKUP_SEMANTICS,
  97. NULL);
  98. if (hDirectory == INVALID_HANDLE_VALUE)
  99. {
  100. Status = GetLastError();
  101. ClRtlLogPrint(LOG_CRITICAL,
  102. "[CP] CppDepositCheckpoint unable to open directory %1!ws!, error %2!d!\n",
  103. DirectoryName,
  104. Status);
  105. goto FnExit;
  106. }
  107. Status = ClRtlSetObjSecurityInfo(hDirectory,
  108. SE_FILE_OBJECT,
  109. GENERIC_ALL,
  110. GENERIC_ALL,
  111. 0);
  112. if (Status != ERROR_SUCCESS)
  113. {
  114. ClRtlLogPrint(LOG_CRITICAL,
  115. "[CP] CppDepositCheckpoint- unable to set ACL on directory %1!ws!, error %2!d!\n",
  116. DirectoryName,
  117. Status);
  118. goto FnExit;
  119. }
  120. }
  121. //
  122. // Pull the checkpoint data file across RPC
  123. //
  124. Status = DmPullFile(FileName, CheckpointData);
  125. if (Status != ERROR_SUCCESS) {
  126. ClRtlLogPrint(LOG_CRITICAL,
  127. "[CP] CppDepositCheckpoint - DmPullFile %1!ws! failed %2!d!\n",
  128. FileName,
  129. Status);
  130. }
  131. FnExit:
  132. RELEASE_LOCK(gQuoLock);
  133. //clean up
  134. if (DirectoryName) LocalFree(DirectoryName);
  135. if (FileName) LocalFree(FileName);
  136. if (hDirectory != INVALID_HANDLE_VALUE)
  137. CloseHandle(hDirectory);
  138. //
  139. // Adjust the return status if the quorum volume is truly offline and that is why this
  140. // call failed.
  141. //
  142. if ( ( Status != ERROR_SUCCESS ) && ( CppIsQuorumVolumeOffline() == TRUE ) ) Status = ERROR_NOT_READY;
  143. //At this point, CppDepositCheckpoint should either
  144. //a) throw the error code as an exception, or
  145. //b) drain the [in] pipe and then return the error code normally
  146. //but if it returns without draining the pipe, and the RPC runtime throws
  147. //the pipe-discipline exception.
  148. if (Status != ERROR_SUCCESS)
  149. RpcRaiseException(Status);
  150. return(Status);
  151. }
  152. error_status_t
  153. s_CpDepositCheckpoint(
  154. handle_t IDL_handle,
  155. LPCWSTR ResourceId,
  156. DWORD dwCheckpointId,
  157. BYTE_PIPE CheckpointData
  158. )
  159. /*++
  160. Routine Description:
  161. Server side RPC to allow other nodes to checkpoint data to the
  162. quorum disk.
  163. Arguments:
  164. IDL_handle - RPC binding handle, not used.
  165. ResourceId - Name of the resource whose data is being checkpointed
  166. dwCheckpointId - Unique identifier of the checkpoint
  167. CheckpointData - pipe through which checkpoint data can be retrieved.
  168. Return Value:
  169. ERROR_SUCCESS if successful
  170. Win32 error code otherwise
  171. --*/
  172. {
  173. return CppDepositCheckpoint(IDL_handle,
  174. ResourceId,
  175. dwCheckpointId,
  176. CheckpointData,
  177. FALSE
  178. );
  179. }
  180. error_status_t
  181. s_CpDepositCryptoCheckpoint(
  182. handle_t IDL_handle,
  183. LPCWSTR ResourceId,
  184. DWORD dwCheckpointId,
  185. BYTE_PIPE CheckpointData
  186. )
  187. /*++
  188. Routine Description:
  189. Server side RPC to allow other nodes to checkpoint data to the
  190. quorum disk.
  191. Arguments:
  192. IDL_handle - RPC binding handle, not used.
  193. ResourceId - Name of the resource whose data is being checkpointed
  194. dwCheckpointId - Unique identifier of the checkpoint
  195. CheckpointData - pipe through which checkpoint data can be retrieved.
  196. Return Value:
  197. ERROR_SUCCESS if successful
  198. Win32 error code otherwise
  199. --*/
  200. {
  201. return CppDepositCheckpoint(IDL_handle,
  202. ResourceId,
  203. dwCheckpointId,
  204. CheckpointData,
  205. TRUE
  206. );
  207. }
  208. error_status_t
  209. CppRetrieveCheckpoint(
  210. handle_t IDL_handle,
  211. LPCWSTR ResourceId,
  212. DWORD dwCheckpointId,
  213. BOOLEAN fCryptoCheckpoint,
  214. BYTE_PIPE CheckpointData
  215. )
  216. /*++
  217. Routine Description:
  218. Server side RPC through which data checkpointed to the quorum disk
  219. can be retrieved by other nodes.
  220. Arguments:
  221. IDL_handle - RPC binding handle, not used.
  222. ResourceId - Name of the resource whose checkpoint data is to be retrieved
  223. dwCheckpointId - Unique identifier of the checkpoint
  224. fCryptoCheckpoint - Indicates if the checkpoint is a crypto checkpoint
  225. CheckpointData - pipe through which checkpoint data should be sent
  226. Return Value:
  227. ERROR_SUCCESS if successful
  228. Win32 error code otherwise
  229. --*/
  230. {
  231. DWORD Status;
  232. LPWSTR FileName=NULL;
  233. HANDLE hFile;
  234. BOOL Success;
  235. PFM_RESOURCE Resource;
  236. ACQUIRE_SHARED_LOCK(gQuoLock);
  237. Resource = OmReferenceObjectById(ObjectTypeResource, ResourceId);
  238. if (Resource == NULL) {
  239. Status = ERROR_FILE_NOT_FOUND;
  240. goto FnExit;
  241. }
  242. Status = CppGetCheckpointFile(Resource,
  243. dwCheckpointId,
  244. NULL,
  245. &FileName,
  246. NULL,
  247. fCryptoCheckpoint);
  248. OmDereferenceObject(Resource);
  249. if (Status != ERROR_SUCCESS) {
  250. ClRtlLogPrint(LOG_CRITICAL,
  251. "[CP] CppRetrieveCheckpoint - CppGetCheckpointFile failed %1!d!\n",
  252. Status);
  253. goto FnExit;
  254. }
  255. ClRtlLogPrint(LOG_NOISE,
  256. "[CP] CppRetrieveCheckpoint retrieving data from file %1!ws!\n",
  257. FileName);
  258. //
  259. // Push the checkpoint data file across RPC
  260. //
  261. Status = DmPushFile(FileName, CheckpointData);
  262. if (Status != ERROR_SUCCESS) {
  263. ClRtlLogPrint(LOG_CRITICAL,
  264. "[CP] CppRetrieveCheckpoint - DmPushFile %1!ws! failed %2!d!\n",
  265. FileName,
  266. Status);
  267. }
  268. FnExit:
  269. RELEASE_LOCK(gQuoLock);
  270. //cleanup
  271. if (FileName) LocalFree(FileName);
  272. //
  273. // Adjust the return status if the quorum volume is truly offline and that is why this
  274. // call failed.
  275. //
  276. if ( ( Status != ERROR_SUCCESS ) && ( CppIsQuorumVolumeOffline() == TRUE ) ) Status = ERROR_NOT_READY;
  277. return(Status);
  278. }
  279. error_status_t
  280. s_CpRetrieveCheckpoint(
  281. handle_t IDL_handle,
  282. LPCWSTR ResourceId,
  283. DWORD dwCheckpointId,
  284. BYTE_PIPE CheckpointData
  285. )
  286. /*++
  287. Routine Description:
  288. Server side RPC through which data checkpointed to the quorum disk
  289. can be retrieved by other nodes.
  290. Arguments:
  291. IDL_handle - RPC binding handle, not used.
  292. ResourceId - Name of the resource whose checkpoint data is to be retrieved
  293. dwCheckpointId - Unique identifier of the checkpoint
  294. CheckpointData - pipe through which checkpoint data should be sent
  295. Return Value:
  296. ERROR_SUCCESS if successful
  297. Win32 error code otherwise
  298. --*/
  299. {
  300. return CppRetrieveCheckpoint(IDL_handle,
  301. ResourceId,
  302. dwCheckpointId,
  303. FALSE,
  304. CheckpointData
  305. );
  306. }
  307. error_status_t
  308. s_CpRetrieveCryptoCheckpoint(
  309. handle_t IDL_handle,
  310. LPCWSTR ResourceId,
  311. DWORD dwCheckpointId,
  312. BYTE_PIPE CheckpointData
  313. )
  314. /*++
  315. Routine Description:
  316. Server side RPC through which data checkpointed to the quorum disk
  317. can be retrieved by other nodes.
  318. Arguments:
  319. IDL_handle - RPC binding handle, not used.
  320. ResourceId - Name of the resource whose checkpoint data is to be retrieved
  321. dwCheckpointId - Unique identifier of the checkpoint
  322. CheckpointData - pipe through which checkpoint data should be sent
  323. Return Value:
  324. ERROR_SUCCESS if successful
  325. Win32 error code otherwise
  326. --*/
  327. {
  328. return CppRetrieveCheckpoint(IDL_handle,
  329. ResourceId,
  330. dwCheckpointId,
  331. TRUE,
  332. CheckpointData
  333. );
  334. }
  335. error_status_t
  336. CppDeleteCheckpoint(
  337. handle_t IDL_handle,
  338. LPCWSTR ResourceId,
  339. DWORD dwCheckpointId,
  340. LPCWSTR lpszQuorumPath,
  341. BOOL fCryptoCheckpoint
  342. )
  343. /*++
  344. Routine Description:
  345. Server side RPC through which the checkpoint file corresponding to a
  346. given checkpointid for a resource is deleted.
  347. Arguments:
  348. IDL_handle - RPC binding handle, not used.
  349. ResourceId - Name of the resource whose checkpoint file is to be deleted.
  350. dwCheckpointId - Unique identifier of the checkpoint. If 0, all checkpoints
  351. must be deleted.
  352. lpszQuorumPath - The path to the cluster files from where these files must
  353. be deleted.
  354. fCryptoCheckpoint - Indicates if the checkpoint is a crypto checkpoint
  355. Return Value:
  356. ERROR_SUCCESS if successful
  357. Win32 error code otherwise
  358. --*/
  359. {
  360. DWORD Status;
  361. PFM_RESOURCE Resource = NULL;
  362. Resource = OmReferenceObjectById(ObjectTypeResource, ResourceId);
  363. if (Resource == NULL) {
  364. Status = ERROR_FILE_NOT_FOUND;
  365. goto FnExit;
  366. }
  367. if (fCryptoCheckpoint) {
  368. Status = CpckDeleteCheckpointFile(Resource, dwCheckpointId, lpszQuorumPath);
  369. } else {
  370. Status = CppDeleteCheckpointFile(Resource, dwCheckpointId, lpszQuorumPath);
  371. }
  372. if (Status != ERROR_SUCCESS)
  373. {
  374. goto FnExit;
  375. }
  376. FnExit:
  377. if (Resource) OmDereferenceObject(Resource);
  378. return(Status);
  379. }
  380. error_status_t
  381. s_CpDeleteCheckpoint(
  382. handle_t IDL_handle,
  383. LPCWSTR ResourceId,
  384. DWORD dwCheckpointId,
  385. LPCWSTR lpszQuorumPath
  386. )
  387. /*++
  388. Routine Description:
  389. Server side RPC through which the checkpoint file corresponding to a
  390. given checkpointid for a resource is deleted.
  391. Arguments:
  392. IDL_handle - RPC binding handle, not used.
  393. ResourceId - Name of the resource whose checkpoint file is to be deleted.
  394. dwCheckpointId - Unique identifier of the checkpoint. If 0, all checkpoints
  395. must be deleted.
  396. lpszQuorumPath - The path to the cluster files from where these files must
  397. be deleted.
  398. Return Value:
  399. ERROR_SUCCESS if successful
  400. Win32 error code otherwise
  401. --*/
  402. {
  403. return CppDeleteCheckpoint(IDL_handle,
  404. ResourceId,
  405. dwCheckpointId,
  406. lpszQuorumPath,
  407. FALSE);
  408. }
  409. error_status_t
  410. s_CpDeleteCryptoCheckpoint(
  411. handle_t IDL_handle,
  412. LPCWSTR ResourceId,
  413. DWORD dwCheckpointId,
  414. LPCWSTR lpszQuorumPath
  415. )
  416. /*++
  417. Routine Description:
  418. Server side RPC through which the crypto checkpoint file corresponding to a
  419. given checkpointid for a resource is deleted.
  420. Arguments:
  421. IDL_handle - RPC binding handle, not used.
  422. ResourceId - Name of the resource whose checkpoint file is to be deleted.
  423. dwCheckpointId - Unique identifier of the checkpoint. If 0, all checkpoints
  424. must be deleted.
  425. lpszQuorumPath - The path to the cluster files from where these files must
  426. be deleted.
  427. Return Value:
  428. ERROR_SUCCESS if successful
  429. Win32 error code otherwise
  430. --*/
  431. {
  432. return CppDeleteCheckpoint(IDL_handle,
  433. ResourceId,
  434. dwCheckpointId,
  435. lpszQuorumPath,
  436. TRUE);
  437. }