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.

1858 lines
43 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.p->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. numRefs = 0;
  385. m_waitingClientsNotified = FALSE;
  386. m_pFilterPriv = NULL;
  387. m_threadId = 0;
  388. WsbAffirmHr(CoCreateGuid(&m_id));
  389. // Initialize notify synchronization event and waiting clients event
  390. WsbAffirmHandle((m_notifyEvent = CreateEvent(NULL, FALSE, TRUE, NULL)));
  391. WsbAffirmHandle((m_waitingClientEvent = CreateEvent(NULL, FALSE, TRUE, NULL)));
  392. // Create the waiting client collection.
  393. WsbAffirmHr(CoCreateInstance(CLSID_CWsbOrderedCollection, NULL, CLSCTX_SERVER, IID_IWsbCollection, (void**) &m_pWaitingClients));
  394. } WsbCatch(hr);
  395. iCountFtrcl++;
  396. WsbTraceOut(OLESTR("CFsaFilterRecall::FinalConstruct"), OLESTR("hr = %ls, Count is <%d>"), WsbHrAsString(hr), iCountFtrcl);
  397. return(hr);
  398. }
  399. void
  400. CFsaFilterRecall::FinalRelease(
  401. void
  402. )
  403. /*++
  404. Implements:
  405. CComObjectRoot::FinalRelease().
  406. --*/
  407. {
  408. WsbTraceIn(OLESTR("CFsaFilterRecall::FinalRelease"), OLESTR(""));
  409. CWsbCollectable::FinalRelease();
  410. // Free notify synchronization event and waiting client event
  411. if (m_waitingClientEvent != NULL) {
  412. CloseHandle(m_waitingClientEvent);
  413. m_waitingClientEvent = NULL;
  414. }
  415. if (m_notifyEvent != NULL) {
  416. CloseHandle(m_notifyEvent);
  417. m_notifyEvent = NULL;
  418. }
  419. iCountFtrcl--;
  420. WsbTraceOut(OLESTR("CFsaFilterRecall::FinalRelease"), OLESTR("Count is <%d>"), iCountFtrcl);
  421. }
  422. #ifdef FSA_RECALL_LEAK_TEST
  423. ULONG
  424. CFsaFilterRecall::InternalAddRef(
  425. void
  426. )
  427. /*++
  428. Implements:
  429. CComObjectRoot::AddRef().
  430. --*/
  431. {
  432. numRefs++;
  433. WsbTrace(OLESTR("CFsaFilterRecall::AddRef (%p) - Count = %u\n"), this, numRefs);
  434. return(CComObjectRoot::InternalAddRef());
  435. }
  436. ULONG
  437. CFsaFilterRecall::InternalRelease(
  438. void
  439. )
  440. /*++
  441. Implements:
  442. CComObjectRoot::InternalRelease().
  443. --*/
  444. {
  445. WsbTrace(OLESTR("CFsaFilterRecall::Release (%p) - Count = %u\n"), this, numRefs);
  446. numRefs--;
  447. return(CComObjectRoot::InternalRelease());
  448. }
  449. #endif
  450. HRESULT
  451. CFsaFilterRecall::GetClassID(
  452. OUT CLSID* pClsid
  453. )
  454. /*++
  455. Implements:
  456. IPersist::GetClassID().
  457. --*/
  458. {
  459. HRESULT hr = S_OK;
  460. WsbTraceIn(OLESTR("CFsaFilterRecall::GetClassID"), OLESTR(""));
  461. try {
  462. WsbAssert(0 != pClsid, E_POINTER);
  463. *pClsid = CLSID_CFsaFilterRecallNTFS;
  464. } WsbCatch(hr);
  465. WsbTraceOut(OLESTR("CFsaFilterRecall::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid));
  466. return(hr);
  467. }
  468. HRESULT
  469. CFsaFilterRecall::GetClient(
  470. OUT IFsaFilterClient** ppClient
  471. )
  472. /*++
  473. Implements:
  474. IFsaFilterRecallPriv::GetClient().
  475. --*/
  476. {
  477. HRESULT hr = S_OK;
  478. try {
  479. WsbAssert(0 != ppClient, E_POINTER);
  480. *ppClient = m_pClient;
  481. if (m_pClient != 0) {
  482. m_pClient.p->AddRef();
  483. }
  484. } WsbCatch(hr);
  485. return(hr);
  486. }
  487. HRESULT
  488. CFsaFilterRecall::GetRecallFlags(
  489. OUT ULONG *pFlags
  490. )
  491. /*++
  492. Implements:
  493. IFsaFilterRecall::GetRecallFlags()
  494. --*/
  495. {
  496. HRESULT hr = S_OK;
  497. WsbTraceIn(OLESTR("CFsaFilterRecall::GetRecallFlags"), OLESTR(""));
  498. try {
  499. WsbAssert( 0 != pFlags, E_POINTER);
  500. *pFlags = m_recallFlags;
  501. } WsbCatch(hr);
  502. WsbTraceOut(OLESTR("CFsaFilterRecall::GetRecallFlags"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  503. return(hr);
  504. }
  505. HRESULT
  506. CFsaFilterRecall::GetStream(
  507. OUT IStream **ppStream
  508. )
  509. /*++
  510. Implements:
  511. IFsaFilterRecall::GetStream()
  512. --*/
  513. {
  514. HRESULT hr = S_OK;
  515. WsbTraceIn(OLESTR("CFsaFilterRecall::GetStream"), OLESTR(""));
  516. try {
  517. WsbAssert( 0 != ppStream, E_POINTER);
  518. if ((m_mode & FILE_OPEN_NO_RECALL) && (m_pStream != 0)) {
  519. *ppStream = m_pStream;
  520. m_pStream.p->AddRef();
  521. } else {
  522. *ppStream = 0;
  523. hr = WSB_E_NOTFOUND;
  524. }
  525. } WsbCatch(hr);
  526. WsbTraceOut(OLESTR("CFsaFilterRecall::GetStream"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  527. return(hr);
  528. }
  529. HRESULT
  530. CFsaFilterRecall::GetDriversRecallId(
  531. OUT ULONGLONG* pId
  532. )
  533. /*++
  534. Implements:
  535. IFsaFilterRecallPriv::GetDriversRecallId().
  536. --*/
  537. {
  538. HRESULT hr = S_OK;
  539. try {
  540. WsbAssert(0 != pId, E_POINTER);
  541. *pId = m_driversRecallId;
  542. } WsbCatch(hr);
  543. return(hr);
  544. }
  545. HRESULT
  546. CFsaFilterRecall::GetIdentifier(
  547. OUT GUID* pId
  548. )
  549. /*++
  550. Implements:
  551. IFsaFilterRecall::GetIdentifier().
  552. --*/
  553. {
  554. HRESULT hr = S_OK;
  555. try {
  556. WsbAssert(0 != pId, E_POINTER);
  557. *pId = m_id;
  558. } WsbCatch(hr);
  559. return(hr);
  560. }
  561. HRESULT
  562. CFsaFilterRecall::GetMode(
  563. OUT ULONG* pMode
  564. )
  565. /*++
  566. Implements:
  567. IFsaFilterRecall::GetMode().
  568. --*/
  569. {
  570. HRESULT hr = S_OK;
  571. try {
  572. WsbAssert(0 != pMode, E_POINTER);
  573. *pMode = m_mode;
  574. } WsbCatch(hr);
  575. return(hr);
  576. }
  577. HRESULT
  578. CFsaFilterRecall::GetOffset(
  579. OUT LONGLONG* pOffset
  580. )
  581. /*++
  582. Implements:
  583. IFsaFilterRecall::GetOffset().
  584. --*/
  585. {
  586. HRESULT hr = S_OK;
  587. try {
  588. WsbAssert(0 != pOffset, E_POINTER);
  589. *pOffset = m_offset;
  590. } WsbCatch(hr);
  591. return(hr);
  592. }
  593. HRESULT
  594. CFsaFilterRecall::GetPath(
  595. OUT OLECHAR** pName,
  596. IN ULONG bufferSize
  597. )
  598. /*++
  599. Implements:
  600. IFsaFilterRecall::GetPath().
  601. --*/
  602. {
  603. HRESULT hr = S_OK;
  604. CWsbStringPtr tmpString;
  605. try {
  606. WsbAssert(0 != pName, E_POINTER);
  607. WsbAffirmHr(tmpString.TakeFrom(*pName, bufferSize));
  608. try {
  609. WsbAffirmHr(m_pResource->GetUncPath(&tmpString, 0));
  610. WsbAffirmHr(tmpString.Append(m_path));
  611. } WsbCatch(hr);
  612. WsbAffirmHr(tmpString.GiveTo(pName));
  613. } WsbCatch(hr);
  614. return(hr);
  615. }
  616. HRESULT
  617. CFsaFilterRecall::GetPlaceholder(
  618. OUT FSA_PLACEHOLDER* pPlaceholder
  619. )
  620. /*++
  621. Implements:
  622. IFsaFilterRecallPriv::GetPlaceholder().
  623. --*/
  624. {
  625. HRESULT hr = S_OK;
  626. try {
  627. WsbAssert(0 != pPlaceholder, E_POINTER);
  628. *pPlaceholder = m_placeholder;
  629. } WsbCatch(hr);
  630. return(hr);
  631. }
  632. HRESULT
  633. CFsaFilterRecall::GetResource(
  634. OUT IFsaResource** ppResource
  635. )
  636. /*++
  637. Implements:
  638. IFsaFilterRecall::GetResource().
  639. --*/
  640. {
  641. HRESULT hr = S_OK;
  642. try {
  643. WsbAssert(0 != ppResource, E_POINTER);
  644. *ppResource = m_pResource;
  645. m_pResource.p->AddRef();
  646. } WsbCatch(hr);
  647. return(hr);
  648. }
  649. HRESULT
  650. CFsaFilterRecall::GetSession(
  651. OUT IHsmSession** ppSession
  652. )
  653. /*++
  654. Implements:
  655. IFsaFilterRecall::GetSession().
  656. --*/
  657. {
  658. HRESULT hr = S_OK;
  659. try {
  660. WsbAssert(0 != ppSession, E_POINTER);
  661. *ppSession = m_pSession;
  662. m_pSession.p->AddRef();
  663. } WsbCatch(hr);
  664. return(hr);
  665. }
  666. HRESULT
  667. CFsaFilterRecall::GetSize(
  668. OUT LONGLONG* pSize
  669. )
  670. /*++
  671. Implements:
  672. IFsaFilterRecall::GetSize().
  673. --*/
  674. {
  675. HRESULT hr = S_OK;
  676. try {
  677. WsbAssert(0 != pSize, E_POINTER);
  678. *pSize = m_size;
  679. } WsbCatch(hr);
  680. return(hr);
  681. }
  682. HRESULT
  683. CFsaFilterRecall::GetSizeMax(
  684. OUT ULARGE_INTEGER* pSize
  685. )
  686. /*++
  687. Implements:
  688. IPersistStream::GetSizeMax().
  689. --*/
  690. {
  691. HRESULT hr = S_OK;
  692. WsbTraceIn(OLESTR("CFsaFilterRecall::GetSizeMax"), OLESTR(""));
  693. try {
  694. WsbAssert(0 != pSize, E_POINTER);
  695. pSize->QuadPart = 0;
  696. // WE don't need to persist these.
  697. hr = E_NOTIMPL;
  698. } WsbCatch(hr);
  699. WsbTraceOut(OLESTR("CFsaFilterRecall::GetSizeMax"), OLESTR("hr = <%ls>, Size = <%ls>"), WsbHrAsString(hr), WsbPtrToUliAsString(pSize));
  700. return(hr);
  701. }
  702. HRESULT
  703. CFsaFilterRecall::GetState(
  704. OUT HSM_JOB_STATE* pState
  705. )
  706. /*++
  707. Implements:
  708. IFsaFilterRecall::GetState().
  709. --*/
  710. {
  711. HRESULT hr = S_OK;
  712. try {
  713. WsbAssert(0 != pState, E_POINTER);
  714. *pState = m_state;
  715. } WsbCatch(hr);
  716. return(hr);
  717. }
  718. HRESULT
  719. CFsaFilterRecall::GetUserName(
  720. OUT OLECHAR** pName,
  721. IN ULONG bufferSize
  722. )
  723. /*++
  724. Implements:
  725. IFsaFilterRecall::GetUserName().
  726. --*/
  727. {
  728. HRESULT hr = S_OK;
  729. try {
  730. WsbAssert(0 != pName, E_POINTER);
  731. if (m_pClient != 0) {
  732. WsbAffirmHr(m_pClient->GetUserName(pName, bufferSize));
  733. } else {
  734. hr = WSB_E_NOTFOUND;
  735. }
  736. } WsbCatch(hr);
  737. return(hr);
  738. }
  739. HRESULT
  740. CFsaFilterRecall::HasCompleted(
  741. HRESULT resultHr
  742. )
  743. /*++
  744. Implements:
  745. IFsaFilterRecall::HasCompleted().
  746. --*/
  747. {
  748. HRESULT hr = S_OK, hr2 = S_OK;
  749. CComPtr<IFsaFilterClient> pClient;
  750. CComPtr<IWsbEnum> pEnum;
  751. FILETIME now;
  752. BOOL bSendNotify = TRUE;
  753. DWORD dwStatus;
  754. WsbTraceIn(OLESTR("CFsaFilterRecall::HasCompleted"),
  755. OLESTR("filter Id = %I64x, recall hr = <%ls>"), m_driversRecallId,
  756. WsbHrAsString(resultHr));
  757. try {
  758. // The job is complete, let the kernel mode filter know what happened.
  759. GetSystemTimeAsFileTime(&now);
  760. if (m_pClient != 0) {
  761. m_pClient->SetLastRecallTime(now); // Not fatal if this fails
  762. }
  763. if (m_kernelCompletionSent == FALSE) {
  764. WsbAffirmHr(m_pFilterPriv->SendComplete((IFsaFilterRecallPriv *) this, resultHr));
  765. m_kernelCompletionSent = TRUE;
  766. }
  767. if (m_pClient != 0) {
  768. // Reporting on recall end must be synchronized with the recall start notification,
  769. // because such notification might be sent after the recall starts
  770. switch (WaitForSingleObject(m_notifyEvent, INFINITE)) {
  771. case WAIT_OBJECT_0:
  772. // Send recall notifications to the client that initiated the recall
  773. m_pClient->SendRecallInfo((IFsaFilterRecall *) this, FALSE, resultHr);
  774. SetEvent(m_notifyEvent);
  775. break;
  776. case WAIT_FAILED:
  777. default:
  778. WsbTrace(OLESTR("CFsaFilterRecall::HasCompleted: WaitForSingleObject returned error %lu\n"), GetLastError());
  779. // Notify anyway
  780. m_pClient->SendRecallInfo((IFsaFilterRecall *) this, FALSE, resultHr);
  781. break;
  782. }
  783. bSendNotify = FALSE;
  784. }
  785. dwStatus = WaitForSingleObject(m_waitingClientEvent, INFINITE);
  786. // Notify on recall end no matter what the status is
  787. if (m_pWaitingClients != 0) {
  788. //
  789. // Send recall notifications to all clients waiting for the recall
  790. // to finish
  791. //
  792. hr2 = m_pWaitingClients->Enum(&pEnum);
  793. if (S_OK == hr2) {
  794. hr2 = pEnum->First(IID_IFsaFilterClient, (void**) &pClient);
  795. while (S_OK == hr2) {
  796. pClient->SendRecallInfo((IFsaFilterRecall *) this, FALSE, resultHr);
  797. m_pWaitingClients->RemoveAndRelease(pClient);
  798. pClient = NULL;
  799. pEnum->Reset();
  800. hr2 = pEnum->First(IID_IFsaFilterClient, (void**) &pClient);
  801. }
  802. }
  803. }
  804. m_waitingClientsNotified = TRUE;
  805. switch (dwStatus) {
  806. case WAIT_OBJECT_0:
  807. SetEvent(m_waitingClientEvent);
  808. break;
  809. case WAIT_FAILED:
  810. default:
  811. WsbTrace(OLESTR("CFsaFilterRecall::HasCompleted: WaitForSingleObject returned error %lu\n"), dwStatus);
  812. break;
  813. }
  814. //
  815. // Detach the data mover stream
  816. //
  817. if (m_pDataMover != 0) {
  818. WsbAffirmHr( m_pDataMover->CloseStream() );
  819. }
  820. } WsbCatchAndDo(hr,
  821. if ((m_pClient != 0) && bSendNotify) {
  822. m_pClient->SendRecallInfo((IFsaFilterRecall *) this, FALSE, resultHr);
  823. bSendNotify = FALSE;
  824. }
  825. );
  826. WsbTraceOut(OLESTR("CFsaFilterRecall::HasCompleted"), OLESTR("filter Id = %I64x, sent = <%ls>, hr = <%ls>"),
  827. m_driversRecallId, WsbBoolAsString(m_kernelCompletionSent),
  828. WsbHrAsString(hr));
  829. return(hr);
  830. }
  831. HRESULT
  832. CFsaFilterRecall::CheckRecallLimit(
  833. IN DWORD minRecallInterval,
  834. IN DWORD maxRecalls,
  835. IN BOOLEAN exemptAdmin
  836. )
  837. /*++
  838. Implements:
  839. IFsaFilterRecall::CheckRecallLimit().
  840. --*/
  841. {
  842. HRESULT hr = S_OK;
  843. WsbTraceIn(OLESTR("CFsaFilterRecall::CheckRecallLimit"), OLESTR("filter Id = %I64x"),
  844. m_driversRecallId);
  845. try {
  846. // Check the limit if we are not file open no recall
  847. if (!(m_mode & FILE_OPEN_NO_RECALL) && (m_pClient != NULL)) {
  848. WsbAffirmHr(m_pClient->CheckRecallLimit(minRecallInterval, maxRecalls, exemptAdmin));
  849. }
  850. } WsbCatch(hr);
  851. //
  852. // Commenting the following out: we are reverting back to
  853. // denial of service when we hit the recall limit, not trunc-on-close
  854. //
  855. // If we hit the recall limit then we start to truncate on close.
  856. //
  857. // if (hr == FSA_E_HIT_RECALL_LIMIT) {
  858. // m_recallFlags |= RP_RECALL_ACTION_TRUNCATE;
  859. // }
  860. WsbTraceOut(OLESTR("CFsaFilterRecall::CheckRecallLimit"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  861. return(hr);
  862. }
  863. HRESULT
  864. CFsaFilterRecall::Init(
  865. IN IFsaFilterClient* pClient,
  866. IN ULONGLONG DriversRecallId,
  867. IN IFsaResource* pResource,
  868. IN OLECHAR* path,
  869. IN LONGLONG fileId,
  870. IN LONGLONG offset,
  871. IN LONGLONG size,
  872. IN ULONG mode,
  873. IN FSA_PLACEHOLDER* pPlaceholder,
  874. IN IFsaFilterPriv *pFilterPriv
  875. )
  876. /*++
  877. Implements:
  878. IFsaFilterRecallPriv::Init().
  879. --*/
  880. {
  881. HRESULT hr = S_OK;
  882. FILETIME now;
  883. CComPtr<IFsaResourcePriv> pResourcePriv;
  884. WsbTraceIn(OLESTR("CFsaFilterRecall::Init"), OLESTR("filter ID = %I64x, offset = %I64u, size = %I64u"),
  885. DriversRecallId, offset, size);
  886. try {
  887. m_pClient = pClient;
  888. m_driversRecallId = DriversRecallId;
  889. m_pResource = pResource;
  890. m_placeholder = *pPlaceholder;
  891. m_pFilterPriv = pFilterPriv;
  892. m_path = path;
  893. m_mode = mode;
  894. m_fileId = fileId;
  895. GetSystemTimeAsFileTime(&m_startTime);
  896. m_offset = offset;
  897. m_size = size;
  898. m_isDirty = TRUE;
  899. WsbAssert(m_path != 0, E_UNEXPECTED);
  900. //
  901. // Get the recall started with the engine
  902. // Start a session and ask it to advise us of state changes.
  903. // Tell the resource object that we got an open.
  904. //
  905. hr = S_OK;
  906. } WsbCatchAndDo(hr,
  907. //
  908. // Something failed - send the kernel completion if it has not been sent already.
  909. //
  910. GetSystemTimeAsFileTime(&now);
  911. if (m_pClient != 0) {
  912. m_pClient->SetLastRecallTime(now);
  913. }
  914. if (m_kernelCompletionSent == FALSE) {
  915. m_pFilterPriv->SendComplete((IFsaFilterRecallPriv *) this, hr);
  916. m_kernelCompletionSent = TRUE;
  917. } else {
  918. WsbLogEvent(FSA_MESSAGE_RECALL_FAILED, 0, NULL, (OLECHAR*) WsbAbbreviatePath(path, 120), WsbHrAsString(hr), NULL);
  919. }
  920. if (m_pClient != 0) {
  921. m_pClient->SendRecallInfo((IFsaFilterRecall *) this, FALSE, E_FAIL); // Not fatal if this fails
  922. }
  923. );
  924. WsbTraceOut(OLESTR("CFsaFilterRecall::Init"), OLESTR("%ls"), WsbHrAsString(hr));
  925. return(hr);
  926. }
  927. HRESULT
  928. CFsaFilterRecall::Load(
  929. IN IStream* pStream
  930. )
  931. /*++
  932. Implements:
  933. IPersistStream::Load().
  934. --*/
  935. {
  936. HRESULT hr = S_OK;
  937. WsbTraceIn(OLESTR("CFsaFilterRecall::Load"), OLESTR(""));
  938. try {
  939. WsbAssert(0 != pStream, E_POINTER);
  940. // No persistence.
  941. hr = E_NOTIMPL;
  942. } WsbCatch(hr);
  943. WsbTraceOut(OLESTR("CFsaFilterRecall::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  944. return(hr);
  945. }
  946. HRESULT
  947. CFsaFilterRecall::LogComplete(
  948. IN HRESULT result
  949. )
  950. /*++
  951. Implements:
  952. IFsaFilterRecallPriv:LogComplete(HRESULT result)
  953. --*/
  954. {
  955. HRESULT hr = S_OK;
  956. FILETIME completeTime;
  957. LONGLONG recallTime;
  958. WsbTraceIn(OLESTR("CFsaFilterRecall::LogComplete"), OLESTR("filter Id = %I64x"),
  959. m_driversRecallId);
  960. try {
  961. // Calculate the time it took for this recall to complete
  962. GetSystemTimeAsFileTime(&completeTime);
  963. recallTime = WsbFTtoLL(WsbFtSubFt(completeTime, m_startTime));
  964. // If over 10 minutes then show time in minutes otherwise show in seconds
  965. if (recallTime >= (WSB_FT_TICKS_PER_MINUTE * (LONGLONG) 10)) {
  966. recallTime = recallTime / WSB_FT_TICKS_PER_MINUTE;
  967. WsbTrace(OLESTR("CFsaFilterRecall::LogComplete Recall of %ws completed in %I64u minutes. (%ws)\n"),
  968. WsbAbbreviatePath(m_path, 120), recallTime, WsbHrAsString(result));
  969. WsbLogEvent(FSA_MESSAGE_RECALL_TIMING_MINUTES, 0, NULL,
  970. WsbAbbreviatePath(m_path, 120), WsbLonglongAsString(recallTime), WsbHrAsString(result), NULL);
  971. } else {
  972. recallTime = recallTime / WSB_FT_TICKS_PER_SECOND;
  973. WsbTrace(OLESTR("CFsaFilterRecall::LogComplete Recall of %ws completed in %I64u seconds. (%ws)\n"),
  974. WsbAbbreviatePath(m_path, 120), recallTime, WsbHrAsString(result));
  975. WsbLogEvent(FSA_MESSAGE_RECALL_TIMING_SECONDS, 0, NULL,
  976. WsbAbbreviatePath(m_path, 120), WsbLonglongAsString(recallTime), WsbHrAsString(result), NULL);
  977. }
  978. } WsbCatch(hr);
  979. WsbTraceOut(OLESTR("CFsaFilterRecall::LogComplete"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  980. return(hr);
  981. }
  982. HRESULT
  983. CFsaFilterRecall::Save(
  984. IN IStream* pStream,
  985. IN BOOL clearDirty
  986. )
  987. /*++
  988. Implements:
  989. IPersistStream::Save().
  990. --*/
  991. {
  992. HRESULT hr = S_OK;
  993. CComPtr<IPersistStream> pPersistStream;
  994. WsbTraceIn(OLESTR("CFsaFilterRecall::Save"), OLESTR("clearDirty = <%ls>"), WsbBoolAsString(clearDirty));
  995. try {
  996. WsbAssert(0 != pStream, E_POINTER);
  997. // No persistence.
  998. hr = E_NOTIMPL;
  999. // If we got it saved and we were asked to clear the dirty bit, then
  1000. // do so now.
  1001. if (clearDirty) {
  1002. m_isDirty = FALSE;
  1003. }
  1004. } WsbCatch(hr);
  1005. WsbTraceOut(OLESTR("CFsaFilterRecall::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  1006. return(hr);
  1007. }
  1008. HRESULT
  1009. CFsaFilterRecall::SetDriversRecallId(
  1010. IN ULONGLONG pId
  1011. )
  1012. /*++
  1013. Implements:
  1014. IFsaFilterRecallPriv::SetDriversRecallId().
  1015. --*/
  1016. {
  1017. HRESULT hr = S_OK;
  1018. try {
  1019. m_driversRecallId = pId;
  1020. } WsbCatch(hr);
  1021. return(hr);
  1022. }
  1023. HRESULT
  1024. CFsaFilterRecall::SetThreadId(
  1025. IN DWORD id
  1026. )
  1027. /*++
  1028. Implements:
  1029. IFsaFilterRecallPriv::SetThreadId().
  1030. --*/
  1031. {
  1032. HRESULT hr = S_OK;
  1033. try {
  1034. m_threadId = id;
  1035. } WsbCatch(hr);
  1036. return(hr);
  1037. }
  1038. HRESULT
  1039. CFsaFilterRecall::SetIdentifier(
  1040. IN GUID id
  1041. )
  1042. /*++
  1043. Implements:
  1044. IFsaFilterRecallPriv::SetIdentifier().
  1045. --*/
  1046. {
  1047. HRESULT hr = S_OK;
  1048. m_id = id;
  1049. m_isDirty = TRUE;
  1050. return(hr);
  1051. }
  1052. HRESULT
  1053. CFsaFilterRecall::StartRecall(
  1054. IN ULONGLONG offset,
  1055. IN ULONGLONG size
  1056. )
  1057. /*++
  1058. Implements:
  1059. IFsaFilterRecallPriv::StartRecall().
  1060. --*/
  1061. {
  1062. HRESULT hr = S_OK;
  1063. FILETIME now;
  1064. CComPtr<IFsaResourcePriv> pResourcePriv;
  1065. CWsbStringPtr sessionName;
  1066. ULONG tryLoop;
  1067. BOOL bSentNotify = FALSE;
  1068. WsbTraceIn(OLESTR("CFsaFilterRecall::StartRecall"), OLESTR("filter Id = %I64x"),
  1069. m_driversRecallId);
  1070. try {
  1071. m_offset = offset;
  1072. m_size = size;
  1073. if (m_mode & FILE_OPEN_NO_RECALL) {
  1074. if (m_offset >= m_placeholder.dataStreamSize) {
  1075. //
  1076. // Read beyond the end of file
  1077. //
  1078. hr = STATUS_END_OF_FILE;
  1079. WsbAffirmHr(hr);
  1080. } else if ( (m_offset + m_size) > (m_placeholder.dataStreamStart + m_placeholder.dataStreamSize) ) {
  1081. //
  1082. // They are asking for more than we have - adjust the read size
  1083. //
  1084. m_size -= (m_offset + m_size) - (m_placeholder.dataStreamStart + m_placeholder.dataStreamSize);
  1085. }
  1086. }
  1087. m_isDirty = TRUE;
  1088. WsbAssert(m_path != 0, E_UNEXPECTED);
  1089. //
  1090. // Get the recall started with the engine
  1091. // Start a session and ask it to advise us of state changes.
  1092. // Tell the resource object that we got an open.
  1093. //
  1094. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: BeginSession\n"));
  1095. // Get the string that we are using to describe the session.
  1096. WsbAffirmHr(sessionName.LoadFromRsc(_Module.m_hInst, IDS_FSA_RECALL_NAME));
  1097. WsbAffirmHr(m_pResource->BeginSession(sessionName, HSM_JOB_LOG_ITEMMOSTFAIL | HSM_JOB_LOG_HR, 1, 1, &m_pSession));
  1098. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: Session is setup.\n"));
  1099. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: Notify the client that the recall started.\n"));
  1100. if (m_pClient != 0) {
  1101. hr = m_pClient->SendRecallInfo((IFsaFilterRecall *) this, TRUE, S_OK); // Not fatal if this fails
  1102. if (! SUCCEEDED(hr)) {
  1103. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: SendNotify failed with %ls.\n"),
  1104. WsbHrAsString(hr));
  1105. } else {
  1106. if (hr != S_OK) {
  1107. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: SendNotify returned %ls.\n"),
  1108. WsbHrAsString(hr));
  1109. }
  1110. bSentNotify = TRUE;
  1111. }
  1112. }
  1113. hr = S_OK;
  1114. //
  1115. // Tell the resource to send the job to the engine.
  1116. //
  1117. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: Calling FilterSawOpen.\n"));
  1118. WsbAffirmHr(m_pResource->QueryInterface(IID_IFsaResourcePriv, (void**) &pResourcePriv));
  1119. if (m_mode & FILE_OPEN_NO_RECALL) {
  1120. WsbAffirmHr(pResourcePriv->FilterSawOpen(m_pSession,
  1121. (IFsaFilterRecall*) this,
  1122. m_path,
  1123. m_fileId,
  1124. offset,
  1125. size,
  1126. &m_placeholder,
  1127. m_mode,
  1128. FSA_RESULT_ACTION_NORECALL,
  1129. m_threadId));
  1130. } else {
  1131. WsbAffirmHr(pResourcePriv->FilterSawOpen(m_pSession,
  1132. (IFsaFilterRecall*) this,
  1133. m_path,
  1134. m_fileId,
  1135. offset,
  1136. size,
  1137. &m_placeholder,
  1138. m_mode,
  1139. FSA_RESULT_ACTION_OPEN,
  1140. m_threadId));
  1141. }
  1142. //
  1143. // The work is now complete - terminate the session.
  1144. //
  1145. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: End Session.\n"));
  1146. WsbAffirmHr(m_pResource->EndSession(m_pSession));
  1147. //
  1148. // Try the notification again if we have not sent it yet.
  1149. // On the first recall from a remote client the identification usually does not
  1150. // happen in time for the first attempt so we try again here.
  1151. // We will try 5 times with a .1 second delay between.
  1152. //
  1153. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: m_pClient = %x sent = %u.\n"),
  1154. m_pClient, bSentNotify);
  1155. if ((m_pClient != 0) && (!bSentNotify)) {
  1156. tryLoop = 5;
  1157. while ((tryLoop != 0) &&( !bSentNotify)) {
  1158. // Reporting here is done after the recall is started.
  1159. // Therefore, it must be synchronized with the recall end notification
  1160. switch (WaitForSingleObject(m_notifyEvent, INFINITE)) {
  1161. case WAIT_OBJECT_0:
  1162. // Check if need to report (if recall did not end yet)
  1163. if (m_kernelCompletionSent == FALSE) {
  1164. // Recall end was not sent yet
  1165. hr = m_pClient->SendRecallInfo((IFsaFilterRecall *) this, TRUE, S_OK); // Not fatal if this fails
  1166. }
  1167. SetEvent(m_notifyEvent);
  1168. break;
  1169. case WAIT_FAILED:
  1170. default:
  1171. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: WaitForSingleObject returned error %lu\n"), GetLastError());
  1172. // Just get out without notifying
  1173. hr = S_OK;
  1174. break;
  1175. }
  1176. if (! SUCCEEDED(hr)) {
  1177. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: Retried notify failed with %ls.\n"),
  1178. WsbHrAsString(hr));
  1179. if (tryLoop != 1) {
  1180. Sleep(100); // Sleep .1 sec and try again
  1181. }
  1182. } else {
  1183. if (hr != S_OK)
  1184. WsbTrace(OLESTR("CFsaFilterRecall::StartRecall: Retried notify returned %ls.\n"),
  1185. WsbHrAsString(hr));
  1186. bSentNotify = TRUE;
  1187. }
  1188. tryLoop--;
  1189. }
  1190. hr = S_OK;
  1191. }
  1192. } WsbCatchAndDo(hr,
  1193. //
  1194. // Something failed - send the kernel completion if it has not been sent already.
  1195. //
  1196. GetSystemTimeAsFileTime(&now);
  1197. if (m_pClient != 0) {
  1198. m_pClient->SetLastRecallTime(now);
  1199. }
  1200. if (m_kernelCompletionSent == FALSE) {
  1201. m_pFilterPriv->SendComplete((IFsaFilterRecallPriv *) this, hr);
  1202. m_kernelCompletionSent = TRUE;
  1203. } else {
  1204. //
  1205. // 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
  1206. // this status to tell them when to stop reading.
  1207. //
  1208. if (hr != STATUS_END_OF_FILE) {
  1209. WsbLogEvent(FSA_MESSAGE_RECALL_FAILED, 0, NULL, (OLECHAR*) WsbAbbreviatePath(m_path, 120), WsbHrAsString(hr), NULL);
  1210. }
  1211. }
  1212. if (m_pClient != 0) {
  1213. m_pClient->SendRecallInfo((IFsaFilterRecall *) this, FALSE, E_FAIL); // Not fatal if this fails
  1214. }
  1215. );
  1216. WsbTraceOut(OLESTR("CFsaFilterRecall::StartRecall"), OLESTR("%ls"), WsbHrAsString(hr));
  1217. return(hr);
  1218. }
  1219. HRESULT
  1220. CFsaFilterRecall::Test(
  1221. USHORT* passed,
  1222. USHORT* failed
  1223. )
  1224. /*++
  1225. Implements:
  1226. IWsbTestable::Test().
  1227. --*/
  1228. {
  1229. HRESULT hr = S_OK;
  1230. try {
  1231. WsbAssert(0 != passed, E_POINTER);
  1232. WsbAssert(0 != failed, E_POINTER);
  1233. *passed = 0;
  1234. *failed = 0;
  1235. } WsbCatch(hr);
  1236. return(hr);
  1237. }
  1238. HRESULT
  1239. CFsaFilterRecall::WasCancelled(
  1240. void
  1241. )
  1242. /*++
  1243. Implements:
  1244. IFsaFilterRecall::WasCancelled().
  1245. --*/
  1246. {
  1247. HRESULT hr = S_OK;
  1248. if (!m_wasCancelled) {
  1249. hr = S_FALSE;
  1250. }
  1251. return(hr);
  1252. }
  1253. HRESULT
  1254. CFsaFilterRecall::AddClient(
  1255. IFsaFilterClient *pWaitingClient
  1256. )
  1257. /*++
  1258. Implements:
  1259. IFsaFilterRecall::AddClient
  1260. --*/
  1261. {
  1262. HRESULT hr = E_FAIL;
  1263. switch (WaitForSingleObject(m_waitingClientEvent, INFINITE)) {
  1264. case WAIT_OBJECT_0:
  1265. if ((!m_waitingClientsNotified) && (m_pWaitingClients != 0)) {
  1266. hr = m_pWaitingClients->Add(pWaitingClient);
  1267. if (hr == S_OK) {
  1268. // Notify client only if it was added successfully to the collection
  1269. hr = pWaitingClient->SendRecallInfo((IFsaFilterRecall *) this, TRUE, S_OK); // Not fatal if this fails
  1270. if (hr != S_OK) {
  1271. // Note that S_FALSE is an "expected failure" but we still want to trace this
  1272. WsbTrace(OLESTR("CFsaFilterRecall::AddClient: SendNotify for start returned %ls.\n"),
  1273. WsbHrAsString(hr));
  1274. }
  1275. }
  1276. }
  1277. SetEvent(m_waitingClientEvent);
  1278. break;
  1279. case WAIT_FAILED:
  1280. default:
  1281. DWORD dwErr = GetLastError();
  1282. WsbTrace(OLESTR("CFsaFilterRecall::AddClient: WaitForSingleObject returned error %lu\n"), dwErr);
  1283. // Don't add waiting client
  1284. hr = HRESULT_FROM_WIN32(dwErr);
  1285. break;
  1286. }
  1287. return(hr);
  1288. }