// cl /DIS2257 /Od /MT vssenum.cpp /link ole32.lib oleaut32.lib #define WIN32_LEAN_AND_MEAN #include #include #include #pragma region VSSBits enum VSS_OBJECT_TYPE { VSS_OBJECT_UNKNOWN, VSS_OBJECT_NONE, VSS_OBJECT_SNAPSHOT_SET, VSS_OBJECT_SNAPSHOT, VSS_OBJECT_VOLUME, VSS_OBJECT_PROVIDER, VSS_OBJECT_TYPE_COUNT }; struct VSS_SNAPSHOT_SET_PROP { GUID m_SnapshotSetId; int m_lSnapshotsCount; }; struct VSS_VOLUME_PROP { GUID m_VolumeId; int m_lType; int m_bHasSnasphots; LPWSTR m_pwszVolumeName; LPWSTR m_pwszVolumeDeviceObject; GUID m_ProviderId; }; enum VSS_PROVIDER_TYPE { VSS_PROV_UNKNOWN, VSS_PROV_SYSTEM, VSS_PROV_SOFTWARE, VSS_PROV_HARDWARE }; struct VSS_PROVIDER_PROP { GUID m_ProviderId; LPWSTR m_pwszProviderName; #if defined(IS2250) || defined(IS2257) VSS_PROVIDER_TYPE m_eProviderType; #endif LPWSTR m_pwszProviderVersion; GUID m_ProviderVersionId; GUID m_ClassId; }; enum VSS_SNAPSHOT_STATE { VSS_SS_UNKNOWN, VSS_SS_PREPARING, VSS_SS_PROCESSING_PREPARE, VSS_SS_PREPARED, VSS_SS_PROCESSING_PRECOMMIT, VSS_SS_PRECOMMITED, VSS_SS_PROCESSING_COMMIT, VSS_SS_COMMITED, VSS_SS_PROCESSING_POSTCOMMIT, VSS_SS_CREATED, VSS_SS_ABORTED, VSS_SS_DELETED, VSS_SS_SUSPENDED, VSS_SS_RESYNC, VSS_SS_COUNT }; struct VSS_SNAPSHOT_PROP { GUID m_SnapshotId; GUID m_SnapshotSetId; LPWSTR m_pwszSnapshotVolumeName; LPWSTR m_pwszSnapshotDeviceObject; GUID m_OriginalVolumeId; LPWSTR m_pwszOriginalVolumeName; GUID m_ProviderId; int m_lSnapshotAttributes; LPWSTR m_pwszDetails; int m_lCommitFlags; __int64 m_tsCreationTimestamp; VSS_SNAPSHOT_STATE m_eStatus; __int64 m_llIncarnationNumber; int m_lDataLength; BYTE* m_pbOpaqueData; }; union VSS_OBJECT_PROP_DATA { VSS_SNAPSHOT_SET_PROP Set; VSS_SNAPSHOT_PROP Snap; VSS_VOLUME_PROP Vol; VSS_PROVIDER_PROP Prov; }; struct VSS_OBJECT_PROP { VSS_OBJECT_TYPE Type; VSS_OBJECT_PROP_DATA Obj; }; MIDL_INTERFACE("AE1C7110-2F60-11D3-8A39-00C04F72D8E3") IVssEnumObject : IUnknown { virtual HRESULT __stdcall Next(UINT celt, VSS_OBJECT_PROP* rgelt, UINT* pceltFetched) = 0; virtual HRESULT __stdcall Skip(UINT celt) = 0; virtual HRESULT __stdcall Reset() = 0; virtual HRESULT __stdcall Clone(IVssEnumObject** ppenum) = 0; }; MIDL_INTERFACE("77ED5996-2F63-11D3-8A39-00C04F72D8E3") IVssAdmin : public IUnknown { virtual HRESULT __stdcall RegisterProvider(GUID pProviderId, GUID ClassId, LPWSTR pwszProviderName, VSS_PROVIDER_TYPE eProviderType, LPWSTR pwszProviderVersion, GUID ProviderVersionId) = 0; virtual HRESULT __stdcall UnregisterProvider(GUID ProviderId) = 0; virtual HRESULT __stdcall QueryProviders(IVssEnumObject** ppenum) = 0; virtual HRESULT __stdcall AbortAllSnapshotsInProgress() = 0; }; MIDL_INTERFACE("D6D37103-3035-11D3-8A3A-00C04F72D8E3") IVssSnapshot : public IUnknown { virtual HRESULT __stdcall GetID(GUID* pSnapshotId) = 0; virtual HRESULT __stdcall GetDevice(LPWSTR* pDeviceName) = 0; virtual HRESULT __stdcall GetOriginalVolumeName(LPWSTR* pVolumeName) = 0; virtual HRESULT __stdcall GetAttributes(int* lAttributes) = 0; #ifdef IS2257 virtual HRESULT __stdcall GetProperties(int mask, VSS_SNAPSHOT_PROP* pProp) = 0; virtual HRESULT __stdcall SetProperties(int mask, VSS_SNAPSHOT_PROP* pProp) = 0; #else virtual HRESULT __stdcall GetProperties(VSS_SNAPSHOT_PROP* pProp) = 0; virtual HRESULT __stdcall SetProperties(VSS_SNAPSHOT_PROP* pProp) = 0; #endif #ifdef IS2250 virtual HRESULT __stdcall GetCustomProperty(VARIANT* pPropertyValue) = 0; virtual HRESULT __stdcall SetCustomProperty(VARIANT PropertyValue) = 0; #endif }; #ifdef IS2257 MIDL_INTERFACE("C7B98A22-222D-4E62-B875-1A44980634AF") IVssAsync : public IUnknown { virtual HRESULT __stdcall Cancel() = 0; virtual HRESULT __stdcall Wait() = 0; virtual HRESULT __stdcall QueryStatus(HRESULT* pHrResult, int* pReserved) = 0; }; #else MIDL_INTERFACE("C1B6F275-2F61-11D3-8A39-00C04F72D8E3") IVssAsync : public IDispatch { virtual VOID __stdcall Cancel() = 0; virtual VOID __stdcall Wait() = 0; virtual VOID __stdcall QueryStatus(HRESULT* pHrResult, int* pReserved) = 0; }; #endif MIDL_INTERFACE("93BA4344-AA56-403E-87F2-819650FEDACD") IVssCoordinator : public IUnknown { virtual HRESULT __stdcall StartSnapshotSet(GUID* pSnapshotSetId) = 0; virtual HRESULT __stdcall AddToSnapshotSet( LPWSTR pwszVolumeName, GUID ProviderId, LPWSTR pwszDetails, int lAttributes, int lDataLength, BYTE* pbOpaqueData, IVssSnapshot** ppSnapshot ) = 0; #if defined(IS2250) || defined(IS2257) virtual HRESULT __stdcall DoSnapshotSet(int lCommitFlags, IVssAsync** ppAsync) = 0; #else virtual HRESULT __stdcall DoSnapshotSet(short nCommitFlags, int nFlushType, LPWSTR pwszFlushContext, IDispatch* pWriterCallback, IVssAsync** ppAsync) = 0; #endif virtual HRESULT __stdcall GetSnapshot(GUID SnapshotId, GUID* SnapshotInterfaceId, IUnknown** ppSnapshot) = 0; virtual HRESULT __stdcall Query( GUID QueriedObjectId, VSS_OBJECT_TYPE eQueriedObjectType, VSS_OBJECT_TYPE eReturnedObjectsType, int lMask, IVssEnumObject** ppenum ) = 0; virtual HRESULT __stdcall DeleteSnapshots( GUID SourceObjectId, VSS_OBJECT_TYPE eSourceObjectType, int bForceDelete, int* plDeletedSnapshots, GUID* pNondeletedSnapshotID ) = 0; }; #pragma endregion #define CHECK_FAIL(exp) \ { \ HRESULT hr = S_OK; \ hr = (exp); \ if(hr != S_OK) \ { \ printf(#exp " not S_OK! err = %#x\n", hr); \ return 1; \ } \ } #define CASE_STRING(x) case x: return L#x; PCWSTR SnapStateToString(VSS_SNAPSHOT_STATE state) { switch(state) { CASE_STRING(VSS_SS_UNKNOWN) CASE_STRING(VSS_SS_PREPARING) CASE_STRING(VSS_SS_PROCESSING_PREPARE) CASE_STRING(VSS_SS_PREPARED) CASE_STRING(VSS_SS_PROCESSING_PRECOMMIT) CASE_STRING(VSS_SS_PRECOMMITED) CASE_STRING(VSS_SS_PROCESSING_COMMIT) CASE_STRING(VSS_SS_COMMITED) CASE_STRING(VSS_SS_PROCESSING_POSTCOMMIT) CASE_STRING(VSS_SS_CREATED) CASE_STRING(VSS_SS_ABORTED) CASE_STRING(VSS_SS_DELETED) CASE_STRING(VSS_SS_SUSPENDED) CASE_STRING(VSS_SS_RESYNC) } return L"SnapState value not recognized"; }; void PrintSnapshotProp(const VSS_SNAPSHOT_PROP& snap) { WCHAR snapId[50] = {0}, origVolId[50] = {0}, provId[50] = {0}; StringFromGUID2(snap.m_SnapshotId, snapId, ARRAYSIZE(snapId)); StringFromGUID2(snap.m_OriginalVolumeId, origVolId, ARRAYSIZE(origVolId)); StringFromGUID2(snap.m_ProviderId, provId, ARRAYSIZE(provId)); printf( "Enummed Snapshot\nSnapshot Id: %S\nSnapshot Volume Name: %S\nOrig Volume Name: %S\n" "Snap Device Object: %S\nOiginal Volume Id: %S\nAttributes: %#x\nDetails: %S\nSnap Status: %S\n" "Proverid id: %S\n\n", snapId, snap.m_pwszSnapshotVolumeName, snap.m_pwszOriginalVolumeName, snap.m_pwszSnapshotDeviceObject, origVolId, snap.m_lSnapshotAttributes, snap.m_pwszDetails, SnapStateToString(snap.m_eStatus), provId ); CoTaskMemFree(snap.m_pwszSnapshotVolumeName); CoTaskMemFree(snap.m_pwszOriginalVolumeName); CoTaskMemFree(snap.m_pwszSnapshotDeviceObject); CoTaskMemFree(snap.m_pwszDetails); CoTaskMemFree(snap.m_pbOpaqueData); } void PrintProp(VSS_OBJECT_PROP& prop, GUID* pProvId) { switch(prop.Type) { case VSS_OBJECT_NONE: case VSS_OBJECT_UNKNOWN: { puts("Enummed none/unknown prop"); } break; case VSS_OBJECT_PROVIDER: { WCHAR clsid[50] = {0}, provVerId[50] = {0}, provId[50] = {0}; VSS_PROVIDER_PROP& prov = prop.Obj.Prov; StringFromGUID2(prov.m_ClassId, clsid, ARRAYSIZE(clsid)); StringFromGUID2(prov.m_ProviderVersionId, provVerId, ARRAYSIZE(provVerId)); StringFromGUID2(prov.m_ProviderId, provId, ARRAYSIZE(provId)); printf("Enummed provider:\nName: %S\nVersion: %S\nVerClsid: %S\nProv Clsid: %S\nProv Guid: %S\nType: %d\n\n", prov.m_pwszProviderName, prov.m_pwszProviderVersion, provVerId, clsid, provId, #if defined(IS2250) || defined(IS2257) prov.m_eProviderType #else 0 #endif ); *pProvId = prov.m_ProviderId; CoTaskMemFree(prov.m_pwszProviderName); CoTaskMemFree(prov.m_pwszProviderVersion); } break; case VSS_OBJECT_SNAPSHOT: { PrintSnapshotProp(prop.Obj.Snap); } break; case VSS_OBJECT_SNAPSHOT_SET: { puts("Enummed Object Snapshot Set"); } break; } } LONG WINAPI Filter(EXCEPTION_POINTERS* pEp) { MEMORY_BASIC_INFORMATION mbi = {0}; VirtualQuery(pEp->ExceptionRecord->ExceptionAddress, &mbi, sizeof(mbi)); WCHAR module[MAX_PATH] = {0}; GetModuleFileNameW((HMODULE)mbi.AllocationBase, module, ARRAYSIZE(module)); printf("Unhandled exception %#x at %#p (%S)\n", pEp->ExceptionRecord->ExceptionCode, pEp->ExceptionRecord->ExceptionAddress, module); return EXCEPTION_CONTINUE_SEARCH; } int CreateSnapshot(IVssCoordinator* pCoord, const GUID& prov) { GUID snapSet = {0}; CHECK_FAIL(pCoord->StartSnapshotSet(&snapSet)); WCHAR snapId[50]; StringFromGUID2(snapSet, snapId, ARRAYSIZE(snapId)); printf("StartSnapshotSet returned id %S\n", snapId); IVssSnapshot* pSnap = NULL; WCHAR vol[] = L"C:\\"; WCHAR dets[] = L"C:\\bits"; CHECK_FAIL(pCoord->AddToSnapshotSet(vol, IID_NULL, dets, 1, 0, NULL, &pSnap)); printf("AddToSnapshotSet returned pSnap = %#x\n", pSnap); IVssAsync* pAsync = NULL; #if defined(IS2250) || defined(IS2257) #if defined(IS2257) VSS_SNAPSHOT_PROP props = {0}; CHECK_FAIL(pSnap->GetProperties(0, &props)); puts("Printing snapshots"); PrintSnapshotProp(props); #endif CHECK_FAIL(pCoord->DoSnapshotSet(0, &pAsync)); puts("Called DoSnapshotSet"); HRESULT hr = S_OK, hrRet = S_OK; hrRet = pAsync->Wait(); printf("Async Wait returned %#x\n", hrRet); int unk = 0; hrRet = pAsync->QueryStatus(&hr, &unk); printf("pAsync->QueryStatus ptr returned %#x, retVal = %#x\n", hr, hrRet); #else CHECK_FAIL(pCoord->DoSnapshotSet(1, 2, NULL, NULL, NULL)); #endif pAsync->Release(); pSnap->Release(); return 0; } int __cdecl main(int argc, char** argv) { puts("Usage: VssEnum "); EXCEPTION_POINTERS* pEp = NULL; //SetUnhandledExceptionFilter(&Filter); /*__try {*/ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); IVssAdmin* pAdmin = NULL; GUID CLSID_VSSCoordinator = GUID_NULL; CLSIDFromString(L"{E579AB5F-1CC4-44B4-BED9-DE0991FF0623}", &CLSID_VSSCoordinator); CHECK_FAIL(CoCreateInstance( CLSID_VSSCoordinator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pAdmin) )); GUID prov = IID_NULL; IVssCoordinator* pCoord = NULL; CHECK_FAIL(pAdmin->QueryInterface(&pCoord)); if(argc > 1) { IVssEnumObject* pEnum = NULL; CHECK_FAIL(pAdmin->QueryProviders(&pEnum)); UINT i = 0, got = 0; VSS_OBJECT_PROP prop; memset(&prop, 0, sizeof(prop)); GUID temp = IID_NULL; while(S_OK == pEnum->Next(1, &prop, &got)) { PrintProp(prop, &prov); ++i; } printf("Enummed %i objects\n", i); pEnum->Release(); i = 0; for(int i = 0; i < 4; i += 2) { int thisType = ((int)VSS_OBJECT_SNAPSHOT + i); printf("Qurying objects of type %i\n", thisType); HRESULT hr = S_OK; if((hr = pCoord->Query(GUID_NULL, VSS_OBJECT_NONE, (VSS_OBJECT_TYPE)thisType, 0, &pEnum)) == S_OK) { memset(&prop, 0, sizeof(prop)); while(S_OK == pEnum->Next(1, &prop, &got)) { PrintProp(prop, &temp); ++i; } printf("Enummed %i objects\n", i); pEnum->Release(); } else { printf("Query failed with hr=%#x\n", hr); } } } if(CreateSnapshot(pCoord, prov) == 0) { puts("Press enter to exit"); getchar(); } pCoord->Release(); pAdmin->Release(); CoUninitialize(); /*} __except(pEp = GetExceptionInformation(), EXCEPTION_EXECUTE_HANDLER) { printf("Caught exception %#x at %#p\n", pEp->ExceptionRecord->ExceptionCode, pEp->ExceptionRecord->ExceptionAddress); }*/ return 0; }