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.

1423 lines
45 KiB

  1. #include "stdafx.hxx"
  2. //#include "vs_idl.hxx"
  3. #include "vss.h"
  4. #include "vswriter.h"
  5. #include "vsbackup.h"
  6. #include "compont.h"
  7. #include <debug.h>
  8. #include <cwriter.h>
  9. #include <lmshare.h>
  10. #include <lmaccess.h>
  11. #include <time.h>
  12. #include <vs_inc.hxx>
  13. extern WCHAR g_wszSavedFilesDirectory[];
  14. bool FindComponent
  15. (
  16. IVssExamineWriterMetadata *pMetadata,
  17. LPCWSTR wszLogicalPath,
  18. LPCWSTR wszComponentName,
  19. IVssWMComponent **ppComponent
  20. );
  21. typedef struct _SAVE_INFO
  22. {
  23. IVssBackupComponents *pvbc;
  24. IVssComponent *pComponent;
  25. IVssExamineWriterMetadata *pMetadata;
  26. CVssSimpleMap<VSS_PWSZ, VSS_PWSZ> mapSnapshots;
  27. } SAVE_INFO;
  28. void DoCopyFile(LPCWSTR wszSource, LPCWSTR wszDest)
  29. {
  30. CComBSTR bstr = wszDest;
  31. UINT cwc = (UINT) wcslen(wszDest);
  32. HANDLE hFile;
  33. LPWSTR wszBuf = new WCHAR[cwc + 1];
  34. if (wszBuf == NULL)
  35. Error(E_OUTOFMEMORY, L"Out of Memory");
  36. while(TRUE)
  37. {
  38. LPWSTR wsz = wcsrchr(bstr, L'\\');
  39. if (wsz == NULL)
  40. break;
  41. *wsz = L'\0';
  42. wcscpy(wszBuf, bstr);
  43. wcscat(wszBuf, L"\\");
  44. hFile = CreateFile
  45. (
  46. wszBuf,
  47. GENERIC_READ,
  48. FILE_SHARE_READ|FILE_SHARE_WRITE,
  49. NULL,
  50. OPEN_EXISTING,
  51. FILE_FLAG_BACKUP_SEMANTICS,
  52. NULL
  53. );
  54. if (hFile != INVALID_HANDLE_VALUE)
  55. {
  56. CloseHandle(hFile);
  57. break;
  58. }
  59. }
  60. delete wszBuf;
  61. // add backslash removed previously
  62. bstr[wcslen(bstr)] = L'\\';
  63. while(wcslen(bstr) < cwc)
  64. {
  65. if (!CreateDirectory(bstr, NULL))
  66. {
  67. DWORD dwErr = GetLastError();
  68. Error(HRESULT_FROM_WIN32(dwErr), L"CreateDirectory failed with error %d.\n", dwErr);
  69. }
  70. bstr[wcslen(bstr)] = L'\\';
  71. }
  72. if (wszSource)
  73. {
  74. if (!CopyFile(wszSource, wszDest, FALSE))
  75. {
  76. DWORD dwErr = GetLastError();
  77. Error(HRESULT_FROM_WIN32(dwErr), L"CopyFile failed with error %d.\n", dwErr);
  78. }
  79. }
  80. }
  81. void SaveFilesMatchingFilespec
  82. (
  83. LPCWSTR wszSnapshotPath,
  84. LPCWSTR wszSavedPath,
  85. LPCWSTR wszFilespec
  86. )
  87. {
  88. CComBSTR bstrSP = wszSnapshotPath;
  89. if (bstrSP[wcslen(bstrSP) - 1] != L'\\')
  90. bstrSP.Append(L"\\");
  91. bstrSP.Append(wszFilespec);
  92. WIN32_FIND_DATA findData;
  93. HANDLE hFile = FindFirstFile(bstrSP, &findData);
  94. if (hFile == INVALID_HANDLE_VALUE)
  95. return;
  96. try
  97. {
  98. do
  99. {
  100. if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
  101. {
  102. CComBSTR bstrCP = wszSavedPath;
  103. bstrSP = wszSnapshotPath;
  104. if (bstrSP[wcslen(bstrSP) - 1] != L'\\')
  105. bstrSP.Append(L"\\");
  106. bstrSP.Append(findData.cFileName);
  107. if (bstrCP[wcslen(bstrCP) - 1] != L'\\')
  108. bstrCP.Append(L"\\");
  109. bstrCP.Append(findData.cFileName);
  110. DoCopyFile(bstrSP, bstrCP);
  111. }
  112. } while(FindNextFile(hFile, &findData));
  113. FindClose(hFile);
  114. }
  115. catch(...)
  116. {
  117. FindClose(hFile);
  118. throw;
  119. }
  120. }
  121. void RecurseSaveFiles
  122. (
  123. LPCWSTR wszSnapshotPath,
  124. LPCWSTR wszSavedPath,
  125. LPCWSTR wszFilespec
  126. )
  127. {
  128. CComBSTR bstrSP = wszSnapshotPath;
  129. bstrSP.Append(L"\\*.*");
  130. WIN32_FIND_DATA findData;
  131. HANDLE hFile = FindFirstFile(bstrSP, &findData);
  132. if (hFile == INVALID_HANDLE_VALUE)
  133. return;
  134. try
  135. {
  136. do
  137. {
  138. if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  139. {
  140. if (wcscmp(findData.cFileName, L".") == 0 ||
  141. wcscmp(findData.cFileName, L"..") == 0)
  142. continue;
  143. bstrSP = wszSnapshotPath;
  144. bstrSP.Append(L"\\");
  145. bstrSP.Append(findData.cFileName);
  146. CComBSTR bstrCP = wszSavedPath;
  147. bstrCP.Append(L"\\");
  148. bstrCP.Append(findData.cFileName);
  149. SaveFilesMatchingFilespec(bstrSP, bstrCP, wszFilespec);
  150. RecurseSaveFiles(bstrSP, bstrCP, wszFilespec);
  151. }
  152. } while(FindNextFile(hFile, &findData));
  153. FindClose(hFile);
  154. }
  155. catch(...)
  156. {
  157. FindClose(hFile);
  158. throw;
  159. }
  160. }
  161. bool BuildSnapshotPath
  162. (
  163. SAVE_INFO &info,
  164. LPCWSTR wszPath,
  165. CComBSTR &bstrSnapshotPath
  166. )
  167. {
  168. CComBSTR bstrPath((UINT) wcslen(wszPath) + 1);
  169. CComBSTR bstrVolumePath((UINT) wcslen(wszPath) + 1);
  170. wcscpy(bstrPath, wszPath);
  171. if (wszPath[wcslen(wszPath) - 1] != L'\\')
  172. wcscat(bstrPath, L"\\");
  173. if (!GetVolumePathName(bstrPath, bstrVolumePath, (UINT) wcslen(wszPath) + 1))
  174. {
  175. DWORD dwErr = GetLastError();
  176. if (dwErr == ERROR_FILENAME_EXCED_RANGE)
  177. {
  178. if (wcslen(bstrPath) >= 3 && bstrPath[1] == L':' && bstrPath[2] == L'\\')
  179. {
  180. memcpy(bstrVolumePath, bstrPath, 6);
  181. bstrVolumePath[3] = L'\0';
  182. }
  183. else
  184. Error(HRESULT_FROM_WIN32(dwErr), L"GetVolumePathName failed with error %d\nPath=%s.", dwErr, wszPath);
  185. }
  186. else
  187. Error(HRESULT_FROM_WIN32(dwErr), L"GetVolumePathName failed with error %d\nPath=%s.", dwErr, wszPath);
  188. }
  189. WCHAR wszVolumeName[MAX_PATH];
  190. if (!GetVolumeNameForVolumeMountPoint(bstrVolumePath, wszVolumeName, MAX_PATH))
  191. return false;
  192. LPCWSTR wszSnapshotDeviceName = info.mapSnapshots.Lookup(wszVolumeName);
  193. if (wszSnapshotDeviceName == NULL)
  194. Error(E_UNEXPECTED, L"Snapshot device does not exist for path %s", wszPath);
  195. bstrSnapshotPath.Append(wszSnapshotDeviceName);
  196. bstrSnapshotPath.Append(wszPath + wcslen(bstrVolumePath) - 1);
  197. return true;
  198. }
  199. void BuildSavedPath
  200. (
  201. LPCWSTR wszPath,
  202. CComBSTR &bstrSavedPath
  203. )
  204. {
  205. bstrSavedPath.Append(g_wszSavedFilesDirectory);
  206. bstrSavedPath.Append(L"VOLUME");
  207. WCHAR wszDrive[2];
  208. wszDrive[0] = wszPath[0];
  209. wszDrive[1] = L'\0';
  210. bstrSavedPath.Append(wszDrive);
  211. bstrSavedPath.Append(wszPath + 2);
  212. }
  213. void DoExpandEnvironmentStrings(CComBSTR &bstrPath)
  214. {
  215. if (!bstrPath)
  216. return;
  217. if (wcschr(bstrPath, L'%') != NULL)
  218. {
  219. WCHAR wsz[MAX_PATH];
  220. UINT cwc = ExpandEnvironmentStrings(bstrPath, wsz, MAX_PATH);
  221. if (cwc == 0)
  222. {
  223. DWORD dwErr = GetLastError();
  224. Error(HRESULT_FROM_WIN32(dwErr), L"ExpandEnvironmentStrings failed due to error %d.\n", dwErr);
  225. }
  226. else if (cwc <= MAX_PATH)
  227. bstrPath = wsz;
  228. else
  229. {
  230. LPWSTR wszT = new WCHAR[cwc];
  231. if (!ExpandEnvironmentStrings(bstrPath, wszT, MAX_PATH))
  232. {
  233. DWORD dwErr = GetLastError();
  234. Error(HRESULT_FROM_WIN32(dwErr), L"ExpandEnvironmentStrings failed due to error %d.\n", dwErr);
  235. }
  236. bstrPath = wszT;
  237. }
  238. }
  239. }
  240. void SaveDataFiles
  241. (
  242. SAVE_INFO &saveInfo,
  243. IVssWMFiledesc *pFiledesc
  244. )
  245. {
  246. CComBSTR bstrPath;
  247. CComBSTR bstrFilespec;
  248. bool bRecursive;
  249. CComBSTR bstrAlternatePath;
  250. HRESULT hr;
  251. CHECK_SUCCESS(pFiledesc->GetPath(&bstrPath));
  252. CHECK_SUCCESS(pFiledesc->GetFilespec(&bstrFilespec));
  253. CHECK_NOFAIL(pFiledesc->GetRecursive(&bRecursive));
  254. CHECK_NOFAIL(pFiledesc->GetAlternateLocation(&bstrAlternatePath));
  255. DoExpandEnvironmentStrings(bstrPath);
  256. DoExpandEnvironmentStrings(bstrAlternatePath);
  257. CComBSTR bstrSnapshotPath;
  258. CComBSTR bstrSavedPath;
  259. if (!BuildSnapshotPath
  260. (
  261. saveInfo,
  262. bstrAlternatePath ? bstrAlternatePath : bstrPath,
  263. bstrSnapshotPath
  264. ))
  265. return;
  266. BuildSavedPath(bstrPath, bstrSavedPath);
  267. SaveFilesMatchingFilespec(bstrSnapshotPath, bstrSavedPath, bstrFilespec);
  268. if (bRecursive)
  269. RecurseSaveFiles(bstrSnapshotPath, bstrSavedPath, bstrFilespec);
  270. }
  271. // save data files associated with a component
  272. void SaveComponentFiles
  273. (
  274. SAVE_INFO &saveInfo
  275. )
  276. {
  277. HRESULT hr;
  278. PVSSCOMPONENTINFO pInfo = NULL;
  279. CComPtr<IVssWMComponent> pComponent;
  280. CComBSTR bstrComponentLogicalPath;
  281. CComBSTR bstrComponentName;
  282. CHECK_NOFAIL(saveInfo.pComponent->GetLogicalPath(&bstrComponentLogicalPath));
  283. CHECK_SUCCESS(saveInfo.pComponent->GetComponentName(&bstrComponentName));
  284. // calculate the component's full path
  285. CComBSTR bstrFullPath = bstrComponentLogicalPath;
  286. if (bstrFullPath)
  287. bstrFullPath += L"\\";
  288. bstrFullPath += bstrComponentName;
  289. if (!bstrFullPath)
  290. Error(E_OUTOFMEMORY, L"Ran out of memory");
  291. try
  292. {
  293. unsigned cIncludeFiles, cExcludeFiles, cComponents;
  294. CHECK_SUCCESS(saveInfo.pMetadata->GetFileCounts
  295. (
  296. &cIncludeFiles,
  297. &cExcludeFiles,
  298. &cComponents
  299. ));
  300. for(unsigned iComponent = 0; iComponent < cComponents; iComponent++)
  301. {
  302. CHECK_SUCCESS(saveInfo.pMetadata->GetComponent(iComponent, &pComponent));
  303. CHECK_SUCCESS(pComponent->GetComponentInfo(&pInfo));
  304. // if the name and logical path match, we want to save the files
  305. bool bSaveComponent = false;
  306. bSaveComponent = (wcscmp(pInfo->bstrComponentName, bstrComponentName) == 0) &&
  307. (!bstrComponentLogicalPath && !pInfo->bstrLogicalPath) ||
  308. (bstrComponentLogicalPath && pInfo->bstrLogicalPath &&
  309. wcscmp(bstrComponentLogicalPath, pInfo->bstrLogicalPath) == 0);
  310. // if this is a subcomponent, we want to save the files
  311. bSaveComponent = bSaveComponent ||
  312. (pInfo->bstrLogicalPath && (wcsstr(pInfo->bstrLogicalPath, bstrFullPath) == pInfo->bstrLogicalPath));
  313. if (bSaveComponent)
  314. {
  315. for(UINT iFile = 0; iFile < pInfo->cFileCount; iFile++)
  316. {
  317. CComPtr<IVssWMFiledesc> pFiledesc;
  318. CHECK_SUCCESS(pComponent->GetFile(iFile, &pFiledesc));
  319. SaveDataFiles(saveInfo, pFiledesc);
  320. }
  321. for(iFile = 0; iFile < pInfo->cDatabases; iFile++)
  322. {
  323. CComPtr<IVssWMFiledesc> pFiledesc;
  324. CHECK_SUCCESS(pComponent->GetDatabaseFile(iFile, &pFiledesc));
  325. SaveDataFiles(saveInfo, pFiledesc);
  326. }
  327. for(iFile = 0; iFile < pInfo->cLogFiles; iFile++)
  328. {
  329. CComPtr<IVssWMFiledesc> pFiledesc;
  330. CHECK_SUCCESS(pComponent->GetDatabaseLogFile(iFile, &pFiledesc));
  331. SaveDataFiles(saveInfo, pFiledesc);
  332. }
  333. }
  334. pComponent->FreeComponentInfo(pInfo);
  335. pInfo = NULL;
  336. pComponent = NULL;
  337. }
  338. }
  339. catch(...)
  340. {
  341. pComponent->FreeComponentInfo(pInfo);
  342. throw;
  343. }
  344. }
  345. HANDLE OpenMetadataFile(VSS_ID idInstance, BOOL fWrite)
  346. {
  347. // create name of saved metadata file
  348. CComBSTR bstr;
  349. CComBSTR bstrId = idInstance;
  350. bstr.Append(g_wszSavedFilesDirectory);
  351. bstr.Append(L"WRITER");
  352. bstr.Append(bstrId);
  353. bstr.Append(L".xml");
  354. // create and write metadata file
  355. HANDLE hFile = CreateFile
  356. (
  357. bstr,
  358. GENERIC_READ|GENERIC_WRITE,
  359. 0,
  360. NULL,
  361. fWrite ? CREATE_ALWAYS : OPEN_EXISTING,
  362. 0,
  363. NULL
  364. );
  365. if (hFile == INVALID_HANDLE_VALUE)
  366. {
  367. DWORD dwErr = GetLastError();
  368. Error(HRESULT_FROM_WIN32(dwErr), L"CreateFile failed due to error %d.\n", dwErr);
  369. }
  370. return hFile;
  371. }
  372. void SaveFiles
  373. (
  374. IVssBackupComponents *pvbc,
  375. VSS_ID *rgSnapshotId,
  376. UINT cSnapshots
  377. )
  378. {
  379. SAVE_INFO saveInfo;
  380. HRESULT hr;
  381. unsigned cWriterComponents;
  382. unsigned cWriters;
  383. if (g_wszSavedFilesDirectory[0] != L'\0')
  384. {
  385. for(UINT iSnapshot = 0; iSnapshot < cSnapshots; iSnapshot++)
  386. {
  387. VSS_SNAPSHOT_PROP prop;
  388. pvbc->GetSnapshotProperties(rgSnapshotId[iSnapshot], &prop);
  389. CoTaskMemFree(prop.m_pwszOriginatingMachine);
  390. CoTaskMemFree(prop.m_pwszServiceMachine);
  391. CoTaskMemFree(prop.m_pwszExposedName);
  392. CoTaskMemFree(prop.m_pwszExposedPath);
  393. saveInfo.mapSnapshots.Add(prop.m_pwszOriginalVolumeName, prop.m_pwszSnapshotDeviceObject);
  394. }
  395. }
  396. CHECK_SUCCESS(pvbc->GetWriterComponentsCount(&cWriterComponents));
  397. CHECK_SUCCESS(pvbc->GetWriterMetadataCount(&cWriters));
  398. saveInfo.pvbc = pvbc;
  399. for(unsigned iWriter = 0; iWriter < cWriterComponents; iWriter++)
  400. {
  401. CComPtr<IVssWriterComponentsExt> pWriter;
  402. CComPtr<IVssExamineWriterMetadata> pMetadata = NULL;
  403. CHECK_SUCCESS(pvbc->GetWriterComponents(iWriter, &pWriter));
  404. unsigned cComponents;
  405. CHECK_SUCCESS(pWriter->GetComponentCount(&cComponents));
  406. VSS_ID idWriter, idInstance;
  407. CHECK_SUCCESS(pWriter->GetWriterInfo(&idInstance, &idWriter));
  408. if (g_wszSavedFilesDirectory[0] != L'\0')
  409. {
  410. for(unsigned iWriter = 0; iWriter < cWriters; iWriter++)
  411. {
  412. VSS_ID idInstanceMetadata;
  413. CHECK_SUCCESS(pvbc->GetWriterMetadata(iWriter, &idInstanceMetadata, &pMetadata));
  414. if (idInstance == idInstanceMetadata)
  415. break;
  416. pMetadata = NULL;
  417. }
  418. // save metadata
  419. CComBSTR bstrMetadata;
  420. CHECK_SUCCESS(pMetadata->SaveAsXML(&bstrMetadata));
  421. CVssAutoWin32Handle hFile = OpenMetadataFile(idInstance, true);
  422. DWORD cbWritten;
  423. if (!WriteFile(hFile, bstrMetadata, (UINT) wcslen(bstrMetadata)*sizeof(WCHAR), &cbWritten, NULL))
  424. {
  425. CloseHandle(hFile);
  426. DWORD dwErr = GetLastError();
  427. Error(HRESULT_FROM_WIN32(dwErr), L"WriteFile failed due to error %d.\n", dwErr);
  428. }
  429. BS_ASSERT(pMetadata);
  430. saveInfo.pMetadata = pMetadata;
  431. }
  432. for(unsigned iComponent = 0; iComponent < cComponents; iComponent++)
  433. {
  434. CComPtr<IVssComponent> pComponent;
  435. CHECK_SUCCESS(pWriter->GetComponent(iComponent, &pComponent));
  436. VSS_COMPONENT_TYPE ct;
  437. CComBSTR bstrLogicalPath;
  438. CComBSTR bstrComponentName;
  439. CHECK_NOFAIL(pComponent->GetLogicalPath(&bstrLogicalPath));
  440. CHECK_SUCCESS(pComponent->GetComponentType(&ct));
  441. CHECK_SUCCESS(pComponent->GetComponentName(&bstrComponentName));
  442. CComBSTR bstrStamp;
  443. CHECK_NOFAIL(pComponent->GetBackupStamp(&bstrStamp));
  444. if (bstrStamp)
  445. wprintf(L"Backup stamp for component %s = %s\n", bstrComponentName, bstrStamp);
  446. if (g_wszSavedFilesDirectory[0] != L'\0')
  447. {
  448. saveInfo.pComponent = pComponent;
  449. SaveComponentFiles(saveInfo);
  450. }
  451. CHECK_SUCCESS
  452. (
  453. pvbc->SetBackupSucceeded
  454. (
  455. idInstance,
  456. idWriter,
  457. ct,
  458. bstrLogicalPath,
  459. bstrComponentName,
  460. true)
  461. );
  462. }
  463. }
  464. }
  465. class CRestoreFile
  466. {
  467. public:
  468. CRestoreFile(CRestoreFile *pFile)
  469. {
  470. m_hDestination = INVALID_HANDLE_VALUE;
  471. m_pNext = pFile;
  472. }
  473. ~CRestoreFile()
  474. {
  475. if (m_hDestination != INVALID_HANDLE_VALUE)
  476. CloseHandle(m_hDestination);
  477. }
  478. void SetSourceFile(LPCWSTR wszPath) { m_bstrSourceFile = wszPath; }
  479. void SetDestinationHandle(HANDLE hFile) { m_hDestination = hFile; }
  480. void SetDestinationFile(LPCWSTR wszPath) { m_bstrDestinationPath = wszPath; }
  481. CRestoreFile *m_pNext;
  482. CComBSTR m_bstrSourceFile;
  483. CComBSTR m_bstrDestinationPath;
  484. HANDLE m_hDestination;
  485. };
  486. typedef struct _ALTERNATE_MAPPING
  487. {
  488. CComBSTR bstrPath;
  489. CComBSTR bstrAlternatePath;
  490. CComBSTR bstrFilespec;
  491. bool bRecursive;
  492. } ALTERNATE_MAPPING;
  493. static const COPYBUFSIZE = 1024 * 1024;
  494. class RESTORE_INFO
  495. {
  496. public:
  497. RESTORE_INFO()
  498. {
  499. rgMappings = NULL;
  500. pFile = NULL;
  501. pCopyBuf = NULL;
  502. bRebootRequired = false;
  503. cMappings = 0;
  504. }
  505. ~RESTORE_INFO()
  506. {
  507. delete [] rgMappings;
  508. CRestoreFile *pFileT = pFile;
  509. while(pFileT)
  510. {
  511. CRestoreFile *pFileNext = pFileT->m_pNext;
  512. delete pFileT;
  513. pFileT = pFileNext;
  514. }
  515. delete pCopyBuf;
  516. }
  517. VSS_ID idWriter;
  518. VSS_ID idInstance;
  519. VSS_COMPONENT_TYPE ct;
  520. IVssExamineWriterMetadata *pMetadataWriter;
  521. IVssExamineWriterMetadata *pMetadataSaved;
  522. IVssBackupComponents *pvbc;
  523. IVssComponent *pComponent;
  524. LPCWSTR wszLogicalPath;
  525. LPCWSTR wszComponentName;
  526. VSS_RESTOREMETHOD_ENUM method;
  527. bool bRebootRequired;
  528. CRestoreFile *pFile;
  529. unsigned cMappings;
  530. ALTERNATE_MAPPING *rgMappings;
  531. BYTE *pCopyBuf;
  532. };
  533. void CompleteRestore(RESTORE_INFO &info)
  534. {
  535. CRestoreFile *pFile = info.pFile;
  536. while(pFile != NULL)
  537. {
  538. if (pFile->m_hDestination != INVALID_HANDLE_VALUE &&
  539. pFile->m_bstrSourceFile)
  540. {
  541. CVssAutoWin32Handle hSource = CreateFile
  542. (
  543. pFile->m_bstrSourceFile,
  544. GENERIC_READ,
  545. FILE_SHARE_READ,
  546. NULL,
  547. OPEN_EXISTING,
  548. 0,
  549. NULL
  550. );
  551. if (hSource == INVALID_HANDLE_VALUE)
  552. {
  553. DWORD dwErr = GetLastError();
  554. Error(HRESULT_FROM_WIN32(dwErr), L"CreateFile failed with error %d.\n", dwErr);
  555. }
  556. DWORD dwSize = GetFileSize(hSource, NULL);
  557. if (dwSize == 0xffffffff)
  558. {
  559. DWORD dwErr = GetLastError();
  560. Error(HRESULT_FROM_WIN32(dwErr), L"GetFileSize failed with error %d.\n", dwErr);
  561. }
  562. while(dwSize > 0)
  563. {
  564. DWORD cb = min(COPYBUFSIZE, dwSize);
  565. DWORD dwRead, dwWritten;
  566. if (!ReadFile(hSource, info.pCopyBuf, cb, &dwRead, NULL))
  567. {
  568. DWORD dwErr = GetLastError();
  569. Error(HRESULT_FROM_WIN32(dwErr), L"ReadFile failed dued to error %d.\n", dwErr);
  570. }
  571. if (!WriteFile(pFile->m_hDestination, info.pCopyBuf, cb, &dwWritten, NULL) ||
  572. dwWritten < cb)
  573. {
  574. DWORD dwErr = GetLastError();
  575. Error(HRESULT_FROM_WIN32(dwErr), L"Write file failed due to error %d.\n", dwErr);
  576. }
  577. dwSize -= cb;
  578. }
  579. if (!SetEndOfFile(pFile->m_hDestination))
  580. {
  581. DWORD dwErr = GetLastError();
  582. Error(HRESULT_FROM_WIN32(dwErr), L"SetEndOfFile failed due to error %d.\n", dwErr);
  583. }
  584. }
  585. info.pFile = pFile->m_pNext;
  586. delete pFile;
  587. pFile = info.pFile;
  588. }
  589. }
  590. void CleanupFailedRestore(RESTORE_INFO &info)
  591. {
  592. CRestoreFile *pFile = info.pFile;
  593. while (pFile != NULL)
  594. {
  595. info.pFile = pFile->m_pNext;
  596. delete pFile;
  597. pFile = info.pFile;
  598. }
  599. }
  600. bool SetupRestoreFile
  601. (
  602. RESTORE_INFO &info,
  603. LPCWSTR wszSavedFile,
  604. LPCWSTR wszRestoreFile
  605. )
  606. {
  607. CRestoreFile *pFile = new CRestoreFile(info.pFile);
  608. if (info.method == VSS_RME_RESTORE_TO_ALTERNATE_LOCATION)
  609. {
  610. DoCopyFile(wszSavedFile, wszRestoreFile);
  611. pFile->SetDestinationFile(wszRestoreFile);
  612. info.pFile = pFile;
  613. return true;
  614. }
  615. // ensure path up to destination file exists
  616. CComBSTR bstrDestinationPath = wszRestoreFile;
  617. LPWSTR wsz = wcsrchr(bstrDestinationPath, L'\\');
  618. *(wsz+1) = L'\0';
  619. DoCopyFile(NULL, bstrDestinationPath);
  620. if (info.method == VSS_RME_RESTORE_AT_REBOOT)
  621. {
  622. *wsz = L'\0';
  623. CComBSTR bstrTempFileName((UINT) wcslen(bstrDestinationPath) + MAX_PATH);
  624. if (!GetTempFileName(bstrDestinationPath, L"TBCK", 0, bstrTempFileName))
  625. {
  626. DWORD dwErr = GetLastError();
  627. Error(HRESULT_FROM_WIN32(dwErr), L"GetTempFileName failed due to error %d.\n", dwErr);
  628. }
  629. if (!CopyFile(wszSavedFile, bstrTempFileName, FALSE))
  630. {
  631. DWORD dwErr = GetLastError();
  632. Error(HRESULT_FROM_WIN32(dwErr), L"CopyFile failed due to error %d.\n", dwErr);
  633. }
  634. if (!MoveFileEx
  635. (
  636. bstrTempFileName,
  637. wszRestoreFile,
  638. MOVEFILE_DELAY_UNTIL_REBOOT|MOVEFILE_REPLACE_EXISTING
  639. ))
  640. {
  641. DWORD dwErr = GetLastError();
  642. Error(HRESULT_FROM_WIN32(dwErr), L"MoveFileEx failed due to error %d.\n", dwErr);
  643. }
  644. info.bRebootRequired = true;
  645. }
  646. else if (info.method == VSS_RME_RESTORE_IF_NOT_THERE)
  647. {
  648. HANDLE hFile = CreateFile
  649. (
  650. wszRestoreFile,
  651. GENERIC_WRITE,
  652. 0,
  653. NULL,
  654. CREATE_NEW,
  655. 0,
  656. NULL
  657. );
  658. // assume if the create fails
  659. if (hFile == INVALID_HANDLE_VALUE)
  660. {
  661. DWORD dwErr = GetLastError();
  662. if (dwErr == ERROR_FILE_EXISTS)
  663. return false;
  664. else
  665. Error(HRESULT_FROM_WIN32(dwErr), L"CreateFile failed due to error %d.\n", dwErr);
  666. }
  667. pFile->SetDestinationHandle(hFile);
  668. }
  669. else if (info.method == VSS_RME_RESTORE_IF_CAN_REPLACE)
  670. {
  671. HANDLE hFile = CreateFile
  672. (
  673. wszRestoreFile,
  674. GENERIC_WRITE|GENERIC_WRITE,
  675. 0,
  676. NULL,
  677. CREATE_ALWAYS,
  678. 0,
  679. NULL
  680. );
  681. if (hFile == INVALID_HANDLE_VALUE)
  682. {
  683. DWORD dwErr = GetLastError();
  684. if (dwErr == ERROR_SHARING_VIOLATION ||
  685. dwErr == ERROR_USER_MAPPED_FILE ||
  686. dwErr == ERROR_LOCK_VIOLATION)
  687. return false;
  688. else
  689. Error(HRESULT_FROM_WIN32(dwErr), L"CreateFile failed due to error %d.\n", dwErr);
  690. }
  691. pFile->SetDestinationHandle(hFile);
  692. pFile->SetSourceFile(wszSavedFile);
  693. }
  694. info.pFile = pFile;
  695. return true;
  696. }
  697. void TranslateRestorePath
  698. (
  699. RESTORE_INFO &info,
  700. CComBSTR &bstrRP,
  701. LPCWSTR wszFilename
  702. )
  703. {
  704. ALTERNATE_MAPPING *pMapping = NULL;
  705. UINT cwc = 0, cwcMapping = 0;
  706. for(unsigned iMapping = 0; iMapping < info.cMappings; iMapping++)
  707. {
  708. pMapping = &info.rgMappings[iMapping];
  709. cwc = (UINT) wcslen(bstrRP);
  710. cwcMapping = (UINT) wcslen(pMapping->bstrPath);
  711. if (cwc < cwcMapping)
  712. continue;
  713. if (_wcsnicmp(bstrRP, pMapping->bstrPath, cwcMapping) != 0)
  714. continue;
  715. if (cwcMapping != cwc && !pMapping->bRecursive)
  716. continue;
  717. BOOL bReplacePath = FALSE;
  718. LPCWSTR wszFilespec = pMapping->bstrFilespec;
  719. if (wcscmp(wszFilespec, L"*") == 0 ||
  720. wcscmp(wszFilespec, L"*.*") == 0)
  721. bReplacePath = true;
  722. else if (wcschr(wszFilespec, L'*') == NULL)
  723. bReplacePath = _wcsicmp(wszFilespec, wszFilename) == 0;
  724. else if (wcsncmp(wszFilespec, L"*.", 2) == 0)
  725. {
  726. LPCWSTR wszSuffix = wcschr(wszFilename, L'.');
  727. if (wszSuffix == NULL)
  728. bReplacePath = wcslen(wszFilespec) == 2;
  729. else
  730. bReplacePath = _wcsicmp(wszSuffix, wszFilespec + 1) == 0;
  731. }
  732. else
  733. {
  734. UINT cwcFilespec = (UINT) wcslen(wszFilespec);
  735. if (cwcFilespec > 2 &&
  736. _wcsicmp(wszFilespec + cwcFilespec - 2, L".*") == 0)
  737. {
  738. if (wcslen(wszFilename) >= cwcFilespec - 1)
  739. bReplacePath = _wcsnicmp(wszFilename, wszFilespec, cwcFilespec - 1) == 0;
  740. }
  741. }
  742. if (bReplacePath)
  743. {
  744. if (cwcMapping == cwc)
  745. bstrRP = pMapping->bstrAlternatePath;
  746. else
  747. {
  748. CComBSTR bstr;
  749. bstr.Append(pMapping->bstrAlternatePath);
  750. bstr.Append(bstrRP + cwcMapping);
  751. bstrRP = bstr;
  752. }
  753. break;
  754. }
  755. }
  756. }
  757. bool SetupRestoreFilesMatchingFilespec
  758. (
  759. RESTORE_INFO &info,
  760. LPCWSTR wszSourcePath,
  761. LPCWSTR wszRestorePath,
  762. LPCWSTR wszFilespec
  763. )
  764. {
  765. CComBSTR bstrSP = wszSourcePath;
  766. bstrSP.Append(L"\\");
  767. bstrSP.Append(wszFilespec);
  768. WIN32_FIND_DATA findData;
  769. HANDLE hFile = FindFirstFile(bstrSP, &findData);
  770. if (hFile == INVALID_HANDLE_VALUE)
  771. return true;
  772. try
  773. {
  774. do
  775. {
  776. if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
  777. {
  778. CComBSTR bstrRP = wszRestorePath;
  779. bstrSP = wszSourcePath;
  780. bstrSP.Append(L"\\");
  781. bstrSP.Append(findData.cFileName);
  782. if (info.method == VSS_RME_RESTORE_TO_ALTERNATE_LOCATION)
  783. TranslateRestorePath(info, bstrRP, findData.cFileName);
  784. bstrRP.Append(L"\\");
  785. bstrRP.Append(findData.cFileName);
  786. if (!SetupRestoreFile(info, bstrSP, bstrRP))
  787. return false;
  788. }
  789. } while(FindNextFile(hFile, &findData));
  790. FindClose(hFile);
  791. }
  792. catch(...)
  793. {
  794. FindClose(hFile);
  795. throw;
  796. }
  797. return true;
  798. }
  799. bool RecursiveRestoreFiles
  800. (
  801. RESTORE_INFO &info,
  802. LPCWSTR wszSavedPath,
  803. LPCWSTR wszPath,
  804. LPCWSTR wszFilespec
  805. )
  806. {
  807. CComBSTR bstrSP = wszSavedPath;
  808. bstrSP.Append(L"\\*.*");
  809. WIN32_FIND_DATA findData;
  810. HANDLE hFile = FindFirstFile(bstrSP, &findData);
  811. if (hFile == INVALID_HANDLE_VALUE)
  812. return true;
  813. try
  814. {
  815. do
  816. {
  817. if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  818. {
  819. if (wcscmp(findData.cFileName, L".") == 0 ||
  820. wcscmp(findData.cFileName, L"..") == 0)
  821. continue;
  822. bstrSP = wszSavedPath;
  823. bstrSP.Append(L"\\");
  824. bstrSP.Append(findData.cFileName);
  825. CComBSTR bstrRP = wszPath;
  826. bstrRP.Append(L"\\");
  827. bstrRP.Append(findData.cFileName);
  828. if (!SetupRestoreFilesMatchingFilespec(info, bstrSP, bstrRP, wszFilespec))
  829. return false;
  830. if (!RecursiveRestoreFiles(info, bstrSP, bstrRP, wszFilespec))
  831. return false;
  832. }
  833. } while(FindNextFile(hFile, &findData));
  834. FindClose(hFile);
  835. }
  836. catch(...)
  837. {
  838. FindClose(hFile);
  839. throw;
  840. }
  841. return true;
  842. }
  843. bool SetupRestoreDataFiles(RESTORE_INFO &info, IVssWMFiledesc *pFiledesc)
  844. {
  845. HRESULT hr;
  846. CComBSTR bstrPath;
  847. CComBSTR bstrFilespec;
  848. bool bRecursive;
  849. CHECK_SUCCESS(pFiledesc->GetPath(&bstrPath));
  850. CHECK_SUCCESS(pFiledesc->GetFilespec(&bstrFilespec));
  851. CHECK_NOFAIL(pFiledesc->GetRecursive(&bRecursive));
  852. CComBSTR bstrSavedPath;
  853. BuildSavedPath(bstrPath, bstrSavedPath);
  854. if (!SetupRestoreFilesMatchingFilespec(info, bstrSavedPath, bstrPath, bstrFilespec))
  855. return false;
  856. if (bRecursive)
  857. return RecursiveRestoreFiles(info, bstrSavedPath, bstrPath, bstrFilespec);
  858. return true;
  859. }
  860. bool SetupRestoreDataFilesForComponent(RESTORE_INFO& info, IVssWMComponent* pComponent)
  861. {
  862. HRESULT hr = S_OK;
  863. PVSSCOMPONENTINFO pInfo = NULL;
  864. CHECK_SUCCESS(pComponent->GetComponentInfo(&pInfo));
  865. for(UINT iFile = 0; iFile < pInfo->cFileCount; iFile++)
  866. {
  867. CComPtr<IVssWMFiledesc> pFiledesc;
  868. CHECK_SUCCESS(pComponent->GetFile(iFile, &pFiledesc));
  869. if (!SetupRestoreDataFiles(info, pFiledesc))
  870. {
  871. pComponent->FreeComponentInfo(pInfo);
  872. return false;
  873. }
  874. }
  875. for(iFile = 0; iFile < pInfo->cDatabases; iFile++)
  876. {
  877. CComPtr<IVssWMFiledesc> pFiledesc;
  878. CHECK_SUCCESS(pComponent->GetDatabaseFile(iFile, &pFiledesc));
  879. if (!SetupRestoreDataFiles(info, pFiledesc))
  880. {
  881. pComponent->FreeComponentInfo(pInfo);
  882. return false;
  883. }
  884. }
  885. for(iFile = 0; iFile < pInfo->cLogFiles; iFile++)
  886. {
  887. CComPtr<IVssWMFiledesc> pFiledesc;
  888. CHECK_SUCCESS(pComponent->GetDatabaseLogFile(iFile, &pFiledesc));
  889. if (!SetupRestoreDataFiles(info, pFiledesc))
  890. {
  891. pComponent->FreeComponentInfo(pInfo);
  892. return false;
  893. }
  894. }
  895. pComponent->FreeComponentInfo(pInfo);
  896. return true;
  897. }
  898. void LoadMetadataFile(VSS_ID idInstance, IVssExamineWriterMetadata **ppMetadataSaved)
  899. {
  900. HRESULT hr;
  901. // load saved metadata
  902. CVssAutoWin32Handle hFile = OpenMetadataFile(idInstance, false);
  903. DWORD dwSize = GetFileSize(hFile, NULL);
  904. if (dwSize == 0xffffffff)
  905. {
  906. DWORD dwErr = GetLastError();
  907. Error(HRESULT_FROM_WIN32(dwErr), L"GetFileSize failed with error %d.\n", dwErr);
  908. }
  909. CComBSTR bstrXML(dwSize/sizeof(WCHAR));
  910. DWORD dwRead;
  911. if(!ReadFile(hFile, bstrXML, dwSize, &dwRead, NULL))
  912. {
  913. DWORD dwErr = GetLastError();
  914. Error(HRESULT_FROM_WIN32(dwErr), L"ReadFile failed with error %d.\n", dwErr);
  915. }
  916. // null terminate XML string
  917. bstrXML[dwSize/sizeof(WCHAR)] = L'\0';
  918. CHECK_SUCCESS(CreateVssExamineWriterMetadata(bstrXML, ppMetadataSaved));
  919. }
  920. void RestoreComponentFiles(RESTORE_INFO &info)
  921. {
  922. HRESULT hr;
  923. PVSSCOMPONENTINFO pInfo = NULL;
  924. CComPtr<IVssWMComponent> pComponent;
  925. VSS_FILE_RESTORE_STATUS status = VSS_RS_NONE;
  926. try
  927. {
  928. CComBSTR bstrUserProcedure;
  929. CComBSTR bstrService;
  930. bool bRebootRequired;
  931. VSS_WRITERRESTORE_ENUM writerRestore;
  932. IVssExamineWriterMetadata *pMetadata;
  933. UINT cIncludeFiles, cExcludeFiles, cComponents;
  934. CHECK_SUCCESS(info.pMetadataSaved->GetFileCounts(&cIncludeFiles, &cExcludeFiles, &cComponents));
  935. for (UINT iComponent = 0; iComponent < cComponents; iComponent++)
  936. {
  937. CHECK_SUCCESS(info.pMetadataSaved->GetComponent(iComponent, &pComponent));
  938. CHECK_SUCCESS(pComponent->GetComponentInfo(&pInfo));
  939. if (wcscmp(pInfo->bstrComponentName, info.wszComponentName) == 0)
  940. {
  941. if ((!info.wszLogicalPath && !pInfo->bstrLogicalPath) ||
  942. (info.wszLogicalPath && pInfo->bstrLogicalPath &&
  943. wcscmp(info.wszLogicalPath, pInfo->bstrLogicalPath) == 0))
  944. break;
  945. }
  946. pComponent->FreeComponentInfo(pInfo);
  947. pInfo = NULL;
  948. pComponent = NULL;
  949. }
  950. pMetadata = info.pMetadataSaved;
  951. BS_ASSERT(pComponent != NULL);
  952. CHECK_NOFAIL(pMetadata->GetRestoreMethod
  953. (
  954. &info.method,
  955. &bstrService,
  956. &bstrUserProcedure,
  957. &writerRestore,
  958. &bRebootRequired,
  959. &info.cMappings
  960. ));
  961. // cannot do anything with custom method
  962. if (info.method == VSS_RME_CUSTOM)
  963. {
  964. pComponent->FreeComponentInfo(pInfo);
  965. return;
  966. }
  967. BS_ASSERT(info.method != VSS_RME_STOP_RESTORE_START);
  968. if (info.rgMappings == NULL)
  969. {
  970. if (info.cMappings > 0)
  971. {
  972. info.rgMappings = new ALTERNATE_MAPPING[info.cMappings];
  973. if (info.rgMappings == NULL)
  974. Error(E_OUTOFMEMORY, L"OutOfMemory");
  975. }
  976. for(unsigned iMapping = 0; iMapping < info.cMappings; iMapping++)
  977. {
  978. CComPtr<IVssWMFiledesc> pFiledesc;
  979. CHECK_SUCCESS(pMetadata->GetAlternateLocationMapping(iMapping, &pFiledesc));
  980. CHECK_SUCCESS(pFiledesc->GetPath(&info.rgMappings[iMapping].bstrPath));
  981. DoExpandEnvironmentStrings(info.rgMappings[iMapping].bstrPath);
  982. CHECK_SUCCESS(pFiledesc->GetAlternateLocation(&info.rgMappings[iMapping].bstrAlternatePath));
  983. DoExpandEnvironmentStrings(info.rgMappings[iMapping].bstrAlternatePath);
  984. CHECK_SUCCESS(pFiledesc->GetFilespec(&info.rgMappings[iMapping].bstrFilespec));
  985. CHECK_SUCCESS(pFiledesc->GetRecursive(&info.rgMappings[iMapping].bRecursive));
  986. }
  987. }
  988. if (info.method == VSS_RME_RESTORE_IF_NOT_THERE ||
  989. info.method == VSS_RME_RESTORE_IF_CAN_REPLACE)
  990. {
  991. if (info.pCopyBuf == NULL)
  992. {
  993. info.pCopyBuf = new BYTE[COPYBUFSIZE];
  994. if (info.pCopyBuf == NULL)
  995. Error(E_OUTOFMEMORY, L"Out of Memory");
  996. }
  997. }
  998. _retry:
  999. info.pFile = NULL;
  1000. bool bFailRestore = false;
  1001. // setup restore data files for the current component
  1002. bFailRestore = !SetupRestoreDataFilesForComponent(info, pComponent);
  1003. // setup restore data files for all subcomponents
  1004. UINT cSubcomponents = 0;
  1005. CHECK_SUCCESS(info.pComponent->GetRestoreSubcomponentCount(&cSubcomponents));
  1006. for (UINT iSubcomponent = 0; !bFailRestore && iSubcomponent < cSubcomponents; iSubcomponent++)
  1007. {
  1008. CComBSTR bstrSubLogicalPath, bstrSubName;
  1009. bool foo;
  1010. CHECK_SUCCESS(info.pComponent->GetRestoreSubcomponent(iSubcomponent, &bstrSubLogicalPath,
  1011. &bstrSubName, &foo));
  1012. CComPtr<IVssWMComponent> pSubcomponent;
  1013. if (!FindComponent(pMetadata, bstrSubLogicalPath, bstrSubName, &pSubcomponent))
  1014. Error(E_UNEXPECTED, L"an invalid subcomponent was selected");
  1015. bFailRestore = !SetupRestoreDataFilesForComponent(info, pSubcomponent);
  1016. }
  1017. // calculate the full path to the current component
  1018. CComBSTR fullPath = info.wszLogicalPath;
  1019. if (fullPath)
  1020. fullPath += L"\\";
  1021. fullPath += info.wszComponentName;
  1022. if (!fullPath)
  1023. Error(E_OUTOFMEMORY, L"Out of memory!");
  1024. // setup restore data files for all subcomponents
  1025. for (UINT iComponent = 0; !cSubcomponents && !bFailRestore && iComponent < cComponents; iComponent++)
  1026. {
  1027. CComPtr<IVssWMComponent> pCurrentComponent;
  1028. PVSSCOMPONENTINFO pCurrentInfo;
  1029. CHECK_SUCCESS(pMetadata->GetComponent(iComponent, &pCurrentComponent));
  1030. CHECK_SUCCESS(pCurrentComponent->GetComponentInfo(&pCurrentInfo));
  1031. if (pCurrentInfo->bstrLogicalPath &&
  1032. wcsstr(pCurrentInfo->bstrLogicalPath, fullPath) == pCurrentInfo->bstrLogicalPath)
  1033. {
  1034. bFailRestore = !SetupRestoreDataFilesForComponent(info, pCurrentComponent);
  1035. }
  1036. pCurrentComponent->FreeComponentInfo(pCurrentInfo);
  1037. }
  1038. if (!bFailRestore)
  1039. {
  1040. status = VSS_RS_FAILED;
  1041. CompleteRestore(info);
  1042. status = VSS_RS_ALL;
  1043. if (bRebootRequired)
  1044. info.bRebootRequired = true;
  1045. }
  1046. else
  1047. {
  1048. CleanupFailedRestore(info);
  1049. if ((info.method == VSS_RME_RESTORE_IF_NOT_THERE ||
  1050. info.method == VSS_RME_RESTORE_IF_CAN_REPLACE) &&
  1051. info.cMappings > 0)
  1052. {
  1053. info.method = VSS_RME_RESTORE_TO_ALTERNATE_LOCATION;
  1054. goto _retry;
  1055. }
  1056. }
  1057. pComponent->FreeComponentInfo(pInfo);
  1058. pInfo = NULL;
  1059. pComponent = NULL;
  1060. }
  1061. catch(...)
  1062. {
  1063. pComponent->FreeComponentInfo(pInfo);
  1064. throw;
  1065. }
  1066. CHECK_SUCCESS(info.pvbc->SetFileRestoreStatus
  1067. (
  1068. info.idWriter,
  1069. info.ct,
  1070. info.wszLogicalPath,
  1071. info.wszComponentName,
  1072. status
  1073. ));
  1074. }
  1075. void RestoreFiles(IVssBackupComponents *pvbc, const CSimpleMap<VSS_ID, HRESULT>& failedWriters)
  1076. {
  1077. RESTORE_INFO info;
  1078. HRESULT hr;
  1079. UINT cWriterComponents = 0, cWriters = 0;
  1080. info.pvbc = pvbc;
  1081. CHECK_SUCCESS(pvbc->GetWriterComponentsCount(&cWriterComponents));
  1082. CHECK_SUCCESS(pvbc->GetWriterMetadataCount(&cWriters));
  1083. info.pvbc = pvbc;
  1084. for(unsigned iWriter = 0; iWriter < cWriterComponents; iWriter++)
  1085. {
  1086. CComPtr<IVssWriterComponentsExt> pWriter;
  1087. CComPtr<IVssExamineWriterMetadata> pMetadata = NULL;
  1088. CComPtr<IVssExamineWriterMetadata> pMetadataSaved = NULL;
  1089. CHECK_SUCCESS(pvbc->GetWriterComponents(iWriter, &pWriter));
  1090. unsigned cComponents;
  1091. CHECK_SUCCESS(pWriter->GetComponentCount(&cComponents));
  1092. for(unsigned iComponent = 0; iComponent < cComponents; iComponent++)
  1093. {
  1094. CComPtr<IVssComponent> pComponent;
  1095. bool bSelectedForRestore = false;
  1096. CHECK_SUCCESS(pWriter->GetComponent(iComponent, &pComponent));
  1097. CHECK_NOFAIL(pComponent->IsSelectedForRestore(&bSelectedForRestore));
  1098. if (bSelectedForRestore)
  1099. break;
  1100. UINT cSubcomponents = 0;
  1101. CHECK_SUCCESS(pComponent->GetRestoreSubcomponentCount(&cSubcomponents));
  1102. if (cSubcomponents > 0)
  1103. break;
  1104. CComBSTR bstrOptions;
  1105. CHECK_NOFAIL(pComponent->GetRestoreOptions(&bstrOptions));
  1106. if (bstrOptions.Length() != 0 && wcscmp(bstrOptions, L"RESTORE") == 0)
  1107. break;
  1108. }
  1109. if (iComponent >= cComponents)
  1110. continue;
  1111. CHECK_SUCCESS(pWriter->GetWriterInfo(&info.idInstance, &info.idWriter));
  1112. for(unsigned iWriter = 0; iWriter < cWriters; iWriter++)
  1113. {
  1114. VSS_ID idInstance, idWriter;
  1115. CComBSTR bstrWriterName;
  1116. VSS_USAGE_TYPE usage;
  1117. VSS_SOURCE_TYPE source;
  1118. CHECK_SUCCESS(pvbc->GetWriterMetadata(iWriter, &idInstance, &pMetadata));
  1119. CHECK_SUCCESS
  1120. (
  1121. pMetadata->GetIdentity
  1122. (
  1123. &idInstance,
  1124. &idWriter,
  1125. &bstrWriterName,
  1126. &usage,
  1127. &source
  1128. )
  1129. );
  1130. if (idWriter == info.idWriter)
  1131. break;
  1132. pMetadata = NULL;
  1133. }
  1134. // load saved metadata
  1135. LoadMetadataFile(info.idInstance, &pMetadataSaved);
  1136. info.pMetadataWriter = pMetadata;
  1137. info.pMetadataSaved = pMetadataSaved;
  1138. bool bWriterFailed = failedWriters.Lookup(info.idInstance) != NULL;
  1139. for(unsigned iComponent = 0; iComponent < cComponents; iComponent++)
  1140. {
  1141. CComPtr<IVssComponent> pComponent;
  1142. CHECK_SUCCESS(pWriter->GetComponent(iComponent, &pComponent));
  1143. bool bSelectedForRestore = false;
  1144. CHECK_NOFAIL(pComponent->IsSelectedForRestore(&bSelectedForRestore));
  1145. UINT cSubcomponents = 0;
  1146. CHECK_SUCCESS(pComponent->GetRestoreSubcomponentCount(&cSubcomponents));
  1147. if (!bSelectedForRestore && cSubcomponents == 0)
  1148. {
  1149. // BUGBUG: huge hack to fix the AD case. We eventually need to
  1150. // BUGBUG: do something better here
  1151. CComBSTR bstrOptions;
  1152. CHECK_NOFAIL(pComponent->GetRestoreOptions(&bstrOptions));
  1153. if (bstrOptions.Length() == 0 || wcscmp(bstrOptions, L"RESTORE") != 0)
  1154. continue;
  1155. }
  1156. CComBSTR bstrLogicalPath;
  1157. CComBSTR bstrComponentName;
  1158. CHECK_NOFAIL(pComponent->GetLogicalPath(&bstrLogicalPath));
  1159. CHECK_SUCCESS(pComponent->GetComponentType(&info.ct));
  1160. CHECK_SUCCESS(pComponent->GetComponentName(&bstrComponentName));
  1161. CComBSTR bstrPreRestoreFailure;
  1162. CHECK_NOFAIL(pComponent->GetPreRestoreFailureMsg(&bstrPreRestoreFailure));
  1163. if (bstrPreRestoreFailure)
  1164. {
  1165. wprintf
  1166. (
  1167. L"Not restoring Component %s\\%s because PreRestore failed:\n%s\n",
  1168. bstrLogicalPath,
  1169. bstrComponentName,
  1170. bstrPreRestoreFailure
  1171. );
  1172. continue;
  1173. }
  1174. else if (bWriterFailed)
  1175. {
  1176. wprintf
  1177. (
  1178. L"Not restoring Component %s\\%s because PreRestore failed:\n\n",
  1179. bstrLogicalPath,
  1180. bstrComponentName
  1181. );
  1182. continue;
  1183. }
  1184. info.pComponent = pComponent;
  1185. info.wszLogicalPath = bstrLogicalPath;
  1186. info.wszComponentName = bstrComponentName;
  1187. RestoreComponentFiles(info);
  1188. }
  1189. // mappings are on a per writer basis and need to be cleared
  1190. // when advancing to a new writer
  1191. delete [] info.rgMappings;
  1192. info.rgMappings = NULL;
  1193. info.cMappings = 0;
  1194. }
  1195. if (info.bRebootRequired)
  1196. wprintf(L"\n\n!!REBOOT is Required to complete the restore operation.\n\n");
  1197. }