m_bDuringRestore = false;
m_bBackupIsInitialized = false;
m_pVssObject = NULL;
+ m_pVectorWriterStates = new vector<int>;
+ m_pVectorWriterInfo = new vector<string>;
+ m_uidCurrentSnapshotSet = GUID_NULL;
memset (m_wszUniqueVolumeName,0,sizeof (m_wszUniqueVolumeName));
memset (m_szShadowCopyName,0,sizeof (m_szShadowCopyName));
}
m_pVssObject = NULL;
}
+ if (m_pVectorWriterStates)
+ delete (m_pVectorWriterStates);
+
+ if (m_pVectorWriterInfo)
+ delete (m_pVectorWriterInfo);
+
// Call CoUninitialize if the CoInitialize was performed sucesfully
if (m_bCoInitializeCalled)
CoUninitialize();
strncpy (szShadowPath, szFilePath, nBuflen);
return FALSE;
+}
+
+
+const size_t VSSClient::GetWriterCount()
+{
+ vector<int>* pV = (vector<int>*) m_pVectorWriterStates;
+ return pV->size();
+}
+
+const char* VSSClient::GetWriterInfo(size_t nIndex)
+{
+ vector<string>* pV = (vector<string>*) m_pVectorWriterInfo;
+ return pV->at(nIndex).c_str();
+}
+
+
+const int VSSClient::GetWriterState(size_t nIndex)
+{
+ vector<int>* pV = (vector<int>*) m_pVectorWriterStates;
+ return pV->at(nIndex);
}
\ No newline at end of file
virtual const char* GetDriverName() = 0;
BOOL GetShadowPath (const char* szFilePath, char* szShadowPath, int nBuflen);
+ const size_t GetWriterCount();
+ const char* GetWriterInfo(size_t nIndex);
+ const int GetWriterState(size_t nIndex);
private:
virtual BOOL Initialize(DWORD dwContext, BOOL bDuringRestore = FALSE) = 0;
DWORD m_dwContext;
IUnknown* m_pVssObject;
+ GUID m_uidCurrentSnapshotSet;
// TRUE if we are during restore
BOOL m_bDuringRestore;
BOOL m_bBackupIsInitialized;
// drive A will be stored on position 0,Z on pos. 25
WCHAR m_wszUniqueVolumeName[26][MAX_PATH]; // approx. 7 KB
char /* in utf-8 */ m_szShadowCopyName[26][MAX_PATH*2]; // approx. 7 KB
+
+ void* m_pVectorWriterStates;
+ void* m_pVectorWriterInfo;
};
class VSSClientXP:public VSSClient
virtual BOOL Initialize(DWORD dwContext, BOOL bDuringRestore);
virtual void WaitAndCheckForAsyncOperation(IVssAsync* pAsync);
virtual void QuerySnapshotSet(GUID snapshotSetID);
+ BOOL CheckWriterStatus();
};
class VSSClient2003:public VSSClient
virtual BOOL Initialize(DWORD dwContext, BOOL bDuringRestore);
virtual void WaitAndCheckForAsyncOperation(IVssAsync* pAsync);
virtual void QuerySnapshotSet(GUID snapshotSetID);
+ BOOL CheckWriterStatus();
};
#include <vector>
#include <algorithm>
#include <string>
+#include <sstream>
#include <fstream>
using namespace std;
}
+// Helper macro for quick treatment of case statements for error codes
+#define GEN_MERGE(A, B) A##B
+#define GEN_MAKE_W(A) GEN_MERGE(L, A)
+
+#define CHECK_CASE_FOR_CONSTANT(value) \
+ case value: return wstring(GEN_MAKE_W(#value));
+
+
+// Convert a writer status into a string
+inline wstring GetStringFromWriterStatus(VSS_WRITER_STATE eWriterStatus)
+{
+ switch (eWriterStatus)
+ {
+ CHECK_CASE_FOR_CONSTANT(VSS_WS_STABLE);
+ CHECK_CASE_FOR_CONSTANT(VSS_WS_WAITING_FOR_FREEZE);
+ CHECK_CASE_FOR_CONSTANT(VSS_WS_WAITING_FOR_THAW);
+ CHECK_CASE_FOR_CONSTANT(VSS_WS_WAITING_FOR_POST_SNAPSHOT);
+ CHECK_CASE_FOR_CONSTANT(VSS_WS_WAITING_FOR_BACKUP_COMPLETE);
+ CHECK_CASE_FOR_CONSTANT(VSS_WS_FAILED_AT_IDENTIFY);
+ CHECK_CASE_FOR_CONSTANT(VSS_WS_FAILED_AT_PREPARE_BACKUP);
+ CHECK_CASE_FOR_CONSTANT(VSS_WS_FAILED_AT_PREPARE_SNAPSHOT);
+ CHECK_CASE_FOR_CONSTANT(VSS_WS_FAILED_AT_FREEZE);
+ CHECK_CASE_FOR_CONSTANT(VSS_WS_FAILED_AT_THAW);
+ CHECK_CASE_FOR_CONSTANT(VSS_WS_FAILED_AT_POST_SNAPSHOT);
+ CHECK_CASE_FOR_CONSTANT(VSS_WS_FAILED_AT_BACKUP_COMPLETE);
+ CHECK_CASE_FOR_CONSTANT(VSS_WS_FAILED_AT_PRE_RESTORE);
+ CHECK_CASE_FOR_CONSTANT(VSS_WS_FAILED_AT_POST_RESTORE);
+
+ default:
+ return wstring(L"Undefined");
+ }
+}
// Constructor
if (FAILED(hr))
return FALSE;
}
-
- IVssBackupComponents* pVss = (IVssBackupComponents*) m_pVssObject;
+
// Release the IVssBackupComponents interface
- if (pVss) {
- pVss->Release();
- pVss = NULL;
+ if (m_pVssObject) {
+ m_pVssObject->Release();
+ m_pVssObject = NULL;
}
// Create the internal backup components object
if (FAILED(hr))
return FALSE;
+#ifdef B_VSS_W2K3
+ if (dwContext != VSS_CTX_BACKUP) {
+ hr = ((IVssBackupComponents*) m_pVssObject)->SetContext(dwContext);
+ if (FAILED(hr))
+ return FALSE;
+ }
+#endif
+
// We are during restore now?
m_bDuringRestore = bDuringRestore;
LocalFree(pwszBuffer);
}
- throw(hrReturned);
}
}
/* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vss/base/ivssbackupcomponents_startsnapshotset.asp */
if (!m_pVssObject || m_bBackupIsInitialized)
- return FALSE;
+ return FALSE;
+
+ m_uidCurrentSnapshotSet = GUID_NULL;
IVssBackupComponents* pVss = (IVssBackupComponents*) m_pVssObject;
return FALSE;
CComPtr<IVssAsync> pAsync1;
- CComPtr<IVssAsync> pAsync2;
- VSS_ID latestSnapshotSetID;
+ CComPtr<IVssAsync> pAsync2;
+ CComPtr<IVssAsync> pAsync3;
VSS_ID pid;
- // 3. startSnapshotSet
+ // 3. GatherWriterMetaData
+ hr = pVss->GatherWriterMetadata(&pAsync3);
+ if (FAILED(hr))
+ return FALSE;
- pVss->StartSnapshotSet(&latestSnapshotSetID);
+ // Waits for the async operation to finish and checks the result
+ WaitAndCheckForAsyncOperation(pAsync3);
+
+ CheckWriterStatus();
+
+ // 4. startSnapshotSet
+
+ pVss->StartSnapshotSet(&m_uidCurrentSnapshotSet);
// 4. AddToSnapshotSet
}
// 5. PrepareForBackup
-
pVss->PrepareForBackup(&pAsync1);
-
+
// Waits for the async operation to finish and checks the result
WaitAndCheckForAsyncOperation(pAsync1);
-
// 6. DoSnapShotSet
-
pVss->DoSnapshotSet(&pAsync2);
// Waits for the async operation to finish and checks the result
WaitAndCheckForAsyncOperation(pAsync2);
/* query snapshot info */
- QuerySnapshotSet(latestSnapshotSetID);
+ QuerySnapshotSet(m_uidCurrentSnapshotSet);
m_bBackupIsInitialized = true;
pVss->AbortBackup();
}
+ if (m_uidCurrentSnapshotSet != GUID_NULL) {
+ VSS_ID idNonDeletedSnapshotID = GUID_NULL;
+ LONG lSnapshots;
+
+ pVss->DeleteSnapshots(
+ m_uidCurrentSnapshotSet,
+ VSS_OBJECT_SNAPSHOT_SET,
+ FALSE,
+ &lSnapshots,
+ &idNonDeletedSnapshotID);
+
+ m_uidCurrentSnapshotSet = GUID_NULL;
+ }
+
+
pVss->Release();
m_pVssObject = NULL;
return;
IVssBackupComponents* pVss = (IVssBackupComponents*) m_pVssObject;
-
-
+
// Get list all shadow copies.
CComPtr<IVssEnumObject> pIEnumSnapshots;
HRESULT hr = pVss->Query( GUID_NULL,
}
}
+// Check the status for all selected writers
+BOOL VSSClientGeneric::CheckWriterStatus()
+{
+ IVssBackupComponents* pVss = (IVssBackupComponents*) m_pVssObject;
+ vector<int>* pVWriterStates = (vector<int>*) m_pVectorWriterStates;
+ vector<string>* pVWriterInfo = (vector<string>*) m_pVectorWriterInfo;
+
+ pVWriterStates->clear();
+ pVWriterInfo->clear();
+
+ // Gather writer status to detect potential errors
+ CComPtr<IVssAsync> pAsync;
+
+ HRESULT hr = pVss->GatherWriterStatus(&pAsync);
+ if (FAILED(hr))
+ return FALSE;
+
+ // Waits for the async operation to finish and checks the result
+ WaitAndCheckForAsyncOperation(pAsync);
+
+ unsigned cWriters = 0;
+
+ hr = pVss->GetWriterStatusCount(&cWriters);
+ if (FAILED(hr))
+ return FALSE;
+
+ // Enumerate each writer
+ for(unsigned iWriter = 0; iWriter < cWriters; iWriter++)
+ {
+ VSS_ID idInstance = GUID_NULL;
+ VSS_ID idWriter= GUID_NULL;
+ VSS_WRITER_STATE eWriterStatus = VSS_WS_UNKNOWN;
+ CComBSTR bstrWriterName;
+ HRESULT hrWriterFailure = S_OK;
+
+ // Get writer status
+ hr = pVss->GetWriterStatus(iWriter,
+ &idInstance,
+ &idWriter,
+ &bstrWriterName,
+ &eWriterStatus,
+ &hrWriterFailure);
+ if (FAILED(hr))
+ continue;
+
+ // If the writer is in non-stable state, break
+ switch(eWriterStatus)
+ {
+ case VSS_WS_FAILED_AT_IDENTIFY:
+ case VSS_WS_FAILED_AT_PREPARE_BACKUP:
+ case VSS_WS_FAILED_AT_PREPARE_SNAPSHOT:
+ case VSS_WS_FAILED_AT_FREEZE:
+ case VSS_WS_FAILED_AT_THAW:
+ case VSS_WS_FAILED_AT_POST_SNAPSHOT:
+ case VSS_WS_FAILED_AT_BACKUP_COMPLETE:
+ case VSS_WS_FAILED_AT_PRE_RESTORE:
+ case VSS_WS_FAILED_AT_POST_RESTORE:
+#ifdef B_VSS_W2K3
+ case VSS_WS_FAILED_AT_BACKUPSHUTDOWN:
+#endif
+ /* failed */
+ pVWriterStates->push_back(-1);
+ break;
+
+ default:
+ /* okay */
+ pVWriterStates->push_back(1);
+ }
+
+
+ stringstream osf;
+ osf << "\"" << CW2A(bstrWriterName) << "\", State: " << eWriterStatus << " (" << CW2A(GetStringFromWriterStatus(eWriterStatus).c_str()) << ")";
+
+ pVWriterInfo->push_back(osf.str());
+ }
+ return TRUE;
+}
\ No newline at end of file