Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5902 lines
168 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.p->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_manageableItemMaxSize = 0;
  1232. m_isUnmanageDbInitialized = FALSE;
  1233. //Create the default rule list.
  1234. WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, NULL, CLSCTX_SERVER, IID_IWsbCollection, (void**) &m_pDefaultRules));
  1235. // Create the premigrated list DB
  1236. WsbAffirmHr(CoCreateInstance(CLSID_CFsaPremigratedDb, NULL, CLSCTX_SERVER, IID_IFsaPremigratedDb, (void**) &m_pPremigrated));
  1237. m_isDbInitialized = FALSE;
  1238. // Create the object for the auto truncator.
  1239. WsbAffirmHr(CoCreateInstance(CLSID_CFsaTruncatorNTFS, NULL, CLSCTX_SERVER, IID_IFsaTruncator, (void**) &m_pTruncator));
  1240. } WsbCatch(hr);
  1241. if (hr == S_OK) {
  1242. g_InstanceCount++;
  1243. }
  1244. WsbTrace(OLESTR("CFsaResource::FinalConstruct: this = %p, instance count = %d\n"),
  1245. this, g_InstanceCount);
  1246. WsbTraceOut(OLESTR("CFsaResource::FinalConstruct"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1247. return(hr);
  1248. }
  1249. HRESULT
  1250. CFsaResource::FinalRelease(
  1251. void
  1252. )
  1253. /*++
  1254. Implements:
  1255. CComObjectRoot::FinalRelease
  1256. --*/
  1257. {
  1258. HRESULT hr = S_OK;
  1259. WsbTraceIn(OLESTR("CFsaResource::FinalRelease"), OLESTR(""));
  1260. try {
  1261. HSM_SYSTEM_STATE SysState;
  1262. // Terminate Unmanage Db (If it wasn't created, nothing happens...)
  1263. TerminateUnmanageDb();
  1264. m_isUnmanageDbInitialized = FALSE;
  1265. m_pUnmanageDb = NULL;
  1266. // Shutdown resource
  1267. SysState.State = HSM_STATE_SHUTDOWN;
  1268. ChangeSysState(&SysState);
  1269. CWsbCollectable::FinalRelease();
  1270. // Free String members
  1271. // Note: Member objects held in smart-pointers are freed when the
  1272. // smart-pointer destructor is being called (as part of this object destruction)
  1273. m_oldPath.Free();
  1274. m_path.Free();
  1275. m_alternatePath.Free();
  1276. m_name.Free();
  1277. m_fsName.Free();
  1278. } WsbCatch(hr);
  1279. if (hr == S_OK) {
  1280. g_InstanceCount--;
  1281. }
  1282. WsbTrace(OLESTR("CFsaResource::FinalRelease: this = %p, instance count = %d\n"),
  1283. this, g_InstanceCount);
  1284. WsbTraceOut(OLESTR("CFsaResource::FinalRelease"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1285. return(hr);
  1286. }
  1287. HRESULT
  1288. CFsaResource::FindFirst(
  1289. IN OLECHAR* path,
  1290. IN IHsmSession* pSession,
  1291. OUT IFsaScanItem** ppScanItem
  1292. )
  1293. /*++
  1294. Implements:
  1295. IFsaResource::FindFirst().
  1296. --*/
  1297. {
  1298. HRESULT hr = S_OK;
  1299. CComPtr<IFsaScanItemPriv> pScanItem;
  1300. try {
  1301. WsbAssert(0 != path, E_POINTER);
  1302. WsbAssert(0 != ppScanItem, E_POINTER);
  1303. // Create an FsaScanItem that will scan for us.
  1304. WsbAffirmHr(CoCreateInstance(CLSID_CFsaScanItemNTFS, NULL, CLSCTX_SERVER, IID_IFsaScanItemPriv, (void**) &pScanItem));
  1305. // Scan starting at the specified path.
  1306. WsbAffirmHr(pScanItem->FindFirst((IFsaResource*) this, path, pSession));
  1307. // If we found something, then return the scan item.
  1308. WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItem, (void**) ppScanItem));
  1309. } WsbCatch(hr);
  1310. return(hr);
  1311. }
  1312. HRESULT
  1313. CFsaResource::FindFirstInRPIndex(
  1314. IN IHsmSession* pSession,
  1315. OUT IFsaScanItem** ppScanItem
  1316. )
  1317. /*++
  1318. Implements:
  1319. IFsaResource::FindFirstInRPIndex
  1320. --*/
  1321. {
  1322. HRESULT hr = S_OK;
  1323. CComPtr<IFsaScanItemPriv> pScanItem;
  1324. try {
  1325. WsbAssert(0 != ppScanItem, E_POINTER);
  1326. // Create an FsaScanItem that will scan for us.
  1327. WsbAffirmHr(CoCreateInstance(CLSID_CFsaScanItemNTFS, NULL, CLSCTX_SERVER, IID_IFsaScanItemPriv, (void**) &pScanItem));
  1328. // Scan starting at the specified path.
  1329. WsbAffirmHr(pScanItem->FindFirstInRPIndex((IFsaResource*) this, pSession));
  1330. // If we found something, then return the scan item.
  1331. WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItem, (void**) ppScanItem));
  1332. } WsbCatch(hr);
  1333. return(hr);
  1334. }
  1335. HRESULT
  1336. CFsaResource::FindFirstInDbIndex(
  1337. IN IHsmSession* pSession,
  1338. OUT IFsaScanItem** ppScanItem
  1339. )
  1340. /*++
  1341. Implements:
  1342. IFsaResource::FindFirstInDbIndex
  1343. --*/
  1344. {
  1345. HRESULT hr = S_OK;
  1346. CComPtr<IFsaScanItemPriv> pScanItem;
  1347. try {
  1348. WsbAssert(0 != ppScanItem, E_POINTER);
  1349. // Create an FsaScanItem that will scan for us.
  1350. WsbAffirmHr(CoCreateInstance(CLSID_CFsaScanItemNTFS, NULL, CLSCTX_SERVER, IID_IFsaScanItemPriv, (void**) &pScanItem));
  1351. // Scan starting at the specified path.
  1352. WsbAffirmHr(pScanItem->FindFirstInDbIndex((IFsaResource*) this, pSession));
  1353. // If we found something, then return the scan item.
  1354. WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItem, (void**) ppScanItem));
  1355. } WsbCatch(hr);
  1356. return(hr);
  1357. }
  1358. HRESULT
  1359. CFsaResource::FindNext(
  1360. IN IFsaScanItem* pScanItem
  1361. )
  1362. /*++
  1363. Implements:
  1364. IFsaResource::FindNext().
  1365. --*/
  1366. {
  1367. HRESULT hr = S_OK;
  1368. CComPtr<IFsaScanItemPriv> pPriv;
  1369. try {
  1370. WsbAssert(0 != pScanItem, E_POINTER);
  1371. // Continue the scan.
  1372. WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItemPriv, (void**) &pPriv))
  1373. WsbAffirmHr(pPriv->FindNext());
  1374. } WsbCatch(hr);
  1375. return(hr);
  1376. }
  1377. HRESULT
  1378. CFsaResource::FindNextInRPIndex(
  1379. IN IFsaScanItem* pScanItem
  1380. )
  1381. /*++
  1382. Implements:
  1383. IFsaResource::FindNextInRPIndex
  1384. --*/
  1385. {
  1386. HRESULT hr = S_OK;
  1387. CComPtr<IFsaScanItemPriv> pPriv;
  1388. try {
  1389. WsbAssert(0 != pScanItem, E_POINTER);
  1390. // Continue the scan.
  1391. WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItemPriv, (void**) &pPriv))
  1392. WsbAffirmHr(pPriv->FindNextInRPIndex());
  1393. } WsbCatch(hr);
  1394. return(hr);
  1395. }
  1396. HRESULT
  1397. CFsaResource::FindNextInDbIndex(
  1398. IN IFsaScanItem* pScanItem
  1399. )
  1400. /*++
  1401. Implements:
  1402. IFsaResource::FindNextInDbIndex
  1403. --*/
  1404. {
  1405. HRESULT hr = S_OK;
  1406. CComPtr<IFsaScanItemPriv> pPriv;
  1407. try {
  1408. WsbAssert(0 != pScanItem, E_POINTER);
  1409. // Continue the scan.
  1410. WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItemPriv, (void**) &pPriv))
  1411. WsbAffirmHr(pPriv->FindNextInDbIndex());
  1412. } WsbCatch(hr);
  1413. return(hr);
  1414. }
  1415. HRESULT
  1416. CFsaResource::FindFileId(
  1417. IN LONGLONG fileId,
  1418. IN IHsmSession* pSession,
  1419. OUT IFsaScanItem** ppScanItem
  1420. )
  1421. /*++
  1422. Implements:
  1423. IFsaResource::FindFileId().
  1424. Creates a scan item for the given file ID.
  1425. --*/
  1426. {
  1427. HRESULT hr = S_OK;
  1428. CComPtr<IFsaScanItemPriv> pScanItem;
  1429. CWsbStringPtr VolumePath;
  1430. CWsbStringPtr filePath;
  1431. HANDLE File = INVALID_HANDLE_VALUE;
  1432. HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
  1433. IO_STATUS_BLOCK IoStatusBlock;
  1434. NTSTATUS Status;
  1435. NTSTATUS GetNameStatus;
  1436. OBJECT_ATTRIBUTES ObjectAttributes;
  1437. UNICODE_STRING str;
  1438. PFILE_NAME_INFORMATION FileName;
  1439. DWORD pathSize;
  1440. OLECHAR *buffer = NULL;
  1441. WsbTraceIn(OLESTR("CFsaResource::FindFileId"), OLESTR("File ID = %I64x"), fileId);
  1442. try {
  1443. WsbAssert(0 != ppScanItem, E_POINTER);
  1444. // If we were passed an existing scan item (special internal code),
  1445. // use it; otherwise, create one.
  1446. if (NULL != *ppScanItem) {
  1447. WsbAffirmHr((*ppScanItem)->QueryInterface(IID_IFsaScanItemPriv,
  1448. (void**) &pScanItem));
  1449. } else {
  1450. WsbAffirmHr(CoCreateInstance(CLSID_CFsaScanItemNTFS, NULL,
  1451. CLSCTX_SERVER, IID_IFsaScanItemPriv, (void**) &pScanItem));
  1452. }
  1453. //
  1454. // Get the file path from the ID
  1455. //
  1456. //
  1457. // Open by File Reference Number (FileID),
  1458. // Relative opens from the Volume Handle.
  1459. //
  1460. VolumePath = L"\\\\.\\";
  1461. //VolumePath = L"";
  1462. WsbAffirmHr(VolumePath.Append(m_path));
  1463. ((OLECHAR *) VolumePath)[wcslen(VolumePath) - 1] = L'\0';
  1464. WsbTrace(OLESTR("CFsaResource::FindFileId - Volume path is <%ls>\n"),
  1465. static_cast<WCHAR*>(VolumePath));
  1466. VolumeHandle = CreateFileW( VolumePath,
  1467. GENERIC_READ,
  1468. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1469. NULL,
  1470. OPEN_EXISTING,
  1471. 0,
  1472. NULL );
  1473. WsbAffirmHandle(VolumeHandle);
  1474. RtlInitUnicodeString(&str, (WCHAR *) &fileId);
  1475. str.Length = 8;
  1476. str.MaximumLength = 8;
  1477. InitializeObjectAttributes( &ObjectAttributes,
  1478. &str,
  1479. OBJ_CASE_INSENSITIVE,
  1480. VolumeHandle,
  1481. NULL );
  1482. Status = NtCreateFile(&File,
  1483. FILE_READ_ATTRIBUTES,
  1484. &ObjectAttributes,
  1485. &IoStatusBlock,
  1486. NULL, // AllocationSize
  1487. FILE_ATTRIBUTE_NORMAL,
  1488. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1489. FILE_OPEN,
  1490. FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_BY_FILE_ID | FILE_OPEN_REPARSE_POINT,
  1491. NULL, // EaBuffer
  1492. 0);
  1493. WsbTrace(OLESTR("CFsaResource::FindFileId - NtCreateFile status = %lx\n"),
  1494. static_cast<LONG>(Status));
  1495. if (STATUS_INVALID_PARAMETER == Status) {
  1496. // This seems to be the error we get if the file is missing so
  1497. // we translate it to something our code will understand
  1498. WsbThrow(WSB_E_NOTFOUND);
  1499. }
  1500. WsbAffirmNtStatus(Status);
  1501. GetNameStatus = STATUS_BUFFER_OVERFLOW;
  1502. //
  1503. // Take a guess at the path length to start with
  1504. //
  1505. pathSize = 256 + sizeof(FILE_NAME_INFORMATION);
  1506. //
  1507. // Keep trying for the name until we get an error other than buffer overflow or success.
  1508. //
  1509. WsbAffirmPointer((buffer = (OLECHAR *) malloc(pathSize)));
  1510. do {
  1511. FileName = (PFILE_NAME_INFORMATION) buffer;
  1512. GetNameStatus = NtQueryInformationFile( File,
  1513. &IoStatusBlock,
  1514. FileName,
  1515. pathSize - sizeof(WCHAR), // leave room for the NULL we add
  1516. FileNameInformation );
  1517. WsbTrace(OLESTR("CFsaResource::FindFileId - NtQueryInformationFile status = %ld\n"),
  1518. static_cast<LONG>(GetNameStatus));
  1519. if (GetNameStatus == STATUS_BUFFER_OVERFLOW) {
  1520. pathSize += 256;
  1521. LPVOID pTemp = realloc(buffer, pathSize);
  1522. WsbAffirm(0 != pTemp, E_OUTOFMEMORY);
  1523. buffer = (OLECHAR *)pTemp;
  1524. }
  1525. } while (GetNameStatus == STATUS_BUFFER_OVERFLOW);
  1526. WsbAffirmNtStatus(GetNameStatus);
  1527. FileName->FileName[FileName->FileNameLength / sizeof(WCHAR)] = L'\0';
  1528. filePath = FileName->FileName;
  1529. // Scan starting at the specified path.
  1530. WsbAffirmHr(pScanItem->FindFirst((IFsaResource*) this, filePath, pSession));
  1531. // If we found something, then return the scan item.
  1532. WsbAffirmHr(pScanItem->QueryInterface(IID_IFsaScanItem, (void**) ppScanItem));
  1533. } WsbCatch(hr);
  1534. // Make sure we clean up
  1535. if (INVALID_HANDLE_VALUE != VolumeHandle) {
  1536. CloseHandle(VolumeHandle);
  1537. }
  1538. if (INVALID_HANDLE_VALUE != File) {
  1539. NtClose(File);
  1540. }
  1541. if (buffer != NULL) {
  1542. free(buffer);
  1543. }
  1544. WsbTraceOut(OLESTR("CFsaResource::FindFileId"), OLESTR("hr = <%ls>"),
  1545. WsbHrAsString(hr));
  1546. return(hr);
  1547. }
  1548. HRESULT
  1549. CFsaResource::FindObjectId(
  1550. IN LONGLONG objIdHi,
  1551. IN LONGLONG objIdLo,
  1552. IN IHsmSession* pSession,
  1553. OUT IFsaScanItem** ppScanItem
  1554. )
  1555. /*++
  1556. Implements:
  1557. IFsaResource::FindObjectId().
  1558. Creates a scan item for the given object Id.
  1559. --*/
  1560. {
  1561. HRESULT hr = S_OK;
  1562. CComPtr<IFsaScanItemPriv> pScanItem;
  1563. CWsbStringPtr VolumePath;
  1564. HANDLE File = INVALID_HANDLE_VALUE;
  1565. IO_STATUS_BLOCK IoStatusBlock;
  1566. NTSTATUS Status;
  1567. OBJECT_ATTRIBUTES ObjectAttributes;
  1568. LONG pathLength;
  1569. WCHAR unicodeStringBuffer[100];
  1570. UNICODE_STRING unicodeString;
  1571. FILE_INTERNAL_INFORMATION iInfo;
  1572. LONGLONG fileId;
  1573. WsbTraceIn(OLESTR("CFsaResource::FindObjectId"), OLESTR("Object ID = %I64x %I64x"), objIdHi, objIdLo);
  1574. try {
  1575. WsbAssert(0 != ppScanItem, E_POINTER);
  1576. // Create an FsaScanItem that will scan for us.
  1577. WsbAffirmHr(CoCreateInstance(CLSID_CFsaScanItemNTFS, NULL, CLSCTX_SERVER, IID_IFsaScanItemPriv, (void**) &pScanItem));
  1578. //
  1579. // Open by object ID
  1580. // Relative opens from the Volume Handle.
  1581. //
  1582. VolumePath = L"\\??\\";
  1583. //VolumePath = L"";
  1584. WsbAffirmHr(VolumePath.Append((WCHAR *) m_path));
  1585. WsbTrace(OLESTR("CFsaResource::FindObjectId - Volume path is %ws.\n"), (OLECHAR *) VolumePath);
  1586. WsbTrace(OLESTR("CFsaResource::FindObjectId - Object ID = %I64x %I64x.\n"), objIdHi, objIdLo);
  1587. pathLength = wcslen(VolumePath);
  1588. RtlInitUnicodeString(&unicodeString, unicodeStringBuffer);
  1589. unicodeString.Length = (USHORT)((pathLength * sizeof(WCHAR)) + (sizeof(LONGLONG) * 2));
  1590. RtlCopyMemory(&unicodeString.Buffer[0], VolumePath, pathLength * sizeof(WCHAR));
  1591. RtlCopyMemory(&unicodeString.Buffer[pathLength], &objIdHi, sizeof(LONGLONG));
  1592. RtlCopyMemory(&unicodeString.Buffer[pathLength + (sizeof(LONGLONG) / sizeof(WCHAR))], &objIdLo, sizeof(LONGLONG));
  1593. InitializeObjectAttributes( &ObjectAttributes,
  1594. &unicodeString,
  1595. OBJ_CASE_INSENSITIVE,
  1596. 0,
  1597. NULL );
  1598. WsbAffirmNtStatus(Status = NtCreateFile( &File,
  1599. FILE_READ_ATTRIBUTES,
  1600. &ObjectAttributes,
  1601. &IoStatusBlock,
  1602. NULL, // AllocationSize
  1603. FILE_ATTRIBUTE_NORMAL,
  1604. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1605. FILE_OPEN,
  1606. FILE_OPEN_BY_FILE_ID | FILE_OPEN_REPARSE_POINT,
  1607. NULL, // EaBuffer
  1608. 0 ));
  1609. //
  1610. // Get the file id from the object ID
  1611. //
  1612. WsbAffirmHr(NtQueryInformationFile(File, &IoStatusBlock, &iInfo, sizeof(FILE_INTERNAL_INFORMATION), FileInternalInformation));
  1613. fileId = iInfo.IndexNumber.QuadPart;
  1614. WsbAffirmNtStatus(NtClose(File));
  1615. File = INVALID_HANDLE_VALUE;
  1616. // Now open by file id.
  1617. WsbAffirmHr(FindFileId(fileId, pSession, ppScanItem));
  1618. } WsbCatch(hr);
  1619. // Make sure we clean up.
  1620. if (INVALID_HANDLE_VALUE != File) {
  1621. NtClose( File );
  1622. }
  1623. WsbTraceOut(OLESTR("CFsaResource::FindObjectId"), OLESTR("hr = <%ls>"),
  1624. WsbHrAsString(hr));
  1625. return(hr);
  1626. }
  1627. HRESULT
  1628. CFsaResource::GetAlternatePath(
  1629. OUT OLECHAR** pPath,
  1630. IN ULONG bufferSize
  1631. )
  1632. /*++
  1633. Implements:
  1634. IFsaResource::GetAlternatePath().
  1635. --*/
  1636. {
  1637. HRESULT hr = S_OK;
  1638. try {
  1639. WsbAssert(0 != pPath, E_POINTER);
  1640. WsbAffirmHr(m_alternatePath.CopyTo(pPath, bufferSize));
  1641. } WsbCatch(hr);
  1642. return(hr);
  1643. }
  1644. HRESULT
  1645. CFsaResource::GetClassID(
  1646. OUT CLSID* pClsid
  1647. )
  1648. /*++
  1649. Implements:
  1650. IPersist::GetClassID().
  1651. --*/
  1652. {
  1653. HRESULT hr = S_OK;
  1654. WsbTraceIn(OLESTR("CFsaResource::GetClassID"), OLESTR(""));
  1655. try {
  1656. WsbAssert(0 != pClsid, E_POINTER);
  1657. *pClsid = CLSID_CFsaResourceNTFS;
  1658. } WsbCatch(hr);
  1659. WsbTraceOut(OLESTR("CFsaResource::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid));
  1660. return(hr);
  1661. }
  1662. HRESULT
  1663. CFsaResource::GetDbPath(
  1664. OUT OLECHAR** pPath,
  1665. IN ULONG bufferSize
  1666. )
  1667. /*++
  1668. Implements:
  1669. IFsaResource::GetDbPath().
  1670. --*/
  1671. {
  1672. HRESULT hr = S_OK;
  1673. CWsbStringPtr tmpString;
  1674. WsbTraceIn(OLESTR("CFsaResource::GetDbPath"), OLESTR(""));
  1675. try {
  1676. WsbAssert(0 != pPath, E_POINTER);
  1677. // Use a relative path under the install directory.
  1678. WsbAffirmHr(m_pFsaServer->GetIDbPath(&tmpString, 0));
  1679. tmpString.Append(OLESTR("\\"));
  1680. CWsbStringPtr strGuid;
  1681. WsbAffirmHr(WsbSafeGuidAsString(m_id, strGuid));
  1682. tmpString.Append(strGuid);
  1683. WsbAffirmHr(tmpString.CopyTo(pPath, bufferSize));
  1684. } WsbCatch(hr);
  1685. WsbTraceOut(OLESTR("CFsaResource::GetDbPath"), OLESTR("hr = <%ls>, path = <%ls)"),
  1686. WsbHrAsString(hr), WsbPtrToStringAsString(pPath));
  1687. return(hr);
  1688. }
  1689. HRESULT
  1690. CFsaResource::GetUnmanageDbPath(
  1691. OUT OLECHAR** pPath,
  1692. IN ULONG bufferSize
  1693. )
  1694. /*++
  1695. Implements:
  1696. IFsaResource::GetDbPath().
  1697. --*/
  1698. {
  1699. HRESULT hr = S_OK;
  1700. CWsbStringPtr tmpString;
  1701. WsbTraceIn(OLESTR("CFsaResource::GetUnmanageDbPath"), OLESTR(""));
  1702. try {
  1703. WsbAssert(0 != pPath, E_POINTER);
  1704. // Use a relative path under the install directory.
  1705. WsbAffirmHr(m_pFsaServer->GetUnmanageIDbPath(&tmpString, 0));
  1706. tmpString.Append(OLESTR("\\"));
  1707. tmpString.Append(UNMANAGE_DB_PREFIX);
  1708. CWsbStringPtr strGuid;
  1709. WsbAffirmHr(WsbSafeGuidAsString(m_id, strGuid));
  1710. tmpString.Append(strGuid);
  1711. WsbAffirmHr(tmpString.CopyTo(pPath, bufferSize));
  1712. } WsbCatch(hr);
  1713. WsbTraceOut(OLESTR("CFsaResource::GetUnmanageDbPath"), OLESTR("hr = <%ls>, path = <%ls)"),
  1714. WsbHrAsString(hr), WsbPtrToStringAsString(pPath));
  1715. return(hr);
  1716. }
  1717. HRESULT
  1718. CFsaResource::GetDefaultRules(
  1719. OUT IWsbCollection** ppCollection
  1720. )
  1721. /*++
  1722. Implements:
  1723. IFsaResource::GetDefaultRules().
  1724. --*/
  1725. {
  1726. HRESULT hr = S_OK;
  1727. try {
  1728. WsbAssert(0 != ppCollection, E_POINTER);
  1729. *ppCollection = m_pDefaultRules;
  1730. m_pDefaultRules.p->AddRef();
  1731. } WsbCatch(hr);
  1732. return(hr);
  1733. }
  1734. HRESULT
  1735. CFsaResource::GetFreeLevel(
  1736. OUT ULONG* pLevel
  1737. )
  1738. /*++
  1739. Implements:
  1740. IFsaResource::GetFreeLevel().
  1741. --*/
  1742. {
  1743. HRESULT hr = S_OK;
  1744. LONGLONG total;
  1745. LONGLONG free;
  1746. try {
  1747. WsbAssert(0 != pLevel, E_POINTER);
  1748. // Get the capacities for this resource.
  1749. WsbAffirmHr(GetSizes(&total, &free, 0, 0));
  1750. *pLevel = (ULONG) (((double)free / (double)total) * (double)FSA_HSMLEVEL_100);
  1751. } WsbCatch(hr);
  1752. return(hr);
  1753. }
  1754. HRESULT
  1755. CFsaResource::GetFsName(
  1756. OUT OLECHAR** pFsName,
  1757. IN ULONG bufferSize
  1758. )
  1759. /*++
  1760. Implements:
  1761. IFsaResource::GetFsName().
  1762. --*/
  1763. {
  1764. HRESULT hr = S_OK;
  1765. try {
  1766. WsbAssert(0 != pFsName, E_POINTER);
  1767. WsbAffirmHr(m_fsName.CopyTo(pFsName, bufferSize));
  1768. } WsbCatch(hr);
  1769. return(hr);
  1770. }
  1771. HRESULT
  1772. CFsaResource::GetHsmEngine(
  1773. IHsmFsaTskMgr** ppEngine
  1774. )
  1775. /*++
  1776. Implements:
  1777. IFsaResource::GetHsmEngine().
  1778. --*/
  1779. {
  1780. HRESULT hr = S_OK;
  1781. CComPtr<IHsmServer> pHsmServer;
  1782. WsbTraceIn(OLESTR("CFsaResource::GetHsmEngine"), OLESTR(""));
  1783. try {
  1784. WsbAssert(0 != ppEngine, E_POINTER);
  1785. if (m_pHsmEngine != 0) {
  1786. //
  1787. // See if the connection is still valid
  1788. //
  1789. CComPtr<IHsmFsaTskMgr> pTestInterface;
  1790. hr = m_pHsmEngine->ContactOk();
  1791. if (hr != S_OK) {
  1792. // We don't have a valid
  1793. WsbTrace(OLESTR("CHsmServer::GetHsmEngine - Current connection invalid.\n"));
  1794. hr = S_OK;
  1795. m_pHsmEngine = 0;
  1796. }
  1797. }
  1798. // If we haven't already looked it up, then do so now.
  1799. if (m_pHsmEngine == 0) {
  1800. WsbAffirm(IsManaged() == S_OK, E_FAIL);
  1801. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, m_managingHsm, IID_IHsmServer, (void**) &pHsmServer));
  1802. WsbAffirmHr(pHsmServer->GetHsmFsaTskMgr(&m_pHsmEngine));
  1803. }
  1804. // Return the pointer that we have stored.
  1805. *ppEngine = m_pHsmEngine;
  1806. m_pHsmEngine.p->AddRef();
  1807. } WsbCatch(hr);
  1808. WsbTraceOut(OLESTR("CFsaResource::GetHsmEngine"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1809. return(hr);
  1810. }
  1811. HRESULT
  1812. CFsaResource::GetHsmLevel(
  1813. OUT ULONG* pLevel
  1814. )
  1815. /*++
  1816. Implements:
  1817. IFsaResource::GetHsmLevel().
  1818. --*/
  1819. {
  1820. HRESULT hr = S_OK;
  1821. try {
  1822. WsbAssert(0 != pLevel, E_POINTER);
  1823. *pLevel = m_hsmLevel;
  1824. } WsbCatch(hr);
  1825. return(hr);
  1826. }
  1827. HRESULT
  1828. CFsaResource::GetIdentifier(
  1829. OUT GUID* pId
  1830. )
  1831. /*++
  1832. Implements:
  1833. IFsaResource::GetIdentifier().
  1834. --*/
  1835. {
  1836. HRESULT hr = S_OK;
  1837. try {
  1838. WsbAssert(0 != pId, E_POINTER);
  1839. *pId = m_id;
  1840. } WsbCatch(hr);
  1841. return(hr);
  1842. }
  1843. HRESULT
  1844. CFsaResource::GetLogicalName(
  1845. OUT OLECHAR** pName,
  1846. IN ULONG bufferSize
  1847. )
  1848. /*++
  1849. Implements:
  1850. IFsaResource::GetLogicalName().
  1851. --*/
  1852. {
  1853. HRESULT hr = S_OK;
  1854. CWsbStringPtr tmpString;
  1855. CWsbStringPtr name;
  1856. try {
  1857. WsbAssert(0 != pName, E_POINTER);
  1858. WsbAssert(m_pFsaServer != 0, E_POINTER);
  1859. WsbAffirmHr(tmpString.TakeFrom(*pName, bufferSize));
  1860. try {
  1861. // This is an arbitrary choice for the naming convention. Nothing has been
  1862. // decided upon.
  1863. WsbAffirmHr(m_pFsaServer->GetLogicalName(&tmpString, 0));
  1864. WsbAffirmHr(GetPath(&name, 0));
  1865. //
  1866. // Strip off trailing \ if there
  1867. if (name[(int) wcslen((WCHAR *) name) - 1] == L'\\') {
  1868. name[(int) wcslen((WCHAR *) name) - 1] = L'\0';
  1869. }
  1870. WsbAffirmHr(tmpString.Append(OLESTR("\\")));
  1871. WsbAffirmHr(tmpString.Append(name));
  1872. } WsbCatch(hr);
  1873. WsbAffirmHr(tmpString.GiveTo(pName));
  1874. } WsbCatch(hr);
  1875. return(hr);
  1876. }
  1877. HRESULT
  1878. CFsaResource::GetMaxFileLogicalSize(
  1879. OUT LONGLONG* pSize
  1880. )
  1881. /*++
  1882. Implements:
  1883. IFsaResourcePriv::GetMaxFileLogicalSize().
  1884. --*/
  1885. {
  1886. HRESULT hr = S_OK;
  1887. try {
  1888. WsbAssert(0 != pSize, E_POINTER);
  1889. *pSize = m_manageableItemMaxSize;
  1890. } WsbCatch(hr);
  1891. return(hr);
  1892. }
  1893. HRESULT
  1894. CFsaResource::GetManageableItemLogicalSize(
  1895. OUT LONGLONG* pSize
  1896. )
  1897. /*++
  1898. Implements:
  1899. IFsaResource::GetManageableItemLogicalSize().
  1900. --*/
  1901. {
  1902. HRESULT hr = S_OK;
  1903. try {
  1904. WsbAssert(0 != pSize, E_POINTER);
  1905. *pSize = m_manageableItemLogicalSize;
  1906. } WsbCatch(hr);
  1907. return(hr);
  1908. }
  1909. HRESULT
  1910. CFsaResource::GetManageableItemAccessTime(
  1911. OUT BOOL* pIsRelative,
  1912. OUT FILETIME* pTime
  1913. )
  1914. /*++
  1915. Implements:
  1916. IFsaResource::GetManageableItemAccessTime().
  1917. --*/
  1918. {
  1919. HRESULT hr = S_OK;
  1920. try {
  1921. WsbAssert(0 != pIsRelative, E_POINTER);
  1922. WsbAssert(0 != pTime, E_POINTER);
  1923. *pIsRelative = m_manageableItemAccessTimeIsRelative;
  1924. *pTime = m_manageableItemAccessTime;
  1925. } WsbCatch(hr);
  1926. return(hr);
  1927. }
  1928. HRESULT
  1929. CFsaResource::GetManagingHsm(
  1930. GUID* pId
  1931. )
  1932. /*++
  1933. Implements:
  1934. IFsaResource::GetManagingHsm().
  1935. --*/
  1936. {
  1937. HRESULT hr = S_OK;
  1938. try {
  1939. WsbAssert(0 != pId, E_POINTER);
  1940. *pId = m_managingHsm;
  1941. } WsbCatch(hr);
  1942. return(hr);
  1943. }
  1944. HRESULT
  1945. CFsaResource::GetName(
  1946. OUT OLECHAR** pName,
  1947. IN ULONG bufferSize
  1948. )
  1949. /*++
  1950. Implements:
  1951. IFsaResource::GetName().
  1952. --*/
  1953. {
  1954. HRESULT hr = S_OK;
  1955. WsbTraceIn(OLESTR("CFsaResource::GetName"), OLESTR(""));
  1956. try {
  1957. WsbAssert(0 != pName, E_POINTER);
  1958. WsbAffirmHr(m_name.CopyTo(pName, bufferSize));
  1959. } WsbCatch(hr);
  1960. WsbTraceOut(OLESTR("CFsaResource::GetName"), OLESTR("hr = <%ls>, name = <%ls>"),
  1961. WsbHrAsString(hr), (OLECHAR *)m_name);
  1962. return(hr);
  1963. }
  1964. HRESULT
  1965. CFsaResource::GetOldPath(
  1966. OUT OLECHAR** pPath,
  1967. IN ULONG bufferSize
  1968. )
  1969. /*++
  1970. Implements:
  1971. IFsaResource::GetOldPath().
  1972. --*/
  1973. {
  1974. HRESULT hr = S_OK;
  1975. try {
  1976. WsbAssert(0 != pPath, E_POINTER);
  1977. WsbAffirmHr(m_oldPath.CopyTo(pPath, bufferSize));
  1978. } WsbCatch(hr);
  1979. return(hr);
  1980. }
  1981. HRESULT
  1982. CFsaResource::GetPath(
  1983. OUT OLECHAR** pPath,
  1984. IN ULONG bufferSize
  1985. )
  1986. /*++
  1987. Implements:
  1988. IFsaResource::GetPath().
  1989. --*/
  1990. {
  1991. HRESULT hr = S_OK;
  1992. try {
  1993. WsbAssert(0 != pPath, E_POINTER);
  1994. WsbAffirmHr(m_path.CopyTo(pPath, bufferSize));
  1995. } WsbCatch(hr);
  1996. return(hr);
  1997. }
  1998. HRESULT
  1999. CFsaResource::GetStickyName(
  2000. OUT OLECHAR** pPath,
  2001. IN ULONG bufferSize
  2002. )
  2003. /*++
  2004. Implements:
  2005. IFsaResource::GetStickyName().
  2006. --*/
  2007. {
  2008. HRESULT hr = S_OK;
  2009. try {
  2010. WsbAssert(0 != pPath, E_POINTER);
  2011. WsbAffirmHr(m_stickyName.CopyTo(pPath, bufferSize));
  2012. } WsbCatch(hr);
  2013. return(hr);
  2014. }
  2015. HRESULT
  2016. CFsaResource::GetUserFriendlyName(
  2017. OUT OLECHAR** pPath,
  2018. IN ULONG bufferSize
  2019. )
  2020. /*++
  2021. Implements:
  2022. IFsaResource::GetUserFriendlyName().
  2023. --*/
  2024. {
  2025. HRESULT hr = S_OK;
  2026. try {
  2027. WsbAssert(0 != pPath, E_POINTER);
  2028. WsbAffirmHr(m_userName.CopyTo(pPath, bufferSize));
  2029. } WsbCatch(hr);
  2030. return(hr);
  2031. }
  2032. HRESULT
  2033. CFsaResource::GetPremigrated(
  2034. IN REFIID riid,
  2035. OUT void** ppDb
  2036. )
  2037. /*++
  2038. Implements:
  2039. IFsaResourcePriv::GetPremigrated
  2040. --*/
  2041. {
  2042. HRESULT hr = S_OK;
  2043. try {
  2044. WsbAssert(0 != ppDb, E_POINTER);
  2045. if (m_isDbInitialized) {
  2046. WsbAffirmHr(m_pPremigrated->QueryInterface(riid, ppDb));
  2047. hr = S_OK;
  2048. } else {
  2049. hr = WSB_E_RESOURCE_UNAVAILABLE;
  2050. }
  2051. } WsbCatch(hr);
  2052. return(hr);
  2053. }
  2054. HRESULT
  2055. CFsaResource::GetUnmanageDb(
  2056. IN REFIID riid,
  2057. OUT void** ppDb
  2058. )
  2059. /*++
  2060. Implements:
  2061. IFsaResourcePriv::GetUnmanageDb
  2062. --*/
  2063. {
  2064. HRESULT hr = S_OK;
  2065. try {
  2066. WsbAssert(0 != ppDb, E_POINTER);
  2067. if ((m_isUnmanageDbInitialized) && (m_pUnmanageDb != NULL)) {
  2068. WsbAffirmHr(m_pUnmanageDb->QueryInterface(riid, ppDb));
  2069. hr = S_OK;
  2070. } else {
  2071. hr = WSB_E_RESOURCE_UNAVAILABLE;
  2072. }
  2073. } WsbCatch(hr);
  2074. return(hr);
  2075. }
  2076. HRESULT
  2077. CFsaResource::GetSerial(
  2078. OUT ULONG *serial
  2079. )
  2080. /*++
  2081. Implements:
  2082. IFsaResourcePriv:GetSerial
  2083. --*/
  2084. {
  2085. HRESULT hr = S_OK;
  2086. WsbTraceIn(OLESTR("CFsaResource::GetSerial"), OLESTR(""));
  2087. try {
  2088. WsbAssert(0 != serial, E_POINTER);
  2089. *serial = m_serial;
  2090. } WsbCatch(hr);
  2091. WsbTraceOut(OLESTR("CFsaResource::GetSerial"), OLESTR("hr = <%ls>, Serial = %u"), WsbHrAsString(hr), m_serial);
  2092. return(hr);
  2093. }
  2094. HRESULT
  2095. CFsaResource::GetSizeMax(
  2096. OUT ULARGE_INTEGER* pSize
  2097. )
  2098. /*++
  2099. Implements:
  2100. IPersistStream::GetSizeMax().
  2101. --*/
  2102. {
  2103. HRESULT hr = S_OK;
  2104. CComPtr<IPersistStream> pPersistStream;
  2105. ULARGE_INTEGER entrySize;
  2106. WsbTraceIn(OLESTR("CFsaResource::GetSizeMax"), OLESTR(""));
  2107. try {
  2108. WsbAssert(0 != pSize, E_POINTER);
  2109. // Determine the size for a rule with no criteria.
  2110. pSize->QuadPart = WsbPersistSize((wcslen(m_name) + 1) * sizeof(OLECHAR)) +
  2111. WsbPersistSize((wcslen(m_fsName) + 1) * sizeof(OLECHAR)) +
  2112. WsbPersistSize((wcslen(m_path) + 1) * sizeof(OLECHAR)) +
  2113. WsbPersistSize((wcslen(m_alternatePath) + 1) * sizeof(OLECHAR)) +
  2114. 3 * WsbPersistSizeOf(LONGLONG) +
  2115. WsbPersistSizeOf(FILETIME) +
  2116. WsbPersistSizeOf(BOOL) +
  2117. 3 * WsbPersistSizeOf(ULONG) +
  2118. WsbPersistSizeOf(FSA_RESOURCE_COMPARE) +
  2119. 2 * WsbPersistSizeOf(GUID);
  2120. // Now allocate space for the default rules list.
  2121. WsbAffirmHr((m_pDefaultRules)->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  2122. WsbAffirmHr(pPersistStream->GetSizeMax(&entrySize));
  2123. pSize->QuadPart += entrySize.QuadPart;
  2124. pPersistStream = 0;
  2125. // Now allocate space for the premigration list.
  2126. WsbAffirmHr(((IWsbDb*)m_pPremigrated)->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  2127. WsbAffirmHr(pPersistStream->GetSizeMax(&entrySize));
  2128. pSize->QuadPart += entrySize.QuadPart;
  2129. pPersistStream = 0;
  2130. // Now allocate space for truncator.
  2131. WsbAffirmHr(m_pTruncator->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  2132. WsbAffirmHr(pPersistStream->GetSizeMax(&entrySize));
  2133. pSize->QuadPart += entrySize.QuadPart;
  2134. pPersistStream = 0;
  2135. } WsbCatch(hr);
  2136. WsbTraceOut(OLESTR("CFsaResource::GetSizeMax"), OLESTR("hr = <%ls>, Size = <%ls>"), WsbHrAsString(hr), WsbPtrToUliAsString(pSize));
  2137. return(hr);
  2138. }
  2139. HRESULT
  2140. CFsaResource::GetSizes(
  2141. OUT LONGLONG* pTotal,
  2142. OUT LONGLONG* pFree,
  2143. OUT LONGLONG* pPremigrated,
  2144. OUT LONGLONG* pTruncated
  2145. )
  2146. /*++
  2147. Implements:
  2148. IFsaResource::GetSizes().
  2149. --*/
  2150. {
  2151. HRESULT hr = S_OK;
  2152. CWsbStringPtr path;
  2153. ULARGE_INTEGER freeCaller;
  2154. ULARGE_INTEGER total;
  2155. ULARGE_INTEGER free;
  2156. try {
  2157. if ((0 != pTotal) || (0 != pFree)) {
  2158. WsbAffirmHr(GetPath(&path, 0));
  2159. WsbAffirmHr(path.Prepend("\\\\?\\"));
  2160. WsbAffirmStatus(GetDiskFreeSpaceEx(path, &freeCaller, &total, &free));
  2161. if (0 != pTotal) {
  2162. *pTotal = total.QuadPart;
  2163. }
  2164. if (0 != pFree) {
  2165. *pFree = free.QuadPart;
  2166. }
  2167. }
  2168. if (0 != pPremigrated) {
  2169. *pPremigrated = m_premigratedSize;
  2170. }
  2171. if (0 != pTruncated) {
  2172. *pTruncated = m_truncatedSize;
  2173. }
  2174. } WsbCatch(hr);
  2175. return(hr);
  2176. }
  2177. HRESULT
  2178. CFsaResource::GetTruncator(
  2179. IFsaTruncator** ppTruncator
  2180. )
  2181. /*++
  2182. Implements:
  2183. IFsaResource::GetTruncator().
  2184. --*/
  2185. {
  2186. HRESULT hr = S_OK;
  2187. try {
  2188. WsbAssert(0 != ppTruncator, E_POINTER);
  2189. // Return the pointer that we have stored.
  2190. *ppTruncator = m_pTruncator;
  2191. if (m_pTruncator != 0) {
  2192. m_pTruncator.p->AddRef();
  2193. }
  2194. } WsbCatch(hr);
  2195. return(hr);
  2196. }
  2197. HRESULT
  2198. CFsaResource::GetUncPath(
  2199. OUT OLECHAR** pPath,
  2200. IN ULONG bufferSize
  2201. )
  2202. /*++
  2203. Implements:
  2204. IFsaResource::GetUncPath().
  2205. // Returns system generated UNC path if there is one. If not it returns WSB_E_NOTFOUND
  2206. --*/
  2207. {
  2208. HRESULT hr = S_OK;
  2209. CWsbStringPtr tmpString;
  2210. OLECHAR driveName[3];
  2211. try {
  2212. WsbAssert(0 != pPath, E_POINTER);
  2213. // The path is either "d:\" where d is a drive letter or "Volume{GUID}" for an
  2214. // unnamed drive. So make sure we have at least that many characters.
  2215. //
  2216. if (wcslen(m_path) >= 3) {
  2217. // There is no system created UNC path to a volume without a drive letter so
  2218. // see if the path has form of "Volume{GUID}". For a volume with no drive letter we
  2219. // store this PNP (sticky) name as the path also.
  2220. if (wcsstr(m_path, OLESTR("Volume{")) != 0) {
  2221. WsbAffirmHr(tmpString.GiveTo(pPath)); // give caller an empty string back.
  2222. }
  2223. else {
  2224. // The UNC path is \\ssss\d$, where ssss is the server name and d is the drive
  2225. // letter.
  2226. WsbAffirmHr(tmpString.TakeFrom(*pPath, bufferSize));
  2227. WsbAffirmHr(m_pFsaServer->GetName(&tmpString, 0));
  2228. WsbAffirmHr(tmpString.Prepend(OLESTR("\\\\")));
  2229. WsbAffirmHr(tmpString.Append(OLESTR("\\")));
  2230. driveName[0] = m_path[0];
  2231. driveName[1] = L'$';
  2232. driveName[2] = 0;
  2233. WsbAffirmHr(tmpString.Append(driveName));
  2234. WsbAffirmHr(tmpString.GiveTo(pPath));
  2235. }
  2236. } else {
  2237. hr = WSB_E_NOTFOUND;
  2238. }
  2239. } WsbCatch(hr);
  2240. return(hr);
  2241. }
  2242. HRESULT
  2243. CFsaResource::GetUsnId(
  2244. OUT ULONGLONG *usnId
  2245. )
  2246. /*++
  2247. Implements:
  2248. IFsaResource::GetUsnId().
  2249. --*/
  2250. {
  2251. HRESULT hr = S_OK;
  2252. try {
  2253. WsbAssert(0 != usnId, E_POINTER);
  2254. *usnId = m_usnJournalId;
  2255. } WsbCatch(hr);
  2256. return(hr);
  2257. }
  2258. HRESULT
  2259. CFsaResource::Init(
  2260. IN IFsaServer* pFsaServer,
  2261. IN OLECHAR* path,
  2262. IN OLECHAR* dosName
  2263. )
  2264. /*++
  2265. Implements:
  2266. IFsaResourcePriv::Init().
  2267. Routine Description:
  2268. This routine implements the COM method for testing a resource to see if it is
  2269. 'manageable' by the HSM (Remote Storage) system. (Only NTFS-formatted
  2270. volumes which support sparse files and reparse points are considered to be
  2271. manageable by Sakkara.) If the resource is manageable, it initializes the
  2272. resource object.
  2273. Arguments:
  2274. pFsaServer - Interface pointer to the FSA service that is scanning this resource.
  2275. path - The long ugly PNP name that can be used if there is no drive letter for
  2276. the resource being tested (i.e., it is mounted as a volume without a
  2277. drive letter).
  2278. dosName - The drive letter (if there is one) of the resource being tested.
  2279. Return Value:
  2280. S_OK - The call succeeded (the resource being tested was found to be manageable,
  2281. and the resource object was initialized).
  2282. FSA_E_UNMANAGEABLE - Thrown if the resource being tested for manageability is
  2283. found to be unmanageable.
  2284. FSA_E_NOMEDIALOADED - Thrown if the resource being tested for manageability is
  2285. a removable type of drive and no media is presently loaded.
  2286. E_POINTER - Thrown if the path argument passed in is null.
  2287. Any other value - The call failed because one of the Remote Storage or Win32 API
  2288. calls contained internally in this method failed. The error value returned
  2289. is specific to the API call which failed.
  2290. --*/
  2291. {
  2292. HRESULT hr = FSA_E_UNMANAGABLE;
  2293. UINT type;
  2294. UINT lastErrorMode;
  2295. BOOL gotInfo = FALSE;
  2296. OLECHAR alternatePath[256];
  2297. CWsbStringPtr queryPath;
  2298. WsbTraceIn(OLESTR("CFsaResource::Init"), OLESTR("path = <%ls>, dosName = <%ls>"),
  2299. (OLECHAR *)path, (OLECHAR *)dosName);
  2300. try {
  2301. WsbAssert(0 != path, E_POINTER);
  2302. // Determine type of drive (removable, fixed, CD-ROM, RAM or network).
  2303. type = GetDriveType(path);
  2304. // Only FIXED or removable media are candidates for management
  2305. // (ignore network drives, ...).
  2306. //
  2307. // NOTE: For now, it has been decided not to allow removable media.
  2308. // if ((type == DRIVE_FIXED) || (type == DRIVE_REMOVABLE)) {
  2309. if (type == DRIVE_FIXED) {
  2310. // Get more information about the resource. For removable drives, we want to
  2311. // fail if no volume is located.
  2312. m_name.Realloc(128); // volume name
  2313. m_fsName.Realloc(128); // volume file system type (e.g., FAT, NTFS)
  2314. if (type == DRIVE_REMOVABLE) {
  2315. // Suppress OS message asking to install a volume in the drive if it is
  2316. // found to be missing.
  2317. // First get the current error-mode bit flags by clearing them.
  2318. lastErrorMode = SetErrorMode(0);
  2319. // Reset error-mode bit flags by 'or'ing them with the value which
  2320. // suppresses critical error messages.
  2321. SetErrorMode(lastErrorMode | SEM_FAILCRITICALERRORS);
  2322. gotInfo = GetVolumeInformation(path, m_name, 128, &m_serial,
  2323. &m_maxComponentLength, &m_fsFlags, m_fsName, 128);
  2324. // Got resource info, reset error-mode bit flags to original setting.
  2325. SetErrorMode(lastErrorMode);
  2326. // Throw and abort if no volume loaded.
  2327. WsbAffirm(gotInfo, FSA_E_NOMEDIALOADED);
  2328. } else { // if drive is a fixed drive type:
  2329. // This call can fail. This should just cause a message to be logged
  2330. // and the resource to be skipped.
  2331. try {
  2332. WsbAffirmStatus(GetVolumeInformation(path, m_name, 128, &m_serial,
  2333. &m_maxComponentLength, &m_fsFlags, m_fsName, 128));
  2334. } WsbCatchAndDo(hr,
  2335. WsbLogEvent(FSA_MESSAGE_RSCFAILEDINIT, 0, NULL, WsbHrAsString(hr),
  2336. WsbAbbreviatePath(path, 120), 0);
  2337. WsbThrow(FSA_E_UNMANAGABLE);
  2338. );
  2339. }
  2340. // Trace out info about the volume.
  2341. CWsbStringPtr traceString;
  2342. traceString = m_fsName;
  2343. traceString.Append(OLESTR(" file system, supports ... "));
  2344. // Note that MS removed support for Remote Storage bit flag.
  2345. if ((m_fsFlags & FILE_SUPPORTS_REPARSE_POINTS) != 0) {
  2346. traceString.Append(OLESTR("reparse points ... "));
  2347. }
  2348. if ((m_fsFlags & FILE_SUPPORTS_SPARSE_FILES) != 0) {
  2349. traceString.Append(OLESTR("sparse files ... "));
  2350. }
  2351. traceString.Append(OLESTR("\n"));
  2352. WsbTrace(traceString);
  2353. // Currently, we only support NTFS volumes that support sparse files and
  2354. // reparse points (since support for Remote Storage bit flag was removed).
  2355. if ((_wcsicmp(m_fsName, OLESTR("NTFS")) == 0) &&
  2356. ((m_fsFlags & FILE_SUPPORTS_SPARSE_FILES) != 0) &&
  2357. ((m_fsFlags & FILE_SUPPORTS_REPARSE_POINTS) != 0)) {
  2358. // Indicate this is a manageable volume.
  2359. hr = S_OK;
  2360. // Store the parent FSA, but since it is a weak reference, do not AddRef().
  2361. m_pFsaServer = pFsaServer;
  2362. // Store the "sticky" name - this is the long ugly PNP name that can be
  2363. // used if there is no drive letter. (skip the prefix - \\?\)
  2364. m_stickyName = &path[4];
  2365. // Store the path to the resource. Use the drive letter if it is present
  2366. // (dosName != NULL and contains drive letter), else store it to be the same as the "sticky name".
  2367. if (NULL != dosName) {
  2368. if ((wcslen(dosName) == 2) && (dosName[wcslen(dosName)-1] == L':')) {
  2369. m_path = dosName;
  2370. m_path.Append(OLESTR("\\"));
  2371. } else {
  2372. // It is a mount point path
  2373. m_path = &path[4];
  2374. }
  2375. } else {
  2376. m_path = &path[4];
  2377. }
  2378. WsbTrace(OLESTR("CFsaResource::Init - m_path = %ws\n"), (WCHAR *) m_path);
  2379. // Now save the "User Friendly" name for the resource. If there is a
  2380. // drive letter it is used. If it is an unnamed volume then there is
  2381. // no user friendly name and a NULL string is stored. The volume name
  2382. // should also be shown in this case.
  2383. if (NULL != dosName) {
  2384. m_userName = dosName;
  2385. m_userName.Append(OLESTR("\\"));
  2386. } else {
  2387. m_userName = L"";
  2388. }
  2389. WsbTrace(OLESTR("CFsaResource::Init - UserPath = %ws\n"), (WCHAR *) m_userName);
  2390. // Get the alternate path to the resource. This requires removing the '\'
  2391. // from the path.
  2392. queryPath = &path[4];
  2393. if (L'\\' == queryPath[(int) wcslen((WCHAR *) queryPath) - 1]) {
  2394. queryPath[(int) wcslen((WCHAR *) queryPath) - 1] = L'\0';
  2395. }
  2396. WsbTrace(OLESTR("CFsaResource::Init - QueryPath = %ws\n"),
  2397. (WCHAR *) queryPath);
  2398. WsbAffirm(QueryDosDevice(queryPath, alternatePath, 256) != 0,
  2399. HRESULT_FROM_WIN32(GetLastError()));
  2400. m_alternatePath = alternatePath;
  2401. //
  2402. // Get the unique id for the volume
  2403. //
  2404. WsbAffirmHr(ReadIdentifier());
  2405. }
  2406. }
  2407. m_isDirty = TRUE;
  2408. } WsbCatch(hr);
  2409. WsbTraceOut(OLESTR("CFsaResource::Init"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2410. return(hr);
  2411. }
  2412. HRESULT
  2413. CFsaResource::InitializePremigrationList(
  2414. BOOL bStartValidateJob
  2415. )
  2416. /*++
  2417. Routine Description:
  2418. If this volume is managed & active & available: create or
  2419. open the premigration-list DB; schedule a validate job if requested;
  2420. if recovery is also done, start the truncator running.
  2421. Arguments:
  2422. bStartValidateJob - If TRUE, schedule a validate job on this volume
  2423. if we just created a new DB
  2424. Return Value:
  2425. S_OK - The call succeeded.
  2426. S_FALSE - The actions were skipped because some condition was not met
  2427. E_* - An error occurred.
  2428. --*/
  2429. {
  2430. HRESULT hr = S_OK;
  2431. WsbTraceIn(OLESTR("CFsaResource::InitializePremigrationList"),
  2432. OLESTR("m_managingHsm = %ls, m_isActive = %ls, m_isAvailable = %ls, m_isDbInitialized = %ls, m_isRecovered = %ls"),
  2433. WsbGuidAsString(m_managingHsm), WsbBoolAsString(m_isActive),
  2434. WsbBoolAsString(m_isAvailable), WsbBoolAsString(m_isDbInitialized),
  2435. WsbBoolAsString(m_isRecovered));
  2436. try {
  2437. if ((S_OK == IsManaged()) && m_isActive && m_isAvailable) {
  2438. // Create/open the DB if not done already
  2439. if (!m_isDbInitialized) {
  2440. BOOL bCreated;
  2441. CWsbStringPtr dbPath;
  2442. CComPtr<IWsbDbSys> pDbSys;
  2443. WsbAffirmHr(m_pFsaServer->GetIDbSys(&pDbSys));
  2444. WsbAffirmHr(GetDbPath(&dbPath, 0));
  2445. WsbAffirmHr(m_pPremigrated->Init(dbPath, pDbSys, &bCreated));
  2446. m_isDbInitialized = TRUE;
  2447. if (bCreated) {
  2448. // Can't have recovery records if we just created
  2449. // the DB
  2450. m_isRecovered = TRUE;
  2451. }
  2452. if (bCreated && bStartValidateJob) {
  2453. LARGE_INTEGER ctime;
  2454. FILETIME curTime;
  2455. SYSTEMTIME sysTime;
  2456. CWsbStringPtr tmpString;
  2457. // Determine if the Engine is up and running. If it isn't
  2458. // we have to set a value in the registry that the Engine
  2459. // will find when it comes up and it will schedule the
  2460. // validate job. If the Engine is up, we can take care of
  2461. // scheduling the validate job ourselves. (If we don't, the
  2462. // Engine won't do it until the next time it starts up.)
  2463. hr = WsbCheckService(NULL, APPID_RemoteStorageEngine);
  2464. if (S_OK != hr) {
  2465. // "Schedule" a validate job to rebuild the premigration list.
  2466. // This is done by putting a value in the registry since the Engine
  2467. // may not be running right now so we can't set up a job.
  2468. WsbLogEvent(FSA_MESSAGE_PREMIGRATION_LIST_MISSING, 0, NULL,
  2469. (OLECHAR *) m_path, NULL);
  2470. WsbAffirmHr(tmpString.Alloc(32));
  2471. swprintf((OLECHAR *) tmpString, L"%x", m_serial);
  2472. GetSystemTime( &sysTime );
  2473. WsbAffirmStatus(SystemTimeToFileTime(&sysTime, &curTime));
  2474. ctime.LowPart = curTime.dwLowDateTime;
  2475. ctime.HighPart = curTime.dwHighDateTime;
  2476. WsbAffirmHr( WsbEnsureRegistryKeyExists( 0, FSA_VALIDATE_LOG_KEY_NAME ) );
  2477. WsbAffirmHr(WsbSetRegistryValueData(NULL, FSA_VALIDATE_LOG_KEY_NAME,
  2478. tmpString, (BYTE *) &ctime, sizeof(ctime)));
  2479. } else {
  2480. WsbAffirmHr(CheckForValidate(TRUE));
  2481. }
  2482. }
  2483. }
  2484. // Start the auto-truncator if recovery is done
  2485. if (m_pTruncator && m_isRecovered) {
  2486. // Try starting the truncator; ignore errors (we get one if
  2487. // truncator is already started)
  2488. m_pTruncator->Start((IFsaResource*) this);
  2489. }
  2490. }
  2491. } WsbCatch(hr);
  2492. WsbTraceOut(OLESTR("CFsaResource::InitializePremigrationList"), OLESTR("hr = <%ls>"),
  2493. WsbHrAsString(hr));
  2494. return(hr);
  2495. }
  2496. HRESULT
  2497. CFsaResource::InitializeUnmanageDb(
  2498. void
  2499. )
  2500. /*++
  2501. Implements:
  2502. IFsaResourcePriv::InitializeUnmanageDb().
  2503. --*/
  2504. {
  2505. HRESULT hr = S_OK;
  2506. WsbTraceIn(OLESTR("CFsaResource::InitializeUnmanageDb"),
  2507. OLESTR("m_isActive = %ls, m_isAvailable = %ls, m_isUnmanageDbInitialized = %ls"),
  2508. WsbBoolAsString(m_isActive), WsbBoolAsString(m_isAvailable), WsbBoolAsString(m_isUnmanageDbInitialized));
  2509. try {
  2510. if ((S_OK == IsManaged()) && m_isActive && m_isAvailable) {
  2511. if (! m_pUnmanageDb) {
  2512. WsbAffirmHr(CoCreateInstance(CLSID_CFsaUnmanageDb, NULL, CLSCTX_SERVER, IID_IFsaUnmanageDb, (void**) &m_pUnmanageDb));
  2513. }
  2514. if (! m_isUnmanageDbInitialized) {
  2515. BOOL bCreated;
  2516. CWsbStringPtr dbPath;
  2517. CComPtr<IWsbDbSys> pDbSys;
  2518. // Get (and init if necessary) the idb instance
  2519. WsbAffirmHr(m_pFsaServer->GetUnmanageIDbSys(&pDbSys));
  2520. // Initialize the db
  2521. WsbAffirmHr(GetUnmanageDbPath(&dbPath, 0));
  2522. WsbAffirmHr(m_pUnmanageDb->Init(dbPath, pDbSys, &bCreated));
  2523. // Init succeeded means DB must have been created
  2524. WsbAssert(bCreated, E_UNEXPECTED);
  2525. m_isUnmanageDbInitialized = TRUE;
  2526. }
  2527. } else {
  2528. hr = WSB_E_RESOURCE_UNAVAILABLE;
  2529. }
  2530. } WsbCatch(hr);
  2531. WsbTraceOut(OLESTR("CFsaResource::InitializeUnmanageDb"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2532. return(hr);
  2533. }
  2534. HRESULT
  2535. CFsaResource::TerminateUnmanageDb(
  2536. void
  2537. )
  2538. /*++
  2539. Implements:
  2540. IFsaResourcePriv::TerminateUnmanageDb().
  2541. --*/
  2542. {
  2543. HRESULT hr = S_OK;
  2544. WsbTraceIn(OLESTR("CFsaResource::TerminateUnmanageDb"),
  2545. OLESTR("m_isUnmanageDbInitialized = %ls"), WsbBoolAsString(m_isUnmanageDbInitialized));
  2546. try {
  2547. if (m_isUnmanageDbInitialized) {
  2548. WsbTrace(OLESTR("CFsaResource::TerminateUnmanageDb: Deleting Unmanage Db\n"));
  2549. hr = m_pUnmanageDb->Delete(NULL, IDB_DELETE_FLAG_NO_ERROR);
  2550. WsbTrace(OLESTR("CFsaResource::TerminateUnmanageDb: Deleting of Unmanage Db complete, hr = <%ls>\n"),
  2551. WsbHrAsString(hr));
  2552. if (SUCCEEDED(hr)) {
  2553. m_isUnmanageDbInitialized = FALSE;
  2554. m_pUnmanageDb = NULL;
  2555. }
  2556. }
  2557. } WsbCatch(hr);
  2558. WsbTraceOut(OLESTR("CFsaResource::TerminateUnmanageDb"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2559. return(hr);
  2560. }
  2561. HRESULT
  2562. CFsaResource::IsActive(
  2563. void
  2564. )
  2565. /*++
  2566. Implements:
  2567. IFsaResource::IsActive().
  2568. --*/
  2569. {
  2570. return(m_isActive ? S_OK : S_FALSE);
  2571. }
  2572. HRESULT
  2573. CFsaResource::IsAvailable(
  2574. void
  2575. )
  2576. /*++
  2577. Implements:
  2578. IFsaResource::IsAvailable().
  2579. --*/
  2580. {
  2581. return(m_isAvailable ? S_OK : S_FALSE);
  2582. }
  2583. HRESULT
  2584. CFsaResource::IsDeletePending(
  2585. void
  2586. )
  2587. /*++
  2588. Implements:
  2589. IFsaResource::IsDeletePending().
  2590. --*/
  2591. {
  2592. return(m_isDeletePending ? S_OK : S_FALSE);
  2593. }
  2594. HRESULT
  2595. CFsaResource::IsManaged(
  2596. void
  2597. )
  2598. /*++
  2599. Implements:
  2600. IFsaResource::IsManaged().
  2601. --*/
  2602. {
  2603. HRESULT hr = S_OK;
  2604. if (memcmp(&m_managingHsm, &GUID_NULL, sizeof(GUID)) == 0) {
  2605. hr = S_FALSE;
  2606. }
  2607. return(hr);
  2608. }
  2609. HRESULT
  2610. CFsaResource::Load(
  2611. IN IStream* pStream
  2612. )
  2613. /*++
  2614. Implements:
  2615. IPersistStream::Load().
  2616. --*/
  2617. {
  2618. HRESULT hr = S_OK;
  2619. CComPtr<IPersistStream> pPersistStream;
  2620. CComPtr<IWsbCollectable> pCollectable;
  2621. WsbTraceIn(OLESTR("CFsaResource::Load"), OLESTR(""));
  2622. try {
  2623. ULONG tmp;
  2624. WsbAssert(0 != pStream, E_POINTER);
  2625. // Do the easy stuff, but make sure that this order matches the order
  2626. // in the save method.
  2627. WsbAffirmHr(WsbLoadFromStream(pStream, &m_oldPath, 0));
  2628. WsbAffirmHr(WsbLoadFromStream(pStream, &m_alternatePath, 0));
  2629. WsbAffirmHr(WsbLoadFromStream(pStream, &m_name, 0));
  2630. WsbAffirmHr(WsbLoadFromStream(pStream, &m_stickyName, 0));
  2631. WsbAffirmHr(WsbLoadFromStream(pStream, &m_fsName, 0));
  2632. WsbAffirmHr(WsbLoadFromStream(pStream, &m_maxComponentLength));
  2633. WsbAffirmHr(WsbLoadFromStream(pStream, &m_fsFlags));
  2634. WsbAffirmHr(WsbLoadFromStream(pStream, &m_id));
  2635. WsbAffirmHr(WsbLoadFromStream(pStream, &m_isActive));
  2636. WsbAffirmHr(WsbLoadFromStream(pStream, &tmp));
  2637. m_compareBy = (FSA_RESOURCE_COMPARE)tmp;
  2638. WsbAffirmHr(WsbLoadFromStream(pStream, &m_managingHsm));
  2639. WsbAffirmHr(WsbLoadFromStream(pStream, &m_hsmLevel));
  2640. WsbAffirmHr(WsbLoadFromStream(pStream, &m_premigratedSize));
  2641. WsbAffirmHr(WsbLoadFromStream(pStream, &m_truncatedSize));
  2642. WsbAffirmHr(WsbLoadFromStream(pStream, &m_manageableItemLogicalSize));
  2643. WsbAffirmHr(WsbLoadFromStream(pStream, &m_manageableItemAccessTimeIsRelative));
  2644. WsbAffirmHr(WsbLoadFromStream(pStream, &m_manageableItemAccessTime));
  2645. WsbAffirmHr(WsbLoadFromStream(pStream, &m_usnJournalId));
  2646. WsbAffirmHr(WsbLoadFromStream(pStream, &m_lastUsnId));
  2647. // Load the default rules list
  2648. WsbAffirm(m_pDefaultRules != NULL, E_UNEXPECTED);
  2649. WsbAffirmHr((m_pDefaultRules)->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  2650. WsbAffirmHr(pPersistStream->Load(pStream));
  2651. pPersistStream = 0;
  2652. // Load the premigration list DB
  2653. WsbAffirm(m_pPremigrated != NULL, E_UNEXPECTED);
  2654. WsbAffirmHr(((IWsbDb*)m_pPremigrated)->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  2655. hr = pPersistStream->Load(pStream);
  2656. WsbTrace(OLESTR("CFsaResource::Load, DB load hr = <%ls>\n"), WsbHrAsString(hr));
  2657. if (S_OK == hr) {
  2658. m_isDbInitialized = TRUE;
  2659. } else {
  2660. m_isDbInitialized = FALSE;
  2661. hr = S_OK;
  2662. }
  2663. pPersistStream = 0;
  2664. // Load the truncator.
  2665. WsbAffirm(m_pTruncator != NULL, E_UNEXPECTED);
  2666. WsbAffirmHr(m_pTruncator->QueryInterface(IID_IPersistStream, (void**) &pPersistStream));
  2667. WsbAffirmHr(pPersistStream->Load(pStream));
  2668. pPersistStream = 0;
  2669. } WsbCatch(hr);
  2670. WsbTraceOut(OLESTR("CFsaResource::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2671. return(hr);
  2672. }
  2673. HRESULT
  2674. CFsaResource::Manage(
  2675. IN IFsaScanItem* pScanItem,
  2676. IN LONGLONG /*offset*/,
  2677. IN LONGLONG /*size*/,
  2678. IN GUID storagePoolId,
  2679. IN BOOL truncate
  2680. )
  2681. /*++
  2682. Implements:
  2683. IFsaResource::Manage().
  2684. --*/
  2685. {
  2686. HRESULT hr = S_OK;
  2687. CComPtr<IFsaPostIt> pWorkItem;
  2688. CComPtr<IHsmFsaTskMgr> pEngine;
  2689. CComPtr<IHsmSession> pSession;
  2690. CWsbStringPtr tmpString;
  2691. LONGLONG fileVersionId;
  2692. LONGLONG requestSize;
  2693. WsbTraceIn(OLESTR("CFsaResource::Manage"), OLESTR(""));
  2694. try {
  2695. // Make sure the Scan Item interface is OK
  2696. WsbAssert(pScanItem != 0, E_POINTER);
  2697. WsbAffirmHr(CoCreateInstance(CLSID_CFsaPostIt, 0, CLSCTX_SERVER, IID_IFsaPostIt, (void**) &pWorkItem));
  2698. // Get the data from the scan item.
  2699. WsbAffirmHr(pScanItem->GetSession(&pSession));
  2700. WsbAffirmHr(pWorkItem->SetSession(pSession));
  2701. WsbAffirmHr(pScanItem->GetPathAndName(0, &tmpString, 0));
  2702. WsbAffirmHr(pScanItem->GetVersionId(&fileVersionId));
  2703. WsbAffirmHr(pWorkItem->SetFileVersionId(fileVersionId));
  2704. // Currently, we only can ask for the whole file.
  2705. WsbAffirmHr(pWorkItem->SetRequestOffset(0));
  2706. WsbAffirmHr(pScanItem->GetLogicalSize(&requestSize));
  2707. WsbAffirmHr(pWorkItem->SetRequestSize(requestSize));
  2708. // Fill in the rest of the work
  2709. WsbAffirmHr(pWorkItem->SetStoragePoolId(storagePoolId));
  2710. WsbAffirmHr(pWorkItem->SetRequestAction(FSA_REQUEST_ACTION_PREMIGRATE));
  2711. if (truncate) {
  2712. WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_TRUNCATE));
  2713. } else {
  2714. WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_LIST));
  2715. }
  2716. // Send the request to the task manager
  2717. WsbAffirmHr(GetHsmEngine(&pEngine));
  2718. WsbAffirmHr(pWorkItem->SetPath(tmpString));
  2719. WsbAffirmHr(pScanItem->PrepareForManage(0, requestSize));
  2720. WsbAffirmHr(pEngine->DoFsaWork(pWorkItem));
  2721. } WsbCatch(hr);
  2722. WsbTraceOut(OLESTR("CFsaResource::Manage"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2723. return(hr);
  2724. }
  2725. HRESULT
  2726. CFsaResource::ManagedBy(
  2727. IN GUID hsmId,
  2728. IN ULONG hsmLevel,
  2729. IN BOOL release
  2730. )
  2731. /*++
  2732. Implements:
  2733. IFsaResource::ManagedBy().
  2734. --*/
  2735. {
  2736. HRESULT hr = S_OK;
  2737. CComPtr<IHsmSession> pSession;
  2738. HANDLE threadHandle;
  2739. WsbTraceIn(OLESTR("CFsaResource::ManagedBy"), OLESTR("HsmId - <%ls>, hsmLevel - <%lu>, release = <%ls>"),
  2740. WsbGuidAsString(hsmId), hsmLevel, WsbBoolAsString(release));
  2741. try {
  2742. // Are we releasing or acquiring a managing HSM?
  2743. if (release) {
  2744. // We can only release if we are the orignal owner. This is to prevent two HSMs from thinking they
  2745. // manage the same resource at the same time. We may want a better way to do this.
  2746. WsbAffirm(memcmp(&m_managingHsm, &hsmId, sizeof(GUID)) == 0, FSA_E_RSCALREADYMANAGED);
  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. // Clear out the managing Hsm.
  2753. m_managingHsm = GUID_NULL;
  2754. m_pHsmEngine = 0;
  2755. m_isDeletePending = FALSE;
  2756. threadHandle = CreateThread(0, 0, FsaStartOnStateChange, (void*) this, 0, &g_ThreadId);
  2757. if (threadHandle != NULL) {
  2758. CloseHandle(threadHandle);
  2759. }
  2760. } else {
  2761. // Make sure there is a journal
  2762. // At this point we don't care about the need to
  2763. // validate
  2764. BOOL validateNeeded;
  2765. WsbAffirmHr(CheckForJournal(&validateNeeded));
  2766. // Is the id changing?
  2767. if (memcmp(&m_managingHsm, &hsmId, sizeof(GUID)) != 0) {
  2768. // Make sure that they set it to something valid.
  2769. WsbAssert(memcmp(&GUID_NULL, &hsmId, sizeof(GUID)) != 0, E_INVALIDARG);
  2770. // If the truncator is running, then ask it to stop.
  2771. WsbAffirmHr(m_pTruncator->GetSession(&pSession));
  2772. if (pSession != 0) {
  2773. WsbAffirmHr(pSession->ProcessEvent(HSM_JOB_PHASE_ALL, HSM_JOB_EVENT_CANCEL));
  2774. }
  2775. // Create/Recreate the default rules.
  2776. WsbAffirmHr(CreateDefaultRules());
  2777. // Store the Id and level.
  2778. m_managingHsm = hsmId;
  2779. m_hsmLevel = hsmLevel;
  2780. m_pHsmEngine = 0;
  2781. // Do recovery (if needed) and start truncator
  2782. if (m_isActive) {
  2783. if (m_isDbInitialized && !m_isRecovered) {
  2784. // DoRecovery will start truncator when it is done
  2785. WsbAffirmHr(DoRecovery());
  2786. } else {
  2787. WsbAffirmHr(InitializePremigrationList(TRUE));
  2788. }
  2789. }
  2790. threadHandle = CreateThread(0, 0, FsaStartOnStateChange, (void*) this, 0, &g_ThreadId);
  2791. if (threadHandle != NULL) {
  2792. CloseHandle(threadHandle);
  2793. }
  2794. } else {
  2795. BOOL DoKick = FALSE;
  2796. if (m_hsmLevel < hsmLevel) {
  2797. DoKick = TRUE;
  2798. }
  2799. m_hsmLevel = hsmLevel;
  2800. // Create/Recreate the default rules.
  2801. WsbAffirmHr(CreateDefaultRules());
  2802. // Wake up the AutoTruncator if the new level is higher
  2803. if (DoKick) {
  2804. WsbAffirmHr(m_pTruncator->KickStart());
  2805. }
  2806. }
  2807. }
  2808. m_isDirty = TRUE;
  2809. } WsbCatch(hr);
  2810. WsbTraceOut(OLESTR("CFsaResource::ManagedBy"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2811. return(hr);
  2812. }
  2813. HRESULT
  2814. CFsaResource::NeedsRepair(
  2815. void
  2816. )
  2817. /*++
  2818. Implements:
  2819. IFsaResource::NeedsRepair().
  2820. --*/
  2821. {
  2822. HRESULT hr = S_OK;
  2823. ULONG flag;
  2824. IO_STATUS_BLOCK Iosb;
  2825. CWsbStringPtr volumePath;
  2826. HANDLE volumeHandle = INVALID_HANDLE_VALUE;
  2827. WsbTraceIn(OLESTR("CFsaResource::NeedsRepair"), OLESTR(""));
  2828. try {
  2829. volumePath = L"\\\\.\\";
  2830. WsbAffirmHr(volumePath.Append(m_path));
  2831. ((OLECHAR *) volumePath)[wcslen(volumePath) - 1] = L'\0';
  2832. WsbAffirmHandle(volumeHandle = CreateFileW(volumePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL));
  2833. WsbAffirmNtStatus(NtFsControlFile(volumeHandle, NULL, NULL, NULL, &Iosb, FSCTL_IS_VOLUME_DIRTY, NULL, 0, &flag, sizeof(flag)));
  2834. WsbAffirmNtStatus(Iosb.Status);
  2835. if ((flag & VOLUME_IS_DIRTY) == 0) {
  2836. hr = S_FALSE;
  2837. }
  2838. } WsbCatch(hr);
  2839. if (INVALID_HANDLE_VALUE != volumeHandle) {
  2840. CloseHandle(volumeHandle);
  2841. }
  2842. WsbTraceOut(OLESTR("CFsaResource::NeedsRepair"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  2843. return(hr);
  2844. }
  2845. HRESULT
  2846. CFsaResource::ProcessResult(
  2847. IN IFsaPostIt* pResult
  2848. )
  2849. /*++
  2850. Implements:
  2851. IFsaResource::ProcessResult().
  2852. --*/
  2853. {
  2854. HRESULT hr = S_OK;
  2855. CComPtr<IFsaScanItem> pScanItem;
  2856. CComPtr<IHsmSession> pSession;
  2857. FILETIME currentTime;
  2858. FSA_RESULT_ACTION resultAction = FSA_RESULT_ACTION_NONE;
  2859. FSA_PLACEHOLDER placeholder;
  2860. CWsbStringPtr path;
  2861. LONGLONG offset;
  2862. LONGLONG size;
  2863. ULONG mode;
  2864. HRESULT resultHr;
  2865. CComPtr<IFsaFilterRecall> pRecall;
  2866. ULONG completionSent = FALSE;
  2867. LONGLONG usn;
  2868. LONGLONG afterPhUsn;
  2869. WsbTraceIn(OLESTR("CFsaResource::ProcessResult"), OLESTR(""));
  2870. try {
  2871. BOOL wasPremigrated = FALSE;
  2872. BOOL wasTruncated = FALSE;
  2873. // Several of the actions need to know the current time, so calculate it now.
  2874. GetSystemTimeAsFileTime(&currentTime);
  2875. // Since the workItem session is IUnknown, QI for what we want.
  2876. WsbAffirmHr(pResult->GetSession(&pSession));
  2877. // Now perform the required action.
  2878. WsbAffirmHr(pResult->GetResultAction(&resultAction));
  2879. WsbAffirmHr(pResult->GetPlaceholder(&placeholder));
  2880. WsbAffirmHr(pResult->GetPath(&path, 0));
  2881. WsbAffirmHr(pResult->GetRequestOffset(&offset));
  2882. WsbAffirmHr(pResult->GetRequestSize(&size));
  2883. WsbAffirmHr(pResult->GetMode(&mode));
  2884. WsbAffirmHr(pResult->GetUSN(&usn));
  2885. WsbTrace(OLESTR("CFsaResource::ProcessResult, path = <%ls>, requestOffset = %I64d, requestSize = %I64d\n"),
  2886. WsbAbbreviatePath(path, 120), offset, size);
  2887. switch(resultAction) {
  2888. case FSA_RESULT_ACTION_DELETE:
  2889. WsbTrace(OLESTR("CFsaResource::ProcessResult - Delete\n"));
  2890. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  2891. if (S_OK == pScanItem->IsPremigrated(offset, size)) {
  2892. wasPremigrated = TRUE;
  2893. } else if (S_OK == pScanItem->IsTruncated(offset, size)) {
  2894. wasTruncated = TRUE;
  2895. }
  2896. WsbAffirmHr(pScanItem->Delete());
  2897. if (wasPremigrated) {
  2898. WsbAffirmHr(RemovePremigrated(pScanItem, offset, size));
  2899. } else if (wasTruncated) {
  2900. WsbAffirmHr(RemoveTruncated(pScanItem, offset, size));
  2901. }
  2902. break;
  2903. case FSA_RESULT_ACTION_DELETEPLACEHOLDER:
  2904. WsbTrace(OLESTR("CFsaResource::ProcessResult - Delete Placeholder\n"));
  2905. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  2906. // We shouldn't have gotten to here if the file isn't managed,
  2907. // but it's been known to happen
  2908. if (S_OK == pScanItem->IsManaged(offset, size)) {
  2909. HRESULT hrRemove = S_OK;
  2910. if (S_OK == pScanItem->IsPremigrated(offset, size)) {
  2911. wasPremigrated = TRUE;
  2912. } else if (S_OK == pScanItem->IsTruncated(offset, size)) {
  2913. wasTruncated = TRUE;
  2914. }
  2915. // RemovePremigrated needs to get some information from the placeholder, therefore, remove
  2916. // from premigrated db first and then (regardless of the result), delete the placeholder
  2917. if (wasPremigrated) {
  2918. hrRemove = RemovePremigrated(pScanItem, offset, size);
  2919. } else if (wasTruncated) {
  2920. hrRemove = RemoveTruncated(pScanItem, offset, size);
  2921. }
  2922. WsbAffirmHr(pScanItem->DeletePlaceholder(offset, size));
  2923. WsbAffirmHr(hrRemove);
  2924. }
  2925. // Remove the recovery record if we created one
  2926. if (m_isDbInitialized) {
  2927. BOOL bOpenDb = FALSE;
  2928. CComPtr<IWsbDbSession> pDbSession;
  2929. CComPtr<IFsaRecoveryRec> pRecRec;
  2930. try {
  2931. WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
  2932. bOpenDb = TRUE;
  2933. WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, RECOVERY_REC_TYPE,
  2934. IID_IFsaRecoveryRec, (void**) &pRecRec));
  2935. WsbAffirmHr(pRecRec->SetPath(path));
  2936. if (S_OK == pRecRec->FindEQ()) {
  2937. WsbAffirmHr(pRecRec->Remove());
  2938. }
  2939. } WsbCatch(hr);
  2940. if (bOpenDb) {
  2941. WsbAffirmHr(m_pPremigrated->Close(pDbSession));
  2942. }
  2943. }
  2944. break;
  2945. case FSA_RESULT_ACTION_LIST:
  2946. WsbTrace(OLESTR("CFsaResource::ProcessResult - Truncate / Add to Premigration List\n"));
  2947. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  2948. (placeholder).isTruncated = FALSE;
  2949. (placeholder).migrationTime = currentTime;
  2950. hr = pScanItem->CreatePlaceholder(offset, size, placeholder, TRUE, usn, &afterPhUsn);
  2951. if (SUCCEEDED(hr) && (FSA_E_REPARSE_NOT_WRITTEN_FILE_CHANGED != hr)) {
  2952. //
  2953. // Add the file to the premigration list. If this fails, log and error
  2954. // and request that the validation code be run to hopefully correct this
  2955. // problem. This problem should not stop processing, so return OK
  2956. //
  2957. hr = AddPremigrated(pScanItem, offset, size, FALSE, afterPhUsn);
  2958. if (!SUCCEEDED(hr)) {
  2959. WsbLogEvent(FSA_MESSAGE_FILE_NOT_IN_PREMIG_LIST, 0, NULL, WsbAbbreviatePath(path, 120), WsbHrAsString(hr), NULL);
  2960. //
  2961. // TBD - launch validate job
  2962. //
  2963. hr = S_OK;
  2964. }
  2965. //
  2966. // Tell the truncator that we have added something to the list in case we are over the level.
  2967. // This will kick start the truncator to insure quick response.
  2968. //
  2969. WsbAffirmHr(m_pTruncator->KickStart());
  2970. }
  2971. break;
  2972. case FSA_RESULT_ACTION_NONE:
  2973. WsbTrace(OLESTR("CFsaResource::ProcessResult - None\n"));
  2974. break;
  2975. case FSA_RESULT_ACTION_OPEN:
  2976. WsbTrace(OLESTR("CFsaResource::ProcessResult - Open (No longer placeholder)\n"));
  2977. // If it succeeded, then update the placeholder information.
  2978. WsbAffirmHr(pResult->GetResult(&resultHr));
  2979. WsbAffirmHr(pResult->GetFilterRecall(&pRecall));
  2980. WsbAssert(pRecall != 0, E_POINTER);
  2981. if (SUCCEEDED(resultHr)) {
  2982. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  2983. // The placeholder info is updated by the filter now.
  2984. // placeholder.recallTime = currentTime;
  2985. // placeholder.recallCount++;
  2986. // placeholder.isTruncated = FALSE;
  2987. // placeholder.truncateOnClose = FALSE;
  2988. // placeholder.premigrateOnClose = FALSE;
  2989. // WsbAffirmHr(pScanItem->CreatePlaceholder(offset, size, placeholder, TRUE, usn, &afterPhUsn));
  2990. }
  2991. // If it had succeeded, then add the file in the premigration list.
  2992. // (This used to be done after communicating with the filter to
  2993. // give the client time to open the file before the truncator would
  2994. // try to retruncate it. This is no longer needed since we do the
  2995. // recall on first I/O not on the open. Leaving that order created
  2996. // a new problem: the file would have a reparse point saying it was
  2997. // premigrated and test code could then try to retruncate it, but it
  2998. // wouldn't be in the premigration list yet.)
  2999. if (SUCCEEDED(resultHr)) {
  3000. //
  3001. // We do not need to fail the recall if we cannot add the file to the premigration list.
  3002. // Just log a warning, if appropriate, and continue
  3003. //
  3004. try {
  3005. WsbAffirmHr(RemoveTruncated(pScanItem, offset, size));
  3006. WsbAffirmHr(pScanItem->GetFileUsn(&afterPhUsn));
  3007. WsbAffirmHr(AddPremigrated(pScanItem, offset, size, TRUE, afterPhUsn));
  3008. } WsbCatchAndDo(hr,
  3009. //
  3010. // We failed to add it to the premigration list. In some cases this is not an error worth
  3011. // reporting. For instance, when a file is moved to another volume it is copied (causing a recall) and then
  3012. // deleted. We can get an error here if the delete is pending or has completed and the failure to
  3013. // add the original file to the premigration list is not an error since the file is now gone.
  3014. //
  3015. if ( (hr != WSB_E_NOTFOUND) &&
  3016. ((hr & ~(FACILITY_NT_BIT)) != STATUS_DELETE_PENDING) ) {
  3017. //
  3018. // Log all other errors
  3019. //
  3020. WsbLogEvent(FSA_MESSAGE_FILE_NOT_IN_PREMIG_LIST, 0, NULL,
  3021. (OLECHAR *) m_path, WsbQuickString(WsbHrAsString(hr)), NULL);
  3022. }
  3023. );
  3024. }
  3025. // Tell the filter that the recall attempt finished.
  3026. hr = pRecall->HasCompleted(resultHr);
  3027. completionSent = TRUE;
  3028. // Remove the recovery record if we created one
  3029. if (m_isDbInitialized) {
  3030. BOOL bOpenDb = FALSE;
  3031. CComPtr<IWsbDbSession> pDbSession;
  3032. CComPtr<IFsaRecoveryRec> pRecRec;
  3033. try {
  3034. WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
  3035. bOpenDb = TRUE;
  3036. WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, RECOVERY_REC_TYPE,
  3037. IID_IFsaRecoveryRec, (void**) &pRecRec));
  3038. WsbAffirmHr(pRecRec->SetPath(path));
  3039. if (S_OK == pRecRec->FindEQ()) {
  3040. WsbAffirmHr(pRecRec->Remove());
  3041. }
  3042. } WsbCatch(hr);
  3043. if (bOpenDb) {
  3044. WsbAffirmHr(m_pPremigrated->Close(pDbSession));
  3045. }
  3046. }
  3047. break;
  3048. case FSA_RESULT_ACTION_PEEK:
  3049. case FSA_RESULT_ACTION_REPARSE:
  3050. WsbTrace(OLESTR("CFsaResource::ProcessResult - Peek/Reparse\n"));
  3051. hr = E_NOTIMPL;
  3052. break;
  3053. case FSA_RESULT_ACTION_TRUNCATE:
  3054. WsbTrace(OLESTR("CFsaResource::ProcessResult - Truncate\n"));
  3055. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  3056. placeholder.isTruncated = FALSE;
  3057. placeholder.migrationTime = currentTime;
  3058. hr = pScanItem->CreatePlaceholder(offset, size, placeholder, TRUE, usn, &afterPhUsn);
  3059. if (SUCCEEDED(hr) && (FSA_E_REPARSE_NOT_WRITTEN_FILE_CHANGED != hr)) {
  3060. WsbAffirmHr(pScanItem->Truncate(offset, size));
  3061. }
  3062. break;
  3063. case FSA_RESULT_ACTION_REWRITEPLACEHOLDER:
  3064. WsbTrace(OLESTR("CFsaResource::ProcessResult - Rewrite Placeholder\n"));
  3065. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  3066. WsbAffirmHr(pScanItem->CreatePlaceholder(offset, size, placeholder, TRUE, usn, &afterPhUsn));
  3067. break;
  3068. case FSA_RESULT_ACTION_RECALLEDDATA:
  3069. WsbTrace(OLESTR("CFsaResource::ProcessResult - Recalled\n"));
  3070. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  3071. placeholder.isTruncated = FALSE;
  3072. placeholder.recallTime = currentTime;
  3073. placeholder.recallCount++;
  3074. WsbAffirmHr(pScanItem->CreatePlaceholder(offset, size, placeholder, TRUE, usn, &afterPhUsn));
  3075. WsbAffirmHr(RemoveTruncated(pScanItem, offset, size));
  3076. WsbAffirmHr(AddPremigrated(pScanItem, offset, size, FALSE, afterPhUsn));
  3077. // Remove the recovery record if we created one
  3078. if (m_isDbInitialized) {
  3079. BOOL bOpenDb = FALSE;
  3080. CComPtr<IWsbDbSession> pDbSession;
  3081. CComPtr<IFsaRecoveryRec> pRecRec;
  3082. try {
  3083. WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
  3084. bOpenDb = TRUE;
  3085. WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, RECOVERY_REC_TYPE,
  3086. IID_IFsaRecoveryRec, (void**) &pRecRec));
  3087. WsbAffirmHr(pRecRec->SetPath(path));
  3088. if (S_OK == pRecRec->FindEQ()) {
  3089. WsbAffirmHr(pRecRec->Remove());
  3090. }
  3091. } WsbCatch(hr);
  3092. if (bOpenDb) {
  3093. WsbAffirmHr(m_pPremigrated->Close(pDbSession));
  3094. }
  3095. }
  3096. break;
  3097. case FSA_RESULT_ACTION_NORECALL:
  3098. WsbTrace(OLESTR("CFsaResource::ProcessResult - Open without recall\n"));
  3099. // Tell the filter that the recall attempt finished.
  3100. WsbAffirmHr(pResult->GetResult(&resultHr));
  3101. WsbAffirmHr(pResult->GetFilterRecall(&pRecall));
  3102. WsbAssert(pRecall != 0, E_POINTER);
  3103. hr = pRecall->HasCompleted(resultHr);
  3104. completionSent = TRUE;
  3105. break;
  3106. case FSA_RESULT_ACTION_VALIDATE_BAD:
  3107. WsbTrace(OLESTR("CFsaResource::ProcessResult - Validate Bad\n"));
  3108. WsbAffirmHr(pResult->GetResult(&resultHr));
  3109. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  3110. if (S_OK == pScanItem->IsPremigrated(offset, size)) {
  3111. WsbLogEvent(FSA_MESSAGE_VALIDATE_UNMANAGED_FILE_ENGINE, 0, NULL, WsbAbbreviatePath(path, 120), (OLECHAR *)m_path, WsbHrAsString(resultHr), WsbQuickString(WsbHrAsString(resultHr)), NULL);
  3112. WsbAffirmHr(pScanItem->DeletePlaceholder(offset, size));
  3113. } else if (S_OK == pScanItem->IsTruncated(offset, size)) {
  3114. //
  3115. // We no longer delete bad placeholders here - let the diagnostic tool clean them up
  3116. // The message that is logged here has been changed to indicate that the file did not validate
  3117. // and will not be recallable until the problem is fixed.
  3118. //WsbAffirmHr(pScanItem->Delete());
  3119. WsbLogEvent(FSA_MESSAGE_VALIDATE_DELETED_FILE_ENGINE, 0, NULL, WsbAbbreviatePath(path, 120), (OLECHAR *) m_path, WsbHrAsString(resultHr), WsbQuickString(WsbHrAsString(resultHr)), NULL);
  3120. }
  3121. break;
  3122. case FSA_RESULT_ACTION_VALIDATE_OK:
  3123. WsbTrace(OLESTR("CFsaResource::ProcessResult - Validate OK\n"));
  3124. if (m_isDoingValidate) {
  3125. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  3126. if (S_OK == pScanItem->IsPremigrated(offset, size)) {
  3127. WsbAffirmHr(AddPremigrated(pScanItem, offset, size, FALSE, usn));
  3128. } else if (S_OK == pScanItem->IsTruncated(offset, size)) {
  3129. WsbAffirmHr(AddTruncated(pScanItem, offset, size));
  3130. }
  3131. }
  3132. break;
  3133. case FSA_RESULT_ACTION_VALIDATE_FOR_TRUNCATE_BAD:
  3134. WsbTrace(OLESTR("CFsaResource::ProcessResult - Validate for truncate Bad\n"));
  3135. //
  3136. // The file did not validate - make it back into a real file
  3137. //
  3138. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  3139. if (S_OK == pScanItem->IsPremigrated(offset, size)) {
  3140. WsbAffirmHr(pScanItem->DeletePlaceholder(offset, size));
  3141. }
  3142. break;
  3143. case FSA_RESULT_ACTION_VALIDATE_FOR_TRUNCATE_OK:
  3144. WsbTrace(OLESTR("CFsaResource::ProcessResult - Validate for truncate OK\n"));
  3145. //
  3146. // The file validated - go ahead and truncate it (if it has not changed)
  3147. //
  3148. WsbAffirmHr(FindFirst(path, pSession, &pScanItem));
  3149. WsbAffirmHr(pScanItem->TruncateValidated(offset, size));
  3150. break;
  3151. default:
  3152. WsbAssert(FALSE, E_FAIL);
  3153. break;
  3154. }
  3155. } WsbCatchAndDo(hr,
  3156. if (completionSent == FALSE) {
  3157. switch(resultAction) {
  3158. //
  3159. //If it was a demand recall we must make all effort to let them know it failed
  3160. //
  3161. case FSA_RESULT_ACTION_OPEN:
  3162. case FSA_RESULT_ACTION_NORECALL:
  3163. WsbTrace(OLESTR("CFsaResource::ProcessResult - Open (No longer placeholder)\n"));
  3164. // Tell the filter that the recall attempt finished.
  3165. pRecall = 0; // Just in case we already had the interfae we deref it here.
  3166. hr = pResult->GetFilterRecall(&pRecall);
  3167. if (hr == S_OK) {
  3168. hr = pRecall->HasCompleted(E_FAIL);
  3169. }
  3170. break;
  3171. default:
  3172. break;
  3173. }
  3174. }
  3175. );
  3176. WsbTraceOut(OLESTR("CFsaResource::ProcessResult"), OLESTR("hr = %ls"), WsbHrAsString(hr));
  3177. return(hr);
  3178. }
  3179. HRESULT
  3180. CFsaResource::ReadIdentifier(
  3181. void
  3182. )
  3183. /*++
  3184. --*/
  3185. {
  3186. HRESULT hr = S_OK;
  3187. CWsbStringPtr tmpString;
  3188. HANDLE aHandle;
  3189. ULONG size;
  3190. UCHAR bytes[sizeof(m_id)];
  3191. PUCHAR bytePtr;
  3192. UCHAR buffer[sizeof(FILE_FS_VOLUME_INFORMATION)+MAX_PATH];
  3193. PFILE_FS_VOLUME_INFORMATION volInfo;
  3194. NTSTATUS status = STATUS_SUCCESS;
  3195. IO_STATUS_BLOCK ioStatus;
  3196. WCHAR * wString = NULL;
  3197. try {
  3198. //
  3199. // The identifier is composed of:
  3200. //
  3201. // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
  3202. // 0 0 0 0 <---------Volume Creation Time--------> <Volume Serial Number>
  3203. // We need to open a handle to the volume
  3204. //
  3205. tmpString = m_path;
  3206. WsbAffirmHr(tmpString.Prepend("\\\\?\\"));
  3207. tmpString.CopyTo(&wString);
  3208. //
  3209. // Remove trailing backslash in the path
  3210. //
  3211. wString[wcslen(wString)-1] = L'\0';
  3212. WsbAffirmHandle(aHandle = CreateFile(wString,
  3213. GENERIC_READ,
  3214. FILE_SHARE_READ | FILE_SHARE_WRITE,
  3215. 0,
  3216. OPEN_EXISTING,
  3217. FILE_ATTRIBUTE_NORMAL,
  3218. 0));
  3219. WsbFree(wString);
  3220. wString = NULL;
  3221. try {
  3222. volInfo = (PFILE_FS_VOLUME_INFORMATION) buffer;
  3223. bytePtr = bytes;
  3224. status = NtQueryVolumeInformationFile(
  3225. aHandle,
  3226. &ioStatus,
  3227. buffer,
  3228. sizeof(buffer),
  3229. FileFsVolumeInformation);
  3230. WsbAffirmNtStatus(status);
  3231. //
  3232. // Volume serial number forms the lower 4 bytes of the GUID
  3233. //
  3234. WsbAffirmHr(WsbConvertToBytes(bytePtr, volInfo->VolumeSerialNumber, &size));
  3235. WsbAffirm(size == sizeof(volInfo->VolumeSerialNumber), E_FAIL);
  3236. //
  3237. // Volume creation time forms the next 8 bytes
  3238. //
  3239. bytePtr += size;
  3240. WsbAffirmHr(WsbConvertToBytes(bytePtr, volInfo->VolumeCreationTime.QuadPart, &size));
  3241. WsbAffirm(size == sizeof(volInfo->VolumeCreationTime.QuadPart), E_FAIL);
  3242. //
  3243. // Next 4 bytes: 0's are good as any
  3244. //
  3245. bytePtr += size;
  3246. WsbAffirmHr(WsbConvertToBytes(bytePtr, (ULONG) 0, &size));
  3247. WsbAffirm(size == sizeof(ULONG), E_FAIL);
  3248. WsbAffirmHr(WsbConvertFromBytes(bytes, &m_id, &size));
  3249. WsbAffirm(size == sizeof(m_id), E_FAIL);
  3250. } WsbCatch(hr);
  3251. WsbAffirmStatus(CloseHandle(aHandle));
  3252. m_isDirty = TRUE;
  3253. } WsbCatch(hr);
  3254. return(hr);
  3255. }
  3256. HRESULT
  3257. CFsaResource::Recall(
  3258. IN IFsaScanItem* pScanItem,
  3259. IN LONGLONG offset,
  3260. IN LONGLONG size,
  3261. IN BOOL deletePlaceholder
  3262. )
  3263. /*++
  3264. Implements:
  3265. IFsaResource::Recall().
  3266. --*/
  3267. {
  3268. HRESULT hr = S_OK;
  3269. HRESULT hrFind;
  3270. CComPtr<IFsaPostIt> pWorkItem;
  3271. LONGLONG fileId;
  3272. CComPtr<IHsmFsaTskMgr> pEngine;
  3273. CComPtr<IHsmSession> pSession;
  3274. CComPtr<IWsbDbSession> pDbSession;
  3275. CComPtr<IFsaRecoveryRec> pRecRec;
  3276. CWsbStringPtr tmpString;
  3277. FSA_PLACEHOLDER placeholder;
  3278. LONGLONG fileVersionId;
  3279. WsbTraceIn(OLESTR("CFsaResource::Recall"), OLESTR(""));
  3280. try {
  3281. // Make sure the Scan Item interface is OK
  3282. WsbAssert(pScanItem != 0, E_FAIL);
  3283. WsbAffirmHr(CoCreateInstance(CLSID_CFsaPostIt, 0, CLSCTX_SERVER, IID_IFsaPostIt, (void**) &pWorkItem));
  3284. // Get the data from the scan item.
  3285. WsbAffirmHr(pScanItem->GetSession((IHsmSession**) &(pSession)));
  3286. WsbAffirmHr(pWorkItem->SetSession(pSession));
  3287. WsbAffirmHr(pScanItem->GetPathAndName(0, &tmpString, 0));
  3288. WsbAffirmHr(pWorkItem->SetPath(tmpString));
  3289. WsbAffirmHr(pWorkItem->SetRequestOffset(offset));
  3290. WsbAffirmHr(pWorkItem->SetRequestSize(size));
  3291. WsbAffirmHr(pScanItem->GetPlaceholder(offset, size, &placeholder));
  3292. WsbAffirmHr(pWorkItem->SetPlaceholder(&placeholder));
  3293. WsbAffirmHr(pScanItem->GetVersionId(&fileVersionId));
  3294. WsbAffirmHr(pWorkItem->SetFileVersionId(fileVersionId));
  3295. // Fill in the rest of the work
  3296. WsbAffirmHr(pWorkItem->SetRequestAction(FSA_REQUEST_ACTION_RECALL));
  3297. if (deletePlaceholder) {
  3298. WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_DELETEPLACEHOLDER));
  3299. } else {
  3300. WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_RECALLEDDATA));
  3301. }
  3302. // Send the request to the task manager. If the file was archived by someone other
  3303. // than the managing HSM, then that HSM will need to be looked up.
  3304. if ( GUID_NULL != m_managingHsm &&
  3305. memcmp(&m_managingHsm, &(placeholder.hsmId), sizeof(GUID)) == 0) {
  3306. WsbAffirmHr(GetHsmEngine(&pEngine));
  3307. } else {
  3308. CComPtr<IHsmServer> pHsmServer;
  3309. WsbAssertHr(HsmConnectFromId(HSMCONN_TYPE_HSM, placeholder.hsmId, IID_IHsmServer, (void**) &pHsmServer));
  3310. WsbAffirmHr(pHsmServer->GetHsmFsaTskMgr(&pEngine));
  3311. }
  3312. WsbAffirmHr(pScanItem->GetFileId(&fileId));
  3313. if (m_isDbInitialized) {
  3314. // Save a recovery record in case anything goes wrong
  3315. WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
  3316. WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, RECOVERY_REC_TYPE, IID_IFsaRecoveryRec, (void**) &pRecRec));
  3317. WsbAffirmHr(pRecRec->SetPath(tmpString));
  3318. // If the record already exists rewrite it, otherwise create a new record.
  3319. hrFind = pRecRec->FindEQ();
  3320. if (WSB_E_NOTFOUND == hrFind) {
  3321. WsbAffirmHr(pRecRec->MarkAsNew());
  3322. } else if (FAILED(hrFind)) {
  3323. WsbThrow(hrFind);
  3324. }
  3325. WsbAffirmHr(pRecRec->SetFileId(fileId));
  3326. WsbAffirmHr(pRecRec->SetOffsetSize(offset, size));
  3327. WsbAffirmHr(pRecRec->SetStatus(FSA_RECOVERY_FLAG_RECALLING));
  3328. WsbAffirmHr(pRecRec->Write());
  3329. }
  3330. try {
  3331. WsbAffirmHr(pEngine->DoFsaWork(pWorkItem));
  3332. } WsbCatchAndDo(hr,
  3333. // This FindEQ seems unnecessary, but we can't assume the
  3334. // the Remove will work
  3335. if (pRecRec) {
  3336. if (SUCCEEDED(pRecRec->FindEQ())) {
  3337. hr = pRecRec->Remove();
  3338. }
  3339. }
  3340. );
  3341. } WsbCatch(hr);
  3342. if (pDbSession != 0) {
  3343. m_pPremigrated->Close(pDbSession);
  3344. }
  3345. WsbTraceOut(OLESTR("CFsaResource::Recall"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3346. return(hr);
  3347. }
  3348. HRESULT
  3349. CFsaResource::RemovePremigrated(
  3350. IN IFsaScanItem* pScanItem,
  3351. IN LONGLONG offset,
  3352. IN LONGLONG size
  3353. )
  3354. /*++
  3355. Implements:
  3356. IFsaResource::RemovePremigrated().
  3357. --*/
  3358. {
  3359. HRESULT hr = S_OK;
  3360. CWsbStringPtr path;
  3361. CComPtr<IWsbDbSession> pDbSession;
  3362. CComPtr<IFsaPremigratedRec> pRec;
  3363. WsbTraceIn(OLESTR("CFsaResource::RemovePremigrated"), OLESTR(""));
  3364. try {
  3365. WsbAssert(0 != pScanItem, E_POINTER);
  3366. WsbAffirm(m_pPremigrated != NULL, E_UNEXPECTED);
  3367. // Open the database.
  3368. WsbAffirmHr(m_pPremigrated->Open(&pDbSession));
  3369. // Protect the removal with Jet transaction since the auto-truncator thread
  3370. // may try to remove the same record at the same time
  3371. WsbAffirmHr(pDbSession->TransactionBegin());
  3372. try {
  3373. LONGLONG itemSize;
  3374. HRESULT hrTemp;
  3375. // Find the record using the bag/offsets key.
  3376. WsbAffirmHr(m_pPremigrated->GetEntity(pDbSession, PREMIGRATED_REC_TYPE, IID_IFsaPremigratedRec, (void**) &pRec));
  3377. WsbAffirmHr(pRec->UseKey(PREMIGRATED_BAGID_OFFSETS_KEY_TYPE));
  3378. WsbAffirmHr(pRec->SetFromScanItem(pScanItem, offset, size, FALSE));
  3379. // The record may already been deleted by the auto-truncator
  3380. hrTemp = pRec->FindEQ();
  3381. if (hrTemp == WSB_E_NOTFOUND) {
  3382. hr = S_OK;
  3383. WsbThrow(hr);
  3384. }
  3385. WsbAffirmHr(hrTemp);
  3386. WsbAffirmHr(pRec->GetSize(&itemSize));
  3387. // the record may be involved with another transaction with delete pending
  3388. hrTemp = pRec->Remove();
  3389. if (hrTemp == WSB_E_IDB_UPDATE_CONFLICT) {
  3390. hr = S_OK;
  3391. WsbThrow(hr);
  3392. }
  3393. WsbAffirmHr(hrTemp);
  3394. // Remove the size of the section from the amount of premigrated data.
  3395. RemovePremigratedSize(itemSize);
  3396. m_isDirty = TRUE;
  3397. } WsbCatch(hr);
  3398. WsbAffirmHr(pDbSession->TransactionEnd());
  3399. WsbAffirmHr(m_pPremigrated->Close(pDbSession));
  3400. } WsbCatch(hr);
  3401. WsbTraceOut(OLESTR("CFsaResource::RemovePremigrated"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3402. return(hr);
  3403. }
  3404. HRESULT
  3405. CFsaResource::RemoveTruncated(
  3406. IN IFsaScanItem* /*pScanItem*/,
  3407. IN LONGLONG /*offset*/,
  3408. IN LONGLONG size
  3409. )
  3410. /*++
  3411. Implements:
  3412. IFsaResource::RemoveTruncated().
  3413. --*/
  3414. {
  3415. HRESULT hr = S_OK;
  3416. WsbTraceIn(OLESTR("CFsaResource::RemoveTruncated"), OLESTR(""));
  3417. try {
  3418. WsbAffirmHr(RemoveTruncatedSize(size));
  3419. } WsbCatch(hr);
  3420. WsbTraceOut(OLESTR("CFsaResource::RemoveTruncated"),
  3421. OLESTR("hr = <%ls>, m_truncatedSize = %I64d"), WsbHrAsString(hr),
  3422. m_truncatedSize);
  3423. return(hr);
  3424. }
  3425. HRESULT
  3426. CFsaResource::RemoveTruncatedSize(
  3427. IN LONGLONG size
  3428. )
  3429. /*++
  3430. Implements:
  3431. IFsaResource::RemoveTruncatedSize().
  3432. --*/
  3433. {
  3434. HRESULT hr = S_OK;
  3435. WsbTraceIn(OLESTR("CFsaResource::RemoveTruncatedSize"), OLESTR(""));
  3436. try {
  3437. m_truncatedSize = max(0, m_truncatedSize - size);
  3438. m_isDirty = TRUE;
  3439. } WsbCatch(hr);
  3440. WsbTraceOut(OLESTR("CFsaResource::RemoveTruncatedSize"),
  3441. OLESTR("hr = <%ls>, m_truncatedSize = %I64d"), WsbHrAsString(hr),
  3442. m_truncatedSize);
  3443. return(hr);
  3444. }
  3445. HRESULT
  3446. CFsaResource::RemovePremigratedSize(
  3447. IN LONGLONG size
  3448. )
  3449. /*++
  3450. Implements:
  3451. IFsaResourcePriv::RemovePremigratedSize().
  3452. --*/
  3453. {
  3454. WsbTraceIn(OLESTR("CFsaResource::RemovePremigratedSize"),
  3455. OLESTR("m_premigratedSize = %I64d"), m_premigratedSize);
  3456. m_isDirty = TRUE;
  3457. if (size > m_premigratedSize) {
  3458. m_premigratedSize = 0;
  3459. } else {
  3460. m_premigratedSize -= size;
  3461. }
  3462. WsbTraceOut(OLESTR("CFsaResource::RemovePremigratedSize"),
  3463. OLESTR("m_premigratedSize = %I64d"), m_premigratedSize);
  3464. return(S_OK);
  3465. }
  3466. HRESULT
  3467. CFsaResource::Save(
  3468. IN IStream* pStream,
  3469. IN BOOL clearDirty
  3470. )
  3471. /*++
  3472. Implements:
  3473. IPersistStream::Save().
  3474. --*/
  3475. {
  3476. HRESULT hr = S_OK;
  3477. CComPtr<IPersistStream> pPersistStream;
  3478. WsbTraceIn(OLESTR("CFsaResource::Save"), OLESTR("clearDirty = <%ls>"),
  3479. WsbBoolAsString(clearDirty));
  3480. try {
  3481. WsbAssert(0 != pStream, E_POINTER);
  3482. // Do the easy stuff, but make sure that this order matches the order
  3483. // in the Load() method.
  3484. // Save the path by which this resource is/was last known. Note the
  3485. // Load() method reads it back into the resource's 'm_oldPath' field.
  3486. if ( m_path == NULL ) {
  3487. WsbAffirmHr(WsbSaveToStream(pStream, m_oldPath));
  3488. }
  3489. else {
  3490. WsbAffirmHr(WsbSaveToStream(pStream, m_path));
  3491. }
  3492. WsbAffirmHr(WsbSaveToStream(pStream, m_alternatePath));
  3493. WsbAffirmHr(WsbSaveToStream(pStream, m_name));
  3494. WsbAffirmHr(WsbSaveToStream(pStream, m_stickyName));
  3495. WsbAffirmHr(WsbSaveToStream(pStream, m_fsName));
  3496. WsbAffirmHr(WsbSaveToStream(pStream, m_maxComponentLength));
  3497. WsbAffirmHr(WsbSaveToStream(pStream, m_fsFlags));
  3498. WsbAffirmHr(WsbSaveToStream(pStream, m_id));
  3499. WsbAffirmHr(WsbSaveToStream(pStream, m_isActive));
  3500. WsbAffirmHr(WsbSaveToStream(pStream, (ULONG) m_compareBy));
  3501. WsbAffirmHr(WsbSaveToStream(pStream, m_managingHsm));
  3502. WsbAffirmHr(WsbSaveToStream(pStream, m_hsmLevel));
  3503. WsbAffirmHr(WsbSaveToStream(pStream, m_premigratedSize));
  3504. WsbAffirmHr(WsbSaveToStream(pStream, m_truncatedSize));
  3505. WsbAffirmHr(WsbSaveToStream(pStream, m_manageableItemLogicalSize));
  3506. WsbAffirmHr(WsbSaveToStream(pStream, m_manageableItemAccessTimeIsRelative));
  3507. WsbAffirmHr(WsbSaveToStream(pStream, m_manageableItemAccessTime));
  3508. WsbAffirmHr(WsbSaveToStream(pStream, m_usnJournalId));
  3509. WsbAffirmHr(WsbSaveToStream(pStream, m_lastUsnId));
  3510. // Save off the default rules.
  3511. WsbAffirmHr(m_pDefaultRules->QueryInterface(IID_IPersistStream,
  3512. (void**) &pPersistStream));
  3513. WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
  3514. pPersistStream = 0;
  3515. // Save off the premigration list.
  3516. WsbAffirmHr(((IWsbDb*)m_pPremigrated)->QueryInterface(IID_IPersistStream,
  3517. (void**) &pPersistStream));
  3518. WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
  3519. pPersistStream = 0;
  3520. // Save off the truncator.
  3521. WsbAffirmHr(m_pTruncator->QueryInterface(IID_IPersistStream,
  3522. (void**) &pPersistStream));
  3523. WsbAffirmHr(pPersistStream->Save(pStream, clearDirty));
  3524. pPersistStream = 0;
  3525. // If we got it saved and we were asked to clear the dirty bit, then
  3526. // do so now.
  3527. if (clearDirty) {
  3528. m_isDirty = FALSE;
  3529. }
  3530. } WsbCatch(hr);
  3531. WsbTraceOut(OLESTR("CFsaResource::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3532. return(hr);
  3533. }
  3534. HRESULT
  3535. CFsaResource::SetAlternatePath(
  3536. IN OLECHAR* path
  3537. )
  3538. /*++
  3539. Implements:
  3540. IFsaResourcePriv::SetAlternatePath().
  3541. --*/
  3542. {
  3543. HRESULT hr = S_OK;
  3544. try {
  3545. WsbAssert(0 != path, E_POINTER);
  3546. m_alternatePath = path;
  3547. m_isDirty = TRUE;
  3548. } WsbCatch(hr);
  3549. return(hr);
  3550. }
  3551. HRESULT
  3552. CFsaResource::SetHsmLevel(
  3553. IN ULONG level
  3554. )
  3555. /*++
  3556. Implements:
  3557. IFsaResource::SetHsmLevel().
  3558. --*/
  3559. {
  3560. BOOL DoKick = FALSE;
  3561. HRESULT hr = S_OK;
  3562. WsbTraceIn(OLESTR("CFsaResource::SetHsmLevel"),
  3563. OLESTR("current level = %lx, new level = %lx"), m_hsmLevel, level);
  3564. if (m_hsmLevel < level) {
  3565. DoKick = TRUE;
  3566. }
  3567. m_hsmLevel = level;
  3568. // Wake up the AutoTruncator if the new level is higher
  3569. if (DoKick) {
  3570. WsbAffirmHr(m_pTruncator->KickStart());
  3571. }
  3572. m_isDirty = TRUE;
  3573. WsbTraceOut(OLESTR("CFsaResource::SetHsmLevel"), OLESTR("hr = <%ls>"),
  3574. WsbHrAsString(hr));
  3575. return(hr);
  3576. }
  3577. HRESULT
  3578. CFsaResource::SetIdentifier(
  3579. IN GUID id
  3580. )
  3581. /*++
  3582. Implements:
  3583. IFsaResourcePriv::SetIdentifier().
  3584. --*/
  3585. {
  3586. HRESULT hr = S_OK;
  3587. m_id = id;
  3588. m_isDirty = TRUE;
  3589. return(hr);
  3590. }
  3591. HRESULT
  3592. CFsaResource::SetIsActive(
  3593. BOOL isActive
  3594. )
  3595. /*++
  3596. Implements:
  3597. IFsaResource::SetIsActive().
  3598. --*/
  3599. {
  3600. HRESULT hr = S_OK;
  3601. CComPtr<IHsmSession> pSession;
  3602. WsbTraceIn(OLESTR("CFsaResource::SetIsActive"), OLESTR(""));
  3603. // If the flag is changing values, then we may need to do something to the truncator.
  3604. try {
  3605. if (m_isActive != isActive) {
  3606. // Change the flag.
  3607. m_isActive = isActive;
  3608. // If we are becoming active, then we need to start the truncator. Otherwise we need to stop it.
  3609. if (m_isActive) {
  3610. // If we are managed & done with recovery, then the truncator should be running.
  3611. if (IsManaged() == S_OK && m_isRecovered) {
  3612. // Try to start the truncator
  3613. WsbAffirmHr(InitializePremigrationList(TRUE));
  3614. }
  3615. } else {
  3616. // If the truncator is running, then ask it to stop.
  3617. WsbAffirmHr(m_pTruncator->GetSession(&pSession));
  3618. if (pSession != 0) {
  3619. WsbAffirmHr(pSession->ProcessEvent(HSM_JOB_PHASE_ALL, HSM_JOB_EVENT_CANCEL));
  3620. }
  3621. }
  3622. } else {
  3623. m_isActive = isActive;
  3624. }
  3625. m_isDirty = TRUE;
  3626. } WsbCatch( hr );
  3627. WsbTraceOut(OLESTR("CFsaResource::SetIsActive"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3628. return(hr);
  3629. }
  3630. HRESULT
  3631. CFsaResource::SetIsAvailable(
  3632. BOOL isAvailable
  3633. )
  3634. /*++
  3635. Implements:
  3636. IFsaResource::SetIsAvailable().
  3637. --*/
  3638. {
  3639. HRESULT hr = S_OK;
  3640. WsbTraceIn(OLESTR("CFsaResource::SetIsAvailable"), OLESTR(""));
  3641. // Change the flag.
  3642. m_isAvailable = isAvailable;
  3643. WsbTraceOut(OLESTR("CFsaResource::SetIsAvailable"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3644. return(hr);
  3645. }
  3646. HRESULT
  3647. CFsaResource::SetIsDeletePending(
  3648. BOOL isDeletePending
  3649. )
  3650. /*++
  3651. Implements:
  3652. IFsaResource::SetIsDeletePending().
  3653. --*/
  3654. {
  3655. HRESULT hr = S_OK;
  3656. HANDLE threadHandle;
  3657. WsbTraceIn(OLESTR("CFsaResource::SetIsDeletePending"), OLESTR(""));
  3658. // Change the flag.
  3659. m_isDeletePending = isDeletePending;
  3660. threadHandle = CreateThread(0, 0, FsaStartOnStateChange, (void*) this, 0, &g_ThreadId);
  3661. if (threadHandle != NULL) {
  3662. CloseHandle(threadHandle);
  3663. }
  3664. WsbTraceOut(OLESTR("CFsaResource::SetIsDeletePending"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3665. return(hr);
  3666. }
  3667. HRESULT
  3668. CFsaResource::SetManageableItemLogicalSize(
  3669. IN LONGLONG size
  3670. )
  3671. /*++
  3672. Implements:
  3673. IFsaResource::SetManageableItemLogicalSize().
  3674. --*/
  3675. {
  3676. m_manageableItemLogicalSize = size;
  3677. return(S_OK);
  3678. }
  3679. HRESULT
  3680. CFsaResource::SetManageableItemAccessTime(
  3681. IN BOOL isRelative,
  3682. IN FILETIME time
  3683. )
  3684. /*++
  3685. Implements:
  3686. IFsaResource::SetManageableItemAccessTime().
  3687. --*/
  3688. {
  3689. m_manageableItemAccessTimeIsRelative = isRelative;
  3690. m_manageableItemAccessTime = time;
  3691. return(S_OK);
  3692. }
  3693. HRESULT
  3694. CFsaResource::SetName(
  3695. IN OLECHAR* name
  3696. )
  3697. /*++
  3698. Implements:
  3699. IFsaResourcePriv::SetName().
  3700. --*/
  3701. {
  3702. HRESULT hr = S_OK;
  3703. try {
  3704. WsbAssert(0 != name, E_POINTER);
  3705. m_name = name;
  3706. m_isDirty = TRUE;
  3707. } WsbCatch(hr);
  3708. return(hr);
  3709. }
  3710. HRESULT
  3711. CFsaResource::SetOldPath(
  3712. IN OLECHAR* oldPath
  3713. )
  3714. /*++
  3715. Implements:
  3716. IFsaResourcePriv::SetOldPath().
  3717. --*/
  3718. {
  3719. HRESULT hr = S_OK;
  3720. try {
  3721. WsbAssert(0 != oldPath, E_POINTER);
  3722. m_oldPath = oldPath;
  3723. m_isDirty = TRUE;
  3724. } WsbCatch(hr);
  3725. return(hr);
  3726. }
  3727. HRESULT
  3728. CFsaResource::SetPath(
  3729. IN OLECHAR* path
  3730. )
  3731. /*++
  3732. Implements:
  3733. IFsaResourcePriv::SetPath().
  3734. --*/
  3735. {
  3736. HRESULT hr = S_OK;
  3737. try {
  3738. WsbAssert(0 != path, E_POINTER);
  3739. m_path = path;
  3740. m_isDirty = TRUE;
  3741. } WsbCatch(hr);
  3742. return(hr);
  3743. }
  3744. HRESULT
  3745. CFsaResource::SetSerial(
  3746. IN ULONG serial
  3747. )
  3748. /*++
  3749. Implements:
  3750. IFsaResourcePriv::SetSerial().
  3751. --*/
  3752. {
  3753. HRESULT hr = S_OK;
  3754. try {
  3755. m_serial = serial;
  3756. m_isDirty = TRUE;
  3757. } WsbCatch(hr);
  3758. return(hr);
  3759. }
  3760. HRESULT
  3761. CFsaResource::SetStickyName(
  3762. IN OLECHAR* name
  3763. )
  3764. /*++
  3765. Implements:
  3766. IFsaResourcePriv::SetStickyName().
  3767. --*/
  3768. {
  3769. HRESULT hr = S_OK;
  3770. try {
  3771. WsbAssert(0 != name, E_POINTER);
  3772. m_stickyName = name;
  3773. m_isDirty = TRUE;
  3774. } WsbCatch(hr);
  3775. return(hr);
  3776. }
  3777. HRESULT
  3778. CFsaResource::SetUserFriendlyName(
  3779. IN OLECHAR* name
  3780. )
  3781. /*++
  3782. Implements:
  3783. IFsaResourcePriv::SetUserFriendlyName().
  3784. --*/
  3785. {
  3786. HRESULT hr = S_OK;
  3787. try {
  3788. WsbAssert(0 != name, E_POINTER);
  3789. m_userName = name;
  3790. m_isDirty = TRUE;
  3791. } WsbCatch(hr);
  3792. return(hr);
  3793. }
  3794. HRESULT
  3795. CFsaResource::ChangeSysState(
  3796. IN OUT HSM_SYSTEM_STATE* pSysState
  3797. )
  3798. /*++
  3799. Implements:
  3800. IHsmSystemState::ChangeSysState().
  3801. --*/
  3802. {
  3803. HRESULT hr = S_OK;
  3804. WsbTraceIn(OLESTR("CFsaResource::ChangeSysState"), OLESTR(""));
  3805. try {
  3806. //
  3807. // Make sure the truncater is stopped so it won't
  3808. // try to use the database
  3809. //
  3810. if (m_pTruncator) {
  3811. CComPtr<IHsmSession> pSession;
  3812. WsbAffirmHr(m_pTruncator->GetSession(&pSession));
  3813. if (pSession != 0) {
  3814. if (pSysState->State & HSM_STATE_SHUTDOWN) {
  3815. WsbAffirmHr(pSession->ProcessEvent(HSM_JOB_PHASE_ALL, HSM_JOB_EVENT_CANCEL));
  3816. }
  3817. }
  3818. m_pTruncator->ChangeSysState(pSysState);
  3819. }
  3820. } WsbCatch(hr);
  3821. WsbTraceOut(OLESTR("CFsaResource::ChangeSysState"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3822. return(hr);
  3823. }
  3824. HRESULT
  3825. CFsaResource::StartJob(
  3826. IN OLECHAR* startingPath,
  3827. IN IHsmSession* pSession
  3828. )
  3829. /*++
  3830. Implements:
  3831. IFsaResource::StartJob().
  3832. --*/
  3833. {
  3834. HRESULT hr = S_OK;
  3835. CComPtr<IHsmScanner> pScanner;
  3836. WsbTraceIn(OLESTR("CFsaResource::StartJob"), OLESTR("starting path = %ls"), startingPath);
  3837. try {
  3838. WsbAssert(0 != pSession, E_POINTER);
  3839. // Get file-max-size (this is updated in the Registry by the Engine according to max media size)
  3840. DWORD dwMaxSize = 0;
  3841. if (WsbGetRegistryValueDWORD(NULL, HSM_ENGINE_REGISTRY_STRING, HSM_MAX_FILE_TO_MIGRATE, &dwMaxSize) == S_OK) {
  3842. // Trunslate to bytes
  3843. WsbTrace(OLESTR("CFsaResource::StartJob: Setting maximum size for manageable files to %lu MB\n"), dwMaxSize);
  3844. m_manageableItemMaxSize = ((LONGLONG)dwMaxSize) * 1024 * 1024;
  3845. }
  3846. // Create an initialize the scanner.
  3847. WsbAffirmHr(CoCreateInstance(CLSID_CHsmScanner, 0, CLSCTX_SERVER, IID_IHsmScanner, (void**) &pScanner));
  3848. WsbAffirmHr(pScanner->Start(pSession, startingPath));
  3849. } WsbCatch(hr);
  3850. WsbTraceOut(OLESTR("CFsaResource::StartJob"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3851. return(hr);
  3852. }
  3853. HRESULT
  3854. CFsaResource::StartJobSession(
  3855. IN IHsmJob* pJob,
  3856. IN ULONG subRunId,
  3857. OUT IHsmSession** ppSession
  3858. )
  3859. /*++
  3860. Implements:
  3861. IFsaResource::StartJobSession().
  3862. --*/
  3863. {
  3864. HRESULT hr = S_OK;
  3865. CComPtr<IHsmSession> pSession;
  3866. GUID hsmId;
  3867. ULONG runId;
  3868. CWsbStringPtr name;
  3869. WsbTraceIn(OLESTR("CFsaResource::StartJobSession"), OLESTR(""));
  3870. try {
  3871. WsbAssert(0 != pJob, E_POINTER);
  3872. WsbAssert(0 != ppSession, E_POINTER);
  3873. *ppSession = 0;
  3874. // Create and Initialize a session object.
  3875. WsbAffirmHr(CoCreateInstance(CLSID_CHsmSession, 0, CLSCTX_SERVER, IID_IHsmSession, (void**) &pSession));
  3876. WsbAffirmHr(pJob->GetHsmId(&hsmId));
  3877. WsbAffirmHr(pJob->GetRunId(&runId));
  3878. WsbAffirmHr(pJob->GetName(&name, 0));
  3879. WsbAffirmHr(pSession->Start(name, HSM_JOB_LOG_NORMAL, hsmId, pJob, (IFsaResource*) this, runId, subRunId));
  3880. // Return the session to the caller.
  3881. *ppSession = pSession;
  3882. pSession.p->AddRef();
  3883. } WsbCatch(hr);
  3884. WsbTraceOut(OLESTR("CFsaResource::StartJobSession"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  3885. return(hr);
  3886. }
  3887. HRESULT
  3888. CFsaResource::SetupValidateJob(SYSTEMTIME runTime)
  3889. {
  3890. HRESULT hr = S_OK;
  3891. CComPtr<IWsbCreateLocalObject> pLocalObject;
  3892. CComPtr <IWsbIndexedCollection> pJobs;
  3893. CComPtr<IHsmJob> pExistJob;
  3894. CComPtr<IHsmJob> pNewJob;
  3895. CComPtr<IHsmServer> pHsmServer;
  3896. CWsbStringPtr pszExistJobName;
  3897. CWsbStringPtr szJobName;
  3898. CWsbStringPtr parameters;
  3899. CWsbStringPtr commentString;
  3900. CWsbStringPtr tmpString;
  3901. CWsbStringPtr formatString;
  3902. TASK_TRIGGER_TYPE jobTriggerType;
  3903. BOOL scheduledJob;
  3904. WsbTraceIn(OLESTR("CFsaResource::SetupValidateJob"), OLESTR(""));
  3905. try {
  3906. // Get the volume name
  3907. CWsbStringPtr szWsbVolumeName;
  3908. WsbAffirmHr (GetLogicalName ( &szWsbVolumeName, 0));
  3909. // Create a job name
  3910. CWsbStringPtr volumeString;
  3911. WsbAffirmHr( volumeString.Alloc( 128 ) );
  3912. // For now, ignore the user name if it's not a drive letter
  3913. CWsbStringPtr userName = m_userName;
  3914. size_t userLen = 0;
  3915. if ((WCHAR *)userName) {
  3916. userLen = wcslen(userName);
  3917. }
  3918. if ((userLen != 3) || (userName[1] != L':')) {
  3919. userName = L"";
  3920. }
  3921. if( ! userName || userName.IsEqual ( L"" ) ) {
  3922. //
  3923. // No drive letter - use the volume name and serial number instead
  3924. //
  3925. if( ! m_name || m_name.IsEqual( L"" ) ) {
  3926. //
  3927. // No name, no drive letter - just have serial number
  3928. //
  3929. swprintf( volumeString, L"%8.8lx", m_serial );
  3930. } else {
  3931. swprintf( volumeString, L"%ls-%8.8lx", (OLECHAR*)m_name, m_serial );
  3932. }
  3933. } else {
  3934. //
  3935. // Just want the drive letter (first character)
  3936. //
  3937. volumeString = userName;
  3938. volumeString[1] = L'\0';
  3939. }
  3940. WsbAffirmHr(formatString.LoadFromRsc(_Module.m_hInst, IDS_JOB_NAME_PREFIX));
  3941. WsbAffirmHr(szJobName.Alloc(512));
  3942. swprintf((OLECHAR *) szJobName, formatString, (OLECHAR*)volumeString);
  3943. // Get a pointer to the HSM server
  3944. WsbAffirm(IsManaged() == S_OK, E_FAIL);
  3945. WsbAffirmHr(HsmConnectFromId(HSMCONN_TYPE_HSM, m_managingHsm, IID_IHsmServer,
  3946. (void**) &pHsmServer));
  3947. // Get a CreateLocalObject interface with which to create the job
  3948. WsbAffirmHr (pHsmServer->QueryInterface( IID_IWsbCreateLocalObject,
  3949. (void **) &pLocalObject));
  3950. // Create the new job in the engine
  3951. WsbAffirmHr (pLocalObject->CreateInstance( CLSID_CHsmJob, IID_IHsmJob,
  3952. (void**) &pNewJob));
  3953. WsbAffirmHr (pNewJob->InitAs(
  3954. szJobName, NULL, HSM_JOB_DEF_TYPE_VALIDATE, GUID_NULL,
  3955. pHsmServer, TRUE, this));
  3956. // Get the jobs collection from the engine
  3957. WsbAffirmHr (pHsmServer->GetJobs (&pJobs));
  3958. // If any jobs exist with this name, delete them
  3959. ULONG cCount;
  3960. WsbAffirmHr (pJobs->GetEntries (&cCount));
  3961. for (UINT i = 0; i < cCount; i++) {
  3962. WsbAffirmHr (pJobs->At (i, IID_IHsmJob, (void **) &pExistJob));
  3963. WsbAffirmHr (pExistJob->GetName (&pszExistJobName, 0));
  3964. if (pszExistJobName.Compare (szJobName) == 0) {
  3965. WsbAffirmHr (pJobs->RemoveAndRelease(pExistJob));
  3966. i--; cCount--;
  3967. }
  3968. pExistJob = 0; // make sure we release this interface.
  3969. }
  3970. // Add the new job to the engine collection
  3971. WsbAffirmHr (pJobs->Add(pNewJob));
  3972. // Set up to call the Engine to create an entry in the NT Task Scheduler
  3973. // Create the parameter string for the program NT Scheduler
  3974. // will run (for Sakkara this is RsLaunch) by putting the
  3975. // job name in as the parameter. This is how RsLaunch knows
  3976. // which job in the Engine to run.
  3977. WsbAffirmHr(parameters.Alloc(256));
  3978. swprintf((OLECHAR *)parameters, L"run \"%ls\"", (OLECHAR *) szJobName);
  3979. // Create the comment string for the NT Scheduler entry
  3980. WsbAffirmHr(formatString.LoadFromRsc(_Module.m_hInst, IDS_JOB_AUTOVALIDATE_COMMENT));
  3981. WsbAffirmHr(commentString.Alloc(512));
  3982. swprintf((OLECHAR *) commentString, formatString, (OLECHAR *) szWsbVolumeName);
  3983. // Declare and initialize the schedule components passed to
  3984. // the Engine.
  3985. jobTriggerType = TASK_TIME_TRIGGER_ONCE;
  3986. // Indicate this is a scheduled job
  3987. scheduledJob = TRUE;
  3988. // Create the task
  3989. WsbAffirmHr( pHsmServer->CreateTaskEx( szJobName, parameters,
  3990. commentString, jobTriggerType,
  3991. runTime, 0,
  3992. scheduledJob ) );
  3993. //
  3994. // Remove the registry value if it is there.
  3995. //
  3996. WsbAffirmHr(tmpString.Alloc(32));
  3997. swprintf((OLECHAR *) tmpString, L"%x", m_serial);
  3998. (void) WsbRemoveRegistryValue(NULL, FSA_VALIDATE_LOG_KEY_NAME, tmpString);
  3999. } WsbCatch( hr );
  4000. WsbTraceOut( L"CFsaResource::SetupValidateJob", L"hr = <%ls>", WsbHrAsString( hr ) );
  4001. return( hr );
  4002. }
  4003. HRESULT
  4004. CFsaResource::Test(
  4005. USHORT* passed,
  4006. USHORT* failed
  4007. )
  4008. /*++
  4009. Implements:
  4010. IWsbTestable::Test().
  4011. --*/
  4012. {
  4013. HRESULT hr = S_OK;
  4014. try {
  4015. WsbAssert(0 != passed, E_POINTER);
  4016. WsbAssert(0 != failed, E_POINTER);
  4017. *passed = 0;
  4018. *failed = 0;
  4019. } WsbCatch(hr);
  4020. return(hr);
  4021. }
  4022. HRESULT
  4023. CFsaResource::UpdateFrom(
  4024. IN IFsaServer* pServer,
  4025. IN IFsaResource* pResource
  4026. )
  4027. /*++
  4028. Implements:
  4029. IFsaResourcePriv::UpdateFrom().
  4030. Routine Description:
  4031. This routine implements the COM method for updating a resource object from another.
  4032. It is generally used to update a resource contained in the manageable resources
  4033. collection from a 'working' resource which was just created during a scan for
  4034. resources. Note that both source and target resource objects must represent the
  4035. same physical resource.
  4036. To capture the latest information about the resource, only the owning FSA and path
  4037. info is updated from the source resource object. All other resource info is
  4038. updated via a direct query contained within this method. This technique allows
  4039. for capturing any updates made by the user since the scan was run.
  4040. Arguments:
  4041. pServer - Interface pointer to the FSA service that is updating this resource.
  4042. pResource - Interface pointer to the resource used as the source during the update.
  4043. Return Value:
  4044. S_OK - The call succeeded (the resource being tested was found to be manageable,
  4045. and the resource object was initialized).
  4046. E_UNEXPECTED - Thrown if the id's (Guids) for the resource to updated and the
  4047. source resource do not match.
  4048. Any other value - The call failed because one of the Remote Storage or Win32 API
  4049. calls contained internally in this method failed. The error value returned
  4050. is specific to the API call which failed.
  4051. --*/
  4052. {
  4053. HRESULT hr = S_OK;
  4054. GUID id;
  4055. CWsbStringPtr tmpString;
  4056. CWsbStringPtr volPath;
  4057. WsbTraceIn(OLESTR("CFsaResource::UpdateFrom"), OLESTR(""));
  4058. try {
  4059. // The identifiers must be the same! (Meaning both resource objects must
  4060. // represent the same physical resource.)
  4061. WsbAffirmHr(pResource->GetIdentifier(&id));
  4062. WsbAssert(m_id == id, E_UNEXPECTED);
  4063. // Update (store) the owning FSA interface. However, since this is a weak
  4064. // reference, do not AddRef() it.
  4065. m_pFsaServer = pServer;
  4066. // Update the path specific information, preserving the last known path (if any).
  4067. // If the 'path' of this resource is null, set it to the 'path' of the resource
  4068. // we are updating from. Else, compare the 2 'path' fields. If different, copy
  4069. // this resource's path to 'old path', then update 'path' from the resource we are
  4070. // updating from. If the 2 resources' paths are not null and the same, do nothing.
  4071. //
  4072. WsbAffirmHr(pResource->GetPath(&tmpString, 0));
  4073. if (m_path == 0) {
  4074. WsbAffirmHr(SetPath(tmpString));
  4075. }
  4076. else if (wcscmp(tmpString, m_path) != 0) {
  4077. // copy path to 'old path' field, then update 'path' field.
  4078. WsbAffirmHr(m_path.CopyTo(&m_oldPath, 0));
  4079. WsbAffirmHr(SetPath(tmpString));
  4080. }
  4081. // Update 'user friendly' name of this resource from the resource we are updating
  4082. // from.
  4083. WsbAffirmHr(pResource->GetUserFriendlyName(&tmpString, 0));
  4084. WsbTrace(OLESTR("CFsaResource::UpdateFrom - setting user friendly name to %ws\n"),
  4085. (WCHAR *) tmpString);
  4086. WsbAffirmHr(SetUserFriendlyName(tmpString));
  4087. // Update 'sticky' (long, ugly PNP) name of this resource from the resource we are
  4088. // updating from.
  4089. WsbAffirmHr(pResource->GetStickyName(&tmpString, 0));
  4090. WsbAffirmHr(SetStickyName(tmpString));
  4091. // Since the other data that we would like to refresh is not exposed by an interface,
  4092. // we will query for it again.
  4093. //
  4094. // NOTE: fsFlags and maxComponentLength are the real issues, since name and fsName
  4095. // are done via exposed interfaces.
  4096. //
  4097. // NOTE: To keep every update from making the item seem dirty, we may want to
  4098. // compare all the fields first. (Idea for later enhancement)
  4099. m_name.Realloc(128); // volume name
  4100. m_fsName.Realloc(128); // volume file system type (e.g., FAT, NTFS)
  4101. HRESULT hrAvailable;
  4102. WsbAffirmHr( hrAvailable = pResource->IsAvailable( ) );
  4103. m_isAvailable = S_OK == hrAvailable ? TRUE : FALSE;
  4104. // Reformat resource's path for 'GetVolumeInfo' call below.
  4105. volPath = m_path;
  4106. WsbAffirmHr(volPath.Prepend("\\\\?\\"));
  4107. WsbAffirm(GetVolumeInformation(volPath, m_name, 128, &m_serial,
  4108. &m_maxComponentLength, &m_fsFlags, m_fsName, 128), E_FAIL);
  4109. // Now that everything is updated, initialize the
  4110. // premigration list if necessary
  4111. WsbAffirmHr(InitializePremigrationList(TRUE));
  4112. m_isDirty = TRUE;
  4113. } WsbCatch(hr);
  4114. WsbTraceOut(OLESTR("CFsaResource::UpdateFrom"), OLESTR("hr = <%ls>"),
  4115. WsbHrAsString(hr));
  4116. return(hr);
  4117. }
  4118. HRESULT
  4119. CFsaResource::Validate(
  4120. IN IFsaScanItem* pScanItem,
  4121. IN LONGLONG offset,
  4122. IN LONGLONG size,
  4123. IN LONGLONG usn
  4124. )
  4125. /*++
  4126. Implements:
  4127. IFsaResource::Validate().
  4128. --*/
  4129. {
  4130. HRESULT hr = S_OK;
  4131. CComPtr<IFsaPostIt> pWorkItem;
  4132. CComPtr<IHsmFsaTskMgr> pEngine;
  4133. CWsbStringPtr tmpString;
  4134. CComPtr<IHsmSession> pSession;
  4135. FSA_PLACEHOLDER placeholder;
  4136. WsbTraceIn(OLESTR("CFsaResource::Validate"), OLESTR("offset = %I64d, size = %I64d, usn = <%I64d>"),
  4137. offset, size, usn);
  4138. try {
  4139. // Make sure the Scan Item interface is OK
  4140. WsbAssert(pScanItem != 0, E_POINTER);
  4141. WsbAffirmHr(CoCreateInstance(CLSID_CFsaPostIt, 0, CLSCTX_SERVER, IID_IFsaPostIt, (void**) &pWorkItem));
  4142. // Get the data from the scan item.
  4143. WsbAffirmHr(pScanItem->GetSession(&pSession));
  4144. WsbAffirmHr(pWorkItem->SetSession(pSession));
  4145. WsbAffirmHr(pScanItem->GetPathAndName(0, &tmpString, 0));
  4146. WsbAffirmHr(pWorkItem->SetPath(tmpString));
  4147. WsbAffirmHr(pWorkItem->SetRequestOffset(offset));
  4148. WsbAffirmHr(pWorkItem->SetRequestSize(size));
  4149. WsbAffirmHr(pScanItem->GetPlaceholder(offset, size, &(placeholder)));
  4150. WsbAffirmHr(pWorkItem->SetPlaceholder(&placeholder));
  4151. // Fill in the rest of the work
  4152. WsbAffirmHr(pWorkItem->SetRequestAction(FSA_REQUEST_ACTION_VALIDATE));
  4153. WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_NONE));
  4154. // Fill in the USN
  4155. WsbAffirmHr(pWorkItem->SetUSN(usn));
  4156. // Send the request to the task manager
  4157. WsbAffirmHr(GetHsmEngine(&pEngine));
  4158. WsbAffirmHr(pEngine->DoFsaWork(pWorkItem));
  4159. } WsbCatch(hr);
  4160. WsbTraceOut(OLESTR("CFsaResource::Validate"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  4161. return(hr);
  4162. }
  4163. HRESULT
  4164. CFsaResource::ValidateForTruncate(
  4165. IN IFsaScanItem* pScanItem,
  4166. IN LONGLONG offset,
  4167. IN LONGLONG size,
  4168. IN LONGLONG usn
  4169. )
  4170. /*++
  4171. Implements:
  4172. IFsaResource::ValidateForTruncate().
  4173. --*/
  4174. {
  4175. HRESULT hr = S_OK;
  4176. CComPtr<IFsaPostIt> pWorkItem;
  4177. CComPtr<IHsmFsaTskMgr> pEngine;
  4178. CWsbStringPtr tmpString;
  4179. CComPtr<IHsmSession> pSession;
  4180. FSA_PLACEHOLDER placeholder;
  4181. WsbTraceIn(OLESTR("CFsaResource::ValidateForTruncate"), OLESTR("offset = %I64d, size = %I64d, usn = <%I64d>"),
  4182. offset, size, usn);
  4183. try {
  4184. // Make sure the Scan Item interface is OK
  4185. WsbAssert(pScanItem != 0, E_POINTER);
  4186. WsbAffirmHr(CoCreateInstance(CLSID_CFsaPostIt, 0, CLSCTX_SERVER, IID_IFsaPostIt, (void**) &pWorkItem));
  4187. // Get the data from the scan item.
  4188. WsbAffirmHr(pScanItem->GetSession(&pSession));
  4189. WsbAffirmHr(pWorkItem->SetSession(pSession));
  4190. WsbAffirmHr(pScanItem->GetPathAndName(0, &tmpString, 0));
  4191. WsbAffirmHr(pWorkItem->SetPath(tmpString));
  4192. WsbAffirmHr(pWorkItem->SetRequestOffset(offset));
  4193. WsbAffirmHr(pWorkItem->SetRequestSize(size));
  4194. WsbAffirmHr(pScanItem->GetPlaceholder(offset, size, &(placeholder)));
  4195. WsbAffirmHr(pWorkItem->SetPlaceholder(&placeholder));
  4196. // Fill in the rest of the work
  4197. WsbAffirmHr(pWorkItem->SetRequestAction(FSA_REQUEST_ACTION_VALIDATE_FOR_TRUNCATE));
  4198. WsbAffirmHr(pWorkItem->SetResultAction(FSA_RESULT_ACTION_NONE));
  4199. // Fill in the USN
  4200. WsbAffirmHr(pWorkItem->SetUSN(usn));
  4201. // Send the request to the task manager
  4202. WsbAffirmHr(GetHsmEngine(&pEngine));
  4203. WsbAffirmHr(pEngine->DoFsaWork(pWorkItem));
  4204. } WsbCatch(hr);
  4205. WsbTraceOut(OLESTR("CFsaResource::ValidateForTruncate"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  4206. return(hr);
  4207. }
  4208. HRESULT
  4209. CFsaResource::WriteIdentifier(
  4210. void
  4211. )
  4212. /*++
  4213. This code is no longer called, in time it will be removed
  4214. --*/
  4215. {
  4216. #if 0
  4217. HRESULT hr = S_OK;
  4218. CWsbStringPtr tmpString;
  4219. HANDLE aHandle;
  4220. ULONG size;
  4221. ULONG bytesWritten;
  4222. FILE_FS_OBJECT_ID_INFORMATION objectId;
  4223. NTSTATUS status = STATUS_SUCCESS;
  4224. IO_STATUS_BLOCK ioStatus;
  4225. WsbTraceIn(OLESTR("CFsaResource::WriteIdentifier"), OLESTR(""));
  4226. try {
  4227. // For now, we will create a file in the root of the volume.
  4228. tmpString = m_path;
  4229. WsbAffirmHr(tmpString.Prepend("\\\\?\\"));
  4230. // WsbAffirmHr(tmpString.Append(":MSHSM_FSAID"));
  4231. WsbAffirmHandle(aHandle = CreateFile(tmpString,
  4232. GENERIC_WRITE,
  4233. 0,
  4234. 0,
  4235. OPEN_EXISTING,
  4236. FILE_ATTRIBUTE_NORMAL,
  4237. 0));
  4238. try {
  4239. WsbAffirmHr(WsbConvertToBytes(objectId.ObjectId, m_id, &size));
  4240. status = NtSetVolumeInformationFile(
  4241. aHandle,
  4242. &ioStatus,
  4243. &objectId,
  4244. sizeof(objectId),
  4245. FileFsObjectIdInformation);
  4246. WsbAffirmNtStatus(status);
  4247. WsbAffirm(bytesWritten == size, E_FAIL);
  4248. } WsbCatch(hr);
  4249. WsbAffirmStatus(CloseHandle(aHandle));
  4250. } WsbCatch(hr);
  4251. WsbTraceOut(OLESTR("CFsaResource::WriteIdentifier"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  4252. return(hr);
  4253. #else
  4254. return S_OK;
  4255. #endif
  4256. }
  4257. void CFsaResource::OnStateChange( )
  4258. /*++
  4259. Note: This function is run in a separate thread to avoid a deadlock situation
  4260. --*/
  4261. {
  4262. IConnectionPointImpl<CFsaResource, &IID_IHsmEvent, CComDynamicUnkArray>* p = this;
  4263. Lock();
  4264. HRESULT hr = S_OK;
  4265. IUnknown** pp = p->m_vec.begin();
  4266. while (pp < p->m_vec.end() && hr == S_OK)
  4267. {
  4268. if (*pp != NULL)
  4269. {
  4270. IHsmEvent* pIHsmEvent = (IHsmEvent*)*pp;
  4271. hr = pIHsmEvent->OnStateChange( );
  4272. }
  4273. pp++;
  4274. }
  4275. Unlock();
  4276. }