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.

632 lines
15 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Abstract:
  4. @doc
  5. @module async.cxx | Implementation of CVssAsyncBackup object
  6. @end
  7. Author:
  8. brian berkowitz [brianb] 04/10/2000
  9. Revision History:
  10. Name Date Comments
  11. brianb 04/10/2000 Created
  12. --*/
  13. /////////////////////////////////////////////////////////////////////////////
  14. // Includes
  15. #include "stdafx.hxx"
  16. #include "vs_inc.hxx"
  17. #include "vs_sec.hxx"
  18. #include "vs_idl.hxx"
  19. #include "vswriter.h"
  20. #include "vsbackup.h"
  21. #include "vs_wmxml.hxx"
  22. #include "vs_cmxml.hxx"
  23. #include "worker.hxx"
  24. #include "async.hxx"
  25. #include "vssmsg.h"
  26. ////////////////////////////////////////////////////////////////////////
  27. // Standard foo for file name aliasing. This code block must be after
  28. // all includes of VSS header files.
  29. //
  30. #ifdef VSS_FILE_ALIAS
  31. #undef VSS_FILE_ALIAS
  32. #endif
  33. #define VSS_FILE_ALIAS "BUEASYNC"
  34. //
  35. ////////////////////////////////////////////////////////////////////////
  36. /////////////////////////////////////////////////////////////////////////////
  37. // CVssAsyncBackup
  38. // constructor
  39. CVssAsyncBackup::CVssAsyncBackup():
  40. m_hrState(S_OK),
  41. m_state(VSS_AS_UNDEFINED),
  42. m_pBackupComponents(NULL),
  43. m_bOwned(NULL)
  44. {
  45. CVssFunctionTracer ft(VSSDBG_XML, L"CVssAsyncBackup::CVssAsyncBackup");
  46. m_bcsInitialized = false;
  47. try
  48. {
  49. // Initialize the critical section
  50. m_cs.Init();
  51. m_bcsInitialized = true;
  52. }
  53. VSS_STANDARD_CATCH(ft)
  54. }
  55. // destructor
  56. CVssAsyncBackup::~CVssAsyncBackup()
  57. {
  58. CVssFunctionTracer ft(VSSDBG_XML, L"CVssAsyncBackup::~CVssAsyncBackup");
  59. try
  60. {
  61. // Wait for the worker thread to finish, if running.
  62. // WARNING: FinalReleaseWorkerThreadObject uses virtual methods!
  63. // Virtual methods in classes derived from CVssAsync are now inaccessible!
  64. FinalReleaseWorkerThreadObject();
  65. }
  66. VSS_STANDARD_CATCH(ft)
  67. }
  68. // do operation by creating a thread to do it and return an IVssAsync object
  69. // for backup to use
  70. IVssAsync* CVssAsyncBackup::CreateInstanceAndStartJob
  71. (
  72. IN CVssBackupComponents * pBackupComponents,
  73. VSS_ASYNC_STATE state
  74. )
  75. {
  76. CVssFunctionTracer ft(VSSDBG_XML, L"CVssAsyncBackup::CreateInstanceAndStartJob" );
  77. CComPtr<IVssAsync> pAsync;
  78. try
  79. {
  80. BS_ASSERT(state == VSS_AS_PREPARE_FOR_BACKUP ||
  81. state == VSS_AS_BACKUP_COMPLETE ||
  82. state == VSS_AS_RESTORE ||
  83. state == VSS_AS_GATHER_WRITER_METADATA ||
  84. state == VSS_AS_GATHER_WRITER_STATUS);
  85. BS_ASSERT(pBackupComponents);
  86. // Allocate the COM object.
  87. CComObject<CVssAsyncBackup>* pObject;
  88. ft.hr = CComObject<CVssAsyncBackup>::CreateInstance(&pObject);
  89. if (ft.HrFailed())
  90. ft.Throw
  91. (
  92. VSSDBG_XML,
  93. E_OUTOFMEMORY,
  94. L"Error creating the CVssAsync instance. hr = 0x%08lx", ft.hr
  95. );
  96. if (!pObject->m_bcsInitialized)
  97. ft.Throw
  98. (
  99. VSSDBG_XML,
  100. E_OUTOFMEMORY,
  101. L"Error initializing critical section"
  102. );
  103. BS_ASSERT(pObject);
  104. // Setting async object internal data
  105. pObject->m_pBackupComponents = pBackupComponents;
  106. pObject->m_pvbcReference = pBackupComponents;
  107. pObject->m_state = state;
  108. // Querying the IVssSnapshot interface. Now the ref count becomes 1.
  109. CComPtr<IUnknown> pUnknown = pObject->GetUnknown();
  110. BS_ASSERT(pUnknown);
  111. ft.hr = pUnknown->SafeQI(IVssAsync, &pAsync); // The ref count is 2.
  112. if (ft.HrFailed())
  113. {
  114. ft.LogError(VSS_ERROR_QI_IVSSASYNC_FAILED, VSSDBG_XML << ft.hr);
  115. ft.Throw
  116. (
  117. VSSDBG_XML,
  118. E_UNEXPECTED,
  119. L"Error querying the IVssAsync interface. hr = 0x%08lx",
  120. ft.hr
  121. );
  122. }
  123. BS_ASSERT(pAsync);
  124. // Prepare job (thread created in resume state)
  125. ft.hr = pObject->PrepareJob();
  126. if (ft.HrFailed())
  127. ft.Throw
  128. (
  129. VSSDBG_XML,
  130. ft.hr,
  131. L"CVssAsyncBackup::PrepareJob failed. hr = 0x%08lx.",
  132. ft.hr
  133. );
  134. // increment reference count so that it lives throughout lifetime
  135. // of async thread
  136. pObject->GetUnknown()->AddRef();
  137. pObject->SetOwned();
  138. // Start job
  139. ft.hr = pObject->StartJob();
  140. if (ft.HrFailed())
  141. {
  142. // release reference held for thread
  143. pObject->ClearOwned();
  144. pObject->GetUnknown()->Release();
  145. ft.Throw
  146. (
  147. VSSDBG_XML,
  148. ft.hr,
  149. L"Error starting the job. hr = 0x%08lx",
  150. ft.hr
  151. );
  152. }
  153. // Now the background thread related members (m_hrState, m_nPercentDone) begin to update.
  154. }
  155. VSS_STANDARD_CATCH(ft)
  156. return pAsync.Detach(); // The ref count remains 1.
  157. }
  158. /////////////////////////////////////////////////////////////////////////////
  159. // CVssWorkerThread overrides
  160. // do basic initialization
  161. bool CVssAsyncBackup::OnInit()
  162. {
  163. CVssFunctionTracer ft(VSSDBG_XML, L"CVssAsyncBackup::OnInit");
  164. try
  165. {
  166. if (m_pBackupComponents != NULL)
  167. {
  168. BS_ASSERT(m_hrState == S_OK);
  169. m_hrState = VSS_S_ASYNC_PENDING;
  170. }
  171. }
  172. VSS_STANDARD_CATCH(ft)
  173. return m_pBackupComponents != NULL;
  174. }
  175. // execute PrepareForBackup or BackupComplete
  176. void CVssAsyncBackup::OnRun()
  177. {
  178. CVssFunctionTracer ft(VSSDBG_XML, L"CVssAsyncBackup::OnRun");
  179. bool bCoInitializeSucceeded = false;
  180. try
  181. {
  182. // Check if the backup components object is created.
  183. if (m_pBackupComponents == NULL)
  184. {
  185. ft.LogError(VSS_ERROR_BACKUPCOMPONENTS_NULL, VSSDBG_XML);
  186. ft.Throw(VSSDBG_XML, E_UNEXPECTED, L"BackupComponents object is NULL.");
  187. }
  188. ft.hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  189. ft.CheckForError(VSSDBG_XML, L"CoInitializeEx");
  190. bCoInitializeSucceeded = true;
  191. // We assume that the async object is not yet released.
  192. // (the wait in destructor should ensure that).
  193. m_timestamp = m_pBackupComponents->m_timestampOperation + 1;
  194. // Call StartSnapshotSet on the given object.
  195. if (m_state == VSS_AS_PREPARE_FOR_BACKUP)
  196. {
  197. ft.hr = m_pBackupComponents->InternalPrepareForBackup();
  198. if (ft.HrFailed())
  199. ft.Trace
  200. (
  201. VSSDBG_XML,
  202. L"Internal PrepareBackup failed. 0x%08lx",
  203. ft.hr
  204. );
  205. }
  206. else if (m_state == VSS_AS_BACKUP_COMPLETE)
  207. {
  208. ft.hr = m_pBackupComponents->InternalBackupComplete();
  209. if (ft.hr != S_OK)
  210. ft.Trace
  211. (
  212. VSSDBG_XML,
  213. L"Internal BackupComplete failed. 0x%08lx",
  214. ft.hr
  215. );
  216. }
  217. else if (m_state == VSS_AS_RESTORE)
  218. {
  219. ft.hr = m_pBackupComponents->InternalPostRestore();
  220. if (ft.hr != S_OK)
  221. ft.Trace
  222. (
  223. VSSDBG_XML,
  224. L"Internal BackupComplete failed. 0x%08lx",
  225. ft.hr
  226. );
  227. }
  228. else if (m_state == VSS_AS_GATHER_WRITER_METADATA)
  229. {
  230. // save previous state and timestamp that will be used
  231. // for gather writer metadata. It is passed into
  232. // PostGatherWriterMetadata if Cancel is called.
  233. m_stateSaved = m_pBackupComponents->m_state;
  234. ft.hr = m_pBackupComponents->InternalGatherWriterMetadata();
  235. if (ft.hr != S_OK)
  236. ft.Trace
  237. (
  238. VSSDBG_XML,
  239. L"Internal GatherWriterMetadata failed. 0x%08lx",
  240. ft.hr
  241. );
  242. }
  243. else
  244. {
  245. BS_ASSERT(m_state == VSS_AS_GATHER_WRITER_STATUS);
  246. // save previous state and timestamp that will be used
  247. // for gather writer metadata. It is passed into
  248. // PostGatherWriterStatus if Cancel is called.
  249. m_stateSaved = m_pBackupComponents->m_state;
  250. ft.hr = m_pBackupComponents->InternalGatherWriterStatus();
  251. if (ft.hr != S_OK)
  252. ft.Trace
  253. (
  254. VSSDBG_XML,
  255. L"Internal GatherWriterStatus failed. 0x%08lx",
  256. ft.hr
  257. );
  258. }
  259. if (ft.hr != S_OK)
  260. // Put the error code into the
  261. m_hrState = ft.hr;
  262. }
  263. VSS_STANDARD_CATCH(ft)
  264. if (bCoInitializeSucceeded)
  265. CoUninitialize();
  266. }
  267. void CVssAsyncBackup::OnFinish()
  268. {
  269. CVssFunctionTracer ft(VSSDBG_XML, L"CVssAsyncBackup::OnFinish");
  270. try
  271. {
  272. if (m_hrState == VSS_S_ASYNC_PENDING)
  273. m_hrState = VSS_S_ASYNC_FINISHED;
  274. // Mark the thread as finished, as the last operation
  275. MarkAsFinished();
  276. }
  277. VSS_STANDARD_CATCH(ft)
  278. // release interface pointer owned by the thread
  279. BS_ASSERT(m_bOwned);
  280. m_bOwned = false;
  281. Release();
  282. }
  283. void CVssAsyncBackup::OnTerminate()
  284. {
  285. CVssFunctionTracer ft( VSSDBG_COORD, L"CVssAsyncBackup::OnTerminate" );
  286. }
  287. /////////////////////////////////////////////////////////////////////////////
  288. // IVssAsync implementation
  289. STDMETHODIMP CVssAsyncBackup::Cancel()
  290. {
  291. CVssFunctionTracer ft(VSSDBG_XML, L"CVssAsyncBackup::Cancel");
  292. try
  293. {
  294. // The critical section will be left automatically at the end of scope.
  295. CVssSafeAutomaticLock lock(m_cs);
  296. // Safety check
  297. if (m_pBackupComponents == NULL)
  298. {
  299. ft.LogError(VSS_ERROR_BACKUPCOMPONENTS_NULL, VSSDBG_XML);
  300. ft.Throw(VSSDBG_XML, E_UNEXPECTED, L"BackupComponents object is NULL");
  301. }
  302. // If thread is already finished, return correct code.
  303. if (m_hrState == VSS_S_ASYNC_FINISHED ||
  304. m_hrState == VSS_S_ASYNC_CANCELLED)
  305. ft.hr = m_hrState;
  306. else
  307. {
  308. m_hrState = VSS_S_ASYNC_CANCELLED;
  309. switch(m_state)
  310. {
  311. default:
  312. BS_ASSERT(FALSE && "Invalid ASYNC state");
  313. break;
  314. case VSS_AS_PREPARE_FOR_BACKUP:
  315. m_pBackupComponents->PostPrepareForBackup(m_timestamp);
  316. break;
  317. case VSS_AS_BACKUP_COMPLETE:
  318. m_pBackupComponents->PostBackupComplete(m_timestamp);
  319. break;
  320. case VSS_AS_RESTORE:
  321. m_pBackupComponents->PostPostRestore(m_timestamp);
  322. break;
  323. case VSS_AS_GATHER_WRITER_STATUS:
  324. m_pBackupComponents->PostGatherWriterStatus
  325. (
  326. m_timestamp,
  327. m_stateSaved
  328. );
  329. break;
  330. case VSS_AS_GATHER_WRITER_METADATA:
  331. ft.hr = m_pBackupComponents->PostGatherWriterMetadata
  332. (
  333. m_timestamp,
  334. m_stateSaved
  335. );
  336. if (FAILED(ft.hr))
  337. m_hrState = ft.hr;
  338. break;
  339. }
  340. }
  341. }
  342. VSS_STANDARD_CATCH(ft)
  343. return ft.hr;
  344. }
  345. STDMETHODIMP CVssAsyncBackup::Wait(DWORD dwMilliseconds)
  346. {
  347. UNREFERENCED_PARAMETER(dwMilliseconds);
  348. CVssFunctionTracer ft( VSSDBG_XML, L"CVssAsyncBackup::Wait" );
  349. try
  350. {
  351. // Safety check
  352. if (m_pBackupComponents == NULL)
  353. {
  354. BS_ASSERT(false);
  355. ft.LogError(VSS_ERROR_BACKUPCOMPONENTS_NULL, VSSDBG_XML);
  356. ft.Throw( VSSDBG_XML, E_UNEXPECTED, L"BackupComponents object is NULL.");
  357. }
  358. // wait for thread to terminate
  359. HANDLE hThread = GetThreadHandle();
  360. if (hThread == NULL)
  361. {
  362. ft.LogError(VSS_ERROR_THREADHANDLE_NULL, VSSDBG_XML);
  363. ft.Throw( VSSDBG_XML, E_UNEXPECTED, L"invalid hThread");
  364. }
  365. if (::WaitForSingleObject(hThread, INFINITE) == WAIT_FAILED)
  366. {
  367. ft.LogError(VSS_ERROR_WAITFORSINGLEOBJECT, VSSDBG_XML << HRESULT_FROM_WIN32(GetLastError()));
  368. ft.Throw( VSSDBG_XML, E_UNEXPECTED, L"Wait failed. [0x%08lx]", ::GetLastError());
  369. }
  370. }
  371. VSS_STANDARD_CATCH(ft)
  372. return ft.hr;
  373. }
  374. STDMETHODIMP CVssAsyncBackup::QueryStatus
  375. (
  376. OUT HRESULT* pHrResult,
  377. OUT INT* pnReserved
  378. )
  379. {
  380. CVssFunctionTracer ft( VSSDBG_XML, L"CVssAsyncBackup::QueryStatus" );
  381. try
  382. {
  383. VssZeroOut(pHrResult);
  384. VssZeroOut(pnReserved);
  385. // Argument check
  386. if (pHrResult == NULL)
  387. ft.Throw( VSSDBG_XML, E_INVALIDARG, L"Output parameter is NULL.");
  388. // The critical section will be left automatically at the end of scope.
  389. CVssSafeAutomaticLock lock(m_cs);
  390. // Safety check
  391. if (m_pBackupComponents == NULL)
  392. {
  393. ft.LogError(VSS_ERROR_BACKUPCOMPONENTS_NULL, VSSDBG_XML);
  394. ft.Throw( VSSDBG_XML, E_UNEXPECTED, L"BackupComponents object is NULL.");
  395. }
  396. (*pHrResult) = m_hrState;
  397. ft.Trace( VSSDBG_XML, L"Returning *pHrResult: 0x%08x", *pHrResult );
  398. }
  399. VSS_STANDARD_CATCH(ft)
  400. return ft.hr;
  401. }
  402. /////////////////////////////////////////////////////////////////////////////
  403. // IVssAsync Cover implementation
  404. void CVssAsyncCover::CreateInstance(
  405. IN CVssBackupComponents* pBackupComponents,
  406. IN IVssAsync* pAsyncInternal,
  407. OUT IVssAsync** ppAsync
  408. ) throw(HRESULT)
  409. /*++
  410. Description:
  411. Creates a cover for a given IVssAsync and a backup components object.
  412. Comments:
  413. This object is used to intercept all calls to the internal async QueryStatus
  414. --*/
  415. {
  416. CVssFunctionTracer ft(VSSDBG_XML, L"CVssAsyncCover::CreateInstance");
  417. BS_ASSERT(pBackupComponents);
  418. BS_ASSERT(pAsyncInternal);
  419. BS_ASSERT(ppAsync && (*ppAsync == NULL));
  420. // create cover async object
  421. CComObject<CVssAsyncCover>* pObject;
  422. ft.hr = CComObject<CVssAsyncCover>::CreateInstance(&pObject);
  423. if (ft.HrFailed())
  424. ft.Throw
  425. (
  426. VSSDBG_XML,
  427. E_OUTOFMEMORY,
  428. L"Error creating the CVssAsync instance. hr = 0x%08lx", ft.hr
  429. );
  430. // Fill out the data members (the ref counts are incremented)
  431. pObject->m_pvbc = pBackupComponents;
  432. pObject->m_pvbcReference = pBackupComponents;
  433. pObject->m_pAsync = pAsyncInternal;
  434. // Get the IVssAsync interface
  435. CComPtr<IUnknown> pUnknown = pObject->GetUnknown();
  436. BS_ASSERT(pUnknown);
  437. CComPtr<IVssAsync> ptrAsync;
  438. ft.hr = pUnknown->SafeQI(IVssAsync, &ptrAsync);
  439. if (ft.HrFailed())
  440. {
  441. BS_ASSERT(FALSE && "QI shouldn't fail");
  442. ft.LogError(VSS_ERROR_QI_IVSSASYNC_FAILED, VSSDBG_XML << ft.hr);
  443. ft.Throw
  444. (
  445. VSSDBG_XML,
  446. E_UNEXPECTED,
  447. L"Error querying the IVssAsync interface. hr = 0x%08lx",
  448. ft.hr
  449. );
  450. }
  451. // Copy the interface to the out parameter
  452. ptrAsync.CopyTo(ppAsync);
  453. }
  454. STDMETHODIMP CVssAsyncCover::Cancel()
  455. {
  456. CVssFunctionTracer ft(VSSDBG_XML, L"CVssAsyncCover::Cancel");
  457. BS_ASSERT(m_pAsync);
  458. BS_ASSERT(m_pvbc);
  459. ft.hr = m_pAsync->Cancel();
  460. if (ft.hr == VSS_S_ASYNC_FINISHED)
  461. m_pvbc->m_state = x_StateDoSnapshotSucceeded;
  462. else
  463. m_pvbc->m_state = x_StateDoSnapshotFailed;
  464. return ft.hr;
  465. }
  466. STDMETHODIMP CVssAsyncCover::Wait(DWORD dwMilliseconds)
  467. {
  468. CVssFunctionTracer ft(VSSDBG_XML, L"CVssAsyncCover::Wait");
  469. BS_ASSERT(m_pAsync);
  470. BS_ASSERT(m_pvbc);
  471. ft.hr = m_pAsync->Wait(dwMilliseconds);
  472. return ft.hr;
  473. }
  474. STDMETHODIMP CVssAsyncCover::QueryStatus
  475. (
  476. OUT HRESULT* pHrResult,
  477. OUT INT* pnPercentDone
  478. )
  479. {
  480. CVssFunctionTracer ft(VSSDBG_XML, L"CVssAsyncCover::QueryStatus");
  481. if (pHrResult == NULL)
  482. return E_INVALIDARG;
  483. BS_ASSERT(m_pAsync);
  484. BS_ASSERT(m_pvbc);
  485. try
  486. {
  487. ft.hr = m_pAsync->QueryStatus(pHrResult, pnPercentDone);
  488. if (*pHrResult == VSS_E_BAD_STATE)
  489. m_pvbc->m_state = x_StateDoSnapshotFailedWithoutSendingAbort;
  490. else if (FAILED(ft.hr) ||
  491. FAILED(*pHrResult) ||
  492. *pHrResult == VSS_S_ASYNC_CANCELLED)
  493. m_pvbc->m_state = x_StateDoSnapshotFailed;
  494. else if (*pHrResult == VSS_S_ASYNC_FINISHED)
  495. m_pvbc->m_state = x_StateDoSnapshotSucceeded;
  496. }
  497. VSS_STANDARD_CATCH(ft)
  498. return ft.hr;
  499. }