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.

2185 lines
51 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.p->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.p->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. LONGLONG maxFileSize;
  856. FILETIME time;
  857. FILETIME managableTime;
  858. BOOL isRelative;
  859. //
  860. // Get some strings for logging and tracing
  861. //
  862. CWsbStringPtr fileName;
  863. CWsbStringPtr jobName;
  864. try {
  865. WsbAffirmHr(GetFullPathAndName( 0, 0, &fileName, 0));
  866. WsbAffirmHr(m_pSession->GetName(&jobName, 0));
  867. } WsbCatch( hr );
  868. WsbTraceIn(OLESTR("CFsaScanItem::IsManageable"), OLESTR("<%ls>"), (OLECHAR *)fileName);
  869. try {
  870. // To be managable the item:
  871. // - can't already be managed (premigratted or truncated)
  872. // - can't be a link
  873. // - can't be encrypted
  874. // - can't be sparse
  875. // - can't have extended attributes (reparse point limitation)
  876. // - must have a size bigger than the resource's default size
  877. // - must have a last access time older than the resource's default time
  878. // Managed?
  879. hr2 = IsManaged(offset, size);
  880. if (S_FALSE == hr2) {
  881. // A link?
  882. hr2 = IsALink();
  883. if (S_FALSE == hr2) {
  884. // Encrypted?
  885. hr2 = IsEncrypted();
  886. if (S_FALSE == hr2) {
  887. // A sparse?
  888. hr2 = IsSparse();
  889. if (S_FALSE == hr2) {
  890. // A sparse?
  891. hr2 = HasExtendedAttributes();
  892. if (S_FALSE == hr2) {
  893. // Big enough?
  894. WsbAffirmHr(GetLogicalSize(&logicalSize));
  895. WsbAffirmHr(m_pResource->GetManageableItemLogicalSize(&managableSize));
  896. if (logicalSize >= managableSize) {
  897. // Old enough?
  898. WsbAffirmHr(GetAccessTime(&time));
  899. WsbAffirmHr(m_pResource->GetManageableItemAccessTime(&isRelative, &managableTime));
  900. if (WsbCompareFileTimes(time, managableTime, isRelative, FALSE) >= 0) {
  901. // Small enough? (This is according to media size limit !)
  902. CComPtr<IFsaResourcePriv> pResourcePriv;
  903. WsbAffirmHr(m_pResource->QueryInterface(IID_IFsaResourcePriv,
  904. (void**) &pResourcePriv));
  905. WsbAffirmHr(pResourcePriv->GetMaxFileLogicalSize(&maxFileSize));
  906. if ((logicalSize <= maxFileSize) || (0 == maxFileSize)) {
  907. // It can be managed!!
  908. hr = S_OK;
  909. } else {
  910. WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISTOOLARGE, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
  911. WsbTrace(OLESTR("CFsaScanItem::IsManageable: file not manageable: Logical size = %I64d; Max file size = %I64d\n"),
  912. logicalSize, maxFileSize);
  913. }
  914. } else {
  915. WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISACCESSED, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
  916. }
  917. } else {
  918. WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISTOOSMALL, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
  919. }
  920. } else {
  921. WsbLogEvent(FSA_MESSAGE_FILESKIPPED_HASEA, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
  922. }
  923. } else {
  924. WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISSPARSE, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
  925. }
  926. } else {
  927. WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISENCRYPTED, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
  928. }
  929. } else {
  930. WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISALINK, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
  931. }
  932. } else {
  933. WsbLogEvent(FSA_MESSAGE_FILESKIPPED_ISMANAGED, 0, NULL, (OLECHAR*) jobName, WsbAbbreviatePath(fileName, 120), WsbHrAsString(hr), NULL);
  934. }
  935. } WsbCatch(hr);
  936. WsbTraceOut(OLESTR("CFsaScanItem::IsManageable"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  937. return(hr);
  938. }
  939. HRESULT
  940. CFsaScanItem::IsMigrateOK(
  941. IN IFsaPostIt *pPostIt
  942. )
  943. /*++
  944. Implements:
  945. IFsaScanItem::IsMigrateOK().
  946. --*/
  947. {
  948. HRESULT hr = S_OK;
  949. WsbTraceIn(OLESTR("CFsaScanItem::IsMigrateOK"), OLESTR(""));
  950. try {
  951. //
  952. // Make sure the file isn't already managed. This could happen if two jobs were scanning
  953. // the same volume.
  954. //
  955. LONGLONG offset;
  956. LONGLONG size;
  957. WsbAffirmHr(pPostIt->GetRequestOffset(&offset));
  958. WsbAffirmHr(pPostIt->GetRequestSize(&size));
  959. if (IsManaged(offset, size) == S_OK) {
  960. //
  961. // The file is already managed so skip it
  962. //
  963. WsbTrace(OLESTR("A manage request for an already managed file - skip it!\n"));
  964. WsbThrow(FSA_E_FILE_ALREADY_MANAGED);
  965. }
  966. //
  967. // Get the version ID from the FSA Post it. This is the
  968. // version of the file at the time of the migrate request
  969. //
  970. LONGLONG workVersionId;
  971. WsbAffirmHr(pPostIt->GetFileVersionId(&workVersionId));
  972. //
  973. // Get the version of the file at the time of this scan
  974. //
  975. LONGLONG scanVersionId;
  976. WsbAffirmHr(GetVersionId(&scanVersionId));
  977. //
  978. // See if the versions match
  979. //
  980. WsbTrace(OLESTR("CFsaScanItem::IsMigrateOK: workVersionId:<%I64u> scanVersionId:<%I64u>\n"),
  981. workVersionId, scanVersionId);
  982. if (workVersionId != scanVersionId) {
  983. WsbTrace(OLESTR("CFsaScanItem::IsMigrateOK: File version has changed!\n"));
  984. WsbThrow(FSA_E_FILE_CHANGED);
  985. }
  986. } WsbCatch(hr);
  987. WsbTraceOut(OLESTR("CFsaScanItem::IsMigrateOK"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  988. return(hr);
  989. }
  990. HRESULT
  991. CFsaScanItem::IsMbit(
  992. void
  993. )
  994. /*++
  995. Implements:
  996. IFsaScanItem::IsMbit().
  997. --*/
  998. {
  999. HRESULT hr = S_FALSE;
  1000. if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) != 0) {
  1001. hr = S_OK;
  1002. }
  1003. return(hr);
  1004. }
  1005. HRESULT
  1006. CFsaScanItem::IsOffline(
  1007. void
  1008. )
  1009. /*++
  1010. Implements:
  1011. IFsaScanItem::IsOffline().
  1012. --*/
  1013. {
  1014. HRESULT hr = S_FALSE;
  1015. if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) != 0) {
  1016. hr = S_OK;
  1017. }
  1018. return(hr);
  1019. }
  1020. HRESULT
  1021. CFsaScanItem::IsOwnerMemberOf(
  1022. OLECHAR* /*group*/
  1023. )
  1024. /*++
  1025. Implements:
  1026. IFsaScanItem::IsOwnerMemberOf().
  1027. --*/
  1028. {
  1029. HRESULT hr = S_FALSE;
  1030. hr = E_NOTIMPL;
  1031. return(hr);
  1032. }
  1033. HRESULT
  1034. CFsaScanItem::IsReadOnly(
  1035. void
  1036. )
  1037. /*++
  1038. Implements:
  1039. IFsaScanItem::IsReadOnly().
  1040. --*/
  1041. {
  1042. HRESULT hr = S_FALSE;
  1043. if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) != 0) {
  1044. hr = S_OK;
  1045. }
  1046. return(hr);
  1047. }
  1048. HRESULT
  1049. CFsaScanItem::IsRecallOK(
  1050. IN IFsaPostIt *pPostIt
  1051. )
  1052. /*++
  1053. Implements:
  1054. IFsaScanItem::IsRecallOK().
  1055. --*/
  1056. {
  1057. HRESULT hr = S_OK;
  1058. WsbTraceIn(OLESTR("CFsaScanItem::IsRecallOK"), OLESTR(""));
  1059. try {
  1060. LONGLONG offset;
  1061. LONGLONG size;
  1062. //
  1063. // Make sure the file is still truncated
  1064. //
  1065. WsbAffirmHr(pPostIt->GetRequestOffset(&offset));
  1066. WsbAffirmHr(pPostIt->GetRequestSize(&size));
  1067. hr = IsTruncated(offset, size);
  1068. if (S_OK != hr) {
  1069. //
  1070. // The file is not truncated, so skip it
  1071. //
  1072. WsbTrace(OLESTR("CFsaScanItem::IsRecallOK - file isn't truncated.\n"));
  1073. WsbThrow(FSA_E_FILE_NOT_TRUNCATED);
  1074. }
  1075. // Get the version ID from the FSA Post it. This is the
  1076. // version of the file at the time of the migrate request
  1077. //
  1078. LONGLONG workVersionId;
  1079. WsbAffirmHr(pPostIt->GetFileVersionId(&workVersionId));
  1080. //
  1081. // Get the version of the file
  1082. //
  1083. LONGLONG scanVersionId;
  1084. WsbAffirmHr(GetVersionId(&scanVersionId));
  1085. //
  1086. // See if the versions match
  1087. //
  1088. WsbTrace(OLESTR("CFsaScanItem::IsRecallOK: workVersionId:<%I64u> scanVersionId:<%I64u>\n"),
  1089. workVersionId, scanVersionId);
  1090. if (workVersionId != scanVersionId) {
  1091. WsbTrace(OLESTR("CFsaScanItem::IsRecallOK: File version has changed!\n"));
  1092. //
  1093. // If the use has changed alternate data streams
  1094. // the file version ID may have changed but it is
  1095. // OK to recall the file. So if the version ID's
  1096. // don't match, then check to see if the truncated
  1097. // part of the file is OK. If so, allow the recall
  1098. // to happen.
  1099. //
  1100. //
  1101. // Check to see if the whole file is still sparse
  1102. //
  1103. if (IsTotallySparse() == S_OK) {
  1104. //
  1105. // The file is OK so far to recall but we need
  1106. // to make the last modify dates match
  1107. //
  1108. FSA_PLACEHOLDER placeholder;
  1109. WsbAffirmHr(pPostIt->GetPlaceholder(&placeholder));;
  1110. placeholder.fileVersionId = scanVersionId;
  1111. WsbAffirmHr(pPostIt->SetPlaceholder(&placeholder));
  1112. } else {
  1113. //
  1114. // The file has been changed, recalling data will
  1115. // overwrite something that has been added since the
  1116. // truncation occurred. So don't do anything.
  1117. //
  1118. WsbTrace(OLESTR("File is no longer sparse.!\n"));
  1119. WsbThrow(FSA_E_FILE_CHANGED);
  1120. }
  1121. }
  1122. } WsbCatch(hr);
  1123. WsbTraceOut(OLESTR("CFsaScanItem::IsRecallOK"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1124. return(hr);
  1125. }
  1126. HRESULT
  1127. CFsaScanItem::IsSparse(
  1128. void
  1129. )
  1130. /*++
  1131. Implements:
  1132. IFsaScanItem::IsSparse().
  1133. --*/
  1134. {
  1135. HRESULT hr = S_FALSE;
  1136. LONGLONG size;
  1137. WsbTraceIn(OLESTR("CFsaScanItem::IsSparse"), OLESTR(""));
  1138. if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) != 0) {
  1139. hr = GetLogicalSize( &size ) ;
  1140. if ( S_OK == hr ) {
  1141. hr = CheckIfSparse(0, size );
  1142. if ( (FSA_E_FILE_IS_TOTALLY_SPARSE == hr) ||
  1143. (FSA_E_FILE_IS_PARTIALLY_SPARSE == hr) ) {
  1144. hr = S_OK;
  1145. } else {
  1146. hr = S_FALSE;
  1147. }
  1148. }
  1149. }
  1150. WsbTraceOut(OLESTR("CFsaScanItem::IsSparse"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1151. return(hr);
  1152. }
  1153. HRESULT
  1154. CFsaScanItem::IsTotallySparse(
  1155. void
  1156. )
  1157. /*++
  1158. Implements:
  1159. IFsaScanItem::IsTotallySparse().
  1160. --*/
  1161. {
  1162. HRESULT hr = S_FALSE;
  1163. LONGLONG size;
  1164. WsbTraceIn(OLESTR("CFsaScanItem::IsTotallySparse"), OLESTR(""));
  1165. if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) != 0) {
  1166. hr = GetLogicalSize( &size ) ;
  1167. if ( S_OK == hr ) {
  1168. hr = CheckIfSparse(0, size );
  1169. if (FSA_E_FILE_IS_TOTALLY_SPARSE == hr) {
  1170. hr = S_OK;
  1171. } else {
  1172. hr = S_FALSE;
  1173. }
  1174. }
  1175. }
  1176. WsbTraceOut(OLESTR("CFsaScanItem::IsTotallySparse"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1177. return(hr);
  1178. }
  1179. HRESULT
  1180. CFsaScanItem::Manage(
  1181. IN LONGLONG offset,
  1182. IN LONGLONG size,
  1183. IN GUID storagePoolId,
  1184. IN BOOL truncate
  1185. )
  1186. /*++
  1187. Implements:
  1188. IFsaScanItem::Manage().
  1189. --*/
  1190. {
  1191. HRESULT hr = S_OK;
  1192. WsbTraceIn(OLESTR("CFsaScanItem::Manage"), OLESTR(""));
  1193. try {
  1194. WsbAssert(GUID_NULL != storagePoolId, E_INVALIDARG);
  1195. WsbAffirmHr(m_pResource->Manage((IFsaScanItem*) this, offset, size, storagePoolId, truncate));
  1196. } WsbCatch(hr);
  1197. WsbTraceOut(OLESTR("CFsaScanItem::Manage"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1198. return(hr);
  1199. }
  1200. HRESULT
  1201. CFsaScanItem::Move(
  1202. OLECHAR* dest,
  1203. BOOL /*retainHierarcy*/,
  1204. BOOL /*expandPlaceholders*/,
  1205. BOOL overwriteExisting
  1206. )
  1207. /*++
  1208. Implements:
  1209. IFsaScanItem::Move().
  1210. --*/
  1211. {
  1212. HRESULT hr = S_OK;
  1213. DWORD mode = MOVEFILE_COPY_ALLOWED;
  1214. try {
  1215. // NOTE : This default behavior causes placeholders
  1216. // to be expanded when moving to another volume and probably doesn't
  1217. // retain the heirarchy.
  1218. WsbAssert(0 != dest, E_POINTER);
  1219. if (overwriteExisting) {
  1220. mode |= MOVEFILE_REPLACE_EXISTING;
  1221. }
  1222. WsbAssert(MoveFileEx(m_findData.cFileName, dest, mode), E_FAIL);
  1223. } WsbCatch(hr);
  1224. return(hr);
  1225. }
  1226. HRESULT
  1227. CFsaScanItem::Recall(
  1228. IN LONGLONG offset,
  1229. IN LONGLONG size,
  1230. IN BOOL deletePlaceholder
  1231. )
  1232. /*++
  1233. Implements:
  1234. IFsaScanItem::Recall().
  1235. --*/
  1236. {
  1237. HRESULT hr = S_OK;
  1238. WsbTraceIn(OLESTR("CFsaScanItem::Recall"), OLESTR(""));
  1239. try {
  1240. WsbAffirmHr(m_pResource->Recall((IFsaScanItem*) this, offset, size, deletePlaceholder));
  1241. } WsbCatch(hr);
  1242. WsbTraceOut(OLESTR("CFsaScanItem::Recall"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1243. return(hr);
  1244. }
  1245. HRESULT
  1246. CFsaScanItem::Recycle(
  1247. void
  1248. )
  1249. /*++
  1250. Implements:
  1251. IFsaScanItem::Recycle().
  1252. --*/
  1253. {
  1254. HRESULT hr = S_OK;
  1255. try {
  1256. // Probably need to look at SHFileOperation().
  1257. hr = E_NOTIMPL;
  1258. } WsbCatch(hr);
  1259. return(hr);
  1260. }
  1261. HRESULT
  1262. CFsaScanItem::IsSystem(
  1263. void
  1264. )
  1265. /*++
  1266. Implements:
  1267. IFsaScanItem::IsSystem().
  1268. --*/
  1269. {
  1270. HRESULT hr = S_FALSE;
  1271. if ((m_findData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) != 0) {
  1272. hr = S_OK;
  1273. }
  1274. return(hr);
  1275. }
  1276. HRESULT
  1277. CFsaScanItem::Test(
  1278. USHORT* passed,
  1279. USHORT* failed
  1280. )
  1281. /*++
  1282. Implements:
  1283. IWsbTestable::Test().
  1284. --*/
  1285. {
  1286. HRESULT hr = S_OK;
  1287. try {
  1288. WsbAssert(0 != passed, E_POINTER);
  1289. WsbAssert(0 != failed, E_POINTER);
  1290. *passed = 0;
  1291. *failed = 0;
  1292. } WsbCatch(hr);
  1293. return(hr);
  1294. }
  1295. HRESULT
  1296. CFsaScanItem::Unmanage(
  1297. IN LONGLONG offset,
  1298. IN LONGLONG size
  1299. )
  1300. /*++
  1301. Implements:
  1302. IFsaScanItem::Unmanage().
  1303. --*/
  1304. {
  1305. HRESULT hr = S_OK;
  1306. WsbTraceIn(OLESTR("CFsaScanItem::Unmanage"), OLESTR("<%ls>"),
  1307. WsbAbbreviatePath(m_path, 120));
  1308. try {
  1309. // We only need to worry about files that have placeholder information.
  1310. if (IsManaged(offset, size) == S_OK) {
  1311. // If the file is truncated, then we need to recall the data
  1312. // before deleting the placeholder information.
  1313. // NOTE: We set a flag on the Recall so the placeholder will
  1314. // be deleted after the file is recalled.
  1315. if (IsTruncated(offset, size) == S_OK) {
  1316. WsbAffirmHr(Recall(offset, size, TRUE));
  1317. } else {
  1318. // For disaster recovery, it would be better to delete the placeholder
  1319. // and THEN remove this file from the premigration list. Unfortunately,
  1320. // after deleting the placeholder, the RemovePremigrated call fails
  1321. // because it needs to get some information from the placeholder (which
  1322. // is gone). So we do it in this order.
  1323. hr = m_pResource->RemovePremigrated((IFsaScanItem*) this, offset, size);
  1324. if (WSB_E_NOTFOUND == hr) {
  1325. // It's no tragedy if this file wasn't in the list since we were
  1326. // going to delete it anyway (although it shouldn't happen) so
  1327. // let's continue anyway
  1328. hr = S_OK;
  1329. }
  1330. WsbAffirmHr(hr);
  1331. WsbAffirmHr(DeletePlaceholder(offset, size));
  1332. }
  1333. }
  1334. } WsbCatch(hr);
  1335. WsbTraceOut(OLESTR("CFsaScanItem::Unmanage"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1336. return(hr);
  1337. }
  1338. HRESULT
  1339. CFsaScanItem::Validate(
  1340. IN LONGLONG offset,
  1341. IN LONGLONG size
  1342. )
  1343. /*++
  1344. Implements:
  1345. IFsaScanItem::Validate().
  1346. --*/
  1347. {
  1348. HRESULT hr = S_OK;
  1349. BOOL fileIsTruncated = FALSE;
  1350. LONGLONG usn = 0;
  1351. WsbTraceIn(OLESTR("CFsaScanItem::Validate"), OLESTR("offset = <%I64u>, size = <%I64u>"),
  1352. offset, size);
  1353. try {
  1354. //
  1355. // Do some local validation before calling the engine.
  1356. //
  1357. // We only need to worry about files that have placeholder information.
  1358. if (IsManaged(offset, size) == S_OK) {
  1359. //
  1360. // If the file is marked as truncated, make sure it is still truncated.
  1361. //
  1362. if (IsTruncated(offset, size) == S_OK) {
  1363. //
  1364. // Check to see if the file is totally sparse to see if it is truncated.
  1365. //
  1366. if (IsTotallySparse() != S_OK) {
  1367. //
  1368. // The file is marked as truncated but is not truncated
  1369. // Make it truncated.
  1370. //
  1371. WsbAffirmHr(Truncate(offset,size));
  1372. WsbLogEvent(FSA_MESSAGE_VALIDATE_TRUNCATED_FILE, 0, NULL, WsbAbbreviatePath(m_path, 120), WsbHrAsString(hr), NULL);
  1373. }
  1374. fileIsTruncated = TRUE;
  1375. }
  1376. }
  1377. //
  1378. // The last modify date may be updated on a file if the named data streams
  1379. // have been modified. So check to see if the dates match. If they don't,
  1380. // if the file is trunctated, see if it is still truncated, if so, update the
  1381. // modify date in the placeholder to the file's modify date. If the file is
  1382. // premigrated and the modify dates don't match, delete the placeholder.
  1383. // Get the version ID from the file
  1384. LONGLONG scanVersionId;
  1385. WsbAffirmHr(GetVersionId(&scanVersionId));
  1386. // Get the version ID from the placeholder
  1387. FSA_PLACEHOLDER scanPlaceholder;
  1388. WsbAffirmHr(GetPlaceholder(offset, size, &scanPlaceholder));
  1389. if (TRUE == fileIsTruncated) {
  1390. // Check to see if the dates match
  1391. if (scanPlaceholder.fileVersionId != scanVersionId) {
  1392. WsbTrace(OLESTR("CFsaScanItem::Validate - placeholer version ID = <%I64u>, file version Id = <%I64u>"),
  1393. scanPlaceholder.fileVersionId, scanVersionId);
  1394. //
  1395. // Update the placeholder information on the reparse point
  1396. //
  1397. LONGLONG afterPhUsn;
  1398. scanPlaceholder.fileVersionId = scanVersionId;
  1399. WsbAffirmHr(CreatePlaceholder(offset, size, scanPlaceholder, FALSE, 0, &afterPhUsn));
  1400. WsbLogEvent(FSA_MESSAGE_VALIDATE_RESET_PH_MODIFY_TIME, 0, NULL, WsbAbbreviatePath(m_path, 120), WsbHrAsString(hr), NULL);
  1401. }
  1402. } else {
  1403. // The file is pre-migrated. Verify that it has not changed since we managed it and if it has then unmanage it.
  1404. if (Verify(offset, size) != S_OK) {
  1405. WsbAffirmHr(Unmanage(offset, size));
  1406. WsbLogEvent(FSA_MESSAGE_VALIDATE_UNMANAGED_FILE, 0, NULL, WsbAbbreviatePath(m_path, 120), WsbHrAsString(hr), NULL);
  1407. }
  1408. }
  1409. // Now that all of this stuff is OK, call the engine
  1410. if (IsManaged(offset, size) == S_OK) {
  1411. WsbAffirmHr(m_pResource->Validate((IFsaScanItem*) this, offset, size, usn));
  1412. }
  1413. } WsbCatch(hr);
  1414. WsbTraceOut(OLESTR("CFsaScanItem::Validate"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1415. return(hr);
  1416. }
  1417. HRESULT
  1418. CFsaScanItem::FindFirstInDbIndex(
  1419. IN IFsaResource* pResource,
  1420. IN IHsmSession* pSession
  1421. )
  1422. /*++
  1423. Implements:
  1424. IFsaScanItemPriv::FindFirstInDbIndex().
  1425. --*/
  1426. {
  1427. HRESULT hr = S_OK;
  1428. WsbTraceIn(OLESTR("CFsaScanItem::FindFirstInDbIndex"), OLESTR(""));
  1429. try {
  1430. CComPtr<IFsaResourcePriv> pResourcePriv;
  1431. WsbAssert(0 != pResource, E_POINTER);
  1432. // Store off some of the scan information.
  1433. m_pResource = pResource;
  1434. m_pSession = pSession;
  1435. // If Db is already present (could happen if somebody calls First() twice in a row),
  1436. // we close the Db and reopen since we cannot be sure that the resource is the same!
  1437. if (m_pUnmanageDb != NULL) {
  1438. // Db must be open
  1439. (void)m_pUnmanageDb->Close(m_pDbSession);
  1440. m_pDbSession = 0;
  1441. m_pUnmanageRec = 0;
  1442. m_pUnmanageDb = 0;
  1443. }
  1444. // Get and open the Unmanage db
  1445. // (Note: if this scanning is ever extended to use another DB,
  1446. // this method should get additional parameter for which DB to scan)
  1447. WsbAffirmHr(m_pResource->QueryInterface(IID_IFsaResourcePriv,
  1448. (void**) &pResourcePriv));
  1449. hr = pResourcePriv->GetUnmanageDb(IID_IFsaUnmanageDb,
  1450. (void**) &m_pUnmanageDb);
  1451. if (WSB_E_RESOURCE_UNAVAILABLE == hr) {
  1452. // Db was not created ==> no files to scan
  1453. hr = WSB_E_NOTFOUND;
  1454. }
  1455. WsbAffirmHr(hr);
  1456. hr = m_pUnmanageDb->Open(&m_pDbSession);
  1457. if (S_OK != hr) {
  1458. m_pUnmanageDb = NULL;
  1459. WsbAffirmHr(hr);
  1460. }
  1461. // Get a record to traverse with and set for sequential traversing
  1462. WsbAffirmHr(m_pUnmanageDb->GetEntity(m_pDbSession, UNMANAGE_REC_TYPE, IID_IFsaUnmanageRec,
  1463. (void**)&m_pUnmanageRec));
  1464. WsbAffirmHr(m_pUnmanageRec->SetSequentialScan());
  1465. // Get file information
  1466. WsbAffirmHr(GetFromDbIndex(TRUE));
  1467. } WsbCatch(hr);
  1468. WsbTraceOut(OLESTR("CFsaScanItem::FindFirstInDbIndex"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1469. return(hr);
  1470. }
  1471. HRESULT
  1472. CFsaScanItem::FindNextInDbIndex(
  1473. void
  1474. )
  1475. /*++
  1476. Implements:
  1477. IFsaScanItemPriv::FindNextInDbIndex().
  1478. --*/
  1479. {
  1480. HRESULT hr = S_OK;
  1481. WsbTraceIn(OLESTR("CFsaScanItem::FindNextInDbIndex"), OLESTR(""));
  1482. try {
  1483. WsbAssert(m_pUnmanageDb != NULL, E_FAIL);
  1484. // Get file information
  1485. WsbAffirmHr(GetFromDbIndex(FALSE));
  1486. } WsbCatch(hr);
  1487. WsbTraceOut(OLESTR("CFsaScanItem::FindNextInDbIndex"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1488. return(hr);
  1489. }
  1490. HRESULT
  1491. CFsaScanItem::GetFromDbIndex(
  1492. BOOL first
  1493. )
  1494. /*
  1495. Implements:
  1496. CFsaScanItem::GetFromDbIndex().
  1497. --*/
  1498. {
  1499. HRESULT hr = S_OK;
  1500. WsbTraceIn(OLESTR("CFsaScanItem::GetFromDbIndex"), OLESTR(""));
  1501. try {
  1502. IFsaScanItem* pScanItem;
  1503. HRESULT hrFindFileId = S_OK;
  1504. LONGLONG fileId;
  1505. BOOL bCont;
  1506. WsbAssert(m_pUnmanageDb != NULL, E_FAIL);
  1507. WsbAssert(m_pUnmanageRec != NULL, E_FAIL);
  1508. do {
  1509. bCont = FALSE;
  1510. // Get first/next record
  1511. if (first) {
  1512. hr = m_pUnmanageRec->First();
  1513. } else {
  1514. hr = m_pUnmanageRec->Next();
  1515. }
  1516. WsbAffirm(S_OK == hr, WSB_E_NOTFOUND);
  1517. // Get file id
  1518. WsbAffirmHr(m_pUnmanageRec->GetFileId(&fileId));
  1519. // Reset some items in case this isn't the first call to FindFileId
  1520. // (FindFileId actually "attach" the object to a different file)
  1521. if (INVALID_HANDLE_VALUE != m_handle) {
  1522. FindClose(m_handle);
  1523. m_handle = INVALID_HANDLE_VALUE;
  1524. }
  1525. if (TRUE == m_changedAttributes) {
  1526. RestoreAttributes();
  1527. }
  1528. // Find the file from the ID
  1529. pScanItem = this;
  1530. hrFindFileId = m_pResource->FindFileId(fileId, m_pSession, &pScanItem);
  1531. // If the FindFileId failed, we just skip that item and get the
  1532. // next one. This is to keep the scan from just stopping on this
  1533. // item. FindFileId could fail because the file has been deleted
  1534. // or open exclusively by somebody else
  1535. if (!SUCCEEDED(hrFindFileId)) {
  1536. WsbTrace(OLESTR("CFsaScanItem::GetFromDbIndex: file id %I64d skipped since FindFileId failed with hr = <%ls>\n"),
  1537. fileId, WsbHrAsString(hrFindFileId));
  1538. first = FALSE;
  1539. bCont = TRUE;
  1540. }
  1541. } while (bCont);
  1542. WsbAffirmHr(pScanItem->Release()); // Get rid of extra ref. count (we get extra ref count only when FindFileId succeeds)
  1543. } WsbCatch(hr);
  1544. WsbTraceOut(OLESTR("CFsaScanItem::GetFromDbIndex"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1545. return(hr);
  1546. }