957 lines
22 KiB
C++
957 lines
22 KiB
C++
|
//+--------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
||
|
//
|
||
|
// File: backup.cpp
|
||
|
//
|
||
|
// Contents: Cert Server client database backup APIs
|
||
|
//
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
#include <pch.cpp>
|
||
|
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include "certsrvd.h"
|
||
|
#include "csdisp.h"
|
||
|
#include "certadmp.h"
|
||
|
|
||
|
#define __dwFILE__ __dwFILE_CERTADM_BACKUP_CPP__
|
||
|
|
||
|
|
||
|
#if DBG
|
||
|
#define _CERTBCLI_TYPECHECK
|
||
|
#endif
|
||
|
|
||
|
#include <certbcli.h>
|
||
|
|
||
|
|
||
|
WCHAR g_wszBackupAnnotation[] = L"backup";
|
||
|
WCHAR g_wszRestoreAnnotation[] = L"restore";
|
||
|
|
||
|
|
||
|
HRESULT
|
||
|
AllocateContext(
|
||
|
IN WCHAR const *pwszConfig,
|
||
|
OUT CSBACKUPCONTEXT **ppcsbc)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
WCHAR *pwszT = NULL;
|
||
|
|
||
|
CSASSERT(NULL != pfnCertSrvIsServerOnline);
|
||
|
pwszT = (WCHAR *) LocalAlloc(
|
||
|
LMEM_FIXED,
|
||
|
(wcslen(pwszConfig) + 1) * sizeof(WCHAR));
|
||
|
if (NULL == pwszT)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
}
|
||
|
wcscpy(pwszT, pwszConfig);
|
||
|
|
||
|
*ppcsbc = (CSBACKUPCONTEXT *) LocalAlloc(
|
||
|
LMEM_FIXED | LMEM_ZEROINIT,
|
||
|
sizeof(**ppcsbc));
|
||
|
if (NULL == *ppcsbc)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
}
|
||
|
(*ppcsbc)->pwszConfig = pwszT;
|
||
|
pwszT = NULL;
|
||
|
hr = S_OK;
|
||
|
|
||
|
error:
|
||
|
if (NULL != pwszT)
|
||
|
{
|
||
|
LocalFree(pwszT);
|
||
|
}
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
ReleaseContext(
|
||
|
IN OUT CSBACKUPCONTEXT *pcsbc)
|
||
|
{
|
||
|
CSASSERT(NULL != pcsbc);
|
||
|
if (NULL != pcsbc->pwszConfig)
|
||
|
{
|
||
|
LocalFree(const_cast<WCHAR *>(pcsbc->pwszConfig));
|
||
|
pcsbc->pwszConfig = NULL;
|
||
|
}
|
||
|
if (NULL != pcsbc->pICertAdminD)
|
||
|
{
|
||
|
CloseAdminServer(&pcsbc->pICertAdminD);
|
||
|
CSASSERT(NULL == pcsbc->pICertAdminD);
|
||
|
}
|
||
|
if (NULL != pcsbc->pbReadBuffer)
|
||
|
{
|
||
|
VirtualFree(pcsbc->pbReadBuffer, 0, MEM_RELEASE);
|
||
|
}
|
||
|
LocalFree(pcsbc);
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT
|
||
|
OpenAdminServer(
|
||
|
IN WCHAR const *pwszConfig,
|
||
|
OUT WCHAR const **ppwszAuthority,
|
||
|
OUT DWORD *pdwServerVersion,
|
||
|
OUT ICertAdminD2 **ppICertAdminD)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
BOOL fCoInitialized = FALSE;
|
||
|
|
||
|
hr = CoInitialize(NULL);
|
||
|
if (RPC_E_CHANGED_MODE == hr)
|
||
|
{
|
||
|
_PrintError(hr, "CoInitialize");
|
||
|
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||
|
}
|
||
|
if (S_OK != hr && S_FALSE != hr)
|
||
|
{
|
||
|
_JumpError(hr, error, "CoInitialize");
|
||
|
}
|
||
|
fCoInitialized = TRUE;
|
||
|
|
||
|
*pdwServerVersion = 0;
|
||
|
hr = myOpenAdminDComConnection(
|
||
|
pwszConfig,
|
||
|
ppwszAuthority,
|
||
|
NULL,
|
||
|
pdwServerVersion,
|
||
|
ppICertAdminD);
|
||
|
_JumpIfError(hr, error, "myOpenDComConnection");
|
||
|
|
||
|
CSASSERT(0 != *pdwServerVersion);
|
||
|
|
||
|
error:
|
||
|
if (S_OK != hr && fCoInitialized)
|
||
|
{
|
||
|
CoUninitialize();
|
||
|
}
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
CloseAdminServer(
|
||
|
IN OUT ICertAdminD2 **ppICertAdminD)
|
||
|
{
|
||
|
myCloseDComConnection((IUnknown **) ppICertAdminD, NULL);
|
||
|
CoUninitialize();
|
||
|
}
|
||
|
|
||
|
|
||
|
//+--------------------------------------------------------------------------
|
||
|
// CertSrvIsServerOnline -- check to see if the Cert Server is Online on the
|
||
|
// given server. This call is guaranteed to return quickly.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// [in] pwszConfig - name of the server to check
|
||
|
// [out] pfServerOnline - pointer to receive the bool result
|
||
|
// (TRUE if Cert Server is online; FALSE, otherwise)
|
||
|
// Returns:
|
||
|
// S_OK if the call executed successfully;
|
||
|
// Failure code otherwise.
|
||
|
//+--------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT
|
||
|
CERTBCLI_API
|
||
|
CertSrvIsServerOnlineW(
|
||
|
IN WCHAR const *pwszConfig,
|
||
|
OPTIONAL OUT BOOL *pfServerOnline)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
ICertAdminD2 *pICertAdminD = NULL;
|
||
|
WCHAR const *pwszAuthority;
|
||
|
DWORD State;
|
||
|
DWORD dwServerVersion;
|
||
|
|
||
|
if (NULL == pwszConfig)
|
||
|
{
|
||
|
hr = E_POINTER;
|
||
|
_JumpError(hr, error, "NULL parm");
|
||
|
}
|
||
|
__try
|
||
|
{
|
||
|
if (NULL != pfServerOnline)
|
||
|
{
|
||
|
*pfServerOnline = FALSE;
|
||
|
}
|
||
|
hr = OpenAdminServer(
|
||
|
pwszConfig,
|
||
|
&pwszAuthority,
|
||
|
&dwServerVersion,
|
||
|
&pICertAdminD);
|
||
|
|
||
|
// OpenAdminServer etc might get E_ACCESSDENIED -- meaning server down
|
||
|
|
||
|
if (S_OK != hr)
|
||
|
{
|
||
|
_PrintError(hr, "OpenAdminServer");
|
||
|
if (E_ACCESSDENIED == hr || (HRESULT) ERROR_ACCESS_DENIED == hr)
|
||
|
{
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
__leave;
|
||
|
}
|
||
|
hr = pICertAdminD->GetServerState(pwszAuthority, &State);
|
||
|
_LeaveIfError(hr, "GetServerState");
|
||
|
|
||
|
if (NULL != pfServerOnline && 0 != State)
|
||
|
{
|
||
|
*pfServerOnline = TRUE;
|
||
|
}
|
||
|
}
|
||
|
__except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
if (NULL != pICertAdminD)
|
||
|
{
|
||
|
CloseAdminServer(&pICertAdminD);
|
||
|
}
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+--------------------------------------------------------------------------
|
||
|
// CertSrvBackupPrepare -- prepare the DS for the online backup and return a
|
||
|
// Backup Context Handle to be used for subsequent calls to backup
|
||
|
// functions.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// [in] pwszConfig - server name to prepare for online backup
|
||
|
// [in] grbitJet - flag to be passed to jet while backing up dbs
|
||
|
// [in] dwBackupFlags - CSBACKUP_TYPE_FULL or CSBACKUP_TYPE_LOGS_ONLY
|
||
|
// [out] phbc - pointer that will receive the backup context handle
|
||
|
//
|
||
|
// Returns:
|
||
|
// S_OK if the call executed successfully;
|
||
|
// Failure code otherwise.
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT
|
||
|
CERTBCLI_API
|
||
|
CertSrvBackupPrepareW(
|
||
|
IN WCHAR const *pwszConfig,
|
||
|
IN ULONG grbitJet,
|
||
|
IN ULONG dwBackupFlags,
|
||
|
OUT HCSBC *phbc)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
CSBACKUPCONTEXT *pcsbc = NULL;
|
||
|
|
||
|
if (NULL == pwszConfig || NULL == phbc)
|
||
|
{
|
||
|
hr = E_POINTER;
|
||
|
_JumpError(hr, error, "NULL parm");
|
||
|
}
|
||
|
*phbc = NULL;
|
||
|
if (CSBACKUP_TYPE_LOGS_ONLY == dwBackupFlags)
|
||
|
{
|
||
|
grbitJet |= JET_bitBackupIncremental;
|
||
|
}
|
||
|
else if (CSBACKUP_TYPE_FULL != dwBackupFlags)
|
||
|
{
|
||
|
hr = E_INVALIDARG;
|
||
|
_JumpError(hr, error, "dwBackupFlags");
|
||
|
}
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
hr = AllocateContext(pwszConfig, &pcsbc);
|
||
|
_LeaveIfError(hr, "AllocateContext");
|
||
|
|
||
|
hr = OpenAdminServer(
|
||
|
pcsbc->pwszConfig,
|
||
|
&pcsbc->pwszAuthority,
|
||
|
&pcsbc->dwServerVersion,
|
||
|
&pcsbc->pICertAdminD);
|
||
|
_LeaveIfError(hr, "OpenAdminServer");
|
||
|
|
||
|
hr = pcsbc->pICertAdminD->BackupPrepare(
|
||
|
pcsbc->pwszAuthority,
|
||
|
grbitJet,
|
||
|
dwBackupFlags,
|
||
|
g_wszBackupAnnotation,
|
||
|
0); // dwClientIdentifier
|
||
|
_LeaveIfError(hr, "BackupPrepare");
|
||
|
|
||
|
*phbc = (HCSBC) pcsbc;
|
||
|
pcsbc = NULL;
|
||
|
}
|
||
|
__except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
if (NULL != pcsbc)
|
||
|
{
|
||
|
ReleaseContext(pcsbc);
|
||
|
}
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
// Return the length of a double '\0' terminated string -- includes the
|
||
|
// trailing '\0's.
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
mySzzLen(
|
||
|
CHAR const *pszz)
|
||
|
{
|
||
|
CHAR const *psz;
|
||
|
DWORD cb;
|
||
|
|
||
|
psz = pszz;
|
||
|
do
|
||
|
{
|
||
|
cb = strlen(psz);
|
||
|
psz += cb + 1;
|
||
|
} while (0 != cb);
|
||
|
return SAFE_SUBTRACT_POINTERS(psz, pszz); // includes double trailing '\0's
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT
|
||
|
myLocalAllocCopy(
|
||
|
IN VOID *pbIn,
|
||
|
IN DWORD cbIn,
|
||
|
OUT VOID **pbOut)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
*pbOut = LocalAlloc(LMEM_FIXED, cbIn);
|
||
|
if (NULL == *pbOut)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
_JumpError(hr, error, "LocalAlloc");
|
||
|
}
|
||
|
CopyMemory(*pbOut, pbIn, cbIn);
|
||
|
hr = S_OK;
|
||
|
|
||
|
error:
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT
|
||
|
BackupRestoreGetFileList(
|
||
|
IN DWORD FileListType,
|
||
|
IN HCSBC hbc,
|
||
|
OUT WCHAR **ppwszzFileList,
|
||
|
OUT DWORD *pcbList)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
CSBACKUPCONTEXT *pcsbc;
|
||
|
WCHAR *pwszzFileList = NULL;
|
||
|
LONG cwcList;
|
||
|
DWORD cbList;
|
||
|
|
||
|
if (NULL == hbc)
|
||
|
{
|
||
|
hr = E_HANDLE;
|
||
|
_JumpError(hr, error, "NULL handle");
|
||
|
}
|
||
|
if (NULL != ppwszzFileList)
|
||
|
{
|
||
|
*ppwszzFileList = NULL;
|
||
|
}
|
||
|
if (NULL != pcbList)
|
||
|
{
|
||
|
*pcbList = 0;
|
||
|
}
|
||
|
if (NULL == ppwszzFileList || NULL == pcbList)
|
||
|
{
|
||
|
hr = E_POINTER;
|
||
|
_JumpError(hr, error, "NULL parm");
|
||
|
}
|
||
|
pcsbc = (CSBACKUPCONTEXT *) hbc;
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
if (NULL == pcsbc->pICertAdminD)
|
||
|
{
|
||
|
hr = OpenAdminServer(
|
||
|
pcsbc->pwszConfig,
|
||
|
&pcsbc->pwszAuthority,
|
||
|
&pcsbc->dwServerVersion,
|
||
|
&pcsbc->pICertAdminD);
|
||
|
_LeaveIfError(hr, "OpenAdminServer");
|
||
|
}
|
||
|
CSASSERT(NULL != pcsbc->pICertAdminD);
|
||
|
|
||
|
if (FLT_DBFILES == FileListType)
|
||
|
{
|
||
|
hr = pcsbc->pICertAdminD->BackupGetAttachmentInformation(
|
||
|
&pwszzFileList,
|
||
|
&cwcList);
|
||
|
_LeaveIfError(hr, "BackupGetAttachmentInformation");
|
||
|
}
|
||
|
else if (FLT_LOGFILES == FileListType)
|
||
|
{
|
||
|
hr = pcsbc->pICertAdminD->BackupGetBackupLogs(
|
||
|
&pwszzFileList,
|
||
|
&cwcList);
|
||
|
_LeaveIfError(hr, "BackupGetBackupLogs");
|
||
|
}
|
||
|
else if (FLT_DYNAMICFILES == FileListType)
|
||
|
{
|
||
|
hr = pcsbc->pICertAdminD->BackupGetDynamicFiles(
|
||
|
&pwszzFileList,
|
||
|
&cwcList);
|
||
|
_LeaveIfError(hr, "BackupGetDynamicFileList");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CSASSERT(FLT_RESTOREDBLOCATIONS == FileListType);
|
||
|
hr = pcsbc->pICertAdminD->RestoreGetDatabaseLocations(
|
||
|
&pwszzFileList,
|
||
|
&cwcList);
|
||
|
_LeaveIfError(hr, "RestoreGetDatabaseLocations");
|
||
|
}
|
||
|
|
||
|
cbList = cwcList * sizeof(WCHAR);
|
||
|
myRegisterMemAlloc(pwszzFileList, cbList, CSM_COTASKALLOC);
|
||
|
|
||
|
hr = myLocalAllocCopy(pwszzFileList, cbList, (VOID **) ppwszzFileList);
|
||
|
_JumpIfError(hr, error, "myLocalAllocCopy");
|
||
|
|
||
|
*pcbList = cbList;
|
||
|
}
|
||
|
__except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
if (NULL != pwszzFileList)
|
||
|
{
|
||
|
CoTaskMemFree(pwszzFileList);
|
||
|
}
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+--------------------------------------------------------------------------
|
||
|
// CertSrvBackupGetDatabaseNames -- return the list of data bases that need to
|
||
|
// be backed up for the given backup context The information returned in
|
||
|
// ppwszzFileList should not be interpreted, as it only has meaning on
|
||
|
// the server being backed up.
|
||
|
//
|
||
|
// This API will allocate a buffer of sufficient size to hold the entire
|
||
|
// attachment list, which must be later freed with CertSrvBackupFree.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// [in] hbc - backup context handle
|
||
|
// [out] ppwszzFileList - pointer that will receive the pointer to the
|
||
|
// attachment info; allocated memory should be freed using
|
||
|
// CertSrvBackupFree() API by the caller when it is no longer
|
||
|
// needed; ppwszzFileList info is an array of null-terminated
|
||
|
// filenames and the list is terminated by two L'\0's.
|
||
|
// [out] pcbList - will receive the number of bytes returned
|
||
|
//
|
||
|
// Returns:
|
||
|
// S_OK if the call executed successfully;
|
||
|
// Failure code otherwise.
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT
|
||
|
CERTBCLI_API
|
||
|
CertSrvBackupGetDatabaseNamesW(
|
||
|
IN HCSBC hbc,
|
||
|
OUT WCHAR **ppwszzFileList,
|
||
|
OUT DWORD *pcbList)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
hr = BackupRestoreGetFileList(FLT_DBFILES, hbc, ppwszzFileList, pcbList);
|
||
|
_JumpIfError(hr, error, "BackupRestoreGetFileList");
|
||
|
|
||
|
error:
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+--------------------------------------------------------------------------
|
||
|
// CertSrvBackupGetDynamicFileList -- return the list of dynamic files that
|
||
|
// need to be backed up for the given backup context The information
|
||
|
// returned in ppwszzFileList should not be interpreted, as it only has
|
||
|
// meaning on the server being backed up.
|
||
|
//
|
||
|
// This API will allocate a buffer of sufficient size to hold the entire
|
||
|
// attachment list, which must be later freed with CertSrvBackupFree.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// [in] hbc - backup context handle
|
||
|
// [out] ppwszzFileList - pointer that will receive the pointer to the
|
||
|
// attachment info; allocated memory should be freed using
|
||
|
// CertSrvBackupFree() API by the caller when it is no longer
|
||
|
// needed; ppwszzFileList info is an array of null-terminated
|
||
|
// filenames and the list is terminated by two L'\0's.
|
||
|
// [out] pcbList - will receive the number of bytes returned
|
||
|
//
|
||
|
// Returns:
|
||
|
// S_OK if the call executed successfully;
|
||
|
// Failure code otherwise.
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT
|
||
|
CERTBCLI_API
|
||
|
CertSrvBackupGetDynamicFileListW(
|
||
|
IN HCSBC hbc,
|
||
|
OUT WCHAR **ppwszzFileList,
|
||
|
OUT DWORD *pcbList)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
hr = BackupRestoreGetFileList(
|
||
|
FLT_DYNAMICFILES,
|
||
|
hbc,
|
||
|
ppwszzFileList,
|
||
|
pcbList);
|
||
|
_JumpIfError(hr, error, "BackupRestoreGetFileList");
|
||
|
|
||
|
error:
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
#define CBREADMIN (64 * 1024) // 64k minimum buffer
|
||
|
#define CBREADDEFAULT (512 * 1024) // 512k recommended
|
||
|
#define CBREADMAX (4 * 1024 * 1024) // 4mb maximum buffer
|
||
|
|
||
|
HRESULT
|
||
|
BufferAllocate(
|
||
|
IN DWORD cbHintSize,
|
||
|
OUT BYTE **ppbBuffer,
|
||
|
OUT DWORD *pcbBuffer)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
DWORD cb;
|
||
|
|
||
|
*ppbBuffer = NULL;
|
||
|
if (0 == cbHintSize)
|
||
|
{
|
||
|
// at 512k the server begins doing efficient backups
|
||
|
|
||
|
cbHintSize = CBREADDEFAULT;
|
||
|
}
|
||
|
else if (CBREADMIN > cbHintSize)
|
||
|
{
|
||
|
cbHintSize = CBREADMIN;
|
||
|
}
|
||
|
|
||
|
for (cb = CBREADMAX; (cb >> 1) >= cbHintSize; cb >>= 1)
|
||
|
;
|
||
|
|
||
|
while (TRUE)
|
||
|
{
|
||
|
*ppbBuffer = (BYTE *) VirtualAlloc(
|
||
|
NULL,
|
||
|
cb,
|
||
|
MEM_COMMIT,
|
||
|
PAGE_READWRITE);
|
||
|
if (NULL != *ppbBuffer)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
hr = myHLastError();
|
||
|
CSASSERT(S_OK == hr);
|
||
|
_PrintError(hr, "VirtualAlloc");
|
||
|
|
||
|
cb >>= 1;
|
||
|
if (CBREADMIN > cb)
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
}
|
||
|
*pcbBuffer = cb;
|
||
|
hr = S_OK;
|
||
|
|
||
|
error:
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+--------------------------------------------------------------------------
|
||
|
// CertSrvBackupOpenFile -- open a remote file for backup, and perform whatever
|
||
|
// client and server side operations to prepare for the backup.
|
||
|
// It takes in a hint of the size of the buffer that will later be passed
|
||
|
// into the CertSrvBackupRead API that can be used to optimize the network
|
||
|
// traffic for the API.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// [in] hbc - backup context handle
|
||
|
// [in] pwszPath - name of the attachment to be opened for read
|
||
|
// [in] cbReadHintSize - suggested size in bytes that might be used
|
||
|
// during the subsequent reads on this attachment
|
||
|
// [out] pliFileSize - pointer to a large integer that would receive the
|
||
|
// size in bytes of the given attachment
|
||
|
// Returns:
|
||
|
// S_OK if the call executed successfully;
|
||
|
// Failure code otherwise.
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT
|
||
|
CERTBCLI_API
|
||
|
CertSrvBackupOpenFileW(
|
||
|
IN HCSBC hbc,
|
||
|
IN WCHAR const *pwszPath,
|
||
|
IN DWORD cbReadHintSize,
|
||
|
OUT LARGE_INTEGER *pliFileSize)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
CSBACKUPCONTEXT *pcsbc;
|
||
|
|
||
|
if (NULL == hbc)
|
||
|
{
|
||
|
hr = E_HANDLE;
|
||
|
_JumpError(hr, error, "NULL handle");
|
||
|
}
|
||
|
if (NULL == pwszPath || NULL == pliFileSize)
|
||
|
{
|
||
|
hr = E_POINTER;
|
||
|
_JumpError(hr, error, "NULL parm");
|
||
|
}
|
||
|
pcsbc = (CSBACKUPCONTEXT *) hbc;
|
||
|
if (pcsbc->fFileOpen)
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(ERROR_BUSY);
|
||
|
_JumpError(hr, error, "File already open");
|
||
|
}
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
hr = pcsbc->pICertAdminD->BackupOpenFile(
|
||
|
pwszPath,
|
||
|
(ULONGLONG *) pliFileSize);
|
||
|
_LeaveIfErrorStr(hr, "BackupOpenFile", pwszPath);
|
||
|
|
||
|
if (NULL == pcsbc->pbReadBuffer)
|
||
|
{
|
||
|
hr = BufferAllocate(
|
||
|
cbReadHintSize,
|
||
|
&pcsbc->pbReadBuffer,
|
||
|
&pcsbc->cbReadBuffer);
|
||
|
_LeaveIfError(hr, "BufferAllocate");
|
||
|
}
|
||
|
pcsbc->fFileOpen = TRUE;
|
||
|
pcsbc->cbCache = 0;
|
||
|
}
|
||
|
__except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+--------------------------------------------------------------------------
|
||
|
// CertSrvBackupRead -- read the currently open attachment bytes into the given
|
||
|
// buffer. The client application is expected to call this function
|
||
|
// repeatedly until it gets the entire file (the application would have
|
||
|
// received the file size through the CertSrvBackupOpenFile call before.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// [in] hbc - backup context handle
|
||
|
// [in] pvBuffer - pointer to the buffer that would receive the read data.
|
||
|
// [in] cbBuffer - specifies the size of the above buffer
|
||
|
// [out] pcbRead - pointer to receive the actual number of bytes read.
|
||
|
//
|
||
|
// Returns:
|
||
|
// HRESULT - The status of the operation.
|
||
|
// S_OK if successful.
|
||
|
// ERROR_END_OF_FILE if the end of file was reached while being backed up
|
||
|
// Other Win32 and RPC error code.
|
||
|
//
|
||
|
// Note:
|
||
|
// It is important to realize that pcbRead may be less than cbBuffer.
|
||
|
// This does not indicate an error, some transports may choose to fragment
|
||
|
// the buffer being transmitted instead of returning the entire buffers
|
||
|
// worth of data.
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT
|
||
|
CERTBCLI_API
|
||
|
CertSrvBackupRead(
|
||
|
IN HCSBC hbc,
|
||
|
IN VOID *pvBuffer,
|
||
|
IN DWORD cbBuffer,
|
||
|
OUT DWORD *pcbRead)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
CSBACKUPCONTEXT *pcsbc;
|
||
|
BYTE *pbBuffer = (BYTE *) pvBuffer;
|
||
|
DWORD cbRead;
|
||
|
DWORD cb;
|
||
|
|
||
|
hr = E_HANDLE;
|
||
|
if (NULL == hbc)
|
||
|
{
|
||
|
_JumpError(hr, error, "NULL handle");
|
||
|
}
|
||
|
if (NULL == pvBuffer || NULL == pcbRead)
|
||
|
{
|
||
|
hr = E_POINTER;
|
||
|
_JumpError(hr, error, "NULL parm");
|
||
|
}
|
||
|
*pcbRead = 0;
|
||
|
pcsbc = (CSBACKUPCONTEXT *) hbc;
|
||
|
if (NULL == pcsbc->pbReadBuffer)
|
||
|
{
|
||
|
_JumpError(hr, error, "NULL buffer");
|
||
|
}
|
||
|
if (!pcsbc->fFileOpen)
|
||
|
{
|
||
|
_JumpError(hr, error, "File not open");
|
||
|
}
|
||
|
|
||
|
while (TRUE)
|
||
|
{
|
||
|
if (0 != pcsbc->cbCache)
|
||
|
{
|
||
|
cb = min(pcsbc->cbCache, cbBuffer);
|
||
|
CopyMemory(pbBuffer, pcsbc->pbCache, cb);
|
||
|
pbBuffer += cb;
|
||
|
cbBuffer -= cb;
|
||
|
pcsbc->pbCache += cb;
|
||
|
pcsbc->cbCache -= cb;
|
||
|
*pcbRead += cb;
|
||
|
}
|
||
|
if (0 == cbBuffer)
|
||
|
{
|
||
|
hr = S_OK;
|
||
|
break; // request satisfied
|
||
|
}
|
||
|
|
||
|
pcsbc->cbCache = 0;
|
||
|
__try
|
||
|
{
|
||
|
hr = pcsbc->pICertAdminD->BackupReadFile(
|
||
|
pcsbc->pbReadBuffer,
|
||
|
pcsbc->cbReadBuffer,
|
||
|
(LONG *) &cbRead);
|
||
|
_LeaveIfError(hr, "BackupReadFile");
|
||
|
}
|
||
|
__except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
}
|
||
|
if (S_OK != hr || 0 == cbRead)
|
||
|
{
|
||
|
break; // EOF
|
||
|
}
|
||
|
pcsbc->cbCache = cbRead;
|
||
|
pcsbc->pbCache = pcsbc->pbReadBuffer;
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+--------------------------------------------------------------------------
|
||
|
// CertSrvBackupClose -- called by the application after it completes reading
|
||
|
// all the data in the currently opened attachement.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// [in] hbc - backup context handle
|
||
|
//
|
||
|
// Returns:
|
||
|
// S_OK if the call executed successfully;
|
||
|
// Failure code otherwise.
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT
|
||
|
CERTBCLI_API
|
||
|
CertSrvBackupClose(
|
||
|
IN HCSBC hbc)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
CSBACKUPCONTEXT *pcsbc;
|
||
|
|
||
|
hr = E_HANDLE;
|
||
|
if (NULL == hbc)
|
||
|
{
|
||
|
_JumpError(hr, error, "NULL handle");
|
||
|
}
|
||
|
pcsbc = (CSBACKUPCONTEXT *) hbc;
|
||
|
if (!pcsbc->fFileOpen)
|
||
|
{
|
||
|
_JumpError(hr, error, "File not open");
|
||
|
}
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
hr = pcsbc->pICertAdminD->BackupCloseFile();
|
||
|
_LeaveIfError(hr, "BackupCloseFile");
|
||
|
}
|
||
|
__except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
// Clear flag even on failure...
|
||
|
|
||
|
pcsbc->fFileOpen = FALSE;
|
||
|
|
||
|
error:
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+--------------------------------------------------------------------------
|
||
|
// CertSrvBackupGetBackupLogs -- return the list of log files that need to be
|
||
|
// backed up for the given backup context
|
||
|
//
|
||
|
// This API will allocate a buffer of sufficient size to hold the entire
|
||
|
// backup log list, which must be later freed with CertSrvBackupFree.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// [in] hbc - backup context handle
|
||
|
// [out] pszBackupLogFiles - pointer that will receive the pointer to the
|
||
|
// list of log files; allocated memory should be freed using
|
||
|
// CertSrvBackupFree() API by the caller when it is no longer
|
||
|
// needed; Log files are returned in an array of null-terminated
|
||
|
// filenames and the list is terminated by two L'\0's.
|
||
|
// [out] pcbList - will receive the number of bytes returned
|
||
|
//
|
||
|
// Returns:
|
||
|
// S_OK if the call executed successfully;
|
||
|
// Failure code otherwise.
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT
|
||
|
CERTBCLI_API
|
||
|
CertSrvBackupGetBackupLogsW(
|
||
|
IN HCSBC hbc,
|
||
|
OUT WCHAR **ppwszzFileList,
|
||
|
OUT DWORD *pcbList)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
hr = BackupRestoreGetFileList(
|
||
|
FLT_LOGFILES,
|
||
|
hbc,
|
||
|
ppwszzFileList,
|
||
|
pcbList);
|
||
|
_JumpIfError(hr, error, "BackupRestoreGetFileList");
|
||
|
|
||
|
error:
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+--------------------------------------------------------------------------
|
||
|
// CertSrvBackupTruncateLogs -- terminate the backup operation. Called when
|
||
|
// the backup has completed successfully.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// [in] hbc - backup context handle
|
||
|
//
|
||
|
// Returns:
|
||
|
// S_OK if the call executed successfully;
|
||
|
// Failure code otherwise.
|
||
|
//
|
||
|
// Note:
|
||
|
// Again, this API may have to take a grbit parameter to be passed to the
|
||
|
// server to indicate the backup type.
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT
|
||
|
CERTBCLI_API
|
||
|
CertSrvBackupTruncateLogs(
|
||
|
IN HCSBC hbc)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
CSBACKUPCONTEXT *pcsbc;
|
||
|
|
||
|
if (NULL == hbc)
|
||
|
{
|
||
|
hr = E_HANDLE;
|
||
|
_JumpError(hr, error, "NULL handle");
|
||
|
}
|
||
|
pcsbc = (CSBACKUPCONTEXT *) hbc;
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
hr = pcsbc->pICertAdminD->BackupTruncateLogs();
|
||
|
_LeaveIfError(hr, "BackupTruncateLogs");
|
||
|
}
|
||
|
__except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+--------------------------------------------------------------------------
|
||
|
// CertSrvBackupEnd -- clean up after a backup operation has been performed.
|
||
|
// This API will close outstanding binding handles, and do whatever is
|
||
|
// necessary to clean up after successful/unsuccesful backup attempts.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// [in] hbc - backup context handle of the backup session
|
||
|
//
|
||
|
// Returns:
|
||
|
// S_OK if the call executed successfully;
|
||
|
// Failure code otherwise.
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
HRESULT
|
||
|
CERTBCLI_API
|
||
|
CertSrvBackupEnd(
|
||
|
IN HCSBC hbc)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
CSBACKUPCONTEXT *pcsbc;
|
||
|
|
||
|
if (NULL == hbc)
|
||
|
{
|
||
|
hr = E_HANDLE;
|
||
|
_JumpError(hr, error, "NULL handle");
|
||
|
}
|
||
|
pcsbc = (CSBACKUPCONTEXT *) hbc;
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
hr = pcsbc->pICertAdminD->BackupEnd();
|
||
|
_LeaveIfError(hr, "BackupEnd");
|
||
|
|
||
|
ReleaseContext((CSBACKUPCONTEXT *) hbc);
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
__except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
return(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+--------------------------------------------------------------------------
|
||
|
// CertSrvBackupFree -- free any buffer allocated by certbcli.dll APIs.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// [in] pv - pointer to the buffer that is to be freed.
|
||
|
//
|
||
|
// Returns:
|
||
|
// None.
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
VOID
|
||
|
CERTBCLI_API
|
||
|
CertSrvBackupFree(
|
||
|
IN VOID *pv)
|
||
|
{
|
||
|
LocalFree(pv);
|
||
|
}
|