Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1846 lines
40 KiB

  1. /*++
  2. 1998 Seagate Software, Inc. All rights reserved
  3. Module Name:
  4. fsaftrcl.cpp
  5. Abstract:
  6. This class represents a filter initiated recall request that is still in-progress.
  7. Author:
  8. Chuck Bardeen [cbardeen] 12-Feb-1997
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #include "devioctl.h"
  13. #define WSB_TRACE_IS WSB_TRACE_BIT_FSA
  14. #include "wsb.h"
  15. #include "fsa.h"
  16. #include "job.h"
  17. #include "fsaftrcl.h"
  18. #include "rpdata.h"
  19. #include "rpio.h"
  20. static USHORT iCountFtrcl = 0; // Count of existing objects
  21. HRESULT
  22. CFsaFilterRecall::Cancel(
  23. void
  24. )
  25. /*++
  26. Implements:
  27. IFsaFilterRecallPriv::Cancel().
  28. --*/
  29. {
  30. CComPtr<IFsaFilterClient> pClient;
  31. CComPtr<IWsbEnum> pEnum;
  32. HRESULT hr = S_OK, hr2;
  33. DWORD dwStatus;
  34. WsbTraceIn(OLESTR("CFsaFilterRecall::Cancel"), OLESTR("filter Id = %I64x"),
  35. m_driversRecallId);
  36. try {
  37. WsbAffirm(!m_wasCancelled, E_UNEXPECTED);
  38. try {
  39. //
  40. // Tell the filter to fail the open of the file.
  41. //
  42. if (m_kernelCompletionSent == FALSE) {
  43. WsbAffirmHr(m_pFilterPriv->SendCancel((IFsaFilterRecallPriv *) this));
  44. m_kernelCompletionSent = TRUE;
  45. m_wasCancelled = TRUE;
  46. }
  47. if (m_pClient != 0) {
  48. // Reporting on recall end must be synchronized with the recall start notification,
  49. // because such notification might be sent after the recall starts
  50. switch (WaitForSingleObject(m_notifyEvent, INFINITE)) {
  51. case WAIT_OBJECT_0:
  52. m_pClient->SendRecallInfo((IFsaFilterRecall *) this, FALSE, HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED));
  53. SetEvent(m_notifyEvent);
  54. break;
  55. case WAIT_FAILED:
  56. default:
  57. WsbTrace(OLESTR("CFsaFilterRecall::Cancel: WaitForSingleObject returned error %lu\n"), GetLastError());
  58. // Notify anyway
  59. m_pClient->SendRecallInfo((IFsaFilterRecall *) this, FALSE, HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED));
  60. break;
  61. }
  62. }
  63. dwStatus = WaitForSingleObject(m_waitingClientEvent, INFINITE);
  64. // Notify on recall end no matter what the status is
  65. if (m_pWaitingClients != 0) {
  66. //
  67. // Send recall notifications to all clients waiting for
  68. // the recall to finish
  69. //
  70. hr2 = m_pWaitingClients->Enum(&pEnum);
  71. if (S_OK == hr2) {
  72. hr2 = pEnum->First(IID_IFsaFilterClient, (void**) &pClient);
  73. while (S_OK == hr2) {
  74. pClient->SendRecallInfo((IFsaFilterRecall *) this, FALSE, HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED));
  75. m_pWaitingClients->RemoveAndRelease(pClient);
  76. pClient = NULL;
  77. pEnum->Reset();
  78. hr2 = pEnum->First(IID_IFsaFilterClient, (void**) &pClient);
  79. }
  80. }
  81. }
  82. m_waitingClientsNotified = TRUE;
  83. switch (dwStatus) {
  84. case WAIT_OBJECT_0:
  85. SetEvent(m_waitingClientEvent);
  86. break;
  87. case WAIT_FAILED:
  88. default:
  89. WsbTrace(OLESTR("CFsaFilterRecall::Cancel: WaitForSingleObject returned error %lu\n"), dwStatus);
  90. break;
  91. }
  92. //
  93. // Now get the engine to cancel it, if possible..
  94. //
  95. if (m_pSession != 0) {
  96. WsbAffirmHr(m_pSession->Cancel(HSM_JOB_PHASE_ALL));
  97. }
  98. } WsbCatch(hr);
  99. } WsbCatch(hr);
  100. WsbTraceOut(OLESTR("CFsaFilterRecall::Cancel"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  101. return(hr);
  102. }
  103. HRESULT
  104. CFsaFilterRecall::CancelByDriver(
  105. void
  106. )
  107. /*++
  108. Implements:
  109. IFsaFilterRecallPriv::CancelByDriver().
  110. --*/
  111. {
  112. HRESULT hr = S_OK;
  113. WsbTraceIn(OLESTR("CFsaFilterRecall::CancelByDriver"), OLESTR("filter Id = %I64x"),
  114. m_driversRecallId);
  115. try {
  116. WsbAffirm(!m_wasCancelled, E_UNEXPECTED);
  117. try {
  118. //
  119. // No need to tell the filter anymore - reset the flag.
  120. //
  121. m_kernelCompletionSent = TRUE;
  122. //
  123. // Now get the engine to cancel it, if possible..
  124. //
  125. if (m_pSession != 0) {
  126. WsbAffirmHr(m_pSession->Cancel(HSM_JOB_PHASE_ALL));
  127. }
  128. } WsbCatch(hr);
  129. } WsbCatch(hr);
  130. WsbTraceOut(OLESTR("CFsaFilterRecall::CancelByDriver"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  131. return(hr);
  132. }
  133. HRESULT
  134. CFsaFilterRecall::CompareBy(
  135. IN FSA_RECALL_COMPARE by
  136. )
  137. /*++
  138. Implements:
  139. IWsbCollectable::CompareBy().
  140. --*/
  141. {
  142. HRESULT hr = S_OK;
  143. WsbTraceIn(OLESTR("CFsaFilterRecall::CompareBy"), OLESTR("by = %ld"),
  144. static_cast<LONG>(by));
  145. try {
  146. m_compareBy = by;
  147. } WsbCatch(hr);
  148. WsbTraceOut(OLESTR("CFsaFilterRecall::CompareBy"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  149. return(hr);
  150. }
  151. HRESULT
  152. CFsaFilterRecall::CompareTo(
  153. IN IUnknown* pUnknown,
  154. OUT SHORT* pResult
  155. )
  156. /*++
  157. Implements:
  158. IWsbCollectable::CompareTo().
  159. --*/
  160. {
  161. HRESULT hr = S_OK;
  162. CComPtr<IFsaFilterRecall> pRecall;
  163. CComPtr<IFsaFilterRecallPriv> pRecallPriv;
  164. ULONGLONG id;
  165. // WsbTraceIn(OLESTR("CFsaFilterRecall::CompareTo"), OLESTR(""));
  166. try {
  167. // Did they give us a valid item to compare to?
  168. WsbAssert(0 != pUnknown, E_POINTER);
  169. if (m_compareBy == FSA_RECALL_COMPARE_IRECALL) {
  170. // We need the IFsaFilterRecall interface to get the value of the object.
  171. WsbAffirmHr(pUnknown->QueryInterface(IID_IFsaFilterRecall, (void**) &pRecall));
  172. // Compare the rules.
  173. hr = CompareToIRecall(pRecall, pResult);
  174. } else {
  175. // We need the IFsaFilterRecallPriv interface to get the value of the object.
  176. WsbAffirmHr(pUnknown->QueryInterface(IID_IFsaFilterRecallPriv, (void**) &pRecallPriv));
  177. WsbAffirmHr(pRecallPriv->GetDriversRecallId(&id));
  178. // Compare the driver id
  179. if (m_compareBy == FSA_RECALL_COMPARE_CONTEXT_ID) {
  180. hr = CompareToDriversContextId((id&0xFFFFFFFF), pResult);
  181. } else {
  182. hr = CompareToDriversRecallId(id, pResult);
  183. }
  184. }
  185. } WsbCatch(hr);
  186. // WsbTraceOut(OLESTR("CFsaFilterRecall::CompareTo"), OLESTR("hr = <%ls>, result = <%ls>"), WsbHrAsString(hr), WsbPtrToShortAsString(pResult));
  187. return(hr);
  188. }
  189. HRESULT
  190. CFsaFilterRecall::CompareToDriversRecallId(
  191. IN ULONGLONG id,
  192. OUT SHORT* pResult
  193. )
  194. /*++
  195. Implements:
  196. IFsaFilterRecall::CompareToDriversRecallId().
  197. --*/
  198. {
  199. HRESULT hr = S_OK;
  200. SHORT aResult;
  201. // WsbTraceIn(OLESTR("CFsaFilterRecall::CompareToDriversRecallId"), OLESTR(""));
  202. try {
  203. if (m_driversRecallId == id)
  204. aResult = 0;
  205. else
  206. aResult = 1;
  207. if (0 != aResult) {
  208. hr = S_FALSE;
  209. }
  210. if (0 != pResult) {
  211. *pResult = aResult;
  212. }
  213. } WsbCatch(hr);
  214. // WsbTraceOut(OLESTR("CFsaFilterRecall::CompareToDriversRecallId"), OLESTR("hr = <%ls>, result = <%d>"), WsbHrAsString(hr), aResult);
  215. return(hr);
  216. }
  217. HRESULT
  218. CFsaFilterRecall::CompareToDriversContextId(
  219. IN ULONGLONG id,
  220. OUT SHORT* pResult
  221. )
  222. /*++
  223. Implements:
  224. IFsaFilterRecall::CompareToDriversContextId().
  225. --*/
  226. {
  227. HRESULT hr = S_OK;
  228. SHORT aResult;
  229. // WsbTraceIn(OLESTR("CFsaFilterRecall::CompareToDriversContextId"), OLESTR(""));
  230. try {
  231. if ((m_driversRecallId & 0xFFFFFFFF) == id)
  232. aResult = 0;
  233. else
  234. aResult = 1;
  235. if (0 != aResult) {
  236. hr = S_FALSE;
  237. }
  238. if (0 != pResult) {
  239. *pResult = aResult;
  240. }
  241. } WsbCatch(hr);
  242. // WsbTraceOut(OLESTR("CFsaFilterRecall::CompareToDriversContextId"), OLESTR("hr = <%ls>, result = <%d>"), WsbHrAsString(hr), aResult);
  243. return(hr);
  244. }
  245. HRESULT
  246. CFsaFilterRecall::CompareToIdentifier(
  247. IN GUID id,
  248. OUT SHORT* pResult
  249. )
  250. /*++
  251. Implements:
  252. IFsaFilterRecall::CompareToIdentifier().
  253. --*/
  254. {
  255. HRESULT hr = S_OK;
  256. SHORT aResult;
  257. // WsbTraceIn(OLESTR("CFsaFilterRecall::CompareToIdentifier"), OLESTR(""));
  258. try {
  259. aResult = WsbSign( memcmp(&m_id, &id, sizeof(GUID)) );
  260. if (0 != aResult) {
  261. hr = S_FALSE;
  262. }
  263. if (0 != pResult) {
  264. *pResult = aResult;
  265. }
  266. } WsbCatch(hr);
  267. // WsbTraceOut(OLESTR("CFsaFilterRecall::CompareToIdentifier"), OLESTR("hr = <%ls>, result = <%d>"), WsbHrAsString(hr), aResult);
  268. return(hr);
  269. }
  270. HRESULT
  271. CFsaFilterRecall::CompareToIRecall(
  272. IN IFsaFilterRecall* pRecall,
  273. OUT SHORT* pResult
  274. )
  275. /*++
  276. Implements:
  277. IFsaFilterRecall::CompareToIRecall().
  278. --*/
  279. {
  280. HRESULT hr = S_OK;
  281. CWsbStringPtr name;
  282. GUID id;
  283. // WsbTraceIn(OLESTR("CFsaFilterRecall::CompareToIRecall"), OLESTR(""));
  284. try {
  285. // Did they give us a valid item to compare to?
  286. WsbAssert(0 != pRecall, E_POINTER);
  287. WsbAffirmHr(pRecall->GetIdentifier(&id));
  288. hr = CompareToIdentifier(id, pResult);
  289. } WsbCatch(hr);
  290. // WsbTraceOut(OLESTR("CFsaFilterRecall::CompareToIRecall"), OLESTR("hr = <%ls>, result = <%ls>"), WsbHrAsString(hr), WsbPtrToShortAsString(pResult));
  291. return(hr);
  292. }
  293. HRESULT
  294. CFsaFilterRecall::CreateLocalStream(
  295. OUT IStream **ppStream
  296. )
  297. /*++
  298. Implements:
  299. IFsaFilterRecall::CreateLocalStream().
  300. --*/
  301. {
  302. HRESULT hr = S_OK;
  303. WCHAR idString[50];
  304. CWsbStringPtr pDrv;
  305. OLECHAR volume[64];
  306. WsbTraceIn(OLESTR("CFsaFilterRecall::CreateLocalStream"), OLESTR("filter Id = %I64x"),
  307. m_driversRecallId);
  308. try {
  309. WsbAssert( 0 != ppStream, E_POINTER);
  310. swprintf(idString, L"%I64u", m_driversRecallId);
  311. WsbAffirmHr( CoCreateInstance( CLSID_CFilterIo, 0, CLSCTX_SERVER, IID_IDataMover, (void **)&m_pDataMover ) );
  312. WsbAssertHr( m_pDataMover->CreateLocalStream(
  313. idString, MVR_MODE_WRITE | MVR_FLAG_HSM_SEMANTICS | MVR_FLAG_POSIX_SEMANTICS, &m_pStream ) );
  314. //
  315. // Set the device name for the mover which is used to recall the file.
  316. // This is the RsFilter's primary device object's name to which the
  317. // the RP_PARTIAL_DATA msgs etc. will be sent
  318. //
  319. WsbAffirmHr(m_pResource->GetPath(&pDrv,0));
  320. swprintf(volume, L"\\\\.\\%s", pDrv);
  321. //
  322. // strip trailing backslash if any
  323. //
  324. if (volume[wcslen(volume)-1] == L'\\') {
  325. volume[wcslen(volume)-1] = L'\0';
  326. }
  327. WsbAssertHr( m_pDataMover->SetDeviceName(RS_FILTER_SYM_LINK,
  328. volume));
  329. *ppStream = m_pStream;
  330. m_pStream->AddRef();
  331. } WsbCatch(hr);
  332. WsbTraceOut(OLESTR("CFsaFilterRecall::CreateLocalStream"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  333. return(hr);
  334. }
  335. HRESULT
  336. CFsaFilterRecall::Delete(
  337. void
  338. )
  339. /*++
  340. Implements:
  341. IFsaFilterRecallPriv::Delete().
  342. --*/
  343. {
  344. HRESULT hr = S_OK;
  345. WsbTraceIn(OLESTR("CFsaFilterRecall::Delete"), OLESTR("filter Id = %I64x"),
  346. m_driversRecallId);
  347. try {
  348. //
  349. // Tell the kernel mode filter to fail the open of the file.
  350. //
  351. if (m_kernelCompletionSent == FALSE) {
  352. WsbAffirmHr(m_pFilterPriv->SendCancel((IFsaFilterRecallPriv *) this));
  353. m_kernelCompletionSent = TRUE;
  354. m_wasCancelled = TRUE;
  355. }
  356. } WsbCatch(hr);
  357. WsbTraceOut(OLESTR("CFsaFilterRecall::Delete"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  358. return(hr);
  359. }
  360. HRESULT
  361. CFsaFilterRecall::FinalConstruct(
  362. void
  363. )
  364. /*++
  365. Implements:
  366. CComObjectRoot::FinalConstruct().
  367. --*/
  368. {
  369. HRESULT hr = S_OK;
  370. WsbTraceIn(OLESTR("CFsaFilterRecall::FinalConstruct"), OLESTR(""));
  371. try {
  372. WsbAffirmHr(CWsbCollectable::FinalConstruct());
  373. m_notifyEvent = NULL;
  374. m_waitingClientEvent = NULL;
  375. m_driversRecallId = 0;
  376. memset(&m_placeholder, 0, sizeof(FSA_PLACEHOLDER));
  377. m_state = HSM_JOB_STATE_IDLE;
  378. m_wasCancelled = FALSE;
  379. m_kernelCompletionSent = FALSE;
  380. m_pDataMover = 0;
  381. m_pStream = 0;
  382. m_recallFlags = 0;
  383. m_compareBy = FSA_RECALL_COMPARE_IRECALL;
  384. WsbAffirmHr(CoCreateGuid(&m_id));
  385. numRefs = 0;
  386. m_waitingClientsNotified = FALSE;
  387. // Initialize notify synchronization event and waiting clients event
  388. WsbAffirmHandle((m_notifyEvent = CreateEvent(NULL, FALSE, TRUE, NULL)));
  389. WsbAffirmHandle((m_waitingClientEvent = CreateEvent(NULL, FALSE, TRUE, NULL)));
  390. // Create the waiting client collection.
  391. WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, NULL, CLSCTX_SERVER, IID_IWsbCollection, (void**) &m_pWaitingClients));
  392. } WsbCatch(hr);
  393. iCountFtrcl++;
  394. WsbTraceOut(OLESTR("CFsaFilterRecall::FinalConstruct"), OLESTR("hr = %ls, Count is <%d>"), WsbHrAsString(hr), iCountFtrcl);
  395. return(hr);
  396. }
  397. void
  398. CFsaFilterRecall::FinalRelease(
  399. void
  400. )
  401. /*++
  402. Implements:
  403. CComObjectRoot::FinalRelease().
  404. --*/
  405. {
  406. WsbTraceIn(OLESTR("CFsaFilterRecall::FinalRelease"), OLESTR(""));
  407. CWsbCollectable::FinalRelease();
  408. // Free notify synchronization event and waiting client event
  409. if (m_waitingClientEvent != NULL) {
  410. CloseHandle(m_waitingClientEvent);
  411. m_waitingClientEvent = NULL;
  412. }
  413. if (m_notifyEvent != NULL) {
  414. CloseHandle(m_notifyEvent);
  415. m_notifyEvent = NULL;
  416. }
  417. iCountFtrcl--;
  418. WsbTraceOut(OLESTR("CFsaFilterRecall::FinalRelease"), OLESTR("Count is <%d>"), iCountFtrcl);
  419. }
  420. #ifdef FSA_RECALL_LEAK_TEST
  421. ULONG
  422. CFsaFilterRecall::InternalAddRef(
  423. void
  424. )
  425. /*++
  426. Implements:
  427. CComObjectRoot::AddRef().
  428. --*/
  429. {
  430. numRefs++;
  431. WsbTrace(OLESTR("CFsaFilterRecall::AddRef (%p) - Count = %u\n"), this, numRefs);
  432. return(CComObjectRoot::InternalAddRef());
  433. }
  434. ULONG
  435. CFsaFilterRecall::InternalRelease(
  436. void
  437. )
  438. /*++
  439. Implements:
  440. CComObjectRoot::InternalRelease().
  441. --*/
  442. {
  443. WsbTrace(OLESTR("CFsaFilterRecall::Release (%p) - Count = %u\n"), this, numRefs);
  444. numRefs--;
  445. return(CComObjectRoot::InternalRelease());
  446. }
  447. #endif
  448. HRESULT
  449. CFsaFilterRecall::GetClassID(
  450. OUT CLSID* pClsid
  451. )
  452. /*++
  453. Implements:
  454. IPersist::GetClassID().
  455. --*/
  456. {
  457. HRESULT hr = S_OK;
  458. WsbTraceIn(OLESTR("CFsaFilterRecall::GetClassID"), OLESTR(""));
  459. try {
  460. WsbAssert(0 != pClsid, E_POINTER);
  461. *pClsid = CLSID_CFsaFilterRecallNTFS;
  462. } WsbCatch(hr);
  463. WsbTraceOut(OLESTR("CFsaFilterRecall::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid));
  464. return(hr);
  465. }
  466. HRESULT
  467. CFsaFilterRecall::GetClient(
  468. OUT IFsaFilterClient** ppClient
  469. )
  470. /*++
  471. Implements:
  472. IFsaFilterRecallPriv::GetClient().
  473. --*/
  474. {
  475. HRESULT hr = S_OK;
  476. try {
  477. WsbAssert(0 != ppClient, E_POINTER);
  478. *ppClient = m_pClient;
  479. if (m_pClient != 0) {
  480. m_pClient->AddRef();
  481. }
  482. } WsbCatch(hr);
  483. return(hr);
  484. }
  485. HRESULT
  486. CFsaFilterRecall::GetRecallFlags(
  487. OUT ULONG *pFlags
  488. )
  489. /*++
  490. Implements:
  491. IFsaFilterRecall::GetRecallFlags()
  492. --*/
  493. {
  494. HRESULT hr = S_OK;
  495. WsbTraceIn(OLESTR("CFsaFilterRecall::GetRecallFlags"), OLESTR(""));
  496. try {
  497. WsbAssert( 0 != pFlags, E_POINTER);
  498. *pFlags = m_recallFlags;
  499. } WsbCatch(hr);
  500. WsbTraceOut(OLESTR("CFsaFilterRecall::GetRecallFlags"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  501. return(hr);
  502. }
  503. HRESULT
  504. CFsaFilterRecall::GetStream(
  505. OUT IStream **ppStream
  506. )
  507. /*++
  508. Implements:
  509. IFsaFilterRecall::GetStream()
  510. --*/
  511. {
  512. HRESULT hr = S_OK;
  513. WsbTraceIn(OLESTR("CFsaFilterRecall::GetStream"), OLESTR(""));
  514. try {
  515. WsbAssert( 0 != ppStream, E_POINTER);
  516. if ((m_mode & FILE_OPEN_NO_RECALL) && (m_pStream != 0)) {
  517. *ppStream = m_pStream;
  518. m_pStream->AddRef();
  519. } else {
  520. *ppStream = 0;
  521. hr = WSB_E_NOTFOUND;
  522. }
  523. } WsbCatch(hr);
  524. WsbTraceOut(OLESTR("CFsaFilterRecall::GetStream"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  525. return(hr);
  526. }
  527. HRESULT
  528. CFsaFilterRecall::GetDriversRecallId(
  529. OUT ULONGLONG* pId
  530. )
  531. /*++
  532. Implements:
  533. IFsaFilterRecallPriv::GetDriversRecallId().
  534. --*/
  535. {
  536. HRESULT hr = S_OK;
  537. try {
  538. WsbAssert(0 != pId, E_POINTER);
  539. *pId = m_driversRecallId;
  540. } WsbCatch(hr);
  541. return(hr);
  542. }
  543. HRESULT
  544. CFsaFilterRecall::GetIdentifier(
  545. OUT GUID* pId
  546. )
  547. /*++
  548. Implements:
  549. IFsaFilterRecall::GetIdentifier().
  550. --*/
  551. {
  552. HRESULT hr = S_OK;
  553. try {
  554. WsbAssert(0 != pId, E_POINTER);
  555. *pId = m_id;
  556. } WsbCatch(hr);
  557. return(hr);
  558. }
  559. HRESULT
  560. CFsaFilterRecall::GetMode(
  561. OUT ULONG* pMode
  562. )
  563. /*++
  564. Implements:
  565. IFsaFilterRecall::GetMode().
  566. --*/
  567. {
  568. HRESULT hr = S_OK;
  569. try {
  570. WsbAssert(0 != pMode, E_POINTER);
  571. *pMode = m_mode;
  572. } WsbCatch(hr);
  573. return(hr);
  574. }
  575. HRESULT
  576. CFsaFilterRecall::GetOffset(
  577. OUT LONGLONG* pOffset
  578. )
  579. /*++
  580. Implements:
  581. IFsaFilterRecall::GetOffset().
  582. --*/
  583. {
  584. HRESULT hr = S_OK;
  585. try {
  586. WsbAssert(0 != pOffset, E_POINTER);
  587. *pOffset = m_offset;
  588. } WsbCatch(hr);
  589. return(hr);
  590. }
  591. HRESULT
  592. CFsaFilterRecall::GetPath(
  593. OUT OLECHAR** pName,
  594. IN ULONG bufferSize
  595. )
  596. /*++
  597. Implements:
  598. IFsaFilterRecall::GetPath().
  599. --*/
  600. {
  601. HRESULT hr = S_OK;
  602. CWsbStringPtr tmpString;
  603. try {
  604. WsbAssert(0 != pName, E_POINTER);
  605. WsbAffirmHr(tmpString.TakeFrom(*pName, bufferSize));
  606. try {
  607. WsbAffirmHr(m_pResource->GetUncPath(&tmpString, 0));
  608. WsbAffirmHr(tmpString.Append(m_path));
  609. } WsbCatch(hr);
  610. WsbAffirmHr(tmpString.GiveTo(pName));
  611. } WsbCatch(hr);
  612. return(hr);
  613. }
  614. HRESULT
  615. CFsaFilterRecall::GetPlaceholder(
  616. OUT FSA_PLACEHOLDER* pPlaceholder
  617. )
  618. /*++
  619. Implements:
  620. IFsaFilterRecallPriv::GetPlaceholder().
  621. --*/
  622. {
  623. HRESULT hr = S_OK;
  624. try {
  625. WsbAssert(0 != pPlaceholder, E_POINTER);
  626. *pPlaceholder = m_placeholder;
  627. } WsbCatch(hr);
  628. return(hr);
  629. }
  630. HRESULT
  631. CFsaFilterRecall::GetResource(
  632. OUT IFsaResource** ppResource
  633. )
  634. /*++
  635. Implements:
  636. IFsaFilterRecall::GetResource().
  637. --*/
  638. {
  639. HRESULT hr = S_OK;
  640. try {
  641. WsbAssert(0 != ppResource, E_POINTER);
  642. *ppResource = m_pResource;
  643. m_pResource->AddRef();
  644. } WsbCatch(hr);
  645. return(hr);
  646. }
  647. HRESULT
  648. CFsaFilterRecall::GetSession(
  649. OUT IHsmSession** ppSession
  650. )
  651. /*++
  652. Implements:
  653. IFsaFilterRecall::GetSession().
  654. --*/
  655. {
  656. HRESULT hr = S_OK;
  657. try {
  658. WsbAssert(0 != ppSession, E_POINTER);
  659. *ppSession = m_pSession;
  660. m_pSession->AddRef();
  661. } WsbCatch(hr);
  662. return(hr);
  663. }
  664. HRESULT
  665. CFsaFilterRecall::GetSize(
  666. OUT LONGLONG* pSize
  667. )
  668. /*++
  669. Implements:
  670. IFsaFilterRecall::GetSize().
  671. --*/
  672. {
  673. HRESULT hr = S_OK;
  674. try {
  675. WsbAssert(0 != pSize, E_POINTER);
  676. *pSize = m_size;
  677. } WsbCatch(hr);
  678. return(hr);
  679. }
  680. HRESULT
  681. CFsaFilterRecall::GetSizeMax(
  682. OUT ULARGE_INTEGER* pSize
  683. )
  684. /*++
  685. Implements:
  686. IPersistStream::GetSizeMax().
  687. --*/
  688. {
  689. HRESULT hr = S_OK;
  690. WsbTraceIn(OLESTR("CFsaFilterRecall::GetSizeMax"), OLESTR(""));
  691. try {
  692. WsbAssert(0 != pSize, E_POINTER);
  693. pSize->QuadPart = 0;
  694. // WE don't need to persist these.
  695. hr = E_NOTIMPL;
  696. } WsbCatch(hr);
  697. WsbTraceOut(OLESTR("CFsaFilterRecall::GetSizeMax"), OLESTR("hr = <%ls>, Size = <%ls>"), WsbHrAsString(hr), WsbPtrToUliAsString(pSize));
  698. return(hr);
  699. }
  700. HRESULT
  701. CFsaFilterRecall::GetState(
  702. OUT HSM_JOB_STATE* pState
  703. )
  704. /*++
  705. Implements:
  706. IFsaFilterRecall::GetState().
  707. --*/
  708. {
  709. HRESULT hr = S_OK;
  710. try {
  711. WsbAssert(0 != pState, E_POINTER);
  712. *pState = m_state;
  713. } WsbCatch(hr);
  714. return(hr);
  715. }
  716. HRESULT
  717. CFsaFilterRecall::GetUserName(
  718. OUT OLECHAR** pName,
  719. IN ULONG bufferSize
  720. )
  721. /*++
  722. Implements:
  723. IFsaFilterRecall::GetUserName().
  724. --*/
  725. {
  726. HRESULT hr = S_OK;
  727. try {
  728. WsbAssert(0 != pName, E_POINTER);
  729. if (m_pClient != 0) {
  730. WsbAffirmHr(m_pClient->GetUserName(pName, bufferSize));
  731. } else {
  732. hr = WSB_E_NOTFOUND;
  733. }
  734. } WsbCatch(hr);
  735. return(hr);
  736. }
  737. HRESULT
  738. CFsaFilterRecall::HasCompleted(
  739. HRESULT resultHr
  740. )
  741. /*++
  742. Implements:
  743. IFsaFilterRecall::HasCompleted().
  744. --*/
  745. {
  746. HRESULT hr = S_OK, hr2 = S_OK;
  747. CComPtr<IFsaFilterClient> pClient;
  748. CComPtr<IWsbEnum> pEnum;
  749. FILETIME now;
  750. BOOL bSendNotify = TRUE;
  751. DWORD dwStatus;
  752. WsbTraceIn(OLESTR("CFsaFilterRecall::HasCompleted"),
  753. OLESTR("filter Id = %I64x, recall hr = <%ls>"), m_driversRecallId,
  754. WsbHrAsString(resultHr));
  755. try {
  756. // The job is complete, let the kernel mode filter know what happened.
  757. GetSystemTimeAsFileTime(&now);
  758. if (m_pClient != 0) {
  759. m_pClient->SetLastRecallTime(now); // Not fatal if this fails
  760. }
  761. if (m_kernelCompletionSent == FALSE) {
  762. WsbAffirmHr(m_pFilterPriv->SendComplete((IFsaFilterRecallPriv *) this, resultHr));
  763. m_kernelCompletionSent = TRUE;
  764. }
  765. if (m_pClient != 0) {
  766. // Reporting on recall end must be synchronized with the recall start notification,
  767. // because such notification might be sent after the recall starts
  768. switch (WaitForSingleObject(m_notifyEvent, INFINITE)) {
  769. case WAIT_OBJECT_0:
  770. // Send recall notifications to the client that initiated the recall
  771. m_pClient->SendRecallInfo((IFsaFilterRecall *) this, FALSE, resultHr);
  772. SetEvent(m_notifyEvent);
  773. break;
  774. case WAIT_FAILED:
  775. default:
  776. WsbTrace(OLESTR("CFsaFilterRecall::HasCompleted: WaitForSingleObject returned error %lu\n"), GetLastError());
  777. // Notify anyway
  778. m_pClient->SendRecallInfo((IFsaFilterRecall *) this, FALSE, resultHr);
  779. break;
  780. }
  781. bSendNotify = FALSE;
  782. }
  783. dwStatus = WaitForSingleObject(m_waitingClientEvent, INFINITE);
  784. // Notify on recall end no matter what the status is
  785. if (m_pWaitingClients != 0) {
  786. //
  787. // Send recall notifications to all clients waiting for the recall
  788. // to finish
  789. //
  790. hr2 = m_pWaitingClients->Enum(&pEnum);
  791. if (S_OK == hr2) {
  792. hr2 = pEnum->First(IID_IFsaFilterClient, (void**) &pClient);
  793. while (S_OK == hr2) {
  794. pClient->SendRecallInfo((IFsaFilterRecall *) this, FALSE, resultHr);
  795. m_pWaitingClients->RemoveAndRelease(pClient);
  796. pClient = NULL;
  797. pEnum->Reset();
  798. hr2 = pEnum->First(IID_IFsaFilterClient, (void**) &pClient);
  799. }
  800. }
  801. }
  802. m_waitingClientsNotified = TRUE;
  803. switch (dwStatus) {
  804. case WAIT_OBJECT_0:
  805. SetEvent(m_waitingClientEvent);
  806. break;
  807. case WAIT_FAILED:
  808. default:
  809. WsbTrace(OLESTR("CFsaFilterRecall::HasCompleted: WaitForSingleObject returned error %lu\n"), dwStatus);
  810. break;
  811. }
  812. //
  813. // Detach the data mover stream
  814. //
  815. if (m_pDataMover != 0) {
  816. WsbAffirmHr( m_pDataMover->CloseStream() );
  817. }
  818. } WsbCatchAndDo(hr,
  819. if ((m_pClient != 0) && bSendNotify) {
  820. m_pClient->SendRecallInfo((IFsaFilterRecall *) this, FALSE, resultHr);
  821. bSendNotify = FALSE;
  822. }
  823. );
  824. WsbTraceOut(OLESTR("CFsaFilterRecall::HasCompleted"), OLESTR("filter Id = %I64x, sent = <%ls>, hr = <%ls>"),
  825. m_driversRecallId, WsbBoolAsString(m_kernelCompletionSent),
  826. WsbHrAsString(hr));
  827. return(hr);
  828. }
  829. HRESULT
  830. CFsaFilterRecall::CheckRecallLimit(
  831. IN DWORD minRecallInterval,
  832. IN DWORD maxRecalls,
  833. IN BOOLEAN exemptAdmin
  834. )
  835. /*++
  836. Implements:
  837. IFsaFilterRecall::CheckRecallLimit().
  838. --*/
  839. {
  840. HRESULT hr = S_OK;
  841. WsbTraceIn(OLESTR("CFsaFilterRecall::CheckRecallLimit"), OLESTR("filter Id = %I64x"),
  842. m_driversRecallId);
  843. try {
  844. // Check the limit if we are not file open no recall
  845. if (!(m_mode & FILE_OPEN_NO_RECALL) && (m_pClient != NULL)) {
  846. WsbAffirmHr(m_pClient->CheckRecallLimit(minRecallInterval, maxRecalls, exemptAdmin));
  847. }
  848. } WsbCatch(hr);
  849. //
  850. // Commenting the following out: we are reverting back to
  851. // denial of service when we hit the recall limit, not trunc-on-close
  852. //
  853. // If we hit the recall limit then we start to truncate on close.
  854. //
  855. // if (hr == FSA_E_HIT_RECALL_LIMIT) {
  856. // m_recallFlags |= RP_RECALL_ACTION_TRUNCATE;
  857. // }
  858. WsbTraceOut(OLESTR("CFsaFilterRecall::CheckRecallLimit"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  859. return(hr);
  860. }
  861. HRESULT
  862. CFsaFilterRecall::Init(
  863. IN IFsaFilterClient* pClient,
  864. IN ULONGLONG DriversRecallId,
  865. IN IFsaResource* pResource,
  866. IN OLECHAR* path,
  867. IN LONGLONG fileId,
  868. IN LONGLONG offset,
  869. IN LONGLONG size,
  870. IN ULONG mode,
  871. IN FSA_PLACEHOLDER* pPlaceholder,
  872. IN IFsaFilterPriv *pFilterPriv
  873. )
  874. /*++
  875. Implements:
  876. IFsaFilterRecallPriv::Init().
  877. --*/
  878. {
  879. HRESULT hr = S_OK;
  880. FILETIME now;
  881. CComPtr<IFsaResourcePriv> pResourcePriv;
  882. WsbTraceIn(OLESTR("CFsaFilterRecall::Init"), OLESTR("filter ID = %I64x, offset = %I64u, size = %I64u"),
  883. DriversRecallId, offset, size);
  884. try {
  885. m_pClient = pClient;
  886. m_driversRecallId = DriversRecallId;
  887. m_pResource = pResource;
  888. m_placeholder = *pPlaceholder;
  889. m_pFilterPriv = pFilterPriv;
  890. m_path = path;
  891. m_mode = mode;
  892. m_fileId = fileId;
  893. GetSystemTimeAsFileTime(&m_startTime);
  894. m_offset = offset;
  895. m_size = size;
  896. m_isDirty = TRUE;
  897. WsbAssert(m_path != 0, E_UNEXPECTED);
  898. //
  899. // Get the recall started with the engine
  900. // Start a session and ask it to advise us of state changes.
  901. // Tell the resource object that we got an open.
  902. //
  903. hr = S_OK;
  904. } WsbCatchAndDo(hr,
  905. //
  906. // Something failed - send the kernel completion if it has not been sent already.
  907. //
  908. GetSystemTimeAsFileTime(&now);
  909. if (m_pClient != 0) {
  910. m_pClient->SetLastRecallTime(now);
  911. }
  912. if (m_kernelCompletionSent == FALSE) {
  913. m_pFilterPriv->SendComplete((IFsaFilterRecallPriv *) this, hr);
  914. m_kernelCompletionSent = TRUE;
  915. } else {
  916. WsbLogEvent(FSA_MESSAGE_RECALL_FAILED, 0, NULL, (OLECHAR*) WsbAbbreviatePath(path, 120), WsbHrAsString(hr), NULL);
  917. }
  918. if (m_pClient != 0) {
  919. m_pClient->SendRecallInfo((IFsaFilterRecall *) this, FALSE, E_FAIL); // Not fatal if this fails
  920. }
  921. );
  922. WsbTraceOut(OLESTR("CFsaFilterRecall::Init"), OLESTR("%ls"), WsbHrAsString(hr));
  923. return(hr);
  924. }
  925. HRESULT
  926. CFsaFilterRecall::Load(
  927. IN IStream* pStream
  928. )
  929. /*++
  930. Implements:
  931. IPersistStream::Load().
  932. --*/
  933. {
  934. HRESULT hr = S_OK;
  935. WsbTraceIn(OLESTR("CFsaFilterRecall::Load"), OLESTR(""));
  936. try {
  937. WsbAssert(0 != pStream, E_POINTER);
  938. // No persistence.
  939. hr = E_NOTIMPL;
  940. } WsbCatch(hr);
  941. WsbTraceOut(OLESTR("CFsaFilterRecall::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  942. return(hr);
  943. }
  944. HRESULT
  945. CFsaFilterRecall::LogComplete(
  946. IN HRESULT result
  947. )
  948. /*++
  949. Implements:
  950. IFsaFilterRecallPriv:LogComplete(HRESULT result)
  951. --*/
  952. {
  953. HRESULT hr = S_OK;
  954. FILETIME completeTime;
  955. LONGLONG recallTime;
  956. WsbTraceIn(OLESTR("CFsaFilterRecall::LogComplete"), OLESTR("filter Id = %I64x"),
  957. m_driversRecallId);
  958. try {
  959. // Calculate the time it took for this recall to complete
  960. GetSystemTimeAsFileTime(&completeTime);
  961. recallTime = WsbFTtoLL(WsbFtSubFt(completeTime, m_startTime));
  962. // If over 10 minutes then show time in minutes otherwise show in seconds
  963. if (recallTime >= (WSB_FT_TICKS_PER_MINUTE * (LONGLONG) 10)) {
  964. recallTime = recallTime / WSB_FT_TICKS_PER_MINUTE;
  965. WsbTrace(OLESTR("CFsaFilterRecall::LogComplete Recall of %ws completed in %I64u minutes. (%ws)\n"),
  966. WsbAbbreviatePath(m_path, 120), recallTime, WsbHrAsString(result));
  967. WsbLogEvent(FSA_MESSAGE_RECALL_TIMING_MINUTES, 0, NULL,
  968. WsbAbbreviatePath(m_path, 120), WsbLonglongAsString(recallTime), WsbHrAsString(result), NULL);
  969. } else {
  970. recallTime = recallTime / WSB_FT_TICKS_PER_SECOND;
  971. WsbTrace(OLESTR("CFsaFilterRecall::LogComplete Recall of %ws completed in %I64u seconds. (%ws)\n"),
  972. WsbAbbreviatePath(m_path, 120), recallTime, WsbHrAsString(result));
  973. WsbLogEvent(FSA_MESSAGE_RECALL_TIMING_SECONDS, 0, NULL,
  974. WsbAbbreviatePath(m_path, 120), WsbLonglongAsString(recallTime), WsbHrAsString(result), NULL);
  975. }
  976. } WsbCatch(hr);
  977. WsbTraceOut(OLESTR("CFsaFilterRecall::LogComplete"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  978. return(hr);
  979. }
  980. HRESULT
  981. CFsaFilterRecall::Save(
  982. IN IStream* pStream,
  983. IN BOOL clearDirty
  984. )
  985. /*++
  986. Implements:
  987. IPersistStream::Save().
  988. --*/
  989. {
  990. HRESULT hr = S_OK;
  991. CComPtr<IPersistStream> pPersistStream;
  992. WsbTraceIn(OLESTR("CFsaFilterRecall::Save"), OLESTR("clearDirty = <%ls>"), WsbBoolAsString(clearDirty));
  993. try {
  994. WsbAssert(0 != pStream, E_POINTER);
  995. // No persistence.
  996. hr = E_NOTIMPL;
  997. // If we got it saved and we were asked to clear the dirty bit, then
  998. // do so now.
  999. if (clearDirty) {
  1000. m_isDirty = FALSE;
  1001. }
  1002. } WsbCatch(hr);
  1003. WsbTraceOut(OLESTR("CFsaFilterRecall::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1004. return(hr);
  1005. }
  1006. HRESULT
  1007. CFsaFilterRecall::SetDriversRecallId(
  1008. IN ULONGLONG pId
  1009. )
  1010. /*++
  1011. Implements:
  1012. IFsaFilterRecallPriv::SetDriversRecallId().
  1013. --*/
  1014. {
  1015. HRESULT hr = S_OK;
  1016. try {
  1017. m_driversRecallId = pId;
  1018. } WsbCatch(hr);
  1019. return(hr);
  1020. }
  1021. HRESULT
  1022. CFsaFilterRecall::SetThreadId(
  1023. IN DWORD id
  1024. )
  1025. /*++
  1026. Implements:
  1027. IFsaFilterRecallPriv::SetThreadId().
  1028. --*/
  1029. {
  1030. HRESULT hr = S_OK;
  1031. try {
  1032. m_threadId = id;
  1033. } WsbCatch(hr);
  1034. return(hr);
  1035. }
  1036. HRESULT
  1037. CFsaFilterRecall::SetIdentifier(
  1038. IN GUID id
  1039. )
  1040. /*++
  1041. Implements:
  1042. IFsaFilterRecallPriv::SetIdentifier().
  1043. --*/
  1044. {
  1045. HRESULT hr = S_OK;
  1046. m_id = id;
  1047. m_isDirty = TRUE;
  1048. return(hr);
  1049. }
  1050. HRESULT
  1051. CFsaFilterRecall::StartRecall(
  1052. IN ULONGLONG offset,
  1053. IN ULONGLONG size
  1054. )
  1055. /*++
  1056. Implements:
  1057. IFsaFilterRecallPriv::StartRecall().
  1058. --*/
  1059. {
  1060. HRESULT hr = S_OK;
  1061. FILETIME now;
  1062. CComPtr<IFsaResourcePriv> pResourcePriv;
  1063. CWsbStringPtr sessionName;
  1064. ULONG tryLoop;
  1065. BOOL bSentNotify = FALSE;
  1066. WsbTraceIn(OLESTR("CFsaFilterRecall::StartRecall"), OLESTR("filter Id = %I64x"),
  1067. m_driversRecallId);
  1068. try {
  1069. m_offset = offset;
  1070. m_size = size;
  1071. if (m_mode & FILE_OPEN_NO_RECALL) {
  1072. if (m_offset >= m_placeholder.dataStreamSize) {
  1073. //
  1074. // Read beyond the end of file
  1075. //
  1076. hr = STATUS_END_OF_FILE;
  1077. WsbAffirmHr(hr);
  1078. } else if ( (m_offset + m_size) > (m_placeholder.dataStreamStart + m_placeholder.dataStreamSize) ) {
  1079. //
  1080. // They are asking for more than we have - adjust the read size
  1081. //
  1082. m_size -= (m_offset + m_size) - (m_placeholder.dataStreamStart + m_placeholder.dataStreamSize);
  1083. }
  1084. }
  1085. m_isDirty = TRUE;
  1086. WsbAssert(m_path != 0, E_UNEXPECTED);
  1087. //
  1088. // Get the recall started with the engine
  1089. // Start a session and ask it to advise us of state changes.
  1090. // Tell the resource object that we got an open.
  1091. //
  1092. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: BeginSession\n"));
  1093. // Get the string that we are using to describe the session.
  1094. WsbAffirmHr(sessionName.LoadFromRsc(_Module.m_hInst, IDS_FSA_RECALL_NAME));
  1095. WsbAffirmHr(m_pResource->BeginSession(sessionName, HSM_JOB_LOG_ITEMMOSTFAIL | HSM_JOB_LOG_HR, 1, 1, &m_pSession));
  1096. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: Session is setup.\n"));
  1097. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: Notify the client that the recall started.\n"));
  1098. if (m_pClient != 0) {
  1099. hr = m_pClient->SendRecallInfo((IFsaFilterRecall *) this, TRUE, S_OK); // Not fatal if this fails
  1100. if (hr != S_OK) {
  1101. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: SendNotify returned %ls.\n"),
  1102. WsbHrAsString(hr));
  1103. } else {
  1104. bSentNotify = TRUE;
  1105. }
  1106. }
  1107. hr = S_OK;
  1108. //
  1109. // Tell the resource to send the job to the engine.
  1110. //
  1111. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: Calling FilterSawOpen.\n"));
  1112. WsbAffirmHr(m_pResource->QueryInterface(IID_IFsaResourcePriv, (void**) &pResourcePriv));
  1113. if (m_mode & FILE_OPEN_NO_RECALL) {
  1114. WsbAffirmHr(pResourcePriv->FilterSawOpen(m_pSession,
  1115. (IFsaFilterRecall*) this,
  1116. m_path,
  1117. m_fileId,
  1118. offset,
  1119. size,
  1120. &m_placeholder,
  1121. m_mode,
  1122. FSA_RESULT_ACTION_NORECALL,
  1123. m_threadId));
  1124. } else {
  1125. WsbAffirmHr(pResourcePriv->FilterSawOpen(m_pSession,
  1126. (IFsaFilterRecall*) this,
  1127. m_path,
  1128. m_fileId,
  1129. offset,
  1130. size,
  1131. &m_placeholder,
  1132. m_mode,
  1133. FSA_RESULT_ACTION_OPEN,
  1134. m_threadId));
  1135. }
  1136. //
  1137. // The work is now complete - terminate the session.
  1138. //
  1139. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: End Session.\n"));
  1140. WsbAffirmHr(m_pResource->EndSession(m_pSession));
  1141. //
  1142. // Try the notification again if we have not sent it yet.
  1143. // On the first recall from a remote client the identification usually does not
  1144. // happen in time for the first attempt so we try again here.
  1145. // We will try 5 times with a .1 second delay between.
  1146. //
  1147. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: m_pClient = %x sent = %u.\n"),
  1148. m_pClient, bSentNotify);
  1149. if ((m_pClient != 0) && (!bSentNotify)) {
  1150. tryLoop = 5;
  1151. while ((tryLoop != 0) &&( !bSentNotify)) {
  1152. // Reporting here is done after the recall is started.
  1153. // Therefore, it must be synchronized with the recall end notification
  1154. switch (WaitForSingleObject(m_notifyEvent, INFINITE)) {
  1155. case WAIT_OBJECT_0:
  1156. // Check if need to report (if recall did not end yet)
  1157. if (m_kernelCompletionSent == FALSE) {
  1158. // Recall end was not sent yet
  1159. hr = m_pClient->SendRecallInfo((IFsaFilterRecall *) this, TRUE, S_OK); // Not fatal if this fails
  1160. }
  1161. SetEvent(m_notifyEvent);
  1162. break;
  1163. case WAIT_FAILED:
  1164. default:
  1165. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: WaitForSingleObject returned error %lu\n"), GetLastError());
  1166. // Just get out without notifying
  1167. hr = S_OK;
  1168. break;
  1169. }
  1170. if (hr != S_OK) {
  1171. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: Retried notify - %ls.\n"),
  1172. WsbHrAsString(hr));
  1173. if (tryLoop != 1) {
  1174. Sleep(100); // Sleep .1 sec and try again
  1175. }
  1176. } else {
  1177. bSentNotify = TRUE;
  1178. }
  1179. tryLoop--;
  1180. }
  1181. hr = S_OK;
  1182. }
  1183. } WsbCatchAndDo(hr,
  1184. //
  1185. // Something failed - send the kernel completion if it has not been sent already.
  1186. //
  1187. GetSystemTimeAsFileTime(&now);
  1188. if (m_pClient != 0) {
  1189. m_pClient->SetLastRecallTime(now);
  1190. }
  1191. if (m_kernelCompletionSent == FALSE) {
  1192. m_pFilterPriv->SendComplete((IFsaFilterRecallPriv *) this, hr);
  1193. m_kernelCompletionSent = TRUE;
  1194. } else {
  1195. //
  1196. // STATUS_END_OF_FILE is not really an error - it just means they tried to read past the end - some apps do this and expect
  1197. // this status to tell them when to stop reading.
  1198. //
  1199. if (hr != STATUS_END_OF_FILE) {
  1200. WsbLogEvent(FSA_MESSAGE_RECALL_FAILED, 0, NULL, (OLECHAR*) WsbAbbreviatePath(m_path, 120), WsbHrAsString(hr), NULL);
  1201. }
  1202. }
  1203. if (m_pClient != 0) {
  1204. m_pClient->SendRecallInfo((IFsaFilterRecall *) this, FALSE, E_FAIL); // Not fatal if this fails
  1205. }
  1206. );
  1207. WsbTraceOut(OLESTR("CFsaFilterRecall::StartRecall"), OLESTR("%ls"), WsbHrAsString(hr));
  1208. return(hr);
  1209. }
  1210. HRESULT
  1211. CFsaFilterRecall::Test(
  1212. USHORT* passed,
  1213. USHORT* failed
  1214. )
  1215. /*++
  1216. Implements:
  1217. IWsbTestable::Test().
  1218. --*/
  1219. {
  1220. HRESULT hr = S_OK;
  1221. try {
  1222. WsbAssert(0 != passed, E_POINTER);
  1223. WsbAssert(0 != failed, E_POINTER);
  1224. *passed = 0;
  1225. *failed = 0;
  1226. } WsbCatch(hr);
  1227. return(hr);
  1228. }
  1229. HRESULT
  1230. CFsaFilterRecall::WasCancelled(
  1231. void
  1232. )
  1233. /*++
  1234. Implements:
  1235. IFsaFilterRecall::WasCancelled().
  1236. --*/
  1237. {
  1238. HRESULT hr = S_OK;
  1239. if (!m_wasCancelled) {
  1240. hr = S_FALSE;
  1241. }
  1242. return(hr);
  1243. }
  1244. HRESULT
  1245. CFsaFilterRecall::AddClient(
  1246. IFsaFilterClient *pWaitingClient
  1247. )
  1248. /*++
  1249. Implements:
  1250. IFsaFilterRecall::AddClient
  1251. --*/
  1252. {
  1253. HRESULT hr = E_FAIL;
  1254. switch (WaitForSingleObject(m_waitingClientEvent, INFINITE)) {
  1255. case WAIT_OBJECT_0:
  1256. if ((!m_waitingClientsNotified) && (m_pWaitingClients != 0)) {
  1257. hr = m_pWaitingClients->Add(pWaitingClient);
  1258. if (hr == S_OK) {
  1259. // Notify client only if it was added successfully to the collection
  1260. hr = pWaitingClient->SendRecallInfo((IFsaFilterRecall *) this, TRUE, S_OK); // Not fatal if this fails
  1261. if (hr != S_OK) {
  1262. WsbTrace(OLESTR("CFsaFilterRecall::AddClient: SendNotify for start returned %ls.\n"),
  1263. WsbHrAsString(hr));
  1264. }
  1265. }
  1266. }
  1267. SetEvent(m_waitingClientEvent);
  1268. break;
  1269. case WAIT_FAILED:
  1270. default:
  1271. DWORD dwErr = GetLastError();
  1272. WsbTrace(OLESTR("CFsaFilterRecall::AddClient: WaitForSingleObject returned error %lu\n"), dwErr);
  1273. // Don't add waiting client
  1274. hr = HRESULT_FROM_WIN32(dwErr);
  1275. break;
  1276. }
  1277. return(hr);
  1278. }