/*++ Copyright (c) 2000 Microsoft Corporation Module Name: rswriter.cpp Abstract: Implements CRssJetWriter methods Author: Ran Kalach [rankala] 4/4/2000 Revision History: --*/ #include "stdafx.h" #include "rsevents.h" #include "rswriter.h" // Include these 2 files just for VSS_E_WRITERERROR_TIMEOUT definition #include "vss.h" #include "vswriter.h" #ifndef INITGUID #define INITGUID #include #undef INITGUID #else #include #endif #ifdef __cplusplus extern "C" { #endif DEFINE_GUID(RSS_WRITER_GUID, 0xb959d2c3L, 0x18bb, 0x4607, 0xb0, 0xca, 0x68, 0x8c, 0xd0, 0xd4, 0x1a, 0x50); // {b959d2c3-18bb-4607-b0ca-688cd0d41a50} #ifdef __cplusplus } #endif #define FILES_TO_EXCLUDE OLESTR("%SystemRoot%\\System32\\RemoteStorage\\FsaDb\\*;%SystemRoot%\\System32\\RemoteStorage\\Trace\\*") #define FILES_TO_INCLUDE OLESTR("") CRssJetWriter::CRssJetWriter() /*++ Routine Description: Constructor Arguments: None Return Value: None Notes: We create the events in the constructor because these events might be required before the Init code could be done (Init must be called after Jet is initialized --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CRssJetWriter::CRssJetWriter"), OLESTR("")); m_bTerminating = FALSE; try { for (int index=0; index"), WsbHrAsString(hr)); } CRssJetWriter::~CRssJetWriter( ) /*++ Routine Description: Destructor - free resources Arguments: None Return Value: None --*/ { WsbTraceIn(OLESTR("CRssJetWriter::~CRssJetWriter"), OLESTR("")); // Close event handles for (int index=0; index"), WsbHrAsString(hr)); return hr; } HRESULT CRssJetWriter::Terminate(void) /*++ Routine Description: Terminate Snapshot synchronization Arguments: None Return Value: S_OK - Success --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CRssJetWriter::Terminate"), OLESTR("")); try { DWORD status, errWait; WsbAffirmHr(m_hrInit); // Avoid terminating in the middle of snapshot status = WaitForSingleObject(m_syncHandles[INTERNAL_EVENT_INDEX], INTERNAL_WAIT_TIMEOUT); errWait = GetLastError(); // Whatever the status is - uninitialize underlying writer mechanizm m_bTerminating = TRUE; Uninitialize(); // Check Wait status: if (status == WAIT_OBJECT_0) { // The expected case if (! SetEvent(m_syncHandles[INTERNAL_EVENT_INDEX])) { // Don't abort, just trace error WsbTraceAlways(OLESTR("CRssJetWriter::Terminate: SetEvent returned unexpected error %lu\n"), GetLastError()); } WsbTrace(OLESTR("CRssJetWriter::Terminate: Terminating after a successful wait\n")); } else { // In case of failure we cannot trust Thaw/Abort to be called so we signal the evnets InternalEnd(); switch (status) { case WAIT_TIMEOUT: WsbTraceAlways(OLESTR("CRssJetWriter::Terminate: Wait for Single Object timed out after %lu ms\n"), INTERNAL_WAIT_TIMEOUT); hr = E_FAIL; break; case WAIT_FAILED: WsbTraceAlways(OLESTR("CRssJetWriter::Terminate: Wait for Single Object returned error %lu\n"), errWait); hr = HRESULT_FROM_WIN32(errWait); break; default: WsbTraceAlways(OLESTR("CRssJetWriter::Terminate: Wait for Single Object returned unexpected status %lu\n"), status); hr = E_UNEXPECTED; break; } } } WsbCatch(hr); WsbTraceOut(OLESTR("CRssJetWriter::Terminate"), OLESTR("hr = <%ls>"), WsbHrAsString(hr)); return hr; } HRESULT CRssJetWriter::InternalEnd(void) /*++ Routine Description: Set all events Arguments: None Return Value: S_OK - Success --*/ { HRESULT hr = S_OK; WsbTraceIn(OLESTR("CRssJetWriter::InternalEnd"), OLESTR("")); try { WsbAffirmHr(m_hrInit); // Set all events DWORD errSet; for (int index=0; index"), WsbHrAsString(hr)); return hr; } // // CVssJetWriter overloaded methods // bool STDMETHODCALLTYPE CRssJetWriter::OnFreezeBegin() /*++ Routine Description: Handles Freeze Start event Arguments: None Return Value: TRUE - Success, OK to freeze FALSE - Failure, Don't freeze --*/ { HRESULT hr = S_OK; bool bRet; WsbTraceIn(OLESTR("CRssJetWriter::OnFreezeBegin"), OLESTR("")); try { WsbAffirmHr(m_hrInit); // Just wait for all sync events DWORD status = WaitForMultipleObjects(WRITER_EVENTS_NUM, m_syncHandles, TRUE, EVENT_WAIT_TIMEOUT); // Comparing (status == WAIT_OBJECT_0) || (status > WAIT_OBJECT_0) intsead of (status >= WAIT_OBJECT_0) // to avoid error C4296 - "expression is always true" if ( ((status == WAIT_OBJECT_0) || (status > WAIT_OBJECT_0)) && (status <= WAIT_OBJECT_0 + WRITER_EVENTS_NUM - 1) ) { // Freeze is ready to go... WsbTrace(OLESTR("CRssJetWriter::OnFreezeBegin: All events are nonsignaled, freeze is reday to go\n")); // If we are terminating, no Thaw/Abort will be called - therefore, set the events if (m_bTerminating) { InternalEnd(); } } else { // Something wrong... DWORD errWait = GetLastError(); // Set all events in case of an error InternalEnd(); switch(status) { case WAIT_FAILED: WsbTraceAlways(OLESTR("CRssJetWriter::OnFreezeBegin: Wait for Multiple Objects returned error %lu\n"), errWait); WsbThrow(HRESULT_FROM_WIN32(errWait)); break; case WAIT_TIMEOUT: // Timeout means that one of the sync components is taking too long WsbTraceAlways(OLESTR("CRssJetWriter::OnFreezeBegin: Wait for Multiple Objects timed out after %lu ms\n"), EVENT_WAIT_TIMEOUT); WsbThrow(VSS_E_WRITERERROR_TIMEOUT); break; default: WsbTraceAlways(OLESTR("CRssJetWriter::OnFreezeBegin: Wait for Multiple Objects returned unexpected status %lu\n"), status); WsbThrow(E_UNEXPECTED); break; } } } WsbCatch(hr); if (S_OK == hr) { bRet = CVssJetWriter::OnFreezeBegin(); } else { bRet = false; } WsbTraceOut(OLESTR("CRssJetWriter::OnFreezeBegin"), OLESTR("hr = <%ls> , bRet = <%ls>"), WsbHrAsString(hr), WsbBoolAsString(bRet)); return bRet; } bool STDMETHODCALLTYPE CRssJetWriter::OnThawEnd(IN bool fJetThawSucceeded) /*++ Routine Description: Handles Thaw End event Arguments: fJetThawSucceeded - Ignored Return Value: TRUE - Success FALSE - Failure --*/ { bool bRet; WsbTraceIn(OLESTR("CRssJetWriter::OnThawEnd"), OLESTR("")); // Return value is determined by base class, ignore internal errors here bRet = CVssJetWriter::OnThawEnd(fJetThawSucceeded); // Release all waiting events InternalEnd(); WsbTraceOut(OLESTR("CRssJetWriter::OnThawEnd"), OLESTR("bRet = <%ls>"), WsbBoolAsString(bRet)); return bRet; } void STDMETHODCALLTYPE CRssJetWriter::OnAbortEnd() /*++ Routine Description: Handles Abort End event Arguments: None Return Value: None --*/ { WsbTraceIn(OLESTR("CRssJetWriter::OnAbortEnd"), OLESTR("")); // Call base class imp. CVssJetWriter::OnAbortEnd(); // Release all waiting events InternalEnd(); WsbTraceOut(OLESTR("CRssJetWriter::OnAbortEnd"), OLESTR("")); }