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.

843 lines
28 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Abstract:
  4. @doc
  5. @module sqlwriter.cpp | Implementation of Writer
  6. @end
  7. Author:
  8. Brian Berkowitz [brianb] 04/17/2000
  9. TBD:
  10. Revision History:
  11. Name Date Comments
  12. brianb 04/17/2000 created
  13. brianb 04/20/2000 integrated with coordinator
  14. brainb 05/05/2000 add OnIdentify support
  15. mikejohn 06/01/2000 fix minor but confusing typos in trace messages
  16. mikejohn 09/19/2000 176860: Add the missing calling convention specifiers
  17. --*/
  18. #include <stdafx.hxx>
  19. #include "vs_inc.hxx"
  20. #include "vs_idl.hxx"
  21. #include <vs_hash.hxx>
  22. #include <base64coder.h>
  23. #include "vswriter.h"
  24. #include "sqlsnap.h"
  25. #include "sqlwriter.h"
  26. #include "vs_seh.hxx"
  27. #include "vs_trace.hxx"
  28. #include "vs_debug.hxx"
  29. #include "allerror.h"
  30. #include "sqlwrtguid.h"
  31. ////////////////////////////////////////////////////////////////////////
  32. // Standard foo for file name aliasing. This code block must be after
  33. // all includes of VSS header files.
  34. //
  35. #ifdef VSS_FILE_ALIAS
  36. #undef VSS_FILE_ALIAS
  37. #endif
  38. #define VSS_FILE_ALIAS "SQWWRTRC"
  39. //
  40. ////////////////////////////////////////////////////////////////////////
  41. static LPCWSTR x_wszSqlServerWriter = L"SqlServerWriter";
  42. static LPCWSTR s_wszWriterName = L"MSDEWriter";
  43. HRESULT STDMETHODCALLTYPE CSqlWriter::Initialize()
  44. {
  45. CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::Initialize");
  46. try
  47. {
  48. InitSQLEnvironment();
  49. ft.hr = CVssWriter::Initialize
  50. (
  51. WRITERID_SqlWriter,
  52. s_wszWriterName,
  53. VSS_UT_SYSTEMSERVICE,
  54. VSS_ST_TRANSACTEDDB,
  55. VSS_APP_BACK_END,
  56. 60000
  57. );
  58. if (ft.HrFailed())
  59. ft.Throw
  60. (
  61. VSSDBG_SQLWRITER,
  62. E_UNEXPECTED,
  63. L"Failed to initialize the Sql writer. hr = 0x%08lx",
  64. ft.hr
  65. );
  66. ft.hr = Subscribe();
  67. if (ft.HrFailed())
  68. ft.Throw
  69. (
  70. VSSDBG_SQLWRITER,
  71. E_UNEXPECTED,
  72. L"Subscribing the Sql server writer failed. hr = %0x08lx",
  73. ft.hr
  74. );
  75. }
  76. VSS_STANDARD_CATCH(ft)
  77. return ft.hr;
  78. }
  79. HRESULT STDMETHODCALLTYPE CSqlWriter::Uninitialize()
  80. {
  81. CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::Uninitialize");
  82. return Unsubscribe();
  83. }
  84. bool STDMETHODCALLTYPE CSqlWriter::OnPrepareBackup
  85. (
  86. IN IVssWriterComponents *pComponents
  87. )
  88. {
  89. CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::OnPrepareBackup");
  90. LPWSTR *rgwszDB = NULL;
  91. UINT cwszDB = 0;
  92. LPWSTR *rgwszInstances = NULL;
  93. UINT cwszInstances = 0;
  94. bool bSuccess = true;
  95. try
  96. {
  97. // clear existing arrays
  98. if (m_rgwszDatabases)
  99. {
  100. for(UINT i = 0; i < m_cDatabases; i++)
  101. {
  102. delete m_rgwszDatabases[i];
  103. delete m_rgwszInstances[i];
  104. }
  105. delete m_rgwszDatabases;
  106. delete m_rgwszInstances;
  107. m_rgwszDatabases = NULL;
  108. m_rgwszInstances = NULL;
  109. m_cDatabases = 0;
  110. }
  111. m_bComponentsSelected = AreComponentsSelected();
  112. if (m_bComponentsSelected)
  113. {
  114. UINT cComponents;
  115. ft.hr = pComponents->GetComponentCount(&cComponents);
  116. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterComponents::GetComponentCount");
  117. rgwszDB = new LPWSTR[cComponents];
  118. rgwszInstances = new LPWSTR[cComponents];
  119. if (rgwszDB == NULL || rgwszInstances == NULL)
  120. ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"out of memory");
  121. for(UINT iComponent = 0; iComponent < cComponents; iComponent++)
  122. {
  123. CComPtr<IVssComponent> pComponent;
  124. ft.hr = pComponents->GetComponent(iComponent, &pComponent);
  125. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterComponents::GetComponent");
  126. CComBSTR bstrLogicalPath;
  127. CComBSTR bstrDBName;
  128. ft.hr = pComponent->GetLogicalPath(&bstrLogicalPath);
  129. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetLogicalPath");
  130. ft.hr = pComponent->GetComponentName(&bstrDBName);
  131. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetComponentName");
  132. LPWSTR wszDB = new WCHAR[wcslen(bstrDBName) + 1];
  133. if (wszDB == NULL)
  134. ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"out of memory");
  135. wcscpy(wszDB, bstrDBName);
  136. rgwszDB[cwszDB++] = wszDB;
  137. LPWSTR wszInstance = new WCHAR[wcslen(bstrLogicalPath) + 1];
  138. if (wszInstance == NULL)
  139. ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"out of memory");
  140. wcscpy(wszInstance, bstrLogicalPath);
  141. rgwszInstances[cwszInstances++] = wszInstance;
  142. }
  143. }
  144. m_rgwszDatabases = rgwszDB;
  145. m_rgwszInstances = rgwszInstances;
  146. m_cDatabases = cwszDB;
  147. }
  148. catch(...)
  149. {
  150. for(UINT iwsz = 0; iwsz < cwszDB; iwsz++)
  151. delete rgwszDB[iwsz];
  152. delete rgwszDB;
  153. for(UINT iwsz = 0; iwsz < cwszInstances; iwsz++)
  154. delete rgwszInstances[iwsz];
  155. delete rgwszInstances;
  156. bSuccess = false;
  157. }
  158. return bSuccess;
  159. }
  160. bool STDMETHODCALLTYPE CSqlWriter::OnPrepareSnapshot()
  161. {
  162. CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::OnPrepareSnapshot");
  163. try
  164. {
  165. BS_ASSERT(!m_fFrozen);
  166. // delete sql snapshot element if it exists
  167. delete m_pSqlSnapshot;
  168. m_pSqlSnapshot = NULL;
  169. m_pSqlSnapshot = CreateSqlSnapshot();
  170. if (m_pSqlSnapshot == NULL)
  171. ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"Failed to allocate CSqlSnapshot object.");
  172. ft.hr = m_pSqlSnapshot->Prepare(this);
  173. }
  174. VSS_STANDARD_CATCH(ft)
  175. TranslateWriterError(ft.hr);
  176. return !ft.HrFailed();
  177. }
  178. bool STDMETHODCALLTYPE CSqlWriter::OnFreeze()
  179. {
  180. CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::OnFreeze");
  181. try
  182. {
  183. BS_ASSERT(!m_fFrozen);
  184. ft.hr = m_pSqlSnapshot->Freeze();
  185. if (!ft.HrFailed())
  186. m_fFrozen = true;
  187. }
  188. VSS_STANDARD_CATCH(ft)
  189. TranslateWriterError(ft.hr);
  190. return !ft.HrFailed();
  191. }
  192. bool STDMETHODCALLTYPE CSqlWriter::OnThaw()
  193. {
  194. CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::OnThaw");
  195. try
  196. {
  197. if (m_fFrozen)
  198. {
  199. m_fFrozen = false;
  200. ft.hr = m_pSqlSnapshot->Thaw();
  201. }
  202. }
  203. VSS_STANDARD_CATCH(ft)
  204. TranslateWriterError(ft.hr);
  205. return !ft.HrFailed();
  206. }
  207. bool STDMETHODCALLTYPE CSqlWriter::OnPostSnapshot
  208. (
  209. IN IVssWriterComponents *pWriter
  210. )
  211. {
  212. CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"STDMETHODCALLTYPE CSqlWriter::OnPostSnapshot");
  213. // map of databases that were actually successfully frozen
  214. CVssSimpleMap<VSS_PWSZ, FrozenDatabaseInfo *> mapDatabases;
  215. FrozenDatabaseInfo fInfo;
  216. WCHAR *wsz = NULL;
  217. FrozenDatabaseInfo *pfInfo = NULL;
  218. try
  219. {
  220. ft.hr = m_pSqlSnapshot->GetFirstDatabase(&fInfo);
  221. while(ft.hr != DB_S_ENDOFROWSET)
  222. {
  223. // check for error code
  224. if (ft.HrFailed())
  225. ft.Throw
  226. (
  227. VSSDBG_SQLWRITER,
  228. E_UNEXPECTED,
  229. L"Enumerating database servers failed. hr = 0x%08lx",
  230. ft.hr
  231. );
  232. wsz = (WCHAR *) new WCHAR[wcslen(fInfo.serverName) + wcslen(fInfo.databaseName) + 2];
  233. pfInfo = new FrozenDatabaseInfo;
  234. if (wsz == NULL || pfInfo == NULL)
  235. ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"Cannot allocate frozen info mapping.");
  236. // name is server\database
  237. wcscpy(wsz, fInfo.serverName);
  238. wcscat(wsz, L"\\");
  239. wcscat(wsz, fInfo.databaseName);
  240. memcpy(pfInfo, &fInfo, sizeof(fInfo));
  241. if (!mapDatabases.Add(wsz, pfInfo))
  242. ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"Cannot allocate frozen info mapping.");
  243. // ownership is transfered to the map
  244. wsz = NULL;
  245. pfInfo = NULL;
  246. ft.hr = m_pSqlSnapshot->GetNextDatabase(&fInfo);
  247. }
  248. UINT cComponents;
  249. ft.hr = pWriter->GetComponentCount(&cComponents);
  250. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterComponents::GetComponentCount");
  251. // loop through components supplied by the user.
  252. for(UINT iComponent = 0; iComponent < cComponents; iComponent++)
  253. {
  254. WCHAR wszName[MAX_SERVERNAME + MAX_DBNAME + 1];
  255. CComPtr<IVssComponent> pComponent;
  256. ft.hr = pWriter->GetComponent(iComponent, &pComponent);
  257. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterComponents::GetComponent");
  258. VSS_COMPONENT_TYPE ct;
  259. ft.hr = pComponent->GetComponentType(&ct);
  260. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetComponentType");
  261. if (ct != VSS_CT_DATABASE)
  262. ft.Throw(VSSDBG_SQLWRITER, VSS_E_WRITERERROR_NONRETRYABLE, L"requesting a non-database component");
  263. CComBSTR bstrLogicalPath;
  264. ft.hr = pComponent->GetLogicalPath(&bstrLogicalPath);
  265. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetLogicalPath");
  266. CComBSTR bstrComponentName;
  267. ft.hr = pComponent->GetComponentName(&bstrComponentName);
  268. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterCokmponents::GetComponentName");
  269. wcscpy(wszName, bstrLogicalPath);
  270. wcscat(wszName, L"\\");
  271. wcscat(wszName, bstrComponentName);
  272. FrozenDatabaseInfo *pfInfoFound = mapDatabases.Lookup(wszName);
  273. if (pfInfoFound == NULL)
  274. ft.Throw(VSSDBG_SQLWRITER, VSS_E_WRITERERROR_RETRYABLE, L"database was not successfully snapshotted");
  275. Base64Coder coder;
  276. coder.Encode(pfInfoFound->pMetaData, pfInfoFound->metaDataSize);
  277. ft.hr = pComponent->SetBackupMetadata(coder.EncodedMessage());
  278. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::SetBackupMetadata");
  279. }
  280. }
  281. VSS_STANDARD_CATCH(ft)
  282. int cBuckets = mapDatabases.GetSize();
  283. for(int iBucket = 0; iBucket < cBuckets; iBucket++)
  284. {
  285. delete mapDatabases.GetKeyAt(iBucket);
  286. delete mapDatabases.GetValueAt(iBucket);
  287. }
  288. delete wsz;
  289. delete pfInfo;
  290. delete m_pSqlSnapshot;
  291. m_pSqlSnapshot = NULL;
  292. TranslateWriterError(ft.hr);
  293. return !ft.HrFailed();
  294. }
  295. bool STDMETHODCALLTYPE CSqlWriter::OnAbort()
  296. {
  297. CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::OnAbort");
  298. try
  299. {
  300. if (m_fFrozen)
  301. {
  302. m_fFrozen = false;
  303. ft.hr = m_pSqlSnapshot->Thaw();
  304. }
  305. delete m_pSqlSnapshot;
  306. m_pSqlSnapshot = NULL;
  307. }
  308. VSS_STANDARD_CATCH(ft)
  309. return !ft.HrFailed();
  310. }
  311. bool CSqlWriter::IsPathInSnapshot(const WCHAR *wszPath) throw()
  312. {
  313. return IsPathAffected(wszPath);
  314. }
  315. // returns whether backup supports component based backup/restore
  316. bool CSqlWriter::IsComponentBased()
  317. {
  318. return m_bComponentsSelected;
  319. }
  320. // enumerate selected databases for a given instance, pNextIndex indicates the
  321. // next instance to look for. 0 indicates find first instance
  322. LPCWSTR CSqlWriter::EnumerateSelectedDatabases(LPCWSTR wszInstanceName, UINT *pNextIndex)
  323. {
  324. // should only be called for component based backups
  325. BS_ASSERT(m_bComponentsSelected);
  326. BS_ASSERT(pNextIndex);
  327. if (!m_bComponentsSelected)
  328. return NULL;
  329. // starting point in array
  330. UINT iwsz = *pNextIndex;
  331. // loop until a matching instance is found
  332. for(iwsz; iwsz < m_cDatabases; iwsz++)
  333. {
  334. if (wcscmp(wszInstanceName, m_rgwszInstances[iwsz]) == 0)
  335. break;
  336. }
  337. if (iwsz >= m_cDatabases)
  338. {
  339. // no more matching entries
  340. *pNextIndex = m_cDatabases;
  341. return NULL;
  342. }
  343. // seach should start at next database entry
  344. *pNextIndex = iwsz + 1;
  345. // return current database name
  346. return m_rgwszDatabases[iwsz];
  347. }
  348. // handle request for WRITER_METADATA
  349. // implements CVssWriter::OnIdentify
  350. bool STDMETHODCALLTYPE CSqlWriter::OnIdentify(IVssCreateWriterMetadata *pMetadata)
  351. {
  352. CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::OnIdentify");
  353. ServerInfo server;
  354. DatabaseInfo database;
  355. DatabaseFileInfo file;
  356. // create enumerator
  357. CSqlEnumerator *pEnumServers = NULL;
  358. CSqlEnumerator *pEnumDatabases = NULL;
  359. CSqlEnumerator *pEnumFiles = NULL;
  360. try
  361. {
  362. ft.hr = pMetadata->SetRestoreMethod
  363. (
  364. VSS_RME_RESTORE_IF_CAN_REPLACE,
  365. NULL,
  366. NULL,
  367. VSS_WRE_ALWAYS,
  368. false
  369. );
  370. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssCreateWriterMetadata::SetRestoreMethod");
  371. pEnumServers = CreateSqlEnumerator();
  372. if (pEnumServers == NULL)
  373. ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"Failed to create CSqlEnumerator");
  374. // find first server
  375. ft.hr = pEnumServers->FirstServer(&server);
  376. while(ft.hr != DB_S_ENDOFROWSET)
  377. {
  378. // check for error code
  379. if (ft.HrFailed())
  380. ft.Throw
  381. (
  382. VSSDBG_SQLWRITER,
  383. E_UNEXPECTED,
  384. L"Enumerating database servers failed. hr = 0x%08lx",
  385. ft.hr
  386. );
  387. // only look at server if it is online
  388. if (server.isOnline)
  389. {
  390. // recreate enumerator for databases
  391. BS_ASSERT(pEnumDatabases == NULL);
  392. pEnumDatabases = CreateSqlEnumerator();
  393. if (pEnumDatabases == NULL)
  394. ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"Failed to create CSqlEnumerator");
  395. // find first database
  396. ft.hr = pEnumDatabases->FirstDatabase(server.name, &database);
  397. while(ft.hr != DB_S_ENDOFROWSET)
  398. {
  399. // check for error
  400. if (ft.HrFailed())
  401. ft.Throw
  402. (
  403. VSSDBG_SQLWRITER,
  404. E_UNEXPECTED,
  405. L"Enumerating databases failed. hr = 0x%08lx",
  406. ft.hr
  407. );
  408. // only include database if it supports Freeze and
  409. // don't include the tempdb
  410. if (wcscmp(database.name, L"tempdb") != 0 &&
  411. database.supportsFreeze)
  412. {
  413. // add database component
  414. ft.hr = pMetadata->AddComponent
  415. (
  416. VSS_CT_DATABASE, // component type
  417. server.name, // logical path
  418. database.name, // component name
  419. NULL, // caption
  420. NULL, // pbIcon
  421. 0, // cbIcon
  422. false, // bRestoreMetadata
  423. false, // bNotifyOnBackupComplete
  424. true // bSelectable
  425. );
  426. if (ft.HrFailed())
  427. ft.Throw
  428. (
  429. VSSDBG_SQLWRITER,
  430. E_UNEXPECTED,
  431. L"IVssCreateWriterMetadata::AddComponent failed. hr = 0x%08lx",
  432. ft.hr
  433. );
  434. // recreate enumerator for files
  435. BS_ASSERT(pEnumFiles == NULL);
  436. pEnumFiles = CreateSqlEnumerator();
  437. if (pEnumFiles == NULL)
  438. ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"Failed to create CSqlEnumerator");
  439. // findfirst database file
  440. ft.hr = pEnumFiles->FirstFile(server.name, database.name, &file);
  441. while(ft.hr != DB_S_ENDOFROWSET)
  442. {
  443. // check for error
  444. if (ft.HrFailed())
  445. ft.Throw
  446. (
  447. VSSDBG_SQLWRITER,
  448. E_UNEXPECTED,
  449. L"Enumerating database files failed. hr = 0x%08lx",
  450. ft.hr
  451. );
  452. // split file name into separate path
  453. // and filename components. Path is everything
  454. // before the last backslash.
  455. WCHAR logicalPath[MAX_PATH];
  456. WCHAR *pFileName = file.name + wcslen(file.name);
  457. while(--pFileName > file.name)
  458. {
  459. if (*pFileName == '\\')
  460. break;
  461. }
  462. // if no backslash, then there is no path
  463. if (pFileName == file.name)
  464. logicalPath[0] = '\0';
  465. else
  466. {
  467. // extract path
  468. size_t cwc = wcslen(file.name) - wcslen(pFileName);
  469. memcpy(logicalPath, file.name, cwc*sizeof(WCHAR));
  470. logicalPath[cwc] = L'\0';
  471. pFileName++;
  472. }
  473. if (file.isLogFile)
  474. // log file
  475. ft.hr = pMetadata->AddDatabaseLogFiles
  476. (
  477. server.name,
  478. database.name,
  479. logicalPath,
  480. pFileName
  481. );
  482. else
  483. // physical database file
  484. ft.hr = pMetadata->AddDatabaseFiles
  485. (
  486. server.name,
  487. database.name,
  488. logicalPath,
  489. pFileName
  490. );
  491. // continue at next file
  492. ft.hr = pEnumFiles->NextFile(&file);
  493. }
  494. delete pEnumFiles;
  495. pEnumFiles = NULL;
  496. }
  497. // continue at next database
  498. ft.hr = pEnumDatabases->NextDatabase(&database);
  499. }
  500. delete pEnumDatabases;
  501. pEnumDatabases = NULL;
  502. }
  503. // continue at next server
  504. ft.hr = pEnumServers->NextServer(&server);
  505. }
  506. }
  507. VSS_STANDARD_CATCH(ft)
  508. TranslateWriterError(ft.hr);
  509. delete pEnumServers;
  510. delete pEnumDatabases;
  511. delete pEnumFiles;
  512. return ft.HrFailed() ? false : true;
  513. }
  514. // translate a sql writer error code into a writer error
  515. void CSqlWriter::TranslateWriterError(HRESULT hr)
  516. {
  517. if (SUCCEEDED(hr))
  518. return;
  519. switch(hr)
  520. {
  521. default:
  522. SetWriterFailure(VSS_E_WRITERERROR_NONRETRYABLE);
  523. break;
  524. case S_OK:
  525. break;
  526. case E_OUTOFMEMORY:
  527. case HRESULT_FROM_WIN32(ERROR_DISK_FULL):
  528. case HRESULT_FROM_WIN32(ERROR_TOO_MANY_OPEN_FILES):
  529. case HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY):
  530. case HRESULT_FROM_WIN32(ERROR_NO_MORE_USER_HANDLES):
  531. SetWriterFailure(VSS_E_WRITERERROR_OUTOFRESOURCES);
  532. break;
  533. case HRESULT_FROM_WIN32(E_SQLLIB_TORN_DB):
  534. SetWriterFailure(VSS_E_WRITERERROR_INCONSISTENTSNAPSHOT);
  535. break;
  536. }
  537. }
  538. bool STDMETHODCALLTYPE CSqlWriter::OnPreRestore
  539. (
  540. IN IVssWriterComponents *pWriter
  541. )
  542. {
  543. CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::OnPreRestore");
  544. try
  545. {
  546. // delete sql restore element if it exists
  547. delete m_pSqlRestore;
  548. m_pSqlRestore = NULL;
  549. UINT cComponents;
  550. ft.hr = pWriter->GetComponentCount(&cComponents);
  551. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterComponents::GetComponentCount");
  552. if (cComponents == 0)
  553. return true;
  554. for(UINT iComponent = 0; iComponent < cComponents; iComponent++)
  555. {
  556. CComPtr<IVssComponent> pComponent;
  557. ft.hr = pWriter->GetComponent(iComponent, &pComponent);
  558. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterComponents::GetComponent");
  559. bool bSelectedForRestore;
  560. ft.hr = pComponent->IsSelectedForRestore(&bSelectedForRestore);
  561. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::IsSelectedForRestore");
  562. if (!bSelectedForRestore)
  563. continue;
  564. if (m_pSqlRestore == NULL)
  565. {
  566. m_pSqlRestore = CreateSqlRestore();
  567. if (m_pSqlRestore == NULL)
  568. ft.Throw(VSSDBG_SQLWRITER, E_OUTOFMEMORY, L"cannot allocate CSqlRestore object");
  569. }
  570. VSS_COMPONENT_TYPE ct;
  571. ft.hr = pComponent->GetComponentType(&ct);
  572. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetComponentType");
  573. if (ct != VSS_CT_DATABASE)
  574. ft.Throw(VSSDBG_SQLWRITER, VSS_E_WRITERERROR_NONRETRYABLE, L"requesting a non-database component");
  575. CComBSTR bstrLogicalPath;
  576. ft.hr = pComponent->GetLogicalPath(&bstrLogicalPath);
  577. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetLogicalPath");
  578. CComBSTR bstrComponentName;
  579. ft.hr = pComponent->GetComponentName(&bstrComponentName);
  580. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterCokmponents::GetComponentName");
  581. ft.hr = m_pSqlRestore->PrepareToRestore(bstrLogicalPath, bstrComponentName);
  582. if (ft.HrFailed())
  583. {
  584. WCHAR wsz[128];
  585. swprintf(wsz, L"CSqlRestor::PrepareToRestore failed with HRESULT = 0x%08lx", ft.hr);
  586. ft.hr = pComponent->SetPreRestoreFailureMsg(wsz);
  587. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::SetPreRestoreFailureMsg");
  588. }
  589. }
  590. }
  591. VSS_STANDARD_CATCH(ft)
  592. return true;
  593. }
  594. bool STDMETHODCALLTYPE CSqlWriter::OnPostRestore
  595. (
  596. IN IVssWriterComponents *pWriter
  597. )
  598. {
  599. CVssFunctionTracer ft(VSSDBG_SQLWRITER, L"CSqlWriter::OnPostRestore");
  600. try
  601. {
  602. if (m_pSqlRestore == NULL)
  603. return true;
  604. UINT cComponents;
  605. ft.hr = pWriter->GetComponentCount(&cComponents);
  606. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterComponents::GetComponentCount");
  607. for(UINT iComponent = 0; iComponent < cComponents; iComponent++)
  608. {
  609. CComPtr<IVssComponent> pComponent;
  610. ft.hr = pWriter->GetComponent(iComponent, &pComponent);
  611. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterComponents::GetComponent");
  612. bool bSelectedForRestore;
  613. ft.hr = pComponent->IsSelectedForRestore(&bSelectedForRestore);
  614. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::IsSelectedForRestore");
  615. if (!bSelectedForRestore)
  616. continue;
  617. VSS_COMPONENT_TYPE ct;
  618. ft.hr = pComponent->GetComponentType(&ct);
  619. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetComponentType");
  620. if (ct != VSS_CT_DATABASE)
  621. ft.Throw(VSSDBG_SQLWRITER, VSS_E_WRITERERROR_NONRETRYABLE, L"requesting a non-database component");
  622. CComBSTR bstrLogicalPath;
  623. ft.hr = pComponent->GetLogicalPath(&bstrLogicalPath);
  624. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetLogicalPath");
  625. CComBSTR bstrComponentName;
  626. ft.hr = pComponent->GetComponentName(&bstrComponentName);
  627. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssWriterCokmponents::GetComponentName");
  628. CComBSTR bstrPreRestoreFailure;
  629. ft.hr = pComponent->GetPreRestoreFailureMsg(&bstrPreRestoreFailure);
  630. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetPreRestoreFailureMsg");
  631. // if we got an error during prerestore don't do a post restore
  632. if (bstrPreRestoreFailure)
  633. continue;
  634. bool bAdditionalRestores;
  635. ft.hr = pComponent->GetAdditionalRestores(&bAdditionalRestores);
  636. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetAdditionalRestores");
  637. CComBSTR bstrMetadata;
  638. ft.hr = pComponent->GetBackupMetadata(&bstrMetadata);
  639. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::GetBackupMetadata");
  640. Base64Coder coder;
  641. coder.Decode(bstrMetadata);
  642. BYTE *pbVal = coder.DecodedMessage();
  643. ft.hr = m_pSqlRestore->FinalizeRestore
  644. (
  645. bstrLogicalPath,
  646. bstrComponentName,
  647. bAdditionalRestores,
  648. pbVal + sizeof(UINT),
  649. *(UINT *) pbVal
  650. );
  651. if (ft.HrFailed())
  652. {
  653. WCHAR wsz[128];
  654. swprintf(wsz, L"CSqlRestore::FinalizeRestore failed with HRESULT = 0x%08lx", ft.hr);
  655. ft.hr = pComponent->SetPostRestoreFailureMsg(wsz);
  656. ft.CheckForErrorInternal(VSSDBG_SQLWRITER, L"IVssComponent::SetPreRestoreFailureMsg");
  657. }
  658. }
  659. }
  660. VSS_STANDARD_CATCH(ft)
  661. return true;
  662. }