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.
505 lines
12 KiB
505 lines
12 KiB
#include "stdafx.hxx"
|
|
#include "vs_idl.hxx"
|
|
#include "vswriter.h"
|
|
#include "vsbackup.h"
|
|
#include <debug.h>
|
|
#include <vsswprv.h>
|
|
|
|
|
|
|
|
CComModule _Module;
|
|
|
|
static LPCWSTR s_rgwszStates[] =
|
|
{
|
|
NULL,
|
|
L"STABLE",
|
|
L"WAIT_FOR_FREEZE",
|
|
L"WAIT_FOR_THAW",
|
|
L"WAIT_FOR_COMPLETION",
|
|
L"FAILED_AT_IDENTIFY",
|
|
L"FAILED_AT_PREPARE_BACKUP",
|
|
L"FAILED_AT_PREPARE_SNAPSHOT",
|
|
L"FAILED_AT_FREEZE",
|
|
L"FAILED_AT_THAW"
|
|
};
|
|
|
|
|
|
|
|
void CheckStatus(IVssBackupComponents *pvbc, LPCWSTR wszWhen)
|
|
{
|
|
unsigned cWriters;
|
|
CComPtr<IVssAsync> pAsync;
|
|
|
|
CHECK_NOFAIL(pvbc->GatherWriterStatus(&pAsync));
|
|
CHECK_NOFAIL(pAsync->Wait());
|
|
CHECK_NOFAIL(pvbc->GetWriterStatusCount(&cWriters));
|
|
|
|
|
|
wprintf(L"status %s\n%d writers\n\n", wszWhen, cWriters);
|
|
for(unsigned iWriter = 0; iWriter < cWriters; iWriter++)
|
|
{
|
|
VSS_ID idInstance;
|
|
VSS_ID idWriter;
|
|
CComBSTR bstrWriter;
|
|
VSS_WRITER_STATE status;
|
|
HRESULT hrWriterFailure;
|
|
|
|
CHECK_SUCCESS(pvbc->GetWriterStatus
|
|
(
|
|
iWriter,
|
|
&idInstance,
|
|
&idWriter,
|
|
&bstrWriter,
|
|
&status,
|
|
&hrWriterFailure
|
|
));
|
|
|
|
wprintf
|
|
(
|
|
L"Status for writer %s: %s(0x%08lx)\n",
|
|
bstrWriter,
|
|
s_rgwszStates[status],
|
|
hrWriterFailure
|
|
);
|
|
}
|
|
|
|
pvbc->FreeWriterStatus();
|
|
}
|
|
|
|
|
|
void PrintFiledesc(IVssWMFiledesc *pFiledesc, LPCWSTR wszDescription)
|
|
{
|
|
CComBSTR bstrPath;
|
|
CComBSTR bstrFilespec;
|
|
CComBSTR bstrAlternate;
|
|
CComBSTR bstrDestination;
|
|
bool bRecursive;
|
|
|
|
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\nPath=%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);
|
|
}
|
|
|
|
HANDLE LaunchWriterProcess()
|
|
{
|
|
HANDLE hEventW = CreateEvent(NULL, TRUE, FALSE, L"TESTWRITEREVENT");
|
|
if (hEventW == NULL)
|
|
{
|
|
wprintf(L"CreateEvent failed with error %d.\n", GetLastError());
|
|
DebugBreak();
|
|
}
|
|
|
|
HANDLE hEventB = CreateEvent(NULL, TRUE, FALSE, L"TESTBACKUPEVENT");
|
|
if (hEventB == NULL)
|
|
{
|
|
wprintf(L"CreateEvent failed with error %d.\n", GetLastError());
|
|
DebugBreak();
|
|
}
|
|
|
|
WaitForSingleObject(hEventB, INFINITE);
|
|
return hEventW;
|
|
}
|
|
|
|
void DoAddToSnapshotSet
|
|
(
|
|
IN IVssBackupComponents *pvbc,
|
|
IN BSTR bstrPath,
|
|
IN LPWSTR wszVolumes
|
|
)
|
|
{
|
|
WCHAR wszVolume[100];
|
|
WCHAR *pwc = bstrPath;
|
|
WCHAR *pwcDest = wszVolume;
|
|
|
|
|
|
for(; *pwc != ':'; pwc++, pwcDest++)
|
|
*pwcDest = *pwc;
|
|
|
|
*pwcDest++ = L':';
|
|
*pwcDest++ = L'\\';
|
|
*pwcDest++ = L'\0';
|
|
pwc = wszVolumes;
|
|
while(*pwc != '\0')
|
|
{
|
|
if (wcsncmp(pwc, wszVolume, wcslen(wszVolume)) == 0)
|
|
return;
|
|
|
|
pwc = wcschr(pwc, L';');
|
|
if (pwc == NULL)
|
|
break;
|
|
}
|
|
|
|
pwc = wszVolumes + wcslen(wszVolumes);
|
|
wcscpy(pwc, wszVolume);
|
|
VSS_ID SnapshotId;
|
|
CHECK_SUCCESS(pvbc->AddToSnapshotSet
|
|
(
|
|
wszVolume,
|
|
VSS_SWPRV_ProviderId,
|
|
&SnapshotId
|
|
));
|
|
}
|
|
|
|
|
|
|
|
extern "C" __cdecl wmain(int argc, WCHAR **argv)
|
|
{
|
|
HANDLE hEvent = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
try
|
|
{
|
|
WCHAR wszVolumes[100];
|
|
CHECK_SUCCESS(CoInitializeEx(NULL, COINIT_MULTITHREADED));
|
|
hEvent = LaunchWriterProcess();
|
|
|
|
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_INCREMENTAL
|
|
));
|
|
|
|
unsigned cWriters;
|
|
CComPtr<IVssAsync> pAsync;
|
|
|
|
CHECK_NOFAIL(pvbc->GatherWriterMetadata(&pAsync));
|
|
CHECK_NOFAIL(pAsync->Wait());
|
|
CHECK_NOFAIL(pvbc->GetWriterMetadataCount(&cWriters));
|
|
|
|
VSS_ID id;
|
|
|
|
CHECK_SUCCESS(pvbc->StartSnapshotSet(&id));
|
|
|
|
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
|
|
));
|
|
|
|
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"InstanceId=%s\nWriterId=%s\nWriterName=%s\nUsageType=%d\nSourceType=%d\n",
|
|
pwszInstanceId,
|
|
pwszWriterId,
|
|
bstrWriterName,
|
|
usage,
|
|
source
|
|
);
|
|
|
|
RpcStringFree(&pwszInstanceId);
|
|
RpcStringFree(&pwszWriterId);
|
|
|
|
unsigned cIncludeFiles, cExcludeFiles, cComponents;
|
|
CHECK_SUCCESS(pMetadata->GetFileCounts
|
|
(
|
|
&cIncludeFiles,
|
|
&cExcludeFiles,
|
|
&cComponents
|
|
));
|
|
|
|
CComBSTR bstrPath;
|
|
CComBSTR bstrFilespec;
|
|
CComBSTR bstrAlternate;
|
|
CComBSTR bstrDestination;
|
|
bool bRecursive;
|
|
|
|
for(unsigned i = 0; i < cIncludeFiles; i++)
|
|
{
|
|
CComPtr<IVssWMFiledesc> pFiledesc;
|
|
CHECK_SUCCESS(pMetadata->GetIncludeFile(i, &pFiledesc));
|
|
|
|
PrintFiledesc(pFiledesc, L"Include File");
|
|
}
|
|
|
|
for(i = 0; i < cExcludeFiles; i++)
|
|
{
|
|
CComPtr<IVssWMFiledesc> pFiledesc;
|
|
CHECK_SUCCESS(pMetadata->GetExcludeFile(i, &pFiledesc));
|
|
PrintFiledesc(pFiledesc, L"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"Component %d, type=%d\nLogicalPath=%s,Name=%s\nCaption=%s\n",
|
|
i,
|
|
pInfo->type,
|
|
pInfo->bstrLogicalPath,
|
|
pInfo->bstrComponentName,
|
|
pInfo->bstrCaption
|
|
);
|
|
|
|
wprintf
|
|
(
|
|
L"RestoreMetadata=%s,NotifyOnBackupComplete=%s,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);
|
|
|
|
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);
|
|
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);
|
|
PrintFiledesc(pFiledesc, L"DatabaseLogFile");
|
|
}
|
|
}
|
|
|
|
pComponent->FreeComponentInfo(pInfo);
|
|
}
|
|
|
|
VSS_RESTOREMETHOD_ENUM method;
|
|
CComBSTR bstrUserProcedure;
|
|
CComBSTR bstrService;
|
|
VSS_WRITERRESTORE_ENUM writerRestore;
|
|
unsigned cMappings;
|
|
bool bRebootRequired;
|
|
|
|
CHECK_SUCCESS(pMetadata->GetRestoreMethod
|
|
(
|
|
&method,
|
|
&bstrService,
|
|
&bstrUserProcedure,
|
|
&writerRestore,
|
|
&bRebootRequired,
|
|
&cMappings
|
|
));
|
|
|
|
|
|
wprintf
|
|
(
|
|
L"Restore method=%d\nService=%s\nUser Procedure=%s\nwriterRestore=%d\nrebootRequired=%s\n\n",
|
|
method,
|
|
bstrService,
|
|
bstrUserProcedure,
|
|
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");
|
|
}
|
|
}
|
|
|
|
CHECK_SUCCESS(pvbc->FreeWriterMetadata());
|
|
|
|
{
|
|
CComPtr<IVssAsync> pAsync;
|
|
HRESULT hr;
|
|
INT nPercentDone;
|
|
|
|
CHECK_SUCCESS(pvbc->PrepareForBackup(&pAsync));
|
|
CHECK_SUCCESS(pAsync->Wait());
|
|
CHECK_SUCCESS(pAsync->QueryStatus(&hr, &nPercentDone));
|
|
CHECK_NOFAIL(hr);
|
|
}
|
|
|
|
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;
|
|
bool bBackupSucceeded;
|
|
|
|
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");
|
|
LONG lSnapshotsNotDeleted;
|
|
VSS_ID rgSnapshotsNotDeleted[10];
|
|
|
|
{
|
|
CComPtr<IVssAsync> pAsync;
|
|
HRESULT hr;
|
|
INT nPercentDone;
|
|
|
|
CHECK_SUCCESS(pvbc->BackupComplete(&pAsync));
|
|
CHECK_SUCCESS(pAsync->Wait());
|
|
CHECK_SUCCESS(pAsync->QueryStatus(&hr, &nPercentDone));
|
|
CHECK_NOFAIL(hr);
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
|
|
if (hEvent)
|
|
SetEvent(hEvent);
|
|
|
|
if (FAILED(hr))
|
|
wprintf(L"Failed with %08x.\n", hr);
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
|
|
|