Source code of Windows XP (NT5)
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.

2173 lines
48 KiB

  1. /*++
  2. 1998 Seagate Software, Inc. All rights reserved.
  3. Module Name:
  4. fsaitem.cpp
  5. Abstract:
  6. This class contains represents a scan item (i.e. file or directory) for NTFS 5.0.
  7. Author:
  8. Chuck Bardeen [cbardeen] 1-Dec-1996
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #define WSB_TRACE_IS WSB_TRACE_BIT_FSA
  13. #include "wsb.h"
  14. #include "wsbtrak.h"
  15. #include "fsa.h"
  16. #include "mover.h"
  17. #include "fsaitem.h"
  18. #include "fsaprem.h"
  19. static USHORT iCountItem = 0; // Count of existing objects
  20. HRESULT
  21. CFsaScanItem::CompareTo(
  22. IN IUnknown* pUnknown,
  23. OUT SHORT* pResult
  24. )
  25. /*++
  26. Implements:
  27. IWsbCollectable::CompareTo().
  28. --*/
  29. {
  30. HRESULT hr = S_OK;
  31. CComPtr<IFsaScanItem> pScanItem;
  32. WsbTraceIn(OLESTR("CFsaScanItem::CompareTo"), OLESTR(""));
  33. try {
  34. // Did they give us a valid item to compare to?
  35. WsbAssert(0 != pUnknown, E_POINTER);
  36. // We need the IWsbBool interface to get the value of the object.
  37. WsbAffirmHr(pUnknown->QueryInterface(IID_IFsaScanItem, (void**) &pScanItem));
  38. // Compare the rules.
  39. hr = CompareToIScanItem(pScanItem, pResult);
  40. } WsbCatch(hr);
  41. WsbTraceOut(OLESTR("CFsaScanItem::CompareTo"), OLESTR("hr = <%ls>, result = <%ls>"), WsbHrAsString(hr), WsbPtrToShortAsString(pResult));
  42. return(hr);
  43. }
  44. HRESULT
  45. CFsaScanItem::CompareToIScanItem(
  46. IN IFsaScanItem* pScanItem,
  47. OUT SHORT* pResult
  48. )
  49. /*++
  50. Implements:
  51. IFsaScanItem::CompareToIScanItem().
  52. --*/
  53. {
  54. HRESULT hr = S_OK;
  55. CWsbStringPtr path;
  56. CWsbStringPtr name;
  57. WsbTraceIn(OLESTR("CFsaScanItem::CompareToIScanItem"), OLESTR(""));
  58. try {
  59. // Did they give us a valid item to compare to?
  60. WsbAssert(0 != pScanItem, E_POINTER);
  61. // Either compare the name or the id.
  62. WsbAffirmHr(pScanItem->GetPath(&path, 0));
  63. WsbAffirmHr(pScanItem->GetName(&name, 0));
  64. hr = CompareToPathAndName(path, name, pResult);
  65. } WsbCatch(hr);
  66. WsbTraceOut(OLESTR("CFsaScanItem::CompareToIScanItem"), OLESTR("hr = <%ls>, result = <%ls>"), WsbHrAsString(hr), WsbPtrToShortAsString(pResult));
  67. return(hr);
  68. }
  69. HRESULT
  70. CFsaScanItem::CompareToPathAndName(
  71. IN OLECHAR* path,
  72. IN OLECHAR* name,
  73. OUT SHORT* pResult
  74. )
  75. /*++
  76. Implements:
  77. IFsaScanItem::CompareToPathAndName().
  78. --*/
  79. {
  80. HRESULT hr = S_OK;
  81. SHORT aResult = 0;
  82. WsbTraceIn(OLESTR("CFsaScanItem::CompareToPathAndName"), OLESTR(""));
  83. try {
  84. // Compare the path.
  85. aResult = (SHORT) _wcsicmp(m_path, path);
  86. // Compare the name.
  87. if (0 == aResult) {
  88. aResult = (SHORT) _wcsicmp(m_findData.cFileName, name);
  89. }
  90. if (0 != aResult) {
  91. hr = S_FALSE;
  92. }
  93. if (0 != pResult) {
  94. *pResult = aResult;
  95. }
  96. } WsbCatch(hr);
  97. WsbTraceOut(OLESTR("CFsaScanItem::CompareToPathAndName"), OLESTR("hr = <%ls>, result = <%u>"), WsbHrAsString(hr), aResult);
  98. return(hr);
  99. }
  100. HRESULT
  101. CFsaScanItem::Copy(
  102. IN OLECHAR* dest,
  103. IN BOOL /*retainHierarcy*/,
  104. IN BOOL /*expandPlaceholders*/,
  105. IN BOOL overwriteExisting
  106. )
  107. /*++
  108. Implements:
  109. IFsaScanItem::Copy().
  110. --*/
  111. {
  112. HRESULT hr = S_OK;
  113. try {
  114. // NOTE : This default behavior causes placeholders
  115. // to be expanded and probably doesn't retain the heirarchy.
  116. WsbAssert(0 != dest, E_POINTER);
  117. WsbAssert(CopyFile(m_findData.cFileName, dest, overwriteExisting), E_FAIL);
  118. } WsbCatch(hr);
  119. return(hr);
  120. }
  121. HRESULT
  122. CFsaScanItem::CreateLocalStream(
  123. OUT IStream **ppStream
  124. )
  125. /*++
  126. Implements:
  127. IFsaScanItem::CreateLocalStream().
  128. --*/
  129. {
  130. HRESULT hr = S_OK;
  131. LARGE_INTEGER fileSize;
  132. CWsbStringPtr volName;
  133. WsbTraceIn(OLESTR("CFsaScanItem::CreateLocalStream"), OLESTR(""));
  134. try {
  135. CWsbStringPtr localName;
  136. if ( !m_gotPlaceholder) {
  137. //
  138. // Get the placeholder info
  139. //
  140. fileSize.LowPart = m_findData.nFileSizeLow;
  141. fileSize.HighPart = m_findData.nFileSizeHigh;
  142. WsbAffirmHr(IsManaged(0, fileSize.QuadPart));
  143. }
  144. WsbAssert( 0 != ppStream, E_POINTER);
  145. WsbAffirmHr( CoCreateInstance( CLSID_CNtFileIo, 0, CLSCTX_SERVER, IID_IDataMover, (void **)&m_pDataMover ) );
  146. //
  147. // Set the device name for the mover so it can set the source infor for the USN journal.
  148. //
  149. WsbAffirmHr(m_pResource->GetPath(&volName, 0));
  150. WsbAffirmHr( m_pDataMover->SetDeviceName(volName));
  151. //WsbAffirmHr(GetFullPathAndName( NULL, 0, &localName, 0));
  152. WsbAffirmHr(GetFullPathAndName( OLESTR("\\\\?\\"), 0, &localName, 0));
  153. WsbAffirmHr( m_pDataMover->CreateLocalStream(
  154. localName, MVR_MODE_WRITE | MVR_FLAG_HSM_SEMANTICS | MVR_FLAG_POSIX_SEMANTICS, &m_pStream ) );
  155. LARGE_INTEGER seekTo;
  156. ULARGE_INTEGER pos;
  157. seekTo.QuadPart = m_placeholder.dataStreamStart;
  158. WsbAffirmHr( m_pStream->Seek( seekTo, STREAM_SEEK_SET, &pos ) );
  159. *ppStream = m_pStream;
  160. m_pStream->AddRef();
  161. } WsbCatch(hr);
  162. WsbTraceOut(OLESTR("CFsaScanItem::CreateLocalStream"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  163. return(hr);
  164. }
  165. HRESULT
  166. CFsaScanItem::Delete(
  167. void
  168. )
  169. /*++
  170. Implements:
  171. IFsaScanItem::Delete().
  172. --*/
  173. {
  174. HRESULT hr = S_OK;
  175. CWsbStringPtr tmpString;
  176. HANDLE fileHandle;
  177. try {
  178. // This is the name of the file we want to delete.
  179. WsbAffirmHr(GetFullPathAndName(OLESTR("\\\\?\\"), 0, &tmpString, 0));
  180. // Since we want to be POSIX compliant, we can't use DeleteFile() and instead will
  181. // open with the delete on close flag. This doesn't handle read-only files, so we
  182. // have to change that ourselves.
  183. WsbAffirmHr(MakeReadWrite());
  184. fileHandle = CreateFile(tmpString, GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_POSIX_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE, 0);
  185. if (INVALID_HANDLE_VALUE == fileHandle) {
  186. WsbThrow(HRESULT_FROM_WIN32(GetLastError()));
  187. } else {
  188. if (!CloseHandle(fileHandle)) {
  189. WsbThrow(HRESULT_FROM_WIN32(GetLastError()));
  190. }
  191. }
  192. } WsbCatch(hr);
  193. return(hr);
  194. }
  195. #pragma optimize("g", off)
  196. HRESULT
  197. CFsaScanItem::FinalConstruct(
  198. void
  199. )
  200. /*++
  201. Implements:
  202. CComObjectRoot::FinalConstruct().
  203. --*/
  204. {
  205. HRESULT hr = S_OK;
  206. WsbTraceIn(OLESTR("CFsaScanItem::FinalConstruct"), OLESTR(""));
  207. try {
  208. WsbAffirmHr(CComObjectRoot::FinalConstruct());
  209. m_handle = INVALID_HANDLE_VALUE;
  210. m_gotPhysicalSize = FALSE;
  211. m_physicalSize.QuadPart = 0;
  212. m_gotPlaceholder = FALSE;
  213. m_changedAttributes = FALSE;
  214. m_handleRPI = 0;
  215. // Add class to object table
  216. WSB_OBJECT_ADD(CLSID_CFsaScanItemNTFS, this);
  217. } WsbCatch(hr);
  218. iCountItem++;
  219. WsbTraceOut(OLESTR("CFsaScanItem::FinalConstruct"), OLESTR("hr = <%ls>, Count is <%d>"),
  220. WsbHrAsString(hr), iCountItem);
  221. return(hr);
  222. }
  223. #pragma optimize("", on)
  224. void
  225. CFsaScanItem::FinalRelease(
  226. void
  227. )
  228. /*++
  229. Implements:
  230. CComObjectRoot::FinalRelease().
  231. --*/
  232. {
  233. WsbTraceIn(OLESTR("CFsaScanItem::FinalRelease"), OLESTR(""));
  234. // Subtract class from object table
  235. WSB_OBJECT_SUB(CLSID_CFsaScanItemNTFS, this);
  236. // Terminate the scan and free the path memory.
  237. if (INVALID_HANDLE_VALUE != m_handle) {
  238. FindClose(m_handle);
  239. m_handle = INVALID_HANDLE_VALUE;
  240. }
  241. if (0 != m_handleRPI) {
  242. CloseHandle(m_handleRPI);
  243. m_handleRPI = 0;
  244. }
  245. if (m_pUnmanageDb != NULL) {
  246. // Db must be open
  247. (void)m_pUnmanageDb->Close(m_pDbSession);
  248. m_pDbSession = 0;
  249. m_pUnmanageRec = 0;
  250. }
  251. if (TRUE == m_changedAttributes) {
  252. //
  253. // We changed it from read only to read/write - put it back.
  254. //
  255. RestoreAttributes();
  256. }
  257. //
  258. // Detach the data mover stream
  259. if (m_pDataMover != 0) {
  260. WsbAffirmHr( m_pDataMover->CloseStream() );
  261. }
  262. // Let the parent class do his thing.
  263. CComObjectRoot::FinalRelease();
  264. iCountItem--;
  265. WsbTraceOut(OLESTR("CFsaScanItem::FinalRelease"), OLESTR("Count is <%d>"), iCountItem);
  266. }
  267. HRESULT
  268. CFsaScanItem::FindFirst(
  269. IN IFsaResource* pResource,
  270. IN OLECHAR* path,
  271. IN IHsmSession* pSession
  272. )
  273. /*++
  274. Implements:
  275. IFsaScanItem::FindFirst().
  276. --*/
  277. {
  278. HRESULT hr = S_OK;
  279. CWsbStringPtr findPath;
  280. CWsbStringPtr searchName;
  281. OLECHAR* slashPtr;
  282. DWORD lErr;
  283. WsbTraceIn(OLESTR("CFsaScanItem::FindFirst"), OLESTR("path = <%ls>"),
  284. path);
  285. try {
  286. WsbAssert(0 != pResource, E_POINTER);
  287. WsbAssert(0 != path, E_POINTER);
  288. // Store off some of the scan information.
  289. m_pResource = pResource;
  290. m_pSession = pSession;
  291. // Break up the incoming path into a path and a name.
  292. m_path = path;
  293. slashPtr = wcsrchr(m_path, L'\\');
  294. // We could try to support relative path stuff (i.e. current
  295. // directory, but I am not going to do it for now.
  296. WsbAffirm(slashPtr != 0, E_FAIL);
  297. searchName = &(slashPtr[1]);
  298. slashPtr[1] = 0;
  299. // Get a path that can be used by the find function.
  300. WsbAffirmHr(GetPathForFind(searchName, &findPath, 0));
  301. // Scan starting at the specified path.
  302. m_handle = FindFirstFileEx(findPath, FindExInfoStandard, &m_findData, FindExSearchNameMatch, 0, FIND_FIRST_EX_CASE_SENSITIVE);
  303. lErr = GetLastError();
  304. // If we found a file, then remember the scan handle and
  305. // return the scan item.
  306. WsbAffirm(INVALID_HANDLE_VALUE != m_handle, WSB_E_NOTFOUND);
  307. m_gotPhysicalSize = FALSE;
  308. m_physicalSize.QuadPart = 0;
  309. m_gotPlaceholder = FALSE;
  310. } WsbCatch(hr);
  311. WsbTraceOut(OLESTR("CFsaScanItem::FindFirst"), OLESTR("hr = <%ls>"),
  312. WsbHrAsString(hr));
  313. return(hr);
  314. }
  315. HRESULT
  316. CFsaScanItem::FindNext(
  317. void
  318. )
  319. /*++
  320. Implements:
  321. IFsaScanItem::FindNext().
  322. --*/
  323. {
  324. HRESULT hr = S_OK;
  325. WsbTraceIn(OLESTR("CFsaScanItem::FindNext"), OLESTR(""));
  326. try {
  327. WsbAssert(INVALID_HANDLE_VALUE != m_handle, E_FAIL);
  328. if (TRUE == m_changedAttributes) {
  329. //
  330. // We changed it from read only to read/write - put it back.
  331. //
  332. RestoreAttributes();
  333. }
  334. // Continue the scan.
  335. WsbAffirm(FindNextFile(m_handle, &m_findData), WSB_E_NOTFOUND);
  336. m_gotPhysicalSize = FALSE;
  337. m_physicalSize.QuadPart = 0;
  338. m_gotPlaceholder = FALSE;
  339. } WsbCatch(hr);
  340. WsbTraceOut(OLESTR("CFsaScanItem::FindNext"), OLESTR("hr = <%ls>"),
  341. WsbHrAsString(hr));
  342. return(hr);
  343. }
  344. HRESULT
  345. CFsaScanItem::GetAccessTime(
  346. OUT FILETIME* pTime
  347. )
  348. /*++
  349. Implements:
  350. IFsaScanItem::GetAccessTime().
  351. --*/
  352. {
  353. HRESULT hr = S_OK;
  354. try {
  355. WsbAssert(0 != pTime, E_POINTER);
  356. *pTime = m_findData.ftLastAccessTime;
  357. } WsbCatch(hr);
  358. return(hr);
  359. }
  360. HRESULT
  361. CFsaScanItem::GetGroup(
  362. OUT OLECHAR** /*pGroup*/,
  363. IN ULONG /*bufferSize*/
  364. )
  365. /*++
  366. Implements:
  367. IFsaScanItem::GetGroup().
  368. --*/
  369. {
  370. HRESULT hr = S_OK;
  371. try {
  372. hr = E_NOTIMPL;
  373. } WsbCatch(hr);
  374. return(hr);
  375. }
  376. HRESULT
  377. CFsaScanItem::GetLogicalSize(
  378. OUT LONGLONG* pSize
  379. )
  380. /*++
  381. Implements:
  382. IFsaScanItem::GetLogicalSize().
  383. --*/
  384. {
  385. HRESULT hr = S_OK;
  386. LARGE_INTEGER logSize;
  387. try {
  388. WsbAssert(0 != pSize, E_POINTER);
  389. logSize.LowPart = m_findData.nFileSizeLow;
  390. logSize.HighPart = m_findData.nFileSizeHigh;
  391. *pSize = logSize.QuadPart;
  392. } WsbCatch(hr);
  393. return(hr);
  394. }
  395. HRESULT
  396. CFsaScanItem::GetModifyTime(
  397. OUT FILETIME* pTime
  398. )
  399. /*++
  400. Implements:
  401. IFsaScanItem::GetModifyTime().
  402. --*/
  403. {
  404. HRESULT hr = S_OK;
  405. try {
  406. WsbAssert(0 != pTime, E_POINTER);
  407. *pTime = m_findData.ftLastWriteTime;
  408. } WsbCatch(hr);
  409. return(hr);
  410. }
  411. HRESULT
  412. CFsaScanItem::GetName(
  413. OUT OLECHAR** pName,
  414. IN ULONG bufferSize
  415. )
  416. /*++
  417. Implements:
  418. IFsaScanItem::GetName().
  419. --*/
  420. {
  421. HRESULT hr = S_OK;
  422. CWsbStringPtr tmpString = m_findData.cFileName;
  423. try {
  424. WsbAssert(0 != pName, E_POINTER);
  425. WsbAffirmHr(tmpString.CopyTo(pName, bufferSize));
  426. } WsbCatch(hr);
  427. return(hr);
  428. }
  429. HRESULT
  430. CFsaScanItem::GetOwner(
  431. OUT OLECHAR** /*pOwner*/,
  432. IN ULONG /*bufferSize*/
  433. )
  434. /*++
  435. Implements:
  436. IFsaScanItem::GetOwner().
  437. --*/
  438. {
  439. HRESULT hr = S_OK;
  440. try {
  441. hr = E_NOTIMPL;
  442. } WsbCatch(hr);
  443. return(hr);
  444. }
  445. HRESULT
  446. CFsaScanItem::GetPath(
  447. OUT OLECHAR** pPath,
  448. IN ULONG bufferSize
  449. )
  450. /*++
  451. Implements:
  452. IFsaScanItem::GetPath().
  453. --*/
  454. {
  455. HRESULT hr = S_OK;
  456. try {
  457. WsbAssert(0 != pPath, E_POINTER);
  458. WsbAffirmHr(m_path.CopyTo(pPath, bufferSize));
  459. } WsbCatch(hr);
  460. return(hr);
  461. }
  462. HRESULT
  463. CFsaScanItem::GetPathForFind(
  464. IN OLECHAR* searchName,
  465. OUT OLECHAR** pPath,
  466. IN ULONG bufferSize
  467. )
  468. /*++
  469. Implements:
  470. IFsaScanItem::GetPathForFind().
  471. --*/
  472. {
  473. HRESULT hr = S_OK;
  474. CWsbStringPtr tmpString;
  475. try {
  476. WsbAssert(0 != pPath, E_POINTER);
  477. // Get a buffer.
  478. WsbAffirmHr(tmpString.TakeFrom(*pPath, bufferSize));
  479. try {
  480. // Get the path to the resource of the resource.
  481. //
  482. WsbAffirmHr(m_pResource->GetPath(&tmpString, 0));
  483. WsbAffirmHr(tmpString.Prepend(OLESTR("\\\\?\\")));
  484. //WsbAffirmHr(tmpString.Append(OLESTR("\\")));
  485. // Copy in the path.
  486. //WsbAffirmHr(tmpString.Prepend(OLESTR("\\\\?\\")));
  487. WsbAffirmHr(tmpString.Append(&(m_path[1])));
  488. WsbAffirmHr(tmpString.Append(searchName));
  489. } WsbCatch(hr);
  490. WsbAffirmHr(tmpString.GiveTo(pPath));
  491. } WsbCatch(hr);
  492. return(hr);
  493. }
  494. HRESULT
  495. CFsaScanItem::GetPathAndName(
  496. IN OLECHAR* appendix,
  497. OUT OLECHAR** pPath,
  498. IN ULONG bufferSize
  499. )
  500. /*++
  501. Implements:
  502. IFsaScanItem::GetPathAndName().
  503. --*/
  504. {
  505. HRESULT hr = S_OK;
  506. CWsbStringPtr tmpString;
  507. try {
  508. WsbAssert(0 != pPath, E_POINTER);
  509. // Get a buffer.
  510. WsbAffirmHr(tmpString.TakeFrom(*pPath, bufferSize));
  511. try {
  512. tmpString = m_path;
  513. tmpString.Append(m_findData.cFileName);
  514. if (0 != appendix) {
  515. tmpString.Append(appendix);
  516. }
  517. } WsbCatch(hr);
  518. // Give responsibility for freeing the memory back to the caller.
  519. WsbAffirmHr(tmpString.GiveTo(pPath));
  520. } WsbCatch(hr);
  521. return(hr);
  522. }
  523. HRESULT
  524. CFsaScanItem::GetFullPathAndName(
  525. IN OLECHAR* prependix,
  526. IN OLECHAR* appendix,
  527. OUT OLECHAR** pPath,
  528. IN ULONG bufferSize
  529. )
  530. /*++
  531. Implements:
  532. IFsaScanItem::GetFullPathAndName().
  533. --*/
  534. {
  535. HRESULT hr = S_OK;
  536. CWsbStringPtr tmpString;
  537. CWsbStringPtr tmpString2;
  538. try {
  539. WsbAssert(0 != pPath, E_POINTER);
  540. // Get a buffer.
  541. WsbAffirmHr(tmpString.TakeFrom(*pPath, bufferSize));
  542. try {
  543. if (0 != prependix) {
  544. tmpString = prependix;
  545. // Get the path to the resource of the resource.
  546. WsbAffirmHr(m_pResource->GetPath(&tmpString2, 0));
  547. WsbAffirmHr(tmpString.Append(tmpString2));
  548. } else {
  549. WsbAffirmHr(m_pResource->GetPath(&tmpString, 0));
  550. }
  551. // Copy in the path.
  552. WsbAffirmHr(tmpString.Append(&(m_path[1])));
  553. WsbAffirmHr(tmpString.Append(m_findData.cFileName));
  554. if (0 != appendix) {
  555. WsbAffirmHr(tmpString.Append(appendix));
  556. }
  557. } WsbCatch(hr);
  558. // Give responsibility for freeing the memory back to the caller.
  559. WsbAffirmHr(tmpString.GiveTo(pPath));
  560. } WsbCatch(hr);
  561. return(hr);
  562. }
  563. HRESULT
  564. CFsaScanItem::GetPhysicalSize(
  565. OUT LONGLONG* pSize
  566. )
  567. /*++
  568. Implements:
  569. IFsaScanItem::GetPhysicalSize().
  570. --*/
  571. {
  572. HRESULT hr = S_OK;
  573. CWsbStringPtr path;
  574. try {
  575. WsbAssert(0 != pSize, E_POINTER);
  576. //WsbAssertHr(GetFullPathAndName(NULL, 0, &path, 0));
  577. WsbAssertHr(GetFullPathAndName(OLESTR("\\\\?\\"), 0, &path, 0));
  578. // Only read this value in once, but wait until it is asked for
  579. // before reading it in (since this call takes time and many scans
  580. // won't need the information.
  581. if (!m_gotPhysicalSize) {
  582. m_physicalSize.LowPart = GetCompressedFileSize(path, &m_physicalSize.HighPart);
  583. if (MAXULONG == m_physicalSize.LowPart) {
  584. // Have to check last error since MAXULONG could be a valid
  585. // value for the low part of the size.
  586. DWORD err = GetLastError();
  587. if (err != NO_ERROR) {
  588. WsbTrace(OLESTR("CFsaScanItem::GetPhysicalSize of %ws Last error = %u\n"),
  589. (WCHAR *) path, err);
  590. }
  591. WsbAffirm(NO_ERROR == err, E_FAIL);
  592. }
  593. m_gotPhysicalSize = TRUE;
  594. }
  595. *pSize = m_physicalSize.QuadPart;
  596. } WsbCatch(hr);
  597. return(hr);
  598. }
  599. HRESULT
  600. CFsaScanItem::GetPremigratedUsn(
  601. OUT LONGLONG* pFileUsn
  602. )
  603. /*++
  604. Implements:
  605. Routine Description:
  606. Get the USN Journal number for this file from the premigrated list.
  607. Arguments:
  608. pFileUsn - Pointer to File USN to be returned.
  609. Return Value:
  610. S_OK - success
  611. --*/
  612. {
  613. HRESULT hr = S_OK;
  614. try {
  615. CComPtr<IWsbDbSession> pDbSession;
  616. CComPtr<IFsaPremigratedDb> pPremDb;
  617. CComPtr<IFsaResourcePriv> pResourcePriv;
  618. WsbAssert(pFileUsn, E_POINTER);
  619. // Get the premigrated list DB
  620. WsbAffirmHr(m_pResource->QueryInterface(IID_IFsaResourcePriv,
  621. (void**) &pResourcePriv));
  622. WsbAffirmHr(pResourcePriv->GetPremigrated(IID_IFsaPremigratedDb,
  623. (void**) &pPremDb));
  624. // Open the premigration list
  625. WsbAffirmHr(pPremDb->Open(&pDbSession));
  626. try {
  627. FSA_PLACEHOLDER PlaceHolder;
  628. CComPtr<IFsaPremigratedRec> pPremRec;
  629. LONGLONG usn;
  630. // Get a DB entity for the search
  631. WsbAffirmHr(pPremDb->GetEntity(pDbSession, PREMIGRATED_REC_TYPE,
  632. IID_IFsaPremigratedRec, (void**) &pPremRec));
  633. WsbAffirmHr(pPremRec->UseKey(PREMIGRATED_BAGID_OFFSETS_KEY_TYPE));
  634. // Find the record
  635. WsbAffirmHr(GetPlaceholder(0, 0, &PlaceHolder));
  636. WsbAffirmHr(pPremRec->SetBagId(PlaceHolder.bagId));
  637. WsbAffirmHr(pPremRec->SetBagOffset(PlaceHolder.fileStart));
  638. WsbAffirmHr(pPremRec->SetOffset(PlaceHolder.dataStreamStart));
  639. WsbAffirmHr(pPremRec->FindEQ());
  640. // Get the stored USN
  641. WsbAffirmHr(pPremRec->GetFileUSN(&usn));
  642. *pFileUsn = usn;
  643. } WsbCatch(hr);
  644. // Close the DB
  645. pPremDb->Close(pDbSession);
  646. } WsbCatch(hr);
  647. return(hr);
  648. }
  649. HRESULT
  650. CFsaScanItem::GetSession(
  651. OUT IHsmSession** ppSession
  652. )
  653. /*++
  654. Implements:
  655. IFsaScanItem::GetSession().
  656. --*/
  657. {
  658. HRESULT hr = S_OK;
  659. try {
  660. WsbAssert(0 != ppSession, E_POINTER);
  661. *ppSession = m_pSession;
  662. m_pSession->AddRef();
  663. } WsbCatch(hr);
  664. return(hr);
  665. }
  666. HRESULT
  667. CFsaScanItem::GetUncPathAndName(
  668. IN OLECHAR* prependix,
  669. IN OLECHAR* appendix,
  670. OUT OLECHAR** pPath,
  671. IN ULONG bufferSize
  672. )
  673. /*++
  674. Implements:
  675. IFsaScanItem::GetUncPathAndName().
  676. --*/
  677. {
  678. HRESULT hr = S_OK;
  679. CWsbStringPtr tmpString;
  680. CWsbStringPtr tmpString2;
  681. try {
  682. WsbAssert(0 != pPath, E_POINTER);
  683. // Get a buffer.
  684. WsbAffirmHr(tmpString.TakeFrom(*pPath, bufferSize));
  685. try {
  686. if (0 != prependix) {
  687. tmpString = prependix;
  688. // Get the path to the resource of the resource.
  689. WsbAffirmHr(m_pResource->GetUncPath(&tmpString2, 0));
  690. WsbAffirmHr(tmpString.Append(tmpString2));
  691. } else {
  692. WsbAffirmHr(m_pResource->GetPath(&tmpString, 0));
  693. }
  694. // Copy in the path.
  695. WsbAffirmHr(tmpString.Append(&(m_path[1])));
  696. WsbAffirmHr(tmpString.Append(m_findData.cFileName));
  697. if (0 != appendix) {
  698. WsbAffirmHr(tmpString.Append(appendix));
  699. }
  700. } WsbCatch(hr);
  701. // Give responsibility for freeing the memory back to the caller.
  702. WsbAffirmHr(tmpString.GiveTo(pPath));
  703. } WsbCatch(hr);
  704. return(hr);
  705. }
  706. HRESULT
  707. CFsaScanItem::IsAParent(
  708. void
  709. )
  710. /*++
  711. Implements:
  712. IFsaScanItem::IsAParent().
  713. --*/
  714. {
  715. HRESULT hr = S_FALSE;
  716. if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
  717. hr = S_OK;
  718. }
  719. return(hr);
  720. }
  721. HRESULT
  722. CFsaScanItem::IsARelativeParent(
  723. void
  724. )
  725. /*++
  726. Implements:
  727. IFsaScanItem::IsARelativeParent().
  728. --*/
  729. {
  730. HRESULT hr = S_FALSE;
  731. if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
  732. // looking for "."
  733. if (m_findData.cFileName[0] == L'.') {
  734. if (m_findData.cFileName[1] == 0) {
  735. hr = S_OK;
  736. }
  737. // looking for "."
  738. else if (m_findData.cFileName[1] == L'.') {
  739. if (m_findData.cFileName[2] == 0) {
  740. hr = S_OK;
  741. }
  742. }
  743. }
  744. }
  745. return(hr);
  746. }
  747. HRESULT
  748. CFsaScanItem::IsCompressed(
  749. void
  750. )
  751. /*++
  752. Implements:
  753. IFsaScanItem::IsCompressed().
  754. --*/
  755. {
  756. HRESULT hr = S_FALSE;
  757. if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) != 0) {
  758. hr = S_OK;
  759. }
  760. return(hr);
  761. }
  762. HRESULT
  763. CFsaScanItem::IsEncrypted(
  764. void
  765. )
  766. /*++
  767. Implements:
  768. IFsaScanItem::IsEncrypted().
  769. --*/
  770. {
  771. HRESULT hr = S_FALSE;
  772. if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) != 0) {
  773. hr = S_OK;
  774. }
  775. return(hr);
  776. }
  777. HRESULT
  778. CFsaScanItem::IsDeleteOK(
  779. IN IFsaPostIt *pPostIt
  780. )
  781. /*++
  782. Implements:
  783. IFsaScanItem::IsDeleteOK().
  784. --*/
  785. {
  786. HRESULT hr = S_OK;
  787. WsbTraceIn(OLESTR("CFsaScanItem::IsDeleteOK"), OLESTR(""));
  788. try {
  789. //
  790. // Get the version ID from the FSA Post it. This is the
  791. // version of the file at the time of the migrate request
  792. //
  793. LONGLONG workVersionId;
  794. WsbAffirmHr(pPostIt->GetFileVersionId(&workVersionId));
  795. //
  796. // Get the version of the file at the time of this scan
  797. //
  798. LONGLONG scanVersionId;
  799. WsbAffirmHr(GetVersionId(&scanVersionId));
  800. //
  801. // See if the versions match
  802. //
  803. WsbTrace(OLESTR("CFsaScanItem::IsDeleteOK: workVersionId:<%I64u> scanVersionId:<%I64u>\n"),
  804. workVersionId, scanVersionId);
  805. if (workVersionId != scanVersionId) {
  806. WsbTrace(OLESTR("CFsaScanItem::IsDeleteOK: File version has changed!\n"));
  807. WsbThrow(FSA_E_FILE_CHANGED);
  808. }
  809. } WsbCatch(hr);
  810. WsbTraceOut(OLESTR("CFsaScanItem::IsDeleteOk"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  811. return(hr);
  812. }
  813. HRESULT
  814. CFsaScanItem::IsGroupMemberOf(
  815. OLECHAR* /*group*/
  816. )
  817. /*++
  818. Implements:
  819. IFsaScanItem::IsGroupMemberOf().
  820. --*/
  821. {
  822. HRESULT hr = S_FALSE;
  823. hr = E_NOTIMPL;
  824. return(hr);
  825. }
  826. HRESULT
  827. CFsaScanItem::IsHidden(
  828. void
  829. )
  830. /*++
  831. Implements:
  832. IFsaScanItem::IsHidden().
  833. --*/
  834. {
  835. HRESULT hr = S_FALSE;
  836. if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0) {
  837. hr = S_OK;
  838. }
  839. return(hr);
  840. }
  841. HRESULT
  842. CFsaScanItem::IsManageable(
  843. IN LONGLONG offset,
  844. IN LONGLONG size
  845. )
  846. /*++
  847. Implements:
  848. IFsaScanItem::IsManageable().
  849. --*/
  850. {
  851. HRESULT hr = S_FALSE;
  852. HRESULT hr2;
  853. LONGLONG logicalSize;
  854. LONGLONG managableSize;
  855. FILETIME time;
  856. FILETIME managableTime;
  857. BOOL isRelative;
  858. //
  859. // Get some strings for logging and tracing
  860. //
  861. CWsbStringPtr fileName;
  862. CWsbStringPtr jobName;
  863. try {
  864. WsbAffirmHr(GetFullPathAndName( 0, 0, &fileName, 0));
  865. WsbAffirmHr(m_pSession->GetName(&jobName, 0));
  866. } WsbCatch( hr );
  867. WsbTraceIn(OLESTR("CFsaScanItem::IsManageable"), OLESTR("<%ls>"), (OLECHAR *)fileName);
  868. try {
  869. // To be managable the item:
  870. // - can't already be managed (premigratted or truncated)
  871. // - can't be a link
  872. // - can't be encrypted
  873. // - can't be sparse
  874. // - can't have extended attributes (reparse point limitation)
  875. // - must have a size bigger than the resource's default size
  876. // - must have a last access time older than the resource's default time
  877. // Managed?
  878. hr2 = IsManaged(offset, size);
  879. if (S_FALSE == hr2) {
  880. // A link?
  881. hr2 = IsALink();
  882. if (S_FALSE == hr2) {
  883. // Encrypted?
  884. hr2 = IsEncrypted();
  885. if (S_FALSE == hr2) {
  886. // A sparse?
  887. hr2 = IsSparse();
  888. if (S_FALSE == hr2) {
  889. // A sparse?
  890. hr2 = HasExtendedAttributes();
  891. if (S_FALSE == hr2) {
  892. // Big enough?
  893. WsbAffirmHr(GetLogicalSize(&logicalSize));
  894. WsbAffirmHr(m_pResource->GetManageableItemLogicalSize(&managableSize));
  895. if (logicalSize >= managableSize) {
  896. // Old enough?
  897. WsbAffirmHr(GetAccessTime(&time));
  898. WsbAffirmHr(m_pResource->GetManageableItemAccessTime(&isRelative, &managableTime));
  899. if (WsbCompareFileTimes(time, managableTime, isRelative, FALSE) >= 0) {
  900. // It can be managed!!
  901. hr = S_OK;
  902. } else {
  903. WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISACCESSED, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
  904. }
  905. } else {
  906. WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISTOOSMALL, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
  907. WsbTrace( OLESTR("LogicalSize is %I64d; ManagableSize is %I64d\n"), logicalSize, managableSize);
  908. }
  909. } else {
  910. WsbLogEvent(FSA_MESSAGE_FILESKIPPED_HASEA, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
  911. }
  912. } else {
  913. WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISSPARSE, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
  914. }
  915. } else {
  916. WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISENCRYPTED, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
  917. }
  918. } else {
  919. WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISALINK, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
  920. }
  921. } else {
  922. WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISMANAGED, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
  923. }
  924. } WsbCatch(hr);
  925. WsbTraceOut(OLESTR("CFsaScanItem::IsManageable"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  926. return(hr);
  927. }
  928. HRESULT
  929. CFsaScanItem::IsMigrateOK(
  930. IN IFsaPostIt *pPostIt
  931. )
  932. /*++
  933. Implements:
  934. IFsaScanItem::IsMigrateOK().
  935. --*/
  936. {
  937. HRESULT hr = S_OK;
  938. WsbTraceIn(OLESTR("CFsaScanItem::IsMigrateOK"), OLESTR(""));
  939. try {
  940. //
  941. // Make sure the file isn't already managed. This could happen if two jobs were scanning
  942. // the same volume.
  943. //
  944. LONGLONG offset;
  945. LONGLONG size;
  946. WsbAffirmHr(pPostIt->GetRequestOffset(&offset));
  947. WsbAffirmHr(pPostIt->GetRequestSize(&size));
  948. if (IsManaged(offset, size) == S_OK) {
  949. //
  950. // The file is already managed so skip it
  951. //
  952. WsbTrace(OLESTR("A manage request for an already managed file - skip it!\n"));
  953. WsbThrow(FSA_E_FILE_ALREADY_MANAGED);
  954. }
  955. //
  956. // Get the version ID from the FSA Post it. This is the
  957. // version of the file at the time of the migrate request
  958. //
  959. LONGLONG workVersionId;
  960. WsbAffirmHr(pPostIt->GetFileVersionId(&workVersionId));
  961. //
  962. // Get the version of the file at the time of this scan
  963. //
  964. LONGLONG scanVersionId;
  965. WsbAffirmHr(GetVersionId(&scanVersionId));
  966. //
  967. // See if the versions match
  968. //
  969. WsbTrace(OLESTR("CFsaScanItem::IsMigrateOK: workVersionId:<%I64u> scanVersionId:<%I64u>\n"),
  970. workVersionId, scanVersionId);
  971. if (workVersionId != scanVersionId) {
  972. WsbTrace(OLESTR("CFsaScanItem::IsMigrateOK: File version has changed!\n"));
  973. WsbThrow(FSA_E_FILE_CHANGED);
  974. }
  975. } WsbCatch(hr);
  976. WsbTraceOut(OLESTR("CFsaScanItem::IsMigrateOK"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  977. return(hr);
  978. }
  979. HRESULT
  980. CFsaScanItem::IsMbit(
  981. void
  982. )
  983. /*++
  984. Implements:
  985. IFsaScanItem::IsMbit().
  986. --*/
  987. {
  988. HRESULT hr = S_FALSE;
  989. if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) != 0) {
  990. hr = S_OK;
  991. }
  992. return(hr);
  993. }
  994. HRESULT
  995. CFsaScanItem::IsOffline(
  996. void
  997. )
  998. /*++
  999. Implements:
  1000. IFsaScanItem::IsOffline().
  1001. --*/
  1002. {
  1003. HRESULT hr = S_FALSE;
  1004. if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) != 0) {
  1005. hr = S_OK;
  1006. }
  1007. return(hr);
  1008. }
  1009. HRESULT
  1010. CFsaScanItem::IsOwnerMemberOf(
  1011. OLECHAR* /*group*/
  1012. )
  1013. /*++
  1014. Implements:
  1015. IFsaScanItem::IsOwnerMemberOf().
  1016. --*/
  1017. {
  1018. HRESULT hr = S_FALSE;
  1019. hr = E_NOTIMPL;
  1020. return(hr);
  1021. }
  1022. HRESULT
  1023. CFsaScanItem::IsReadOnly(
  1024. void
  1025. )
  1026. /*++
  1027. Implements:
  1028. IFsaScanItem::IsReadOnly().
  1029. --*/
  1030. {
  1031. HRESULT hr = S_FALSE;
  1032. if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0) {
  1033. hr = S_OK;
  1034. }
  1035. return(hr);
  1036. }
  1037. HRESULT
  1038. CFsaScanItem::IsRecallOK(
  1039. IN IFsaPostIt *pPostIt
  1040. )
  1041. /*++
  1042. Implements:
  1043. IFsaScanItem::IsRecallOK().
  1044. --*/
  1045. {
  1046. HRESULT hr = S_OK;
  1047. WsbTraceIn(OLESTR("CFsaScanItem::IsRecallOK"), OLESTR(""));
  1048. try {
  1049. LONGLONG offset;
  1050. LONGLONG size;
  1051. //
  1052. // Make sure the file is still truncated
  1053. //
  1054. WsbAffirmHr(pPostIt->GetRequestOffset(&offset));
  1055. WsbAffirmHr(pPostIt->GetRequestSize(&size));
  1056. hr = IsTruncated(offset, size);
  1057. if (S_OK != hr) {
  1058. //
  1059. // The file is not truncated, so skip it
  1060. //
  1061. WsbTrace(OLESTR("CFsaScanItem::IsRecallOK - file isn't truncated.\n"));
  1062. WsbThrow(FSA_E_FILE_NOT_TRUNCATED);
  1063. }
  1064. // Get the version ID from the FSA Post it. This is the
  1065. // version of the file at the time of the migrate request
  1066. //
  1067. LONGLONG workVersionId;
  1068. WsbAffirmHr(pPostIt->GetFileVersionId(&workVersionId));
  1069. //
  1070. // Get the version of the file
  1071. //
  1072. LONGLONG scanVersionId;
  1073. WsbAffirmHr(GetVersionId(&scanVersionId));
  1074. //
  1075. // See if the versions match
  1076. //
  1077. WsbTrace(OLESTR("CFsaScanItem::IsRecallOK: workVersionId:<%I64u> scanVersionId:<%I64u>\n"),
  1078. workVersionId, scanVersionId);
  1079. if (workVersionId != scanVersionId) {
  1080. WsbTrace(OLESTR("CFsaScanItem::IsRecallOK: File version has changed!\n"));
  1081. //
  1082. // If the use has changed alternate data streams
  1083. // the file version ID may have changed but it is
  1084. // OK to recall the file. So if the version ID's
  1085. // don't match, then check to see if the truncated
  1086. // part of the file is OK. If so, allow the recall
  1087. // to happen.
  1088. //
  1089. //
  1090. // Check to see if the whole file is still sparse
  1091. //
  1092. if (IsTotallySparse() == S_OK) {
  1093. //
  1094. // The file is OK so far to recall but we need
  1095. // to make the last modify dates match
  1096. //
  1097. FSA_PLACEHOLDER placeholder;
  1098. WsbAffirmHr(pPostIt->GetPlaceholder(&placeholder));;
  1099. placeholder.fileVersionId = scanVersionId;
  1100. WsbAffirmHr(pPostIt->SetPlaceholder(&placeholder));
  1101. } else {
  1102. //
  1103. // The file has been changed, recalling data will
  1104. // overwrite something that has been added since the
  1105. // truncation occurred. So don't do anything.
  1106. //
  1107. WsbTrace(OLESTR("File is no longer sparse.!\n"));
  1108. WsbThrow(FSA_E_FILE_CHANGED);
  1109. }
  1110. }
  1111. } WsbCatch(hr);
  1112. WsbTraceOut(OLESTR("CFsaScanItem::IsRecallOK"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1113. return(hr);
  1114. }
  1115. HRESULT
  1116. CFsaScanItem::IsSparse(
  1117. void
  1118. )
  1119. /*++
  1120. Implements:
  1121. IFsaScanItem::IsSparse().
  1122. --*/
  1123. {
  1124. HRESULT hr = S_FALSE;
  1125. LONGLONG size;
  1126. WsbTraceIn(OLESTR("CFsaScanItem::IsSparse"), OLESTR(""));
  1127. if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) != 0) {
  1128. hr = GetLogicalSize( &size ) ;
  1129. if ( S_OK == hr ) {
  1130. hr = CheckIfSparse(0, size );
  1131. if ( (FSA_E_FILE_IS_TOTALLY_SPARSE == hr) ||
  1132. (FSA_E_FILE_IS_PARTIALLY_SPARSE == hr) ) {
  1133. hr = S_OK;
  1134. } else {
  1135. hr = S_FALSE;
  1136. }
  1137. }
  1138. }
  1139. WsbTraceOut(OLESTR("CFsaScanItem::IsSparse"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1140. return(hr);
  1141. }
  1142. HRESULT
  1143. CFsaScanItem::IsTotallySparse(
  1144. void
  1145. )
  1146. /*++
  1147. Implements:
  1148. IFsaScanItem::IsTotallySparse().
  1149. --*/
  1150. {
  1151. HRESULT hr = S_FALSE;
  1152. LONGLONG size;
  1153. WsbTraceIn(OLESTR("CFsaScanItem::IsTotallySparse"), OLESTR(""));
  1154. if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) != 0) {
  1155. hr = GetLogicalSize( &size ) ;
  1156. if ( S_OK == hr ) {
  1157. hr = CheckIfSparse(0, size );
  1158. if (FSA_E_FILE_IS_TOTALLY_SPARSE == hr) {
  1159. hr = S_OK;
  1160. } else {
  1161. hr = S_FALSE;
  1162. }
  1163. }
  1164. }
  1165. WsbTraceOut(OLESTR("CFsaScanItem::IsTotallySparse"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1166. return(hr);
  1167. }
  1168. HRESULT
  1169. CFsaScanItem::Manage(
  1170. IN LONGLONG offset,
  1171. IN LONGLONG size,
  1172. IN GUID storagePoolId,
  1173. IN BOOL truncate
  1174. )
  1175. /*++
  1176. Implements:
  1177. IFsaScanItem::Manage().
  1178. --*/
  1179. {
  1180. HRESULT hr = S_OK;
  1181. WsbTraceIn(OLESTR("CFsaScanItem::Manage"), OLESTR(""));
  1182. try {
  1183. WsbAssert(GUID_NULL != storagePoolId, E_INVALIDARG);
  1184. WsbAffirmHr(m_pResource->Manage((IFsaScanItem*) this, offset, size, storagePoolId, truncate));
  1185. } WsbCatch(hr);
  1186. WsbTraceOut(OLESTR("CFsaScanItem::Manage"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1187. return(hr);
  1188. }
  1189. HRESULT
  1190. CFsaScanItem::Move(
  1191. OLECHAR* dest,
  1192. BOOL /*retainHierarcy*/,
  1193. BOOL /*expandPlaceholders*/,
  1194. BOOL overwriteExisting
  1195. )
  1196. /*++
  1197. Implements:
  1198. IFsaScanItem::Move().
  1199. --*/
  1200. {
  1201. HRESULT hr = S_OK;
  1202. DWORD mode = MOVEFILE_COPY_ALLOWED;
  1203. try {
  1204. // NOTE : This default behavior causes placeholders
  1205. // to be expanded when moving to another volume and probably doesn't
  1206. // retain the heirarchy.
  1207. WsbAssert(0 != dest, E_POINTER);
  1208. if (overwriteExisting) {
  1209. mode |= MOVEFILE_REPLACE_EXISTING;
  1210. }
  1211. WsbAssert(MoveFileEx(m_findData.cFileName, dest, mode), E_FAIL);
  1212. } WsbCatch(hr);
  1213. return(hr);
  1214. }
  1215. HRESULT
  1216. CFsaScanItem::Recall(
  1217. IN LONGLONG offset,
  1218. IN LONGLONG size,
  1219. IN BOOL deletePlaceholder
  1220. )
  1221. /*++
  1222. Implements:
  1223. IFsaScanItem::Recall().
  1224. --*/
  1225. {
  1226. HRESULT hr = S_OK;
  1227. WsbTraceIn(OLESTR("CFsaScanItem::Recall"), OLESTR(""));
  1228. try {
  1229. WsbAffirmHr(m_pResource->Recall((IFsaScanItem*) this, offset, size, deletePlaceholder));
  1230. } WsbCatch(hr);
  1231. WsbTraceOut(OLESTR("CFsaScanItem::Recall"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1232. return(hr);
  1233. }
  1234. HRESULT
  1235. CFsaScanItem::Recycle(
  1236. void
  1237. )
  1238. /*++
  1239. Implements:
  1240. IFsaScanItem::Recycle().
  1241. --*/
  1242. {
  1243. HRESULT hr = S_OK;
  1244. try {
  1245. // Probably need to look at SHFileOperation().
  1246. hr = E_NOTIMPL;
  1247. } WsbCatch(hr);
  1248. return(hr);
  1249. }
  1250. HRESULT
  1251. CFsaScanItem::IsSystem(
  1252. void
  1253. )
  1254. /*++
  1255. Implements:
  1256. IFsaScanItem::IsSystem().
  1257. --*/
  1258. {
  1259. HRESULT hr = S_FALSE;
  1260. if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) != 0) {
  1261. hr = S_OK;
  1262. }
  1263. return(hr);
  1264. }
  1265. HRESULT
  1266. CFsaScanItem::Test(
  1267. USHORT* passed,
  1268. USHORT* failed
  1269. )
  1270. /*++
  1271. Implements:
  1272. IWsbTestable::Test().
  1273. --*/
  1274. {
  1275. HRESULT hr = S_OK;
  1276. try {
  1277. WsbAssert(0 != passed, E_POINTER);
  1278. WsbAssert(0 != failed, E_POINTER);
  1279. *passed = 0;
  1280. *failed = 0;
  1281. } WsbCatch(hr);
  1282. return(hr);
  1283. }
  1284. HRESULT
  1285. CFsaScanItem::Unmanage(
  1286. IN LONGLONG offset,
  1287. IN LONGLONG size
  1288. )
  1289. /*++
  1290. Implements:
  1291. IFsaScanItem::Unmanage().
  1292. --*/
  1293. {
  1294. HRESULT hr = S_OK;
  1295. WsbTraceIn(OLESTR("CFsaScanItem::Unmanage"), OLESTR("<%ls>"),
  1296. WsbAbbreviatePath(m_path, 120));
  1297. try {
  1298. // We only need to worry about files that have placeholder information.
  1299. if (IsManaged(offset, size) == S_OK) {
  1300. // If the file is truncated, then we need to recall the data
  1301. // before deleting the placeholder information.
  1302. // NOTE: We set a flag on the Recall so the placeholder will
  1303. // be deleted after the file is recalled.
  1304. if (IsTruncated(offset, size) == S_OK) {
  1305. WsbAffirmHr(Recall(offset, size, TRUE));
  1306. } else {
  1307. // For disaster recovery, it would be better to delete the placeholder
  1308. // and THEN remove this file from the premigration list. Unfortunately,
  1309. // after deleting the placeholder, the RemovePremigrated call fails
  1310. // because it needs to get some information from the placeholder (which
  1311. // is gone). So we do it in this order.
  1312. hr = m_pResource->RemovePremigrated((IFsaScanItem*) this, offset, size);
  1313. if (WSB_E_NOTFOUND == hr) {
  1314. // It's no tragedy if this file wasn't in the list since we were
  1315. // going to delete it anyway (although it shouldn't happen) so
  1316. // let's continue anyway
  1317. hr = S_OK;
  1318. }
  1319. WsbAffirmHr(hr);
  1320. WsbAffirmHr(DeletePlaceholder(offset, size));
  1321. }
  1322. }
  1323. } WsbCatch(hr);
  1324. WsbTraceOut(OLESTR("CFsaScanItem::Unmanage"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1325. return(hr);
  1326. }
  1327. HRESULT
  1328. CFsaScanItem::Validate(
  1329. IN LONGLONG offset,
  1330. IN LONGLONG size
  1331. )
  1332. /*++
  1333. Implements:
  1334. IFsaScanItem::Validate().
  1335. --*/
  1336. {
  1337. HRESULT hr = S_OK;
  1338. BOOL fileIsTruncated = FALSE;
  1339. LONGLONG usn = 0;
  1340. WsbTraceIn(OLESTR("CFsaScanItem::Validate"), OLESTR("offset = <%I64u>, size = <%I64u>"),
  1341. offset, size);
  1342. try {
  1343. //
  1344. // Do some local validation before calling the engine.
  1345. //
  1346. // We only need to worry about files that have placeholder information.
  1347. if (IsManaged(offset, size) == S_OK) {
  1348. //
  1349. // If the file is marked as truncated, make sure it is still truncated.
  1350. //
  1351. if (IsTruncated(offset, size) == S_OK) {
  1352. //
  1353. // Check to see if the file is totally sparse to see if it is truncated.
  1354. //
  1355. if (IsTotallySparse() != S_OK) {
  1356. //
  1357. // The file is marked as truncated but is not truncated
  1358. // Make it truncated.
  1359. //
  1360. WsbAffirmHr(Truncate(offset,size));
  1361. WsbLogEvent(FSA_MESSAGE_VALIDATE_TRUNCATED_FILE, 0, NULL, WsbAbbreviatePath(m_path, 120), WsbHrAsString(hr), NULL);
  1362. }
  1363. fileIsTruncated = TRUE;
  1364. }
  1365. }
  1366. //
  1367. // The last modify date may be updated on a file if the named data streams
  1368. // have been modified. So check to see if the dates match. If they don't,
  1369. // if the file is trunctated, see if it is still truncated, if so, update the
  1370. // modify date in the placeholder to the file's modify date. If the file is
  1371. // premigrated and the modify dates don't match, delete the placeholder.
  1372. // Get the version ID from the file
  1373. LONGLONG scanVersionId;
  1374. WsbAffirmHr(GetVersionId(&scanVersionId));
  1375. // Get the version ID from the placeholder
  1376. FSA_PLACEHOLDER scanPlaceholder;
  1377. WsbAffirmHr(GetPlaceholder(offset, size, &scanPlaceholder));
  1378. if (TRUE == fileIsTruncated) {
  1379. // Check to see if the dates match
  1380. if (scanPlaceholder.fileVersionId != scanVersionId) {
  1381. WsbTrace(OLESTR("CFsaScanItem::Validate - placeholer version ID = <%I64u>, file version Id = <%I64u>"),
  1382. scanPlaceholder.fileVersionId, scanVersionId);
  1383. //
  1384. // Update the placeholder information on the reparse point
  1385. //
  1386. LONGLONG afterPhUsn;
  1387. scanPlaceholder.fileVersionId = scanVersionId;
  1388. WsbAffirmHr(CreatePlaceholder(offset, size, scanPlaceholder, FALSE, 0, &afterPhUsn));
  1389. WsbLogEvent(FSA_MESSAGE_VALIDATE_RESET_PH_MODIFY_TIME, 0, NULL, WsbAbbreviatePath(m_path, 120), WsbHrAsString(hr), NULL);
  1390. }
  1391. } else {
  1392. // The file is pre-migrated. Verify that it has not changed since we managed it and if it has then unmanage it.
  1393. if (Verify(offset, size) != S_OK) {
  1394. WsbAffirmHr(Unmanage(offset, size));
  1395. WsbLogEvent(FSA_MESSAGE_VALIDATE_UNMANAGED_FILE, 0, NULL, WsbAbbreviatePath(m_path, 120), WsbHrAsString(hr), NULL);
  1396. }
  1397. }
  1398. // Now that all of this stuff is OK, call the engine
  1399. if (IsManaged(offset, size) == S_OK) {
  1400. WsbAffirmHr(m_pResource->Validate((IFsaScanItem*) this, offset, size, usn));
  1401. }
  1402. } WsbCatch(hr);
  1403. WsbTraceOut(OLESTR("CFsaScanItem::Validate"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1404. return(hr);
  1405. }
  1406. HRESULT
  1407. CFsaScanItem::FindFirstInDbIndex(
  1408. IN IFsaResource* pResource,
  1409. IN IHsmSession* pSession
  1410. )
  1411. /*++
  1412. Implements:
  1413. IFsaScanItemPriv::FindFirstInDbIndex().
  1414. --*/
  1415. {
  1416. HRESULT hr = S_OK;
  1417. WsbTraceIn(OLESTR("CFsaScanItem::FindFirstInDbIndex"), OLESTR(""));
  1418. try {
  1419. CComPtr<IFsaResourcePriv> pResourcePriv;
  1420. WsbAssert(0 != pResource, E_POINTER);
  1421. // Store off some of the scan information.
  1422. m_pResource = pResource;
  1423. m_pSession = pSession;
  1424. // If Db is already present (could happen if somebody calls First() twice in a row),
  1425. // we close the Db and reopen since we cannot be sure that the resource is the same!
  1426. if (m_pUnmanageDb != NULL) {
  1427. // Db must be open
  1428. (void)m_pUnmanageDb->Close(m_pDbSession);
  1429. m_pDbSession = 0;
  1430. m_pUnmanageRec = 0;
  1431. m_pUnmanageDb = 0;
  1432. }
  1433. // Get and open the Unmanage db
  1434. // (Note: if this scanning is ever extended to use another DB,
  1435. // this method should get additional parameter for which DB to scan)
  1436. WsbAffirmHr(m_pResource->QueryInterface(IID_IFsaResourcePriv,
  1437. (void**) &pResourcePriv));
  1438. hr = pResourcePriv->GetUnmanageDb(IID_IFsaUnmanageDb,
  1439. (void**) &m_pUnmanageDb);
  1440. if (WSB_E_RESOURCE_UNAVAILABLE == hr) {
  1441. // Db was not created ==> no files to scan
  1442. hr = WSB_E_NOTFOUND;
  1443. }
  1444. WsbAffirmHr(hr);
  1445. hr = m_pUnmanageDb->Open(&m_pDbSession);
  1446. if (S_OK != hr) {
  1447. m_pUnmanageDb = NULL;
  1448. WsbAffirmHr(hr);
  1449. }
  1450. // Get a record to traverse with and set for sequential traversing
  1451. WsbAffirmHr(m_pUnmanageDb->GetEntity(m_pDbSession, UNMANAGE_REC_TYPE, IID_IFsaUnmanageRec,
  1452. (void**)&m_pUnmanageRec));
  1453. WsbAffirmHr(m_pUnmanageRec->SetSequentialScan());
  1454. // Get file information
  1455. WsbAffirmHr(GetFromDbIndex(TRUE));
  1456. } WsbCatch(hr);
  1457. WsbTraceOut(OLESTR("CFsaScanItem::FindFirstInDbIndex"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1458. return(hr);
  1459. }
  1460. HRESULT
  1461. CFsaScanItem::FindNextInDbIndex(
  1462. void
  1463. )
  1464. /*++
  1465. Implements:
  1466. IFsaScanItemPriv::FindNextInDbIndex().
  1467. --*/
  1468. {
  1469. HRESULT hr = S_OK;
  1470. WsbTraceIn(OLESTR("CFsaScanItem::FindNextInDbIndex"), OLESTR(""));
  1471. try {
  1472. WsbAssert(m_pUnmanageDb != NULL, E_FAIL);
  1473. // Get file information
  1474. WsbAffirmHr(GetFromDbIndex(FALSE));
  1475. } WsbCatch(hr);
  1476. WsbTraceOut(OLESTR("CFsaScanItem::FindNextInDbIndex"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1477. return(hr);
  1478. }
  1479. HRESULT
  1480. CFsaScanItem::GetFromDbIndex(
  1481. BOOL first
  1482. )
  1483. /*
  1484. Implements:
  1485. CFsaScanItem::GetFromDbIndex().
  1486. --*/
  1487. {
  1488. HRESULT hr = S_OK;
  1489. WsbTraceIn(OLESTR("CFsaScanItem::GetFromDbIndex"), OLESTR(""));
  1490. try {
  1491. IFsaScanItem* pScanItem;
  1492. HRESULT hrFindFileId = S_OK;
  1493. LONGLONG fileId;
  1494. BOOL bCont;
  1495. WsbAssert(m_pUnmanageDb != NULL, E_FAIL);
  1496. WsbAssert(m_pUnmanageRec != NULL, E_FAIL);
  1497. do {
  1498. bCont = FALSE;
  1499. // Get first/next record
  1500. if (first) {
  1501. hr = m_pUnmanageRec->First();
  1502. } else {
  1503. hr = m_pUnmanageRec->Next();
  1504. }
  1505. WsbAffirm(S_OK == hr, WSB_E_NOTFOUND);
  1506. // Get file id
  1507. WsbAffirmHr(m_pUnmanageRec->GetFileId(&fileId));
  1508. // Reset some items in case this isn't the first call to FindFileId
  1509. // (FindFileId actually "attach" the object to a different file)
  1510. if (INVALID_HANDLE_VALUE != m_handle) {
  1511. FindClose(m_handle);
  1512. m_handle = INVALID_HANDLE_VALUE;
  1513. }
  1514. if (TRUE == m_changedAttributes) {
  1515. RestoreAttributes();
  1516. }
  1517. // Find the file from the ID
  1518. pScanItem = this;
  1519. hrFindFileId = m_pResource->FindFileId(fileId, m_pSession, &pScanItem);
  1520. // If the FindFileId failed, we just skip that item and get the
  1521. // next one. This is to keep the scan from just stopping on this
  1522. // item. FindFileId could fail because the file has been deleted
  1523. // or open exclusively by somebody else
  1524. if (!SUCCEEDED(hrFindFileId)) {
  1525. WsbTrace(OLESTR("CFsaScanItem::GetFromDbIndex: file id %I64d skipped since FindFileId failed with hr = <%ls>\n"),
  1526. fileId, WsbHrAsString(hrFindFileId));
  1527. first = FALSE;
  1528. bCont = TRUE;
  1529. }
  1530. } while (bCont);
  1531. WsbAffirmHr(pScanItem->Release()); // Get rid of extra ref. count (we get extra ref count only when FindFileId succeeds)
  1532. } WsbCatch(hr);
  1533. WsbTraceOut(OLESTR("CFsaScanItem::GetFromDbIndex"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1534. return(hr);
  1535. }