/* **++ ** ** Copyright (c) 2000-2001 Microsoft Corporation ** ** ** Module Name: ** ** waitsnap.cpp ** ** ** Abstract: ** ** Test program that starts a VSS writer and waits upon receiving a specific event ** ** Author: ** ** Charles Chung [cchung] 04-Dec-2001 ** ** ** Revision History: ** 1.0 Altered from Failsnap.cpp ** **-- */ /* ** Defines ** ** ** C4290: C++ Exception Specification ignored ** warning C4511: 'CVssCOMApplication' : copy constructor could not be generated ** warning C4127: conditional expression is constant */ #pragma warning(disable:4290) #pragma warning(disable:4511) #pragma warning(disable:4127) /* ** Includes */ #include #include #include #include #include #include #include #include #include #define GET_STATUS_FROM_BOOL(_bSucceeded) ((_bSucceeded) ? NOERROR : HRESULT_FROM_WIN32 (GetLastError())) #define GET_STATUS_FROM_HANDLE(_handle) ((NULL != (_handle)) ? NOERROR : HRESULT_FROM_WIN32 (GetLastError())) #define GET_STATUS_FROM_POINTER(_ptr) ((NULL != (_ptr)) ? NOERROR : E_OUTOFMEMORY) #define SIZEOF_ARRAY(_aBase) (sizeof (_aBase) / sizeof ((_aBase)[0])) typedef enum FAIL_PHASE { PHASE_UNDEFINED = 0, PHASE_IDENTIFY, PHASE_PREPARE_FOR_BACKUP, PHASE_PREPARE_FOR_SNAPSHOT, PHASE_FREEZE, PHASE_THAW, PHASE_ABORT, PHASE_BACKUP_COMPLETE, PHASE_RESTORE } FAIL_PHASE; HRESULT SelectFailureStatus (VOID) { HRESULT hrStatus; switch (rand () / (RAND_MAX / 5)) { case 0: hrStatus = VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT; break; case 1: hrStatus = VSS_E_WRITERERROR_OUTOFRESOURCES; break; case 2: hrStatus = VSS_E_WRITERERROR_TIMEOUT; break; case 3: hrStatus = VSS_E_WRITERERROR_NONRETRYABLE; break; case 4: hrStatus = VSS_E_WRITERERROR_RETRYABLE; break; default: assert (FALSE); break; } return (hrStatus); } void ForceSleep(INT sec) { wprintf(L"\tGoing to sleep for %d seconds...\n", sec) ; while(sec>0) { Sleep(1000) ; sec-- ; if(sec%10==0) { wprintf(L"\tSeconds left=%d\n", sec) ; } } wprintf(L"\tAwaken!\n") ; } LPCWSTR GetStringFromFailureType (HRESULT hrStatus) { LPCWSTR pwszFailureType; switch (hrStatus) { case NOERROR: pwszFailureType = L""; break; case VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT: pwszFailureType = L"InconsistentSnapshot"; break; case VSS_E_WRITERERROR_OUTOFRESOURCES: pwszFailureType = L"OutOfResources"; break; case VSS_E_WRITERERROR_TIMEOUT: pwszFailureType = L"Timeout"; break; case VSS_E_WRITERERROR_NONRETRYABLE: pwszFailureType = L"Non-Retryable"; break; case VSS_E_WRITERERROR_RETRYABLE: pwszFailureType = L"Retryable"; break; default: pwszFailureType = L"UNDEFINED"; break; } return (pwszFailureType); } LPCWSTR GetStringFromWriterType (VSS_USAGE_TYPE wtWriterType) { LPCWSTR pwszWriterType; switch (wtWriterType) { case VSS_UT_BOOTABLESYSTEMSTATE: pwszWriterType = L"BootableSystemState"; break; case VSS_UT_SYSTEMSERVICE: pwszWriterType = L"SystemServiceState"; break; case VSS_UT_USERDATA: pwszWriterType = L"UserData"; break; case VSS_UT_OTHER: pwszWriterType = L"Other"; break; default: pwszWriterType = L"UNDEFINED"; break; } return (pwszWriterType); } LPCWSTR GetStringFromWaitPhase (FAIL_PHASE fpWaitPhase) { LPCWSTR pwszWaitPhase; switch (fpWaitPhase) { case PHASE_IDENTIFY: pwszWaitPhase = L"Identify"; break; case PHASE_PREPARE_FOR_BACKUP: pwszWaitPhase = L"PrepareForBackup"; break; case PHASE_PREPARE_FOR_SNAPSHOT: pwszWaitPhase = L"PrepareForSnapshot"; break; case PHASE_FREEZE: pwszWaitPhase = L"Freeze"; break; case PHASE_THAW: pwszWaitPhase = L"Thaw"; break; case PHASE_ABORT: pwszWaitPhase = L"Abort"; break; case PHASE_BACKUP_COMPLETE: pwszWaitPhase = L"BackupComplete"; break; case PHASE_RESTORE: pwszWaitPhase = L"Restore"; break; default: pwszWaitPhase = L"UNDEFINED"; break; } return (pwszWaitPhase); } static volatile BOOL bContinue = TRUE; static volatile FAIL_PHASE fpWaitPhase = PHASE_FREEZE; static volatile INT nWaitTime = 10 ; class CVssWriterWaitsnap : public CVssWriter { public: bool STDMETHODCALLTYPE OnIdentify (IVssCreateWriterMetadata *pIVssCreateWriterMetadata); bool STDMETHODCALLTYPE OnPrepareBackup (IVssWriterComponents *pIVssWriterComponents); bool STDMETHODCALLTYPE OnPrepareSnapshot (); bool STDMETHODCALLTYPE OnFreeze (); bool STDMETHODCALLTYPE OnThaw (); bool STDMETHODCALLTYPE OnAbort (); bool STDMETHODCALLTYPE OnBackupComplete (IVssWriterComponents *pIVssWriterComponents); bool STDMETHODCALLTYPE OnPostRestore (IVssWriterComponents *pIVssWriterComponents); }; bool STDMETHODCALLTYPE CVssWriterWaitsnap::OnIdentify (IVssCreateWriterMetadata *pIVssCreateWriterMetadata) { bool bPhaseSucceeded = (PHASE_IDENTIFY != fpWaitPhase); HRESULT hrStatus = SelectFailureStatus (); if (bPhaseSucceeded) { hrStatus = pIVssCreateWriterMetadata->AddComponent (VSS_CT_FILEGROUP, NULL, L"Waitsnap Writer Component", L"Waitsnap Writer Caption", NULL, // icon 0, true, false, false); bPhaseSucceeded = SUCCEEDED (hrStatus); } wprintf (L"\nThreadId 0x%04x - Received event - OnIdentify ()%s%s\n", GetCurrentThreadId (), bPhaseSucceeded ? L"" : L" - FAILED ", GetStringFromFailureType (hrStatus)); if (!bPhaseSucceeded) { ForceSleep(nWaitTime) ; } return (TRUE); } bool STDMETHODCALLTYPE CVssWriterWaitsnap::OnPrepareBackup (IVssWriterComponents *pIVssWriterComponents) { bool bPhaseSucceeded = (PHASE_PREPARE_FOR_BACKUP != fpWaitPhase); HRESULT hrStatus = bPhaseSucceeded ? NOERROR : SelectFailureStatus (); wprintf (L"\nThreadId 0x%04x - Received event - OnPrepareBackup ()%s%s\n", GetCurrentThreadId (), bPhaseSucceeded ? L"" : L" - FAILED ", GetStringFromFailureType (hrStatus)); if (!bPhaseSucceeded) { ForceSleep(nWaitTime) ; } return (TRUE); } bool STDMETHODCALLTYPE CVssWriterWaitsnap::OnPrepareSnapshot () { bool bPhaseSucceeded = (PHASE_PREPARE_FOR_SNAPSHOT != fpWaitPhase); HRESULT hrStatus = bPhaseSucceeded ? NOERROR : SelectFailureStatus (); wprintf (L"\nThreadId 0x%04x - Received event - OnPrepareSnapshot ()%s%s\n", GetCurrentThreadId (), bPhaseSucceeded ? L"" : L" - FAILED ", GetStringFromFailureType (hrStatus)); if (!bPhaseSucceeded) { ForceSleep(nWaitTime) ; } return (TRUE); } bool STDMETHODCALLTYPE CVssWriterWaitsnap::OnFreeze () { bool bPhaseSucceeded = (PHASE_FREEZE != fpWaitPhase); HRESULT hrStatus = bPhaseSucceeded ? NOERROR : SelectFailureStatus (); wprintf (L"\nThreadId 0x%04x - Received event - OnFreeze ()%s%s\n", GetCurrentThreadId (), bPhaseSucceeded ? L"" : L" - FAILED ", GetStringFromFailureType (hrStatus)); if (!bPhaseSucceeded) { ForceSleep(nWaitTime) ; } return (TRUE); } bool STDMETHODCALLTYPE CVssWriterWaitsnap::OnThaw () { bool bPhaseSucceeded = (PHASE_THAW != fpWaitPhase); HRESULT hrStatus = bPhaseSucceeded ? NOERROR : SelectFailureStatus (); wprintf (L"\nThreadId 0x%04x - Received event - OnThaw ()%s%s\n", GetCurrentThreadId (), bPhaseSucceeded ? L"" : L" - FAILED ", GetStringFromFailureType (hrStatus)); if (!bPhaseSucceeded) { ForceSleep(nWaitTime) ; } return (TRUE); } bool STDMETHODCALLTYPE CVssWriterWaitsnap::OnAbort () { bool bPhaseSucceeded = (PHASE_ABORT != fpWaitPhase); HRESULT hrStatus = bPhaseSucceeded ? NOERROR : SelectFailureStatus (); wprintf (L"\nThreadId 0x%04x - Received event - OnAbort ()%s%s\n", GetCurrentThreadId (), bPhaseSucceeded ? L"" : L" - FAILED ", GetStringFromFailureType (hrStatus)); if (!bPhaseSucceeded) { ForceSleep(nWaitTime) ; } return (TRUE); } bool STDMETHODCALLTYPE CVssWriterWaitsnap::OnBackupComplete (IVssWriterComponents *pIVssWriterComponents) { bool bPhaseSucceeded = (PHASE_BACKUP_COMPLETE != fpWaitPhase); HRESULT hrStatus = bPhaseSucceeded ? NOERROR : SelectFailureStatus (); wprintf (L"\nThreadId 0x%04x - Received event - OnBackupComplete ()%s%s\n", GetCurrentThreadId (), bPhaseSucceeded ? L"" : L" - FAILED ", GetStringFromFailureType (hrStatus)); if (!bPhaseSucceeded) { ForceSleep(nWaitTime) ; } return (TRUE); } bool STDMETHODCALLTYPE CVssWriterWaitsnap::OnPostRestore (IVssWriterComponents *pIVssWriterComponents) { bool bPhaseSucceeded = (PHASE_RESTORE != fpWaitPhase); HRESULT hrStatus = bPhaseSucceeded ? NOERROR : SelectFailureStatus (); wprintf (L"\nThreadId 0x%04x - Received event - OnPostRestore ()%s%s\n", GetCurrentThreadId (), bPhaseSucceeded ? L"" : L" - FAILED ", GetStringFromFailureType (hrStatus)); if (!bPhaseSucceeded) { ForceSleep(nWaitTime) ; } return (TRUE); } static BOOL AssertPrivilege (LPCWSTR privName) { HANDLE tokenHandle; BOOL stat = FALSE; if (OpenProcessToken (GetCurrentProcess (), TOKEN_ADJUST_PRIVILEGES, &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; /* ** 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 0x%08X", privName, error); } } CloseHandle (tokenHandle); } return stat; } BOOL WINAPI CtrlC_HandlerRoutine (IN DWORD /* dwType */) { bContinue = FALSE; // Mark that the break was handled. return TRUE; } extern "C" int __cdecl wmain (int argc, WCHAR *argv[]) { HRESULT hrStatus = NOERROR; CVssWriterWaitsnap *pCVssWriterWaitsnap = NULL; BOOL bSucceeded = FALSE; BOOL bComInitialized = FALSE; BOOL bSubscribed = FALSE; VSS_USAGE_TYPE wtWriterType = VSS_UT_USERDATA; const GUID guidIdWriter = {0xd335a99e, 0x57fb, 0x4b80, {0x85, 0xb1, 0x15, 0xda, 0xa7, 0xc7, 0x4e, 0x14}}; srand ((unsigned)time (NULL)); SetConsoleCtrlHandler(CtrlC_HandlerRoutine, TRUE); if ((argc >= 2) && (wcslen (argv[1]) > 0)) { //get the stage which the writer is to fail switch (*argv[1]) { case L'I': case L'i': fpWaitPhase = PHASE_IDENTIFY; break; case L'B': case L'b': fpWaitPhase = PHASE_PREPARE_FOR_BACKUP; break; case L'S': case L's': fpWaitPhase = PHASE_PREPARE_FOR_SNAPSHOT; break; case L'F': case L'f': fpWaitPhase = PHASE_FREEZE; break; case L'T': case L't': fpWaitPhase = PHASE_THAW; break; case L'A': case L'a': fpWaitPhase = PHASE_ABORT; break; case L'C': case L'c': fpWaitPhase = PHASE_BACKUP_COMPLETE; break; case L'R': case L'r': fpWaitPhase = PHASE_RESTORE; break; default: wprintf (L"\nWAITSNAP [phase] [writer type] [sec to wait]" L"\n\n\tWaitPhases" L"\n\t\ti - Identify" L"\n\t\tb - PrepareForBackup" L"\n\t\ts - PrepareForSnapshot" L"\n\t\tf - Freeze (default)" L"\n\t\tt - Thaw" L"\n\t\ta - Abort" L"\n\t\tc - BackupComplete" L"\n\t\tr - PostRestore" L"\n\n\tWriterTypes" L"\n\t\tb - BootableState writer" L"\n\t\ts - ServiceState writer" L"\n\t\tu - UserData writer (default)" L"\n\t\to - Other writer" L"\n"); bContinue = FALSE; break; } //get the amount of time the stage is to wait } if ((argc >= 3) && (wcslen (argv[2]) > 0)) { switch (*argv[2]) { case L'B': case L'b': wtWriterType = VSS_UT_BOOTABLESYSTEMSTATE; break; case L'S': case L's': wtWriterType = VSS_UT_SYSTEMSERVICE; break; case L'U': case L'u': wtWriterType = VSS_UT_USERDATA; break; case L'O': case L'o': wtWriterType = VSS_UT_OTHER; break; default: bContinue = FALSE; break; } } //get the amount of seconds to wait if ((argc >= 4) && (wcslen (argv[3]) > 0)) { nWaitTime=_wtoi(argv[3]) ; } if (bContinue) { wprintf (L"\nSetting up %s writer to wait %s requests (ProcessId 0x%04x) for %d seconds", GetStringFromWriterType (wtWriterType), GetStringFromWaitPhase (fpWaitPhase), GetCurrentProcessId (), nWaitTime); wprintf (L"\nChecking privileges"); bSubscribed = AssertPrivilege (SE_BACKUP_NAME); hrStatus = GET_STATUS_FROM_BOOL (bSucceeded); if (FAILED (hrStatus)) { wprintf (L"\nAssertPrivilege returned error 0x%08X", hrStatus); } } if (bContinue && SUCCEEDED (hrStatus)) { wprintf (L"\nInitializing COM"); hrStatus = CoInitializeEx (NULL, COINIT_MULTITHREADED); if (FAILED (hrStatus)) { wprintf (L"\nCoInitialize() returned error 0x%08X", hrStatus); } else { bComInitialized = TRUE; } } if (bContinue && SUCCEEDED (hrStatus)) { wprintf (L"\nConstructing Writer"); pCVssWriterWaitsnap = new CVssWriterWaitsnap; if (NULL == pCVssWriterWaitsnap) { hrStatus = HRESULT_FROM_WIN32 (ERROR_NOT_ENOUGH_MEMORY); wprintf (L"\nFailed to allocate CVssWriterWaitsnap : 0x%08X", hrStatus); } } if (bContinue && SUCCEEDED (hrStatus)) { WCHAR awchWriterName [256]; wprintf (L"\nInitialising the writer"); _snwprintf (awchWriterName, SIZEOF_ARRAY (awchWriterName), L"Microsoft Test Writer - Waitsnap (%s/%s/0x%04x)", GetStringFromWriterType (wtWriterType), GetStringFromWaitPhase (fpWaitPhase), GetCurrentProcessId ()); hrStatus = pCVssWriterWaitsnap->Initialize (guidIdWriter, awchWriterName, wtWriterType, VSS_ST_OTHER); if (FAILED (hrStatus)) { wprintf (L"\nFailed to initialize the writer : 0x%08X", hrStatus); } } if (bContinue && SUCCEEDED (hrStatus)) { wprintf (L"\nSubscribing to snapshot events"); hrStatus = pCVssWriterWaitsnap->Subscribe (); if (FAILED (hrStatus)) { wprintf (L"\nFailed to subscribe to snapshot events : 0x%08X", hrStatus); } else { bSubscribed = TRUE; } } if (bContinue && SUCCEEDED (hrStatus)) { wprintf (L"\nWaiting for snapshot events (or Ctrl-C)"); while (bContinue) { Sleep (100); } } if (bSubscribed) { wprintf (L"\nUn-Subscribing from snapshot events"); pCVssWriterWaitsnap->Unsubscribe (); } if (NULL != pCVssWriterWaitsnap) { wprintf (L"\nDeconstructing Writer"); delete pCVssWriterWaitsnap; } if (bComInitialized) { wprintf (L"\nUnInitialising COM"); CoUninitialize(); } return (hrStatus); }