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.

5858 lines
161 KiB

  1. /*++
  2. (c) 1998 Seagate Software, Inc. All rights reserved.
  3. Module Name:
  4. fsarsc.cpp
  5. Abstract:
  6. This class represents a file system resource (i.e. volume)
  7. for NTFS 5.0.
  8. Author:
  9. Chuck Bardeen [cbardeen] 1-Dec-1996
  10. --*/
  11. #include "stdafx.h"
  12. #define WSB_TRACE_IS WSB_TRACE_BIT_FSA
  13. #include "wsb.h"
  14. #include "fsa.h"
  15. #include "fsaprem.h"
  16. #include "fsaprv.h"
  17. #include "fsarcvy.h"
  18. #include "fsarsc.h"
  19. #include "fsasrvr.h"
  20. #include "engine.h"
  21. #include "HsmConn.h"
  22. #include "job.h"
  23. #include "task.h"
  24. #include "mstask.h"
  25. #include <shlobj.h>
  26. static short g_InstanceCount = 0;
  27. static DWORD g_ThreadId;
  28. DWORD FsaStartOnStateChange(
  29. void* pVoid
  30. )
  31. /*++
  32. Note: This is done as a separate thread to avoid a deadlock situation
  33. --*/
  34. {
  35. ((CFsaResource*) pVoid)->OnStateChange();
  36. return(0);
  37. }
  38. HRESULT
  39. CFsaResource::AddPremigrated(
  40. IN IFsaScanItem* pScanItem,
  41. IN LONGLONG offset,
  42. IN LONGLONG size,
  43. IN BOOL isWaitingForClose,
  44. IN LONGLONG usn
  45. )
  46. /*++
  47. Implements:
  48. IFsaResource::AddPremigrated().
  49. --*/
  50. {
  51. HRESULT hr = S_OK;
  52. CComPtr<IWsbDbSession> pDbSession;
  53. CComPtr<IFsaPremigratedRec> pRec;
  54. WsbTraceIn(OLESTR("CFsaResource::AddPremigrated"), OLESTR("offset = %I64d, size = %I64d, waiting = <%ls>, usn = <%I64d>"),
  55. offset, size, WsbBoolAsString(isWaitingForClose), usn);
  56. try {
  57. WsbAssert(0 != pScanItem, E_POINTER);
  58. WsbAffirm(m_pPremigrated != NULL, E_UNEXPECTED);
  59. WsbAffirm(m_isDbInitialized, S_FALSE); // Not an necessarily an error
  60. // Open the data base
  61. WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
  62. try {
  63. WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, PREMIGRATED_REC_TYPE, IID_IFsaPremigratedRec, (void**) &pRec));
  64. WsbAffirmHr(pRec->UseKey(PREMIGRATED_BAGID_OFFSETS_KEY_TYPE));
  65. WsbAffirmHr(pRec->SetFromScanItem(pScanItem, offset, size, isWaitingForClose));
  66. WsbAffirmHr(pRec->SetFileUSN(usn));
  67. // If the key doesn't exist, then create it.
  68. if (FAILED(pRec->FindEQ())) {
  69. WsbAffirmHr(pRec->MarkAsNew());
  70. WsbAffirmHr(pRec->Write());
  71. // Add the size of the section migrated to the amount of premigrated data.
  72. m_premigratedSize += size;
  73. }
  74. // Otherwise, update it.
  75. else {
  76. LONGLONG itemSize;
  77. WsbAffirmHr(pRec->GetSize(&itemSize));
  78. WsbAffirmHr(pRec->SetFromScanItem(pScanItem, offset, size, isWaitingForClose));
  79. WsbAffirmHr(pRec->Write());
  80. if (m_isDoingValidate) {
  81. m_premigratedSize += size;
  82. } else if (itemSize != size) {
  83. m_premigratedSize = max(0, (m_premigratedSize - itemSize) + size);
  84. }
  85. }
  86. m_isDirty = TRUE;
  87. } WsbCatch(hr);
  88. // Close the data base
  89. WsbAffirmHr(m_pPremigrated->Close(pDbSession));
  90. } WsbCatch(hr);
  91. WsbTraceOut(OLESTR("CFsaResource::AddPremigrated"),
  92. OLESTR("hr = <%ls>, m_premigratedSize = %I64d"), WsbHrAsString(hr),
  93. m_premigratedSize);
  94. return(hr);
  95. }
  96. HRESULT
  97. CFsaResource::AddPremigratedSize(
  98. IN LONGLONG size
  99. )
  100. /*++
  101. Implements:
  102. IFsaResourcePriv::AddPremigratedSize().
  103. --*/
  104. {
  105. WsbTraceIn(OLESTR("CFsaResource::AddPremigratedSize"), OLESTR("m_premigratedSize = %I64d"), m_premigratedSize);
  106. m_isDirty = TRUE;
  107. m_premigratedSize += size;
  108. WsbTraceOut(OLESTR("CFsaResource::AddPremigratedSize"), OLESTR("m_premigratedSize = %I64d"), m_premigratedSize);
  109. return(S_OK);
  110. }
  111. HRESULT
  112. CFsaResource::AddTruncated(
  113. IN IFsaScanItem* /*pScanItem*/,
  114. IN LONGLONG /*offset*/,
  115. IN LONGLONG size
  116. )
  117. /*++
  118. Implements:
  119. IFsaResource::AddTruncated().
  120. --*/
  121. {
  122. HRESULT hr = S_OK;
  123. WsbTraceIn(OLESTR("CFsaResource::AddTruncated"), OLESTR(""));
  124. try {
  125. m_truncatedSize += size;
  126. m_isDirty = TRUE;
  127. } WsbCatch(hr);
  128. WsbTraceOut(OLESTR("CFsaResource::AddTruncated"),
  129. OLESTR("hr = <%ls>, m_truncatedSize = %I64d"), WsbHrAsString(hr),
  130. m_truncatedSize);
  131. return(hr);
  132. }
  133. HRESULT
  134. CFsaResource::AddTruncatedSize(
  135. IN LONGLONG size
  136. )
  137. /*++
  138. Implements:
  139. IFsaResource::AddTruncatedSize().
  140. --*/
  141. {
  142. HRESULT hr = S_OK;
  143. WsbTraceIn(OLESTR("CFsaResource::AddTruncatedSize"), OLESTR(""));
  144. try {
  145. m_truncatedSize += size;
  146. m_isDirty = TRUE;
  147. } WsbCatch(hr);
  148. WsbTraceOut(OLESTR("CFsaResource::AddTruncatedSize"), OLESTR("hr = <%ls>, m_truncatedSize = %I64d"), WsbHrAsString(hr), m_truncatedSize);
  149. return(hr);
  150. }
  151. HRESULT
  152. CFsaResource::BeginSession(
  153. IN OLECHAR* name,
  154. IN ULONG logControl,
  155. IN ULONG runId,
  156. IN ULONG subRunId,
  157. OUT IHsmSession** ppSession
  158. )
  159. /*++
  160. Implements:
  161. IFsaResource::BeginSession().
  162. --*/
  163. {
  164. HRESULT hr = S_OK;
  165. CComPtr<IHsmSession> pSession;
  166. BOOL bLog = TRUE;
  167. WsbTraceIn(OLESTR("CFsaResource::BeginSession"), OLESTR("name = <%ls>, Log = <%lu>, runId = <%lu>, subRunId = <%lu>"),
  168. (OLECHAR *)name, logControl, runId, subRunId);
  169. try {
  170. WsbAssert(0 != ppSession, E_POINTER);
  171. *ppSession = 0;
  172. // Create and Initialize a session object.
  173. WsbAffirmHr(CoCreateInstance(CLSID_CHsmSession, 0, CLSCTX_SERVER, IID_IHsmSession, (void**) &pSession));
  174. WsbAffirmHr(pSession->Start(name, logControl, m_managingHsm, 0, (IFsaResource*) this, runId, subRunId));
  175. // Since begin sesson doesn't use a formal scan, indicate that the scan phase has
  176. // started.
  177. WsbAffirmHr(pSession->ProcessState(HSM_JOB_PHASE_SCAN, HSM_JOB_STATE_STARTING, OLESTR(""),bLog));
  178. // Return the session to the caller.
  179. *ppSession = pSession;
  180. pSession->AddRef();
  181. } WsbCatch(hr);
  182. WsbTraceOut(OLESTR("CFsaResource::BeginSession"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  183. return(hr);
  184. }
  185. HRESULT
  186. CFsaResource::BeginValidate(
  187. void
  188. )
  189. /*++
  190. Implements:
  191. IFsaResource::BeginValidate().
  192. --*/
  193. {
  194. HRESULT hr = S_OK;
  195. WsbTraceIn(OLESTR("CFsaResource::BeginValidate"),
  196. OLESTR("PremigratedSize = %I64d, TruncatedSize = %I64d"),
  197. m_premigratedSize, m_truncatedSize);
  198. try {
  199. m_oldPremigratedSize = m_premigratedSize;
  200. m_premigratedSize = 0;
  201. m_oldTruncatedSize = m_truncatedSize;
  202. m_truncatedSize = 0;
  203. m_isDoingValidate = TRUE;
  204. } WsbCatch(hr);
  205. WsbTraceOut(OLESTR("CFsaResource::BeginValidate"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  206. return(hr);
  207. }
  208. HRESULT
  209. CFsaResource::CheckForJournal(
  210. BOOL *pValidateNeeded
  211. )
  212. /*++
  213. Implements:
  214. IFsaResource::CheckForJournal
  215. --*/
  216. {
  217. HRESULT hr = S_OK;
  218. ULONGLONG usnSize, usnId;
  219. DWORD spc, bps, freeC, totalC;
  220. CWsbStringPtr name;
  221. WsbTraceIn(OLESTR("CFsaResource::CheckForJournal"),OLESTR("volume = %ls"), m_path);
  222. //
  223. // First we check the USN journal and determine if it is out of date.
  224. //
  225. try {
  226. hr = WsbGetUsnJournalId(m_path, &usnId);
  227. if (S_OK == hr) {
  228. WsbTrace(OLESTR("CFsaResource::CheckForJournal - USN Journal ID = %I64x\n"),
  229. usnId);
  230. if (0 != m_usnJournalId && usnId != m_usnJournalId) {
  231. WsbTrace(OLESTR("CFsaResource::CheckForJournal - USN Journal ID changed from %I64\n"),
  232. m_usnJournalId);
  233. *pValidateNeeded = TRUE; // No match - we must validate
  234. // WsbAffirmHr(E_FAIL);
  235. }
  236. } else if (WSB_E_NOTFOUND == hr) {
  237. hr = S_OK;
  238. // The journal is not active, try to create it.
  239. // Make the max USN journal 1/64 the volume size.
  240. //
  241. WsbTrace(OLESTR("CFsaResource::CheckForJournal - Failed to get the journal ID for %ws\n"), m_path);
  242. name = m_path;
  243. WsbAffirmHr(name.Prepend(OLESTR("\\\\?\\")));
  244. if (GetDiskFreeSpace(name, &spc, &bps, &freeC, &totalC)) {
  245. ULONGLONG freeBytes, totalBytes;
  246. ULONGLONG minSize, maxSize;
  247. ULONG freeSpaceFraction, totalSpaceFraction, minSizeMB, maxSizeMB;
  248. WsbTrace(OLESTR("CFsaResource::CheckForJournal - Got disk free space\n"));
  249. freeBytes = (ULONGLONG) spc * (ULONGLONG) bps * (ULONGLONG) freeC;
  250. totalBytes = (ULONGLONG) spc * (ULONGLONG) bps * (ULONGLONG) totalC;
  251. // Get constants for USN size calculation
  252. minSizeMB = FSA_USN_MIN_SIZE_DEFAULT;
  253. WsbAffirmHr(WsbRegistryValueUlongAsString(NULL, FSA_REGISTRY_PARMS, FSA_USN_MIN_SIZE,
  254. &minSizeMB));
  255. minSize = (ULONGLONG)minSizeMB * (ULONGLONG)0x100000;
  256. maxSizeMB = FSA_USN_MAX_SIZE_DEFAULT;
  257. WsbAffirmHr(WsbRegistryValueUlongAsString(NULL, FSA_REGISTRY_PARMS, FSA_USN_MAX_SIZE,
  258. &maxSizeMB));
  259. maxSize = (ULONGLONG)maxSizeMB * (ULONGLONG)0x100000;
  260. freeSpaceFraction = FSA_USN_FREE_SPACE_FRACTION_DEFAULT;
  261. WsbAffirmHr(WsbRegistryValueUlongAsString(NULL, FSA_REGISTRY_PARMS, FSA_USN_FREE_SPACE_FRACTION,
  262. &freeSpaceFraction));
  263. totalSpaceFraction = FSA_USN_TOTAL_SPACE_FRACTION_DEFAULT;
  264. WsbAffirmHr(WsbRegistryValueUlongAsString(NULL, FSA_REGISTRY_PARMS, FSA_USN_TOTAL_SPACE_FRACTION,
  265. &totalSpaceFraction));
  266. // Get a max value out of fraction-of-free=space and a constant
  267. // This ensures that volume with little free space still gets a decent journal size
  268. usnSize = MAX( (freeBytes / freeSpaceFraction) , minSize );
  269. // Get a min value out of fraction-of-total-bytes and previous number
  270. // This ensures that small volumes don't allocate unproportional size for the journal
  271. usnSize = MIN ( (totalBytes / totalSpaceFraction) , usnSize);
  272. // Get a min of an NTFS upper-limit const and previous number
  273. // This ensures that large empty volumes don't allocate a too large journal
  274. usnSize = MIN ( maxSize , usnSize);
  275. WsbTrace(OLESTR("CFsaResource::CheckForJournal - Create USN journal - %u\n"), usnSize);
  276. WsbAffirmHr(WsbCreateUsnJournal(m_path, usnSize));
  277. WsbAffirmHr(WsbGetUsnJournalId(m_path, &m_usnJournalId));
  278. WsbTrace(OLESTR("CFsaResource::CheckForJournal - USN Journal ID = %I64x\n"),
  279. m_usnJournalId);
  280. } else {
  281. DWORD lErr;
  282. lErr = GetLastError();
  283. WsbTrace(OLESTR("CFsaResource::CheckForJournal - GetDiskFreeSpace failed - %x\n"), lErr);
  284. hr = E_FAIL;
  285. }
  286. }
  287. } WsbCatch(hr);
  288. if (hr != S_OK) {
  289. //
  290. // Problem - could not find or create the USN journal - we refuse to
  291. // run without it
  292. //
  293. WsbTrace(OLESTR("CFsaResource::CheckForJournal - ERROR creating/accessing the USN journal for %ws\n"),
  294. m_path);
  295. if (WSB_E_USNJ_CREATE_DISK_FULL == hr) {
  296. WsbLogEvent(FSA_MESSAGE_CANNOT_CREATE_USNJ_DISK_FULL, 0, NULL,
  297. (OLECHAR *) m_path, NULL);
  298. } else if (WSB_E_USNJ_CREATE == hr) {
  299. WsbLogEvent(FSA_MESSAGE_CANNOT_CREATE_USNJ, 0, NULL,
  300. (OLECHAR *) m_path, NULL);
  301. } else {
  302. WsbLogEvent(FSA_MESSAGE_CANNOT_ACCESS_USNJ, 0, NULL,
  303. WsbHrAsString(hr), (OLECHAR *) m_path, NULL);
  304. }
  305. m_usnJournalId = (ULONGLONG) 0;
  306. }
  307. WsbTraceOut(OLESTR("CFsaResource::CheckForJournal"),OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  308. return(hr);
  309. }
  310. HRESULT
  311. CFsaResource::CheckForValidate(BOOL bForceValidate)
  312. /*++
  313. Implements:
  314. IFsaResource::CheckForValidate
  315. --*/
  316. {
  317. HRESULT hr = S_OK;
  318. SYSTEMTIME sysTime;
  319. FILETIME curTime;
  320. LARGE_INTEGER ctime;
  321. CWsbStringPtr tmpString;
  322. BOOL validateNeeded = FALSE; // Start out assuming no validate needed
  323. WsbTraceIn(OLESTR("CFsaResource::CheckForValidate"),OLESTR("bForceValidate"),
  324. WsbBoolAsString(bForceValidate));
  325. try {
  326. //
  327. // First we check the USN journal and determine if it is out of date.
  328. //
  329. WsbAffirmHr(CheckForJournal(&validateNeeded));
  330. //
  331. // Check the registry to see if a validate job needs to be run. If the filter detected
  332. // a HSM reparse point getting set and it was not by us it sets a registry value to
  333. // indicate it.
  334. //
  335. try {
  336. WsbAffirmHr(tmpString.Alloc(32));
  337. swprintf((OLECHAR *) tmpString, L"%x", m_serial);
  338. WsbTrace(L"CFsaResource::CheckForValidate - Checking registry for validate - %ws\\%ws\n",
  339. FSA_VALIDATE_LOG_KEY_NAME, (OLECHAR *) tmpString);
  340. hr = WsbGetRegistryValueData(NULL, FSA_VALIDATE_LOG_KEY_NAME,
  341. tmpString, (BYTE *) &ctime, sizeof(ctime), NULL);
  342. if ((hr == S_OK) || validateNeeded || bForceValidate) {
  343. //
  344. // Regardless of what value the registry entry was we set up the job for 2 hours from now.
  345. // The actual event may have been well in the past and the task scheduler will not like a
  346. // time in the past as the start time.
  347. //
  348. GetLocalTime(&sysTime);
  349. WsbAffirmStatus(SystemTimeToFileTime(&sysTime, &curTime));
  350. ctime.LowPart = curTime.dwLowDateTime;
  351. ctime.HighPart = curTime.dwHighDateTime;
  352. if (validateNeeded || bForceValidate) {
  353. ctime.QuadPart += WSB_FT_TICKS_PER_MINUTE * 5; // 5 Minutes from now if the USN journal changed
  354. } else {
  355. ctime.QuadPart += WSB_FT_TICKS_PER_HOUR * 2; // 2 Hours from now if restore activity took place
  356. }
  357. curTime.dwLowDateTime = ctime.LowPart;
  358. curTime.dwHighDateTime = ctime.HighPart;
  359. WsbAffirmStatus(FileTimeToSystemTime(&curTime, &sysTime));
  360. WsbAffirmHr(SetupValidateJob(sysTime));
  361. WsbLogEvent(FSA_MESSAGE_AUTO_VALIDATE, 0, NULL,
  362. (OLECHAR *) m_path, NULL);
  363. } else {
  364. WsbTrace(L"CFsaResource::CheckForValidate - Registry entry not there - %ws\n", WsbHrAsString(hr));
  365. }
  366. hr = S_OK;
  367. } WsbCatchAndDo(hr,
  368. //
  369. // Log an event if we fail to set up the job
  370. //
  371. WsbTrace(L"CFsaResource::CheckForValidate - Failed to set the job - %x\n", hr);
  372. WsbLogEvent(FSA_MESSAGE_AUTOVALIDATE_SCHEDULE_FAILED, 0, NULL, WsbAbbreviatePath(m_path, 120), NULL);
  373. );
  374. } WsbCatch(hr);
  375. WsbTraceOut(OLESTR("CFsaResource::CheckForValidate"),OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  376. return(hr);
  377. }
  378. HRESULT
  379. CFsaResource::CompareBy(
  380. FSA_RESOURCE_COMPARE by
  381. )
  382. /*++
  383. Implements:
  384. IFsaResource::CompareBy().
  385. --*/
  386. {
  387. HRESULT hr = S_OK;
  388. m_compareBy = by;
  389. m_isDirty = TRUE;
  390. return(hr);
  391. }
  392. HRESULT
  393. CFsaResource::CompareTo(
  394. IN IUnknown* pUnknown,
  395. OUT SHORT* pResult
  396. )
  397. /*++
  398. Implements:
  399. IWsbCollectable::CompareTo().
  400. --*/
  401. {
  402. HRESULT hr = S_OK;
  403. CComPtr<IFsaResource> pResource;
  404. WsbTraceIn(OLESTR("CFsaResource::CompareTo"), OLESTR(""));
  405. try {
  406. // Did they give us a valid item to compare to?
  407. WsbAssert(0 != pUnknown, E_POINTER);
  408. // We need the IFsaResource interface to get the value of the object.
  409. WsbAffirmHr(pUnknown->QueryInterface(IID_IFsaResource, (void**) &pResource));
  410. // Compare the rules.
  411. hr = CompareToIResource(pResource, pResult);
  412. } WsbCatch(hr);
  413. WsbTraceOut(OLESTR("CFsaResource::CompareTo"), OLESTR("hr = <%ls>, result = <%ls>"),
  414. WsbHrAsString(hr), WsbPtrToShortAsString(pResult));
  415. return(hr);
  416. }
  417. HRESULT
  418. CFsaResource::CompareToAlternatePath(
  419. IN OLECHAR* path,
  420. OUT SHORT* pResult
  421. )
  422. /*++
  423. Implements:
  424. IFsaResource::CompareToAlternatePath().
  425. --*/
  426. {
  427. HRESULT hr = S_OK;
  428. SHORT aResult = 0;
  429. WsbTraceIn(OLESTR("CFsaResource::CompareToAlternatePath"), OLESTR("path = <%ls>"), (OLECHAR *)path);
  430. try {
  431. WsbTrace(OLESTR("CFsaResource::CompareToAlternatePath - Compare %ls to %ls\n"),
  432. (WCHAR *) m_alternatePath, (WCHAR *) path);
  433. // Compare the path.
  434. aResult = WsbSign( _wcsicmp(m_alternatePath, path) );
  435. if (0 != aResult) {
  436. hr = S_FALSE;
  437. }
  438. if (0 != pResult) {
  439. *pResult = aResult;
  440. }
  441. } WsbCatch(hr);
  442. WsbTraceOut(OLESTR("CFsaResource::CompareToAlternatePath"), OLESTR("hr = <%ls>, result = <%u>"), WsbHrAsString(hr), aResult);
  443. return(hr);
  444. }
  445. HRESULT
  446. CFsaResource::CompareToIdentifier(
  447. IN GUID id,
  448. OUT SHORT* pResult
  449. )
  450. /*++
  451. Implements:
  452. IFsaResource::CompareToIdentifier().
  453. --*/
  454. {
  455. HRESULT hr = S_OK;
  456. SHORT aResult = 0;
  457. WsbTraceIn(OLESTR("CFsaResource::CompareToIdentifier"), OLESTR(""));
  458. try {
  459. aResult = WsbSign( memcmp(&m_id, &id, sizeof(GUID)) );
  460. if (0 != aResult) {
  461. hr = S_FALSE;
  462. }
  463. if (0 != pResult) {
  464. *pResult = aResult;
  465. }
  466. } WsbCatch(hr);
  467. WsbTraceOut(OLESTR("CFsaResource::CompareToIdentifier"), OLESTR("hr = <%ls>, result = <%u>"), WsbHrAsString(hr), aResult);
  468. return(hr);
  469. }
  470. HRESULT
  471. CFsaResource::CompareToIResource(
  472. IN IFsaResource* pResource,
  473. OUT SHORT* pResult
  474. )
  475. /*++
  476. Implements:
  477. IFsaResource::CompareToIResource().
  478. --*/
  479. {
  480. HRESULT hr = S_OK;
  481. CWsbStringPtr name;
  482. GUID id;
  483. ULONG serial;
  484. WsbTraceIn(OLESTR("CFsaResource::CompareToIResource"), OLESTR(""));
  485. try {
  486. // Did they give us a valid item to compare to?
  487. WsbAssert(0 != pResource, E_POINTER);
  488. // Either compare the name or the id.
  489. if (m_compareBy == FSA_RESOURCE_COMPARE_PATH) {
  490. WsbAffirmHr(pResource->GetPath(&name, 0));
  491. hr = CompareToPath(name, pResult);
  492. } else if (m_compareBy == FSA_RESOURCE_COMPARE_ALTERNATEPATH) {
  493. WsbAffirmHr(pResource->GetAlternatePath(&name, 0));
  494. hr = CompareToAlternatePath(name, pResult);
  495. } else if (m_compareBy == FSA_RESOURCE_COMPARE_ID) {
  496. WsbAffirmHr(pResource->GetIdentifier(&id));
  497. hr = CompareToIdentifier(id, pResult);
  498. } else if (m_compareBy == FSA_RESOURCE_COMPARE_NAME) {
  499. WsbAffirmHr(pResource->GetName(&name, 0));
  500. hr = CompareToName(name, pResult);
  501. } else if (m_compareBy == FSA_RESOURCE_COMPARE_SERIAL) {
  502. WsbAffirmHr(pResource->GetSerial(&serial));
  503. hr = CompareToSerial(serial, pResult);
  504. } else if (m_compareBy == FSA_RESOURCE_COMPARE_USER_NAME) {
  505. WsbAffirmHr(pResource->GetUserFriendlyName(&name, 0));
  506. hr = CompareToUserName(name, pResult);
  507. } else if (m_compareBy == FSA_RESOURCE_COMPARE_STICKY_NAME) {
  508. WsbAffirmHr(pResource->GetStickyName(&name, 0));
  509. hr = CompareToStickyName(name, pResult);
  510. } else {
  511. WsbAssert(FALSE, E_FAIL);
  512. }
  513. } WsbCatch(hr);
  514. WsbTraceOut(OLESTR("CFsaResource::CompareToIResource"), OLESTR("hr = <%ls>, result = <%ls>"), WsbHrAsString(hr), WsbPtrToShortAsString(pResult));
  515. return(hr);
  516. }
  517. HRESULT
  518. CFsaResource::CompareToName(
  519. IN OLECHAR* name,
  520. OUT SHORT* pResult
  521. )
  522. /*++
  523. Implements:
  524. IFsaResource::CompareToName().
  525. --*/
  526. {
  527. HRESULT hr = S_OK;
  528. SHORT aResult = 0;
  529. WsbTraceIn(OLESTR("CFsaResource::CompareToName"), OLESTR(""));
  530. try {
  531. // Compare the path.
  532. aResult = WsbSign( _wcsicmp(m_name, name) );
  533. if (0 != aResult) {
  534. hr = S_FALSE;
  535. }
  536. if (0 != pResult) {
  537. *pResult = aResult;
  538. }
  539. } WsbCatch(hr);
  540. WsbTraceOut(OLESTR("CFsaResource::CompareToName"), OLESTR("hr = <%ls>, result = <%u>"), WsbHrAsString(hr), aResult);
  541. return(hr);
  542. }
  543. HRESULT
  544. CFsaResource::CompareToUserName(
  545. IN OLECHAR* name,
  546. OUT SHORT* pResult
  547. )
  548. /*++
  549. Implements:
  550. IFsaResource::CompareToUserName().
  551. --*/
  552. {
  553. HRESULT hr = S_OK;
  554. SHORT aResult = 0;
  555. WsbTraceIn(OLESTR("CFsaResource::CompareToUserName"), OLESTR(""));
  556. try {
  557. // Compare the path.
  558. aResult = WsbSign( _wcsicmp(m_userName, name) );
  559. if (0 != aResult) {
  560. hr = S_FALSE;
  561. }
  562. if (0 != pResult) {
  563. *pResult = aResult;
  564. }
  565. } WsbCatch(hr);
  566. WsbTraceOut(OLESTR("CFsaResource::CompareToUserName"), OLESTR("hr = <%ls>, result = <%u>"), WsbHrAsString(hr), aResult);
  567. return(hr);
  568. }
  569. HRESULT
  570. CFsaResource::CompareToPath(
  571. IN OLECHAR* path,
  572. OUT SHORT* pResult
  573. )
  574. /*++
  575. Implements:
  576. IFsaResource::CompareToPath().
  577. --*/
  578. {
  579. HRESULT hr = S_OK;
  580. SHORT aResult = 0;
  581. WsbTraceIn(OLESTR("CFsaResource::CompareToPath"), OLESTR(""));
  582. try {
  583. // Compare the path.
  584. aResult = WsbSign( _wcsicmp(m_path, path) );
  585. if (0 != aResult) {
  586. hr = S_FALSE;
  587. }
  588. if (0 != pResult) {
  589. *pResult = aResult;
  590. }
  591. } WsbCatch(hr);
  592. WsbTraceOut(OLESTR("CFsaResource::CompareToPath"), OLESTR("hr = <%ls>, result = <%u>"), WsbHrAsString(hr), aResult);
  593. return(hr);
  594. }
  595. HRESULT
  596. CFsaResource::CompareToSerial(
  597. IN ULONG serial,
  598. OUT SHORT* pResult
  599. )
  600. /*++
  601. Implements:
  602. IFsaResource::CompareToSerial().
  603. --*/
  604. {
  605. HRESULT hr = S_OK;
  606. SHORT aResult = 0;
  607. WsbTraceIn(OLESTR("CFsaResource::CompareToSerial"), OLESTR(""));
  608. try {
  609. WsbTrace(OLESTR("CFsaResource::CompareToSerial - Compare %lu to %lu\n"),
  610. m_serial, serial);
  611. // Compare the path.
  612. if (m_serial == serial) {
  613. aResult = 0;
  614. } else {
  615. aResult = 1;
  616. }
  617. if (0 != aResult) {
  618. hr = S_FALSE;
  619. }
  620. if (0 != pResult) {
  621. *pResult = aResult;
  622. }
  623. } WsbCatch(hr);
  624. WsbTraceOut(OLESTR("CFsaResource::CompareToSerial"), OLESTR("hr = <%ls>, result = <%u>"), WsbHrAsString(hr), aResult);
  625. return(hr);
  626. }
  627. HRESULT
  628. CFsaResource::CompareToStickyName(
  629. IN OLECHAR* name,
  630. OUT SHORT* pResult
  631. )
  632. /*++
  633. Implements:
  634. IFsaResource::CompareToStickyName().
  635. --*/
  636. {
  637. HRESULT hr = S_OK;
  638. SHORT aResult = 0;
  639. WsbTraceIn(OLESTR("CFsaResource::CompareToStickyName"), OLESTR(""));
  640. try {
  641. WsbTrace(OLESTR("CFsaResource::CompareToStickyName - Compare %ws to %ws\n"),
  642. (WCHAR *) m_stickyName, name);
  643. aResult = WsbSign( _wcsicmp(m_stickyName, name) );
  644. if (0 != aResult) {
  645. hr = S_FALSE;
  646. }
  647. if (0 != pResult) {
  648. *pResult = aResult;
  649. }
  650. if (0 != pResult) {
  651. *pResult = aResult;
  652. }
  653. } WsbCatch(hr);
  654. WsbTraceOut(OLESTR("CFsaResource::CompareToStickyName"), OLESTR("hr = <%ls>, result = <%u>"), WsbHrAsString(hr), aResult);
  655. return(hr);
  656. }
  657. static
  658. HRESULT
  659. AddExclusion(
  660. const OLECHAR* DrivePath,
  661. IWsbIndexedCollection* pDefaultRules,
  662. const OLECHAR* ExcludePath,
  663. BOOL UserRule
  664. )
  665. {
  666. HRESULT hr = S_OK;
  667. try {
  668. // If this is resource matches the drive of the folder path, exclude the path.
  669. if( _wcsnicmp( DrivePath, ExcludePath, 1 ) == 0 ) {
  670. CComPtr<IHsmRule> pRule;
  671. CComPtr<IWsbCollection> pCollection;
  672. CComPtr<IHsmCriteria> pCriteria;
  673. WsbAffirmHr( CoCreateInstance( CLSID_CHsmRule, NULL, CLSCTX_SERVER, IID_IHsmRule, (void**) &pRule ) );
  674. WsbAffirmHr( pRule->SetIsInclude( FALSE ) );
  675. WsbAffirmHr( pRule->SetIsUserDefined( UserRule ) );
  676. WsbAffirmHr( pRule->SetPath( (OLECHAR*) &ExcludePath[2] ) );
  677. WsbAffirmHr( pRule->SetName( OLESTR("*") ) );
  678. WsbAssertHr( CoCreateInstance( CLSID_CHsmCritAlways, NULL, CLSCTX_SERVER, IID_IHsmCriteria, (void**) &pCriteria ) );
  679. WsbAssertHr( pRule->Criteria( &pCollection ) );
  680. WsbAssertHr( pCollection->Add( pCriteria ) );
  681. WsbAffirmHr( pDefaultRules->Append( pRule ) );
  682. WsbTrace( L"Excluding <%ls>, <%ls>\n", ExcludePath, UserRule ? "UserRule" : "SystemRule" );
  683. }
  684. } WsbCatch( hr );
  685. return( hr );
  686. }
  687. static
  688. HRESULT
  689. AddShellFolderExclusion(
  690. const OLECHAR* DrivePath,
  691. IWsbIndexedCollection* pDefaultRules,
  692. int FolderId,
  693. BOOL UserRule
  694. )
  695. {
  696. HRESULT hr = S_OK;
  697. try {
  698. OLECHAR folderPath[_MAX_PATH] = L"";
  699. WsbAffirmHrOk( SHGetFolderPath( 0, FolderId, 0, 0, folderPath ) );
  700. WsbAffirmHr( AddExclusion( DrivePath, pDefaultRules, folderPath, UserRule ) );
  701. } WsbCatch( hr );
  702. return( hr );
  703. }
  704. static
  705. HRESULT
  706. AddRegistryPathExclusion(
  707. const OLECHAR* DrivePath,
  708. IWsbIndexedCollection* pDefaultRules,
  709. HKEY hKeyRoot,
  710. const OLECHAR* KeyName,
  711. const OLECHAR* ValueName,
  712. BOOL UserRule
  713. )
  714. {
  715. HRESULT hr = S_OK;
  716. try {
  717. DWORD pathSize = 0;
  718. CWsbStringPtr folderPath, regValue;
  719. //
  720. // Open the Key
  721. //
  722. CRegKey key;
  723. WsbAffirmWin32( key.Open( hKeyRoot, KeyName, KEY_QUERY_VALUE ) );
  724. //
  725. // Get the size of the value's data and allocatate buffer
  726. //
  727. WsbAffirmWin32( key.QueryValue( 0, ValueName, &pathSize ) );
  728. WsbAffirmHr( regValue.Alloc( ( pathSize / sizeof( OLECHAR ) ) + 1 ) );
  729. //
  730. // Get the data and expand any environment variables
  731. //
  732. WsbAffirmWin32( key.QueryValue( regValue, ValueName, &pathSize ) );
  733. pathSize = ExpandEnvironmentStrings( regValue, 0, 0 );
  734. WsbAffirmHr( folderPath.Alloc( pathSize ) );
  735. pathSize = ExpandEnvironmentStrings( regValue, folderPath, pathSize );
  736. WsbAffirmStatus( pathSize > 0 );
  737. //
  738. // And finally add the exclusion
  739. //
  740. WsbAffirmHr( AddExclusion( DrivePath, pDefaultRules, folderPath, UserRule ) );
  741. } WsbCatch( hr );
  742. return( hr );
  743. }
  744. HRESULT
  745. CFsaResource::CreateDefaultRules(
  746. void
  747. )
  748. /*++
  749. Implements:
  750. IFsaResource::CreateDefaultRules().
  751. --*/
  752. {
  753. HRESULT hr = S_OK;
  754. CComPtr<IHsmRule> pRule;
  755. CComPtr<IWsbCollection> pCollection;
  756. CComPtr<IWsbIndexedCollection> pDefaultRules;
  757. CComPtr<IHsmCriteria> pCriteria;
  758. WsbTraceIn(OLESTR("CFsaResource::CreateDefaultRules"), OLESTR(""));
  759. try {
  760. // Since we are recreating back to the default rules, remove all the existing default
  761. // rules.
  762. //
  763. // NOTE: This will cause any extra rules (non-default) to be removed.
  764. WsbAffirmHr(m_pDefaultRules->RemoveAllAndRelease());
  765. // We need to preserve the order of the rules, so use the indexed collection interface.
  766. WsbAffirmHr(m_pDefaultRules->QueryInterface(IID_IWsbIndexedCollection, (void**) &pDefaultRules));
  767. // Create rules to exclude the following file types:
  768. // *.cur - cursors
  769. // *.ico - icons
  770. // *.lnk - shortcuts
  771. WsbAffirmHr(CoCreateInstance(CLSID_CHsmRule, NULL, CLSCTX_SERVER, IID_IHsmRule, (void**) &pRule));
  772. WsbAffirmHr(pRule->SetIsInclude(FALSE));
  773. WsbAffirmHr(pRule->SetIsUserDefined(FALSE));
  774. WsbAffirmHr(pRule->SetPath(OLESTR("\\")));
  775. WsbAffirmHr(pRule->SetName(OLESTR("*.cur")));
  776. WsbAssertHr(CoCreateInstance(CLSID_CHsmCritAlways, NULL, CLSCTX_SERVER, IID_IHsmCriteria, (void**) &pCriteria));
  777. WsbAssertHr(pRule->Criteria(&pCollection));
  778. WsbAssertHr(pCollection->Add(pCriteria));
  779. WsbAffirmHr(pDefaultRules->Append(pRule));
  780. pCollection = 0;
  781. pCriteria = 0;
  782. pRule = 0;
  783. WsbAffirmHr(CoCreateInstance(CLSID_CHsmRule, NULL, CLSCTX_SERVER, IID_IHsmRule, (void**) &pRule));
  784. WsbAffirmHr(pRule->SetIsInclude(FALSE));
  785. WsbAffirmHr(pRule->SetIsUserDefined(FALSE));
  786. WsbAffirmHr(pRule->SetPath(OLESTR("\\")));
  787. WsbAffirmHr(pRule->SetName(OLESTR("*.ico")));
  788. WsbAssertHr(CoCreateInstance(CLSID_CHsmCritAlways, NULL, CLSCTX_SERVER, IID_IHsmCriteria, (void**) &pCriteria));
  789. WsbAssertHr(pRule->Criteria(&pCollection));
  790. WsbAssertHr(pCollection->Add(pCriteria));
  791. WsbAffirmHr(pDefaultRules->Append(pRule));
  792. pCollection = 0;
  793. pCriteria = 0;
  794. pRule = 0;
  795. WsbAffirmHr(CoCreateInstance(CLSID_CHsmRule, NULL, CLSCTX_SERVER, IID_IHsmRule, (void**) &pRule));
  796. WsbAffirmHr(pRule->SetIsInclude(FALSE));
  797. WsbAffirmHr(pRule->SetIsUserDefined(FALSE));
  798. WsbAffirmHr(pRule->SetPath(OLESTR("\\")));
  799. WsbAffirmHr(pRule->SetName(OLESTR("*.lnk")));
  800. WsbAssertHr(CoCreateInstance(CLSID_CHsmCritAlways, NULL, CLSCTX_SERVER, IID_IHsmCriteria, (void**) &pCriteria));
  801. WsbAssertHr(pRule->Criteria(&pCollection));
  802. WsbAssertHr(pCollection->Add(pCriteria));
  803. WsbAffirmHr(pDefaultRules->Append(pRule));
  804. pCollection = 0;
  805. pCriteria = 0;
  806. pRule = 0;
  807. WsbAffirmHr( AddShellFolderExclusion( m_path, pDefaultRules, CSIDL_WINDOWS, FALSE ) );
  808. WsbAffirmHr( AddShellFolderExclusion( m_path, pDefaultRules, CSIDL_PROGRAM_FILES, TRUE ) );\
  809. WsbAffirmHr( AddRegistryPathExclusion( m_path, pDefaultRules,
  810. HKEY_LOCAL_MACHINE,
  811. WSB_PROFILELIST_REGISTRY_KEY,
  812. WSB_PROFILES_DIR_REGISTRY_VALUE,
  813. TRUE ) );
  814. // If this is the boot drive (i.e. C), then exclude everything in the root, since most of
  815. // these files are important to boot the system (better safe than sorry, fewer rules).
  816. if (_wcsnicmp(m_path, OLESTR("C"), 1) == 0) {
  817. WsbAffirmHr(CoCreateInstance(CLSID_CHsmRule, NULL, CLSCTX_SERVER, IID_IHsmRule, (void**) &pRule));
  818. WsbAffirmHr(pRule->SetIsInclude(FALSE));
  819. WsbAffirmHr(pRule->SetIsUserDefined(FALSE));
  820. WsbAffirmHr(pRule->SetIsUsedInSubDirs(FALSE));
  821. WsbAffirmHr(pRule->SetPath(OLESTR("\\")));
  822. WsbAffirmHr(pRule->SetName(OLESTR("*")));
  823. WsbAssertHr(CoCreateInstance(CLSID_CHsmCritAlways, NULL, CLSCTX_SERVER, IID_IHsmCriteria, (void**) &pCriteria));
  824. WsbAssertHr(pRule->Criteria(&pCollection));
  825. WsbAssertHr(pCollection->Add(pCriteria));
  826. WsbAffirmHr(pDefaultRules->Append(pRule));
  827. pCollection = 0;
  828. pCriteria = 0;
  829. pRule = 0;
  830. }
  831. } WsbCatch(hr);
  832. WsbTraceOut(OLESTR("CFsaResource::CreateDefaultRules"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  833. return(hr);
  834. }
  835. HRESULT
  836. CFsaResource::DoRecovery(
  837. void
  838. )
  839. /*++
  840. Implements:
  841. IFsaResourcePriv::DoRecovery().
  842. --*/
  843. {
  844. HRESULT hr = S_OK;
  845. HRESULT hrFindFile;
  846. HRESULT hrFindRec;
  847. HRESULT hrLoop = S_OK;
  848. LONGLONG Offset;
  849. GUID bagId;
  850. LONGLONG bagOffset;
  851. LONGLONG fileId;
  852. OLECHAR * pPath = NULL;
  853. LONG RecCount;
  854. ULONG RecStatus;
  855. LONGLONG Size;
  856. FSA_PLACEHOLDER placeholder;
  857. CComPtr<IWsbDbSession> pDbSession;
  858. CComPtr<IFsaPremigratedRec> pPremRec;
  859. CComPtr<IFsaScanItem> pScanItem;
  860. CComPtr<IFsaScanItemPriv> pScanItemPriv;
  861. CComPtr<IFsaRecoveryRec> pRecRec;
  862. CComPtr<IHsmSession> pSession;
  863. WsbTraceIn(OLESTR("CFsaResource::DoRecovery"), OLESTR("Path = <%ls>"), WsbAbbreviatePath(m_path,120));
  864. try {
  865. // Don't bother if we already did recovery
  866. WsbAffirm(!m_isRecovered, S_FALSE);
  867. // Don't bother if this volume isn't managed
  868. WsbAffirm(S_OK == IsManaged(), S_FALSE);
  869. // Don't bother if we don't have a premigration-list DB (since it
  870. // contains the recovery records)
  871. if (!m_isDbInitialized) {
  872. // Set recovered flag so we don't end up in here again
  873. m_isRecovered = TRUE;
  874. WsbThrow(S_FALSE);
  875. }
  876. // Create and Initialize a session object.
  877. WsbAffirmHr(CoCreateInstance(CLSID_CHsmSession, 0, CLSCTX_SERVER, IID_IHsmSession, (void**) &pSession));
  878. WsbAffirmHr(pSession->Start(OLESTR(""), HSM_JOB_LOG_NONE, m_managingHsm, 0, (IFsaResource*) this, 0, 0));
  879. // Loop over recovery records and fix any problems
  880. WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
  881. WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, RECOVERY_REC_TYPE, IID_IFsaRecoveryRec, (void**) &pRecRec));
  882. WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, PREMIGRATED_REC_TYPE, IID_IFsaPremigratedRec, (void**) &pPremRec));
  883. WsbAffirmHr(pPremRec->UseKey(PREMIGRATED_BAGID_OFFSETS_KEY_TYPE));
  884. WsbAffirmHr(pRecRec->First());
  885. while (TRUE) {
  886. // Get record data
  887. WsbAffirmHr(pRecRec->GetBagId(&bagId));
  888. WsbAffirmHr(pRecRec->GetBagOffset(&bagOffset));
  889. WsbAffirmHr(pRecRec->GetFileId(&fileId));
  890. WsbAffirmHr(pRecRec->GetPath(&pPath, 0));
  891. WsbAffirmHr(pRecRec->GetStatus(&RecStatus));
  892. WsbAffirmHr(pRecRec->GetOffsetSize(&Offset, &Size));
  893. WsbAffirmHr(pRecRec->GetRecoveryCount(&RecCount));
  894. WsbTrace(OLESTR("CFsaResource::DoRecovery, FileId = %I64u, File = <%ls>, RecStatus = %lx, RecCount = %ld\n"), fileId, WsbAbbreviatePath(pPath, 120), RecStatus, RecCount);
  895. RecCount++;
  896. WsbAffirmHr(pRecRec->SetRecoveryCount(RecCount));
  897. // Mark the record as being recovered (in case we crash here)
  898. WsbAffirmHr(pRecRec->Write());
  899. try {
  900. // Create a scan item for this file
  901. hrFindFile = FindFileId(fileId, pSession, &pScanItem);
  902. if (SUCCEEDED(hrFindFile) && (pScanItem->IsManaged(Offset, Size) != S_FALSE)) {
  903. WsbAffirmHr(pScanItem->GetPlaceholder(Offset, Size, &placeholder));
  904. }
  905. WsbAffirmHr(pPremRec->SetBagId(bagId));
  906. WsbAffirmHr(pPremRec->SetBagOffset(bagOffset));
  907. WsbAffirmHr(pPremRec->SetOffset(Offset));
  908. hrFindRec = pPremRec->FindEQ();
  909. // If the file has been deleted, is not managed by HSM or its BAG data is
  910. // different from the RP data, then it shouldn't be in the premigration list.
  911. if ( (WSB_E_NOTFOUND == hrFindFile) ||
  912. (SUCCEEDED(hrFindFile) && (pScanItem->IsManaged(Offset, Size) != S_OK)) ||
  913. (SUCCEEDED(hrFindFile) && (pScanItem->IsManaged(Offset, Size) == S_OK) &&
  914. ((bagId != placeholder.bagId) || (bagOffset != placeholder.fileStart))) ) {
  915. // If the record is in the list, then remove it and adjust the sizes.
  916. // Note: The removal is not protected within a transaction since the
  917. // recovery is done only during initialization or when a new volume is
  918. // managed. In both cases, the auto-truncator does not run yet.
  919. if (S_OK == hrFindRec) {
  920. WsbAffirmHr(pPremRec->Remove());
  921. WsbAffirmHr(RemovePremigratedSize(Size));
  922. } else {
  923. WsbAffirmHr(RemoveTruncatedSize(Size));
  924. }
  925. }
  926. else {
  927. WsbAffirmHr(hrFindFile);
  928. // Check the status of the file according to the reparse point
  929. if (S_OK == pScanItem->IsTruncated(Offset, Size)) {
  930. // Force a truncate, just in case
  931. WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItemPriv, (void**)&pScanItemPriv));
  932. hrLoop = pScanItemPriv->TruncateInternal(Offset, Size);
  933. // Remove from premigrated list if there
  934. if (S_OK == hrFindRec) {
  935. if ((S_OK == hrLoop) || (FSA_E_ITEMCHANGED == hrLoop)) {
  936. WsbAffirmHr(pPremRec->Remove());
  937. WsbAffirmHr(RemovePremigratedSize(Size));
  938. if (S_OK == hrLoop) {
  939. WsbAffirmHr(AddTruncatedSize(Size));
  940. }
  941. }
  942. }
  943. }
  944. else if (S_OK == pScanItem->IsPremigrated(Offset, Size)) {
  945. // Add to premigrated list if not there
  946. if (WSB_E_NOTFOUND == hrFindRec) {
  947. WsbAffirmHr(RemoveTruncatedSize(Size));
  948. WsbAffirmHr(AddPremigratedSize(Size));
  949. WsbAffirmHr(pPremRec->MarkAsNew());
  950. WsbAffirmHr(pPremRec->Write());
  951. }
  952. }
  953. }
  954. } WsbCatch(hrLoop);
  955. if (FAILED(hrLoop)) {
  956. if ((RecStatus & FSA_RECOVERY_FLAG_TRUNCATING) != 0) {
  957. WsbLogEvent(FSA_MESSAGE_TRUNCATE_RECOVERY_FAIL, 0, NULL, WsbAbbreviatePath(pPath, 120), WsbHrAsString(hr), 0);
  958. } else if ((RecStatus & FSA_RECOVERY_FLAG_RECALLING) != 0) {
  959. WsbLogEvent(FSA_MESSAGE_RECALL_RECOVERY_FAIL, 0, NULL, WsbAbbreviatePath(pPath, 120), WsbHrAsString(hr), 0);
  960. }
  961. // If we have tried enough, then get rid of the record.
  962. if (RecCount > 2) {
  963. WsbTrace(OLESTR("CFsaResource::DoRecovery, unable to do recovery - too many attempts already\n"));
  964. WsbAffirmHr(pRecRec->Remove());
  965. }
  966. } else {
  967. // Log an event to commemorate our success
  968. WsbTrace(OLESTR("CFsaResource::DoRecovery, recovered <%ls>\n"), WsbAbbreviatePath(pPath, 120));
  969. if ((RecStatus & FSA_RECOVERY_FLAG_TRUNCATING) != 0) {
  970. WsbLogEvent(FSA_MESSAGE_TRUNCATE_RECOVERY_OK, 0, NULL, WsbAbbreviatePath(pPath, 120), 0);
  971. } else if ((RecStatus & FSA_RECOVERY_FLAG_RECALLING) != 0) {
  972. WsbLogEvent(FSA_MESSAGE_RECALL_RECOVERY_OK, 0, NULL, WsbAbbreviatePath(pPath, 120), 0);
  973. }
  974. // Remove this record from the DB
  975. WsbAffirmHr(pRecRec->Remove());
  976. }
  977. // Get the next one
  978. WsbAffirmHr(pRecRec->FindGT());
  979. // Release any objects we may have created
  980. // this time through the loop
  981. pScanItem = 0;
  982. pScanItemPriv = 0;
  983. hrLoop = S_OK;
  984. }
  985. } WsbCatch(hr);
  986. if (WSB_E_NOTFOUND == hr) {
  987. hr = S_OK;
  988. }
  989. if (pDbSession != 0) {
  990. m_pPremigrated->Close(pDbSession);
  991. }
  992. m_isRecovered = TRUE;
  993. // Now that everything is done, see if we need to start the truncator.
  994. WsbTrace(OLESTR("CFsaResource::DoRecovery, IsManaged = %ls, isActive = %ls\n"),
  995. WsbQuickString(WsbBoolAsString(IsManaged() == S_OK)),
  996. WsbQuickString(WsbBoolAsString(m_isActive)));
  997. // Make sure the truncator is started
  998. WsbAffirmHr(InitializePremigrationList(FALSE));
  999. WsbTraceOut(OLESTR("CFsaResource::DoRecovery"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1000. return(hr);
  1001. }
  1002. HRESULT
  1003. CFsaResource::EndSession(
  1004. IN IHsmSession* pSession
  1005. )
  1006. /*++
  1007. Implements:
  1008. IFsaResource::EndSession().
  1009. --*/
  1010. {
  1011. HRESULT hr = S_OK;
  1012. BOOL bLog = TRUE;
  1013. WsbTraceIn(OLESTR("CFsaResource::EndSession"), OLESTR(""));
  1014. try {
  1015. WsbAssert(0 != pSession, E_POINTER);
  1016. // Tell the session that the scan is done.
  1017. WsbAffirmHr(pSession->ProcessState(HSM_JOB_PHASE_SCAN, HSM_JOB_STATE_DONE, OLESTR(""), bLog));
  1018. } WsbCatch(hr);
  1019. WsbTraceOut(OLESTR("CFsaResource::EndSession"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1020. return(hr);
  1021. }
  1022. HRESULT
  1023. CFsaResource::EndValidate(
  1024. HSM_JOB_STATE state
  1025. )
  1026. /*++
  1027. Implements:
  1028. IFsaResource::EndValidate().
  1029. --*/
  1030. {
  1031. HRESULT hr = S_OK;
  1032. WsbTraceIn(OLESTR("CFsaResource::EndValidate"),
  1033. OLESTR("state = %ld, new PremigratedSize = %I64d, new TruncatedSize = %I64d"),
  1034. (LONG)state, m_premigratedSize, m_truncatedSize);
  1035. try {
  1036. if (HSM_JOB_STATE_DONE != state) {
  1037. m_premigratedSize = m_oldPremigratedSize;
  1038. m_truncatedSize = m_oldTruncatedSize;
  1039. }
  1040. m_isDoingValidate = FALSE;
  1041. // Make sure the truncator is running
  1042. WsbAffirmHr(InitializePremigrationList(FALSE));
  1043. WsbAffirmHr(m_pTruncator->KickStart());
  1044. } WsbCatch(hr);
  1045. WsbTraceOut(OLESTR("CFsaResource::EndValidate"),
  1046. OLESTR("hr = <%ls>, PremigratedSize = %I64d, TruncatedSize = %I64d"),
  1047. WsbQuickString(WsbHrAsString(hr)), m_premigratedSize, m_truncatedSize);
  1048. return(hr);
  1049. }
  1050. HRESULT
  1051. CFsaResource::EnumDefaultRules(
  1052. OUT IWsbEnum** ppEnum
  1053. )
  1054. /*++
  1055. Implements:
  1056. IFsaResource::EnumDefaultRules().
  1057. --*/
  1058. {
  1059. HRESULT hr = S_OK;
  1060. try {
  1061. WsbAssert(0 != ppEnum, E_POINTER);
  1062. WsbAffirmHr(m_pDefaultRules->Enum(ppEnum));
  1063. } WsbCatch(hr);
  1064. return(hr);
  1065. }
  1066. HRESULT
  1067. CFsaResource::FilterSawOpen(
  1068. IN IHsmSession* pSession,
  1069. IN IFsaFilterRecall* pRecall,
  1070. IN OLECHAR* path,
  1071. IN LONGLONG fileId,
  1072. IN LONGLONG requestOffset,
  1073. IN LONGLONG requestSize,
  1074. IN FSA_PLACEHOLDER* pPlaceholder,
  1075. IN ULONG mode,
  1076. IN FSA_RESULT_ACTION resultAction,
  1077. IN DWORD threadId
  1078. )
  1079. /*++
  1080. Implements:
  1081. IFsaResource::FilterSawOpen().
  1082. --*/
  1083. {
  1084. HRESULT hr = S_OK;
  1085. HRESULT hrFind;
  1086. CComPtr<IFsaPostIt> pWorkItem;
  1087. CComPtr<IHsmFsaTskMgr> pEngine;
  1088. CComPtr<IWsbDbSession> pDbSession;
  1089. CComPtr<IFsaRecoveryRec> pRecRec;
  1090. WsbTraceIn(OLESTR("CFsaResource::FilterSawOpen"),
  1091. OLESTR("path = <%ls>, requestOffset = %I64d, requestSize = %I64d"),
  1092. path, requestOffset, requestSize);
  1093. try {
  1094. WsbAssert(0 != pSession, E_POINTER);
  1095. WsbAssert(0 != pRecall, E_POINTER);
  1096. WsbAssert(0 != path, E_POINTER);
  1097. WsbAssert(0 != pPlaceholder, E_POINTER);
  1098. WsbAffirmHr(CoCreateInstance(CLSID_CFsaPostIt, 0, CLSCTX_SERVER, IID_IFsaPostIt, (void**) &pWorkItem));
  1099. // Remember which recall is being used to track the open.
  1100. WsbAffirmHr(pWorkItem->SetFilterRecall(pRecall));
  1101. //
  1102. // Set the session for others to know
  1103. //
  1104. WsbAffirmHr(pWorkItem->SetSession(pSession));
  1105. WsbAffirmHr(pWorkItem->SetMode(mode));
  1106. WsbAffirmHr(pWorkItem->SetFileVersionId(pPlaceholder->fileVersionId));
  1107. //
  1108. // Set the transfer size
  1109. //
  1110. WsbAffirmHr(pWorkItem->SetRequestOffset(requestOffset));
  1111. WsbAffirmHr(pWorkItem->SetRequestSize(requestSize));
  1112. WsbAffirmHr(pWorkItem->SetPlaceholder(pPlaceholder));
  1113. //
  1114. // Get a new copy of the path into the workitem
  1115. //
  1116. WsbAffirmHr(pWorkItem->SetPath(path));
  1117. //
  1118. // Need to check the mode to set the right result action. For now
  1119. // just set it to OPEN.
  1120. //
  1121. WsbAffirmHr(pWorkItem->SetResultAction(resultAction));
  1122. WsbAffirmHr(pWorkItem->SetThreadId(threadId));
  1123. //
  1124. // Send the request to the task manager. If the file was archived by someone other
  1125. // than the managing HSM, then that HSM will need to be looked up.
  1126. //
  1127. if ( GUID_NULL != m_managingHsm &&
  1128. memcmp(&m_managingHsm, &(pPlaceholder->hsmId), sizeof(GUID)) == 0) {
  1129. WsbAffirmHr(GetHsmEngine(&pEngine));
  1130. } else {
  1131. CComPtr<IHsmServer> pHsmServer;
  1132. WsbAssertHr(HsmConnectFromId(HSMCONN_TYPE_HSM, (pPlaceholder->hsmId), IID_IHsmServer, (void**) &pHsmServer));
  1133. WsbAffirmHr(pHsmServer->GetHsmFsaTskMgr(&pEngine));
  1134. }
  1135. //
  1136. // Fill in the rest of the work
  1137. //
  1138. if (mode & FILE_OPEN_NO_RECALL) {
  1139. WsbAffirmHr(pWorkItem->SetRequestAction(FSA_REQUEST_ACTION_FILTER_READ));
  1140. } else {
  1141. WsbAffirmHr(pWorkItem->SetRequestAction(FSA_REQUEST_ACTION_FILTER_RECALL));
  1142. if (m_isDbInitialized) {
  1143. // Save a recovery record in case anything goes wrong
  1144. WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
  1145. WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, RECOVERY_REC_TYPE, IID_IFsaRecoveryRec, (void**) &pRecRec));
  1146. WsbAffirmHr(pRecRec->SetPath(path));
  1147. // If the record already exists rewrite it, otherwise create a new record.
  1148. hrFind = pRecRec->FindEQ();
  1149. if (WSB_E_NOTFOUND == hrFind) {
  1150. WsbAffirmHr(pRecRec->MarkAsNew());
  1151. } else if (FAILED(hrFind)) {
  1152. WsbThrow(hrFind);
  1153. }
  1154. WsbAffirmHr(pRecRec->SetFileId(fileId));
  1155. WsbAffirmHr(pRecRec->SetOffsetSize(requestOffset, requestSize));
  1156. WsbAffirmHr(pRecRec->SetStatus(FSA_RECOVERY_FLAG_RECALLING));
  1157. WsbAffirmHr(pRecRec->Write());
  1158. }
  1159. }
  1160. // If anything that follows fails, then we need to delete the recovery record.
  1161. try {
  1162. WsbTrace(OLESTR("CFsaResource::FilterSawOpen calling DoFsaWork\n"));
  1163. WsbAffirmHr(pEngine->DoFsaWork(pWorkItem));
  1164. } WsbCatchAndDo(hr,
  1165. if (pRecRec != 0) {
  1166. hrFind = pRecRec->FindEQ();
  1167. if (hrFind == S_OK) {
  1168. WsbAffirmHr(pRecRec->Remove());
  1169. }
  1170. }
  1171. );
  1172. } WsbCatch(hr);
  1173. if (pDbSession != 0) {
  1174. m_pPremigrated->Close(pDbSession);
  1175. }
  1176. WsbTraceOut(OLESTR("CFsaResource::FilterSawOpen"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1177. return(hr);
  1178. }
  1179. HRESULT
  1180. CFsaResource::FilterSawDelete(
  1181. IN GUID /*filterId*/,
  1182. IN OLECHAR* path,
  1183. IN LONGLONG /*size*/,
  1184. IN FSA_PLACEHOLDER* pPlaceholder
  1185. )
  1186. /*++
  1187. Implements:
  1188. IFsaResource::FilterSawDelete().
  1189. --*/
  1190. {
  1191. HRESULT hr = S_OK;
  1192. WsbTraceIn(OLESTR("CFsaResource::FilterSawDelete"), OLESTR("path = <%ls>"), (OLECHAR *)path);
  1193. try {
  1194. WsbAssert(0 != path, E_POINTER);
  1195. WsbAssert(0 != pPlaceholder, E_POINTER);
  1196. hr = E_NOTIMPL;
  1197. } WsbCatch(hr);
  1198. WsbTraceOut(OLESTR("CFsaResource::FilterSawDelete"), OLESTR(""));
  1199. return(hr);
  1200. }
  1201. HRESULT
  1202. CFsaResource::FinalConstruct(
  1203. void
  1204. )
  1205. /*++
  1206. Implements:
  1207. CComObjectRoot::FinalConstruct().
  1208. --*/
  1209. {
  1210. HRESULT hr = S_OK;
  1211. WsbTraceIn(OLESTR("CFsaResource::FinalConstruct"), OLESTR(""));
  1212. try {
  1213. WsbAffirmHr(CWsbCollectable::FinalConstruct());
  1214. m_id = GUID_NULL;
  1215. m_compareBy = FSA_RESOURCE_COMPARE_ID;
  1216. m_managingHsm = GUID_NULL;
  1217. m_isActive = TRUE;
  1218. m_isAvailable = TRUE;
  1219. m_isDeletePending = FALSE;
  1220. m_isRecovered = FALSE;
  1221. m_hsmLevel = 0;
  1222. m_premigratedSize = 0;
  1223. m_truncatedSize = 0;
  1224. m_isDoingValidate = FALSE;
  1225. m_usnJournalId = (ULONGLONG) 0;
  1226. m_lastUsnId = (LONGLONG) 0; // Not used yet but persisted for possible future use.
  1227. // Default Criteria (12Kb, 180 days old)
  1228. m_manageableItemLogicalSize = 12288;
  1229. m_manageableItemAccessTimeIsRelative = TRUE;
  1230. m_manageableItemAccessTime = WsbLLtoFT(180 * WSB_FT_TICKS_PER_DAY);
  1231. m_isUnmanageDbInitialized = FALSE;
  1232. //Create the default rule list.
  1233. WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, NULL, CLSCTX_SERVER, IID_IWsbCollection, (void**) &m_pDefaultRules));
  1234. // Create the premigrated list DB
  1235. WsbAffirmHr(CoCreateInstance(CLSID_CFsaPremigratedDb, NULL, CLSCTX_SERVER, IID_IFsaPremigratedDb, (void**) &m_pPremigrated));
  1236. m_isDbInitialized = FALSE;
  1237. // Create the object for the auto truncator.
  1238. WsbAffirmHr(CoCreateInstance(CLSID_CFsaTruncatorNTFS, NULL, CLSCTX_SERVER, IID_IFsaTruncator, (void**) &m_pTruncator));
  1239. } WsbCatch(hr);
  1240. if (hr == S_OK) {
  1241. g_InstanceCount++;
  1242. }
  1243. WsbTrace(OLESTR("CFsaResource::FinalConstruct: this = %p, instance count = %d\n"),
  1244. this, g_InstanceCount);
  1245. WsbTraceOut(OLESTR("CFsaResource::FinalConstruct"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1246. return(hr);
  1247. }
  1248. HRESULT
  1249. CFsaResource::FinalRelease(
  1250. void
  1251. )
  1252. /*++
  1253. Implements:
  1254. CComObjectRoot::FinalRelease
  1255. --*/
  1256. {
  1257. HRESULT hr = S_OK;
  1258. WsbTraceIn(OLESTR("CFsaResource::FinalRelease"), OLESTR(""));
  1259. try {
  1260. HSM_SYSTEM_STATE SysState;
  1261. // Terminate Unmanage Db (If it wasn't created, nothing happens...)
  1262. TerminateUnmanageDb();
  1263. m_isUnmanageDbInitialized = FALSE;
  1264. m_pUnmanageDb = NULL;
  1265. // Shutdown resource
  1266. SysState.State = HSM_STATE_SHUTDOWN;
  1267. ChangeSysState(&SysState);
  1268. CWsbCollectable::FinalRelease();
  1269. // Free String members
  1270. // Note: Member objects held in smart-pointers are freed when the
  1271. // smart-pointer destructor is being called (as part of this object destruction)
  1272. m_oldPath.Free();
  1273. m_path.Free();
  1274. m_alternatePath.Free();
  1275. m_name.Free();
  1276. m_fsName.Free();
  1277. } WsbCatch(hr);
  1278. if (hr == S_OK) {
  1279. g_InstanceCount--;
  1280. }
  1281. WsbTrace(OLESTR("CFsaResource::FinalRelease: this = %p, instance count = %d\n"),
  1282. this, g_InstanceCount);
  1283. WsbTraceOut(OLESTR("CFsaResource::FinalRelease"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1284. return(hr);
  1285. }
  1286. HRESULT
  1287. CFsaResource::FindFirst(
  1288. IN OLECHAR* path,
  1289. IN IHsmSession* pSession,
  1290. OUT IFsaScanItem** ppScanItem
  1291. )
  1292. /*++
  1293. Implements:
  1294. IFsaResource::FindFirst().
  1295. --*/
  1296. {
  1297. HRESULT hr = S_OK;
  1298. CComPtr<IFsaScanItemPriv> pScanItem;
  1299. try {
  1300. WsbAssert(0 != path, E_POINTER);
  1301. WsbAssert(0 != ppScanItem, E_POINTER);
  1302. // Create an FsaScanItem that will scan for us.
  1303. WsbAffirmHr(CoCreateInstance(CLSID_CFsaScanItemNTFS, NULL, CLSCTX_SERVER, IID_IFsaScanItemPriv, (void**) &pScanItem));
  1304. // Scan starting at the specified path.
  1305. WsbAffirmHr(pScanItem->FindFirst((IFsaResource*) this, path, pSession));
  1306. // If we found something, then return the scan item.
  1307. WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItem, (void**) ppScanItem));
  1308. } WsbCatch(hr);
  1309. return(hr);
  1310. }
  1311. HRESULT
  1312. CFsaResource::FindFirstInRPIndex(
  1313. IN IHsmSession* pSession,
  1314. OUT IFsaScanItem** ppScanItem
  1315. )
  1316. /*++
  1317. Implements:
  1318. IFsaResource::FindFirstInRPIndex
  1319. --*/
  1320. {
  1321. HRESULT hr = S_OK;
  1322. CComPtr<IFsaScanItemPriv> pScanItem;
  1323. try {
  1324. WsbAssert(0 != ppScanItem, E_POINTER);
  1325. // Create an FsaScanItem that will scan for us.
  1326. WsbAffirmHr(CoCreateInstance(CLSID_CFsaScanItemNTFS, NULL, CLSCTX_SERVER, IID_IFsaScanItemPriv, (void**) &pScanItem));
  1327. // Scan starting at the specified path.
  1328. WsbAffirmHr(pScanItem->FindFirstInRPIndex((IFsaResource*) this, pSession));
  1329. // If we found something, then return the scan item.
  1330. WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItem, (void**) ppScanItem));
  1331. } WsbCatch(hr);
  1332. return(hr);
  1333. }
  1334. HRESULT
  1335. CFsaResource::FindFirstInDbIndex(
  1336. IN IHsmSession* pSession,
  1337. OUT IFsaScanItem** ppScanItem
  1338. )
  1339. /*++
  1340. Implements:
  1341. IFsaResource::FindFirstInDbIndex
  1342. --*/
  1343. {
  1344. HRESULT hr = S_OK;
  1345. CComPtr<IFsaScanItemPriv> pScanItem;
  1346. try {
  1347. WsbAssert(0 != ppScanItem, E_POINTER);
  1348. // Create an FsaScanItem that will scan for us.
  1349. WsbAffirmHr(CoCreateInstance(CLSID_CFsaScanItemNTFS, NULL, CLSCTX_SERVER, IID_IFsaScanItemPriv, (void**) &pScanItem));
  1350. // Scan starting at the specified path.
  1351. WsbAffirmHr(pScanItem->FindFirstInDbIndex((IFsaResource*) this, pSession));
  1352. // If we found something, then return the scan item.
  1353. WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItem, (void**) ppScanItem));
  1354. } WsbCatch(hr);
  1355. return(hr);
  1356. }
  1357. HRESULT
  1358. CFsaResource::FindNext(
  1359. IN IFsaScanItem* pScanItem
  1360. )
  1361. /*++
  1362. Implements:
  1363. IFsaResource::FindNext().
  1364. --*/
  1365. {
  1366. HRESULT hr = S_OK;
  1367. CComPtr<IFsaScanItemPriv> pPriv;
  1368. try {
  1369. WsbAssert(0 != pScanItem, E_POINTER);
  1370. // Continue the scan.
  1371. WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItemPriv, (void**) &pPriv))
  1372. WsbAffirmHr(pPriv->FindNext());
  1373. } WsbCatch(hr);
  1374. return(hr);
  1375. }
  1376. HRESULT
  1377. CFsaResource::FindNextInRPIndex(
  1378. IN IFsaScanItem* pScanItem
  1379. )
  1380. /*++
  1381. Implements:
  1382. IFsaResource::FindNextInRPIndex
  1383. --*/
  1384. {
  1385. HRESULT hr = S_OK;
  1386. CComPtr<IFsaScanItemPriv> pPriv;
  1387. try {
  1388. WsbAssert(0 != pScanItem, E_POINTER);
  1389. // Continue the scan.
  1390. WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItemPriv, (void**) &pPriv))
  1391. WsbAffirmHr(pPriv->FindNextInRPIndex());
  1392. } WsbCatch(hr);
  1393. return(hr);
  1394. }
  1395. HRESULT
  1396. CFsaResource::FindNextInDbIndex(
  1397. IN IFsaScanItem* pScanItem
  1398. )
  1399. /*++
  1400. Implements:
  1401. IFsaResource::FindNextInDbIndex
  1402. --*/
  1403. {
  1404. HRESULT hr = S_OK;
  1405. CComPtr<IFsaScanItemPriv> pPriv;
  1406. try {
  1407. WsbAssert(0 != pScanItem, E_POINTER);
  1408. // Continue the scan.
  1409. WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItemPriv, (void**) &pPriv))
  1410. WsbAffirmHr(pPriv->FindNextInDbIndex());
  1411. } WsbCatch(hr);
  1412. return(hr);
  1413. }
  1414. HRESULT
  1415. CFsaResource::FindFileId(
  1416. IN LONGLONG fileId,
  1417. IN IHsmSession* pSession,
  1418. OUT IFsaScanItem** ppScanItem
  1419. )
  1420. /*++
  1421. Implements:
  1422. IFsaResource::FindFileId().
  1423. Creates a scan item for the given file ID.
  1424. --*/
  1425. {
  1426. HRESULT hr = S_OK;
  1427. CComPtr<IFsaScanItemPriv> pScanItem;
  1428. CWsbStringPtr VolumePath;
  1429. CWsbStringPtr filePath;
  1430. HANDLE File = INVALID_HANDLE_VALUE;
  1431. HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
  1432. IO_STATUS_BLOCK IoStatusBlock;
  1433. NTSTATUS Status;
  1434. NTSTATUS GetNameStatus;
  1435. OBJECT_ATTRIBUTES ObjectAttributes;
  1436. UNICODE_STRING str;
  1437. PFILE_NAME_INFORMATION FileName;
  1438. DWORD pathSize;
  1439. OLECHAR *buffer = NULL;
  1440. WsbTraceIn(OLESTR("CFsaResource::FindFileId"), OLESTR("File ID = %I64x"), fileId);
  1441. try {
  1442. WsbAssert(0 != ppScanItem, E_POINTER);
  1443. // If we were passed an existing scan item (special internal code),
  1444. // use it; otherwise, create one.
  1445. if (NULL != *ppScanItem) {
  1446. WsbAffirmHr((*ppScanItem)->QueryInterface(IID_IFsaScanItemPriv,
  1447. (void**) &pScanItem));
  1448. } else {
  1449. WsbAffirmHr(CoCreateInstance(CLSID_CFsaScanItemNTFS, NULL,
  1450. CLSCTX_SERVER, IID_IFsaScanItemPriv, (void**) &pScanItem));
  1451. }
  1452. //
  1453. // Get the file path from the ID
  1454. //
  1455. //
  1456. // Open by File Reference Number (FileID),
  1457. // Relative opens from the Volume Handle.
  1458. //
  1459. VolumePath = L"\\\\.\\";
  1460. //VolumePath = L"";
  1461. WsbAffirmHr(VolumePath.Append(m_path));
  1462. ((OLECHAR *) VolumePath)[wcslen(VolumePath) - 1] = L'\0';
  1463. WsbTrace(OLESTR("CFsaResource::FindFileId - Volume path is <%ls>\n"),
  1464. static_cast<WCHAR*>(VolumePath));
  1465. VolumeHandle = CreateFileW( VolumePath,
  1466. GENERIC_READ,
  1467. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1468. NULL,
  1469. OPEN_EXISTING,
  1470. 0,
  1471. NULL );
  1472. WsbAffirmHandle(VolumeHandle);
  1473. RtlInitUnicodeString(&str, (WCHAR *) &fileId);
  1474. str.Length = 8;
  1475. str.MaximumLength = 8;
  1476. InitializeObjectAttributes( &ObjectAttributes,
  1477. &str,
  1478. OBJ_CASE_INSENSITIVE,
  1479. VolumeHandle,
  1480. NULL );
  1481. Status = NtCreateFile(&File,
  1482. FILE_READ_ATTRIBUTES,
  1483. &ObjectAttributes,
  1484. &IoStatusBlock,
  1485. NULL, // AllocationSize
  1486. FILE_ATTRIBUTE_NORMAL,
  1487. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1488. FILE_OPEN,
  1489. FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_BY_FILE_ID | FILE_OPEN_REPARSE_POINT,
  1490. NULL, // EaBuffer
  1491. 0);
  1492. WsbTrace(OLESTR("CFsaResource::FindFileId - NtCreateFile status = %lx\n"),
  1493. static_cast<LONG>(Status));
  1494. if (STATUS_INVALID_PARAMETER == Status) {
  1495. // This seems to be the error we get if the file is missing so
  1496. // we translate it to something our code will understand
  1497. WsbThrow(WSB_E_NOTFOUND);
  1498. }
  1499. WsbAffirmNtStatus(Status);
  1500. GetNameStatus = STATUS_BUFFER_OVERFLOW;
  1501. //
  1502. // Take a guess at the path length to start with
  1503. //
  1504. pathSize = 256 + sizeof(FILE_NAME_INFORMATION);
  1505. //
  1506. // Keep trying for the name until we get an error other than buffer overflow or success.
  1507. //
  1508. WsbAffirmPointer((buffer = (OLECHAR *) malloc(pathSize)));
  1509. do {
  1510. FileName = (PFILE_NAME_INFORMATION) buffer;
  1511. GetNameStatus = NtQueryInformationFile( File,
  1512. &IoStatusBlock,
  1513. FileName,
  1514. pathSize - sizeof(WCHAR), // leave room for the NULL we add
  1515. FileNameInformation );
  1516. WsbTrace(OLESTR("CFsaResource::FindFileId - NtQueryInformationFile status = %ld\n"),
  1517. static_cast<LONG>(GetNameStatus));
  1518. if (GetNameStatus == STATUS_BUFFER_OVERFLOW) {
  1519. pathSize += 256;
  1520. WsbAffirmPointer((buffer = (OLECHAR *) realloc(buffer, pathSize)));
  1521. }
  1522. } while (GetNameStatus == STATUS_BUFFER_OVERFLOW);
  1523. WsbAffirmNtStatus(GetNameStatus);
  1524. FileName->FileName[FileName->FileNameLength / sizeof(WCHAR)] = L'\0';
  1525. filePath = FileName->FileName;
  1526. // Scan starting at the specified path.
  1527. WsbAffirmHr(pScanItem->FindFirst((IFsaResource*) this, filePath, pSession));
  1528. // If we found something, then return the scan item.
  1529. WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItem, (void**) ppScanItem));
  1530. } WsbCatch(hr);
  1531. // Make sure we clean up
  1532. if (INVALID_HANDLE_VALUE != VolumeHandle) {
  1533. CloseHandle(VolumeHandle);
  1534. }
  1535. if (INVALID_HANDLE_VALUE != File) {
  1536. NtClose(File);
  1537. }
  1538. if (buffer != NULL) {
  1539. free(buffer);
  1540. }
  1541. WsbTraceOut(OLESTR("CFsaResource::FindFileId"), OLESTR("hr = <%ls>"),
  1542. WsbHrAsString(hr));
  1543. return(hr);
  1544. }
  1545. HRESULT
  1546. CFsaResource::FindObjectId(
  1547. IN LONGLONG objIdHi,
  1548. IN LONGLONG objIdLo,
  1549. IN IHsmSession* pSession,
  1550. OUT IFsaScanItem** ppScanItem
  1551. )
  1552. /*++
  1553. Implements:
  1554. IFsaResource::FindObjectId().
  1555. Creates a scan item for the given object Id.
  1556. --*/
  1557. {
  1558. HRESULT hr = S_OK;
  1559. CComPtr<IFsaScanItemPriv> pScanItem;
  1560. CWsbStringPtr VolumePath;
  1561. HANDLE File = INVALID_HANDLE_VALUE;
  1562. IO_STATUS_BLOCK IoStatusBlock;
  1563. NTSTATUS Status;
  1564. OBJECT_ATTRIBUTES ObjectAttributes;
  1565. LONG pathLength;
  1566. WCHAR unicodeStringBuffer[100];
  1567. UNICODE_STRING unicodeString;
  1568. FILE_INTERNAL_INFORMATION iInfo;
  1569. LONGLONG fileId;
  1570. WsbTraceIn(OLESTR("CFsaResource::FindObjectId"), OLESTR("Object ID = %I64x %I64x"), objIdHi, objIdLo);
  1571. try {
  1572. WsbAssert(0 != ppScanItem, E_POINTER);
  1573. // Create an FsaScanItem that will scan for us.
  1574. WsbAffirmHr(CoCreateInstance(CLSID_CFsaScanItemNTFS, NULL, CLSCTX_SERVER, IID_IFsaScanItemPriv, (void**) &pScanItem));
  1575. //
  1576. // Open by object ID
  1577. // Relative opens from the Volume Handle.
  1578. //
  1579. VolumePath = L"\\??\\";
  1580. //VolumePath = L"";
  1581. WsbAffirmHr(VolumePath.Append((WCHAR *) m_path));
  1582. WsbTrace(OLESTR("CFsaResource::FindObjectId - Volume path is %ws.\n"), (OLECHAR *) VolumePath);
  1583. WsbTrace(OLESTR("CFsaResource::FindObjectId - Object ID = %I64x %I64x.\n"), objIdHi, objIdLo);
  1584. pathLength = wcslen(VolumePath);
  1585. RtlInitUnicodeString(&unicodeString, unicodeStringBuffer);
  1586. unicodeString.Length = (USHORT)((pathLength * sizeof(WCHAR)) + (sizeof(LONGLONG) * 2));
  1587. RtlCopyMemory(&unicodeString.Buffer[0], VolumePath, pathLength * sizeof(WCHAR));
  1588. RtlCopyMemory(&unicodeString.Buffer[pathLength], &objIdHi, sizeof(LONGLONG));
  1589. RtlCopyMemory(&unicodeString.Buffer[pathLength + (sizeof(LONGLONG) / sizeof(WCHAR))], &objIdLo, sizeof(LONGLONG));
  1590. InitializeObjectAttributes( &ObjectAttributes,
  1591. &unicodeString,
  1592. OBJ_CASE_INSENSITIVE,
  1593. 0,
  1594. NULL );
  1595. WsbAffirmNtStatus(Status = NtCreateFile( &File,
  1596. FILE_READ_ATTRIBUTES,
  1597. &ObjectAttributes,
  1598. &IoStatusBlock,
  1599. NULL, // AllocationSize
  1600. FILE_ATTRIBUTE_NORMAL,
  1601. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1602. FILE_OPEN,
  1603. FILE_OPEN_BY_FILE_ID | FILE_OPEN_REPARSE_POINT,
  1604. NULL, // EaBuffer
  1605. 0 ));
  1606. //
  1607. // Get the file id from the object ID
  1608. //
  1609. WsbAffirmHr(NtQueryInformationFile(File, &IoStatusBlock, &iInfo, sizeof(FILE_INTERNAL_INFORMATION), FileInternalInformation));
  1610. fileId = iInfo.IndexNumber.QuadPart;
  1611. WsbAffirmNtStatus(NtClose(File));
  1612. File = INVALID_HANDLE_VALUE;
  1613. // Now open by file id.
  1614. WsbAffirmHr(FindFileId(fileId, pSession, ppScanItem));
  1615. } WsbCatch(hr);
  1616. // Make sure we clean up.
  1617. if (INVALID_HANDLE_VALUE != File) {
  1618. NtClose( File );
  1619. }
  1620. WsbTraceOut(OLESTR("CFsaResource::FindObjectId"), OLESTR("hr = <%ls>"),
  1621. WsbHrAsString(hr));
  1622. return(hr);
  1623. }
  1624. HRESULT
  1625. CFsaResource::GetAlternatePath(
  1626. OUT OLECHAR** pPath,
  1627. IN ULONG bufferSize
  1628. )
  1629. /*++
  1630. Implements:
  1631. IFsaResource::GetAlternatePath().
  1632. --*/
  1633. {
  1634. HRESULT hr = S_OK;
  1635. try {
  1636. WsbAssert(0 != pPath, E_POINTER);
  1637. WsbAffirmHr(m_alternatePath.CopyTo(pPath, bufferSize));
  1638. } WsbCatch(hr);
  1639. return(hr);
  1640. }
  1641. HRESULT
  1642. CFsaResource::GetClassID(
  1643. OUT CLSID* pClsid
  1644. )
  1645. /*++
  1646. Implements:
  1647. IPersist::GetClassID().
  1648. --*/
  1649. {
  1650. HRESULT hr = S_OK;
  1651. WsbTraceIn(OLESTR("CFsaResource::GetClassID"), OLESTR(""));
  1652. try {
  1653. WsbAssert(0 != pClsid, E_POINTER);
  1654. *pClsid = CLSID_CFsaResourceNTFS;
  1655. } WsbCatch(hr);
  1656. WsbTraceOut(OLESTR("CFsaResource::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid));
  1657. return(hr);
  1658. }
  1659. HRESULT
  1660. CFsaResource::GetDbPath(
  1661. OUT OLECHAR** pPath,
  1662. IN ULONG bufferSize
  1663. )
  1664. /*++
  1665. Implements:
  1666. IFsaResource::GetDbPath().
  1667. --*/
  1668. {
  1669. HRESULT hr = S_OK;
  1670. CWsbStringPtr tmpString;
  1671. WsbTraceIn(OLESTR("CFsaResource::GetDbPath"), OLESTR(""));
  1672. try {
  1673. WsbAssert(0 != pPath, E_POINTER);
  1674. // Use a relative path under the install directory.
  1675. WsbAffirmHr(m_pFsaServer->GetIDbPath(&tmpString, 0));
  1676. tmpString.Append(OLESTR("\\"));
  1677. tmpString.Append(WsbGuidAsString(m_id));
  1678. WsbAffirmHr(tmpString.CopyTo(pPath, bufferSize));
  1679. } WsbCatch(hr);
  1680. WsbTraceOut(OLESTR("CFsaResource::GetDbPath"), OLESTR("hr = <%ls>, path = <%ls)"),
  1681. WsbHrAsString(hr), WsbPtrToStringAsString(pPath));
  1682. return(hr);
  1683. }
  1684. HRESULT
  1685. CFsaResource::GetUnmanageDbPath(
  1686. OUT OLECHAR** pPath,
  1687. IN ULONG bufferSize
  1688. )
  1689. /*++
  1690. Implements:
  1691. IFsaResource::GetDbPath().
  1692. --*/
  1693. {
  1694. HRESULT hr = S_OK;
  1695. CWsbStringPtr tmpString;
  1696. WsbTraceIn(OLESTR("CFsaResource::GetUnmanageDbPath"), OLESTR(""));
  1697. try {
  1698. WsbAssert(0 != pPath, E_POINTER);
  1699. // Use a relative path under the install directory.
  1700. WsbAffirmHr(m_pFsaServer->GetUnmanageIDbPath(&tmpString, 0));
  1701. tmpString.Append(OLESTR("\\"));
  1702. tmpString.Append(UNMANAGE_DB_PREFIX);
  1703. tmpString.Append(WsbGuidAsString(m_id));
  1704. WsbAffirmHr(tmpString.CopyTo(pPath, bufferSize));
  1705. } WsbCatch(hr);
  1706. WsbTraceOut(OLESTR("CFsaResource::GetUnmanageDbPath"), OLESTR("hr = <%ls>, path = <%ls)"),
  1707. WsbHrAsString(hr), WsbPtrToStringAsString(pPath));
  1708. return(hr);
  1709. }
  1710. HRESULT
  1711. CFsaResource::GetDefaultRules(
  1712. OUT IWsbCollection** ppCollection
  1713. )
  1714. /*++
  1715. Implements:
  1716. IFsaResource::GetDefaultRules().
  1717. --*/
  1718. {
  1719. HRESULT hr = S_OK;
  1720. try {
  1721. WsbAssert(0 != ppCollection, E_POINTER);
  1722. *ppCollection = m_pDefaultRules;
  1723. m_pDefaultRules->AddRef();
  1724. } WsbCatch(hr);
  1725. return(hr);
  1726. }
  1727. HRESULT
  1728. CFsaResource::GetFreeLevel(
  1729. OUT ULONG* pLevel
  1730. )
  1731. /*++
  1732. Implements:
  1733. IFsaResource::GetFreeLevel().
  1734. --*/
  1735. {
  1736. HRESULT hr = S_OK;
  1737. LONGLONG total;
  1738. LONGLONG free;
  1739. try {
  1740. WsbAssert(0 != pLevel, E_POINTER);
  1741. // Get the capacities for this resource.
  1742. WsbAffirmHr(GetSizes(&total, &free, 0, 0));
  1743. *pLevel = (ULONG) (((double)free / (double)total) * (double)FSA_HSMLEVEL_100);
  1744. } WsbCatch(hr);
  1745. return(hr);
  1746. }
  1747. HRESULT
  1748. CFsaResource::GetFsName(
  1749. OUT OLECHAR** pFsName,
  1750. IN ULONG bufferSize
  1751. )
  1752. /*++
  1753. Implements:
  1754. IFsaResource::GetFsName().
  1755. --*/
  1756. {
  1757. HRESULT hr = S_OK;
  1758. try {
  1759. WsbAssert(0 != pFsName, E_POINTER);
  1760. WsbAffirmHr(m_fsName.CopyTo(pFsName, bufferSize));
  1761. } WsbCatch(hr);
  1762. return(hr);
  1763. }
  1764. HRESULT
  1765. CFsaResource::GetHsmEngine(
  1766. IHsmFsaTskMgr** ppEngine
  1767. )
  1768. /*++
  1769. Implements:
  1770. IFsaResource::GetHsmEngine().
  1771. --*/
  1772. {
  1773. HRESULT hr = S_OK;
  1774. CComPtr<IHsmServer> pHsmServer;
  1775. WsbTraceIn(OLESTR("CFsaResource::GetHsmEngine"), OLESTR(""));
  1776. try {
  1777. WsbAssert(0 != ppEngine, E_POINTER);
  1778. if (m_pHsmEngine != 0) {
  1779. //
  1780. // See if the connection is still valid
  1781. //
  1782. CComPtr<IHsmFsaTskMgr> pTestInterface;
  1783. hr = m_pHsmEngine->ContactOk();
  1784. if (hr != S_OK) {
  1785. // We don't have a valid
  1786. WsbTrace(OLESTR("CHsmServer::GetHsmEngine - Current connection invalid.\n"));
  1787. hr = S_OK;
  1788. m_pHsmEngine = 0;
  1789. }
  1790. }
  1791. // If we haven't already looked it up, then do so now.
  1792. if (m_pHsmEngine == 0) {
  1793. WsbAffirm(IsManaged() == S_OK, E_FAIL);
  1794. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, m_managingHsm, IID_IHsmServer, (void**) &pHsmServer));
  1795. WsbAffirmHr(pHsmServer->GetHsmFsaTskMgr(&m_pHsmEngine));
  1796. }
  1797. // Return the pointer that we have stored.
  1798. *ppEngine = m_pHsmEngine;
  1799. m_pHsmEngine->AddRef();
  1800. } WsbCatch(hr);
  1801. WsbTraceOut(OLESTR("CFsaResource::GetHsmEngine"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1802. return(hr);
  1803. }
  1804. HRESULT
  1805. CFsaResource::GetHsmLevel(
  1806. OUT ULONG* pLevel
  1807. )
  1808. /*++
  1809. Implements:
  1810. IFsaResource::GetHsmLevel().
  1811. --*/
  1812. {
  1813. HRESULT hr = S_OK;
  1814. try {
  1815. WsbAssert(0 != pLevel, E_POINTER);
  1816. *pLevel = m_hsmLevel;
  1817. } WsbCatch(hr);
  1818. return(hr);
  1819. }
  1820. HRESULT
  1821. CFsaResource::GetIdentifier(
  1822. OUT GUID* pId
  1823. )
  1824. /*++
  1825. Implements:
  1826. IFsaResource::GetIdentifier().
  1827. --*/
  1828. {
  1829. HRESULT hr = S_OK;
  1830. try {
  1831. WsbAssert(0 != pId, E_POINTER);
  1832. *pId = m_id;
  1833. } WsbCatch(hr);
  1834. return(hr);
  1835. }
  1836. HRESULT
  1837. CFsaResource::GetLogicalName(
  1838. OUT OLECHAR** pName,
  1839. IN ULONG bufferSize
  1840. )
  1841. /*++
  1842. Implements:
  1843. IFsaResource::GetLogicalName().
  1844. --*/
  1845. {
  1846. HRESULT hr = S_OK;
  1847. CWsbStringPtr tmpString;
  1848. CWsbStringPtr name;
  1849. try {
  1850. WsbAssert(0 != pName, E_POINTER);
  1851. WsbAssert(m_pFsaServer != 0, E_POINTER);
  1852. WsbAffirmHr(tmpString.TakeFrom(*pName, bufferSize));
  1853. try {
  1854. // This is an arbitrary choice for the naming convention. Nothing has been
  1855. // decided upon.
  1856. WsbAffirmHr(m_pFsaServer->GetLogicalName(&tmpString, 0));
  1857. WsbAffirmHr(GetPath(&name, 0));
  1858. //
  1859. // Strip off trailing \ if there
  1860. if (name[(int) wcslen((WCHAR *) name) - 1] == L'\\') {
  1861. name[(int) wcslen((WCHAR *) name) - 1] = L'\0';
  1862. }
  1863. WsbAffirmHr(tmpString.Append(OLESTR("\\")));
  1864. WsbAffirmHr(tmpString.Append(name));
  1865. } WsbCatch(hr);
  1866. WsbAffirmHr(tmpString.GiveTo(pName));
  1867. } WsbCatch(hr);
  1868. return(hr);
  1869. }
  1870. HRESULT
  1871. CFsaResource::GetManageableItemLogicalSize(
  1872. OUT LONGLONG* pSize
  1873. )
  1874. /*++
  1875. Implements:
  1876. IFsaResource::GetManageableItemLogicalSize().
  1877. --*/
  1878. {
  1879. HRESULT hr = S_OK;
  1880. try {
  1881. WsbAssert(0 != pSize, E_POINTER);
  1882. *pSize = m_manageableItemLogicalSize;
  1883. } WsbCatch(hr);
  1884. return(hr);
  1885. }
  1886. HRESULT
  1887. CFsaResource::GetManageableItemAccessTime(
  1888. OUT BOOL* pIsRelative,
  1889. OUT FILETIME* pTime
  1890. )
  1891. /*++
  1892. Implements:
  1893. IFsaResource::GetManageableItemAccessTime().
  1894. --*/
  1895. {
  1896. HRESULT hr = S_OK;
  1897. try {
  1898. WsbAssert(0 != pIsRelative, E_POINTER);
  1899. WsbAssert(0 != pTime, E_POINTER);
  1900. *pIsRelative = m_manageableItemAccessTimeIsRelative;
  1901. *pTime = m_manageableItemAccessTime;
  1902. } WsbCatch(hr);
  1903. return(hr);
  1904. }
  1905. HRESULT
  1906. CFsaResource::GetManagingHsm(
  1907. GUID* pId
  1908. )
  1909. /*++
  1910. Implements:
  1911. IFsaResource::GetManagingHsm().
  1912. --*/
  1913. {
  1914. HRESULT hr = S_OK;
  1915. try {
  1916. WsbAssert(0 != pId, E_POINTER);
  1917. *pId = m_managingHsm;
  1918. } WsbCatch(hr);
  1919. return(hr);
  1920. }
  1921. HRESULT
  1922. CFsaResource::GetName(
  1923. OUT OLECHAR** pName,
  1924. IN ULONG bufferSize
  1925. )
  1926. /*++
  1927. Implements:
  1928. IFsaResource::GetName().
  1929. --*/
  1930. {
  1931. HRESULT hr = S_OK;
  1932. WsbTraceIn(OLESTR("CFsaResource::GetName"), OLESTR(""));
  1933. try {
  1934. WsbAssert(0 != pName, E_POINTER);
  1935. WsbAffirmHr(m_name.CopyTo(pName, bufferSize));
  1936. } WsbCatch(hr);
  1937. WsbTraceOut(OLESTR("CFsaResource::GetName"), OLESTR("hr = <%ls>, name = <%ls>"),
  1938. WsbHrAsString(hr), (OLECHAR *)m_name);
  1939. return(hr);
  1940. }
  1941. HRESULT
  1942. CFsaResource::GetOldPath(
  1943. OUT OLECHAR** pPath,
  1944. IN ULONG bufferSize
  1945. )
  1946. /*++
  1947. Implements:
  1948. IFsaResource::GetOldPath().
  1949. --*/
  1950. {
  1951. HRESULT hr = S_OK;
  1952. try {
  1953. WsbAssert(0 != pPath, E_POINTER);
  1954. WsbAffirmHr(m_oldPath.CopyTo(pPath, bufferSize));
  1955. } WsbCatch(hr);
  1956. return(hr);
  1957. }
  1958. HRESULT
  1959. CFsaResource::GetPath(
  1960. OUT OLECHAR** pPath,
  1961. IN ULONG bufferSize
  1962. )
  1963. /*++
  1964. Implements:
  1965. IFsaResource::GetPath().
  1966. --*/
  1967. {
  1968. HRESULT hr = S_OK;
  1969. try {
  1970. WsbAssert(0 != pPath, E_POINTER);
  1971. WsbAffirmHr(m_path.CopyTo(pPath, bufferSize));
  1972. } WsbCatch(hr);
  1973. return(hr);
  1974. }
  1975. HRESULT
  1976. CFsaResource::GetStickyName(
  1977. OUT OLECHAR** pPath,
  1978. IN ULONG bufferSize
  1979. )
  1980. /*++
  1981. Implements:
  1982. IFsaResource::GetStickyName().
  1983. --*/
  1984. {
  1985. HRESULT hr = S_OK;
  1986. try {
  1987. WsbAssert(0 != pPath, E_POINTER);
  1988. WsbAffirmHr(m_stickyName.CopyTo(pPath, bufferSize));
  1989. } WsbCatch(hr);
  1990. return(hr);
  1991. }
  1992. HRESULT
  1993. CFsaResource::GetUserFriendlyName(
  1994. OUT OLECHAR** pPath,
  1995. IN ULONG bufferSize
  1996. )
  1997. /*++
  1998. Implements:
  1999. IFsaResource::GetUserFriendlyName().
  2000. --*/
  2001. {
  2002. HRESULT hr = S_OK;
  2003. try {
  2004. WsbAssert(0 != pPath, E_POINTER);
  2005. WsbAffirmHr(m_userName.CopyTo(pPath, bufferSize));
  2006. } WsbCatch(hr);
  2007. return(hr);
  2008. }
  2009. HRESULT
  2010. CFsaResource::GetPremigrated(
  2011. IN REFIID riid,
  2012. OUT void** ppDb
  2013. )
  2014. /*++
  2015. Implements:
  2016. IFsaResourcePriv::GetPremigrated
  2017. --*/
  2018. {
  2019. HRESULT hr = S_OK;
  2020. try {
  2021. WsbAssert(0 != ppDb, E_POINTER);
  2022. if (m_isDbInitialized) {
  2023. WsbAffirmHr(m_pPremigrated->QueryInterface(riid, ppDb));
  2024. hr = S_OK;
  2025. } else {
  2026. hr = WSB_E_RESOURCE_UNAVAILABLE;
  2027. }
  2028. } WsbCatch(hr);
  2029. return(hr);
  2030. }
  2031. HRESULT
  2032. CFsaResource::GetUnmanageDb(
  2033. IN REFIID riid,
  2034. OUT void** ppDb
  2035. )
  2036. /*++
  2037. Implements:
  2038. IFsaResourcePriv::GetUnmanageDb
  2039. --*/
  2040. {
  2041. HRESULT hr = S_OK;
  2042. try {
  2043. WsbAssert(0 != ppDb, E_POINTER);
  2044. if ((m_isUnmanageDbInitialized) && (m_pUnmanageDb != NULL)) {
  2045. WsbAffirmHr(m_pUnmanageDb->QueryInterface(riid, ppDb));
  2046. hr = S_OK;
  2047. } else {
  2048. hr = WSB_E_RESOURCE_UNAVAILABLE;
  2049. }
  2050. } WsbCatch(hr);
  2051. return(hr);
  2052. }
  2053. HRESULT
  2054. CFsaResource::GetSerial(
  2055. OUT ULONG *serial
  2056. )
  2057. /*++
  2058. Implements:
  2059. IFsaResourcePriv:GetSerial
  2060. --*/
  2061. {
  2062. HRESULT hr = S_OK;
  2063. WsbTraceIn(OLESTR("CFsaResource::GetSerial"), OLESTR(""));
  2064. try {
  2065. WsbAssert(0 != serial, E_POINTER);
  2066. *serial = m_serial;
  2067. } WsbCatch(hr);
  2068. WsbTraceOut(OLESTR("CFsaResource::GetSerial"), OLESTR("hr = <%ls>, Serial = %u"), WsbHrAsString(hr), m_serial);
  2069. return(hr);
  2070. }
  2071. HRESULT
  2072. CFsaResource::GetSizeMax(
  2073. OUT ULARGE_INTEGER* pSize
  2074. )
  2075. /*++
  2076. Implements:
  2077. IPersistStream::GetSizeMax().
  2078. --*/
  2079. {
  2080. HRESULT hr = S_OK;
  2081. CComPtr<IPersistStream> pPersistStream;
  2082. ULARGE_INTEGER entrySize;
  2083. WsbTraceIn(OLESTR("CFsaResource::GetSizeMax"), OLESTR(""));
  2084. try {
  2085. WsbAssert(0 != pSize, E_POINTER);
  2086. // Determine the size for a rule with no criteria.
  2087. pSize->QuadPart = WsbPersistSize((wcslen(m_name) + 1) * sizeof(OLECHAR)) +
  2088. WsbPersistSize((wcslen(m_fsName) + 1) * sizeof(OLECHAR)) +
  2089. WsbPersistSize((wcslen(m_path) + 1) * sizeof(OLECHAR)) +
  2090. WsbPersistSize((wcslen(m_alternatePath) + 1) * sizeof(OLECHAR)) +
  2091. 3 * WsbPersistSizeOf(LONGLONG) +
  2092. WsbPersistSizeOf(FILETIME) +
  2093. WsbPersistSizeOf(BOOL) +
  2094. 3 * WsbPersistSizeOf(ULONG) +
  2095. WsbPersistSizeOf(FSA_RESOURCE_COMPARE) +
  2096. 2 * WsbPersistSizeOf(GUID);
  2097. // Now allocate space for the default rules list.
  2098. WsbAffirmHr((m_pDefaultRules)->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  2099. WsbAffirmHr(pPersistStream->GetSizeMax(&entrySize));
  2100. pSize->QuadPart += entrySize.QuadPart;
  2101. pPersistStream = 0;
  2102. // Now allocate space for the premigration list.
  2103. WsbAffirmHr(((IWsbDb*)m_pPremigrated)->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  2104. WsbAffirmHr(pPersistStream->GetSizeMax(&entrySize));
  2105. pSize->QuadPart += entrySize.QuadPart;
  2106. pPersistStream = 0;
  2107. // Now allocate space for truncator.
  2108. WsbAffirmHr(m_pTruncator->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  2109. WsbAffirmHr(pPersistStream->GetSizeMax(&entrySize));
  2110. pSize->QuadPart += entrySize.QuadPart;
  2111. pPersistStream = 0;
  2112. } WsbCatch(hr);
  2113. WsbTraceOut(OLESTR("CFsaResource::GetSizeMax"), OLESTR("hr = <%ls>, Size = <%ls>"), WsbHrAsString(hr), WsbPtrToUliAsString(pSize));
  2114. return(hr);
  2115. }
  2116. HRESULT
  2117. CFsaResource::GetSizes(
  2118. OUT LONGLONG* pTotal,
  2119. OUT LONGLONG* pFree,
  2120. OUT LONGLONG* pPremigrated,
  2121. OUT LONGLONG* pTruncated
  2122. )
  2123. /*++
  2124. Implements:
  2125. IFsaResource::GetSizes().
  2126. --*/
  2127. {
  2128. HRESULT hr = S_OK;
  2129. CWsbStringPtr path;
  2130. ULARGE_INTEGER freeCaller;
  2131. ULARGE_INTEGER total;
  2132. ULARGE_INTEGER free;
  2133. try {
  2134. if ((0 != pTotal) || (0 != pFree)) {
  2135. WsbAffirmHr(GetPath(&path, 0));
  2136. WsbAffirmHr(path.Prepend("\\\\?\\"));
  2137. WsbAffirmStatus(GetDiskFreeSpaceEx(path, &freeCaller, &total, &free));
  2138. if (0 != pTotal) {
  2139. *pTotal = total.QuadPart;
  2140. }
  2141. if (0 != pFree) {
  2142. *pFree = free.QuadPart;
  2143. }
  2144. }
  2145. if (0 != pPremigrated) {
  2146. *pPremigrated = m_premigratedSize;
  2147. }
  2148. if (0 != pTruncated) {
  2149. *pTruncated = m_truncatedSize;
  2150. }
  2151. } WsbCatch(hr);
  2152. return(hr);
  2153. }
  2154. HRESULT
  2155. CFsaResource::GetTruncator(
  2156. IFsaTruncator** ppTruncator
  2157. )
  2158. /*++
  2159. Implements:
  2160. IFsaResource::GetTruncator().
  2161. --*/
  2162. {
  2163. HRESULT hr = S_OK;
  2164. try {
  2165. WsbAssert(0 != ppTruncator, E_POINTER);
  2166. // Return the pointer that we have stored.
  2167. *ppTruncator = m_pTruncator;
  2168. if (m_pTruncator != 0) {
  2169. m_pTruncator->AddRef();
  2170. }
  2171. } WsbCatch(hr);
  2172. return(hr);
  2173. }
  2174. HRESULT
  2175. CFsaResource::GetUncPath(
  2176. OUT OLECHAR** pPath,
  2177. IN ULONG bufferSize
  2178. )
  2179. /*++
  2180. Implements:
  2181. IFsaResource::GetUncPath().
  2182. // Returns system generated UNC path if there is one. If not it returns WSB_E_NOTFOUND
  2183. --*/
  2184. {
  2185. HRESULT hr = S_OK;
  2186. CWsbStringPtr tmpString;
  2187. OLECHAR driveName[3];
  2188. try {
  2189. WsbAssert(0 != pPath, E_POINTER);
  2190. // The path is either "d:\" where d is a drive letter or "Volume{GUID}" for an
  2191. // unnamed drive. So make sure we have at least that many characters.
  2192. //
  2193. if (wcslen(m_path) >= 3) {
  2194. // There is no system created UNC path to a volume without a drive letter so
  2195. // see if the path has form of "Volume{GUID}". For a volume with no drive letter we
  2196. // store this PNP (sticky) name as the path also.
  2197. if (wcsstr(m_path, OLESTR("Volume{")) != 0) {
  2198. WsbAffirmHr(tmpString.GiveTo(pPath)); // give caller an empty string back.
  2199. }
  2200. else {
  2201. // The UNC path is \\ssss\d$, where ssss is the server name and d is the drive
  2202. // letter.
  2203. WsbAffirmHr(tmpString.TakeFrom(*pPath, bufferSize));
  2204. WsbAffirmHr(m_pFsaServer->GetName(&tmpString, 0));
  2205. WsbAffirmHr(tmpString.Prepend(OLESTR("\\\\")));
  2206. WsbAffirmHr(tmpString.Append(OLESTR("\\")));
  2207. driveName[0] = m_path[0];
  2208. driveName[1] = L'$';
  2209. driveName[2] = 0;
  2210. WsbAffirmHr(tmpString.Append(driveName));
  2211. WsbAffirmHr(tmpString.GiveTo(pPath));
  2212. }
  2213. } else {
  2214. hr = WSB_E_NOTFOUND;
  2215. }
  2216. } WsbCatch(hr);
  2217. return(hr);
  2218. }
  2219. HRESULT
  2220. CFsaResource::GetUsnId(
  2221. OUT ULONGLONG *usnId
  2222. )
  2223. /*++
  2224. Implements:
  2225. IFsaResource::GetUsnId().
  2226. --*/
  2227. {
  2228. HRESULT hr = S_OK;
  2229. try {
  2230. WsbAssert(0 != usnId, E_POINTER);
  2231. *usnId = m_usnJournalId;
  2232. } WsbCatch(hr);
  2233. return(hr);
  2234. }
  2235. HRESULT
  2236. CFsaResource::Init(
  2237. IN IFsaServer* pFsaServer,
  2238. IN OLECHAR* path,
  2239. IN OLECHAR* dosName
  2240. )
  2241. /*++
  2242. Implements:
  2243. IFsaResourcePriv::Init().
  2244. Routine Description:
  2245. This routine implements the COM method for testing a resource to see if it is
  2246. 'manageable' by the HSM (Remote Storage) system. (Only NTFS-formatted
  2247. volumes which support sparse files and reparse points are considered to be
  2248. manageable by Sakkara.) If the resource is manageable, it initializes the
  2249. resource object.
  2250. Arguments:
  2251. pFsaServer - Interface pointer to the FSA service that is scanning this resource.
  2252. path - The long ugly PNP name that can be used if there is no drive letter for
  2253. the resource being tested (i.e., it is mounted as a volume without a
  2254. drive letter).
  2255. dosName - The drive letter (if there is one) of the resource being tested.
  2256. Return Value:
  2257. S_OK - The call succeeded (the resource being tested was found to be manageable,
  2258. and the resource object was initialized).
  2259. FSA_E_UNMANAGEABLE - Thrown if the resource being tested for manageability is
  2260. found to be unmanageable.
  2261. FSA_E_NOMEDIALOADED - Thrown if the resource being tested for manageability is
  2262. a removable type of drive and no media is presently loaded.
  2263. E_POINTER - Thrown if the path argument passed in is null.
  2264. Any other value - The call failed because one of the Remote Storage or Win32 API
  2265. calls contained internally in this method failed. The error value returned
  2266. is specific to the API call which failed.
  2267. --*/
  2268. {
  2269. HRESULT hr = FSA_E_UNMANAGABLE;
  2270. UINT type;
  2271. UINT lastErrorMode;
  2272. BOOL gotInfo = FALSE;
  2273. OLECHAR alternatePath[256];
  2274. CWsbStringPtr queryPath;
  2275. WsbTraceIn(OLESTR("CFsaResource::Init"), OLESTR("path = <%ls>, dosName = <%ls>"),
  2276. (OLECHAR *)path, (OLECHAR *)dosName);
  2277. try {
  2278. WsbAssert(0 != path, E_POINTER);
  2279. // Determine type of drive (removable, fixed, CD-ROM, RAM or network).
  2280. type = GetDriveType(path);
  2281. // Only FIXED or removable media are candidates for management
  2282. // (ignore network drives, ...).
  2283. //
  2284. // NOTE: For now, it has been decided not to allow removable media.
  2285. // if ((type == DRIVE_FIXED) || (type == DRIVE_REMOVABLE)) {
  2286. if (type == DRIVE_FIXED) {
  2287. // Get more information about the resource. For removable drives, we want to
  2288. // fail if no volume is located.
  2289. m_name.Realloc(128); // volume name
  2290. m_fsName.Realloc(128); // volume file system type (e.g., FAT, NTFS)
  2291. if (type == DRIVE_REMOVABLE) {
  2292. // Suppress OS message asking to install a volume in the drive if it is
  2293. // found to be missing.
  2294. // First get the current error-mode bit flags by clearing them.
  2295. lastErrorMode = SetErrorMode(0);
  2296. // Reset error-mode bit flags by 'or'ing them with the value which
  2297. // suppresses critical error messages.
  2298. SetErrorMode(lastErrorMode | SEM_FAILCRITICALERRORS);
  2299. gotInfo = GetVolumeInformation(path, m_name, 128, &m_serial,
  2300. &m_maxComponentLength, &m_fsFlags, m_fsName, 128);
  2301. // Got resource info, reset error-mode bit flags to original setting.
  2302. SetErrorMode(lastErrorMode);
  2303. // Throw and abort if no volume loaded.
  2304. WsbAffirm(gotInfo, FSA_E_NOMEDIALOADED);
  2305. } else { // if drive is a fixed drive type:
  2306. // This call can fail. This should just cause a message to be logged
  2307. // and the resource to be skipped.
  2308. try {
  2309. WsbAffirmStatus(GetVolumeInformation(path, m_name, 128, &m_serial,
  2310. &m_maxComponentLength, &m_fsFlags, m_fsName, 128));
  2311. } WsbCatchAndDo(hr,
  2312. WsbLogEvent(FSA_MESSAGE_RSCFAILEDINIT, 0, NULL, WsbHrAsString(hr),
  2313. WsbAbbreviatePath(path, 120), 0);
  2314. WsbThrow(FSA_E_UNMANAGABLE);
  2315. );
  2316. }
  2317. // Trace out info about the volume.
  2318. CWsbStringPtr traceString;
  2319. traceString = m_fsName;
  2320. traceString.Append(OLESTR(" file system, supports ... "));
  2321. // Note that MS removed support for Remote Storage bit flag.
  2322. if ((m_fsFlags & FILE_SUPPORTS_REPARSE_POINTS) != 0) {
  2323. traceString.Append(OLESTR("reparse points ... "));
  2324. }
  2325. if ((m_fsFlags & FILE_SUPPORTS_SPARSE_FILES) != 0) {
  2326. traceString.Append(OLESTR("sparse files ... "));
  2327. }
  2328. traceString.Append(OLESTR("\n"));
  2329. WsbTrace(traceString);
  2330. // Currently, we only support NTFS volumes that support sparse files and
  2331. // reparse points (since support for Remote Storage bit flag was removed).
  2332. if ((_wcsicmp(m_fsName, OLESTR("NTFS")) == 0) &&
  2333. ((m_fsFlags & FILE_SUPPORTS_SPARSE_FILES) != 0) &&
  2334. ((m_fsFlags & FILE_SUPPORTS_REPARSE_POINTS) != 0)) {
  2335. // Indicate this is a manageable volume.
  2336. hr = S_OK;
  2337. // Store the parent FSA, but since it is a weak reference, do not AddRef().
  2338. m_pFsaServer = pFsaServer;
  2339. // Store the "sticky" name - this is the long ugly PNP name that can be
  2340. // used if there is no drive letter. (skip the prefix - \\?\)
  2341. m_stickyName = &path[4];
  2342. // Store the path to the resource. Use the drive letter if it is present
  2343. // (dosName != NULL and contains drive letter), else store it to be the same as the "sticky name".
  2344. if (NULL != dosName) {
  2345. if ((wcslen(dosName) == 2) && (dosName[wcslen(dosName)-1] == L':')) {
  2346. m_path = dosName;
  2347. m_path.Append(OLESTR("\\"));
  2348. } else {
  2349. // It is a mount point path
  2350. m_path = &path[4];
  2351. }
  2352. } else {
  2353. m_path = &path[4];
  2354. }
  2355. WsbTrace(OLESTR("CFsaResource::Init - m_path = %ws\n"), (WCHAR *) m_path);
  2356. // Now save the "User Friendly" name for the resource. If there is a
  2357. // drive letter it is used. If it is an unnamed volume then there is
  2358. // no user friendly name and a NULL string is stored. The volume name
  2359. // should also be shown in this case.
  2360. if (NULL != dosName) {
  2361. m_userName = dosName;
  2362. m_userName.Append(OLESTR("\\"));
  2363. } else {
  2364. m_userName = L"";
  2365. }
  2366. WsbTrace(OLESTR("CFsaResource::Init - UserPath = %ws\n"), (WCHAR *) m_userName);
  2367. // Get the alternate path to the resource. This requires removing the '\'
  2368. // from the path.
  2369. queryPath = &path[4];
  2370. if (L'\\' == queryPath[(int) wcslen((WCHAR *) queryPath) - 1]) {
  2371. queryPath[(int) wcslen((WCHAR *) queryPath) - 1] = L'\0';
  2372. }
  2373. WsbTrace(OLESTR("CFsaResource::Init - QueryPath = %ws\n"),
  2374. (WCHAR *) queryPath);
  2375. WsbAffirm(QueryDosDevice(queryPath, alternatePath, 256) != 0,
  2376. HRESULT_FROM_WIN32(GetLastError()));
  2377. m_alternatePath = alternatePath;
  2378. //
  2379. // Get the unique id for the volume
  2380. //
  2381. WsbAffirmHr(ReadIdentifier());
  2382. }
  2383. }
  2384. m_isDirty = TRUE;
  2385. } WsbCatch(hr);
  2386. WsbTraceOut(OLESTR("CFsaResource::Init"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2387. return(hr);
  2388. }
  2389. HRESULT
  2390. CFsaResource::InitializePremigrationList(
  2391. BOOL bStartValidateJob
  2392. )
  2393. /*++
  2394. Routine Description:
  2395. If this volume is managed & active & available: create or
  2396. open the premigration-list DB; schedule a validate job if requested;
  2397. if recovery is also done, start the truncator running.
  2398. Arguments:
  2399. bStartValidateJob - If TRUE, schedule a validate job on this volume
  2400. if we just created a new DB
  2401. Return Value:
  2402. S_OK - The call succeeded.
  2403. S_FALSE - The actions were skipped because some condition was not met
  2404. E_* - An error occurred.
  2405. --*/
  2406. {
  2407. HRESULT hr = S_OK;
  2408. WsbTraceIn(OLESTR("CFsaResource::InitializePremigrationList"),
  2409. OLESTR("m_managingHsm = %ls, m_isActive = %ls, m_isAvailable = %ls, m_isDbInitialized = %ls, m_isRecovered = %ls"),
  2410. WsbGuidAsString(m_managingHsm), WsbBoolAsString(m_isActive),
  2411. WsbBoolAsString(m_isAvailable), WsbBoolAsString(m_isDbInitialized),
  2412. WsbBoolAsString(m_isRecovered));
  2413. try {
  2414. if ((S_OK == IsManaged()) && m_isActive && m_isAvailable) {
  2415. // Create/open the DB if not done already
  2416. if (!m_isDbInitialized) {
  2417. BOOL bCreated;
  2418. CWsbStringPtr dbPath;
  2419. CComPtr<IWsbDbSys> pDbSys;
  2420. WsbAffirmHr(m_pFsaServer->GetIDbSys(&pDbSys));
  2421. WsbAffirmHr(GetDbPath(&dbPath, 0));
  2422. WsbAffirmHr(m_pPremigrated->Init(dbPath, pDbSys, &bCreated));
  2423. m_isDbInitialized = TRUE;
  2424. if (bCreated) {
  2425. // Can't have recovery records if we just created
  2426. // the DB
  2427. m_isRecovered = TRUE;
  2428. }
  2429. if (bCreated && bStartValidateJob) {
  2430. LARGE_INTEGER ctime;
  2431. FILETIME curTime;
  2432. SYSTEMTIME sysTime;
  2433. CWsbStringPtr tmpString;
  2434. // Determine if the Engine is up and running. If it isn't
  2435. // we have to set a value in the registry that the Engine
  2436. // will find when it comes up and it will schedule the
  2437. // validate job. If the Engine is up, we can take care of
  2438. // scheduling the validate job ourselves. (If we don't, the
  2439. // Engine won't do it until the next time it starts up.)
  2440. hr = WsbCheckService(NULL, APPID_RemoteStorageEngine);
  2441. if (S_OK != hr) {
  2442. // "Schedule" a validate job to rebuild the premigration list.
  2443. // This is done by putting a value in the registry since the Engine
  2444. // may not be running right now so we can't set up a job.
  2445. WsbLogEvent(FSA_MESSAGE_PREMIGRATION_LIST_MISSING, 0, NULL,
  2446. (OLECHAR *) m_path, NULL);
  2447. WsbAffirmHr(tmpString.Alloc(32));
  2448. swprintf((OLECHAR *) tmpString, L"%x", m_serial);
  2449. GetSystemTime( &sysTime );
  2450. WsbAffirmStatus(SystemTimeToFileTime(&sysTime, &curTime));
  2451. ctime.LowPart = curTime.dwLowDateTime;
  2452. ctime.HighPart = curTime.dwHighDateTime;
  2453. WsbAffirmHr( WsbEnsureRegistryKeyExists( 0, FSA_VALIDATE_LOG_KEY_NAME ) );
  2454. WsbAffirmHr(WsbSetRegistryValueData(NULL, FSA_VALIDATE_LOG_KEY_NAME,
  2455. tmpString, (BYTE *) &ctime, sizeof(ctime)));
  2456. } else {
  2457. WsbAffirmHr(CheckForValidate(TRUE));
  2458. }
  2459. }
  2460. }
  2461. // Start the auto-truncator if recovery is done
  2462. if (m_pTruncator && m_isRecovered) {
  2463. // Try starting the truncator; ignore errors (we get one if
  2464. // truncator is already started)
  2465. m_pTruncator->Start((IFsaResource*) this);
  2466. }
  2467. }
  2468. } WsbCatch(hr);
  2469. WsbTraceOut(OLESTR("CFsaResource::InitializePremigrationList"), OLESTR("hr = <%ls>"),
  2470. WsbHrAsString(hr));
  2471. return(hr);
  2472. }
  2473. HRESULT
  2474. CFsaResource::InitializeUnmanageDb(
  2475. void
  2476. )
  2477. /*++
  2478. Implements:
  2479. IFsaResourcePriv::InitializeUnmanageDb().
  2480. --*/
  2481. {
  2482. HRESULT hr = S_OK;
  2483. WsbTraceIn(OLESTR("CFsaResource::InitializeUnmanageDb"),
  2484. OLESTR("m_isActive = %ls, m_isAvailable = %ls, m_isUnmanageDbInitialized = %ls"),
  2485. WsbBoolAsString(m_isActive), WsbBoolAsString(m_isAvailable), WsbBoolAsString(m_isUnmanageDbInitialized));
  2486. try {
  2487. if ((S_OK == IsManaged()) && m_isActive && m_isAvailable) {
  2488. if (! m_pUnmanageDb) {
  2489. WsbAffirmHr(CoCreateInstance(CLSID_CFsaUnmanageDb, NULL, CLSCTX_SERVER, IID_IFsaUnmanageDb, (void**) &m_pUnmanageDb));
  2490. }
  2491. if (! m_isUnmanageDbInitialized) {
  2492. BOOL bCreated;
  2493. CWsbStringPtr dbPath;
  2494. CComPtr<IWsbDbSys> pDbSys;
  2495. // Get (and init if necessary) the idb instance
  2496. WsbAffirmHr(m_pFsaServer->GetUnmanageIDbSys(&pDbSys));
  2497. // Initialize the db
  2498. WsbAffirmHr(GetUnmanageDbPath(&dbPath, 0));
  2499. WsbAffirmHr(m_pUnmanageDb->Init(dbPath, pDbSys, &bCreated));
  2500. // Init succeeded means DB must have been created
  2501. WsbAssert(bCreated, E_UNEXPECTED);
  2502. m_isUnmanageDbInitialized = TRUE;
  2503. }
  2504. } else {
  2505. hr = WSB_E_RESOURCE_UNAVAILABLE;
  2506. }
  2507. } WsbCatch(hr);
  2508. WsbTraceOut(OLESTR("CFsaResource::InitializeUnmanageDb"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2509. return(hr);
  2510. }
  2511. HRESULT
  2512. CFsaResource::TerminateUnmanageDb(
  2513. void
  2514. )
  2515. /*++
  2516. Implements:
  2517. IFsaResourcePriv::TerminateUnmanageDb().
  2518. --*/
  2519. {
  2520. HRESULT hr = S_OK;
  2521. WsbTraceIn(OLESTR("CFsaResource::TerminateUnmanageDb"),
  2522. OLESTR("m_isUnmanageDbInitialized = %ls"), WsbBoolAsString(m_isUnmanageDbInitialized));
  2523. try {
  2524. if (m_isUnmanageDbInitialized) {
  2525. WsbTrace(OLESTR("CFsaResource::TerminateUnmanageDb: Deleting Unmanage Db\n"));
  2526. hr = m_pUnmanageDb->Delete(NULL, IDB_DELETE_FLAG_NO_ERROR);
  2527. WsbTrace(OLESTR("CFsaResource::TerminateUnmanageDb: Deleting of Unmanage Db complete, hr = <%ls>\n"),
  2528. WsbHrAsString(hr));
  2529. if (SUCCEEDED(hr)) {
  2530. m_isUnmanageDbInitialized = FALSE;
  2531. m_pUnmanageDb = NULL;
  2532. }
  2533. }
  2534. } WsbCatch(hr);
  2535. WsbTraceOut(OLESTR("CFsaResource::TerminateUnmanageDb"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2536. return(hr);
  2537. }
  2538. HRESULT
  2539. CFsaResource::IsActive(
  2540. void
  2541. )
  2542. /*++
  2543. Implements:
  2544. IFsaResource::IsActive().
  2545. --*/
  2546. {
  2547. return(m_isActive ? S_OK : S_FALSE);
  2548. }
  2549. HRESULT
  2550. CFsaResource::IsAvailable(
  2551. void
  2552. )
  2553. /*++
  2554. Implements:
  2555. IFsaResource::IsAvailable().
  2556. --*/
  2557. {
  2558. return(m_isAvailable ? S_OK : S_FALSE);
  2559. }
  2560. HRESULT
  2561. CFsaResource::IsDeletePending(
  2562. void
  2563. )
  2564. /*++
  2565. Implements:
  2566. IFsaResource::IsDeletePending().
  2567. --*/
  2568. {
  2569. return(m_isDeletePending ? S_OK : S_FALSE);
  2570. }
  2571. HRESULT
  2572. CFsaResource::IsManaged(
  2573. void
  2574. )
  2575. /*++
  2576. Implements:
  2577. IFsaResource::IsManaged().
  2578. --*/
  2579. {
  2580. HRESULT hr = S_OK;
  2581. if (memcmp(&m_managingHsm, &GUID_NULL, sizeof(GUID)) == 0) {
  2582. hr = S_FALSE;
  2583. }
  2584. return(hr);
  2585. }
  2586. HRESULT
  2587. CFsaResource::Load(
  2588. IN IStream* pStream
  2589. )
  2590. /*++
  2591. Implements:
  2592. IPersistStream::Load().
  2593. --*/
  2594. {
  2595. HRESULT hr = S_OK;
  2596. CComPtr<IPersistStream> pPersistStream;
  2597. CComPtr<IWsbCollectable> pCollectable;
  2598. WsbTraceIn(OLESTR("CFsaResource::Load"), OLESTR(""));
  2599. try {
  2600. ULONG tmp;
  2601. WsbAssert(0 != pStream, E_POINTER);
  2602. // Do the easy stuff, but make sure that this order matches the order
  2603. // in the save method.
  2604. WsbAffirmHr(WsbLoadFromStream(pStream, &m_oldPath, 0));
  2605. WsbAffirmHr(WsbLoadFromStream(pStream, &m_alternatePath, 0));
  2606. WsbAffirmHr(WsbLoadFromStream(pStream, &m_name, 0));
  2607. WsbAffirmHr(WsbLoadFromStream(pStream, &m_stickyName, 0));
  2608. WsbAffirmHr(WsbLoadFromStream(pStream, &m_fsName, 0));
  2609. WsbAffirmHr(WsbLoadFromStream(pStream, &m_maxComponentLength));
  2610. WsbAffirmHr(WsbLoadFromStream(pStream, &m_fsFlags));
  2611. WsbAffirmHr(WsbLoadFromStream(pStream, &m_id));
  2612. WsbAffirmHr(WsbLoadFromStream(pStream, &m_isActive));
  2613. WsbAffirmHr(WsbLoadFromStream(pStream, &tmp));
  2614. m_compareBy = (FSA_RESOURCE_COMPARE)tmp;
  2615. WsbAffirmHr(WsbLoadFromStream(pStream, &m_managingHsm));
  2616. WsbAffirmHr(WsbLoadFromStream(pStream, &m_hsmLevel));
  2617. WsbAffirmHr(WsbLoadFromStream(pStream, &m_premigratedSize));
  2618. WsbAffirmHr(WsbLoadFromStream(pStream, &m_truncatedSize));
  2619. WsbAffirmHr(WsbLoadFromStream(pStream, &m_manageableItemLogicalSize));
  2620. WsbAffirmHr(WsbLoadFromStream(pStream, &m_manageableItemAccessTimeIsRelative));
  2621. WsbAffirmHr(WsbLoadFromStream(pStream, &m_manageableItemAccessTime));
  2622. WsbAffirmHr(WsbLoadFromStream(pStream, &m_usnJournalId));
  2623. WsbAffirmHr(WsbLoadFromStream(pStream, &m_lastUsnId));
  2624. // Load the default rules list
  2625. WsbAffirm(m_pDefaultRules != NULL, E_UNEXPECTED);
  2626. WsbAffirmHr((m_pDefaultRules)->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  2627. WsbAffirmHr(pPersistStream->Load(pStream));
  2628. pPersistStream = 0;
  2629. // Load the premigration list DB
  2630. WsbAffirm(m_pPremigrated != NULL, E_UNEXPECTED);
  2631. WsbAffirmHr(((IWsbDb*)m_pPremigrated)->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  2632. hr = pPersistStream->Load(pStream);
  2633. WsbTrace(OLESTR("CFsaResource::Load, DB load hr = <%ls>\n"), WsbHrAsString(hr));
  2634. if (S_OK == hr) {
  2635. m_isDbInitialized = TRUE;
  2636. } else {
  2637. m_isDbInitialized = FALSE;
  2638. hr = S_OK;
  2639. }
  2640. pPersistStream = 0;
  2641. // Load the truncator.
  2642. WsbAffirm(m_pTruncator != NULL, E_UNEXPECTED);
  2643. WsbAffirmHr(m_pTruncator->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  2644. WsbAffirmHr(pPersistStream->Load(pStream));
  2645. pPersistStream = 0;
  2646. } WsbCatch(hr);
  2647. WsbTraceOut(OLESTR("CFsaResource::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2648. return(hr);
  2649. }
  2650. HRESULT
  2651. CFsaResource::Manage(
  2652. IN IFsaScanItem* pScanItem,
  2653. IN LONGLONG /*offset*/,
  2654. IN LONGLONG /*size*/,
  2655. IN GUID storagePoolId,
  2656. IN BOOL truncate
  2657. )
  2658. /*++
  2659. Implements:
  2660. IFsaResource::Manage().
  2661. --*/
  2662. {
  2663. HRESULT hr = S_OK;
  2664. CComPtr<IFsaPostIt> pWorkItem;
  2665. CComPtr<IHsmFsaTskMgr> pEngine;
  2666. CComPtr<IHsmSession> pSession;
  2667. CWsbStringPtr tmpString;
  2668. LONGLONG fileVersionId;
  2669. LONGLONG requestSize;
  2670. WsbTraceIn(OLESTR("CFsaResource::Manage"), OLESTR(""));
  2671. try {
  2672. // Make sure the Scan Item interface is OK
  2673. WsbAssert(pScanItem != 0, E_POINTER);
  2674. WsbAffirmHr(CoCreateInstance(CLSID_CFsaPostIt, 0, CLSCTX_SERVER, IID_IFsaPostIt, (void**) &pWorkItem));
  2675. // Get the data from the scan item.
  2676. WsbAffirmHr(pScanItem->GetSession(&pSession));
  2677. WsbAffirmHr(pWorkItem->SetSession(pSession));
  2678. WsbAffirmHr(pScanItem->GetPathAndName(0, &tmpString, 0));
  2679. WsbAffirmHr(pScanItem->GetVersionId(&fileVersionId));
  2680. WsbAffirmHr(pWorkItem->SetFileVersionId(fileVersionId));
  2681. // Currently, we only can ask for the whole file.
  2682. WsbAffirmHr(pWorkItem->SetRequestOffset(0));
  2683. WsbAffirmHr(pScanItem->GetLogicalSize(&requestSize));
  2684. WsbAffirmHr(pWorkItem->SetRequestSize(requestSize));
  2685. // Fill in the rest of the work
  2686. WsbAffirmHr(pWorkItem->SetStoragePoolId(storagePoolId));
  2687. WsbAffirmHr(pWorkItem->SetRequestAction(FSA_REQUEST_ACTION_PREMIGRATE));
  2688. if (truncate) {
  2689. WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_TRUNCATE));
  2690. } else {
  2691. WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_LIST));
  2692. }
  2693. // Send the request to the task manager
  2694. WsbAffirmHr(GetHsmEngine(&pEngine));
  2695. WsbAffirmHr(pWorkItem->SetPath(tmpString));
  2696. WsbAffirmHr(pScanItem->PrepareForManage(0, requestSize));
  2697. WsbAffirmHr(pEngine->DoFsaWork(pWorkItem));
  2698. } WsbCatch(hr);
  2699. WsbTraceOut(OLESTR("CFsaResource::Manage"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2700. return(hr);
  2701. }
  2702. HRESULT
  2703. CFsaResource::ManagedBy(
  2704. IN GUID hsmId,
  2705. IN ULONG hsmLevel,
  2706. IN BOOL release
  2707. )
  2708. /*++
  2709. Implements:
  2710. IFsaResource::ManagedBy().
  2711. --*/
  2712. {
  2713. HRESULT hr = S_OK;
  2714. CComPtr<IHsmSession> pSession;
  2715. HANDLE threadHandle;
  2716. WsbTraceIn(OLESTR("CFsaResource::ManagedBy"), OLESTR("HsmId - <%ls>, hsmLevel - <%lu>, release = <%ls>"),
  2717. WsbGuidAsString(hsmId), hsmLevel, WsbBoolAsString(release));
  2718. try {
  2719. // Are we releasing or acquiring a managing HSM?
  2720. if (release) {
  2721. // We can only release if we are the orignal owner. This is to prevent two HSMs from thinking they
  2722. // manage the same resource at the same time. We may want a better way to do this.
  2723. WsbAffirm(memcmp(&m_managingHsm, &hsmId, sizeof(GUID)) == 0, FSA_E_RSCALREADYMANAGED);
  2724. // If the truncator is running, then ask it to stop.
  2725. WsbAffirmHr(m_pTruncator->GetSession(&pSession));
  2726. if (pSession != 0) {
  2727. WsbAffirmHr(pSession->ProcessEvent(HSM_JOB_PHASE_ALL, HSM_JOB_EVENT_CANCEL));
  2728. }
  2729. // Clear out the managing Hsm.
  2730. m_managingHsm = GUID_NULL;
  2731. m_pHsmEngine = 0;
  2732. m_isDeletePending = FALSE;
  2733. threadHandle = CreateThread(0, 0, FsaStartOnStateChange, (void*) this, 0, &g_ThreadId);
  2734. if (threadHandle != NULL) {
  2735. CloseHandle(threadHandle);
  2736. }
  2737. } else {
  2738. // Make sure there is a journal
  2739. // At this point we don't care about the need to
  2740. // validate
  2741. BOOL validateNeeded;
  2742. WsbAffirmHr(CheckForJournal(&validateNeeded));
  2743. // Is the id changing?
  2744. if (memcmp(&m_managingHsm, &hsmId, sizeof(GUID)) != 0) {
  2745. // Make sure that they set it to something valid.
  2746. WsbAssert(memcmp(&GUID_NULL, &hsmId, sizeof(GUID)) != 0, E_INVALIDARG);
  2747. // If the truncator is running, then ask it to stop.
  2748. WsbAffirmHr(m_pTruncator->GetSession(&pSession));
  2749. if (pSession != 0) {
  2750. WsbAffirmHr(pSession->ProcessEvent(HSM_JOB_PHASE_ALL, HSM_JOB_EVENT_CANCEL));
  2751. }
  2752. // Create/Recreate the default rules.
  2753. WsbAffirmHr(CreateDefaultRules());
  2754. // Store the Id and level.
  2755. m_managingHsm = hsmId;
  2756. m_hsmLevel = hsmLevel;
  2757. m_pHsmEngine = 0;
  2758. // Do recovery (if needed) and start truncator
  2759. if (m_isActive) {
  2760. if (m_isDbInitialized && !m_isRecovered) {
  2761. // DoRecovery will start truncator when it is done
  2762. WsbAffirmHr(DoRecovery());
  2763. } else {
  2764. WsbAffirmHr(InitializePremigrationList(TRUE));
  2765. }
  2766. }
  2767. threadHandle = CreateThread(0, 0, FsaStartOnStateChange, (void*) this, 0, &g_ThreadId);
  2768. if (threadHandle != NULL) {
  2769. CloseHandle(threadHandle);
  2770. }
  2771. } else {
  2772. BOOL DoKick = FALSE;
  2773. if (m_hsmLevel < hsmLevel) {
  2774. DoKick = TRUE;
  2775. }
  2776. m_hsmLevel = hsmLevel;
  2777. // Create/Recreate the default rules.
  2778. WsbAffirmHr(CreateDefaultRules());
  2779. // Wake up the AutoTruncator if the new level is higher
  2780. if (DoKick) {
  2781. WsbAffirmHr(m_pTruncator->KickStart());
  2782. }
  2783. }
  2784. }
  2785. m_isDirty = TRUE;
  2786. } WsbCatch(hr);
  2787. WsbTraceOut(OLESTR("CFsaResource::ManagedBy"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2788. return(hr);
  2789. }
  2790. HRESULT
  2791. CFsaResource::NeedsRepair(
  2792. void
  2793. )
  2794. /*++
  2795. Implements:
  2796. IFsaResource::NeedsRepair().
  2797. --*/
  2798. {
  2799. HRESULT hr = S_OK;
  2800. ULONG flag;
  2801. IO_STATUS_BLOCK Iosb;
  2802. CWsbStringPtr volumePath;
  2803. HANDLE volumeHandle = INVALID_HANDLE_VALUE;
  2804. WsbTraceIn(OLESTR("CFsaResource::NeedsRepair"), OLESTR(""));
  2805. try {
  2806. volumePath = L"\\\\.\\";
  2807. WsbAffirmHr(volumePath.Append(m_path));
  2808. ((OLECHAR *) volumePath)[wcslen(volumePath) - 1] = L'\0';
  2809. WsbAffirmHandle(volumeHandle = CreateFileW(volumePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL));
  2810. WsbAffirmNtStatus(NtFsControlFile(volumeHandle, NULL, NULL, NULL, &Iosb, FSCTL_IS_VOLUME_DIRTY, NULL, 0, &flag, sizeof(flag)));
  2811. WsbAffirmNtStatus(Iosb.Status);
  2812. if ((flag & VOLUME_IS_DIRTY) == 0) {
  2813. hr = S_FALSE;
  2814. }
  2815. } WsbCatch(hr);
  2816. if (INVALID_HANDLE_VALUE != volumeHandle) {
  2817. CloseHandle(volumeHandle);
  2818. }
  2819. WsbTraceOut(OLESTR("CFsaResource::NeedsRepair"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2820. return(hr);
  2821. }
  2822. HRESULT
  2823. CFsaResource::ProcessResult(
  2824. IN IFsaPostIt* pResult
  2825. )
  2826. /*++
  2827. Implements:
  2828. IFsaResource::ProcessResult().
  2829. --*/
  2830. {
  2831. HRESULT hr = S_OK;
  2832. CComPtr<IFsaScanItem> pScanItem;
  2833. CComPtr<IHsmSession> pSession;
  2834. FILETIME currentTime;
  2835. FSA_RESULT_ACTION resultAction = FSA_RESULT_ACTION_NONE;
  2836. FSA_PLACEHOLDER placeholder;
  2837. CWsbStringPtr path;
  2838. LONGLONG offset;
  2839. LONGLONG size;
  2840. ULONG mode;
  2841. HRESULT resultHr;
  2842. CComPtr<IFsaFilterRecall> pRecall;
  2843. ULONG completionSent = FALSE;
  2844. LONGLONG usn;
  2845. LONGLONG afterPhUsn;
  2846. WsbTraceIn(OLESTR("CFsaResource::ProcessResult"), OLESTR(""));
  2847. try {
  2848. BOOL wasPremigrated = FALSE;
  2849. BOOL wasTruncated = FALSE;
  2850. // Several of the actions need to know the current time, so calculate it now.
  2851. GetSystemTimeAsFileTime(&currentTime);
  2852. // Since the workItem session is IUnknown, QI for what we want.
  2853. WsbAffirmHr(pResult->GetSession(&pSession));
  2854. // Now perform the required action.
  2855. WsbAffirmHr(pResult->GetResultAction(&resultAction));
  2856. WsbAffirmHr(pResult->GetPlaceholder(&placeholder));
  2857. WsbAffirmHr(pResult->GetPath(&path, 0));
  2858. WsbAffirmHr(pResult->GetRequestOffset(&offset));
  2859. WsbAffirmHr(pResult->GetRequestSize(&size));
  2860. WsbAffirmHr(pResult->GetMode(&mode));
  2861. WsbAffirmHr(pResult->GetUSN(&usn));
  2862. WsbTrace(OLESTR("CFsaResource::ProcessResult, path = <%ls>, requestOffset = %I64d, requestSize = %I64d\n"),
  2863. WsbAbbreviatePath(path, 120), offset, size);
  2864. switch(resultAction) {
  2865. case FSA_RESULT_ACTION_DELETE:
  2866. WsbTrace(OLESTR("CFsaResource::ProcessResult - Delete\n"));
  2867. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  2868. if (S_OK == pScanItem->IsPremigrated(offset, size)) {
  2869. wasPremigrated = TRUE;
  2870. } else if (S_OK == pScanItem->IsTruncated(offset, size)) {
  2871. wasTruncated = TRUE;
  2872. }
  2873. WsbAffirmHr(pScanItem->Delete());
  2874. if (wasPremigrated) {
  2875. WsbAffirmHr(RemovePremigrated(pScanItem, offset, size));
  2876. } else if (wasTruncated) {
  2877. WsbAffirmHr(RemoveTruncated(pScanItem, offset, size));
  2878. }
  2879. break;
  2880. case FSA_RESULT_ACTION_DELETEPLACEHOLDER:
  2881. WsbTrace(OLESTR("CFsaResource::ProcessResult - Delete Placeholder\n"));
  2882. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  2883. // We shouldn't have gotten to here if the file isn't managed,
  2884. // but it's been known to happen
  2885. if (S_OK == pScanItem->IsManaged(offset, size)) {
  2886. HRESULT hrRemove = S_OK;
  2887. if (S_OK == pScanItem->IsPremigrated(offset, size)) {
  2888. wasPremigrated = TRUE;
  2889. } else if (S_OK == pScanItem->IsTruncated(offset, size)) {
  2890. wasTruncated = TRUE;
  2891. }
  2892. // RemovePremigrated needs to get some information from the placeholder, therefore, remove
  2893. // from premigrated db first and then (regardless of the result), delete the placeholder
  2894. if (wasPremigrated) {
  2895. hrRemove = RemovePremigrated(pScanItem, offset, size);
  2896. } else if (wasTruncated) {
  2897. hrRemove = RemoveTruncated(pScanItem, offset, size);
  2898. }
  2899. WsbAffirmHr(pScanItem->DeletePlaceholder(offset, size));
  2900. WsbAffirmHr(hrRemove);
  2901. }
  2902. // Remove the recovery record if we created one
  2903. if (m_isDbInitialized) {
  2904. BOOL bOpenDb = FALSE;
  2905. CComPtr<IWsbDbSession> pDbSession;
  2906. CComPtr<IFsaRecoveryRec> pRecRec;
  2907. try {
  2908. WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
  2909. bOpenDb = TRUE;
  2910. WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, RECOVERY_REC_TYPE,
  2911. IID_IFsaRecoveryRec, (void**) &pRecRec));
  2912. WsbAffirmHr(pRecRec->SetPath(path));
  2913. if (S_OK == pRecRec->FindEQ()) {
  2914. WsbAffirmHr(pRecRec->Remove());
  2915. }
  2916. } WsbCatch(hr);
  2917. if (bOpenDb) {
  2918. WsbAffirmHr(m_pPremigrated->Close(pDbSession));
  2919. }
  2920. }
  2921. break;
  2922. case FSA_RESULT_ACTION_LIST:
  2923. WsbTrace(OLESTR("CFsaResource::ProcessResult - Truncate / Add to Premigration List\n"));
  2924. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  2925. (placeholder).isTruncated = FALSE;
  2926. (placeholder).migrationTime = currentTime;
  2927. hr = pScanItem->CreatePlaceholder(offset, size, placeholder, TRUE, usn, &afterPhUsn);
  2928. if (SUCCEEDED(hr) && (FSA_E_REPARSE_NOT_WRITTEN_FILE_CHANGED != hr)) {
  2929. //
  2930. // Add the file to the premigration list. If this fails, log and error
  2931. // and request that the validation code be run to hopefully correct this
  2932. // problem. This problem should not stop processing, so return OK
  2933. //
  2934. hr = AddPremigrated(pScanItem, offset, size, FALSE, afterPhUsn);
  2935. if (!SUCCEEDED(hr)) {
  2936. WsbLogEvent(FSA_MESSAGE_FILE_NOT_IN_PREMIG_LIST, 0, NULL, WsbAbbreviatePath(path, 120), WsbHrAsString(hr), NULL);
  2937. //
  2938. // TBD - launch validate job
  2939. //
  2940. hr = S_OK;
  2941. }
  2942. //
  2943. // Tell the truncator that we have added something to the list in case we are over the level.
  2944. // This will kick start the truncator to insure quick response.
  2945. //
  2946. WsbAffirmHr(m_pTruncator->KickStart());
  2947. }
  2948. break;
  2949. case FSA_RESULT_ACTION_NONE:
  2950. WsbTrace(OLESTR("CFsaResource::ProcessResult - None\n"));
  2951. break;
  2952. case FSA_RESULT_ACTION_OPEN:
  2953. WsbTrace(OLESTR("CFsaResource::ProcessResult - Open (No longer placeholder)\n"));
  2954. // If it succeeded, then update the placeholder information.
  2955. WsbAffirmHr(pResult->GetResult(&resultHr));
  2956. WsbAffirmHr(pResult->GetFilterRecall(&pRecall));
  2957. WsbAssert(pRecall != 0, E_POINTER);
  2958. if (SUCCEEDED(resultHr)) {
  2959. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  2960. // The placeholder info is updated by the filter now.
  2961. // placeholder.recallTime = currentTime;
  2962. // placeholder.recallCount++;
  2963. // placeholder.isTruncated = FALSE;
  2964. // placeholder.truncateOnClose = FALSE;
  2965. // placeholder.premigrateOnClose = FALSE;
  2966. // WsbAffirmHr(pScanItem->CreatePlaceholder(offset, size, placeholder, TRUE, usn, &afterPhUsn));
  2967. }
  2968. // If it had succeeded, then add the file in the premigration list.
  2969. // (This used to be done after communicating with the filter to
  2970. // give the client time to open the file before the truncator would
  2971. // try to retruncate it. This is no longer needed since we do the
  2972. // recall on first I/O not on the open. Leaving that order created
  2973. // a new problem: the file would have a reparse point saying it was
  2974. // premigrated and test code could then try to retruncate it, but it
  2975. // wouldn't be in the premigration list yet.)
  2976. if (SUCCEEDED(resultHr)) {
  2977. //
  2978. // We do not need to fail the recall if we cannot add the file to the premigration list.
  2979. // Just log a warning, if appropriate, and continue
  2980. //
  2981. try {
  2982. WsbAffirmHr(RemoveTruncated(pScanItem, offset, size));
  2983. WsbAffirmHr(pScanItem->GetFileUsn(&afterPhUsn));
  2984. WsbAffirmHr(AddPremigrated(pScanItem, offset, size, TRUE, afterPhUsn));
  2985. } WsbCatchAndDo(hr,
  2986. //
  2987. // We failed to add it to the premigration list. In some cases this is not an error worth
  2988. // reporting. For instance, when a file is moved to another volume it is copied (causing a recall) and then
  2989. // deleted. We can get an error here if the delete is pending or has completed and the failure to
  2990. // add the original file to the premigration list is not an error since the file is now gone.
  2991. //
  2992. if ( (hr != WSB_E_NOTFOUND) &&
  2993. ((hr & ~(FACILITY_NT_BIT)) != STATUS_DELETE_PENDING) ) {
  2994. //
  2995. // Log all other errors
  2996. //
  2997. WsbLogEvent(FSA_MESSAGE_FILE_NOT_IN_PREMIG_LIST, 0, NULL,
  2998. (OLECHAR *) m_path, WsbQuickString(WsbHrAsString(hr)), NULL);
  2999. }
  3000. );
  3001. }
  3002. // Tell the filter that the recall attempt finished.
  3003. hr = pRecall->HasCompleted(resultHr);
  3004. completionSent = TRUE;
  3005. // Remove the recovery record if we created one
  3006. if (m_isDbInitialized) {
  3007. BOOL bOpenDb = FALSE;
  3008. CComPtr<IWsbDbSession> pDbSession;
  3009. CComPtr<IFsaRecoveryRec> pRecRec;
  3010. try {
  3011. WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
  3012. bOpenDb = TRUE;
  3013. WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, RECOVERY_REC_TYPE,
  3014. IID_IFsaRecoveryRec, (void**) &pRecRec));
  3015. WsbAffirmHr(pRecRec->SetPath(path));
  3016. if (S_OK == pRecRec->FindEQ()) {
  3017. WsbAffirmHr(pRecRec->Remove());
  3018. }
  3019. } WsbCatch(hr);
  3020. if (bOpenDb) {
  3021. WsbAffirmHr(m_pPremigrated->Close(pDbSession));
  3022. }
  3023. }
  3024. break;
  3025. case FSA_RESULT_ACTION_PEEK:
  3026. case FSA_RESULT_ACTION_REPARSE:
  3027. WsbTrace(OLESTR("CFsaResource::ProcessResult - Peek/Reparse\n"));
  3028. hr = E_NOTIMPL;
  3029. break;
  3030. case FSA_RESULT_ACTION_TRUNCATE:
  3031. WsbTrace(OLESTR("CFsaResource::ProcessResult - Truncate\n"));
  3032. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  3033. placeholder.isTruncated = FALSE;
  3034. placeholder.migrationTime = currentTime;
  3035. hr = pScanItem->CreatePlaceholder(offset, size, placeholder, TRUE, usn, &afterPhUsn);
  3036. if (SUCCEEDED(hr) && (FSA_E_REPARSE_NOT_WRITTEN_FILE_CHANGED != hr)) {
  3037. WsbAffirmHr(pScanItem->Truncate(offset, size));
  3038. }
  3039. break;
  3040. case FSA_RESULT_ACTION_REWRITEPLACEHOLDER:
  3041. WsbTrace(OLESTR("CFsaResource::ProcessResult - Rewrite Placeholder\n"));
  3042. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  3043. WsbAffirmHr(pScanItem->CreatePlaceholder(offset, size, placeholder, TRUE, usn, &afterPhUsn));
  3044. break;
  3045. case FSA_RESULT_ACTION_RECALLEDDATA:
  3046. WsbTrace(OLESTR("CFsaResource::ProcessResult - Recalled\n"));
  3047. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  3048. placeholder.isTruncated = FALSE;
  3049. placeholder.recallTime = currentTime;
  3050. placeholder.recallCount++;
  3051. WsbAffirmHr(pScanItem->CreatePlaceholder(offset, size, placeholder, TRUE, usn, &afterPhUsn));
  3052. WsbAffirmHr(RemoveTruncated(pScanItem, offset, size));
  3053. WsbAffirmHr(AddPremigrated(pScanItem, offset, size, FALSE, afterPhUsn));
  3054. // Remove the recovery record if we created one
  3055. if (m_isDbInitialized) {
  3056. BOOL bOpenDb = FALSE;
  3057. CComPtr<IWsbDbSession> pDbSession;
  3058. CComPtr<IFsaRecoveryRec> pRecRec;
  3059. try {
  3060. WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
  3061. bOpenDb = TRUE;
  3062. WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, RECOVERY_REC_TYPE,
  3063. IID_IFsaRecoveryRec, (void**) &pRecRec));
  3064. WsbAffirmHr(pRecRec->SetPath(path));
  3065. if (S_OK == pRecRec->FindEQ()) {
  3066. WsbAffirmHr(pRecRec->Remove());
  3067. }
  3068. } WsbCatch(hr);
  3069. if (bOpenDb) {
  3070. WsbAffirmHr(m_pPremigrated->Close(pDbSession));
  3071. }
  3072. }
  3073. break;
  3074. case FSA_RESULT_ACTION_NORECALL:
  3075. WsbTrace(OLESTR("CFsaResource::ProcessResult - Open without recall\n"));
  3076. // Tell the filter that the recall attempt finished.
  3077. WsbAffirmHr(pResult->GetResult(&resultHr));
  3078. WsbAffirmHr(pResult->GetFilterRecall(&pRecall));
  3079. WsbAssert(pRecall != 0, E_POINTER);
  3080. hr = pRecall->HasCompleted(resultHr);
  3081. completionSent = TRUE;
  3082. break;
  3083. case FSA_RESULT_ACTION_VALIDATE_BAD:
  3084. WsbTrace(OLESTR("CFsaResource::ProcessResult - Validate Bad\n"));
  3085. WsbAffirmHr(pResult->GetResult(&resultHr));
  3086. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  3087. if (S_OK == pScanItem->IsPremigrated(offset, size)) {
  3088. WsbLogEvent(FSA_MESSAGE_VALIDATE_UNMANAGED_FILE_ENGINE, 0, NULL, WsbAbbreviatePath(path, 120), (OLECHAR *)m_path, WsbHrAsString(resultHr), WsbQuickString(WsbHrAsString(resultHr)), NULL);
  3089. WsbAffirmHr(pScanItem->DeletePlaceholder(offset, size));
  3090. } else if (S_OK == pScanItem->IsTruncated(offset, size)) {
  3091. //
  3092. // We no longer delete bad placeholders here - let the diagnostic tool clean them up
  3093. // The message that is logged here has been changed to indicate that the file did not validate
  3094. // and will not be recallable until the problem is fixed.
  3095. //WsbAffirmHr(pScanItem->Delete());
  3096. WsbLogEvent(FSA_MESSAGE_VALIDATE_DELETED_FILE_ENGINE, 0, NULL, WsbAbbreviatePath(path, 120), (OLECHAR *) m_path, WsbHrAsString(resultHr), WsbQuickString(WsbHrAsString(resultHr)), NULL);
  3097. }
  3098. break;
  3099. case FSA_RESULT_ACTION_VALIDATE_OK:
  3100. WsbTrace(OLESTR("CFsaResource::ProcessResult - Validate OK\n"));
  3101. if (m_isDoingValidate) {
  3102. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  3103. if (S_OK == pScanItem->IsPremigrated(offset, size)) {
  3104. WsbAffirmHr(AddPremigrated(pScanItem, offset, size, FALSE, usn));
  3105. } else if (S_OK == pScanItem->IsTruncated(offset, size)) {
  3106. WsbAffirmHr(AddTruncated(pScanItem, offset, size));
  3107. }
  3108. }
  3109. break;
  3110. case FSA_RESULT_ACTION_VALIDATE_FOR_TRUNCATE_BAD:
  3111. WsbTrace(OLESTR("CFsaResource::ProcessResult - Validate for truncate Bad\n"));
  3112. //
  3113. // The file did not validate - make it back into a real file
  3114. //
  3115. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  3116. if (S_OK == pScanItem->IsPremigrated(offset, size)) {
  3117. WsbAffirmHr(pScanItem->DeletePlaceholder(offset, size));
  3118. }
  3119. break;
  3120. case FSA_RESULT_ACTION_VALIDATE_FOR_TRUNCATE_OK:
  3121. WsbTrace(OLESTR("CFsaResource::ProcessResult - Validate for truncate OK\n"));
  3122. //
  3123. // The file validated - go ahead and truncate it (if it has not changed)
  3124. //
  3125. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  3126. WsbAffirmHr(pScanItem->TruncateValidated(offset, size));
  3127. break;
  3128. default:
  3129. WsbAssert(FALSE, E_FAIL);
  3130. break;
  3131. }
  3132. } WsbCatchAndDo(hr,
  3133. if (completionSent == FALSE) {
  3134. switch(resultAction) {
  3135. //
  3136. //If it was a demand recall we must make all effort to let them know it failed
  3137. //
  3138. case FSA_RESULT_ACTION_OPEN:
  3139. case FSA_RESULT_ACTION_NORECALL:
  3140. WsbTrace(OLESTR("CFsaResource::ProcessResult - Open (No longer placeholder)\n"));
  3141. // Tell the filter that the recall attempt finished.
  3142. pRecall = 0; // Just in case we already had the interfae we deref it here.
  3143. hr = pResult->GetFilterRecall(&pRecall);
  3144. if (hr == S_OK) {
  3145. hr = pRecall->HasCompleted(E_FAIL);
  3146. }
  3147. break;
  3148. default:
  3149. break;
  3150. }
  3151. }
  3152. );
  3153. WsbTraceOut(OLESTR("CFsaResource::ProcessResult"), OLESTR("hr = %ls"), WsbHrAsString(hr));
  3154. return(hr);
  3155. }
  3156. HRESULT
  3157. CFsaResource::ReadIdentifier(
  3158. void
  3159. )
  3160. /*++
  3161. --*/
  3162. {
  3163. HRESULT hr = S_OK;
  3164. CWsbStringPtr tmpString;
  3165. HANDLE aHandle;
  3166. ULONG size;
  3167. UCHAR bytes[sizeof(m_id)];
  3168. PUCHAR bytePtr;
  3169. UCHAR buffer[sizeof(FILE_FS_VOLUME_INFORMATION)+MAX_PATH];
  3170. PFILE_FS_VOLUME_INFORMATION volInfo;
  3171. NTSTATUS status = STATUS_SUCCESS;
  3172. IO_STATUS_BLOCK ioStatus;
  3173. WCHAR * wString = NULL;
  3174. try {
  3175. //
  3176. // The identifier is composed of:
  3177. //
  3178. // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
  3179. // 0 0 0 0 <---------Volume Creation Time--------> <Volume Serial Number>
  3180. // We need to open a handle to the volume
  3181. //
  3182. tmpString = m_path;
  3183. WsbAffirmHr(tmpString.Prepend("\\\\?\\"));
  3184. tmpString.CopyTo(&wString);
  3185. //
  3186. // Remove trailing backslash in the path
  3187. //
  3188. wString[wcslen(wString)-1] = L'\0';
  3189. WsbAffirmHandle(aHandle = CreateFile(wString,
  3190. GENERIC_READ,
  3191. FILE_SHARE_READ | FILE_SHARE_WRITE,
  3192. 0,
  3193. OPEN_EXISTING,
  3194. FILE_ATTRIBUTE_NORMAL,
  3195. 0));
  3196. WsbFree(wString);
  3197. wString = NULL;
  3198. try {
  3199. volInfo = (PFILE_FS_VOLUME_INFORMATION) buffer;
  3200. bytePtr = bytes;
  3201. status = NtQueryVolumeInformationFile(
  3202. aHandle,
  3203. &ioStatus,
  3204. buffer,
  3205. sizeof(buffer),
  3206. FileFsVolumeInformation);
  3207. WsbAffirmNtStatus(status);
  3208. //
  3209. // Volume serial number forms the lower 4 bytes of the GUID
  3210. //
  3211. WsbAffirmHr(WsbConvertToBytes(bytePtr, volInfo->VolumeSerialNumber, &size));
  3212. WsbAffirm(size == sizeof(volInfo->VolumeSerialNumber), E_FAIL);
  3213. //
  3214. // Volume creation time forms the next 8 bytes
  3215. //
  3216. bytePtr += size;
  3217. WsbAffirmHr(WsbConvertToBytes(bytePtr, volInfo->VolumeCreationTime.QuadPart, &size));
  3218. WsbAffirm(size == sizeof(volInfo->VolumeCreationTime.QuadPart), E_FAIL);
  3219. //
  3220. // Next 4 bytes: 0's are good as any
  3221. //
  3222. bytePtr += size;
  3223. WsbAffirmHr(WsbConvertToBytes(bytePtr, (ULONG) 0, &size));
  3224. WsbAffirm(size == sizeof(ULONG), E_FAIL);
  3225. WsbAffirmHr(WsbConvertFromBytes(bytes, &m_id, &size));
  3226. WsbAffirm(size == sizeof(m_id), E_FAIL);
  3227. } WsbCatch(hr);
  3228. WsbAffirmStatus(CloseHandle(aHandle));
  3229. m_isDirty = TRUE;
  3230. } WsbCatch(hr);
  3231. return(hr);
  3232. }
  3233. HRESULT
  3234. CFsaResource::Recall(
  3235. IN IFsaScanItem* pScanItem,
  3236. IN LONGLONG offset,
  3237. IN LONGLONG size,
  3238. IN BOOL deletePlaceholder
  3239. )
  3240. /*++
  3241. Implements:
  3242. IFsaResource::Recall().
  3243. --*/
  3244. {
  3245. HRESULT hr = S_OK;
  3246. HRESULT hrFind;
  3247. CComPtr<IFsaPostIt> pWorkItem;
  3248. LONGLONG fileId;
  3249. CComPtr<IHsmFsaTskMgr> pEngine;
  3250. CComPtr<IHsmSession> pSession;
  3251. CComPtr<IWsbDbSession> pDbSession;
  3252. CComPtr<IFsaRecoveryRec> pRecRec;
  3253. CWsbStringPtr tmpString;
  3254. FSA_PLACEHOLDER placeholder;
  3255. LONGLONG fileVersionId;
  3256. WsbTraceIn(OLESTR("CFsaResource::Recall"), OLESTR(""));
  3257. try {
  3258. // Make sure the Scan Item interface is OK
  3259. WsbAssert(pScanItem != 0, E_FAIL);
  3260. WsbAffirmHr(CoCreateInstance(CLSID_CFsaPostIt, 0, CLSCTX_SERVER, IID_IFsaPostIt, (void**) &pWorkItem));
  3261. // Get the data from the scan item.
  3262. WsbAffirmHr(pScanItem->GetSession((IHsmSession**) &(pSession)));
  3263. WsbAffirmHr(pWorkItem->SetSession(pSession));
  3264. WsbAffirmHr(pScanItem->GetPathAndName(0, &tmpString, 0));
  3265. WsbAffirmHr(pWorkItem->SetPath(tmpString));
  3266. WsbAffirmHr(pWorkItem->SetRequestOffset(offset));
  3267. WsbAffirmHr(pWorkItem->SetRequestSize(size));
  3268. WsbAffirmHr(pScanItem->GetPlaceholder(offset, size, &placeholder));
  3269. WsbAffirmHr(pWorkItem->SetPlaceholder(&placeholder));
  3270. WsbAffirmHr(pScanItem->GetVersionId(&fileVersionId));
  3271. WsbAffirmHr(pWorkItem->SetFileVersionId(fileVersionId));
  3272. // Fill in the rest of the work
  3273. WsbAffirmHr(pWorkItem->SetRequestAction(FSA_REQUEST_ACTION_RECALL));
  3274. if (deletePlaceholder) {
  3275. WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_DELETEPLACEHOLDER));
  3276. } else {
  3277. WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_RECALLEDDATA));
  3278. }
  3279. // Send the request to the task manager. If the file was archived by someone other
  3280. // than the managing HSM, then that HSM will need to be looked up.
  3281. if ( GUID_NULL != m_managingHsm &&
  3282. memcmp(&m_managingHsm, &(placeholder.hsmId), sizeof(GUID)) == 0) {
  3283. WsbAffirmHr(GetHsmEngine(&pEngine));
  3284. } else {
  3285. CComPtr<IHsmServer> pHsmServer;
  3286. WsbAssertHr(HsmConnectFromId(HSMCONN_TYPE_HSM, placeholder.hsmId, IID_IHsmServer, (void**) &pHsmServer));
  3287. WsbAffirmHr(pHsmServer->GetHsmFsaTskMgr(&pEngine));
  3288. }
  3289. WsbAffirmHr(pScanItem->GetFileId(&fileId));
  3290. if (m_isDbInitialized) {
  3291. // Save a recovery record in case anything goes wrong
  3292. WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
  3293. WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, RECOVERY_REC_TYPE, IID_IFsaRecoveryRec, (void**) &pRecRec));
  3294. WsbAffirmHr(pRecRec->SetPath(tmpString));
  3295. // If the record already exists rewrite it, otherwise create a new record.
  3296. hrFind = pRecRec->FindEQ();
  3297. if (WSB_E_NOTFOUND == hrFind) {
  3298. WsbAffirmHr(pRecRec->MarkAsNew());
  3299. } else if (FAILED(hrFind)) {
  3300. WsbThrow(hrFind);
  3301. }
  3302. WsbAffirmHr(pRecRec->SetFileId(fileId));
  3303. WsbAffirmHr(pRecRec->SetOffsetSize(offset, size));
  3304. WsbAffirmHr(pRecRec->SetStatus(FSA_RECOVERY_FLAG_RECALLING));
  3305. WsbAffirmHr(pRecRec->Write());
  3306. }
  3307. try {
  3308. WsbAffirmHr(pEngine->DoFsaWork(pWorkItem));
  3309. } WsbCatchAndDo(hr,
  3310. // This FindEQ seems unnecessary, but we can't assume the
  3311. // the Remove will work
  3312. if (pRecRec) {
  3313. if (SUCCEEDED(pRecRec->FindEQ())) {
  3314. hr = pRecRec->Remove();
  3315. }
  3316. }
  3317. );
  3318. } WsbCatch(hr);
  3319. if (pDbSession != 0) {
  3320. m_pPremigrated->Close(pDbSession);
  3321. }
  3322. WsbTraceOut(OLESTR("CFsaResource::Recall"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3323. return(hr);
  3324. }
  3325. HRESULT
  3326. CFsaResource::RemovePremigrated(
  3327. IN IFsaScanItem* pScanItem,
  3328. IN LONGLONG offset,
  3329. IN LONGLONG size
  3330. )
  3331. /*++
  3332. Implements:
  3333. IFsaResource::RemovePremigrated().
  3334. --*/
  3335. {
  3336. HRESULT hr = S_OK;
  3337. CWsbStringPtr path;
  3338. CComPtr<IWsbDbSession> pDbSession;
  3339. CComPtr<IFsaPremigratedRec> pRec;
  3340. WsbTraceIn(OLESTR("CFsaResource::RemovePremigrated"), OLESTR(""));
  3341. try {
  3342. WsbAssert(0 != pScanItem, E_POINTER);
  3343. WsbAffirm(m_pPremigrated != NULL, E_UNEXPECTED);
  3344. // Open the database.
  3345. WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
  3346. // Protect the removal with Jet transaction since the auto-truncator thread
  3347. // may try to remove the same record at the same time
  3348. WsbAffirmHr(pDbSession->TransactionBegin());
  3349. try {
  3350. LONGLONG itemSize;
  3351. HRESULT hrTemp;
  3352. // Find the record using the bag/offsets key.
  3353. WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, PREMIGRATED_REC_TYPE, IID_IFsaPremigratedRec, (void**) &pRec));
  3354. WsbAffirmHr(pRec->UseKey(PREMIGRATED_BAGID_OFFSETS_KEY_TYPE));
  3355. WsbAffirmHr(pRec->SetFromScanItem(pScanItem, offset, size, FALSE));
  3356. // The record may already been deleted by the auto-truncator
  3357. hrTemp = pRec->FindEQ();
  3358. if (hrTemp == WSB_E_NOTFOUND) {
  3359. hr = S_OK;
  3360. WsbThrow(hr);
  3361. }
  3362. WsbAffirmHr(hrTemp);
  3363. WsbAffirmHr(pRec->GetSize(&itemSize));
  3364. // the record may be involved with another transaction with delete pending
  3365. hrTemp = pRec->Remove();
  3366. if (hrTemp == WSB_E_IDB_UPDATE_CONFLICT) {
  3367. hr = S_OK;
  3368. WsbThrow(hr);
  3369. }
  3370. WsbAffirmHr(hrTemp);
  3371. // Remove the size of the section from the amount of premigrated data.
  3372. RemovePremigratedSize(itemSize);
  3373. m_isDirty = TRUE;
  3374. } WsbCatch(hr);
  3375. WsbAffirmHr(pDbSession->TransactionEnd());
  3376. WsbAffirmHr(m_pPremigrated->Close(pDbSession));
  3377. } WsbCatch(hr);
  3378. WsbTraceOut(OLESTR("CFsaResource::RemovePremigrated"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3379. return(hr);
  3380. }
  3381. HRESULT
  3382. CFsaResource::RemoveTruncated(
  3383. IN IFsaScanItem* /*pScanItem*/,
  3384. IN LONGLONG /*offset*/,
  3385. IN LONGLONG size
  3386. )
  3387. /*++
  3388. Implements:
  3389. IFsaResource::RemoveTruncated().
  3390. --*/
  3391. {
  3392. HRESULT hr = S_OK;
  3393. WsbTraceIn(OLESTR("CFsaResource::RemoveTruncated"), OLESTR(""));
  3394. try {
  3395. WsbAffirmHr(RemoveTruncatedSize(size));
  3396. } WsbCatch(hr);
  3397. WsbTraceOut(OLESTR("CFsaResource::RemoveTruncated"),
  3398. OLESTR("hr = <%ls>, m_truncatedSize = %I64d"), WsbHrAsString(hr),
  3399. m_truncatedSize);
  3400. return(hr);
  3401. }
  3402. HRESULT
  3403. CFsaResource::RemoveTruncatedSize(
  3404. IN LONGLONG size
  3405. )
  3406. /*++
  3407. Implements:
  3408. IFsaResource::RemoveTruncatedSize().
  3409. --*/
  3410. {
  3411. HRESULT hr = S_OK;
  3412. WsbTraceIn(OLESTR("CFsaResource::RemoveTruncatedSize"), OLESTR(""));
  3413. try {
  3414. m_truncatedSize = max(0, m_truncatedSize - size);
  3415. m_isDirty = TRUE;
  3416. } WsbCatch(hr);
  3417. WsbTraceOut(OLESTR("CFsaResource::RemoveTruncatedSize"),
  3418. OLESTR("hr = <%ls>, m_truncatedSize = %I64d"), WsbHrAsString(hr),
  3419. m_truncatedSize);
  3420. return(hr);
  3421. }
  3422. HRESULT
  3423. CFsaResource::RemovePremigratedSize(
  3424. IN LONGLONG size
  3425. )
  3426. /*++
  3427. Implements:
  3428. IFsaResourcePriv::RemovePremigratedSize().
  3429. --*/
  3430. {
  3431. WsbTraceIn(OLESTR("CFsaResource::RemovePremigratedSize"),
  3432. OLESTR("m_premigratedSize = %I64d"), m_premigratedSize);
  3433. m_isDirty = TRUE;
  3434. if (size > m_premigratedSize) {
  3435. m_premigratedSize = 0;
  3436. } else {
  3437. m_premigratedSize -= size;
  3438. }
  3439. WsbTraceOut(OLESTR("CFsaResource::RemovePremigratedSize"),
  3440. OLESTR("m_premigratedSize = %I64d"), m_premigratedSize);
  3441. return(S_OK);
  3442. }
  3443. HRESULT
  3444. CFsaResource::Save(
  3445. IN IStream* pStream,
  3446. IN BOOL clearDirty
  3447. )
  3448. /*++
  3449. Implements:
  3450. IPersistStream::Save().
  3451. --*/
  3452. {
  3453. HRESULT hr = S_OK;
  3454. CComPtr<IPersistStream> pPersistStream;
  3455. WsbTraceIn(OLESTR("CFsaResource::Save"), OLESTR("clearDirty = <%ls>"),
  3456. WsbBoolAsString(clearDirty));
  3457. try {
  3458. WsbAssert(0 != pStream, E_POINTER);
  3459. // Do the easy stuff, but make sure that this order matches the order
  3460. // in the Load() method.
  3461. // Save the path by which this resource is/was last known. Note the
  3462. // Load() method reads it back into the resource's 'm_oldPath' field.
  3463. if ( m_path == NULL ) {
  3464. WsbAffirmHr(WsbSaveToStream(pStream, m_oldPath));
  3465. }
  3466. else {
  3467. WsbAffirmHr(WsbSaveToStream(pStream, m_path));
  3468. }
  3469. WsbAffirmHr(WsbSaveToStream(pStream, m_alternatePath));
  3470. WsbAffirmHr(WsbSaveToStream(pStream, m_name));
  3471. WsbAffirmHr(WsbSaveToStream(pStream, m_stickyName));
  3472. WsbAffirmHr(WsbSaveToStream(pStream, m_fsName));
  3473. WsbAffirmHr(WsbSaveToStream(pStream, m_maxComponentLength));
  3474. WsbAffirmHr(WsbSaveToStream(pStream, m_fsFlags));
  3475. WsbAffirmHr(WsbSaveToStream(pStream, m_id));
  3476. WsbAffirmHr(WsbSaveToStream(pStream, m_isActive));
  3477. WsbAffirmHr(WsbSaveToStream(pStream, (ULONG) m_compareBy));
  3478. WsbAffirmHr(WsbSaveToStream(pStream, m_managingHsm));
  3479. WsbAffirmHr(WsbSaveToStream(pStream, m_hsmLevel));
  3480. WsbAffirmHr(WsbSaveToStream(pStream, m_premigratedSize));
  3481. WsbAffirmHr(WsbSaveToStream(pStream, m_truncatedSize));
  3482. WsbAffirmHr(WsbSaveToStream(pStream, m_manageableItemLogicalSize));
  3483. WsbAffirmHr(WsbSaveToStream(pStream, m_manageableItemAccessTimeIsRelative));
  3484. WsbAffirmHr(WsbSaveToStream(pStream, m_manageableItemAccessTime));
  3485. WsbAffirmHr(WsbSaveToStream(pStream, m_usnJournalId));
  3486. WsbAffirmHr(WsbSaveToStream(pStream, m_lastUsnId));
  3487. // Save off the default rules.
  3488. WsbAffirmHr(m_pDefaultRules->QueryInterface(IID_IPersistStream,
  3489. (void**) &pPersistStream));
  3490. WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
  3491. pPersistStream = 0;
  3492. // Save off the premigration list.
  3493. WsbAffirmHr(((IWsbDb*)m_pPremigrated)->QueryInterface(IID_IPersistStream,
  3494. (void**) &pPersistStream));
  3495. WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
  3496. pPersistStream = 0;
  3497. // Save off the truncator.
  3498. WsbAffirmHr(m_pTruncator->QueryInterface(IID_IPersistStream,
  3499. (void**) &pPersistStream));
  3500. WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
  3501. pPersistStream = 0;
  3502. // If we got it saved and we were asked to clear the dirty bit, then
  3503. // do so now.
  3504. if (clearDirty) {
  3505. m_isDirty = FALSE;
  3506. }
  3507. } WsbCatch(hr);
  3508. WsbTraceOut(OLESTR("CFsaResource::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3509. return(hr);
  3510. }
  3511. HRESULT
  3512. CFsaResource::SetAlternatePath(
  3513. IN OLECHAR* path
  3514. )
  3515. /*++
  3516. Implements:
  3517. IFsaResourcePriv::SetAlternatePath().
  3518. --*/
  3519. {
  3520. HRESULT hr = S_OK;
  3521. try {
  3522. WsbAssert(0 != path, E_POINTER);
  3523. m_alternatePath = path;
  3524. m_isDirty = TRUE;
  3525. } WsbCatch(hr);
  3526. return(hr);
  3527. }
  3528. HRESULT
  3529. CFsaResource::SetHsmLevel(
  3530. IN ULONG level
  3531. )
  3532. /*++
  3533. Implements:
  3534. IFsaResource::SetHsmLevel().
  3535. --*/
  3536. {
  3537. BOOL DoKick = FALSE;
  3538. HRESULT hr = S_OK;
  3539. WsbTraceIn(OLESTR("CFsaResource::SetHsmLevel"),
  3540. OLESTR("current level = %lx, new level = %lx"), m_hsmLevel, level);
  3541. if (m_hsmLevel < level) {
  3542. DoKick = TRUE;
  3543. }
  3544. m_hsmLevel = level;
  3545. // Wake up the AutoTruncator if the new level is higher
  3546. if (DoKick) {
  3547. WsbAffirmHr(m_pTruncator->KickStart());
  3548. }
  3549. m_isDirty = TRUE;
  3550. WsbTraceOut(OLESTR("CFsaResource::SetHsmLevel"), OLESTR("hr = <%ls>"),
  3551. WsbHrAsString(hr));
  3552. return(hr);
  3553. }
  3554. HRESULT
  3555. CFsaResource::SetIdentifier(
  3556. IN GUID id
  3557. )
  3558. /*++
  3559. Implements:
  3560. IFsaResourcePriv::SetIdentifier().
  3561. --*/
  3562. {
  3563. HRESULT hr = S_OK;
  3564. m_id = id;
  3565. m_isDirty = TRUE;
  3566. return(hr);
  3567. }
  3568. HRESULT
  3569. CFsaResource::SetIsActive(
  3570. BOOL isActive
  3571. )
  3572. /*++
  3573. Implements:
  3574. IFsaResource::SetIsActive().
  3575. --*/
  3576. {
  3577. HRESULT hr = S_OK;
  3578. CComPtr<IHsmSession> pSession;
  3579. WsbTraceIn(OLESTR("CFsaResource::SetIsActive"), OLESTR(""));
  3580. // If the flag is changing values, then we may need to do something to the truncator.
  3581. try {
  3582. if (m_isActive != isActive) {
  3583. // Change the flag.
  3584. m_isActive = isActive;
  3585. // If we are becoming active, then we need to start the truncator. Otherwise we need to stop it.
  3586. if (m_isActive) {
  3587. // If we are managed & done with recovery, then the truncator should be running.
  3588. if (IsManaged() == S_OK && m_isRecovered) {
  3589. // Try to start the truncator
  3590. WsbAffirmHr(InitializePremigrationList(TRUE));
  3591. }
  3592. } else {
  3593. // If the truncator is running, then ask it to stop.
  3594. WsbAffirmHr(m_pTruncator->GetSession(&pSession));
  3595. if (pSession != 0) {
  3596. WsbAffirmHr(pSession->ProcessEvent(HSM_JOB_PHASE_ALL, HSM_JOB_EVENT_CANCEL));
  3597. }
  3598. }
  3599. } else {
  3600. m_isActive = isActive;
  3601. }
  3602. m_isDirty = TRUE;
  3603. } WsbCatch( hr );
  3604. WsbTraceOut(OLESTR("CFsaResource::SetIsActive"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3605. return(hr);
  3606. }
  3607. HRESULT
  3608. CFsaResource::SetIsAvailable(
  3609. BOOL isAvailable
  3610. )
  3611. /*++
  3612. Implements:
  3613. IFsaResource::SetIsAvailable().
  3614. --*/
  3615. {
  3616. HRESULT hr = S_OK;
  3617. WsbTraceIn(OLESTR("CFsaResource::SetIsAvailable"), OLESTR(""));
  3618. // Change the flag.
  3619. m_isAvailable = isAvailable;
  3620. WsbTraceOut(OLESTR("CFsaResource::SetIsAvailable"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3621. return(hr);
  3622. }
  3623. HRESULT
  3624. CFsaResource::SetIsDeletePending(
  3625. BOOL isDeletePending
  3626. )
  3627. /*++
  3628. Implements:
  3629. IFsaResource::SetIsDeletePending().
  3630. --*/
  3631. {
  3632. HRESULT hr = S_OK;
  3633. HANDLE threadHandle;
  3634. WsbTraceIn(OLESTR("CFsaResource::SetIsDeletePending"), OLESTR(""));
  3635. // Change the flag.
  3636. m_isDeletePending = isDeletePending;
  3637. threadHandle = CreateThread(0, 0, FsaStartOnStateChange, (void*) this, 0, &g_ThreadId);
  3638. if (threadHandle != NULL) {
  3639. CloseHandle(threadHandle);
  3640. }
  3641. WsbTraceOut(OLESTR("CFsaResource::SetIsDeletePending"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3642. return(hr);
  3643. }
  3644. HRESULT
  3645. CFsaResource::SetManageableItemLogicalSize(
  3646. IN LONGLONG size
  3647. )
  3648. /*++
  3649. Implements:
  3650. IFsaResource::SetManageableItemLogicalSize().
  3651. --*/
  3652. {
  3653. m_manageableItemLogicalSize = size;
  3654. return(S_OK);
  3655. }
  3656. HRESULT
  3657. CFsaResource::SetManageableItemAccessTime(
  3658. IN BOOL isRelative,
  3659. IN FILETIME time
  3660. )
  3661. /*++
  3662. Implements:
  3663. IFsaResource::SetManageableItemAccessTime().
  3664. --*/
  3665. {
  3666. m_manageableItemAccessTimeIsRelative = isRelative;
  3667. m_manageableItemAccessTime = time;
  3668. return(S_OK);
  3669. }
  3670. HRESULT
  3671. CFsaResource::SetName(
  3672. IN OLECHAR* name
  3673. )
  3674. /*++
  3675. Implements:
  3676. IFsaResourcePriv::SetName().
  3677. --*/
  3678. {
  3679. HRESULT hr = S_OK;
  3680. try {
  3681. WsbAssert(0 != name, E_POINTER);
  3682. m_name = name;
  3683. m_isDirty = TRUE;
  3684. } WsbCatch(hr);
  3685. return(hr);
  3686. }
  3687. HRESULT
  3688. CFsaResource::SetOldPath(
  3689. IN OLECHAR* oldPath
  3690. )
  3691. /*++
  3692. Implements:
  3693. IFsaResourcePriv::SetOldPath().
  3694. --*/
  3695. {
  3696. HRESULT hr = S_OK;
  3697. try {
  3698. WsbAssert(0 != oldPath, E_POINTER);
  3699. m_oldPath = oldPath;
  3700. m_isDirty = TRUE;
  3701. } WsbCatch(hr);
  3702. return(hr);
  3703. }
  3704. HRESULT
  3705. CFsaResource::SetPath(
  3706. IN OLECHAR* path
  3707. )
  3708. /*++
  3709. Implements:
  3710. IFsaResourcePriv::SetPath().
  3711. --*/
  3712. {
  3713. HRESULT hr = S_OK;
  3714. try {
  3715. WsbAssert(0 != path, E_POINTER);
  3716. m_path = path;
  3717. m_isDirty = TRUE;
  3718. } WsbCatch(hr);
  3719. return(hr);
  3720. }
  3721. HRESULT
  3722. CFsaResource::SetSerial(
  3723. IN ULONG serial
  3724. )
  3725. /*++
  3726. Implements:
  3727. IFsaResourcePriv::SetSerial().
  3728. --*/
  3729. {
  3730. HRESULT hr = S_OK;
  3731. try {
  3732. m_serial = serial;
  3733. m_isDirty = TRUE;
  3734. } WsbCatch(hr);
  3735. return(hr);
  3736. }
  3737. HRESULT
  3738. CFsaResource::SetStickyName(
  3739. IN OLECHAR* name
  3740. )
  3741. /*++
  3742. Implements:
  3743. IFsaResourcePriv::SetStickyName().
  3744. --*/
  3745. {
  3746. HRESULT hr = S_OK;
  3747. try {
  3748. WsbAssert(0 != name, E_POINTER);
  3749. m_stickyName = name;
  3750. m_isDirty = TRUE;
  3751. } WsbCatch(hr);
  3752. return(hr);
  3753. }
  3754. HRESULT
  3755. CFsaResource::SetUserFriendlyName(
  3756. IN OLECHAR* name
  3757. )
  3758. /*++
  3759. Implements:
  3760. IFsaResourcePriv::SetUserFriendlyName().
  3761. --*/
  3762. {
  3763. HRESULT hr = S_OK;
  3764. try {
  3765. WsbAssert(0 != name, E_POINTER);
  3766. m_userName = name;
  3767. m_isDirty = TRUE;
  3768. } WsbCatch(hr);
  3769. return(hr);
  3770. }
  3771. HRESULT
  3772. CFsaResource::ChangeSysState(
  3773. IN OUT HSM_SYSTEM_STATE* pSysState
  3774. )
  3775. /*++
  3776. Implements:
  3777. IHsmSystemState::ChangeSysState().
  3778. --*/
  3779. {
  3780. HRESULT hr = S_OK;
  3781. WsbTraceIn(OLESTR("CFsaResource::ChangeSysState"), OLESTR(""));
  3782. try {
  3783. //
  3784. // Make sure the truncater is stopped so it won't
  3785. // try to use the database
  3786. //
  3787. if (m_pTruncator) {
  3788. CComPtr<IHsmSession> pSession;
  3789. WsbAffirmHr(m_pTruncator->GetSession(&pSession));
  3790. if (pSession != 0) {
  3791. if (pSysState->State & HSM_STATE_SHUTDOWN) {
  3792. WsbAffirmHr(pSession->ProcessEvent(HSM_JOB_PHASE_ALL, HSM_JOB_EVENT_CANCEL));
  3793. }
  3794. }
  3795. m_pTruncator->ChangeSysState(pSysState);
  3796. }
  3797. } WsbCatch(hr);
  3798. WsbTraceOut(OLESTR("CFsaResource::ChangeSysState"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3799. return(hr);
  3800. }
  3801. HRESULT
  3802. CFsaResource::StartJob(
  3803. IN OLECHAR* startingPath,
  3804. IN IHsmSession* pSession
  3805. )
  3806. /*++
  3807. Implements:
  3808. IFsaResource::StartJob().
  3809. --*/
  3810. {
  3811. HRESULT hr = S_OK;
  3812. CComPtr<IHsmScanner> pScanner;
  3813. WsbTraceIn(OLESTR("CFsaResource::StartJob"), OLESTR("starting path = %ls"), startingPath);
  3814. try {
  3815. WsbAssert(0 != pSession, E_POINTER);
  3816. // Create an initialize the scanner.
  3817. WsbAffirmHr(CoCreateInstance(CLSID_CHsmScanner, 0, CLSCTX_SERVER, IID_IHsmScanner, (void**) &pScanner));
  3818. WsbAffirmHr(pScanner->Start(pSession, startingPath));
  3819. } WsbCatch(hr);
  3820. WsbTraceOut(OLESTR("CFsaResource::StartJob"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3821. return(hr);
  3822. }
  3823. HRESULT
  3824. CFsaResource::StartJobSession(
  3825. IN IHsmJob* pJob,
  3826. IN ULONG subRunId,
  3827. OUT IHsmSession** ppSession
  3828. )
  3829. /*++
  3830. Implements:
  3831. IFsaResource::StartJobSession().
  3832. --*/
  3833. {
  3834. HRESULT hr = S_OK;
  3835. CComPtr<IHsmSession> pSession;
  3836. GUID hsmId;
  3837. ULONG runId;
  3838. CWsbStringPtr name;
  3839. WsbTraceIn(OLESTR("CFsaResource::StartJobSession"), OLESTR(""));
  3840. try {
  3841. WsbAssert(0 != pJob, E_POINTER);
  3842. WsbAssert(0 != ppSession, E_POINTER);
  3843. *ppSession = 0;
  3844. // Create and Initialize a session object.
  3845. WsbAffirmHr(CoCreateInstance(CLSID_CHsmSession, 0, CLSCTX_SERVER, IID_IHsmSession, (void**) &pSession));
  3846. WsbAffirmHr(pJob->GetHsmId(&hsmId));
  3847. WsbAffirmHr(pJob->GetRunId(&runId));
  3848. WsbAffirmHr(pJob->GetName(&name, 0));
  3849. WsbAffirmHr(pSession->Start(name, HSM_JOB_LOG_NORMAL, hsmId, pJob, (IFsaResource*) this, runId, subRunId));
  3850. // Return the session to the caller.
  3851. *ppSession = pSession;
  3852. pSession->AddRef();
  3853. } WsbCatch(hr);
  3854. WsbTraceOut(OLESTR("CFsaResource::StartJobSession"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3855. return(hr);
  3856. }
  3857. HRESULT
  3858. CFsaResource::SetupValidateJob(SYSTEMTIME runTime)
  3859. {
  3860. HRESULT hr = S_OK;
  3861. CComPtr<IWsbCreateLocalObject> pLocalObject;
  3862. CComPtr <IWsbIndexedCollection> pJobs;
  3863. CComPtr<IHsmJob> pExistJob;
  3864. CComPtr<IHsmJob> pNewJob;
  3865. CComPtr<IHsmServer> pHsmServer;
  3866. CWsbStringPtr pszExistJobName;
  3867. CWsbStringPtr szJobName;
  3868. CWsbStringPtr parameters;
  3869. CWsbStringPtr commentString;
  3870. CWsbStringPtr tmpString;
  3871. CWsbStringPtr formatString;
  3872. TASK_TRIGGER_TYPE jobTriggerType;
  3873. BOOL scheduledJob;
  3874. WsbTraceIn(OLESTR("CFsaResource::SetupValidateJob"), OLESTR(""));
  3875. try {
  3876. // Get the volume name
  3877. CWsbStringPtr szWsbVolumeName;
  3878. WsbAffirmHr (GetLogicalName ( &szWsbVolumeName, 0));
  3879. // Create a job name
  3880. CWsbStringPtr volumeString;
  3881. WsbAffirmHr( volumeString.Alloc( 128 ) );
  3882. // For now, ignore the user name if it's not a drive letter
  3883. CWsbStringPtr userName = m_userName;
  3884. size_t userLen = 0;
  3885. if ((WCHAR *)userName) {
  3886. userLen = wcslen(userName);
  3887. }
  3888. if ((userLen != 3) || (userName[1] != L':')) {
  3889. userName = L"";
  3890. }
  3891. if( ! userName || userName.IsEqual ( L"" ) ) {
  3892. //
  3893. // No drive letter - use the volume name and serial number instead
  3894. //
  3895. if( ! m_name || m_name.IsEqual( L"" ) ) {
  3896. //
  3897. // No name, no drive letter - just have serial number
  3898. //
  3899. swprintf( volumeString, L"%8.8lx", m_serial );
  3900. } else {
  3901. swprintf( volumeString, L"%ls-%8.8lx", (OLECHAR*)m_name, m_serial );
  3902. }
  3903. } else {
  3904. //
  3905. // Just want the drive letter (first character)
  3906. //
  3907. volumeString = userName;
  3908. volumeString[1] = L'\0';
  3909. }
  3910. WsbAffirmHr(formatString.LoadFromRsc(_Module.m_hInst, IDS_JOB_NAME_PREFIX));
  3911. WsbAffirmHr(szJobName.Alloc(512));
  3912. swprintf((OLECHAR *) szJobName, formatString, (OLECHAR*)volumeString);
  3913. // Get a pointer to the HSM server
  3914. WsbAffirm(IsManaged() == S_OK, E_FAIL);
  3915. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, m_managingHsm, IID_IHsmServer,
  3916. (void**) &pHsmServer));
  3917. // Get a CreateLocalObject interface with which to create the job
  3918. WsbAffirmHr (pHsmServer->QueryInterface( IID_IWsbCreateLocalObject,
  3919. (void **) &pLocalObject));
  3920. // Create the new job in the engine
  3921. WsbAffirmHr (pLocalObject->CreateInstance( CLSID_CHsmJob, IID_IHsmJob,
  3922. (void**) &pNewJob));
  3923. WsbAffirmHr (pNewJob->InitAs(
  3924. szJobName, NULL, HSM_JOB_DEF_TYPE_VALIDATE, GUID_NULL,
  3925. pHsmServer, TRUE, this));
  3926. // Get the jobs collection from the engine
  3927. WsbAffirmHr (pHsmServer->GetJobs (&pJobs));
  3928. // If any jobs exist with this name, delete them
  3929. ULONG cCount;
  3930. WsbAffirmHr (pJobs->GetEntries (&cCount));
  3931. for (UINT i = 0; i < cCount; i++) {
  3932. WsbAffirmHr (pJobs->At (i, IID_IHsmJob, (void **) &pExistJob));
  3933. WsbAffirmHr (pExistJob->GetName (&pszExistJobName, 0));
  3934. if (pszExistJobName.Compare (szJobName) == 0) {
  3935. WsbAffirmHr (pJobs->RemoveAndRelease(pExistJob));
  3936. i--; cCount--;
  3937. }
  3938. pExistJob = 0; // make sure we release this interface.
  3939. }
  3940. // Add the new job to the engine collection
  3941. WsbAffirmHr (pJobs->Add(pNewJob));
  3942. // Set up to call the Engine to create an entry in the NT Task Scheduler
  3943. // Create the parameter string for the program NT Scheduler
  3944. // will run (for Sakkara this is RsLaunch) by putting the
  3945. // job name in as the parameter. This is how RsLaunch knows
  3946. // which job in the Engine to run.
  3947. WsbAffirmHr(parameters.Alloc(256));
  3948. swprintf((OLECHAR *)parameters, L"run \"%ls\"", (OLECHAR *) szJobName);
  3949. // Create the comment string for the NT Scheduler entry
  3950. WsbAffirmHr(formatString.LoadFromRsc(_Module.m_hInst, IDS_JOB_AUTOVALIDATE_COMMENT));
  3951. WsbAffirmHr(commentString.Alloc(512));
  3952. swprintf((OLECHAR *) commentString, formatString, (OLECHAR *) szWsbVolumeName);
  3953. // Declare and initialize the schedule components passed to
  3954. // the Engine.
  3955. jobTriggerType = TASK_TIME_TRIGGER_ONCE;
  3956. // Indicate this is a scheduled job
  3957. scheduledJob = TRUE;
  3958. // Create the task
  3959. WsbAffirmHr( pHsmServer->CreateTaskEx( szJobName, parameters,
  3960. commentString, jobTriggerType,
  3961. runTime, 0,
  3962. scheduledJob ) );
  3963. //
  3964. // Remove the registry value if it is there.
  3965. //
  3966. WsbAffirmHr(tmpString.Alloc(32));
  3967. swprintf((OLECHAR *) tmpString, L"%x", m_serial);
  3968. (void) WsbRemoveRegistryValue(NULL, FSA_VALIDATE_LOG_KEY_NAME, tmpString);
  3969. } WsbCatch( hr );
  3970. WsbTraceOut( L"CFsaResource::SetupValidateJob", L"hr = <%ls>", WsbHrAsString( hr ) );
  3971. return( hr );
  3972. }
  3973. HRESULT
  3974. CFsaResource::Test(
  3975. USHORT* passed,
  3976. USHORT* failed
  3977. )
  3978. /*++
  3979. Implements:
  3980. IWsbTestable::Test().
  3981. --*/
  3982. {
  3983. HRESULT hr = S_OK;
  3984. try {
  3985. WsbAssert(0 != passed, E_POINTER);
  3986. WsbAssert(0 != failed, E_POINTER);
  3987. *passed = 0;
  3988. *failed = 0;
  3989. } WsbCatch(hr);
  3990. return(hr);
  3991. }
  3992. HRESULT
  3993. CFsaResource::UpdateFrom(
  3994. IN IFsaServer* pServer,
  3995. IN IFsaResource* pResource
  3996. )
  3997. /*++
  3998. Implements:
  3999. IFsaResourcePriv::UpdateFrom().
  4000. Routine Description:
  4001. This routine implements the COM method for updating a resource object from another.
  4002. It is generally used to update a resource contained in the manageable resources
  4003. collection from a 'working' resource which was just created during a scan for
  4004. resources. Note that both source and target resource objects must represent the
  4005. same physical resource.
  4006. To capture the latest information about the resource, only the owning FSA and path
  4007. info is updated from the source resource object. All other resource info is
  4008. updated via a direct query contained within this method. This technique allows
  4009. for capturing any updates made by the user since the scan was run.
  4010. Arguments:
  4011. pServer - Interface pointer to the FSA service that is updating this resource.
  4012. pResource - Interface pointer to the resource used as the source during the update.
  4013. Return Value:
  4014. S_OK - The call succeeded (the resource being tested was found to be manageable,
  4015. and the resource object was initialized).
  4016. E_UNEXPECTED - Thrown if the id's (Guids) for the resource to updated and the
  4017. source resource do not match.
  4018. Any other value - The call failed because one of the Remote Storage or Win32 API
  4019. calls contained internally in this method failed. The error value returned
  4020. is specific to the API call which failed.
  4021. --*/
  4022. {
  4023. HRESULT hr = S_OK;
  4024. GUID id;
  4025. CWsbStringPtr tmpString;
  4026. CWsbStringPtr volPath;
  4027. WsbTraceIn(OLESTR("CFsaResource::UpdateFrom"), OLESTR(""));
  4028. try {
  4029. // The identifiers must be the same! (Meaning both resource objects must
  4030. // represent the same physical resource.)
  4031. WsbAffirmHr(pResource->GetIdentifier(&id));
  4032. WsbAssert(m_id == id, E_UNEXPECTED);
  4033. // Update (store) the owning FSA interface. However, since this is a weak
  4034. // reference, do not AddRef() it.
  4035. m_pFsaServer = pServer;
  4036. // Update the path specific information, preserving the last known path (if any).
  4037. // If the 'path' of this resource is null, set it to the 'path' of the resource
  4038. // we are updating from. Else, compare the 2 'path' fields. If different, copy
  4039. // this resource's path to 'old path', then update 'path' from the resource we are
  4040. // updating from. If the 2 resources' paths are not null and the same, do nothing.
  4041. //
  4042. WsbAffirmHr(pResource->GetPath(&tmpString, 0));
  4043. if (m_path == 0) {
  4044. WsbAffirmHr(SetPath(tmpString));
  4045. }
  4046. else if (wcscmp(tmpString, m_path) != 0) {
  4047. // copy path to 'old path' field, then update 'path' field.
  4048. WsbAffirmHr(m_path.CopyTo(&m_oldPath, 0));
  4049. WsbAffirmHr(SetPath(tmpString));
  4050. }
  4051. // Update 'user friendly' name of this resource from the resource we are updating
  4052. // from.
  4053. WsbAffirmHr(pResource->GetUserFriendlyName(&tmpString, 0));
  4054. WsbTrace(OLESTR("CFsaResource::UpdateFrom - setting user friendly name to %ws\n"),
  4055. (WCHAR *) tmpString);
  4056. WsbAffirmHr(SetUserFriendlyName(tmpString));
  4057. // Update 'sticky' (long, ugly PNP) name of this resource from the resource we are
  4058. // updating from.
  4059. WsbAffirmHr(pResource->GetStickyName(&tmpString, 0));
  4060. WsbAffirmHr(SetStickyName(tmpString));
  4061. // Since the other data that we would like to refresh is not exposed by an interface,
  4062. // we will query for it again.
  4063. //
  4064. // NOTE: fsFlags and maxComponentLength are the real issues, since name and fsName
  4065. // are done via exposed interfaces.
  4066. //
  4067. // NOTE: To keep every update from making the item seem dirty, we may want to
  4068. // compare all the fields first. (Idea for later enhancement)
  4069. m_name.Realloc(128); // volume name
  4070. m_fsName.Realloc(128); // volume file system type (e.g., FAT, NTFS)
  4071. HRESULT hrAvailable;
  4072. WsbAffirmHr( hrAvailable = pResource->IsAvailable( ) );
  4073. m_isAvailable = S_OK == hrAvailable ? TRUE : FALSE;
  4074. // Reformat resource's path for 'GetVolumeInfo' call below.
  4075. volPath = m_path;
  4076. WsbAffirmHr(volPath.Prepend("\\\\?\\"));
  4077. WsbAffirm(GetVolumeInformation(volPath, m_name, 128, &m_serial,
  4078. &m_maxComponentLength, &m_fsFlags, m_fsName, 128), E_FAIL);
  4079. // Now that everything is updated, initialize the
  4080. // premigration list if necessary
  4081. WsbAffirmHr(InitializePremigrationList(TRUE));
  4082. m_isDirty = TRUE;
  4083. } WsbCatch(hr);
  4084. WsbTraceOut(OLESTR("CFsaResource::UpdateFrom"), OLESTR("hr = <%ls>"),
  4085. WsbHrAsString(hr));
  4086. return(hr);
  4087. }
  4088. HRESULT
  4089. CFsaResource::Validate(
  4090. IN IFsaScanItem* pScanItem,
  4091. IN LONGLONG offset,
  4092. IN LONGLONG size,
  4093. IN LONGLONG usn
  4094. )
  4095. /*++
  4096. Implements:
  4097. IFsaResource::Validate().
  4098. --*/
  4099. {
  4100. HRESULT hr = S_OK;
  4101. CComPtr<IFsaPostIt> pWorkItem;
  4102. CComPtr<IHsmFsaTskMgr> pEngine;
  4103. CWsbStringPtr tmpString;
  4104. CComPtr<IHsmSession> pSession;
  4105. FSA_PLACEHOLDER placeholder;
  4106. WsbTraceIn(OLESTR("CFsaResource::Validate"), OLESTR("offset = %I64d, size = %I64d, usn = <%I64d>"),
  4107. offset, size, usn);
  4108. try {
  4109. // Make sure the Scan Item interface is OK
  4110. WsbAssert(pScanItem != 0, E_POINTER);
  4111. WsbAffirmHr(CoCreateInstance(CLSID_CFsaPostIt, 0, CLSCTX_SERVER, IID_IFsaPostIt, (void**) &pWorkItem));
  4112. // Get the data from the scan item.
  4113. WsbAffirmHr(pScanItem->GetSession(&pSession));
  4114. WsbAffirmHr(pWorkItem->SetSession(pSession));
  4115. WsbAffirmHr(pScanItem->GetPathAndName(0, &tmpString, 0));
  4116. WsbAffirmHr(pWorkItem->SetPath(tmpString));
  4117. WsbAffirmHr(pWorkItem->SetRequestOffset(offset));
  4118. WsbAffirmHr(pWorkItem->SetRequestSize(size));
  4119. WsbAffirmHr(pScanItem->GetPlaceholder(offset, size, &(placeholder)));
  4120. WsbAffirmHr(pWorkItem->SetPlaceholder(&placeholder));
  4121. // Fill in the rest of the work
  4122. WsbAffirmHr(pWorkItem->SetRequestAction(FSA_REQUEST_ACTION_VALIDATE));
  4123. WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_NONE));
  4124. // Fill in the USN
  4125. WsbAffirmHr(pWorkItem->SetUSN(usn));
  4126. // Send the request to the task manager
  4127. WsbAffirmHr(GetHsmEngine(&pEngine));
  4128. WsbAffirmHr(pEngine->DoFsaWork(pWorkItem));
  4129. } WsbCatch(hr);
  4130. WsbTraceOut(OLESTR("CFsaResource::Validate"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  4131. return(hr);
  4132. }
  4133. HRESULT
  4134. CFsaResource::ValidateForTruncate(
  4135. IN IFsaScanItem* pScanItem,
  4136. IN LONGLONG offset,
  4137. IN LONGLONG size,
  4138. IN LONGLONG usn
  4139. )
  4140. /*++
  4141. Implements:
  4142. IFsaResource::ValidateForTruncate().
  4143. --*/
  4144. {
  4145. HRESULT hr = S_OK;
  4146. CComPtr<IFsaPostIt> pWorkItem;
  4147. CComPtr<IHsmFsaTskMgr> pEngine;
  4148. CWsbStringPtr tmpString;
  4149. CComPtr<IHsmSession> pSession;
  4150. FSA_PLACEHOLDER placeholder;
  4151. WsbTraceIn(OLESTR("CFsaResource::ValidateForTruncate"), OLESTR("offset = %I64d, size = %I64d, usn = <%I64d>"),
  4152. offset, size, usn);
  4153. try {
  4154. // Make sure the Scan Item interface is OK
  4155. WsbAssert(pScanItem != 0, E_POINTER);
  4156. WsbAffirmHr(CoCreateInstance(CLSID_CFsaPostIt, 0, CLSCTX_SERVER, IID_IFsaPostIt, (void**) &pWorkItem));
  4157. // Get the data from the scan item.
  4158. WsbAffirmHr(pScanItem->GetSession(&pSession));
  4159. WsbAffirmHr(pWorkItem->SetSession(pSession));
  4160. WsbAffirmHr(pScanItem->GetPathAndName(0, &tmpString, 0));
  4161. WsbAffirmHr(pWorkItem->SetPath(tmpString));
  4162. WsbAffirmHr(pWorkItem->SetRequestOffset(offset));
  4163. WsbAffirmHr(pWorkItem->SetRequestSize(size));
  4164. WsbAffirmHr(pScanItem->GetPlaceholder(offset, size, &(placeholder)));
  4165. WsbAffirmHr(pWorkItem->SetPlaceholder(&placeholder));
  4166. // Fill in the rest of the work
  4167. WsbAffirmHr(pWorkItem->SetRequestAction(FSA_REQUEST_ACTION_VALIDATE_FOR_TRUNCATE));
  4168. WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_NONE));
  4169. // Fill in the USN
  4170. WsbAffirmHr(pWorkItem->SetUSN(usn));
  4171. // Send the request to the task manager
  4172. WsbAffirmHr(GetHsmEngine(&pEngine));
  4173. WsbAffirmHr(pEngine->DoFsaWork(pWorkItem));
  4174. } WsbCatch(hr);
  4175. WsbTraceOut(OLESTR("CFsaResource::ValidateForTruncate"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  4176. return(hr);
  4177. }
  4178. HRESULT
  4179. CFsaResource::WriteIdentifier(
  4180. void
  4181. )
  4182. /*++
  4183. This code is no longer called, in time it will be removed
  4184. --*/
  4185. {
  4186. #if 0
  4187. HRESULT hr = S_OK;
  4188. CWsbStringPtr tmpString;
  4189. HANDLE aHandle;
  4190. ULONG size;
  4191. ULONG bytesWritten;
  4192. FILE_FS_OBJECT_ID_INFORMATION objectId;
  4193. NTSTATUS status = STATUS_SUCCESS;
  4194. IO_STATUS_BLOCK ioStatus;
  4195. WsbTraceIn(OLESTR("CFsaResource::WriteIdentifier"), OLESTR(""));
  4196. try {
  4197. // For now, we will create a file in the root of the volume.
  4198. tmpString = m_path;
  4199. WsbAffirmHr(tmpString.Prepend("\\\\?\\"));
  4200. // WsbAffirmHr(tmpString.Append(":MSHSM_FSAID"));
  4201. WsbAffirmHandle(aHandle = CreateFile(tmpString,
  4202. GENERIC_WRITE,
  4203. 0,
  4204. 0,
  4205. OPEN_EXISTING,
  4206. FILE_ATTRIBUTE_NORMAL,
  4207. 0));
  4208. try {
  4209. WsbAffirmHr(WsbConvertToBytes(objectId.ObjectId, m_id, &size));
  4210. status = NtSetVolumeInformationFile(
  4211. aHandle,
  4212. &ioStatus,
  4213. &objectId,
  4214. sizeof(objectId),
  4215. FileFsObjectIdInformation);
  4216. WsbAffirmNtStatus(status);
  4217. WsbAffirm(bytesWritten == size, E_FAIL);
  4218. } WsbCatch(hr);
  4219. WsbAffirmStatus(CloseHandle(aHandle));
  4220. } WsbCatch(hr);
  4221. WsbTraceOut(OLESTR("CFsaResource::WriteIdentifier"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  4222. return(hr);
  4223. #else
  4224. return S_OK;
  4225. #endif
  4226. }
  4227. void CFsaResource::OnStateChange( )
  4228. /*++
  4229. Note: This function is run in a separate thread to avoid a deadlock situation
  4230. --*/
  4231. {
  4232. IConnectionPointImpl<CFsaResource, &IID_IHsmEvent, CComDynamicUnkArray>* p = this;
  4233. Lock();
  4234. HRESULT hr = S_OK;
  4235. IUnknown** pp = p->m_vec.begin();
  4236. while (pp < p->m_vec.end() && hr == S_OK)
  4237. {
  4238. if (*pp != NULL)
  4239. {
  4240. IHsmEvent* pIHsmEvent = (IHsmEvent*)*pp;
  4241. hr = pIHsmEvent->OnStateChange( );
  4242. }
  4243. pp++;
  4244. }
  4245. Unlock();
  4246. }