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.

793 lines
19 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Abstract:
  4. @doc
  5. @module Writer.h | Declaration of Writer
  6. @end
  7. Author:
  8. Adi Oltean [aoltean] 08/18/1999
  9. TBD:
  10. Add comments.
  11. Revision History:
  12. Name Date Comments
  13. aoltean 08/18/1999 Created
  14. brianb 05/03/2000 Changed for new security model
  15. brianb 05/09/2000 fix problem with autolocks
  16. mikejohn 06/23/2000 Add connection for SetWriterFailure()
  17. --*/
  18. #ifndef __CVSS_WRITER_IMPL_H_
  19. #define __CVSS_WRITER_IMPL_H_
  20. // forward declarations
  21. class CVssWriterImplStateMachine;
  22. class CVssCreateWriterMetadata;
  23. class CVssWriterComponents;
  24. class IVssWriterComponentsInt;
  25. ////////////////////////////////////////////////////////////////////////
  26. // Standard foo for file name aliasing. This code block must be after
  27. // all includes of VSS header files.
  28. //
  29. #ifdef VSS_FILE_ALIAS
  30. #undef VSS_FILE_ALIAS
  31. #endif
  32. #define VSS_FILE_ALIAS "INCWRMPH"
  33. //
  34. ////////////////////////////////////////////////////////////////////////
  35. // implementation class for writers
  36. class IVssWriterImpl : public IVssWriter
  37. {
  38. public:
  39. // initialize writer
  40. virtual void Initialize
  41. (
  42. VSS_ID writerId,
  43. LPCWSTR wszWriterName,
  44. VSS_USAGE_TYPE ut,
  45. VSS_SOURCE_TYPE st,
  46. VSS_APPLICATION_LEVEL nLevel,
  47. DWORD dwTimeout
  48. ) = 0;
  49. // subscribe to events
  50. virtual void Subscribe
  51. (
  52. ) = 0;
  53. // unsubscribe from events
  54. virtual void Unsubscribe
  55. (
  56. ) = 0;
  57. virtual void Uninitialize
  58. (
  59. ) = 0;
  60. // get array of volume names
  61. virtual LPCWSTR *GetCurrentVolumeArray() const = 0;
  62. // get # of volumes in volume array
  63. virtual UINT GetCurrentVolumeCount() const = 0;
  64. // get the snapshot device name for a particular volume
  65. virtual HRESULT GetSnapshotDeviceName
  66. (
  67. LPCWSTR wszOriginalVolume,
  68. LPCWSTR* ppwszSnapshotDevice
  69. ) const = 0;
  70. // get id of snapshot set
  71. virtual VSS_ID GetCurrentSnapshotSetId() const = 0;
  72. // get the current backup context
  73. virtual LONG GetContext() const = 0;
  74. // determine which Freeze event writer responds to
  75. virtual VSS_APPLICATION_LEVEL GetCurrentLevel() const = 0;
  76. // determine if path is included in the snapshot
  77. virtual bool IsPathAffected(IN LPCWSTR wszPath) const = 0;
  78. // determine if bootable state is backed up
  79. virtual bool IsBootableSystemStateBackedUp() const = 0;
  80. // determine if the backup application is selecting components
  81. virtual bool AreComponentsSelected() const = 0;
  82. // determine the backup type for the backup
  83. virtual VSS_BACKUP_TYPE GetBackupType() const = 0;
  84. // determine the type of restore
  85. virtual VSS_RESTORE_TYPE GetRestoreType() const = 0;
  86. // let writer pass back indication of reason for failure
  87. virtual HRESULT SetWriterFailure(HRESULT hr) = 0;
  88. // determine if requestor support partial file backups
  89. virtual bool IsPartialFileSupportEnabled() const = 0;
  90. };
  91. // writer state structure. encapsulates state of this writer for a
  92. // specific snapshot set
  93. typedef struct _VSWRITER_STATE
  94. {
  95. // snapshot id
  96. VSS_ID m_idSnapshotSet;
  97. // writer state
  98. volatile VSS_WRITER_STATE m_state;
  99. // reason for writer failure
  100. volatile HRESULT m_hrWriterFailure;
  101. // are we currently in an operation
  102. volatile bool m_bInOperation;
  103. // current operation
  104. volatile VSS_OPERATION m_currentOperation;
  105. } VSWRITER_STATE;
  106. class CVssWriterState;
  107. //////////////////////////////////////////////////////////////////////////
  108. // Auto diag class
  109. class CVssAutoDiagLogger
  110. {
  111. public:
  112. // Constructor
  113. CVssAutoDiagLogger(
  114. IN CVssWriterState & state,
  115. IN DWORD dwEventID,
  116. IN VSS_ID ssid = GUID_NULL,
  117. IN DWORD dwEventFlags = 0
  118. );
  119. // Constructor
  120. CVssAutoDiagLogger(
  121. IN CVssWriterState & state,
  122. IN DWORD dwEventID,
  123. IN WCHAR* pwszSSID,
  124. IN DWORD dwEventFlags = 0
  125. );
  126. // Destructor
  127. ~CVssAutoDiagLogger();
  128. private:
  129. CVssAutoDiagLogger( const CVssAutoDiagLogger& );
  130. void operator = ( const CVssAutoDiagLogger& );
  131. CVssWriterState & m_state;
  132. DWORD m_dwEventID;
  133. DWORD m_dwEventFlags;
  134. VSS_ID m_ssid;
  135. };
  136. //////////////////////////////////////////////////////////////////////////
  137. // writer state class. encapsulates all aspects of a writer's state
  138. class CVssWriterState
  139. {
  140. private:
  141. CVssWriterState();
  142. CVssWriterState(const CVssWriterState&);
  143. public:
  144. // constructors and destructors
  145. CVssWriterState( IN CVssDiag& diag );
  146. // initialization function
  147. void Initialize()
  148. {
  149. m_cs.Init();
  150. }
  151. // get state for a snapshot set
  152. void GetStateForSnapshot
  153. (
  154. IN const VSS_ID &idSnapshot,
  155. OUT VSWRITER_STATE &state
  156. );
  157. // initialize a snapshot
  158. void InitializeCurrentState(IN const VSS_ID &idSnapshot);
  159. // indicate we are in an operation
  160. void SetInOperation(VSS_OPERATION operation)
  161. {
  162. CVssSafeAutomaticLock lock(m_cs);
  163. m_currentState.m_bInOperation = true;
  164. m_currentState.m_currentOperation = operation;
  165. }
  166. // are we in a restore operation
  167. bool IsInRestore()
  168. {
  169. return (m_currentState.m_currentOperation == VSS_IN_PRERESTORE ||
  170. m_currentState.m_currentOperation == VSS_IN_POSTRESTORE);
  171. }
  172. // indicate that we are leaving an operation
  173. void ExitOperation()
  174. {
  175. CVssSafeAutomaticLock lock(m_cs);
  176. m_currentState.m_bInOperation = false;
  177. }
  178. // push the current state onto the recent snapshot set stack
  179. void PushCurrentState();
  180. // set the current state
  181. void SetCurrentState(IN VSS_WRITER_STATE state)
  182. {
  183. CVssSafeAutomaticLock lock(m_cs);
  184. CVssAutoDiagLogger logger(*this, state,
  185. GetCurrentSnapshotSet(),
  186. CVssDiag::VSS_DIAG_IGNORE_LEAVE
  187. | CVssDiag::VSS_DIAG_IS_STATE);
  188. m_currentState.m_state = state;
  189. }
  190. // get current state
  191. VSS_WRITER_STATE GetCurrentState()
  192. {
  193. return m_currentState.m_state;
  194. }
  195. // set current failure
  196. void SetCurrentFailure(IN HRESULT hrWriterFailure)
  197. {
  198. CVssSafeAutomaticLock lock(m_cs);
  199. // Make sure S_OK is translated
  200. CVssAutoDiagLogger logger(*this,
  201. hrWriterFailure? hrWriterFailure: VSS_S_OK,
  202. GetCurrentSnapshotSet(),
  203. CVssDiag::VSS_DIAG_IGNORE_LEAVE
  204. | CVssDiag::VSS_DIAG_IS_HRESULT);
  205. m_currentState.m_hrWriterFailure = hrWriterFailure;
  206. }
  207. // obtain the current failure
  208. HRESULT GetCurrentFailure()
  209. {
  210. return m_currentState.m_hrWriterFailure;
  211. }
  212. // obtain the snapshot set for the current state
  213. VSS_ID GetCurrentSnapshotSet()
  214. {
  215. return m_currentState.m_idSnapshotSet;
  216. }
  217. // handle backup complete state transition to being stable
  218. void FinishBackupComplete(const VSS_ID &id);
  219. // indicate that backup complete failed
  220. void SetBackupCompleteStatus(const VSS_ID &id, HRESULT hr);
  221. // determine if a snapshot set id is in the cache of previous
  222. // snapshot sets
  223. bool CVssWriterState::IsSnapshotSetIdValid(VSS_ID &id)
  224. {
  225. CVssSafeAutomaticLock lock(m_cs);
  226. INT nPrevious = SearchForPreviousSequence(id);
  227. return nPrevious != INVALID_SEQUENCE_INDEX;
  228. }
  229. // set a failure in the case where a writer is returning a
  230. // no response error. It first checks to see if we are still
  231. // in the operation. If not, then we need to retry obtaining
  232. // the writer's state
  233. bool SetNoResponseFailure(
  234. IN const VSS_ID &id,
  235. IN const VSWRITER_STATE &state
  236. );
  237. CVssDiag & GetDiag() { return m_diag; };
  238. private:
  239. // search for a previous state
  240. INT SearchForPreviousSequence(IN const VSS_ID& idSnapshotSet);
  241. // critical section protecting class
  242. CVssSafeCriticalSection m_cs;
  243. // current state
  244. VSWRITER_STATE m_currentState;
  245. // structures to keep track of writer status from previous snapshots
  246. enum
  247. {
  248. MAX_PREVIOUS_SNAPSHOTS = 8,
  249. INVALID_SEQUENCE_INDEX = -1
  250. };
  251. // previous states
  252. VSWRITER_STATE m_rgPreviousStates[MAX_PREVIOUS_SNAPSHOTS];
  253. // current slot for dumping a previous snapshots result
  254. volatile UINT m_iPreviousSnapshots;
  255. // are we currently in a sequence
  256. volatile bool m_bSequenceInProgress;
  257. CVssDiag & m_diag;
  258. };
  259. /////////////////////////////////////////////////////////////////////////////
  260. // CVssWriterImpl
  261. class ATL_NO_VTABLE CVssWriterImpl :
  262. public CComObjectRootEx<CComMultiThreadModel>,
  263. public IVssWriterImpl
  264. {
  265. public:
  266. friend class CVssWriterImplLock;
  267. // Constructors & Destructors
  268. CVssWriterImpl();
  269. ~CVssWriterImpl();
  270. // Exposed operations
  271. public:
  272. // create a writer implementation for a specific writer
  273. static void CreateWriter
  274. (
  275. CVssWriter *pWriter,
  276. IVssWriterImpl **ppImpl
  277. );
  278. // set external writer object
  279. void SetWriter(CVssWriter *pWriter)
  280. {
  281. BS_ASSERT(pWriter);
  282. m_pWriter = pWriter;
  283. }
  284. // initialize class
  285. void Initialize
  286. (
  287. IN VSS_ID WriterID,
  288. IN LPCWSTR wszWriterName,
  289. IN VSS_USAGE_TYPE ut,
  290. IN VSS_SOURCE_TYPE st,
  291. IN VSS_APPLICATION_LEVEL nLevel,
  292. IN DWORD dwTimeoutFreeze
  293. );
  294. // subscribe to writer events
  295. void Subscribe
  296. (
  297. );
  298. // unsubscribe from writer events
  299. void Unsubscribe();
  300. // uninitialize the writer
  301. void Uninitialize();
  302. // get array of volume names
  303. LPCWSTR* GetCurrentVolumeArray() const { return (LPCWSTR *) m_ppwszVolumesArray; };
  304. // get count of volumes in array
  305. UINT GetCurrentVolumeCount() const { return m_nVolumesCount; };
  306. // get the snapshot device name for a particular volume
  307. HRESULT GetSnapshotDeviceName
  308. (
  309. LPCWSTR wszOriginalVolume,
  310. LPCWSTR* ppwszSnapshotDevice
  311. ) const;
  312. // get id of snapshot
  313. VSS_ID GetCurrentSnapshotSetId() const { return m_CurrentSnapshotSetId; };
  314. // get the current backup context
  315. LONG GetContext() const { return m_lContext; }
  316. // get level at which freeze takes place
  317. VSS_APPLICATION_LEVEL GetCurrentLevel() const { return m_nLevel; };
  318. // determine if path is included in the snapshot
  319. bool IsPathAffected(IN LPCWSTR wszPath) const;
  320. // determine if the backup is including bootable system state
  321. bool IsBootableSystemStateBackedUp() const
  322. { return m_bBootableSystemStateBackup ? true : false; }
  323. // determine if the backup selects components
  324. bool AreComponentsSelected() const
  325. { return m_bComponentsSelected ? true : false; }
  326. // return the type of backup
  327. VSS_BACKUP_TYPE GetBackupType() const { return m_backupType; }
  328. VSS_RESTORE_TYPE GetRestoreType() const { return m_restoreType; }
  329. // indicate why the writer failed
  330. HRESULT SetWriterFailure(HRESULT hr);
  331. // does requestor support partial file backups and restores
  332. bool IsPartialFileSupportEnabled() const
  333. {
  334. return m_bPartialFileSupport ? true : false;
  335. }
  336. // IVssWriter ovverides
  337. public:
  338. BEGIN_COM_MAP(CVssWriterImpl)
  339. COM_INTERFACE_ENTRY(IVssWriter)
  340. END_COM_MAP()
  341. // request WRITER_METADATA or writer state
  342. STDMETHOD(RequestWriterInfo)(
  343. IN BSTR bstrSnapshotSetId,
  344. IN BOOL bWriterMetadata,
  345. IN BOOL bWriterState,
  346. IN IDispatch* pWriterCallback
  347. );
  348. // prepare for backup event
  349. STDMETHOD(PrepareForBackup)(
  350. IN BSTR bstrSnapshotSetId,
  351. IN IDispatch* pWriterCallback
  352. );
  353. // prepare for snapshot event
  354. STDMETHOD(PrepareForSnapshot)(
  355. IN BSTR bstrSnapshotSetId,
  356. IN BSTR VolumeNamesList
  357. );
  358. // freeze event
  359. STDMETHOD(Freeze)(
  360. IN BSTR bstrSnapshotSetId,
  361. IN INT nApplicationLevel
  362. );
  363. // thaw event
  364. STDMETHOD(Thaw)(
  365. IN BSTR bstrSnapshotSetId
  366. );
  367. STDMETHOD(PostSnapshot)(
  368. IN BSTR bstrSnapshotSetId,
  369. IN IDispatch *pWriterCallback,
  370. IN BSTR SnapshotDevicesList
  371. );
  372. // backup complete event
  373. STDMETHOD(BackupComplete)(
  374. IN BSTR bstrSnapshotSetId,
  375. IN IDispatch* pWriterCallback
  376. );
  377. // backup shutdown event
  378. STDMETHOD(BackupShutdown)(
  379. IN BSTR bstrSnapshotSetId
  380. );
  381. // abort event
  382. STDMETHOD(Abort)(
  383. IN BSTR bstrSnapshotSetId
  384. );
  385. STDMETHOD(PreRestore)(
  386. IN IDispatch* pWriterCallback
  387. );
  388. STDMETHOD(PostRestore)(
  389. IN IDispatch* pWriterCallback
  390. );
  391. // Implementation - methods
  392. private:
  393. enum VSS_EVENT_MASK
  394. {
  395. VSS_EVENT_PREPAREBACKUP = 0x00000001,
  396. VSS_EVENT_PREPARESNAPSHOT = 0x00000002,
  397. VSS_EVENT_FREEZE = 0x00000004,
  398. VSS_EVENT_THAW = 0x00000008,
  399. VSS_EVENT_POST_SNAPSHOT = 0x00000010,
  400. VSS_EVENT_ABORT = 0x00000020,
  401. VSS_EVENT_BACKUPCOMPLETE = 0x00000040,
  402. VSS_EVENT_REQUESTINFO = 0x00000080,
  403. VSS_EVENT_PRERESTORE = 0x00000100,
  404. VSS_EVENT_POSTRESTORE = 0x00000200,
  405. VSS_EVENT_BACKUPSHUTDOWN = 0x00000400,
  406. VSS_EVENT_ALL = 0x7ff,
  407. };
  408. // get WRITER callback from IDispatch
  409. void GetCallback
  410. (
  411. IN IDispatch *pWriterCallback,
  412. OUT IVssWriterCallback **ppCallback,
  413. IN BOOL bAllowImpersonate = FALSE
  414. );
  415. // reset state machine
  416. void ResetSequence
  417. (
  418. IN bool bCalledFromTimerThread
  419. );
  420. // abort the current snapshot sequence
  421. void DoAbort
  422. (
  423. IN bool bCalledFromTimerThread,
  424. IN BSTR strSnapshotSetId = NULL
  425. );
  426. // obtain components for this writer
  427. void InternalGetWriterComponents
  428. (
  429. IN IVssWriterCallback *pCallback,
  430. OUT IVssWriterComponentsInt **ppWriter,
  431. IN bool bWriteable,
  432. IN bool bInRestore
  433. );
  434. void SaveChangedComponents
  435. (
  436. IN IVssWriterCallback *pCallback,
  437. IN bool bInRestore,
  438. IN IVssWriterComponentsInt *pComponents
  439. );
  440. // create WRITER_METADATA XML document
  441. CVssCreateWriterMetadata *CreateBasicWriterMetadata();
  442. // startup routine for timer thread
  443. static DWORD StartTimerThread(void *pv);
  444. // function to run in timer thread
  445. void TimerFunc(VSS_ID id);
  446. // enter a state
  447. bool EnterState
  448. (
  449. IN const CVssWriterImplStateMachine &vwsm,
  450. IN BSTR bstrSnapshotSetId
  451. ) throw(HRESULT);
  452. // leave a state
  453. void LeaveState
  454. (
  455. IN const CVssWriterImplStateMachine &vwsm,
  456. IN bool fSuccessful
  457. );
  458. // create a Handle to an event
  459. void SetupEvent
  460. (
  461. IN HANDLE *phevt
  462. ) throw(HRESULT);
  463. // begin a sequence to create a snapshot
  464. void BeginSequence
  465. (
  466. IN CVssID &SnapshotSetId
  467. ) throw(HRESULT);
  468. // terminate timer thread
  469. void TerminateTimerThread();
  470. // lock critical section
  471. inline void Lock()
  472. {
  473. m_cs.Lock();
  474. m_bLocked = true;
  475. }
  476. // unlock critical section
  477. inline void Unlock()
  478. {
  479. m_bLocked = false;
  480. m_cs.Unlock();
  481. }
  482. // assert that critical section is locked
  483. inline void AssertLocked()
  484. {
  485. BS_ASSERT(m_bLocked);
  486. }
  487. // Implementation - members
  488. private:
  489. enum VSS_TIMER_COMMAND
  490. {
  491. VSS_TC_UNDEFINED,
  492. VSS_TC_ABORT_CURRENT_SEQUENCE,
  493. VSS_TC_TERMINATE_THREAD,
  494. VSS_TIMEOUT_FREEZE = 120*1000, // two minutes
  495. VSS_STACK_SIZE = 256 * 1024 // 256K
  496. };
  497. enum
  498. {
  499. x_MAX_SUBSCRIPTIONS = 32
  500. };
  501. // data related to writer
  502. // writer class id
  503. VSS_ID m_WriterID;
  504. // writer instance id
  505. VSS_ID m_InstanceID;
  506. // usage type for writer
  507. VSS_USAGE_TYPE m_usage;
  508. // data source type for writer
  509. VSS_SOURCE_TYPE m_source;
  510. // writer name
  511. LPWSTR m_wszWriterName;
  512. // Data related to the current sequence
  513. // snapshot set id
  514. VSS_ID m_CurrentSnapshotSetId;
  515. // context
  516. LONG m_lContext;
  517. // volume array list passed in as a string
  518. LPWSTR m_pwszLocalVolumeNameList;
  519. // # of volumes in volume array
  520. INT m_nVolumesCount;
  521. // volume array
  522. LPWSTR* m_ppwszVolumesArray;
  523. // Subscription-related data
  524. CComBSTR m_bstrSubscriptionName;
  525. // actual subscription ids
  526. CComBSTR m_rgbstrSubscriptionId[x_MAX_SUBSCRIPTIONS];
  527. // number of allocated subscription ids
  528. UINT m_cbstrSubscriptionId;
  529. // Data related with the Writer object
  530. // which freeze event is handled
  531. VSS_APPLICATION_LEVEL m_nLevel;
  532. // what events are subscribed to
  533. DWORD m_dwEventMask;
  534. // Critical section or avoiding race between tasks
  535. CVssSafeCriticalSection m_cs;
  536. // was critical section initialized
  537. bool m_bLockCreated;
  538. // flag indicating if critical section is locked
  539. bool m_bLocked;
  540. // timeout and queuing mechanisms
  541. HANDLE m_hevtTimerThread; // event used to signal timer thread if timer is aborted
  542. HANDLE m_hmtxTimerThread; // mutex used to guarantee only one timer thread exists at a time
  543. HANDLE m_hThreadTimerThread; // handle to timer thread
  544. VSS_TIMER_COMMAND m_command; // timer command when it exits the wait
  545. DWORD m_dwTimeoutFreeze; // timeout for freeze
  546. // actual writer implementation
  547. CVssWriter *m_pWriter;
  548. // state of backup components
  549. BOOL m_bBootableSystemStateBackup;
  550. BOOL m_bComponentsSelected;
  551. VSS_BACKUP_TYPE m_backupType;
  552. VSS_RESTORE_TYPE m_restoreType;
  553. BOOL m_bPartialFileSupport;
  554. // state of writer
  555. CVssWriterState m_writerstate;
  556. // TRUE if an OnPrepareForBackup/Freeze/Thaw
  557. // was sent and without a corresponding OnAbort
  558. bool m_bOnAbortPermitted;
  559. // is a sequence in progress
  560. bool m_bSequenceInProgress;
  561. // current state
  562. CVssSidCollection m_SidCollection;
  563. // Initialization flag
  564. bool m_bInitialized;
  565. // This flags are TRUE only during Setup/SafeMode
  566. bool m_bInSafeMode;
  567. bool m_bInSetup;
  568. // Diagnose tool
  569. CVssDiag m_diag;
  570. };
  571. // auto class for locks
  572. class CVssWriterImplLock
  573. {
  574. public:
  575. CVssWriterImplLock(CVssWriterImpl *pImpl) :
  576. m_pImpl(pImpl)
  577. {
  578. m_pImpl->Lock();
  579. }
  580. ~CVssWriterImplLock()
  581. {
  582. m_pImpl->Unlock();
  583. }
  584. private:
  585. CVssWriterImpl *m_pImpl;
  586. };
  587. #endif //__CVSS_WRITER_IMPL_H_