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.
920 lines
27 KiB
920 lines
27 KiB
#include "stdafx.hxx"
|
|
#include "vs_idl.hxx"
|
|
#include "vswriter.h"
|
|
#include "vsbackup.h"
|
|
#include <debug.h>
|
|
#include <cwriter.h>
|
|
#include <lmshare.h>
|
|
#include <lmaccess.h>
|
|
#include <time.h>
|
|
|
|
BOOL AssertPrivilege( LPCWSTR privName )
|
|
{
|
|
HANDLE tokenHandle;
|
|
BOOL stat = FALSE;
|
|
|
|
if ( OpenProcessToken (GetCurrentProcess(),
|
|
TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
|
|
&tokenHandle))
|
|
{
|
|
LUID value;
|
|
|
|
if ( LookupPrivilegeValue( NULL, privName, &value ) )
|
|
{
|
|
TOKEN_PRIVILEGES newState;
|
|
DWORD error;
|
|
|
|
newState.PrivilegeCount = 1;
|
|
newState.Privileges[0].Luid = value;
|
|
newState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT|SE_PRIVILEGE_ENABLED;
|
|
|
|
/*
|
|
* We will always call GetLastError below, so clear
|
|
* any prior error values on this thread.
|
|
*/
|
|
SetLastError( ERROR_SUCCESS );
|
|
|
|
stat = AdjustTokenPrivileges (tokenHandle,
|
|
FALSE,
|
|
&newState,
|
|
(DWORD)0,
|
|
NULL,
|
|
NULL );
|
|
|
|
/*
|
|
* Supposedly, AdjustTokenPriveleges always returns TRUE
|
|
* (even when it fails). So, call GetLastError to be
|
|
* extra sure everything's cool.
|
|
*/
|
|
if ( (error = GetLastError()) != ERROR_SUCCESS )
|
|
{
|
|
stat = FALSE;
|
|
}
|
|
|
|
if ( !stat )
|
|
{
|
|
wprintf( L"AdjustTokenPrivileges for %s failed with %d",
|
|
privName,
|
|
error );
|
|
}
|
|
}
|
|
|
|
DWORD cbTokens;
|
|
GetTokenInformation (tokenHandle,
|
|
TokenPrivileges,
|
|
NULL,
|
|
0,
|
|
&cbTokens);
|
|
|
|
TOKEN_PRIVILEGES *pTokens = (TOKEN_PRIVILEGES *) new BYTE[cbTokens];
|
|
GetTokenInformation (tokenHandle,
|
|
TokenPrivileges,
|
|
pTokens,
|
|
cbTokens,
|
|
&cbTokens);
|
|
|
|
delete pTokens;
|
|
CloseHandle( tokenHandle );
|
|
}
|
|
|
|
|
|
return stat;
|
|
}
|
|
|
|
|
|
LPCWSTR GetStringFromUsageType (VSS_USAGE_TYPE eUsageType)
|
|
{
|
|
LPCWSTR pwszRetString = L"UNDEFINED";
|
|
|
|
switch (eUsageType)
|
|
{
|
|
case VSS_UT_BOOTABLESYSTEMSTATE: pwszRetString = L"BootableSystemState"; break;
|
|
case VSS_UT_SYSTEMSERVICE: pwszRetString = L"SystemService"; break;
|
|
case VSS_UT_USERDATA: pwszRetString = L"UserData"; break;
|
|
case VSS_UT_OTHER: pwszRetString = L"Other"; break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
|
|
return (pwszRetString);
|
|
}
|
|
|
|
|
|
LPCWSTR GetStringFromSourceType (VSS_SOURCE_TYPE eSourceType)
|
|
{
|
|
LPCWSTR pwszRetString = L"UNDEFINED";
|
|
|
|
switch (eSourceType)
|
|
{
|
|
case VSS_ST_TRANSACTEDDB: pwszRetString = L"TransactionDb"; break;
|
|
case VSS_ST_NONTRANSACTEDDB: pwszRetString = L"NonTransactionDb"; break;
|
|
case VSS_ST_OTHER: pwszRetString = L"Other"; break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
|
|
return (pwszRetString);
|
|
}
|
|
|
|
|
|
LPCWSTR GetStringFromRestoreMethod (VSS_RESTOREMETHOD_ENUM eRestoreMethod)
|
|
{
|
|
LPCWSTR pwszRetString = L"UNDEFINED";
|
|
|
|
switch (eRestoreMethod)
|
|
{
|
|
case VSS_RME_RESTORE_IF_NOT_THERE: pwszRetString = L"RestoreIfNotThere"; break;
|
|
case VSS_RME_RESTORE_IF_CAN_REPLACE: pwszRetString = L"RestoreIfCanReplace"; break;
|
|
case VSS_RME_STOP_RESTORE_START: pwszRetString = L"StopRestoreStart"; break;
|
|
case VSS_RME_RESTORE_TO_ALTERNATE_LOCATION: pwszRetString = L"RestoreToAlternateLocation"; break;
|
|
case VSS_RME_RESTORE_AT_REBOOT: pwszRetString = L"RestoreAtReboot"; break;
|
|
case VSS_RME_CUSTOM: pwszRetString = L"Custom"; break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
|
|
return (pwszRetString);
|
|
}
|
|
|
|
|
|
LPCWSTR GetStringFromWriterRestoreMethod (VSS_WRITERRESTORE_ENUM eWriterRestoreMethod)
|
|
{
|
|
LPCWSTR pwszRetString = L"UNDEFINED";
|
|
|
|
switch (eWriterRestoreMethod)
|
|
{
|
|
case VSS_WRE_NEVER: pwszRetString = L"RestoreNever"; break;
|
|
case VSS_WRE_IF_REPLACE_FAILS: pwszRetString = L"RestoreIfReplaceFailsI"; break;
|
|
case VSS_WRE_ALWAYS: pwszRetString = L"RestoreAlways"; break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
|
|
return (pwszRetString);
|
|
}
|
|
|
|
|
|
LPCWSTR GetStringFromComponentType (VSS_COMPONENT_TYPE eComponentType)
|
|
{
|
|
LPCWSTR pwszRetString = L"UNDEFINED";
|
|
|
|
switch (eComponentType)
|
|
{
|
|
case VSS_CT_DATABASE: pwszRetString = L"Database"; break;
|
|
case VSS_CT_FILEGROUP: pwszRetString = L"FileGroup"; break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
|
|
return (pwszRetString);
|
|
}
|
|
|
|
|
|
|
|
|
|
void PrintFiledesc(IVssWMFiledesc *pFiledesc, LPCWSTR wszDescription)
|
|
{
|
|
CComBSTR bstrPath;
|
|
CComBSTR bstrFilespec;
|
|
CComBSTR bstrAlternate;
|
|
CComBSTR bstrDestination;
|
|
bool bRecursive;
|
|
HRESULT hr;
|
|
|
|
CHECK_SUCCESS(pFiledesc->GetPath(&bstrPath));
|
|
CHECK_SUCCESS(pFiledesc->GetFilespec(&bstrFilespec));
|
|
CHECK_NOFAIL(pFiledesc->GetRecursive(&bRecursive));
|
|
CHECK_NOFAIL(pFiledesc->GetAlternateLocation(&bstrAlternate));
|
|
CHECK_NOFAIL(pFiledesc->GetAlternateLocation(&bstrDestination));
|
|
|
|
wprintf (L"%s\n Path = %s, Filespec = %s, Recursive = %s\n",
|
|
wszDescription,
|
|
bstrPath,
|
|
bstrFilespec,
|
|
bRecursive ? L"yes" : L"no");
|
|
|
|
if (bstrAlternate && wcslen(bstrAlternate) > 0)
|
|
wprintf(L" Alternate Location = %s\n", bstrAlternate);
|
|
|
|
if (bstrDestination && wcslen(bstrDestination) > 0)
|
|
wprintf(L" Destination Location = %s\n", bstrDestination);
|
|
}
|
|
|
|
|
|
/*
|
|
void AddShares(IVssSnapshot **rgpSnapshot, UINT cSnapshot)
|
|
{
|
|
VSS_PWSZ wszDeviceName = NULL;
|
|
|
|
try
|
|
{
|
|
for(UINT iSnapshot = 0; iSnapshot < cSnapshot; iSnapshot++)
|
|
{
|
|
SHARE_INFO_502 info;
|
|
CHECK_SUCCESS(rgpSnapshot[iSnapshot]->GetDevice(&wszDeviceName));
|
|
WCHAR *wszPath = new WCHAR[wcslen(wszDeviceName) + 2];
|
|
if (wszPath != NULL)
|
|
{
|
|
wcscpy(wszPath, wszDeviceName);
|
|
wcscat(wszPath, L"\\");
|
|
memset(&info, 0, sizeof(info));
|
|
WCHAR wszName[20];
|
|
swprintf(wszName, L"Snapshot%d", iSnapshot);
|
|
|
|
info.shi502_netname = wszName;
|
|
info.shi502_type = STYPE_DISKTREE;
|
|
info.shi502_permissions = ACCESS_READ;
|
|
info.shi502_max_uses = 10;
|
|
info.shi502_path = wszDeviceName;
|
|
|
|
NET_API_STATUS status;
|
|
DWORD parm_err;
|
|
|
|
status = NetShareAdd(NULL, 502, (LPBYTE) &info, &parm_err);
|
|
}
|
|
|
|
CoTaskMemFree(wszDeviceName);
|
|
wszDeviceName = NULL;
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
}
|
|
|
|
if (wszDeviceName)
|
|
CoTaskMemFree(wszDeviceName);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void DoAddToSnapshotSet
|
|
(
|
|
IN IVssBackupComponents *pvbc,
|
|
IN BSTR bstrPath,
|
|
IN LPWSTR wszVolumes,
|
|
OUT VSS_ID * rgpSnapshotId,
|
|
UINT *pcSnapshot
|
|
)
|
|
{
|
|
PWCHAR pwszPath = NULL;
|
|
PWCHAR pwszMountPointName = NULL;
|
|
WCHAR wszVolumeName [50];
|
|
ULONG ulPathLength;
|
|
ULONG ulMountpointBufferLength;
|
|
HRESULT hr;
|
|
|
|
|
|
ulPathLength = ExpandEnvironmentStringsW (bstrPath, NULL, 0);
|
|
|
|
pwszPath = (PWCHAR) malloc (ulPathLength * sizeof (WCHAR));
|
|
|
|
ulPathLength = ExpandEnvironmentStringsW (bstrPath, pwszPath, ulPathLength);
|
|
|
|
|
|
ulMountpointBufferLength = GetFullPathName (pwszPath, 0, NULL, NULL);
|
|
|
|
pwszMountPointName = (PWCHAR) malloc (ulMountpointBufferLength * sizeof (WCHAR));
|
|
|
|
bool fSuccess = false;
|
|
if (wcslen(pwszPath) >= 3 && pwszPath[1] == L':' && pwszPath[2] == L'\\')
|
|
{
|
|
wcsncpy(pwszMountPointName, pwszPath, 3);
|
|
pwszMountPointName[3] = L'\0';
|
|
fSuccess = true;
|
|
}
|
|
else
|
|
{
|
|
if (GetVolumePathNameW (pwszPath, pwszMountPointName, ulMountpointBufferLength))
|
|
fSuccess = true;
|
|
else
|
|
printf("GetVolumeMountPointW failed with error %d\npath=%s\n", GetLastError(), pwszPath);
|
|
}
|
|
|
|
if (fSuccess)
|
|
{
|
|
if (!GetVolumeNameForVolumeMountPointW (pwszMountPointName, wszVolumeName, sizeof (wszVolumeName) / sizeof (WCHAR)))
|
|
printf("GetVolumeNameForVolumeMountPointW failed with error %d", GetLastError());
|
|
else
|
|
{
|
|
if (NULL == wcsstr (wszVolumes, wszVolumeName))
|
|
{
|
|
if (L'\0' != wszVolumes [0])
|
|
wcscat (wszVolumes, L";");
|
|
|
|
wcscat (wszVolumes, wszVolumeName);
|
|
|
|
CHECK_SUCCESS
|
|
(
|
|
pvbc->AddToSnapshotSet
|
|
(
|
|
wszVolumeName,
|
|
GUID_NULL,
|
|
&rgpSnapshotId[*pcSnapshot]
|
|
)
|
|
);
|
|
|
|
*pcSnapshot += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (NULL != pwszPath) free (pwszPath);
|
|
if (NULL != pwszMountPointName) free (pwszMountPointName);
|
|
}
|
|
|
|
static LPCWSTR s_rgwszStates[] =
|
|
{
|
|
NULL,
|
|
L"STABLE",
|
|
L"WAIT_FOR_FREEZE",
|
|
L"WAIT_FOR_THAW",
|
|
L"WAIT_FOR_POST_SNAPSHOT",
|
|
L"WAIT_FOR_BACKUP_COMPLETE",
|
|
L"FAILED_AT_IDENTIFY",
|
|
L"FAILED_AT_PREPARE_BACKUP",
|
|
L"FAILED_AT_PREPARE_SNAPSHOT",
|
|
L"FAILED_AT_FREEZE",
|
|
L"FAILED_AT_THAW",
|
|
L"FAILED_AT_BACKUP_COMPLETE",
|
|
L"FAILED_AT_PRE_RESTORE",
|
|
L"FAILED_AT_POST_RESTORE"
|
|
};
|
|
|
|
void CheckStatus(IVssBackupComponents *pvbc, LPCWSTR wszWhen)
|
|
{
|
|
unsigned cWriters;
|
|
CComPtr<IVssAsync> pAsync;
|
|
HRESULT hr;
|
|
HRESULT hrResult;
|
|
|
|
|
|
CHECK_NOFAIL(pvbc->GatherWriterStatus(&pAsync));
|
|
CHECK_NOFAIL(pAsync->Wait());
|
|
CHECK_SUCCESS(pAsync->QueryStatus(&hrResult, NULL));
|
|
CHECK_NOFAIL(hrResult);
|
|
|
|
CHECK_NOFAIL(pvbc->GetWriterStatusCount(&cWriters));
|
|
|
|
|
|
wprintf(L"\n\nstatus %s (%d writers)\n\n", wszWhen, cWriters);
|
|
|
|
for(unsigned iWriter = 0; iWriter < cWriters; iWriter++)
|
|
{
|
|
VSS_ID idInstance;
|
|
VSS_ID idWriter;
|
|
VSS_WRITER_STATE status;
|
|
CComBSTR bstrWriter;
|
|
HRESULT hrWriterFailure;
|
|
|
|
CHECK_SUCCESS(pvbc->GetWriterStatus (iWriter,
|
|
&idInstance,
|
|
&idWriter,
|
|
&bstrWriter,
|
|
&status,
|
|
&hrWriterFailure));
|
|
|
|
wprintf (L"Status for writer %s: %s(0x%08lx%s%s)\n",
|
|
bstrWriter,
|
|
s_rgwszStates[status],
|
|
hrWriterFailure,
|
|
SUCCEEDED (hrWriterFailure) ? L"" : L" - ",
|
|
GetStringFromFailureType (hrWriterFailure));
|
|
}
|
|
|
|
pvbc->FreeWriterStatus();
|
|
}
|
|
|
|
// wait a maximum number of seconds before cancelling the operation
|
|
void LoopWait
|
|
(
|
|
IVssAsync *pAsync,
|
|
LONG seconds,
|
|
LPCWSTR wszOperation
|
|
)
|
|
{
|
|
clock_t start = clock();
|
|
HRESULT hr, hrStatus;
|
|
while(TRUE)
|
|
{
|
|
Sleep(1000);
|
|
CHECK_SUCCESS(pAsync->QueryStatus(&hrStatus, NULL));
|
|
if (hrStatus != VSS_S_ASYNC_PENDING)
|
|
break;
|
|
|
|
if (((clock() - start)/CLOCKS_PER_SEC) >= seconds)
|
|
break;
|
|
}
|
|
|
|
if (hrStatus == VSS_S_ASYNC_PENDING)
|
|
{
|
|
CHECK_NOFAIL(pAsync->Cancel());
|
|
wprintf(L"Called cancelled for %s.\n", wszOperation);
|
|
}
|
|
|
|
CHECK_SUCCESS(pAsync->QueryStatus(&hrStatus, NULL));
|
|
CHECK_NOFAIL(hrStatus);
|
|
}
|
|
|
|
|
|
extern "C" __cdecl wmain(int argc, WCHAR **argv)
|
|
{
|
|
WCHAR wszVolumes[2048];
|
|
wszVolumes[0] = L'\0';
|
|
|
|
UINT cSnapshot = 0;
|
|
VSS_ID rgpSnapshotId[64];
|
|
|
|
CTestVssWriter *pInstance = NULL;
|
|
bool bCreated = false;
|
|
bool bSubscribed = false;
|
|
HRESULT hr = S_OK;
|
|
bool bCoInitializeSucceeded = false;
|
|
|
|
|
|
try
|
|
{
|
|
HRESULT hr;
|
|
CComBSTR bstrXML;
|
|
CComBSTR bstrXMLOut;
|
|
LONG lWait = 0;
|
|
|
|
if (argc == 2 &&
|
|
wcslen(argv[1]) == 3 &&
|
|
argv[1][0] == L'-' &&
|
|
argv[1][1] == L'w' &&
|
|
(argv[1][2] >= L'0' && argv[1][2] <= L'9'||
|
|
argv[1][2] >= L'a' && argv[1][2] <= L'f'))
|
|
{
|
|
if (argv[1][2] >= L'0' && argv[1][2] <= L'9')
|
|
lWait = argv[1][2] - L'0';
|
|
else
|
|
lWait = argv[1][2] - L'a' + 10;
|
|
|
|
wprintf(L"wait parameter=%d.\n", lWait);
|
|
}
|
|
|
|
|
|
|
|
CHECK_SUCCESS(CoInitializeEx(NULL, COINIT_MULTITHREADED));
|
|
|
|
CComPtr<IGlobalOptions> ptrIGLB;
|
|
CHECK_SUCCESS( ptrIGLB.CoCreateInstance(CLSID_GlobalOptions) );
|
|
CHECK_SUCCESS( ptrIGLB->Set(COMGLB_EXCEPTION_HANDLING, COMGLB_EXCEPTION_DONOT_HANDLE));
|
|
|
|
// Initialize COM security
|
|
CHECK_SUCCESS
|
|
(
|
|
CoInitializeSecurity
|
|
(
|
|
NULL, // IN PSECURITY_DESCRIPTOR pSecDesc,
|
|
-1, // IN LONG cAuthSvc,
|
|
NULL, // IN SOLE_AUTHENTICATION_SERVICE *asAuthSvc,
|
|
NULL, // IN void *pReserved1,
|
|
RPC_C_AUTHN_LEVEL_CONNECT, // IN DWORD dwAuthnLevel,
|
|
RPC_C_IMP_LEVEL_IMPERSONATE, // IN DWORD dwImpLevel,
|
|
NULL, // IN void *pAuthList,
|
|
EOAC_NONE, // IN DWORD dwCapabilities,
|
|
NULL // IN void *pReserved3
|
|
)
|
|
);
|
|
|
|
bCoInitializeSucceeded = true;
|
|
|
|
if ( !AssertPrivilege( SE_BACKUP_NAME ) )
|
|
{
|
|
wprintf( L"AssertPrivilege returned error, rc:%d\n", GetLastError() );
|
|
return 2;
|
|
}
|
|
|
|
pInstance = new CTestVssWriter(lWait);
|
|
if (pInstance == NULL)
|
|
{
|
|
wprintf(L"allocation failure\n");
|
|
DebugBreak();
|
|
}
|
|
|
|
bCreated = true;
|
|
pInstance->Initialize();
|
|
CHECK_SUCCESS(pInstance->Subscribe());
|
|
bSubscribed = true;
|
|
|
|
CComBSTR strSnapshotSetId = "12345678-1234-1234-1234-1234567890ab";
|
|
|
|
CComPtr<IVssBackupComponents> pvbc;
|
|
|
|
CHECK_SUCCESS(CreateVssBackupComponents(&pvbc));
|
|
|
|
|
|
CHECK_SUCCESS(pvbc->InitializeForBackup());
|
|
CHECK_SUCCESS(pvbc->SetBackupState (true,
|
|
false,
|
|
VSS_BT_FULL));
|
|
|
|
unsigned cWriters;
|
|
CComPtr<IVssAsync> pAsync;
|
|
CHECK_NOFAIL(pvbc->GatherWriterMetadata(&pAsync));
|
|
|
|
LoopWait(pAsync, 15, L"GatherWriterMetadata");
|
|
|
|
CHECK_NOFAIL(pvbc->GetWriterMetadataCount(&cWriters));
|
|
|
|
VSS_ID id;
|
|
|
|
while(TRUE)
|
|
{
|
|
hr = pvbc->StartSnapshotSet(&id);
|
|
if (hr == S_OK)
|
|
break;
|
|
|
|
if (hr == VSS_E_SNAPSHOT_SET_IN_PROGRESS)
|
|
Sleep(1000);
|
|
else
|
|
CHECK_SUCCESS(hr);
|
|
}
|
|
|
|
for(unsigned iWriter = 0; iWriter < cWriters; iWriter++)
|
|
{
|
|
CComPtr<IVssExamineWriterMetadata> pMetadata;
|
|
VSS_ID idInstance;
|
|
|
|
CHECK_SUCCESS(pvbc->GetWriterMetadata(iWriter, &idInstance, &pMetadata));
|
|
VSS_ID idInstanceT;
|
|
VSS_ID idWriter;
|
|
CComBSTR bstrWriterName;
|
|
VSS_USAGE_TYPE usage;
|
|
VSS_SOURCE_TYPE source;
|
|
|
|
CHECK_SUCCESS(pMetadata->GetIdentity (&idInstanceT,
|
|
&idWriter,
|
|
&bstrWriterName,
|
|
&usage,
|
|
&source));
|
|
|
|
wprintf (L"\n\n");
|
|
|
|
if (memcmp(&idInstance, &idInstanceT, sizeof(VSS_ID)) != 0)
|
|
{
|
|
wprintf(L"Instance id mismatch\n");
|
|
DebugBreak();
|
|
}
|
|
|
|
WCHAR *pwszInstanceId;
|
|
WCHAR *pwszWriterId;
|
|
UuidToString(&idInstance, &pwszInstanceId);
|
|
UuidToString(&idWriter, &pwszWriterId);
|
|
wprintf (L"WriterName = %s\n\n"
|
|
L" WriterId = %s\n"
|
|
L" InstanceId = %s\n"
|
|
L" UsageType = %d (%s)\n"
|
|
L" SourceType = %d (%s)\n",
|
|
bstrWriterName,
|
|
pwszWriterId,
|
|
pwszInstanceId,
|
|
usage,
|
|
GetStringFromUsageType (usage),
|
|
source,
|
|
GetStringFromSourceType (source));
|
|
|
|
RpcStringFree(&pwszInstanceId);
|
|
RpcStringFree(&pwszWriterId);
|
|
|
|
unsigned cIncludeFiles, cExcludeFiles, cComponents;
|
|
CHECK_SUCCESS(pMetadata->GetFileCounts (&cIncludeFiles,
|
|
&cExcludeFiles,
|
|
&cComponents));
|
|
|
|
CComBSTR bstrPath;
|
|
CComBSTR bstrFilespec;
|
|
CComBSTR bstrAlternate;
|
|
CComBSTR bstrDestination;
|
|
|
|
for(unsigned i = 0; i < cIncludeFiles; i++)
|
|
{
|
|
CComPtr<IVssWMFiledesc> pFiledesc;
|
|
CHECK_SUCCESS(pMetadata->GetIncludeFile(i, &pFiledesc));
|
|
|
|
PrintFiledesc(pFiledesc, L"\n Include File");
|
|
}
|
|
|
|
for(i = 0; i < cExcludeFiles; i++)
|
|
{
|
|
CComPtr<IVssWMFiledesc> pFiledesc;
|
|
CHECK_SUCCESS(pMetadata->GetExcludeFile(i, &pFiledesc));
|
|
PrintFiledesc(pFiledesc, L"\n Exclude File");
|
|
}
|
|
|
|
for(unsigned iComponent = 0; iComponent < cComponents; iComponent++)
|
|
{
|
|
CComPtr<IVssWMComponent> pComponent;
|
|
PVSSCOMPONENTINFO pInfo;
|
|
CHECK_SUCCESS(pMetadata->GetComponent(iComponent, &pComponent));
|
|
CHECK_SUCCESS(pComponent->GetComponentInfo(&pInfo));
|
|
wprintf (L"\n"
|
|
L" Component %d, type = %d (%s)\n"
|
|
L" LogicalPath = %s\n"
|
|
L" Name = %s\n"
|
|
L" Caption = %s\n"
|
|
L" Icon size = %u\n",
|
|
iComponent,
|
|
pInfo->type,
|
|
GetStringFromComponentType (pInfo->type),
|
|
pInfo->bstrLogicalPath,
|
|
pInfo->bstrComponentName,
|
|
pInfo->bstrCaption,
|
|
pInfo->cbIcon );
|
|
|
|
wprintf (L" RestoreMetadata = %s\n"
|
|
L" NotifyOnBackupComplete = %s\n"
|
|
L" Selectable = %s\n",
|
|
pInfo->bRestoreMetadata ? L"yes" : L"no",
|
|
pInfo->bNotifyOnBackupComplete ? L"yes" : L"no",
|
|
pInfo->bSelectable ? L"yes" : L"no");
|
|
|
|
|
|
|
|
CHECK_SUCCESS(pvbc->AddComponent (idInstance,
|
|
idWriter,
|
|
pInfo->type,
|
|
pInfo->bstrLogicalPath,
|
|
pInfo->bstrComponentName));
|
|
|
|
|
|
if (pInfo->cFileCount > 0)
|
|
{
|
|
for(i = 0; i < pInfo->cFileCount; i++)
|
|
{
|
|
CComPtr<IVssWMFiledesc> pFiledesc;
|
|
CHECK_SUCCESS(pComponent->GetFile(i, &pFiledesc));
|
|
|
|
CComBSTR bstrPath;
|
|
CHECK_SUCCESS(pFiledesc->GetPath(&bstrPath));
|
|
DoAddToSnapshotSet(pvbc, bstrPath, wszVolumes, rgpSnapshotId, &cSnapshot);
|
|
|
|
PrintFiledesc(pFiledesc, L" FileGroupFile");
|
|
}
|
|
}
|
|
|
|
if (pInfo->cDatabases > 0)
|
|
{
|
|
for(i = 0; i < pInfo->cDatabases; i++)
|
|
{
|
|
CComPtr<IVssWMFiledesc> pFiledesc;
|
|
CHECK_SUCCESS(pComponent->GetDatabaseFile(i, &pFiledesc));
|
|
|
|
CComBSTR bstrPath;
|
|
CHECK_SUCCESS(pFiledesc->GetPath(&bstrPath));
|
|
DoAddToSnapshotSet(pvbc, bstrPath, wszVolumes, rgpSnapshotId, &cSnapshot);
|
|
PrintFiledesc(pFiledesc, L" DatabaseFile");
|
|
}
|
|
}
|
|
|
|
if (pInfo->cLogFiles > 0)
|
|
{
|
|
for(i = 0; i < pInfo->cLogFiles; i++)
|
|
{
|
|
CComPtr<IVssWMFiledesc> pFiledesc;
|
|
CHECK_SUCCESS(pComponent->GetDatabaseLogFile(i, &pFiledesc));
|
|
|
|
CComBSTR bstrPath;
|
|
CHECK_SUCCESS(pFiledesc->GetPath(&bstrPath));
|
|
DoAddToSnapshotSet(pvbc, bstrPath, wszVolumes, rgpSnapshotId, &cSnapshot);
|
|
PrintFiledesc(pFiledesc, L" DatabaseLogFile");
|
|
}
|
|
}
|
|
|
|
pComponent->FreeComponentInfo(pInfo);
|
|
}
|
|
|
|
VSS_RESTOREMETHOD_ENUM method;
|
|
CComBSTR bstrUserProcedure;
|
|
CComBSTR bstrService;
|
|
VSS_WRITERRESTORE_ENUM writerRestore;
|
|
unsigned cMappings;
|
|
bool bRebootRequired;
|
|
|
|
CHECK_NOFAIL(pMetadata->GetRestoreMethod (&method,
|
|
&bstrService,
|
|
&bstrUserProcedure,
|
|
&writerRestore,
|
|
&bRebootRequired,
|
|
&cMappings));
|
|
|
|
|
|
wprintf (L"\n"
|
|
L" Restore method = %d (%s)\n"
|
|
L" Service = %s\n"
|
|
L" User Procedure = %s\n"
|
|
L" WriterRestore = %d (%s)\n"
|
|
L" RebootRequired = %s\n",
|
|
method,
|
|
GetStringFromRestoreMethod (method),
|
|
bstrService,
|
|
bstrUserProcedure,
|
|
writerRestore,
|
|
GetStringFromWriterRestoreMethod (writerRestore),
|
|
bRebootRequired ? L"yes" : L"no");
|
|
|
|
for(i = 0; i < cMappings; i++)
|
|
{
|
|
CComPtr<IVssWMFiledesc> pFiledesc;
|
|
|
|
CHECK_SUCCESS(pMetadata->GetAlternateLocationMapping(i, &pFiledesc));
|
|
|
|
PrintFiledesc(pFiledesc, L"AlternateMapping");
|
|
}
|
|
|
|
CComBSTR bstrMetadata;
|
|
CHECK_SUCCESS(pMetadata->SaveAsXML(&bstrMetadata));
|
|
CComPtr<IVssExamineWriterMetadata> pMetadataNew;
|
|
CHECK_SUCCESS(CreateVssExamineWriterMetadata(bstrMetadata, &pMetadataNew));
|
|
CHECK_SUCCESS(pMetadataNew->GetIdentity (&idInstanceT,
|
|
&idWriter,
|
|
&bstrWriterName,
|
|
&usage,
|
|
&source));
|
|
|
|
wprintf (L"\n\n");
|
|
|
|
if (memcmp(&idInstance, &idInstanceT, sizeof(VSS_ID)) != 0)
|
|
{
|
|
wprintf(L"Instance id mismatch\n");
|
|
DebugBreak();
|
|
}
|
|
|
|
UuidToString(&idInstance, &pwszInstanceId);
|
|
UuidToString(&idWriter, &pwszWriterId);
|
|
wprintf (L"WriterName = %s\n\n"
|
|
L" WriterId = %s\n"
|
|
L" InstanceId = %s\n"
|
|
L" UsageType = %d (%s)\n"
|
|
L" SourceType = %d (%s)\n",
|
|
bstrWriterName,
|
|
pwszWriterId,
|
|
pwszInstanceId,
|
|
usage,
|
|
GetStringFromUsageType (usage),
|
|
source,
|
|
GetStringFromSourceType (source));
|
|
|
|
RpcStringFree(&pwszInstanceId);
|
|
RpcStringFree(&pwszWriterId);
|
|
}
|
|
|
|
|
|
CHECK_SUCCESS(pvbc->FreeWriterMetadata());
|
|
|
|
{
|
|
CComPtr<IVssAsync> pAsync;
|
|
HRESULT hr;
|
|
|
|
CHECK_SUCCESS(pvbc->PrepareForBackup(&pAsync));
|
|
LoopWait(pAsync, 5, L"PrepareForBackup");
|
|
}
|
|
|
|
|
|
CheckStatus(pvbc, L"After Prepare Backup");
|
|
|
|
unsigned cWriterComponents;
|
|
CHECK_SUCCESS(pvbc->GetWriterComponentsCount(&cWriterComponents));
|
|
|
|
for(iWriter = 0; iWriter < cWriterComponents; iWriter++)
|
|
{
|
|
CComPtr<IVssWriterComponentsExt> pWriter;
|
|
CHECK_SUCCESS(pvbc->GetWriterComponents(iWriter, &pWriter));
|
|
|
|
unsigned cComponents;
|
|
CHECK_SUCCESS(pWriter->GetComponentCount(&cComponents));
|
|
VSS_ID idWriter, idInstance;
|
|
CHECK_SUCCESS(pWriter->GetWriterInfo(&idInstance, &idWriter));
|
|
for(unsigned iComponent = 0; iComponent < cComponents; iComponent++)
|
|
{
|
|
CComPtr<IVssComponent> pComponent;
|
|
CHECK_SUCCESS(pWriter->GetComponent(iComponent, &pComponent));
|
|
|
|
VSS_COMPONENT_TYPE ct;
|
|
CComBSTR bstrLogicalPath;
|
|
CComBSTR bstrComponentName;
|
|
|
|
CHECK_NOFAIL(pComponent->GetLogicalPath(&bstrLogicalPath));
|
|
CHECK_SUCCESS(pComponent->GetComponentType(&ct));
|
|
CHECK_SUCCESS(pComponent->GetComponentName(&bstrComponentName));
|
|
CHECK_SUCCESS(pvbc->SetBackupSucceeded (idInstance,
|
|
idWriter,
|
|
ct,
|
|
bstrLogicalPath,
|
|
bstrComponentName,
|
|
true));
|
|
}
|
|
}
|
|
|
|
|
|
{
|
|
CComPtr<IVssAsync> pAsync;
|
|
INT nPercentDone;
|
|
CHECK_SUCCESS(pvbc->DoSnapshotSet (&pAsync));
|
|
|
|
|
|
CHECK_SUCCESS(pAsync->Wait());
|
|
CHECK_SUCCESS(pAsync->QueryStatus(&hr, &nPercentDone));
|
|
}
|
|
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
wprintf(L"Creating the snapshot failed. hr = 0x%08lx\n", hr);
|
|
CheckStatus(pvbc, L"After Do Snapshot");
|
|
}
|
|
else
|
|
{
|
|
CheckStatus(pvbc, L"After Do Snapshot");
|
|
CComBSTR bstrXML;
|
|
CComPtr<IVssBackupComponents> pvbcRestore;
|
|
|
|
CHECK_SUCCESS(pvbc->SaveAsXML(&bstrXML));
|
|
CHECK_SUCCESS(CreateVssBackupComponents(&pvbcRestore));
|
|
CHECK_SUCCESS(pvbcRestore->InitializeForRestore(bstrXML));
|
|
wprintf(L"InitializeForRestore succeeded.\n");
|
|
|
|
LONG lSnapshotsNotDeleted;
|
|
VSS_ID rgSnapshotsNotDeleted[10];
|
|
{
|
|
CComPtr<IVssAsync> pAsync;
|
|
HRESULT hr;
|
|
|
|
CHECK_SUCCESS(pvbc->BackupComplete(&pAsync));
|
|
LoopWait(pAsync, 5, L"BackupComplete");
|
|
}
|
|
|
|
CheckStatus(pvbc, L"After Backup Complete");
|
|
hr = pvbc->DeleteSnapshots (id,
|
|
VSS_OBJECT_SNAPSHOT_SET,
|
|
false,
|
|
&lSnapshotsNotDeleted,
|
|
rgSnapshotsNotDeleted);
|
|
|
|
if (FAILED(hr))
|
|
wprintf(L"Deletion of Snapshots failed. hr = 0x%08lx\n", hr);
|
|
{
|
|
CComPtr<IVssAsync> pAsync;
|
|
HRESULT hr;
|
|
|
|
pvbcRestore->GatherWriterMetadata(&pAsync);
|
|
CHECK_SUCCESS(pAsync->Wait());
|
|
CHECK_SUCCESS(pAsync->QueryStatus(&hr, NULL));
|
|
|
|
CHECK_NOFAIL(hr);
|
|
|
|
CHECK_SUCCESS(pvbcRestore->GetWriterMetadataCount(&cWriters));
|
|
for(iWriter = 0; iWriter < cWriters; iWriter++)
|
|
{
|
|
CComPtr<IVssExamineWriterMetadata> pMetadata;
|
|
VSS_ID idInstance;
|
|
CHECK_SUCCESS(pvbcRestore->GetWriterMetadata(iWriter, &idInstance, &pMetadata));
|
|
}
|
|
|
|
pAsync = NULL;
|
|
|
|
pvbcRestore->PostRestore(&pAsync);
|
|
LoopWait(pAsync, 5, L"PostRetore");
|
|
CHECK_NOFAIL(hr);
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
BS_ASSERT(FALSE);
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
|
|
if (bSubscribed)
|
|
pInstance->Unsubscribe();
|
|
|
|
if (bCreated)
|
|
delete pInstance;
|
|
|
|
if (FAILED(hr))
|
|
wprintf(L"Failed with %08x.\n", hr);
|
|
|
|
if (bCoInitializeSucceeded)
|
|
CoUninitialize();
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
|
|
|