Leaked source code of windows server 2003
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.

3304 lines
105 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Abstract:
  4. @doc
  5. @module VsWrtImp.cpp | Implementation of Writer
  6. @end
  7. Author:
  8. Adi Oltean [aoltean] 02/02/2000
  9. TBD:
  10. Add comments.
  11. Remove the C++ exception-handler related code.
  12. Revision History:
  13. Name Date Comments
  14. aoltean 02/02/2000 Created
  15. brianb 03/25/2000 modified to include additional events
  16. brianb 03/28/2000 modified to include timeouts and sync for OnPrepareBackup
  17. brianb 03/28/2000 renamed to vswrtimp.cpp to separate internal state from external interface
  18. brianb 04/19/2000 added security checks
  19. brianb 05/03/2000 new security model
  20. brianb 05/09/2000 fix problem with autolocks
  21. --*/
  22. #include <stdafx.hxx>
  23. #include <eventsys.h>
  24. #include "vs_inc.hxx"
  25. #include "vs_sec.hxx"
  26. #include "vs_idl.hxx"
  27. #include "vs_reg.hxx"
  28. #include "vscoordint.h"
  29. #include "comadmin.hxx"
  30. #include "vsevent.h"
  31. #include "vswriter.h"
  32. #include "vsbackup.h"
  33. #include "vssmsg.h"
  34. #include "vswrtimp.h"
  35. // xml support
  36. #include "vs_wmxml.hxx"
  37. #include "vs_cmxml.hxx"
  38. #include "rpcdce.h"
  39. ////////////////////////////////////////////////////////////////////////
  40. // Standard foo for file name aliasing. This code block must be after
  41. // all includes of VSS header files.
  42. //
  43. #ifdef VSS_FILE_ALIAS
  44. #undef VSS_FILE_ALIAS
  45. #endif
  46. #define VSS_FILE_ALIAS "WRTWRTIC"
  47. //
  48. ////////////////////////////////////////////////////////////////////////
  49. /////////////////////////////////////////////////////////////////////////////
  50. // Constants
  51. const WCHAR g_wszPublisherID[] = L"VSS Publisher";
  52. // event names
  53. const WCHAR g_wszRequestInfoMethodName[] = L"RequestWriterInfo";
  54. const WCHAR g_wszPrepareForBackupMethodName[] = L"PrepareForBackup";
  55. const WCHAR g_wszBackupCompleteMethodName[] = L"BackupComplete";
  56. const WCHAR g_wszPrepareForSnapshotMethodName[] = L"PrepareForSnapshot";
  57. const WCHAR g_wszFreezeMethodName[] = L"Freeze";
  58. const WCHAR g_wszThawMethodName[] = L"Thaw";
  59. const WCHAR g_wszPostSnapshotMethodName[] = L"PostSnapshot";
  60. const WCHAR g_wszAbortMethodName[] = L"Abort";
  61. const WCHAR g_wszPreRestoreMethodName[] = L"PreRestore";
  62. const WCHAR g_wszPostRestoreMethodName[] = L"PostRestore";
  63. const WCHAR g_wszBackupShutdownName[] = L"BackupShutdown";
  64. // List of received volumes is in the following formatDate
  65. // <Volume Name 1>;<Volume Name 2>: ... :<Volume Name N>
  66. const WCHAR VSS_VOLUME_DELIMITERS[] = L";";
  67. // class describing state machine for writer
  68. class CVssWriterImplStateMachine
  69. {
  70. private:
  71. // disable default and copy constructors
  72. CVssWriterImplStateMachine();
  73. public:
  74. CVssWriterImplStateMachine
  75. (
  76. VSS_WRITER_STATE previousState,
  77. VSS_WRITER_STATE successfulExitState,
  78. VSS_WRITER_STATE failureExitState,
  79. bool bBeginningState,
  80. bool bSuccessiveState,
  81. bool bResetSequenceOnLeave
  82. ) :
  83. m_previousState(previousState),
  84. m_successfulExitState(successfulExitState),
  85. m_failureExitState(failureExitState),
  86. m_bBeginningState(bBeginningState),
  87. m_bSuccessiveState(bSuccessiveState),
  88. m_bResetSequenceOnLeave(bResetSequenceOnLeave)
  89. {
  90. }
  91. // previous state writer must be in to enter the current
  92. // state unless this is the first state of a sequence
  93. VSS_WRITER_STATE m_previousState;
  94. // state we are in if the operation is successful
  95. VSS_WRITER_STATE m_successfulExitState;
  96. // state we are in if the operation is uncessful
  97. VSS_WRITER_STATE m_failureExitState;
  98. // is this state a possible state for the beginning of the sequence
  99. bool m_bBeginningState;
  100. // is this a possible non-beginning state in a sequence
  101. bool m_bSuccessiveState;
  102. // should the sequence be reset on successful exit of the state
  103. bool m_bResetSequenceOnLeave;
  104. };
  105. // definition of state machine
  106. static CVssWriterImplStateMachine s_rgWriterStates[] =
  107. {
  108. // OnPrepareBackup
  109. CVssWriterImplStateMachine
  110. (
  111. VSS_WS_STABLE, // previous state
  112. VSS_WS_STABLE, // next state if successful
  113. VSS_WS_FAILED_AT_PREPARE_BACKUP, // next state if failure
  114. true, // this can be a first state
  115. false, // this must be a first state
  116. false // do not reset sequence on leaving this state
  117. ),
  118. // OnPrepareSnapshot
  119. CVssWriterImplStateMachine
  120. (
  121. VSS_WS_STABLE, // previous state
  122. VSS_WS_WAITING_FOR_FREEZE, // next state if successful
  123. VSS_WS_FAILED_AT_PREPARE_SNAPSHOT, // next state if failure
  124. true, // this can be a first state
  125. true, // this can be a follow on state
  126. false // do not reset sequence on leaving this state
  127. ),
  128. // OnFreeze
  129. CVssWriterImplStateMachine
  130. (
  131. VSS_WS_WAITING_FOR_FREEZE, // previous state
  132. VSS_WS_WAITING_FOR_THAW, // next state if successful
  133. VSS_WS_FAILED_AT_FREEZE, // next state if unsuccessful
  134. false, // this may not be a first state
  135. true, // this must be a follow on state
  136. false // do not reset sequence on leaving this state
  137. ),
  138. // OnThaw
  139. CVssWriterImplStateMachine
  140. (
  141. VSS_WS_WAITING_FOR_THAW, // previous state
  142. VSS_WS_WAITING_FOR_POST_SNAPSHOT, // next state if successful
  143. VSS_WS_FAILED_AT_THAW, // next state if unsuccessful
  144. false, // this may not be a first state
  145. true, // this must be a follow on state
  146. false // reset sequence on leaving this state
  147. ),
  148. // OnPostSnapshot
  149. CVssWriterImplStateMachine
  150. (
  151. VSS_WS_WAITING_FOR_POST_SNAPSHOT, // previous state
  152. VSS_WS_WAITING_FOR_BACKUP_COMPLETE, // next state if successful
  153. VSS_WS_FAILED_AT_POST_SNAPSHOT, // next state if unsuccessful
  154. false, // this may not be a first state
  155. true, // this must be a follow on state
  156. true // reset sequence on leaving this state
  157. )
  158. };
  159. // state ids
  160. static const unsigned s_ivwsmPrepareForBackup = 0;
  161. static const unsigned s_ivwsmPrepareForSnapshot = 1;
  162. static const unsigned s_ivwsmFreeze = 2;
  163. static const unsigned s_ivwsmThaw = 3;
  164. static const unsigned s_ivwsmPostSnapshot = 4;
  165. /////////////////////////////////////////////////////////////////////////////
  166. // CVssWriterImpl constructors/destructors
  167. // constructor
  168. CVssWriterImpl::CVssWriterImpl():
  169. m_bInitialized(false),
  170. m_writerstate(m_diag),
  171. m_WriterID(GUID_NULL),
  172. m_InstanceID(GUID_NULL),
  173. m_usage(VSS_UT_UNDEFINED),
  174. m_source(VSS_ST_UNDEFINED),
  175. m_nLevel(VSS_APP_FRONT_END),
  176. m_dwTimeoutFreeze(VSS_TIMEOUT_FREEZE),
  177. m_CurrentSnapshotSetId(GUID_NULL),
  178. m_lContext(VSS_CTX_BACKUP),
  179. m_nVolumesCount(0),
  180. m_ppwszVolumesArray(NULL),
  181. m_pwszLocalVolumeNameList(NULL),
  182. m_dwEventMask(0),
  183. m_wszWriterName(NULL),
  184. m_hevtTimerThread(NULL),
  185. m_hmtxTimerThread(NULL),
  186. m_hThreadTimerThread(NULL),
  187. m_bLocked(false),
  188. m_bLockCreated(false),
  189. m_command(VSS_TC_UNDEFINED),
  190. m_cbstrSubscriptionId(0),
  191. m_bOnAbortPermitted(false),
  192. m_bSequenceInProgress(false),
  193. m_pWriter(NULL),
  194. m_bBootableSystemStateBackup(false),
  195. m_bComponentsSelected(false),
  196. m_backupType(VSS_BT_UNDEFINED),
  197. m_restoreType(VSS_RTYPE_UNDEFINED),
  198. m_bPartialFileSupport(false),
  199. m_bInSafeMode(false),
  200. m_bInSetup(false)
  201. {
  202. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterImpl::CVssWriterImpl");
  203. ft.Trace( VSSDBG_WRITER, L"*** Constructing object %p", this);
  204. }
  205. // destructor
  206. CVssWriterImpl::~CVssWriterImpl()
  207. {
  208. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterImpl::~CVssWriterImpl");
  209. ft.Trace( VSSDBG_WRITER, L"*** Destructing object %p", this);
  210. Uninitialize();
  211. }
  212. void CVssWriterImpl::Uninitialize()
  213. {
  214. if (!m_bInitialized)
  215. return;
  216. // terminate timer thread if it is still running
  217. if (m_bLockCreated)
  218. {
  219. if (m_bstrSubscriptionName.Length() > 0)
  220. {
  221. try
  222. {
  223. Unsubscribe();
  224. }
  225. catch(...)
  226. {
  227. }
  228. }
  229. Lock();
  230. TerminateTimerThread();
  231. Unlock();
  232. m_cs.Uninit();
  233. m_bLockCreated = false;
  234. }
  235. // delete volume array
  236. delete[] m_ppwszVolumesArray;
  237. m_ppwszVolumesArray = NULL;
  238. // delete volume list string
  239. ::VssFreeString(m_pwszLocalVolumeNameList);
  240. // delete writer name
  241. free(m_wszWriterName);
  242. m_wszWriterName = NULL;
  243. if (m_hevtTimerThread)
  244. {
  245. CloseHandle(m_hevtTimerThread);
  246. m_hevtTimerThread = NULL;
  247. }
  248. if (m_hmtxTimerThread)
  249. {
  250. CloseHandle(m_hmtxTimerThread);
  251. m_hmtxTimerThread = NULL;
  252. }
  253. }
  254. // get the snapshot device name for a particular volume
  255. HRESULT CVssWriterImpl::GetSnapshotDeviceName
  256. (
  257. LPCWSTR wszOriginalVolume,
  258. LPCWSTR* ppwszSnapshotDevice
  259. ) const
  260. {
  261. UNREFERENCED_PARAMETER(wszOriginalVolume);
  262. UNREFERENCED_PARAMETER(ppwszSnapshotDevice);
  263. return E_NOTIMPL;
  264. }
  265. // create an event
  266. void CVssWriterImpl::SetupEvent(IN HANDLE *phevt)
  267. {
  268. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterImple::SetupEvent");
  269. BS_ASSERT(phevt);
  270. // setup events as enabled and manual reset
  271. *phevt = CreateEvent(NULL, TRUE, TRUE, NULL);
  272. if (*phevt == NULL)
  273. ft.Throw
  274. (
  275. VSSDBG_WRITER,
  276. E_OUTOFMEMORY,
  277. L"Failure to create event object due to error %d.",
  278. GetLastError()
  279. );
  280. }
  281. // initialize writer object
  282. // This function returns S_FALSE when the writer is inactive (setup or safe mode)
  283. void CVssWriterImpl::Initialize
  284. (
  285. IN VSS_ID WriterID, // writer class id
  286. IN LPCWSTR wszWriterName, // friendly name of writer
  287. IN VSS_USAGE_TYPE usage, // usage type
  288. IN VSS_SOURCE_TYPE source, // data source type
  289. IN VSS_APPLICATION_LEVEL nLevel, // which freeze event this writer handles
  290. IN DWORD dwTimeoutFreeze // timeout between freeze and thaw
  291. )
  292. {
  293. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterImpl::Initialize");
  294. // validate that the writer is initialized
  295. if (m_bInitialized)
  296. ft.Throw
  297. (
  298. VSSDBG_WRITER,
  299. VSS_E_BAD_STATE,
  300. L"You cannot initialize the writer twice"
  301. );
  302. // determine if we are in setup. If we are then reject the
  303. // initialize call and log an error in the application log
  304. m_bInSetup = CVssMachineInformation::IsDuringSetup();
  305. if (m_bInSetup)
  306. {
  307. ft.LogError(VSS_ERROR_SETUP_WRITER, VSSDBG_WRITER << wszWriterName << WriterID );
  308. ft.Throw(VSSDBG_WRITER, S_FALSE, L"Calling Initialize during setup");
  309. }
  310. // determine if we are in safe mode. If we are then reject the
  311. // initialize call and log an error in the application log
  312. m_bInSafeMode = CVssMachineInformation::IsDuringSafeMode();
  313. if (m_bInSafeMode)
  314. {
  315. ft.LogError(VSS_ERROR_SAFE_MODE_WRITER, VSSDBG_WRITER << wszWriterName << WriterID );
  316. ft.Throw(VSSDBG_WRITER, S_FALSE, L"Calling Initialize during safe mode");
  317. }
  318. // Initialize the list of possible SIDs from registry
  319. m_SidCollection.Initialize();
  320. // Check if the writer runs under a proper user
  321. if (!m_SidCollection.IsProcessValidWriter())
  322. {
  323. ft.LogError(VSS_ERROR_NON_PRIVILEGED_WRITER, VSSDBG_WRITER << wszWriterName << WriterID );
  324. ft.Throw(VSSDBG_WRITER, E_ACCESSDENIED, L"Writer is not privileged");
  325. }
  326. // Testing arguments validity
  327. if (wszWriterName == NULL)
  328. ft.Throw
  329. (
  330. VSSDBG_WRITER,
  331. E_INVALIDARG,
  332. L"NULL writer name"
  333. );
  334. switch(nLevel) {
  335. case VSS_APP_SYSTEM:
  336. case VSS_APP_BACK_END:
  337. case VSS_APP_FRONT_END:
  338. break;
  339. default:
  340. ft.Throw
  341. (
  342. VSSDBG_WRITER,
  343. E_INVALIDARG,
  344. L"Invalid app level %d", nLevel
  345. );
  346. }
  347. m_cs.Init(); // Warning - may throw NT exceptions...
  348. m_bLockCreated = true;
  349. // initialize writer state
  350. m_writerstate.Initialize();
  351. // save writer class id
  352. m_WriterID = WriterID;
  353. // save writer name
  354. m_wszWriterName = _wcsdup(wszWriterName);
  355. if (m_wszWriterName == NULL)
  356. ft.Throw
  357. (
  358. VSSDBG_WRITER,
  359. E_OUTOFMEMORY,
  360. L"Cannot allocate writer name"
  361. );
  362. // save usage type
  363. m_usage = usage;
  364. // save source type
  365. m_source = source;
  366. // create guid for this instance
  367. ft.hr = ::CoCreateGuid(&m_InstanceID);
  368. ft.CheckForError(VSSDBG_WRITER, L"CoCreateGuid");
  369. ft.Trace
  370. (
  371. VSSDBG_WRITER,
  372. L" InstanceId for Writer %s is" WSTR_GUID_FMT,
  373. m_wszWriterName,
  374. GUID_PRINTF_ARG(m_InstanceID)
  375. );
  376. // save app level
  377. m_nLevel = nLevel;
  378. // save timeout
  379. m_dwTimeoutFreeze = dwTimeoutFreeze;
  380. // setup thread mutex
  381. m_hmtxTimerThread = CreateMutex(NULL, FALSE, NULL);
  382. if (m_hmtxTimerThread == NULL)
  383. ft.Throw
  384. (
  385. VSSDBG_WRITER,
  386. E_OUTOFMEMORY,
  387. L"Failure to create mutex object due to error %d.",
  388. GetLastError()
  389. );
  390. // setup event used to control the timer thread
  391. SetupEvent(&m_hevtTimerThread);
  392. // Initialize the diagnose tool
  393. m_diag.Initialize(m_wszWriterName);
  394. // Mark the writer as initialized
  395. m_bInitialized = true;
  396. }
  397. // start a sequence
  398. // critical section (m_cs) must be locked upone entry to this routine
  399. void CVssWriterImpl::BeginSequence
  400. (
  401. IN CVssID &SnapshotSetId
  402. )
  403. {
  404. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterImpl::BeginSequence");
  405. AssertLocked();
  406. // terminate timer thread if it is still operating
  407. TerminateTimerThread();
  408. // setup current snapshot set id
  409. m_CurrentSnapshotSetId = SnapshotSetId;
  410. BS_ASSERT(m_bOnAbortPermitted == false);
  411. // initialize writer state for this snapshot set
  412. m_writerstate.InitializeCurrentState(SnapshotSetId);
  413. // indicate we are currently in a snapshot sequence.
  414. m_bSequenceInProgress = true;
  415. }
  416. // Reset the sequence-related data members
  417. // critical section must be locked prior to entering this state
  418. void CVssWriterImpl::ResetSequence(bool bCalledFromTimerThread)
  419. {
  420. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterImpl::ResetSequence");
  421. AssertLocked();
  422. // save current state to stack of previous snapshot set states
  423. m_writerstate.PushCurrentState();
  424. // indicate we are no longer within a sequence
  425. m_bSequenceInProgress = false;
  426. // abort is no longer permitted
  427. m_bOnAbortPermitted = false;
  428. // reset volumes array
  429. m_nVolumesCount = 0;
  430. delete[] m_ppwszVolumesArray;
  431. m_ppwszVolumesArray = NULL;
  432. ::VssFreeString(m_pwszLocalVolumeNameList);
  433. m_CurrentSnapshotSetId = GUID_NULL;
  434. // if bCalledFromTimerThread is true, this means that the timer
  435. // thread is causing the sequence to be reset. We are in the timer
  436. // thread already and it will terminate upon completion of this call
  437. // so we shouldn't try causing it to terminate again.
  438. if (!bCalledFromTimerThread)
  439. TerminateTimerThread();
  440. }
  441. // indicate why the writer failed
  442. HRESULT CVssWriterImpl::SetWriterFailure(HRESULT hr)
  443. {
  444. // validate failure is one that is allowed
  445. if (hr != VSS_E_WRITERERROR_TIMEOUT &&
  446. hr != VSS_E_WRITERERROR_RETRYABLE &&
  447. hr != VSS_E_WRITERERROR_NONRETRYABLE &&
  448. hr != VSS_E_WRITERERROR_OUTOFRESOURCES &&
  449. hr != VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT)
  450. return E_INVALIDARG;
  451. // set failure
  452. m_writerstate.SetCurrentFailure(hr);
  453. return S_OK;
  454. }
  455. // determine if path specified is on one of the volumes that is snapshot
  456. bool CVssWriterImpl::IsPathAffected
  457. (
  458. IN LPCWSTR wszPath
  459. ) const
  460. {
  461. // Test the status
  462. if (!m_bSequenceInProgress)
  463. return false;
  464. // check for empty volume count
  465. if (m_nVolumesCount == 0)
  466. return false;
  467. // Get the volume mount point
  468. WCHAR wszVolumeMP[MAX_PATH];
  469. BOOL bRes = ::GetVolumePathNameW(wszPath, wszVolumeMP, MAX_PATH);
  470. if (!bRes)
  471. return false;
  472. // Get the volume name
  473. WCHAR wszVolumeName[MAX_PATH];
  474. bRes = ::GetVolumeNameForVolumeMountPointW(wszVolumeMP, wszVolumeName, MAX_PATH);
  475. if (!bRes)
  476. return false;
  477. // Search to see if that volume is within snapshotted volumes
  478. for (int nIndex = 0; nIndex < m_nVolumesCount; nIndex++)
  479. {
  480. BS_ASSERT(m_ppwszVolumesArray[nIndex]);
  481. if (::wcscmp(wszVolumeName, m_ppwszVolumesArray[nIndex]) == 0)
  482. return true;
  483. }
  484. return false;
  485. }
  486. // obtain IVssWriterCallback from IDispatch pointer
  487. // caller is responsible for releasing interface that is returned
  488. void CVssWriterImpl::GetCallback
  489. (
  490. IN IDispatch *pWriterCallback,
  491. OUT IVssWriterCallback **ppCallback,
  492. IN BOOL bAllowImpersonate
  493. )
  494. {
  495. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterImpl::GetCallback");
  496. // check that pointer is supplied
  497. BS_ASSERT(pWriterCallback != NULL);
  498. // try QueryInterface for IVssWriterCallback interface
  499. ft.hr = pWriterCallback->SafeQI(IVssWriterCallback, ppCallback);
  500. if (FAILED(ft.hr))
  501. {
  502. // If this is a RPC error then the
  503. // requestor might died in the meantime (bug 526472)
  504. if (ft.HrInFacility(FACILITY_RPC))
  505. {
  506. if (m_writerstate.GetCurrentFailure() == S_OK)
  507. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_RETRYABLE);
  508. ft.LogError(VSS_ERROR_RPC_IVSSWRITERCALLBACK, VSSDBG_WRITER << ft.hr);
  509. ft.Throw
  510. (
  511. VSSDBG_WRITER,
  512. E_UNEXPECTED,
  513. L"Error querying for IVssWriterCallback interface. hr = 0x%08lx",
  514. ft.hr
  515. );
  516. }
  517. else // this is a different failure
  518. {
  519. if (m_writerstate.GetCurrentFailure() == S_OK)
  520. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_NONRETRYABLE);
  521. ft.LogError(VSS_ERROR_QI_IVSSWRITERCALLBACK, VSSDBG_WRITER << ft.hr);
  522. ft.Throw
  523. (
  524. VSSDBG_WRITER,
  525. E_UNEXPECTED,
  526. L"Error querying for IVssWriterCallback interface. hr = 0x%08lx",
  527. ft.hr
  528. );
  529. }
  530. }
  531. if ( !bAllowImpersonate )
  532. {
  533. ft.hr = CoSetProxyBlanket
  534. (
  535. *ppCallback,
  536. RPC_C_AUTHN_DEFAULT,
  537. RPC_C_AUTHZ_DEFAULT,
  538. NULL,
  539. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  540. RPC_C_IMP_LEVEL_IDENTIFY,
  541. NULL,
  542. EOAC_NONE
  543. );
  544. // note E_NOINTERFACE means that the pWriterCallback is a in-proc callback
  545. // and there is no proxy
  546. if (FAILED(ft.hr) && ft.hr != E_NOINTERFACE)
  547. {
  548. if (m_writerstate.GetCurrentFailure() == S_OK)
  549. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_NONRETRYABLE);
  550. ft.LogError(VSS_ERROR_BLANKET_FAILED, VSSDBG_WRITER << ft.hr);
  551. ft.Throw
  552. (
  553. VSSDBG_WRITER,
  554. E_UNEXPECTED,
  555. L"Call to CoSetProxyBlanket failed. hr = 0x%08lx", ft.hr
  556. );
  557. }
  558. }
  559. }
  560. // create basic writer metadata for OnIdentify method
  561. CVssCreateWriterMetadata *CVssWriterImpl::CreateBasicWriterMetadata()
  562. {
  563. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterImpl::CreateBasicWriterMetadata");
  564. // create object supporting IVssCreateMetadata interface
  565. CVssCreateWriterMetadata *pMetadata = new CVssCreateWriterMetadata;
  566. if (pMetadata == NULL)
  567. {
  568. // indicate we failed due to an out of resources failure
  569. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_OUTOFRESOURCES);
  570. ft.Throw
  571. (
  572. VSSDBG_WRITER,
  573. E_OUTOFMEMORY,
  574. L"Cannot create CVssCreateWriterMetadata due to allocation failure."
  575. );
  576. }
  577. // call initialize to create IDENTIFICATION section
  578. ft.hr = pMetadata->Initialize
  579. (
  580. m_InstanceID,
  581. m_WriterID,
  582. m_wszWriterName,
  583. m_usage,
  584. m_source
  585. );
  586. if (ft.HrFailed())
  587. {
  588. // indicate that we failed due to an out of resources failure
  589. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_OUTOFRESOURCES);
  590. delete pMetadata;
  591. ft.Throw
  592. (
  593. VSSDBG_WRITER,
  594. ft.hr,
  595. L"CVssCreateWriterMetadata::Initialize failed. hr = 0x%08lx",
  596. ft.hr
  597. );
  598. }
  599. // return object
  600. return pMetadata;
  601. }
  602. static LPCWSTR x_wszElementRoot = L"root";
  603. static LPCWSTR x_wszElementWriterComponents = L"WRITER_COMPONENTS";
  604. // get writer components for OnPrepareBackup, OnBackupComplete, and OnPostRestore
  605. // methods
  606. void CVssWriterImpl::InternalGetWriterComponents
  607. (
  608. IN IVssWriterCallback *pCallback,
  609. OUT IVssWriterComponentsInt **ppWriter,
  610. IN bool bWriteable,
  611. IN bool bInRestore
  612. )
  613. {
  614. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterImpl::InternalGetWriterComponents");
  615. BS_ASSERT(pCallback);
  616. BS_ASSERT(ppWriter);
  617. *ppWriter = NULL;
  618. // call GetContent callback method on the backup application
  619. CComBSTR bstrId(bInRestore ? m_WriterID : m_InstanceID);
  620. if (!bstrId)
  621. {
  622. // indicate we failed due to an out of resources failure
  623. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_OUTOFRESOURCES);
  624. ft.Throw
  625. (
  626. VSSDBG_WRITER,
  627. E_OUTOFMEMORY,
  628. L"Cannot allocate instance Id string"
  629. );
  630. }
  631. ft.hr = pCallback->GetBackupState
  632. (
  633. &m_bBootableSystemStateBackup,
  634. &m_bComponentsSelected,
  635. &m_backupType,
  636. &m_bPartialFileSupport,
  637. &m_lContext
  638. );
  639. if (ft.HrFailed())
  640. {
  641. // if GetBackupState failed assumed that it might work if the
  642. // backup is retried.
  643. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_RETRYABLE);
  644. ft.Throw
  645. (
  646. VSSDBG_WRITER,
  647. ft.hr,
  648. L"IVssWriterCallback::GetBackupState failed. hr = 0x%08lx",
  649. ft.hr
  650. );
  651. }
  652. ft.hr = pCallback->GetRestoreState
  653. (
  654. &m_restoreType
  655. );
  656. if (ft.HrFailed())
  657. {
  658. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_RETRYABLE);
  659. ft.Throw
  660. (
  661. VSSDBG_WRITER,
  662. ft.hr,
  663. L"IVssWriterCallback::GetRestoreState failed. hr = 0x%08lx",
  664. ft.hr
  665. );
  666. }
  667. CComBSTR bstrWriterComponentsDoc;
  668. ft.hr = pCallback->GetContent(bstrId, &bstrWriterComponentsDoc);
  669. if (ft.HrFailed())
  670. {
  671. // if GetContent failed assume that the backup might work if
  672. // the backup was retried
  673. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_RETRYABLE);
  674. ft.Throw
  675. (
  676. VSSDBG_WRITER,
  677. ft.hr,
  678. L"Cannot get WRITER_COMPONENTS document. hr = 0x%08lx",
  679. ft.hr
  680. );
  681. }
  682. if (ft.hr == S_FALSE)
  683. {
  684. // reset status code
  685. ft.hr = S_OK;
  686. *ppWriter = (IVssWriterComponentsInt *) new CVssNULLWriterComponents
  687. (
  688. m_InstanceID,
  689. m_WriterID
  690. );
  691. if (*ppWriter == NULL)
  692. {
  693. // indicate that the writer failed due to an out of resources condition
  694. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_OUTOFRESOURCES);
  695. ft.Throw (VSSDBG_WRITER, E_OUTOFMEMORY, L"Can't allocate CVssWriterComponents object");
  696. }
  697. (*ppWriter)->AddRef();
  698. }
  699. else
  700. {
  701. CXMLDocument doc;
  702. if (!doc.LoadFromXML(bstrWriterComponentsDoc) ||
  703. !doc.FindElement(x_wszElementRoot, true))
  704. {
  705. // if the XML document is not valid then assume that the backup
  706. // application is broken. The backup should not be retried.
  707. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_NONRETRYABLE);
  708. ft.LogError(VSS_ERROR_WRITER_COMPONENTS_CORRUPT, VSSDBG_WRITER);
  709. ft.Throw
  710. (
  711. VSSDBG_WRITER,
  712. VSS_E_CORRUPT_XML_DOCUMENT,
  713. L"Internally transferred WRITER_COMPONENTS document is invalid"
  714. );
  715. }
  716. doc.SetToplevel();
  717. *ppWriter = (IVssWriterComponentsInt *)
  718. new CVssWriterComponents
  719. (
  720. doc.GetCurrentNode(),
  721. doc.GetInterface(),
  722. bWriteable,
  723. false,
  724. m_writerstate.IsInRestore()
  725. );
  726. if (*ppWriter == NULL)
  727. {
  728. // indicate that the writer failed due to an out of resources condition
  729. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_OUTOFRESOURCES);
  730. ft.Throw (VSSDBG_WRITER, E_OUTOFMEMORY, L"Can't allocate CVssWriterComponents object");
  731. }
  732. (*ppWriter)->AddRef();
  733. ft.hr = (*ppWriter)->Initialize(true);
  734. if (ft.HrFailed())
  735. {
  736. // if Initialize failed, assume that the failure is due to an
  737. // out of resources conditition.
  738. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_OUTOFRESOURCES);
  739. (*ppWriter)->Release();
  740. *ppWriter = NULL;
  741. ft.Throw
  742. (
  743. VSSDBG_WRITER,
  744. ft.hr,
  745. L"Failed to initialize WRITER_COMPONENTS document. hr = 0x%08lx",
  746. ft.hr
  747. );
  748. }
  749. }
  750. }
  751. // called when entering a state to verify whether this state can be
  752. // validly entered and generate appropriate error if not.
  753. // this routine always obtains the critical section. If this routine
  754. // is called then LeaveState must also be called in order to free the
  755. // critical section.
  756. bool CVssWriterImpl::EnterState
  757. (
  758. IN const CVssWriterImplStateMachine &vwsm,
  759. IN BSTR bstrSnapshotSetId
  760. ) throw(HRESULT)
  761. {
  762. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterImpl::EnterState");
  763. CVssID id;
  764. // obtain lock just in case next call throws
  765. // no matter how this routine exits, the critical section must be locked
  766. Lock();
  767. // initialize id to snapshot set id
  768. id.Initialize(ft, (LPWSTR)bstrSnapshotSetId, E_OUTOFMEMORY);
  769. // Note:
  770. // 1. There is no check for fail-at-identify because if the writer failed at Identify,
  771. // then the writer won't get anymore events from the requestor object that sent the identify
  772. // 2. Other backup sequences should not be disturbed by a writer failing at identify
  773. // for another requestor
  774. if (!m_bSequenceInProgress)
  775. {
  776. if (!vwsm.m_bBeginningState)
  777. // not a beginning state. Sequence must have been
  778. // interrupted.
  779. return false;
  780. else
  781. {
  782. // BUG 219757 - PrepareForSnapshot, etc. cannot be
  783. // called for the same Snapshot Set if PrepareForBackup failed
  784. // Also we assume here that each new sequence have an UNIQUE SSID.
  785. // This check is needed since the PrepareForBackup phase is optional
  786. // and can be skipped sometimes. Therefore we need to distinguish between
  787. // the case when PrepareForBackup was skipped and the case when PrepareForBackup
  788. // was called and failed.
  789. // Search for a previous sequence with the same Snapshot Set ID.
  790. // If found (this means that a PrepareForBackup was called),
  791. // then reject the call.
  792. if (m_writerstate.IsSnapshotSetIdValid(id))
  793. return false;
  794. // it is a beginning state, start the sequence
  795. BeginSequence(id);
  796. return true;
  797. }
  798. }
  799. else
  800. {
  801. if (vwsm.m_bSuccessiveState)
  802. {
  803. // it is a valid non-beginning state in the sequence
  804. if (id != m_CurrentSnapshotSetId)
  805. {
  806. // if snapshot set id doesn't match and this is not
  807. // a beginning state, then the event must be ignored.
  808. // We must have aborted the sequence it references.
  809. if (!vwsm.m_bBeginningState)
  810. return false;
  811. }
  812. else
  813. {
  814. // make sure current state matches previous state
  815. // of state we are about to enter
  816. return m_writerstate.GetCurrentState() == vwsm.m_previousState;
  817. }
  818. }
  819. }
  820. // We are trying to start a new sequence.
  821. // This means that the previous sequence was not properly
  822. // terminated. Abort the previous sequence and then
  823. // start a new one.
  824. ft.Trace(VSSDBG_WRITER,
  825. L"*** Warning ***: Writer %s with ID "WSTR_GUID_FMT
  826. L"attempts to reset the previous sequence with Snapshot Set ID "WSTR_GUID_FMT
  827. L". Current state = %d",
  828. m_wszWriterName, GUID_PRINTF_ARG(m_InstanceID), GUID_PRINTF_ARG(m_CurrentSnapshotSetId), (INT)m_writerstate.GetCurrentState());
  829. DoAbort(false);
  830. BeginSequence(id);
  831. return true;
  832. }
  833. // do abort on failure of the sequence
  834. // critical section must be locked prior to entering this state
  835. void CVssWriterImpl::DoAbort
  836. (
  837. IN bool bCalledFromTimerThread,
  838. IN BSTR bstrSnapshotSetId
  839. )
  840. {
  841. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterImpl::DoAbort");
  842. AssertLocked();
  843. // do nothing if in a sequence
  844. if (!m_bSequenceInProgress)
  845. return;
  846. BS_ASSERT(m_pWriter);
  847. // catch any exceptions so that we properly reset the
  848. // sequence
  849. try
  850. {
  851. // if the snapshot set doesn't match, don't allow an abort
  852. if (bstrSnapshotSetId)
  853. {
  854. CVssID id;
  855. id.Initialize(ft, bstrSnapshotSetId, E_OUTOFMEMORY);
  856. if (id != m_writerstate.GetCurrentSnapshotSet())
  857. return;
  858. }
  859. // call writer's abort function (depending on the state)
  860. switch(m_writerstate.GetCurrentState())
  861. {
  862. default:
  863. // Unhandled state?
  864. BS_ASSERT(false);
  865. break;
  866. case VSS_WS_FAILED_AT_BACKUP_COMPLETE:
  867. case VSS_WS_FAILED_AT_PRE_RESTORE:
  868. case VSS_WS_FAILED_AT_POST_RESTORE:
  869. // Abort not permitted on these states
  870. BS_ASSERT(m_bOnAbortPermitted == false);
  871. break;
  872. case VSS_WS_STABLE:
  873. // This is possible since you may get an Abort
  874. // in (or after) PrepareForBackup (BUG # 301686)
  875. BS_ASSERT(m_bOnAbortPermitted == true);
  876. break;
  877. case VSS_WS_WAITING_FOR_POST_SNAPSHOT:
  878. case VSS_WS_FAILED_AT_POST_SNAPSHOT:
  879. case VSS_WS_WAITING_FOR_FREEZE:
  880. case VSS_WS_WAITING_FOR_THAW:
  881. case VSS_WS_WAITING_FOR_BACKUP_COMPLETE:
  882. case VSS_WS_FAILED_AT_THAW:
  883. case VSS_WS_FAILED_AT_PREPARE_BACKUP:
  884. case VSS_WS_FAILED_AT_PREPARE_SNAPSHOT:
  885. case VSS_WS_FAILED_AT_FREEZE:
  886. // Fixing bug 225936
  887. if (m_bOnAbortPermitted)
  888. m_pWriter->OnAbort();
  889. else
  890. ft.Trace(VSSDBG_WRITER, L"Abort skipped in state %d", m_writerstate.GetCurrentState());
  891. m_bOnAbortPermitted = false;
  892. break;
  893. }
  894. }
  895. VSS_STANDARD_CATCH(ft)
  896. if (ft.HrFailed())
  897. ft.Trace
  898. (
  899. VSSDBG_WRITER,
  900. L"OnAbort failed. hr = 0x%08lx",
  901. ft.hr
  902. );
  903. // set appropriate failure state
  904. switch(m_writerstate.GetCurrentState())
  905. {
  906. default:
  907. m_writerstate.SetCurrentState(VSS_WS_UNKNOWN);
  908. BS_ASSERT(false);
  909. break;
  910. case VSS_WS_FAILED_AT_PREPARE_BACKUP:
  911. case VSS_WS_FAILED_AT_PREPARE_SNAPSHOT:
  912. case VSS_WS_FAILED_AT_FREEZE:
  913. case VSS_WS_FAILED_AT_THAW:
  914. case VSS_WS_FAILED_AT_POST_SNAPSHOT:
  915. case VSS_WS_FAILED_AT_BACKUP_COMPLETE:
  916. case VSS_WS_FAILED_AT_PRE_RESTORE:
  917. case VSS_WS_FAILED_AT_POST_RESTORE:
  918. // don't change state if already in a failure state
  919. break;
  920. case VSS_WS_STABLE:
  921. // if current state is STABLE then it means
  922. // we were in PrepareBackup
  923. m_writerstate.SetCurrentState(VSS_WS_FAILED_AT_PREPARE_BACKUP);
  924. break;
  925. case VSS_WS_WAITING_FOR_FREEZE:
  926. // if we were waiting for freeze then we failed
  927. // between PrepareSync and Freeze
  928. m_writerstate.SetCurrentState(VSS_WS_FAILED_AT_PREPARE_SNAPSHOT);
  929. break;
  930. case VSS_WS_WAITING_FOR_THAW:
  931. // if we were waiting for thaw then we failed
  932. // between freeze and thaw
  933. m_writerstate.SetCurrentState(VSS_WS_FAILED_AT_FREEZE);
  934. break;
  935. case VSS_WS_WAITING_FOR_POST_SNAPSHOT:
  936. // if we were waiting for completion then
  937. // we failed after thaw.
  938. m_writerstate.SetCurrentState(VSS_WS_FAILED_AT_THAW);
  939. break;
  940. case VSS_WS_WAITING_FOR_BACKUP_COMPLETE:
  941. // if we were waiting for completion then
  942. // we failed after thaw.
  943. m_writerstate.SetCurrentState(VSS_WS_FAILED_AT_POST_SNAPSHOT);
  944. break;
  945. }
  946. if (bCalledFromTimerThread && m_writerstate.GetCurrentFailure() == S_OK)
  947. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_TIMEOUT);
  948. // reset sequence
  949. ResetSequence(bCalledFromTimerThread);
  950. }
  951. // exit a state. This routine must be called with the critical
  952. // section acquired. For a state, EnterState is called first, then work is
  953. // done, then LeaveState is called. This routine will set the state upon
  954. // exit and possibly reset the snapshot sequence if we are at the end of the
  955. // sequence or the sequence is aborted.
  956. void CVssWriterImpl::LeaveState
  957. (
  958. IN const CVssWriterImplStateMachine &vwsm, // current state
  959. IN bool bSucceeded // did operation succeed
  960. )
  961. {
  962. AssertLocked();
  963. m_writerstate.ExitOperation();
  964. // don't change state or call abort if we are not in a sequence
  965. if (m_bSequenceInProgress)
  966. {
  967. m_writerstate.SetCurrentState
  968. (bSucceeded ? vwsm.m_successfulExitState
  969. : vwsm.m_failureExitState);
  970. // call abort on failure when we are not in the exit state
  971. if ((!bSucceeded || m_writerstate.GetCurrentFailure() == VSS_E_WRITER_NOT_RESPONDING) &&
  972. !vwsm.m_bResetSequenceOnLeave)
  973. DoAbort(false);
  974. else if (vwsm.m_bResetSequenceOnLeave)
  975. // if sequence ends at this state (THAW) then
  976. // reset variables
  977. ResetSequence(false);
  978. }
  979. Unlock();
  980. }
  981. // arguments to timer function
  982. class CVssTimerArgs
  983. {
  984. private:
  985. CVssTimerArgs();
  986. public:
  987. CVssTimerArgs(CVssWriterImpl *pWriter, VSS_ID id) :
  988. m_snapshotSetId(id),
  989. m_pWriter(pWriter)
  990. {
  991. }
  992. // snapshot set that we are monitoring
  993. VSS_ID m_snapshotSetId;
  994. // pointer to writer
  995. CVssWriterImpl *m_pWriter;
  996. };
  997. // timer thread startup routine
  998. DWORD CVssWriterImpl::StartTimerThread(void *pv)
  999. {
  1000. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterImpl::StartTimerThread");
  1001. CVssTimerArgs *pArgs = (CVssTimerArgs *) pv;
  1002. BS_ASSERT(pArgs);
  1003. BS_ASSERT(pArgs->m_pWriter);
  1004. bool bCoInitializeSucceeded = false;
  1005. try
  1006. {
  1007. // coinitialize thread
  1008. ft.hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  1009. if (ft.HrFailed())
  1010. {
  1011. pArgs->m_pWriter->m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_OUTOFRESOURCES);
  1012. ft.TranslateError
  1013. (
  1014. VSSDBG_WRITER,
  1015. ft.hr,
  1016. L"CoInitializeEx"
  1017. );
  1018. }
  1019. bCoInitializeSucceeded = true;
  1020. // call timer func
  1021. pArgs->m_pWriter->TimerFunc(pArgs->m_snapshotSetId);
  1022. }
  1023. VSS_STANDARD_CATCH(ft)
  1024. if (bCoInitializeSucceeded)
  1025. CoUninitialize();
  1026. // delete timer arguments
  1027. delete pArgs;
  1028. return 0;
  1029. }
  1030. // function implementing timer functionality
  1031. void CVssWriterImpl::TimerFunc(VSS_ID snapshotSetId)
  1032. {
  1033. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterImpl::TimerFunc");
  1034. // wait on event to insure that only one timer is active at
  1035. // any point in time
  1036. if (WaitForSingleObject(m_hmtxTimerThread, INFINITE) == WAIT_FAILED)
  1037. {
  1038. DWORD dwErr = GetLastError();
  1039. ft.Trace(VSSDBG_WRITER, L"WaitForSingleObject failed with error %d", dwErr);
  1040. BS_ASSERT(FALSE && "WaitForSingleObject failed");
  1041. }
  1042. // reset timer event
  1043. if (!ResetEvent(m_hevtTimerThread))
  1044. {
  1045. DWORD dwErr = GetLastError();
  1046. ft.Trace(VSSDBG_WRITER, L"ResetEvent failed with error %d", dwErr);
  1047. BS_ASSERT(FALSE && "ResetEvent failed");
  1048. }
  1049. Lock();
  1050. CVssAutoDiagLogger logger(m_writerstate, VSS_IN_BKGND_FREEZE_THREAD, snapshotSetId);
  1051. // make sure that we are still in a snapshot sequence
  1052. if (!m_bSequenceInProgress || snapshotSetId != GetCurrentSnapshotSetId())
  1053. {
  1054. // not in sequence, exit function
  1055. Unlock();
  1056. // allow another timer thread to start
  1057. ReleaseMutex(m_hmtxTimerThread);
  1058. return;
  1059. }
  1060. // initial command is to abort the current sequence on timeout
  1061. m_command = VSS_TC_ABORT_CURRENT_SEQUENCE;
  1062. Unlock();
  1063. DWORD dwTimeout = m_dwTimeoutFreeze;
  1064. if (WaitForSingleObject(m_hevtTimerThread, dwTimeout) == WAIT_FAILED)
  1065. {
  1066. ft.Trace
  1067. (
  1068. VSSDBG_WRITER,
  1069. L"Wait in timer thread failed due to reason %d.",
  1070. GetLastError()
  1071. );
  1072. // allow another thread to start
  1073. ReleaseMutex(m_hmtxTimerThread);
  1074. return;
  1075. }
  1076. CVssWriterImplLock lock(this);
  1077. if (m_command != VSS_TC_TERMINATE_THREAD)
  1078. {
  1079. BS_ASSERT(m_command == VSS_TC_ABORT_CURRENT_SEQUENCE);
  1080. // cause current sequence to abort
  1081. ft.Trace(VSSDBG_WRITER, L"Aborting due to timeout\n");
  1082. DoAbort(true);
  1083. }
  1084. // allow another timer thread to start
  1085. ReleaseMutex(m_hmtxTimerThread);
  1086. }
  1087. /////////////////////////////////////////////////////////////////////////////
  1088. // IVssWriter implementation
  1089. STDMETHODIMP CVssWriterImpl::RequestWriterInfo
  1090. (
  1091. IN BSTR bstrSnapshotSetId,
  1092. IN BOOL bWriterMetadata,
  1093. IN BOOL bWriterState,
  1094. IN IDispatch* pWriterCallback
  1095. )
  1096. {
  1097. CVssFunctionTracer ft( VSSDBG_WRITER, L"CVssWriterImpl::RequestWriterInfo" );
  1098. // created metadata, deleted on exit from routine
  1099. CVssCreateWriterMetadata *pcwm = NULL;
  1100. try
  1101. {
  1102. // validate that the flags make sense
  1103. if (bWriterMetadata && bWriterState ||
  1104. !bWriterMetadata && !bWriterState)
  1105. ft.Throw(VSSDBG_WRITER, E_INVALIDARG, L"Incorrect flags");
  1106. // if we are requesting writer state then we must have a snapshot
  1107. // set id
  1108. if (bWriterState && bstrSnapshotSetId == NULL)
  1109. ft.Throw(VSSDBG_WRITER, E_INVALIDARG, L"NULL required input parameter.");
  1110. if (pWriterCallback == NULL)
  1111. ft.Throw(VSSDBG_WRITER, E_INVALIDARG, L"NULL required input parameter.");
  1112. if (!IsBackupOperator())
  1113. ft.Throw(VSSDBG_WRITER, E_ACCESSDENIED, L"Backup Operator privileges are not set");
  1114. _retry_OnIdentify:
  1115. if (bWriterMetadata)
  1116. {
  1117. // obtain writer metadata
  1118. // First, we prevent OnIdentify to be issued between Freeze and Thaw
  1119. DWORD dwTimeout = m_dwTimeoutFreeze;
  1120. if (WaitForSingleObject(m_hevtTimerThread, dwTimeout) == WAIT_FAILED)
  1121. ft.Trace(VSSDBG_WRITER,L"Wait failed due to reason %d.",GetLastError());
  1122. // MTA synchronization: The critical section will be left automatically
  1123. // at the end of scope.
  1124. CVssWriterImplLock lock(this);
  1125. // Still, do not allow OnIdentify to be called between Freeze and Thaw
  1126. // - There is an extremely small window where Freeze can be send after
  1127. // WaitForSingleObject test passed but before acquiring the lock
  1128. VSWRITER_STATE state;
  1129. m_writerstate.GetStateForSnapshot(GUID_NULL, state);
  1130. // A writer cannot stay forever in this state...
  1131. // (the background timer thread will reset the current VSS_WS_WAITING_FOR_THAW state)
  1132. if ((state.m_state == VSS_WS_WAITING_FOR_THAW) &&
  1133. (state.m_idSnapshotSet != GUID_NULL))
  1134. goto _retry_OnIdentify;
  1135. CVssAutoDiagLogger logger(m_writerstate, VSS_IN_IDENTIFY);
  1136. try
  1137. {
  1138. // get IVssWriterCallback interface
  1139. CComPtr<IVssWriterCallback> pCallback;
  1140. GetCallback(pWriterCallback, &pCallback);
  1141. // create basic metadata using initialization parameters
  1142. pcwm = CreateBasicWriterMetadata();
  1143. // call writer's OnIdentify method to get more metadata
  1144. BS_ASSERT(m_pWriter);
  1145. bool bSucceeded;
  1146. try
  1147. {
  1148. bSucceeded = m_pWriter->OnIdentify
  1149. (
  1150. (IVssCreateWriterMetadata *) pcwm
  1151. );
  1152. }
  1153. catch(...)
  1154. {
  1155. ft.Trace(VSSDBG_WRITER, L"Writer's OnIdentify method threw and exception.");
  1156. throw;
  1157. }
  1158. if (!bSucceeded)
  1159. {
  1160. // indicate failure if writer fails OnIdentify
  1161. ft.Throw(VSSDBG_WRITER, S_FALSE, L"Writer's OnIdentify method returned false.");
  1162. }
  1163. CComBSTR bstrXML;
  1164. CComBSTR bstrInstanceId(m_InstanceID);
  1165. CComBSTR bstrWriterId(m_WriterID);
  1166. CComBSTR bstrWriterName(m_wszWriterName);
  1167. if (!bstrInstanceId ||
  1168. !bstrWriterId ||
  1169. !bstrWriterName)
  1170. ft.Throw(VSSDBG_WRITER, E_OUTOFMEMORY, L"Couldn't allocate memory for ids or name");
  1171. // save WRITER_METADATA document as XML string
  1172. ft.hr = pcwm->SaveAsXML(&bstrXML);
  1173. if (FAILED(ft.hr))
  1174. ft.Throw
  1175. (
  1176. VSSDBG_WRITER,
  1177. E_OUTOFMEMORY,
  1178. L"Cannot save XML document as string. hr = 0x%08lx",
  1179. ft.hr
  1180. );
  1181. // callback through ExposeWriterMetadata method
  1182. try
  1183. {
  1184. ft.hr = pCallback->ExposeWriterMetadata
  1185. (
  1186. bstrInstanceId,
  1187. bstrWriterId,
  1188. bstrWriterName,
  1189. bstrXML
  1190. );
  1191. }
  1192. catch(...)
  1193. {
  1194. ft.Trace(VSSDBG_WRITER, L"IVssWriterCallback::ExposeWriterMetadata threw an exception.");
  1195. throw;
  1196. }
  1197. }
  1198. catch(...)
  1199. {
  1200. }
  1201. }
  1202. else
  1203. {
  1204. // get writer state
  1205. CComBSTR bstrInstanceId(m_InstanceID);
  1206. if (!bstrInstanceId)
  1207. ft.Throw(VSSDBG_WRITER, E_OUTOFMEMORY, L"Couldn't allocate memory for ids or name");
  1208. CVssID id;
  1209. id.Initialize(ft, (LPCWSTR) bstrSnapshotSetId, E_INVALIDARG);
  1210. CVssAutoDiagLogger logger(m_writerstate, VSS_IN_GETSTATE, id);
  1211. // get IVssWriterCallback interface
  1212. CComPtr<IVssWriterCallback> pCallback;
  1213. GetCallback(pWriterCallback, &pCallback);
  1214. VSWRITER_STATE state;
  1215. _retry:
  1216. m_writerstate.GetStateForSnapshot(id, state);
  1217. // Special handling for the case where the writer is in the middle of operation
  1218. if (state.m_bInOperation)
  1219. {
  1220. if (state.m_state != VSS_WS_FAILED_AT_PREPARE_BACKUP &&
  1221. state.m_state != VSS_WS_FAILED_AT_PREPARE_SNAPSHOT &&
  1222. state.m_state != VSS_WS_FAILED_AT_FREEZE &&
  1223. state.m_state != VSS_WS_FAILED_AT_THAW)
  1224. {
  1225. state.m_hrWriterFailure = VSS_E_WRITER_NOT_RESPONDING;
  1226. switch(state.m_currentOperation)
  1227. {
  1228. default:
  1229. state.m_state = VSS_WS_UNKNOWN;
  1230. BS_ASSERT(false);
  1231. break;
  1232. case VSS_IN_PREPAREBACKUP:
  1233. state.m_state = VSS_WS_FAILED_AT_PREPARE_BACKUP;
  1234. break;
  1235. case VSS_IN_PREPARESNAPSHOT:
  1236. state.m_state = VSS_WS_FAILED_AT_PREPARE_SNAPSHOT;
  1237. break;
  1238. case VSS_IN_FREEZE:
  1239. state.m_state = VSS_WS_FAILED_AT_FREEZE;
  1240. break;
  1241. case VSS_IN_THAW:
  1242. state.m_state = VSS_WS_FAILED_AT_THAW;
  1243. break;
  1244. case VSS_IN_POSTSNAPSHOT:
  1245. state.m_state = VSS_WS_FAILED_AT_POST_SNAPSHOT;
  1246. break;
  1247. case VSS_IN_BACKUPCOMPLETE:
  1248. state.m_state = VSS_WS_FAILED_AT_BACKUP_COMPLETE;
  1249. break;
  1250. case VSS_IN_PRERESTORE:
  1251. state.m_state = VSS_WS_FAILED_AT_PRE_RESTORE;
  1252. break;
  1253. case VSS_IN_POSTRESTORE:
  1254. state.m_state = VSS_WS_FAILED_AT_POST_RESTORE;
  1255. break;
  1256. case VSS_IN_BACKUPSHUTDOWN:
  1257. state.m_state = VSS_WS_UNKNOWN;
  1258. break;
  1259. }
  1260. if (!m_writerstate.SetNoResponseFailure(id, state))
  1261. goto _retry;
  1262. }
  1263. }
  1264. // call Backup's ExposeCurrentState callback method
  1265. try
  1266. {
  1267. ft.hr = pCallback->ExposeCurrentState
  1268. (
  1269. bstrInstanceId,
  1270. state.m_state,
  1271. state.m_hrWriterFailure
  1272. );
  1273. }
  1274. catch(...)
  1275. {
  1276. ft.Trace(VSSDBG_WRITER, L"IVssWriterCallback::ExposeCurrentState threw an exception");
  1277. throw;
  1278. }
  1279. }
  1280. }
  1281. VSS_STANDARD_CATCH(ft)
  1282. delete pcwm;
  1283. // Bug 255996
  1284. return S_OK;
  1285. }
  1286. // process PrepareForBackup event
  1287. STDMETHODIMP CVssWriterImpl::PrepareForBackup
  1288. (
  1289. IN BSTR bstrSnapshotSetId,
  1290. IN IDispatch* pWriterCallback
  1291. )
  1292. {
  1293. CVssFunctionTracer ft( VSSDBG_WRITER, L"CVssWriterImpl::PrepareForBackup" );
  1294. bool EnteredStateCalled = false;
  1295. try
  1296. {
  1297. // access check
  1298. if (!IsBackupOperator())
  1299. ft.Throw(VSSDBG_WRITER, E_ACCESSDENIED, L"Backup Operator privileges are not set");
  1300. if (pWriterCallback == NULL || bstrSnapshotSetId == NULL)
  1301. ft.Throw(VSSDBG_WRITER, E_INVALIDARG, L"NULL required input parameter.");
  1302. ft.Trace(VSSDBG_WRITER, L"\nReceived Event: PrepareForBackup\nParameters:\n");
  1303. ft.Trace(VSSDBG_WRITER, L"\tSnapshotSetID = %s\n", (LPWSTR)bstrSnapshotSetId);
  1304. CVssAutoDiagLogger logger(m_writerstate, VSS_IN_PREPAREBACKUP, bstrSnapshotSetId);
  1305. EnteredStateCalled = true; // At this point, EnterState will always be called
  1306. // enter PrepareForBackup state
  1307. if (!EnterState
  1308. (
  1309. s_rgWriterStates[s_ivwsmPrepareForBackup],
  1310. bstrSnapshotSetId
  1311. ))
  1312. {
  1313. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_RETRYABLE);
  1314. ft.Throw
  1315. (
  1316. VSSDBG_WRITER,
  1317. E_UNEXPECTED,
  1318. L"Couldn't properly begin sequence"
  1319. );
  1320. }
  1321. AssertLocked();
  1322. // indicate we are in an operation
  1323. m_writerstate.SetInOperation(VSS_IN_PREPAREBACKUP);
  1324. // get IVssWriterCallback interface
  1325. CComPtr<IVssWriterCallback> pCallback;
  1326. GetCallback(pWriterCallback, &pCallback);
  1327. // get IVssWriterComponentsExt interface
  1328. CComPtr<IVssWriterComponentsInt> pComponents;
  1329. InternalGetWriterComponents(pCallback, &pComponents, true, false);
  1330. BS_ASSERT(m_pWriter);
  1331. // call writer's OnPrepareBackup method
  1332. bool bResult;
  1333. try
  1334. {
  1335. bResult = m_pWriter->OnPrepareBackup(pComponents);
  1336. BS_ASSERT(m_bOnAbortPermitted == false);
  1337. m_bOnAbortPermitted = true;
  1338. }
  1339. catch(...)
  1340. {
  1341. ft.Trace(VSSDBG_WRITER, L"Writer's OnPrepareBackup method threw an exception");
  1342. if (m_writerstate.GetCurrentFailure() == S_OK)
  1343. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_NONRETRYABLE);
  1344. throw;
  1345. }
  1346. if (!bResult)
  1347. ft.Throw( VSSDBG_WRITER, E_UNEXPECTED, L"Writer rejected the preparebackup");
  1348. // save changes to components if any
  1349. if (pComponents)
  1350. SaveChangedComponents(pCallback, false, pComponents);
  1351. }
  1352. VSS_STANDARD_CATCH(ft)
  1353. // leave PrepareBackup state
  1354. if (EnteredStateCalled)
  1355. LeaveState(s_rgWriterStates[s_ivwsmPrepareForBackup], ft.HrSucceeded());
  1356. // Bug 255996
  1357. return S_OK;
  1358. }
  1359. // if the writer components were changed, save them back to the requestor's
  1360. // XML document.
  1361. void CVssWriterImpl::SaveChangedComponents
  1362. (
  1363. IN IVssWriterCallback *pCallback,
  1364. IN bool bRestore,
  1365. IN IVssWriterComponentsInt *pComponents
  1366. )
  1367. {
  1368. CVssFunctionTracer ft(VSSDBG_XML, L"CVssWriterImpl::SaveChangedComponents");
  1369. bool bChanged;
  1370. // determine if components are changed
  1371. ft.hr = pComponents->IsChanged(&bChanged);
  1372. BS_ASSERT(ft.hr == S_OK);
  1373. if (bChanged)
  1374. {
  1375. // get instance id
  1376. CComBSTR bstrWriterInstanceId(bRestore ? m_WriterID : m_InstanceID);
  1377. if (!bstrWriterInstanceId)
  1378. ft.Throw(VSSDBG_WRITER, E_OUTOFMEMORY, L"Couldn't allocate instance id string");
  1379. // get WRITER_COMPONENTS XML document
  1380. CComBSTR bstrWriterComponentsDocument;
  1381. ft.hr = pComponents->SaveAsXML(&bstrWriterComponentsDocument);
  1382. if (ft.HrFailed())
  1383. {
  1384. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_OUTOFRESOURCES);
  1385. ft.Throw
  1386. (
  1387. VSSDBG_WRITER,
  1388. E_OUTOFMEMORY,
  1389. L"Saving WRITER_COMPONENTS document as XML failed. hr = 0x%08lx",
  1390. ft.hr
  1391. );
  1392. }
  1393. // callback to set component in BACKUP_COMPONENTS document
  1394. try
  1395. {
  1396. ft.hr = pCallback->SetContent(bstrWriterInstanceId, bstrWriterComponentsDocument);
  1397. }
  1398. catch(...)
  1399. {
  1400. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_RETRYABLE);
  1401. ft.Trace(VSSDBG_WRITER, L"IVssWriterCallback::SetContent threw an exception.");
  1402. throw;
  1403. }
  1404. if (ft.HrFailed() && m_writerstate.GetCurrentFailure() == S_OK)
  1405. {
  1406. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_RETRYABLE);
  1407. ft.Throw
  1408. (
  1409. VSSDBG_WRITER,
  1410. ft.hr,
  1411. L"IVssWriterCallback::SetContent failed. hr = 0x%08lx",
  1412. ft.hr
  1413. );
  1414. }
  1415. }
  1416. }
  1417. // process PrepareForSnapshot event
  1418. STDMETHODIMP CVssWriterImpl::PrepareForSnapshot
  1419. (
  1420. IN BSTR bstrSnapshotSetId, // snapshot set id
  1421. IN BSTR bstrVolumeNamesList // list of volume names separated by ';'
  1422. )
  1423. {
  1424. CVssFunctionTracer ft( VSSDBG_WRITER, L"CVssWriterImpl::PrepareForSnapshot" );
  1425. bool EnterStateCalled = false;
  1426. try
  1427. {
  1428. // should only be called by coordinator
  1429. // check for admin privileges
  1430. if (!IsAdministrator())
  1431. ft.Throw(VSSDBG_WRITER, E_ACCESSDENIED, L"ADMIN privileges are not set");
  1432. if (bstrSnapshotSetId == NULL || bstrVolumeNamesList == NULL)
  1433. {
  1434. BS_ASSERT(false);
  1435. ft.Throw(VSSDBG_WRITER, E_INVALIDARG, L"A required in parameter is NULL.");
  1436. }
  1437. ft.Trace(VSSDBG_WRITER, L"\nReceived Event: PrepareForSnapshot\nParameters:\n");
  1438. ft.Trace(VSSDBG_WRITER, L"\tSnapshotSetID = %s\n", (LPWSTR)bstrSnapshotSetId);
  1439. ft.Trace(VSSDBG_WRITER, L"\tVolumeNamesList = %s\n", (LPWSTR)bstrVolumeNamesList);
  1440. CVssAutoDiagLogger logger(m_writerstate, VSS_IN_PREPARESNAPSHOT, bstrSnapshotSetId);
  1441. // enter PrepareForSnapshot state
  1442. EnterStateCalled = true;
  1443. if (!EnterState
  1444. (
  1445. s_rgWriterStates[s_ivwsmPrepareForSnapshot],
  1446. bstrSnapshotSetId
  1447. ))
  1448. {
  1449. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_RETRYABLE);
  1450. ft.Throw
  1451. (
  1452. VSSDBG_WRITER,
  1453. E_UNEXPECTED,
  1454. L"improper state transition"
  1455. );
  1456. }
  1457. AssertLocked();
  1458. // indicate that we are in an operation
  1459. m_writerstate.SetInOperation(VSS_IN_PREPARESNAPSHOT);
  1460. // Get the array of volume names
  1461. BS_ASSERT(m_pwszLocalVolumeNameList == NULL);
  1462. ::VssSafeDuplicateStr(ft, m_pwszLocalVolumeNameList, (LPWSTR)bstrVolumeNamesList);
  1463. // Get the number of volumes
  1464. BS_ASSERT(m_nVolumesCount == 0);
  1465. m_nVolumesCount = 0; // For safety
  1466. LPWSTR pwszVolumesToBeParsed = m_pwszLocalVolumeNameList;
  1467. // parse volume name string
  1468. while(true)
  1469. {
  1470. // get pointer to next volume
  1471. WCHAR* pwszNextVolume = ::wcstok(pwszVolumesToBeParsed, VSS_VOLUME_DELIMITERS);
  1472. pwszVolumesToBeParsed = NULL;
  1473. if (pwszNextVolume == NULL)
  1474. // no more volumes
  1475. break;
  1476. // skip if volume name is empty
  1477. if (pwszNextVolume[0] == L'\0')
  1478. continue;
  1479. // count of volumes
  1480. m_nVolumesCount++;
  1481. }
  1482. // make sure there is at least one volume
  1483. if (m_nVolumesCount == 0)
  1484. {
  1485. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_RETRYABLE);
  1486. ft.LogError(VSS_ERROR_EMPTY_SNAPSHOT_SET, VSSDBG_WRITER);
  1487. ft.Throw
  1488. (
  1489. VSSDBG_WRITER,
  1490. E_UNEXPECTED,
  1491. L"No volumes in the snapshot set"
  1492. );
  1493. }
  1494. // Allocate the array of pointers to volume names
  1495. BS_ASSERT(m_nVolumesCount > 0);
  1496. BS_ASSERT(m_ppwszVolumesArray == NULL);
  1497. m_ppwszVolumesArray = new LPWSTR[m_nVolumesCount];
  1498. if (m_ppwszVolumesArray == NULL)
  1499. {
  1500. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_OUTOFRESOURCES);
  1501. ft.Throw( VSSDBG_WRITER, E_OUTOFMEMORY, L"Memory allocation error");
  1502. }
  1503. //
  1504. // Copy the volume names into the array.
  1505. //
  1506. // re-copy the whole volume list
  1507. ::wcscpy(m_pwszLocalVolumeNameList, (LPWSTR)bstrVolumeNamesList);
  1508. // Fill the array by re-parsing the volume list.
  1509. INT nVolumesIndex = 0;
  1510. pwszVolumesToBeParsed = m_pwszLocalVolumeNameList;
  1511. while(true)
  1512. {
  1513. WCHAR* pwszNextVolume = ::wcstok(pwszVolumesToBeParsed, VSS_VOLUME_DELIMITERS);
  1514. pwszVolumesToBeParsed = NULL;
  1515. if (pwszNextVolume == NULL)
  1516. break;
  1517. if (pwszNextVolume[0] == L'\0')
  1518. continue;
  1519. BS_ASSERT(nVolumesIndex < m_nVolumesCount);
  1520. m_ppwszVolumesArray[nVolumesIndex] = pwszNextVolume;
  1521. nVolumesIndex++;
  1522. }
  1523. BS_ASSERT(nVolumesIndex == m_nVolumesCount);
  1524. // Call the writer's OnPrepareSnapshot method
  1525. BS_ASSERT(m_pWriter);
  1526. bool bResult;
  1527. try
  1528. {
  1529. bResult = m_pWriter->OnPrepareSnapshot();
  1530. m_bOnAbortPermitted = true;
  1531. }
  1532. catch(...)
  1533. {
  1534. if (m_writerstate.GetCurrentFailure() == S_OK)
  1535. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_NONRETRYABLE);
  1536. ft.Trace(VSSDBG_WRITER, L"Writer's OnPrepareSnapshot method threw an execption");
  1537. throw;
  1538. }
  1539. if (!bResult)
  1540. ft.Throw( VSSDBG_WRITER, E_UNEXPECTED, L"Writer rejected the prepare snapshot");
  1541. }
  1542. VSS_STANDARD_CATCH(ft)
  1543. // leave PrepareSnapshot state
  1544. if (EnterStateCalled)
  1545. LeaveState(s_rgWriterStates[s_ivwsmPrepareForSnapshot], ft.HrSucceeded());
  1546. // Bug 255996
  1547. return S_OK;
  1548. }
  1549. // process freeze event
  1550. STDMETHODIMP CVssWriterImpl::Freeze
  1551. (
  1552. IN BSTR bstrSnapshotSetId,
  1553. IN INT nLevel
  1554. )
  1555. {
  1556. CVssFunctionTracer ft( VSSDBG_WRITER, L"CVssWriterImpl::Freeze" );
  1557. bool EnterStateCalled = false;
  1558. try
  1559. {
  1560. // should only be called by the coordinator, access check for admin privileges
  1561. if (!IsAdministrator())
  1562. ft.Throw(VSSDBG_WRITER, E_ACCESSDENIED, L"ADMIN privileges are not set");
  1563. if (bstrSnapshotSetId == NULL)
  1564. {
  1565. BS_ASSERT(false);
  1566. ft.Throw(VSSDBG_WRITER, E_INVALIDARG, L"A required parameter is NULL.");
  1567. }
  1568. ft.Trace( VSSDBG_WRITER, L"\nReceived Event: Freeze\nParameters:\n");
  1569. ft.Trace( VSSDBG_WRITER, L"\tSnapshotSetID = %s\n", (LPWSTR)bstrSnapshotSetId);
  1570. ft.Trace( VSSDBG_WRITER, L"\tLevel = %d\n", nLevel);
  1571. // Ignore other Levels
  1572. if (m_nLevel != nLevel)
  1573. return S_OK;
  1574. CVssAutoDiagLogger logger(m_writerstate, VSS_IN_FREEZE, bstrSnapshotSetId);
  1575. // enter freeze state
  1576. EnterStateCalled = true;
  1577. if (!EnterState
  1578. (
  1579. s_rgWriterStates[s_ivwsmFreeze],
  1580. bstrSnapshotSetId
  1581. ))
  1582. {
  1583. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_RETRYABLE);
  1584. ft.Throw
  1585. (
  1586. VSSDBG_WRITER,
  1587. E_UNEXPECTED,
  1588. L"Improper entry into state"
  1589. );
  1590. }
  1591. AssertLocked();
  1592. // indicate that we are in an operation
  1593. m_writerstate.SetInOperation(VSS_IN_FREEZE);
  1594. // Call writer's OnFreeze
  1595. BS_ASSERT(m_pWriter);
  1596. bool bResult;
  1597. try
  1598. {
  1599. bResult = m_pWriter->OnFreeze();
  1600. BS_ASSERT(m_bOnAbortPermitted == true);
  1601. }
  1602. catch(...)
  1603. {
  1604. if (m_writerstate.GetCurrentFailure() == S_OK)
  1605. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_NONRETRYABLE);
  1606. ft.Trace(VSSDBG_WRITER, L"Writer's OnFreeze Method threw and exception");
  1607. throw;
  1608. }
  1609. if (!bResult)
  1610. ft.Throw( VSSDBG_WRITER, E_UNEXPECTED, L"Writer rejected the freeze");
  1611. // setup arguments to timer thread
  1612. CVssTimerArgs *pArgs = new CVssTimerArgs(this, m_CurrentSnapshotSetId);
  1613. if (pArgs == NULL)
  1614. {
  1615. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_OUTOFRESOURCES);
  1616. ft.Throw
  1617. (
  1618. VSSDBG_WRITER,
  1619. E_OUTOFMEMORY,
  1620. L"Cannot create timer args due to allocation failure"
  1621. );
  1622. }
  1623. DWORD tid;
  1624. // create timer thread
  1625. m_hThreadTimerThread =
  1626. CreateThread
  1627. (
  1628. NULL,
  1629. VSS_STACK_SIZE,
  1630. &CVssWriterImpl::StartTimerThread,
  1631. pArgs,
  1632. 0,
  1633. &tid
  1634. );
  1635. if (m_hThreadTimerThread == NULL)
  1636. {
  1637. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_OUTOFRESOURCES);
  1638. delete pArgs;
  1639. ft.Throw
  1640. (
  1641. VSSDBG_WRITER,
  1642. E_OUTOFMEMORY,
  1643. L"Failure to create thread due to error %d.",
  1644. GetLastError()
  1645. );
  1646. }
  1647. }
  1648. VSS_STANDARD_CATCH(ft)
  1649. // leave OnFreeze state
  1650. if (EnterStateCalled)
  1651. LeaveState( s_rgWriterStates[s_ivwsmFreeze], ft.HrSucceeded());
  1652. // Bug 255996
  1653. return S_OK;
  1654. }
  1655. // handle IVssWriter::Thaw event
  1656. STDMETHODIMP CVssWriterImpl::Thaw
  1657. (
  1658. IN BSTR bstrSnapshotSetId
  1659. )
  1660. {
  1661. CVssFunctionTracer ft( VSSDBG_WRITER, L"CVssWriterImpl::Thaw" );
  1662. bool EnterStateCalled = false;
  1663. try
  1664. {
  1665. // should only be called by coordinator. Access check for admin
  1666. if (!IsAdministrator())
  1667. ft.Throw(VSSDBG_WRITER, E_ACCESSDENIED, L"ADMIN privileges are not set");
  1668. if (bstrSnapshotSetId == NULL)
  1669. {
  1670. BS_ASSERT(false);
  1671. ft.Throw(VSSDBG_COORD, E_INVALIDARG, L"A required parameter is NULL");
  1672. }
  1673. ft.Trace( VSSDBG_WRITER, L"\nReceived Event: Thaw\nParameters:\n");
  1674. ft.Trace( VSSDBG_WRITER, L"\tSnapshotSetID = %s\n", (LPWSTR)bstrSnapshotSetId);
  1675. CVssAutoDiagLogger logger(m_writerstate, VSS_IN_THAW, bstrSnapshotSetId);
  1676. // enter Thaw state
  1677. EnterStateCalled = true; // this line of code must be immediately before the call of EnterState
  1678. if (!EnterState
  1679. (
  1680. s_rgWriterStates[s_ivwsmThaw],
  1681. bstrSnapshotSetId
  1682. ))
  1683. {
  1684. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_RETRYABLE);
  1685. ft.Throw
  1686. (
  1687. VSSDBG_WRITER,
  1688. E_UNEXPECTED,
  1689. L"Improper entry into state"
  1690. );
  1691. }
  1692. // indicate that we are in an operation
  1693. m_writerstate.SetInOperation(VSS_IN_THAW);
  1694. AssertLocked();
  1695. // terminate timer thread as we are about to thaw the operation
  1696. // Warning: BUG 488348 VSS: Assert when testing m_bSequenceInProgress Bug Understood Server RC1
  1697. TerminateTimerThread();
  1698. // We should "live" in a sequence since Thaw is not the first phase of the sequence.
  1699. if (!m_bSequenceInProgress)
  1700. {
  1701. ft.Throw( VSSDBG_WRITER, E_UNEXPECTED, L"Writer rejected the thaw");
  1702. }
  1703. // Call writer's OnThaw
  1704. BS_ASSERT(m_pWriter);
  1705. bool bResult;
  1706. try
  1707. {
  1708. bResult = m_pWriter->OnThaw();
  1709. }
  1710. catch(...)
  1711. {
  1712. if (m_writerstate.GetCurrentFailure() == S_OK)
  1713. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_NONRETRYABLE);
  1714. ft.Trace(VSSDBG_WRITER, L"Writer's OnThaw method threw an exception");
  1715. throw;
  1716. }
  1717. // throw veto if writer vetoes the event
  1718. if (!bResult)
  1719. ft.Throw( VSSDBG_WRITER, E_UNEXPECTED, L"Writer rejected the thaw");
  1720. }
  1721. VSS_STANDARD_CATCH(ft)
  1722. // leave OnThaw state
  1723. if (EnterStateCalled)
  1724. LeaveState(s_rgWriterStates[s_ivwsmThaw], ft.HrSucceeded());
  1725. // Bug 255996
  1726. return S_OK;
  1727. }
  1728. // process PostSnapshot event
  1729. STDMETHODIMP CVssWriterImpl::PostSnapshot
  1730. (
  1731. IN BSTR bstrSnapshotSetId,
  1732. IN IDispatch* pWriterCallback,
  1733. IN BSTR SnapshotDevicesList
  1734. )
  1735. {
  1736. UNREFERENCED_PARAMETER(SnapshotDevicesList);
  1737. CVssFunctionTracer ft( VSSDBG_WRITER, L"CVssWriterImpl::PostSnapshot" );
  1738. bool EnterStateCalled = false;
  1739. try
  1740. {
  1741. // access check
  1742. if (!IsAdministrator())
  1743. ft.Throw(VSSDBG_WRITER, E_ACCESSDENIED, L"Backup Operator privileges are not set");
  1744. if (pWriterCallback == NULL || bstrSnapshotSetId == NULL)
  1745. {
  1746. BS_ASSERT(false);
  1747. ft.Throw(VSSDBG_WRITER, E_INVALIDARG, L"NULL required input parameter.");
  1748. }
  1749. ft.Trace(VSSDBG_WRITER, L"\nReceived Event: PostSnapshot\nParameters:\n");
  1750. ft.Trace(VSSDBG_WRITER, L"\tSnapshotSetID = %s\n", (LPWSTR)bstrSnapshotSetId);
  1751. CVssAutoDiagLogger logger(m_writerstate, VSS_IN_POSTSNAPSHOT, bstrSnapshotSetId);
  1752. // enter PostSnapshot state
  1753. EnterStateCalled = true;
  1754. if (!EnterState
  1755. (
  1756. s_rgWriterStates[s_ivwsmPostSnapshot],
  1757. bstrSnapshotSetId
  1758. ))
  1759. {
  1760. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_RETRYABLE);
  1761. ft.Throw
  1762. (
  1763. VSSDBG_WRITER,
  1764. E_UNEXPECTED,
  1765. L"Couldn't properly begin sequence"
  1766. );
  1767. }
  1768. AssertLocked();
  1769. // indicate we are in an operation
  1770. m_writerstate.SetInOperation(VSS_IN_POSTSNAPSHOT);
  1771. // get IVssWriterCallback interface
  1772. CComPtr<IVssWriterCallback> pCallback;
  1773. //
  1774. // This is a special case where the writer calls VSS instead of
  1775. // the requestor. In this case we have to allow impersonation.
  1776. //
  1777. GetCallback(pWriterCallback, &pCallback, TRUE);
  1778. // get IVssWriterComponentsExt interface
  1779. CComPtr<IVssWriterComponentsInt> pComponents;
  1780. InternalGetWriterComponents(pCallback, &pComponents, true, false);
  1781. BS_ASSERT(m_pWriter);
  1782. // call writer's OnPostSnapshot method
  1783. bool bResult;
  1784. try
  1785. {
  1786. bResult = m_pWriter->OnPostSnapshot(pComponents);
  1787. }
  1788. catch(...)
  1789. {
  1790. ft.Trace(VSSDBG_WRITER, L"Writer's OnPostSnapshot method threw an exception");
  1791. if (m_writerstate.GetCurrentFailure() == S_OK)
  1792. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_NONRETRYABLE);
  1793. throw;
  1794. }
  1795. if (!bResult)
  1796. ft.Throw( VSSDBG_WRITER, E_UNEXPECTED, L"Writer rejected the post Snapshot");
  1797. // save changes to components if any
  1798. if (pComponents)
  1799. SaveChangedComponents(pCallback, false, pComponents);
  1800. }
  1801. VSS_STANDARD_CATCH(ft)
  1802. // leave PostSnapshot state
  1803. if (EnterStateCalled)
  1804. LeaveState(s_rgWriterStates[s_ivwsmPostSnapshot], ft.HrSucceeded());
  1805. // Bug 255996
  1806. return S_OK;
  1807. }
  1808. // process backup complete event
  1809. STDMETHODIMP CVssWriterImpl::BackupComplete
  1810. (
  1811. IN BSTR bstrSnapshotSetId,
  1812. IN IDispatch* pWriterCallback
  1813. )
  1814. {
  1815. CVssFunctionTracer ft( VSSDBG_WRITER, L"CVssWriterImpl::BackupComplete" );
  1816. // access check
  1817. try
  1818. {
  1819. if (!IsBackupOperator())
  1820. ft.Throw(VSSDBG_WRITER, E_ACCESSDENIED,L"Backup Operator privileges are not set");
  1821. // MTA synchronization: The critical section will be left automatically at the end of scope.
  1822. CVssWriterImplLock lock(this);
  1823. CVssID id;
  1824. bool bIdInitialized = false;
  1825. try
  1826. {
  1827. if (pWriterCallback == NULL || bstrSnapshotSetId == NULL)
  1828. ft.Throw(VSSDBG_WRITER, E_INVALIDARG, L"NULL required input parameter.");
  1829. ft.Trace(VSSDBG_WRITER, L"\nReceived Event: OnBackupComplete\nParameters:\n");
  1830. ft.Trace(VSSDBG_WRITER, L"\tSnapshotSetID = %s\n", (LPWSTR)bstrSnapshotSetId);
  1831. CVssAutoDiagLogger logger(m_writerstate, VSS_IN_BACKUPCOMPLETE, bstrSnapshotSetId);
  1832. m_writerstate.SetInOperation(VSS_IN_BACKUPCOMPLETE);
  1833. BS_ASSERT(!m_bSequenceInProgress);
  1834. BS_ASSERT(m_CurrentSnapshotSetId == GUID_NULL);
  1835. id.Initialize(ft, (LPCWSTR) bstrSnapshotSetId, E_INVALIDARG);
  1836. bIdInitialized = true;
  1837. m_writerstate.FinishBackupComplete(id);
  1838. // get IVssWriterCallback interface
  1839. CComPtr<IVssWriterCallback> pCallback;
  1840. GetCallback(pWriterCallback, &pCallback);
  1841. // get IVssWriterComponentsInt object
  1842. CComPtr<IVssWriterComponentsInt> pComponents;
  1843. InternalGetWriterComponents(pCallback, &pComponents, false, false);
  1844. // call writer's OnBackupComplete method
  1845. BS_ASSERT(m_pWriter);
  1846. try
  1847. {
  1848. if (!m_pWriter->OnBackupComplete(pComponents))
  1849. ft.hr = S_FALSE;
  1850. }
  1851. catch(...)
  1852. {
  1853. if (m_writerstate.GetCurrentFailure() == S_OK)
  1854. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_NONRETRYABLE);
  1855. ft.Trace(VSSDBG_WRITER, L"Writer's OnBackupComplete method threw an exception.");
  1856. throw;
  1857. }
  1858. if (ft.hr == S_FALSE)
  1859. ft.Throw(VSSDBG_WRITER, E_UNEXPECTED, L"Writer rejected the backup complete");
  1860. }
  1861. VSS_STANDARD_CATCH(ft)
  1862. // indicate that sequence is complete
  1863. if (m_writerstate.GetCurrentState() == VSS_WS_WAITING_FOR_BACKUP_COMPLETE)
  1864. m_writerstate.SetCurrentState(VSS_WS_STABLE);
  1865. m_writerstate.SetBackupCompleteStatus(id, ft.hr);
  1866. m_writerstate.ExitOperation();
  1867. }
  1868. VSS_STANDARD_CATCH(ft)
  1869. // Bug 255996
  1870. return S_OK;
  1871. }
  1872. STDMETHODIMP CVssWriterImpl::BackupShutdown
  1873. (
  1874. IN BSTR bstrSnapshotSetId
  1875. )
  1876. {
  1877. UNREFERENCED_PARAMETER(bstrSnapshotSetId);
  1878. CVssFunctionTracer ft( VSSDBG_WRITER, L"CVssWriterImpl::BackupShutdown");
  1879. // access check
  1880. try
  1881. {
  1882. if (!IsAdministrator())
  1883. ft.Throw(VSSDBG_WRITER, E_ACCESSDENIED,L"Can only be called from the coordinator");
  1884. // MTA synchronization: The critical section will be left automatically at the end of scope.
  1885. CVssWriterImplLock lock(this);
  1886. CVssID id;
  1887. try
  1888. {
  1889. if (bstrSnapshotSetId == NULL)
  1890. ft.Throw(VSSDBG_WRITER, E_INVALIDARG, L"NULL required input parameter.");
  1891. ft.Trace(VSSDBG_WRITER, L"\nReceived Event: OnBackupShutdown\nParameters:\n");
  1892. ft.Trace(VSSDBG_WRITER, L"\tSnapshotSetID = %s\n", (LPWSTR)bstrSnapshotSetId);
  1893. CVssAutoDiagLogger logger(m_writerstate, VSS_IN_BACKUPSHUTDOWN, bstrSnapshotSetId);
  1894. m_writerstate.SetInOperation(VSS_IN_BACKUPSHUTDOWN);
  1895. id.Initialize(ft, (LPCWSTR) bstrSnapshotSetId, E_INVALIDARG);
  1896. // call writer's OnBackupComplete method
  1897. BS_ASSERT(m_pWriter);
  1898. try
  1899. {
  1900. if (!m_pWriter->OnBackupShutdown(id))
  1901. ft.hr = S_FALSE;
  1902. }
  1903. catch(...)
  1904. {
  1905. if (m_writerstate.GetCurrentFailure() == S_OK)
  1906. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_NONRETRYABLE);
  1907. ft.Trace(VSSDBG_WRITER, L"Writer's OnBackupShutdown method threw an exception.");
  1908. throw;
  1909. }
  1910. if (ft.hr == S_FALSE)
  1911. ft.Throw(VSSDBG_WRITER, E_UNEXPECTED, L"Writer rejected the backup shutdown");
  1912. }
  1913. VSS_STANDARD_CATCH(ft)
  1914. m_writerstate.ExitOperation();
  1915. }
  1916. VSS_STANDARD_CATCH(ft)
  1917. // Bug 255996
  1918. return S_OK;
  1919. }
  1920. // handle IVssWriter::Abort event
  1921. STDMETHODIMP CVssWriterImpl::Abort
  1922. (
  1923. IN BSTR bstrSnapshotSetId
  1924. )
  1925. {
  1926. CVssFunctionTracer ft( VSSDBG_WRITER, L"CVssWriterImpl::Abort" );
  1927. try
  1928. {
  1929. if (!IsBackupOperator())
  1930. ft.Throw(VSSDBG_WRITER, E_ACCESSDENIED, L"Backup privileges are not set");
  1931. ft.Trace( VSSDBG_WRITER, L"\nReceived Event: Abort\nParameters:\n");
  1932. ft.Trace( VSSDBG_WRITER, L"\tSnapshotSetID = %s\n", (LPWSTR)bstrSnapshotSetId);
  1933. Lock();
  1934. CVssID id;
  1935. id.Initialize(ft, bstrSnapshotSetId, S_OK); // Ignore errors here.
  1936. CVssAutoDiagLogger logger(m_writerstate, VSS_IN_ABORT, id);
  1937. // call do abort function
  1938. DoAbort(false, bstrSnapshotSetId);
  1939. Unlock();
  1940. }
  1941. VSS_STANDARD_CATCH(ft)
  1942. return ft.hr;
  1943. }
  1944. // process prerestore event
  1945. STDMETHODIMP CVssWriterImpl::PreRestore
  1946. (
  1947. IN IDispatch* pWriterCallback
  1948. )
  1949. {
  1950. CVssFunctionTracer ft( VSSDBG_WRITER, L"CVssWriterImpl::PreRestore" );
  1951. ft.Trace(VSSDBG_WRITER, L"\nReceived Event: PreRestore\n");
  1952. try
  1953. {
  1954. // access check
  1955. if (!IsRestoreOperator())
  1956. ft.Throw(VSSDBG_WRITER, E_INVALIDARG, L"Restore Operator privileges are not set");
  1957. // MTA synchronization: The critical section will be left automatically at the end of scope.
  1958. CVssWriterImplLock lock(this);
  1959. CVssAutoDiagLogger logger(m_writerstate, VSS_IN_PRERESTORE);
  1960. m_writerstate.SetInOperation(VSS_IN_PRERESTORE);
  1961. m_writerstate.SetCurrentFailure(S_OK);
  1962. try
  1963. {
  1964. if (pWriterCallback == NULL)
  1965. ft.Throw(VSSDBG_WRITER, E_INVALIDARG, L"NULL required input parameter.");
  1966. // get writer callback interface
  1967. CComPtr<IVssWriterCallback> pCallback;
  1968. GetCallback(pWriterCallback, &pCallback);
  1969. CComPtr<IVssWriterComponentsInt> pComponents;
  1970. // get IVssWriterComponentsInt object
  1971. InternalGetWriterComponents(pCallback, &pComponents, true, true);
  1972. // call writer's OnPreRestore method
  1973. BS_ASSERT(m_pWriter);
  1974. try
  1975. {
  1976. if (!m_pWriter->OnPreRestore(pComponents))
  1977. ft.hr = S_FALSE;
  1978. }
  1979. catch(...)
  1980. {
  1981. if (m_writerstate.GetCurrentFailure() == S_OK)
  1982. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_NONRETRYABLE);
  1983. ft.Trace(VSSDBG_WRITER, L"Writer's OnPreRestore method threw an exception");
  1984. throw;
  1985. }
  1986. if (ft.hr == S_FALSE)
  1987. ft.Throw( VSSDBG_WRITER, E_UNEXPECTED, L"Writer rejected the prerestore");
  1988. if (pComponents)
  1989. SaveChangedComponents(pCallback, true, pComponents);
  1990. }
  1991. VSS_STANDARD_CATCH(ft)
  1992. if (FAILED(ft.hr))
  1993. m_writerstate.SetCurrentState(VSS_WS_FAILED_AT_PRE_RESTORE);
  1994. else
  1995. m_writerstate.SetCurrentState(VSS_WS_STABLE);
  1996. m_writerstate.ExitOperation();
  1997. }
  1998. VSS_STANDARD_CATCH(ft)
  1999. // Bug 255996
  2000. return S_OK;
  2001. }
  2002. // process post restore event
  2003. STDMETHODIMP CVssWriterImpl::PostRestore
  2004. (
  2005. IN IDispatch* pWriterCallback
  2006. )
  2007. {
  2008. CVssFunctionTracer ft( VSSDBG_WRITER, L"CVssWriterImpl::PostRestore" );
  2009. try
  2010. {
  2011. // access check
  2012. if (!IsRestoreOperator())
  2013. ft.Throw(VSSDBG_WRITER, E_INVALIDARG, L"Restore Operator privileges are not set");
  2014. ft.Trace(VSSDBG_WRITER, L"\nReceived Event: PostRestore\n");
  2015. // MTA synchronization: The critical section will be left automatically at the end of scope.
  2016. CVssWriterImplLock lock(this);
  2017. CVssAutoDiagLogger logger(m_writerstate, VSS_IN_POSTRESTORE);
  2018. m_writerstate.SetInOperation(VSS_IN_POSTRESTORE);
  2019. m_writerstate.SetCurrentFailure(S_OK);
  2020. try
  2021. {
  2022. if (pWriterCallback == NULL)
  2023. ft.Throw(VSSDBG_WRITER, E_INVALIDARG, L"NULL required input parameter.");
  2024. // get writer callback interface
  2025. CComPtr<IVssWriterCallback> pCallback;
  2026. GetCallback(pWriterCallback, &pCallback);
  2027. CComPtr<IVssWriterComponentsInt> pComponents;
  2028. // get IVssWriterComponentsInt object
  2029. InternalGetWriterComponents(pCallback, &pComponents, true, true);
  2030. // call writer's OnPostRestore method
  2031. BS_ASSERT(m_pWriter);
  2032. try
  2033. {
  2034. if (!m_pWriter->OnPostRestore(pComponents))
  2035. ft.hr = S_FALSE;
  2036. }
  2037. catch(...)
  2038. {
  2039. if (m_writerstate.GetCurrentFailure() == S_OK)
  2040. m_writerstate.SetCurrentFailure(VSS_E_WRITERERROR_NONRETRYABLE);
  2041. ft.Trace(VSSDBG_WRITER, L"Writer's OnPostRestore method threw an exception");
  2042. throw;
  2043. }
  2044. if (ft.hr == S_FALSE)
  2045. ft.Throw( VSSDBG_WRITER, E_UNEXPECTED, L"Writer rejected the postrestore");
  2046. if (pComponents)
  2047. SaveChangedComponents(pCallback, true, pComponents);
  2048. }
  2049. VSS_STANDARD_CATCH(ft)
  2050. if (FAILED(ft.hr))
  2051. m_writerstate.SetCurrentState(VSS_WS_FAILED_AT_POST_RESTORE);
  2052. else
  2053. m_writerstate.SetCurrentState(VSS_WS_STABLE);
  2054. m_writerstate.ExitOperation();
  2055. }
  2056. VSS_STANDARD_CATCH(ft)
  2057. // Bug 255996
  2058. return S_OK;
  2059. }
  2060. // table of names of events that we are subscribing to
  2061. // NOTE: this table is based on definition of VSS_EVENT_MASK. Each
  2062. // offset corresponds to a bit on that mask
  2063. const WCHAR *g_rgwszSubscriptions[] =
  2064. {
  2065. g_wszPrepareForBackupMethodName, // VSS_EVENT_PREPAREBackup
  2066. g_wszPrepareForSnapshotMethodName, // VSS_EVENT_PREPARESnapshot
  2067. g_wszFreezeMethodName, // VSS_EVENT_FREEZE
  2068. g_wszThawMethodName, // VSS_EVENT_THAW
  2069. g_wszPostSnapshotMethodName, // VSS_EVENT_POST_SNAPSHOT
  2070. g_wszAbortMethodName, // VSS_EVENT_ABORT
  2071. g_wszBackupCompleteMethodName, // VSS_EVENT_BACKUPCOMPLETE
  2072. g_wszRequestInfoMethodName, // VSS_EVENT_REQUESTINFO
  2073. g_wszPreRestoreMethodName, // VSS_EVENT_RESTORE
  2074. g_wszPostRestoreMethodName, // VSS_EVENT_POST_RESTORE
  2075. g_wszBackupShutdownName // VSS_EVENT_BACKUPSHUTDOWN
  2076. };
  2077. /////////////////////////////////////////////////////////////////////////////
  2078. // Subscription-related members
  2079. // create subscriptions
  2080. // This function returns S_FALSE when the writer is inactive (setup or safe mode)
  2081. void CVssWriterImpl::Subscribe()
  2082. {
  2083. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterImpl::Subscribe");
  2084. // validate that the writer is initialized
  2085. if (m_bInSetup || m_bInSafeMode)
  2086. ft.Throw
  2087. (
  2088. VSSDBG_WRITER,
  2089. S_FALSE,
  2090. L"Writer is inactive during setup or safe mode"
  2091. );
  2092. // validate that the writer is initialized
  2093. if (!m_bInitialized)
  2094. ft.Throw
  2095. (
  2096. VSSDBG_WRITER,
  2097. VSS_E_BAD_STATE,
  2098. L"You must initialize the writer before other operations"
  2099. );
  2100. // currently we subscribe to all events
  2101. m_dwEventMask = VSS_EVENT_ALL;
  2102. if (m_bstrSubscriptionName.Length() > 0)
  2103. ft.Throw
  2104. (
  2105. VSSDBG_XML,
  2106. VSS_E_WRITER_ALREADY_SUBSCRIBED,
  2107. L"The writer has already called the Subscribe function."
  2108. );
  2109. // create event system
  2110. CComPtr<IEventSystem> pSystem;
  2111. ft.CoCreateInstanceWithLog(
  2112. VSSDBG_WRITER,
  2113. CLSID_CEventSystem,
  2114. L"CEventSystem",
  2115. CLSCTX_SERVER,
  2116. IID_IEventSystem,
  2117. (IUnknown**)&(pSystem));
  2118. ft.CheckForError(VSSDBG_WRITER, L"CoCreateInstance");
  2119. CComBSTR bstrClassId = CLSID_VssEvent;
  2120. CComBSTR bstrIID = IID_IVssWriter;
  2121. CComBSTR bstrProgId = PROGID_EventSubscription;
  2122. // see if event class already exists
  2123. CComBSTR bstrQuery = "EventClassID == ";
  2124. if (!bstrQuery)
  2125. ft.Throw(VSSDBG_WRITER, E_OUTOFMEMORY, L"Cannot allocate BSTR.");
  2126. bstrQuery.Append(bstrClassId);
  2127. if (!bstrQuery)
  2128. ft.Throw(VSSDBG_WRITER, E_OUTOFMEMORY, L"Cannot allocate BSTR.");
  2129. int location;
  2130. CComPtr<IEventObjectCollection> pCollection;
  2131. ft.hr = pSystem->Query
  2132. (
  2133. PROGID_EventClassCollection,
  2134. bstrQuery,
  2135. &location,
  2136. (IUnknown **) &pCollection
  2137. );
  2138. ft.CheckForError(VSSDBG_WRITER, L"IEventSystem::Query");
  2139. long cEvents;
  2140. ft.hr = pCollection->get_Count(&cEvents);
  2141. ft.CheckForError(VSSDBG_WRITER, L"IEventObjectCollection::get_Count");
  2142. if (cEvents == 0)
  2143. {
  2144. // event class does not exist, create it. Note that there is a
  2145. // potential race condition here if two writers try creating the event
  2146. // class at the same time. We create the event class during installation
  2147. // so that this should rarely happen
  2148. CComPtr<IEventClass> pEvent;
  2149. CComBSTR bstrEventClassName = L"VssEvent";
  2150. WCHAR buf[MAX_PATH*2];
  2151. // event class typelib
  2152. UINT cwc = ExpandEnvironmentStrings
  2153. (
  2154. L"%systemroot%\\system32\\eventcls.dll",
  2155. buf,
  2156. sizeof(buf)/sizeof(WCHAR)
  2157. );
  2158. if (cwc == 0)
  2159. {
  2160. ft.hr = HRESULT_FROM_WIN32(GetLastError());
  2161. ft.CheckForError(VSSDBG_WRITER, L"ExpandEnvironmentStrings");
  2162. }
  2163. CComBSTR bstrTypelib = buf;
  2164. // create event class
  2165. ft.CoCreateInstanceWithLog(
  2166. VSSDBG_WRITER,
  2167. CLSID_CEventClass,
  2168. L"CEventClass",
  2169. CLSCTX_SERVER,
  2170. IID_IEventClass,
  2171. (IUnknown**)&(pEvent));
  2172. ft.CheckForError(VSSDBG_WRITER, L"CoCreatInstance");
  2173. // setup class id
  2174. ft.hr = pEvent->put_EventClassID(bstrClassId);
  2175. ft.CheckForError(VSSDBG_WRITER, L"IEventClass::put_EventClassID");
  2176. // set up class name
  2177. ft.hr = pEvent->put_EventClassName(bstrEventClassName);
  2178. ft.CheckForError(VSSDBG_WRITER, L"IEventClass::put_EventClassName");
  2179. // set up typelib
  2180. ft.hr = pEvent->put_TypeLib(bstrTypelib);
  2181. ft.CheckForError(VSSDBG_WRITER, L"IEventClass::put_TypeLib");
  2182. // store event class
  2183. ft.hr = pSystem->Store(PROGID_EventClass, pEvent);
  2184. ft.CheckForError(VSSDBG_WRITER, L"IEventSystem::Store");
  2185. }
  2186. // create subscription id
  2187. VSS_ID SubscriptionId;
  2188. ft.hr = ::CoCreateGuid(&SubscriptionId);
  2189. ft.CheckForError(VSSDBG_WRITER, L"CoCreateGuid");
  2190. m_bstrSubscriptionName = SubscriptionId;
  2191. // get IUnknown for subscribers class
  2192. IUnknown *pUnkSubscriber = GetUnknown();
  2193. UINT iwsz, mask;
  2194. try
  2195. {
  2196. // loop through subscriptions
  2197. for(mask = 1, iwsz = 0; mask < VSS_EVENT_ALL; mask = mask << 1, iwsz++)
  2198. {
  2199. if (m_dwEventMask & mask && g_rgwszSubscriptions[iwsz] != NULL)
  2200. {
  2201. // create IEventSubscription object
  2202. CComPtr<IEventSubscription> pSubscription;
  2203. ft.CoCreateInstanceWithLog(
  2204. VSSDBG_WRITER,
  2205. CLSID_CEventSubscription,
  2206. L"CEventSubscription",
  2207. CLSCTX_SERVER,
  2208. IID_IEventSubscription,
  2209. (IUnknown**)&(pSubscription));
  2210. ft.CheckForError(VSSDBG_WRITER, L"CoCreateInstance");
  2211. // set subscription name
  2212. ft.hr = pSubscription->put_SubscriptionName(m_bstrSubscriptionName);
  2213. ft.CheckForError(VSSDBG_WRITER, L"IEventSubscription::put_SubscriptionName");
  2214. // set event class id
  2215. ft.hr = pSubscription->put_EventClassID(bstrClassId);
  2216. ft.CheckForError(VSSDBG_WRITER, L"IEventSubscription::put_EventClassID");
  2217. // set interface id
  2218. ft.hr = pSubscription->put_InterfaceID(bstrIID);
  2219. ft.CheckForError(VSSDBG_WRITER, L"IEventSubscription::put_InterfaceID");
  2220. // set subcriber interface
  2221. ft.hr = pSubscription->put_SubscriberInterface(pUnkSubscriber);
  2222. ft.CheckForError(VSSDBG_WRITER, L"IEventSubscription::put_SubscriberInterface");
  2223. // make subscription per user since this is not necessarily in local system
  2224. ft.hr = pSubscription->put_PerUser(TRUE);
  2225. ft.CheckForError(VSSDBG_WRITER, L"IEventSubscription::put_PerUser");
  2226. // set method name for subscrpition
  2227. ft.hr = pSubscription->put_MethodName(CComBSTR(g_rgwszSubscriptions[iwsz]));
  2228. ft.CheckForError(VSSDBG_WRITER, L"IEventSubscription::put_MethodName");
  2229. // setup InstanceId and WriterId subscription properties
  2230. VARIANT varWriterId;
  2231. VARIANT varInstanceId;
  2232. CComBSTR bstrWriterId = m_WriterID;
  2233. CComBSTR bstrInstanceId = m_InstanceID;
  2234. varWriterId.vt = VT_BSTR;
  2235. varWriterId.bstrVal = bstrWriterId;
  2236. varInstanceId.vt = VT_BSTR;
  2237. varInstanceId.bstrVal = bstrInstanceId;
  2238. ft.hr = pSubscription->PutSubscriberProperty(L"WriterId", &varWriterId);
  2239. ft.CheckForError(VSSDBG_WRITER, L"IEventSubscription::PutSubscriberProperty");
  2240. ft.hr = pSubscription->PutSubscriberProperty(L"WriterInstanceId", &varInstanceId);
  2241. ft.CheckForError(VSSDBG_WRITER, L"IEventSubscription::PutSubscriberProperty");
  2242. // store subscription
  2243. ft.hr = pSystem->Store(bstrProgId, pSubscription);
  2244. ft.CheckForError(VSSDBG_WRITER, L"IEventSystem::Store");
  2245. // get constructed subscription id and save it
  2246. ft.hr = pSubscription->get_SubscriptionID(&m_rgbstrSubscriptionId[m_cbstrSubscriptionId]);
  2247. ft.CheckForError(VSSDBG_WRITER, L"IEventSubscription::get_SubscriptionID");
  2248. // increment count of
  2249. m_cbstrSubscriptionId++;
  2250. }
  2251. }
  2252. }
  2253. VSS_STANDARD_CATCH(ft)
  2254. // if the operation fails with us partially subscribed, then unsubscribe
  2255. if (ft.HrFailed() && m_cbstrSubscriptionId)
  2256. {
  2257. Unsubscribe();
  2258. ft.Throw(VSSDBG_WRITER, ft.hr, L"Rethrowing exception");
  2259. }
  2260. ft.Trace(VSSDBG_WRITER, L"**** Subscribe succeeded for [%p]", this);
  2261. }
  2262. // terminate timer thread
  2263. // assumes caller has the critical section locked
  2264. void CVssWriterImpl::TerminateTimerThread()
  2265. {
  2266. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterImpl::TerminateTimerThread");
  2267. AssertLocked();
  2268. if (m_hThreadTimerThread)
  2269. {
  2270. // cause timer thread to terminate
  2271. m_command = VSS_TC_TERMINATE_THREAD;
  2272. if (!SetEvent(m_hevtTimerThread))
  2273. {
  2274. DWORD dwErr = GetLastError();
  2275. ft.Trace(VSSDBG_WRITER, L"SetEvent failed with error %d\n", dwErr);
  2276. BS_ASSERT(FALSE && "SetEvent failed");
  2277. }
  2278. // get thread handle
  2279. HANDLE hThread = m_hThreadTimerThread;
  2280. m_hThreadTimerThread = NULL;
  2281. // unlock during wait
  2282. Unlock();
  2283. if (WaitForSingleObject(hThread, INFINITE) == WAIT_FAILED)
  2284. {
  2285. DWORD dwErr = GetLastError();
  2286. ft.Trace(VSSDBG_WRITER, L"WaitForSingleObject failed with error %d\n", dwErr);
  2287. BS_ASSERT(FALSE && "WaitForSingleObject failed");
  2288. }
  2289. CloseHandle(hThread);
  2290. Lock();
  2291. }
  2292. }
  2293. // unsubscribe this writer from IVssWriter events
  2294. // This function returns S_FALSE when the writer is inactive (setup or safe mode)
  2295. void CVssWriterImpl::Unsubscribe()
  2296. {
  2297. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterImpl::Unsubscribe");
  2298. if (m_bInSetup || m_bInSafeMode)
  2299. ft.Throw
  2300. (
  2301. VSSDBG_WRITER,
  2302. S_FALSE,
  2303. L"Writer is inactive during setup or safe mode"
  2304. );
  2305. // validate that the writer is initialized
  2306. if (!m_bInitialized)
  2307. ft.Throw
  2308. (
  2309. VSSDBG_WRITER,
  2310. VSS_E_BAD_STATE,
  2311. L"You must initialize the writer before other operations"
  2312. );
  2313. // terminate timer thread if active
  2314. Lock();
  2315. TerminateTimerThread();
  2316. Unlock();
  2317. // make sure subscription name was assigned; if not assume subscriptions
  2318. // weren't created
  2319. if (m_bstrSubscriptionName.Length() == 0)
  2320. return;
  2321. // create event system
  2322. CComPtr<IEventSystem> pSystem;
  2323. ft.CoCreateInstanceWithLog(
  2324. VSSDBG_WRITER,
  2325. CLSID_CEventSystem,
  2326. L"CEventSystem",
  2327. CLSCTX_SERVER,
  2328. IID_IEventSystem,
  2329. (IUnknown**)&(pSystem));
  2330. ft.CheckForError(VSSDBG_WRITER, L"CoCreateInstance");
  2331. #if 0
  2332. WCHAR buf[256];
  2333. int location;
  2334. swprintf(buf, L"SubscriptionName = \"%s\"", m_bstrSubscriptionName);
  2335. CComPtr<IEventObjectCollection> pCollection;
  2336. ft.hr = pSystem->Query
  2337. (
  2338. PROGID_EventSubscriptionCollection,
  2339. buf,
  2340. &location,
  2341. (IUnknown **) &pCollection
  2342. );
  2343. ft.CheckForError(VSSDBG_WRITER, L"IEventSystem::Query");
  2344. long cSub;
  2345. ft.hr = pCollection->get_Count(&cSub);
  2346. ft.CheckForError(VSSDBG_WRITER, L"IEventObjectCollection::get_Count");
  2347. pCollection = NULL;
  2348. #endif
  2349. UINT iSubscription;
  2350. for(iSubscription = 0; iSubscription < m_cbstrSubscriptionId; iSubscription++)
  2351. {
  2352. // setup query string
  2353. CComBSTR bstrQuery = L"SubscriptionID == ";
  2354. if (!bstrQuery)
  2355. ft.Throw(VSSDBG_WRITER, E_OUTOFMEMORY, L"allocation of BSTR failed");
  2356. // if subscription exists, then remove it
  2357. if (m_rgbstrSubscriptionId[iSubscription])
  2358. {
  2359. bstrQuery.Append(m_rgbstrSubscriptionId[iSubscription]);
  2360. if (!bstrQuery)
  2361. ft.Throw(VSSDBG_WRITER, E_OUTOFMEMORY, L"allocation of BSTR failed");
  2362. int location;
  2363. // remove subscription
  2364. ft.hr = pSystem->Remove(PROGID_EventSubscription, bstrQuery, &location);
  2365. ft.CheckForError(VSSDBG_WRITER, L"IEventSystem::Remove");
  2366. // indicate that subscription was removed
  2367. m_rgbstrSubscriptionId[iSubscription].Empty();
  2368. }
  2369. }
  2370. #if 0
  2371. ft.hr = pSystem->Query
  2372. (
  2373. PROGID_EventSubscriptionCollection,
  2374. buf,
  2375. &location,
  2376. (IUnknown **) &pCollection
  2377. );
  2378. ft.CheckForError(VSSDBG_WRITER, L"IEventSystem::Query");
  2379. ft.hr = pCollection->get_Count(&cSub);
  2380. ft.CheckForError(VSSDBG_WRITER, L"IEventObjectCollection::get_Count");
  2381. pCollection = NULL;
  2382. #endif
  2383. // reset subscription name so unsubscribe does nothing if called again
  2384. m_bstrSubscriptionName.Empty();
  2385. m_cbstrSubscriptionId = 0;
  2386. // Disconnect the subscription object, if any are left (bug 496343)
  2387. ::CoDisconnectObject(GetUnknown(), 0);
  2388. ft.Trace(VSSDBG_WRITER, L"**** Unsubscribe succeeded for [%p] (%u subscriptions removed)", this, iSubscription);
  2389. }
  2390. // create a internal writer class and link it up to the external writer class
  2391. void CVssWriterImpl::CreateWriter
  2392. (
  2393. CVssWriter *pWriter, // external writer
  2394. IVssWriterImpl **ppImpl // interface to be used by external writer
  2395. )
  2396. {
  2397. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterImpl::CreateWriter");
  2398. BS_ASSERT(ppImpl);
  2399. BS_ASSERT(pWriter);
  2400. *ppImpl = NULL;
  2401. // create internal wrier class
  2402. CComObject<CVssWriterImpl> *pImpl;
  2403. // create CVssWriterImpl object <core writer class>
  2404. ft.hr = CComObject<CVssWriterImpl>::CreateInstance(&pImpl);
  2405. if (ft.HrFailed())
  2406. ft.Throw
  2407. (
  2408. VSSDBG_WRITER,
  2409. E_OUTOFMEMORY,
  2410. L"Failed to create CVssWriterImpl. hr = 0x%08lx",
  2411. ft.hr
  2412. );
  2413. // set reference count of internal writer to 1
  2414. pImpl->GetUnknown()->AddRef();
  2415. // link external writer into internal writer
  2416. pImpl->SetWriter(pWriter);
  2417. // return internal writer interface
  2418. *ppImpl = (IVssWriterImpl *) pImpl;
  2419. }
  2420. // constructor for writer state
  2421. CVssWriterState::CVssWriterState(
  2422. IN CVssDiag& diag
  2423. ) :
  2424. m_iPreviousSnapshots(0),
  2425. m_bSequenceInProgress(false),
  2426. m_diag(diag)
  2427. {
  2428. // initialize current state
  2429. m_currentState.m_state = VSS_WS_STABLE;
  2430. m_currentState.m_idSnapshotSet = GUID_NULL;
  2431. m_currentState.m_bInOperation = false;
  2432. m_currentState.m_hrWriterFailure = S_OK;
  2433. // initialize stack
  2434. for(UINT i = 0; i < MAX_PREVIOUS_SNAPSHOTS; i++)
  2435. {
  2436. m_rgPreviousStates[i].m_idSnapshotSet = GUID_NULL;
  2437. m_rgPreviousStates[i].m_state = VSS_WS_UNKNOWN;
  2438. m_rgPreviousStates[i].m_bInOperation = false;
  2439. m_rgPreviousStates[i].m_hrWriterFailure = E_UNEXPECTED;
  2440. }
  2441. }
  2442. // setup state at the beginning of a snapshot
  2443. void CVssWriterState::InitializeCurrentState(IN const VSS_ID &idSnapshot)
  2444. {
  2445. CVssSafeAutomaticLock lock(m_cs);
  2446. // initalize snapshot id
  2447. m_currentState.m_idSnapshotSet = idSnapshot;
  2448. // indicate that there is no failure
  2449. m_currentState.m_hrWriterFailure = S_OK;
  2450. // clear that we are in an operation
  2451. m_currentState.m_bInOperation = false;
  2452. // indicate that sequence is in progress
  2453. m_bSequenceInProgress = true;
  2454. // current state is STABLE (i.e., beginning of sequence, clears
  2455. // any completion state we were in)
  2456. SetCurrentState(VSS_WS_STABLE);
  2457. }
  2458. // push the current state
  2459. void CVssWriterState::PushCurrentState()
  2460. {
  2461. CVssSafeAutomaticLock lock(m_cs);
  2462. if (m_bSequenceInProgress)
  2463. {
  2464. // Reset the sequence-related data members
  2465. m_bSequenceInProgress = false;
  2466. // We need to test to not add the same SSID twice - bug 228622.
  2467. if (SearchForPreviousSequence(m_currentState.m_idSnapshotSet) == INVALID_SEQUENCE_INDEX)
  2468. {
  2469. BS_ASSERT(m_iPreviousSnapshots < MAX_PREVIOUS_SNAPSHOTS);
  2470. VSWRITER_STATE *pState = &m_rgPreviousStates[m_iPreviousSnapshots];
  2471. memcpy(pState, &m_currentState, sizeof(m_currentState));
  2472. m_iPreviousSnapshots = (m_iPreviousSnapshots + 1) % MAX_PREVIOUS_SNAPSHOTS;
  2473. }
  2474. else
  2475. BS_ASSERT(false); // The same SSID was already added - programming error.
  2476. }
  2477. }
  2478. // find the state for a previous snapshot set
  2479. INT CVssWriterState::SearchForPreviousSequence(IN const VSS_ID& idSnapshotSet)
  2480. {
  2481. CVssSafeAutomaticLock lock(m_cs);
  2482. for(INT iSeqIndex = 0;
  2483. iSeqIndex < MAX_PREVIOUS_SNAPSHOTS;
  2484. iSeqIndex++)
  2485. {
  2486. if (idSnapshotSet == m_rgPreviousStates[iSeqIndex].m_idSnapshotSet)
  2487. return iSeqIndex;
  2488. } // end for
  2489. return INVALID_SEQUENCE_INDEX;
  2490. }
  2491. // obtain the state given the snapshot id
  2492. void CVssWriterState::GetStateForSnapshot
  2493. (
  2494. IN const VSS_ID &id,
  2495. OUT VSWRITER_STATE &state
  2496. )
  2497. {
  2498. // get lock on state class
  2499. CVssSafeAutomaticLock lock(m_cs);
  2500. if (id == GUID_NULL ||
  2501. m_bSequenceInProgress && id == m_currentState.m_idSnapshotSet)
  2502. {
  2503. // get state for current snapshot set
  2504. state = m_currentState;
  2505. }
  2506. else
  2507. {
  2508. // return state for a previously created snapshot set
  2509. // Search for the previous sequence with the same ID
  2510. INT nPreviousSequence = SearchForPreviousSequence(id);
  2511. if (nPreviousSequence == INVALID_SEQUENCE_INDEX)
  2512. {
  2513. // don't have any information about the snapshot set
  2514. state.m_idSnapshotSet = id;
  2515. state.m_bInOperation = false;
  2516. state.m_state = VSS_WS_UNKNOWN;
  2517. state.m_hrWriterFailure = E_UNEXPECTED;
  2518. }
  2519. else
  2520. {
  2521. BS_ASSERT(m_rgPreviousStates[nPreviousSequence].m_idSnapshotSet == id);
  2522. // return state from snapshot set
  2523. state = m_rgPreviousStates[nPreviousSequence];
  2524. }
  2525. }
  2526. }
  2527. // handle completion of the BackupComplete state.
  2528. void CVssWriterState::FinishBackupComplete(const VSS_ID &id)
  2529. {
  2530. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterState::FinishBackupComplete");
  2531. // lock class
  2532. CVssSafeAutomaticLock lock(m_cs);
  2533. // We must search for a previous state - Thaw already ended the sequence.
  2534. INT iPreviousSequence = SearchForPreviousSequence(id);
  2535. if (iPreviousSequence == INVALID_SEQUENCE_INDEX)
  2536. {
  2537. // couldn't find snapshot set. We will indicate that this is
  2538. // a retryable error
  2539. SetCurrentFailure(VSS_E_WRITERERROR_RETRYABLE);
  2540. // unlock class before throwing
  2541. ft.Throw
  2542. (
  2543. VSSDBG_WRITER,
  2544. E_UNEXPECTED,
  2545. L"Couldn't find a previous sequence with the same Snapshot Set ID"
  2546. );
  2547. }
  2548. // We found a previous sequence with the same SSID.
  2549. BS_ASSERT(id == m_rgPreviousStates[iPreviousSequence].m_idSnapshotSet);
  2550. // BUG 228622 - If we do not have a previous successful Thaw transition
  2551. // then we cannot call BackupComplete
  2552. if (m_rgPreviousStates[iPreviousSequence].m_state != VSS_WS_WAITING_FOR_BACKUP_COMPLETE)
  2553. {
  2554. SetCurrentFailure(VSS_E_WRITERERROR_RETRYABLE);
  2555. ft.Throw
  2556. (
  2557. VSSDBG_WRITER,
  2558. E_UNEXPECTED,
  2559. L"Couldn't call BackupComplete without OnThaw as a previous state [%d]",
  2560. m_rgPreviousStates[iPreviousSequence].m_state
  2561. );
  2562. }
  2563. // BUG 219692 - indicate that sequence is complete even in the saved states
  2564. m_rgPreviousStates[iPreviousSequence].m_state = VSS_WS_STABLE;
  2565. m_rgPreviousStates[iPreviousSequence].m_bInOperation = true;
  2566. m_rgPreviousStates[iPreviousSequence].m_currentOperation = VSS_IN_BACKUPCOMPLETE;
  2567. }
  2568. // indicate that backup complete failed
  2569. void CVssWriterState::SetBackupCompleteStatus(const VSS_ID &id, HRESULT hr)
  2570. {
  2571. CVssFunctionTracer ft(VSSDBG_WRITER, L"CVssWriterState::SetBackupCompleteFailed");
  2572. // lock class
  2573. CVssSafeAutomaticLock lock(m_cs);
  2574. // We must search for a previous state - Thaw already ended the sequence.
  2575. INT iPreviousSequence = SearchForPreviousSequence(id);
  2576. if (iPreviousSequence == INVALID_SEQUENCE_INDEX)
  2577. return;
  2578. // We found a previous sequence with the same SSID.
  2579. BS_ASSERT(id == m_rgPreviousStates[iPreviousSequence].m_idSnapshotSet);
  2580. if (m_rgPreviousStates[iPreviousSequence].m_state == VSS_WS_STABLE ||
  2581. m_rgPreviousStates[iPreviousSequence].m_state == VSS_WS_WAITING_FOR_BACKUP_COMPLETE)
  2582. {
  2583. if (FAILED(hr))
  2584. {
  2585. // indicate failure and use current failure as the backup completion failure
  2586. m_rgPreviousStates[iPreviousSequence].m_state = VSS_WS_FAILED_AT_BACKUP_COMPLETE;
  2587. m_rgPreviousStates[iPreviousSequence].m_hrWriterFailure = m_currentState.m_hrWriterFailure;
  2588. }
  2589. m_rgPreviousStates[iPreviousSequence].m_bInOperation = false;
  2590. }
  2591. }
  2592. // no response error. It first checks to see if we are still
  2593. // in the operation. If not, then we need to retry obtaining
  2594. // the writer's state
  2595. bool CVssWriterState::SetNoResponseFailure(
  2596. IN const VSS_ID &id,
  2597. IN const VSWRITER_STATE &state
  2598. )
  2599. {
  2600. // lock object
  2601. CVssSafeAutomaticLock lock(m_cs);
  2602. if (m_currentState.m_idSnapshotSet == state.m_idSnapshotSet)
  2603. {
  2604. if (!m_currentState.m_bInOperation ||
  2605. m_currentState.m_currentOperation != state.m_currentOperation)
  2606. {
  2607. // no longer in the operation. Should not return a no-response
  2608. // failure. Instead requery the current state
  2609. return false;
  2610. }
  2611. // This should apply only if the ID is the current snapshot set ID
  2612. //
  2613. // The logic is that the writer is now hung from the backup app point of view.
  2614. // We need to set the correct state now, so that the backup app knows what's wrong.
  2615. //
  2616. if ((m_currentState.m_idSnapshotSet == id) && (GUID_NULL != id))
  2617. {
  2618. SetCurrentFailure(VSS_E_WRITER_NOT_RESPONDING);
  2619. SetCurrentState(state.m_state);
  2620. }
  2621. return true;
  2622. }
  2623. INT iPreviousSequence = SearchForPreviousSequence(state.m_idSnapshotSet);
  2624. if (iPreviousSequence == INVALID_SEQUENCE_INDEX)
  2625. return true;
  2626. VSWRITER_STATE *pState = &m_rgPreviousStates[iPreviousSequence];
  2627. if (!pState->m_bInOperation ||
  2628. pState->m_currentOperation != state.m_currentOperation)
  2629. {
  2630. // no longer in the operation. We should not return an no-response
  2631. // failure. Instead requery the state of the snapshot set.
  2632. return false;
  2633. }
  2634. // indicate that writer is not responding
  2635. pState->m_hrWriterFailure = VSS_E_WRITER_NOT_RESPONDING;
  2636. // get last known state of writer
  2637. pState->m_state = state.m_state;
  2638. return true;
  2639. }
  2640. //////////////////////////////////////////////////////////////////////////
  2641. // Auto diag class
  2642. // Constructor
  2643. CVssAutoDiagLogger::CVssAutoDiagLogger(
  2644. IN CVssWriterState & state,
  2645. IN DWORD dwEventID,
  2646. IN VSS_ID ssid, /* = GUID_NULL */
  2647. IN DWORD dwEventFlags /* = 0 */
  2648. ):
  2649. m_state(state),
  2650. m_dwEventID(dwEventID),
  2651. m_ssid(ssid),
  2652. m_dwEventFlags(dwEventFlags)
  2653. {
  2654. m_state.GetDiag().RecordGenericEvent(m_dwEventID,
  2655. CVssDiag::VSS_DIAG_ENTER_OPERATION,
  2656. m_state.GetCurrentState(),
  2657. m_state.GetCurrentFailure(),
  2658. m_ssid);
  2659. }
  2660. // Constructor
  2661. CVssAutoDiagLogger::CVssAutoDiagLogger(
  2662. IN CVssWriterState & state,
  2663. IN DWORD dwEventID,
  2664. IN WCHAR* pwszSSID,
  2665. IN DWORD dwEventFlags /* = 0 */
  2666. ):
  2667. m_state(state),
  2668. m_dwEventID(dwEventID),
  2669. m_ssid(GUID_NULL),
  2670. m_dwEventFlags(dwEventFlags)
  2671. {
  2672. // Try to read the SSID
  2673. if (pwszSSID)
  2674. ::CLSIDFromString(W2OLE(pwszSSID), &m_ssid);
  2675. m_state.GetDiag().RecordGenericEvent(m_dwEventID,
  2676. CVssDiag::VSS_DIAG_ENTER_OPERATION | m_dwEventFlags,
  2677. m_state.GetCurrentState(),
  2678. m_state.GetCurrentFailure(),
  2679. m_ssid);
  2680. }
  2681. // Destructor
  2682. CVssAutoDiagLogger::~CVssAutoDiagLogger()
  2683. {
  2684. m_state.GetDiag().RecordGenericEvent(m_dwEventID,
  2685. CVssDiag::VSS_DIAG_LEAVE_OPERATION | m_dwEventFlags,
  2686. m_state.GetCurrentState(),
  2687. m_state.GetCurrentFailure(),
  2688. m_ssid);
  2689. }