596 lines
14 KiB
C
596 lines
14 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1996 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
receive.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
APIs for the server-side RPC support for the Checkpoint Manager
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
John Vert (jvert) 1/14/1997
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
#include "cpp.h"
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
CppDepositCheckpoint(
|
|||
|
handle_t IDL_handle,
|
|||
|
LPCWSTR ResourceId,
|
|||
|
DWORD dwCheckpointId,
|
|||
|
BYTE_PIPE CheckpointData,
|
|||
|
BOOLEAN fCryptoCheckpoint
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Server side RPC to allow other nodes to checkpoint data to the
|
|||
|
quorum disk.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used.
|
|||
|
|
|||
|
ResourceId - Name of the resource whose data is being checkpointed
|
|||
|
|
|||
|
dwCheckpointId - Unique identifier of the checkpoint
|
|||
|
|
|||
|
CheckpointData - pipe through which checkpoint data can be retrieved.
|
|||
|
|
|||
|
fCryptoCheckpoint - Indicates if the checkpoint is a crypto checkpoint
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD Status = ERROR_SUCCESS;
|
|||
|
LPWSTR FileName = NULL;
|
|||
|
LPWSTR DirectoryName = NULL;
|
|||
|
BOOL Success;
|
|||
|
PFM_RESOURCE Resource;
|
|||
|
HANDLE hDirectory = INVALID_HANDLE_VALUE;
|
|||
|
|
|||
|
ACQUIRE_SHARED_LOCK(gQuoLock);
|
|||
|
|
|||
|
Resource = OmReferenceObjectById(ObjectTypeResource, ResourceId);
|
|||
|
if (Resource == NULL)
|
|||
|
{
|
|||
|
Status = ERROR_FILE_NOT_FOUND;
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
|
|||
|
Status = CppGetCheckpointFile(Resource,
|
|||
|
dwCheckpointId,
|
|||
|
&DirectoryName,
|
|||
|
&FileName,
|
|||
|
NULL,
|
|||
|
fCryptoCheckpoint);
|
|||
|
OmDereferenceObject(Resource);
|
|||
|
|
|||
|
if (Status != ERROR_SUCCESS)
|
|||
|
{
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[CP] CppDepositCheckpoint - CppGetCheckpointFile failed %1!d!\n",
|
|||
|
Status);
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
ClRtlLogPrint(LOG_NOISE,
|
|||
|
"[CP] CppDepositCheckpoint checkpointing data to file %1!ws!\n",
|
|||
|
FileName);
|
|||
|
//
|
|||
|
// Create the directory.
|
|||
|
//
|
|||
|
if (!CreateDirectory(DirectoryName, NULL))
|
|||
|
{
|
|||
|
Status = GetLastError();
|
|||
|
if (Status != ERROR_ALREADY_EXISTS)
|
|||
|
{
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[CP] CppDepositCheckpoint unable to create directory %1!ws!, error %2!d!\n",
|
|||
|
DirectoryName,
|
|||
|
Status);
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//the directory exists, set Status to ERROR_SUCCESS
|
|||
|
Status = ERROR_SUCCESS;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//
|
|||
|
// The directory was newly created. Put the appropriate ACL on it
|
|||
|
// so that only ADMINs can read it.
|
|||
|
//
|
|||
|
hDirectory = CreateFile(DirectoryName,
|
|||
|
GENERIC_READ | WRITE_DAC | READ_CONTROL,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
OPEN_ALWAYS,
|
|||
|
FILE_FLAG_BACKUP_SEMANTICS,
|
|||
|
NULL);
|
|||
|
if (hDirectory == INVALID_HANDLE_VALUE)
|
|||
|
{
|
|||
|
Status = GetLastError();
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[CP] CppDepositCheckpoint unable to open directory %1!ws!, error %2!d!\n",
|
|||
|
DirectoryName,
|
|||
|
Status);
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
Status = ClRtlSetObjSecurityInfo(hDirectory,
|
|||
|
SE_FILE_OBJECT,
|
|||
|
GENERIC_ALL,
|
|||
|
GENERIC_ALL,
|
|||
|
0);
|
|||
|
|
|||
|
if (Status != ERROR_SUCCESS)
|
|||
|
{
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[CP] CppDepositCheckpoint- unable to set ACL on directory %1!ws!, error %2!d!\n",
|
|||
|
DirectoryName,
|
|||
|
Status);
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Pull the checkpoint data file across RPC
|
|||
|
//
|
|||
|
Status = DmPullFile(FileName, CheckpointData);
|
|||
|
if (Status != ERROR_SUCCESS) {
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[CP] CppDepositCheckpoint - DmPullFile %1!ws! failed %2!d!\n",
|
|||
|
FileName,
|
|||
|
Status);
|
|||
|
}
|
|||
|
|
|||
|
FnExit:
|
|||
|
RELEASE_LOCK(gQuoLock);
|
|||
|
|
|||
|
//clean up
|
|||
|
if (DirectoryName) LocalFree(DirectoryName);
|
|||
|
if (FileName) LocalFree(FileName);
|
|||
|
if (hDirectory != INVALID_HANDLE_VALUE)
|
|||
|
CloseHandle(hDirectory);
|
|||
|
|
|||
|
//
|
|||
|
// Adjust the return status if the quorum volume is truly offline and that is why this
|
|||
|
// call failed.
|
|||
|
//
|
|||
|
if ( ( Status != ERROR_SUCCESS ) && ( CppIsQuorumVolumeOffline() == TRUE ) ) Status = ERROR_NOT_READY;
|
|||
|
|
|||
|
//At this point, CppDepositCheckpoint should either
|
|||
|
|
|||
|
//a) throw the error code as an exception, or
|
|||
|
//b) drain the [in] pipe and then return the error code normally
|
|||
|
|
|||
|
//but if it returns without draining the pipe, and the RPC runtime throws
|
|||
|
//the pipe-discipline exception.
|
|||
|
if (Status != ERROR_SUCCESS)
|
|||
|
RpcRaiseException(Status);
|
|||
|
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_CpDepositCheckpoint(
|
|||
|
handle_t IDL_handle,
|
|||
|
LPCWSTR ResourceId,
|
|||
|
DWORD dwCheckpointId,
|
|||
|
BYTE_PIPE CheckpointData
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Server side RPC to allow other nodes to checkpoint data to the
|
|||
|
quorum disk.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used.
|
|||
|
|
|||
|
ResourceId - Name of the resource whose data is being checkpointed
|
|||
|
|
|||
|
dwCheckpointId - Unique identifier of the checkpoint
|
|||
|
|
|||
|
CheckpointData - pipe through which checkpoint data can be retrieved.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return CppDepositCheckpoint(IDL_handle,
|
|||
|
ResourceId,
|
|||
|
dwCheckpointId,
|
|||
|
CheckpointData,
|
|||
|
FALSE
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_CpDepositCryptoCheckpoint(
|
|||
|
handle_t IDL_handle,
|
|||
|
LPCWSTR ResourceId,
|
|||
|
DWORD dwCheckpointId,
|
|||
|
BYTE_PIPE CheckpointData
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Server side RPC to allow other nodes to checkpoint data to the
|
|||
|
quorum disk.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used.
|
|||
|
|
|||
|
ResourceId - Name of the resource whose data is being checkpointed
|
|||
|
|
|||
|
dwCheckpointId - Unique identifier of the checkpoint
|
|||
|
|
|||
|
CheckpointData - pipe through which checkpoint data can be retrieved.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return CppDepositCheckpoint(IDL_handle,
|
|||
|
ResourceId,
|
|||
|
dwCheckpointId,
|
|||
|
CheckpointData,
|
|||
|
TRUE
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
CppRetrieveCheckpoint(
|
|||
|
handle_t IDL_handle,
|
|||
|
LPCWSTR ResourceId,
|
|||
|
DWORD dwCheckpointId,
|
|||
|
BOOLEAN fCryptoCheckpoint,
|
|||
|
BYTE_PIPE CheckpointData
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Server side RPC through which data checkpointed to the quorum disk
|
|||
|
can be retrieved by other nodes.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used.
|
|||
|
|
|||
|
ResourceId - Name of the resource whose checkpoint data is to be retrieved
|
|||
|
|
|||
|
dwCheckpointId - Unique identifier of the checkpoint
|
|||
|
|
|||
|
fCryptoCheckpoint - Indicates if the checkpoint is a crypto checkpoint
|
|||
|
|
|||
|
CheckpointData - pipe through which checkpoint data should be sent
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD Status;
|
|||
|
LPWSTR FileName=NULL;
|
|||
|
HANDLE hFile;
|
|||
|
BOOL Success;
|
|||
|
PFM_RESOURCE Resource;
|
|||
|
|
|||
|
ACQUIRE_SHARED_LOCK(gQuoLock);
|
|||
|
Resource = OmReferenceObjectById(ObjectTypeResource, ResourceId);
|
|||
|
if (Resource == NULL) {
|
|||
|
Status = ERROR_FILE_NOT_FOUND;
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
|
|||
|
Status = CppGetCheckpointFile(Resource,
|
|||
|
dwCheckpointId,
|
|||
|
NULL,
|
|||
|
&FileName,
|
|||
|
NULL,
|
|||
|
fCryptoCheckpoint);
|
|||
|
OmDereferenceObject(Resource);
|
|||
|
if (Status != ERROR_SUCCESS) {
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[CP] CppRetrieveCheckpoint - CppGetCheckpointFile failed %1!d!\n",
|
|||
|
Status);
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
ClRtlLogPrint(LOG_NOISE,
|
|||
|
"[CP] CppRetrieveCheckpoint retrieving data from file %1!ws!\n",
|
|||
|
FileName);
|
|||
|
|
|||
|
//
|
|||
|
// Push the checkpoint data file across RPC
|
|||
|
//
|
|||
|
Status = DmPushFile(FileName, CheckpointData);
|
|||
|
if (Status != ERROR_SUCCESS) {
|
|||
|
ClRtlLogPrint(LOG_CRITICAL,
|
|||
|
"[CP] CppRetrieveCheckpoint - DmPushFile %1!ws! failed %2!d!\n",
|
|||
|
FileName,
|
|||
|
Status);
|
|||
|
}
|
|||
|
|
|||
|
FnExit:
|
|||
|
RELEASE_LOCK(gQuoLock);
|
|||
|
//cleanup
|
|||
|
if (FileName) LocalFree(FileName);
|
|||
|
|
|||
|
//
|
|||
|
// Adjust the return status if the quorum volume is truly offline and that is why this
|
|||
|
// call failed.
|
|||
|
//
|
|||
|
if ( ( Status != ERROR_SUCCESS ) && ( CppIsQuorumVolumeOffline() == TRUE ) ) Status = ERROR_NOT_READY;
|
|||
|
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_CpRetrieveCheckpoint(
|
|||
|
handle_t IDL_handle,
|
|||
|
LPCWSTR ResourceId,
|
|||
|
DWORD dwCheckpointId,
|
|||
|
BYTE_PIPE CheckpointData
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Server side RPC through which data checkpointed to the quorum disk
|
|||
|
can be retrieved by other nodes.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used.
|
|||
|
|
|||
|
ResourceId - Name of the resource whose checkpoint data is to be retrieved
|
|||
|
|
|||
|
dwCheckpointId - Unique identifier of the checkpoint
|
|||
|
|
|||
|
CheckpointData - pipe through which checkpoint data should be sent
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return CppRetrieveCheckpoint(IDL_handle,
|
|||
|
ResourceId,
|
|||
|
dwCheckpointId,
|
|||
|
FALSE,
|
|||
|
CheckpointData
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_CpRetrieveCryptoCheckpoint(
|
|||
|
handle_t IDL_handle,
|
|||
|
LPCWSTR ResourceId,
|
|||
|
DWORD dwCheckpointId,
|
|||
|
BYTE_PIPE CheckpointData
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Server side RPC through which data checkpointed to the quorum disk
|
|||
|
can be retrieved by other nodes.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used.
|
|||
|
|
|||
|
ResourceId - Name of the resource whose checkpoint data is to be retrieved
|
|||
|
|
|||
|
dwCheckpointId - Unique identifier of the checkpoint
|
|||
|
|
|||
|
CheckpointData - pipe through which checkpoint data should be sent
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
return CppRetrieveCheckpoint(IDL_handle,
|
|||
|
ResourceId,
|
|||
|
dwCheckpointId,
|
|||
|
TRUE,
|
|||
|
CheckpointData
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
error_status_t
|
|||
|
CppDeleteCheckpoint(
|
|||
|
handle_t IDL_handle,
|
|||
|
LPCWSTR ResourceId,
|
|||
|
DWORD dwCheckpointId,
|
|||
|
LPCWSTR lpszQuorumPath,
|
|||
|
BOOL fCryptoCheckpoint
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Server side RPC through which the checkpoint file corresponding to a
|
|||
|
given checkpointid for a resource is deleted.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used.
|
|||
|
|
|||
|
ResourceId - Name of the resource whose checkpoint file is to be deleted.
|
|||
|
|
|||
|
dwCheckpointId - Unique identifier of the checkpoint. If 0, all checkpoints
|
|||
|
must be deleted.
|
|||
|
|
|||
|
lpszQuorumPath - The path to the cluster files from where these files must
|
|||
|
be deleted.
|
|||
|
|
|||
|
fCryptoCheckpoint - Indicates if the checkpoint is a crypto checkpoint
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD Status;
|
|||
|
PFM_RESOURCE Resource = NULL;
|
|||
|
|
|||
|
Resource = OmReferenceObjectById(ObjectTypeResource, ResourceId);
|
|||
|
if (Resource == NULL) {
|
|||
|
Status = ERROR_FILE_NOT_FOUND;
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
|
|||
|
if (fCryptoCheckpoint) {
|
|||
|
Status = CpckDeleteCheckpointFile(Resource, dwCheckpointId, lpszQuorumPath);
|
|||
|
} else {
|
|||
|
Status = CppDeleteCheckpointFile(Resource, dwCheckpointId, lpszQuorumPath);
|
|||
|
}
|
|||
|
|
|||
|
if (Status != ERROR_SUCCESS)
|
|||
|
{
|
|||
|
goto FnExit;
|
|||
|
}
|
|||
|
|
|||
|
FnExit:
|
|||
|
if (Resource) OmDereferenceObject(Resource);
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_CpDeleteCheckpoint(
|
|||
|
handle_t IDL_handle,
|
|||
|
LPCWSTR ResourceId,
|
|||
|
DWORD dwCheckpointId,
|
|||
|
LPCWSTR lpszQuorumPath
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Server side RPC through which the checkpoint file corresponding to a
|
|||
|
given checkpointid for a resource is deleted.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used.
|
|||
|
|
|||
|
ResourceId - Name of the resource whose checkpoint file is to be deleted.
|
|||
|
|
|||
|
dwCheckpointId - Unique identifier of the checkpoint. If 0, all checkpoints
|
|||
|
must be deleted.
|
|||
|
|
|||
|
lpszQuorumPath - The path to the cluster files from where these files must
|
|||
|
be deleted.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
return CppDeleteCheckpoint(IDL_handle,
|
|||
|
ResourceId,
|
|||
|
dwCheckpointId,
|
|||
|
lpszQuorumPath,
|
|||
|
FALSE);
|
|||
|
}
|
|||
|
|
|||
|
error_status_t
|
|||
|
s_CpDeleteCryptoCheckpoint(
|
|||
|
handle_t IDL_handle,
|
|||
|
LPCWSTR ResourceId,
|
|||
|
DWORD dwCheckpointId,
|
|||
|
LPCWSTR lpszQuorumPath
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Server side RPC through which the crypto checkpoint file corresponding to a
|
|||
|
given checkpointid for a resource is deleted.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IDL_handle - RPC binding handle, not used.
|
|||
|
|
|||
|
ResourceId - Name of the resource whose checkpoint file is to be deleted.
|
|||
|
|
|||
|
dwCheckpointId - Unique identifier of the checkpoint. If 0, all checkpoints
|
|||
|
must be deleted.
|
|||
|
|
|||
|
lpszQuorumPath - The path to the cluster files from where these files must
|
|||
|
be deleted.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful
|
|||
|
|
|||
|
Win32 error code otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
return CppDeleteCheckpoint(IDL_handle,
|
|||
|
ResourceId,
|
|||
|
dwCheckpointId,
|
|||
|
lpszQuorumPath,
|
|||
|
TRUE);
|
|||
|
}
|