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.

827 lines
20 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2000-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: Cancel.cpp
  6. * Content: DirectNet Cancel Operations
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 04/07/00 mjn Created
  12. * 04/08/00 mjn Added DNCancelEnum(), DNCancelSend()
  13. * 04/11/00 mjn DNCancelEnum() uses CAsyncOp
  14. * 04/17/00 mjn DNCancelSend() uses CAsyncOp
  15. * 04/25/00 mjn Added DNCancelConnect()
  16. * 07/05/00 mjn Added code to handle invalid async ops
  17. * 07/08/00 mjn Fixed CAsyncOp to contain m_bilinkParent
  18. * 08/05/00 mjn Added DNCancelChildren(),DNCancelActiveCommands(),DNCanCancelCommand()
  19. * mjn Removed DNCancelEnum(),DNCancelListen(),DNCancelSend(),DNCancelConnect()
  20. * 08/07/00 mjn Added DNCancelRequestCommands()
  21. * 08/22/00 mjn Remove cancelled receive buffers from the active list in DNDoCancelCommand()
  22. * 09/02/00 mjn Cancel active commands in reverse order (to prevent out of order messages at protocol level)
  23. * 01/10/01 mjn Allow DNCancelActiveCommands() to set result code of cancelled commands
  24. * 02/08/01 mjn Use SyncEvents on AsyncOps to prevent protocol completions from returning before cancels return
  25. * mjn Added DNWaitForCancel()
  26. * 04/13/01 mjn DNCancelRequestCommands() uses request bilink
  27. * 05/23/01 mjn Only cancel commands that are allowed to be cancelled in DNDoCancelCommand()
  28. * 06/03/01 mjn Ignore uncancelable children in DNCancelChildren()
  29. *@@END_MSINTERNAL
  30. *
  31. ***************************************************************************/
  32. #include "dncorei.h"
  33. // DNCanCancelCommand
  34. //
  35. // This will determine if an operation is cancelable based on the selection flags
  36. #undef DPF_MODNAME
  37. #define DPF_MODNAME "DNCanCancelCommand"
  38. BOOL DNCanCancelCommand(CAsyncOp *const pAsyncOp,
  39. const DWORD dwFlags,
  40. CConnection *const pConnection)
  41. {
  42. BOOL fReturnVal;
  43. DPFX(DPFPREP, 8,"Parameters: pAsyncOp [0x%p], dwFlags [0x%lx], pConnection [0x%p]",pAsyncOp,dwFlags,pConnection);
  44. DNASSERT(pAsyncOp != NULL);
  45. fReturnVal = FALSE;
  46. switch(pAsyncOp->GetOpType())
  47. {
  48. case ASYNC_OP_CONNECT:
  49. {
  50. if (dwFlags & DN_CANCEL_FLAG_CONNECT)
  51. {
  52. fReturnVal = TRUE;
  53. }
  54. break;
  55. }
  56. case ASYNC_OP_DISCONNECT:
  57. {
  58. if (dwFlags & DN_CANCEL_FLAG_DISCONNECT)
  59. {
  60. fReturnVal = TRUE;
  61. }
  62. break;
  63. }
  64. case ASYNC_OP_ENUM_QUERY:
  65. {
  66. if (dwFlags & DN_CANCEL_FLAG_ENUM_QUERY)
  67. {
  68. fReturnVal = TRUE;
  69. }
  70. break;
  71. }
  72. case ASYNC_OP_ENUM_RESPONSE:
  73. {
  74. if (dwFlags & DN_CANCEL_FLAG_ENUM_RESPONSE)
  75. {
  76. fReturnVal = TRUE;
  77. }
  78. break;
  79. }
  80. case ASYNC_OP_LISTEN:
  81. {
  82. if (dwFlags & DN_CANCEL_FLAG_LISTEN)
  83. {
  84. fReturnVal = TRUE;
  85. }
  86. break;
  87. }
  88. case ASYNC_OP_SEND:
  89. {
  90. if (pAsyncOp->IsInternal())
  91. {
  92. if (dwFlags & DN_CANCEL_FLAG_INTERNAL_SEND)
  93. {
  94. fReturnVal = TRUE;
  95. }
  96. }
  97. else
  98. {
  99. if (dwFlags & DN_CANCEL_FLAG_USER_SEND)
  100. {
  101. if ((pConnection == NULL) || (pAsyncOp->GetConnection() == pConnection))
  102. {
  103. if (pAsyncOp->GetOpFlags() & DN_SENDFLAGS_HIGH_PRIORITY)
  104. {
  105. if (! (dwFlags & DN_CANCEL_FLAG_USER_SEND_NOTHIGHPRI))
  106. {
  107. fReturnVal = TRUE;
  108. }
  109. }
  110. else if (pAsyncOp->GetOpFlags() & DN_SENDFLAGS_HIGH_PRIORITY)
  111. {
  112. if (! (dwFlags & DN_CANCEL_FLAG_USER_SEND_NOTLOWPRI))
  113. {
  114. fReturnVal = TRUE;
  115. }
  116. }
  117. else
  118. {
  119. if (! (dwFlags & DN_CANCEL_FLAG_USER_SEND_NOTNORMALPRI))
  120. {
  121. fReturnVal = TRUE;
  122. }
  123. }
  124. }
  125. }
  126. }
  127. break;
  128. }
  129. case ASYNC_OP_RECEIVE_BUFFER:
  130. {
  131. if (dwFlags & DN_CANCEL_FLAG_RECEIVE_BUFFER)
  132. {
  133. fReturnVal = TRUE;
  134. }
  135. break;
  136. }
  137. case ASYNC_OP_REQUEST:
  138. {
  139. break;
  140. }
  141. #ifndef DPNBUILD_NOMULTICAST
  142. case ASYNC_OP_LISTEN_MULTICAST:
  143. case ASYNC_OP_CONNECT_MULTICAST_SEND:
  144. {
  145. if (dwFlags & DN_CANCEL_FLAG_JOIN)
  146. {
  147. fReturnVal = TRUE;
  148. }
  149. break;
  150. }
  151. case ASYNC_OP_CONNECT_MULTICAST_RECEIVE:
  152. {
  153. break;
  154. }
  155. #endif // ! DPNBUILD_NOMULTICAST
  156. default:
  157. {
  158. break;
  159. }
  160. }
  161. DPFX(DPFPREP, 8,"Returning: [%ld]",fReturnVal);
  162. return(fReturnVal);
  163. }
  164. // DNDoCancelCommand
  165. //
  166. // This will attempt to cancel a given operation based on its OpType
  167. #undef DPF_MODNAME
  168. #define DPF_MODNAME "DNDoCancelCommand"
  169. HRESULT DNDoCancelCommand(DIRECTNETOBJECT *const pdnObject,
  170. CAsyncOp *const pAsyncOp)
  171. {
  172. HRESULT hResultCode;
  173. DPFX(DPFPREP, 8,"Parameters: pAsyncOp [0x%p]",pAsyncOp);
  174. hResultCode = DPNERR_CANNOTCANCEL;
  175. switch(pAsyncOp->GetOpType())
  176. {
  177. case ASYNC_OP_CONNECT:
  178. case ASYNC_OP_ENUM_QUERY:
  179. case ASYNC_OP_ENUM_RESPONSE:
  180. case ASYNC_OP_LISTEN:
  181. case ASYNC_OP_SEND:
  182. #ifndef DPNBUILD_NOMULTICAST
  183. case ASYNC_OP_LISTEN_MULTICAST:
  184. case ASYNC_OP_CONNECT_MULTICAST_SEND:
  185. case ASYNC_OP_CONNECT_MULTICAST_RECEIVE:
  186. #endif // ! DPNBUILD_NOMULTICAST
  187. {
  188. HANDLE hProtocol;
  189. BOOL fCanCancel;
  190. DNASSERT(pdnObject->pdnProtocolData != NULL );
  191. //
  192. // If this operation has been marked as not cancellable,
  193. // we will return an error
  194. //
  195. pAsyncOp->Lock();
  196. hProtocol = pAsyncOp->GetProtocolHandle();
  197. fCanCancel = !pAsyncOp->IsCannotCancel();
  198. pAsyncOp->Unlock();
  199. if (fCanCancel && (hProtocol != NULL))
  200. {
  201. DPFX(DPFPREP, 9,"Attempting to cancel AsyncOp [0x%p]",pAsyncOp);
  202. hResultCode = DNPCancelCommand(pdnObject->pdnProtocolData,hProtocol);
  203. DPFX(DPFPREP, 9,"Result of cancelling AsyncOp [0x%p] was [0x%lx]",pAsyncOp,hResultCode);
  204. }
  205. else
  206. {
  207. DPFX(DPFPREP,9,"Not allowed to cancel this operation");
  208. hResultCode = DPNERR_CANNOTCANCEL;
  209. }
  210. break;
  211. }
  212. case ASYNC_OP_RECEIVE_BUFFER:
  213. {
  214. hResultCode = pdnObject->HandleTable.Destroy( pAsyncOp->GetHandle(), NULL );
  215. if (hResultCode == DPN_OK)
  216. {
  217. //
  218. // Remove from active list
  219. //
  220. DNEnterCriticalSection(&pdnObject->csActiveList);
  221. pAsyncOp->m_bilinkActiveList.RemoveFromList();
  222. DNLeaveCriticalSection(&pdnObject->csActiveList);
  223. // Remove HandleTable reference
  224. pAsyncOp->Release();
  225. }
  226. else
  227. {
  228. hResultCode = DPNERR_CANNOTCANCEL;
  229. }
  230. break;
  231. }
  232. // case ASYNC_OP_DISCONNECT:
  233. case ASYNC_OP_REQUEST:
  234. default:
  235. {
  236. DNASSERT(FALSE);
  237. break;
  238. }
  239. }
  240. DPFX(DPFPREP, 8,"Returning: [0x%lx]",hResultCode);
  241. return(hResultCode);
  242. }
  243. // DNCancelChildren
  244. //
  245. // This will mark an operation as CANCELLED to prevent new children from attaching,
  246. // build a cancel list of any children, and recursively call itself to cancel those children.
  247. // At the bottom level, if there is a Protocol handle, we will actually call DNPCancelCommand()
  248. #undef DPF_MODNAME
  249. #define DPF_MODNAME "DNCancelChildren"
  250. HRESULT DNCancelChildren(DIRECTNETOBJECT *const pdnObject,
  251. CAsyncOp *const pParent)
  252. {
  253. HRESULT hResultCode;
  254. CBilink *pBilink;
  255. CAsyncOp *pAsyncOp;
  256. CAsyncOp *CancelList[16];
  257. CSyncEvent *pSyncEvent;
  258. DWORD dwRemainingCount;
  259. DWORD dwCurrentCount;
  260. #ifdef DBG
  261. DWORD dwInitialCount;
  262. #endif // DBG
  263. DPFX(DPFPREP, 6,"Parameters: pParent [0x%p]",pParent);
  264. DNASSERT(pdnObject != NULL);
  265. DNASSERT(pParent != NULL);
  266. pAsyncOp = NULL;
  267. memset(CancelList, 0, sizeof(CancelList));
  268. pSyncEvent = NULL;
  269. //
  270. // Mark the parent as cancelled so that no new children can attach
  271. //
  272. pParent->Lock();
  273. if (pParent->IsCancelled() || pParent->IsComplete() || pParent->IsCannotCancel())
  274. {
  275. pParent->Unlock();
  276. DPFX(DPFPREP, 7,"Ignoring pParent [0x%p]",pParent);
  277. hResultCode = DPN_OK;
  278. goto Exit;
  279. }
  280. pParent->SetCancelled();
  281. //
  282. // Determine size of cancel list
  283. //
  284. dwRemainingCount = 0;
  285. pBilink = pParent->m_bilinkParent.GetNext();
  286. while (pBilink != &pParent->m_bilinkParent)
  287. {
  288. pAsyncOp = CONTAINING_OBJECT(pBilink,CAsyncOp,m_bilinkChildren);
  289. pAsyncOp->Lock();
  290. if (!pAsyncOp->IsCancelled() && !pAsyncOp->IsComplete())
  291. {
  292. dwRemainingCount++;
  293. }
  294. pAsyncOp->Unlock();
  295. pBilink = pBilink->GetNext();
  296. }
  297. DPFX(DPFPREP, 7,"Number of cancellable children [%ld]",dwRemainingCount);
  298. //
  299. // Attach a sync event if this is a protocol operation
  300. // This event may be cleared by the completion
  301. //
  302. if (pParent->GetProtocolHandle() != NULL)
  303. {
  304. if ((hResultCode = SyncEventNew(pdnObject,&pSyncEvent)) != DPN_OK)
  305. {
  306. DPFERR("Could not get new sync event");
  307. DisplayDNError(0,hResultCode);
  308. }
  309. else
  310. {
  311. pSyncEvent->Reset();
  312. pParent->SetCancelEvent( pSyncEvent );
  313. pParent->SetCancelThreadID( GetCurrentThreadId() );
  314. DPFX(DPFPREP,7,"Setting sync event [0x%p]",pSyncEvent);
  315. }
  316. }
  317. pParent->Unlock();
  318. #ifdef DBG
  319. dwInitialCount = dwRemainingCount;
  320. #endif // DBG
  321. //
  322. // Preset the return
  323. //
  324. hResultCode = DPN_OK;
  325. //
  326. // Fill cancel list
  327. //
  328. while (dwRemainingCount > 0)
  329. {
  330. dwRemainingCount = 0;
  331. dwCurrentCount = 0;
  332. pParent->Lock();
  333. pBilink = pParent->m_bilinkParent.GetNext();
  334. while (pBilink != &pParent->m_bilinkParent)
  335. {
  336. pAsyncOp = CONTAINING_OBJECT(pBilink,CAsyncOp,m_bilinkChildren);
  337. pAsyncOp->Lock();
  338. if (!pAsyncOp->IsCancelled() && !pAsyncOp->IsComplete())
  339. {
  340. if (dwCurrentCount < (sizeof(CancelList) / sizeof(CAsyncOp*)))
  341. {
  342. pAsyncOp->AddRef();
  343. CancelList[dwCurrentCount] = pAsyncOp;
  344. dwCurrentCount++;
  345. #ifdef DBG
  346. DNASSERT(dwCurrentCount <= dwInitialCount);
  347. #endif // DBG
  348. }
  349. else
  350. {
  351. dwRemainingCount++;
  352. //
  353. // The list should never grow. In fact it should
  354. // always be smaller because the current cancel list
  355. // should have taken some.
  356. //
  357. #ifdef DBG
  358. DNASSERT(dwRemainingCount < dwInitialCount);
  359. #endif // DBG
  360. }
  361. }
  362. pAsyncOp->Unlock();
  363. pBilink = pBilink->GetNext();
  364. }
  365. //
  366. // Drop the lock while we attempt to cancel.
  367. //
  368. pParent->Unlock();
  369. DPFX(DPFPREP, 7,"Actual number of cancellable children [%ld], remaining [%ld]",dwCurrentCount,dwRemainingCount);
  370. //
  371. // Call ourselves with each of the children (if there are any)
  372. // and clean up (release AsyncOp children)
  373. //
  374. if (dwCurrentCount > 0)
  375. {
  376. DWORD dw;
  377. HRESULT hr;
  378. for (dw = 0 ; dw < dwCurrentCount ; dw++ )
  379. {
  380. hr = DNCancelChildren(pdnObject,CancelList[dw]);
  381. if ((hr != DPN_OK) && (hResultCode == DPN_OK))
  382. {
  383. hResultCode = hr;
  384. }
  385. CancelList[dw]->Release();
  386. CancelList[dw] = NULL;
  387. }
  388. }
  389. else
  390. {
  391. DNASSERT(dwRemainingCount == 0);
  392. }
  393. }
  394. //
  395. // Cancel this operation (if we can)
  396. // This will only work for CONNECTs,DISCONNECTs,ENUM_QUERYs,ENUM_RESPONSEs,LISTENs,SENDs with a protocol handle
  397. //
  398. if (pParent->GetProtocolHandle() != NULL)
  399. {
  400. HRESULT hr;
  401. hr = DNDoCancelCommand(pdnObject,pParent);
  402. if ((hr != DPN_OK) && (hResultCode == DPN_OK))
  403. {
  404. hResultCode = hr;
  405. }
  406. }
  407. //
  408. // Set the cancel event and clear it from the async op if it's still there
  409. //
  410. if (pSyncEvent)
  411. {
  412. pSyncEvent->Set();
  413. pParent->Lock();
  414. pSyncEvent = pParent->GetCancelEvent();
  415. pParent->SetCancelEvent( NULL );
  416. pParent->Unlock();
  417. if (pSyncEvent)
  418. {
  419. DPFX(DPFPREP,7,"Returning sync event [0x%p]",pSyncEvent);
  420. pSyncEvent->ReturnSelfToPool();
  421. pSyncEvent = NULL;
  422. }
  423. }
  424. Exit:
  425. DNASSERT( pSyncEvent == NULL );
  426. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  427. return(hResultCode);
  428. }
  429. // DNCancelActiveCommands
  430. //
  431. // This will attempt to cancel ALL operations in the active list.
  432. #undef DPF_MODNAME
  433. #define DPF_MODNAME "DNCancelActiveCommands"
  434. HRESULT DNCancelActiveCommands(DIRECTNETOBJECT *const pdnObject,
  435. const DWORD dwFlags,
  436. CConnection *const pConnection,
  437. const BOOL fSetResult,
  438. const HRESULT hrCancel)
  439. {
  440. HRESULT hResultCode;
  441. CAsyncOp *pAsyncOp;
  442. CAsyncOp *CancelList[64];
  443. CBilink *pBilink;
  444. DWORD dwRemainingCount;
  445. DWORD dwCurrentCount;
  446. DPFX(DPFPREP, 6,"Parameters: dwFlags [0x%lx], pConnection [0x%p], fSetResult [%ld], hrCancel [0x%lx]",dwFlags,pConnection,fSetResult,hrCancel);
  447. DNASSERT(pdnObject != NULL);
  448. DNASSERT((pConnection == NULL) || (dwFlags & DN_CANCEL_FLAG_USER_SEND));
  449. memset(CancelList, 0, sizeof(CancelList));
  450. //
  451. // Preset the return
  452. //
  453. hResultCode = DPN_OK;
  454. //
  455. // Create cancel list
  456. //
  457. do
  458. {
  459. dwRemainingCount = 0;
  460. dwCurrentCount = 0;
  461. //
  462. // Prevent changes
  463. //
  464. DNEnterCriticalSection(&pdnObject->csActiveList);
  465. pBilink = pdnObject->m_bilinkActiveList.GetPrev();
  466. while (pBilink != &pdnObject->m_bilinkActiveList)
  467. {
  468. pAsyncOp = CONTAINING_OBJECT(pBilink,CAsyncOp,m_bilinkActiveList);
  469. if (DNCanCancelCommand(pAsyncOp,dwFlags,pConnection))
  470. {
  471. pAsyncOp->Lock();
  472. if (!pAsyncOp->IsCancelled() && !pAsyncOp->IsComplete())
  473. {
  474. if (dwCurrentCount < (sizeof(CancelList) / sizeof(CNameTableEntry*)))
  475. {
  476. pAsyncOp->AddRef();
  477. CancelList[dwCurrentCount] = pAsyncOp;
  478. dwCurrentCount++;
  479. }
  480. else
  481. {
  482. dwRemainingCount++;
  483. }
  484. }
  485. pAsyncOp->Unlock();
  486. }
  487. pBilink = pBilink->GetPrev();
  488. }
  489. //
  490. // Allow changes, though the list should not grow any more here
  491. //
  492. DNLeaveCriticalSection(&pdnObject->csActiveList);
  493. DPFX(DPFPREP, 7,"Number of cancellable ops [%ld], remaining [%ld]",dwCurrentCount,dwRemainingCount);
  494. //
  495. // Cancel each operation in the cancel list operation (if we can)
  496. // This will only work for CONNECTs,DISCONNECTs,ENUM_QUERYs,ENUM_RESPONSEs,LISTENs,SENDs with a protocol handle
  497. //
  498. if (dwCurrentCount > 0)
  499. {
  500. DWORD dw;
  501. HRESULT hr;
  502. CSyncEvent *pSyncEvent;
  503. pSyncEvent = NULL;
  504. for (dw = 0 ; dw < dwCurrentCount ; dw++ )
  505. {
  506. //
  507. // Ensure operation has not already been cancelled
  508. // If this is a protocol operation, we will add a sync event to prevent any completions from returning
  509. // until we're done
  510. //
  511. DNASSERT( CancelList[dw] != NULL );
  512. CancelList[dw]->Lock();
  513. if (CancelList[dw]->IsCancelled() || CancelList[dw]->IsComplete())
  514. {
  515. CancelList[dw]->Unlock();
  516. CancelList[dw]->Release();
  517. CancelList[dw] = NULL;
  518. continue;
  519. }
  520. if (CancelList[dw]->GetProtocolHandle() != NULL)
  521. {
  522. if ((hr = SyncEventNew(pdnObject,&pSyncEvent)) != DPN_OK)
  523. {
  524. DPFERR("Could not get sync event");
  525. DisplayDNError(0,hr);
  526. }
  527. else
  528. {
  529. pSyncEvent->Reset();
  530. CancelList[dw]->SetCancelEvent( pSyncEvent );
  531. CancelList[dw]->SetCancelThreadID( GetCurrentThreadId() );
  532. DPFX(DPFPREP,7,"Setting sync event [0x%p]",pSyncEvent);
  533. }
  534. }
  535. CancelList[dw]->SetCancelled();
  536. CancelList[dw]->Unlock();
  537. //
  538. // Perform the actual cancel
  539. //
  540. hr = DNDoCancelCommand(pdnObject,CancelList[dw]);
  541. if ((hr != DPN_OK) && (hResultCode == DPN_OK))
  542. {
  543. hResultCode = hr;
  544. }
  545. //
  546. // If this operation was cancelled and we need to set the result, we will
  547. //
  548. if ((hr == DPN_OK) && fSetResult)
  549. {
  550. CancelList[dw]->Lock();
  551. CancelList[dw]->SetResult( hrCancel );
  552. CancelList[dw]->Unlock();
  553. }
  554. //
  555. // Set the cancel event and clear it from the async op if it's still there
  556. //
  557. if (pSyncEvent)
  558. {
  559. pSyncEvent->Set();
  560. CancelList[dw]->Lock();
  561. pSyncEvent = CancelList[dw]->GetCancelEvent();
  562. CancelList[dw]->SetCancelEvent( NULL );
  563. CancelList[dw]->Unlock();
  564. if (pSyncEvent)
  565. {
  566. DPFX(DPFPREP,7,"Returning sync event [0x%p]",pSyncEvent);
  567. pSyncEvent->ReturnSelfToPool();
  568. pSyncEvent = NULL;
  569. }
  570. }
  571. CancelList[dw]->Release();
  572. CancelList[dw] = NULL;
  573. }
  574. DNASSERT(pSyncEvent == NULL);
  575. }
  576. }
  577. while (dwRemainingCount > 0);
  578. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  579. return(hResultCode);
  580. }
  581. // DNCancelRequestCommands
  582. //
  583. // This will attempt to cancel REQUEST operations in the HandleTable.
  584. // Requests have handles which are matched up against responses. Since these
  585. // typically have SEND children (which may have completed and thus vanished),
  586. // there is no guarantee these are not orphaned off in the HandleTable.
  587. // We will look through the HandleTable for them and cancel them.
  588. #undef DPF_MODNAME
  589. #define DPF_MODNAME "DNCancelRequestCommands"
  590. HRESULT DNCancelRequestCommands(DIRECTNETOBJECT *const pdnObject)
  591. {
  592. HRESULT hResultCode;
  593. CAsyncOp **RequestList;
  594. DWORD dwCount;
  595. DWORD dwActual;
  596. CBilink *pBilink;
  597. DPFX(DPFPREP, 6,"Parameters: (none)");
  598. DNASSERT(pdnObject != NULL);
  599. RequestList = NULL;
  600. dwCount = 0;
  601. dwActual = 0;
  602. //
  603. // Determine outstanding request list size and build it
  604. //
  605. DNEnterCriticalSection(&pdnObject->csActiveList);
  606. pBilink = pdnObject->m_bilinkRequestList.GetNext();
  607. while (pBilink != &pdnObject->m_bilinkRequestList)
  608. {
  609. dwCount++;
  610. pBilink = pBilink->GetNext();
  611. }
  612. if (dwCount > 0)
  613. {
  614. CAsyncOp *pAsyncOp;
  615. if ((RequestList = static_cast<CAsyncOp**>(MemoryBlockAlloc(pdnObject,dwCount * sizeof(CAsyncOp*)))) == NULL)
  616. {
  617. DNLeaveCriticalSection(&pdnObject->csActiveList);
  618. DPFERR("Could not allocate request list");
  619. hResultCode = DPNERR_OUTOFMEMORY;
  620. goto Failure;
  621. }
  622. pBilink = pdnObject->m_bilinkRequestList.GetNext();
  623. while (pBilink != &pdnObject->m_bilinkRequestList)
  624. {
  625. pAsyncOp = CONTAINING_OBJECT(pBilink,CAsyncOp,m_bilinkActiveList);
  626. DNASSERT(dwActual < dwCount);
  627. DNASSERT(pAsyncOp->GetOpType() == ASYNC_OP_REQUEST);
  628. pAsyncOp->AddRef();
  629. RequestList[dwActual] = pAsyncOp;
  630. pAsyncOp = NULL;
  631. dwActual++;
  632. pBilink = pBilink->GetNext();
  633. }
  634. }
  635. DNLeaveCriticalSection(&pdnObject->csActiveList);
  636. //
  637. // Remove requests from request list and handle table
  638. //
  639. for (dwActual = 0 ; dwActual < dwCount ; dwActual++)
  640. {
  641. DNEnterCriticalSection(&pdnObject->csActiveList);
  642. RequestList[dwActual]->m_bilinkActiveList.RemoveFromList();
  643. DNLeaveCriticalSection(&pdnObject->csActiveList);
  644. RequestList[dwActual]->Lock();
  645. RequestList[dwActual]->SetResult( DPNERR_USERCANCEL );
  646. RequestList[dwActual]->Unlock();
  647. if (SUCCEEDED(pdnObject->HandleTable.Destroy(RequestList[dwActual]->GetHandle(), NULL)))
  648. {
  649. // Release the HandleTable reference
  650. RequestList[dwActual]->Release();
  651. }
  652. RequestList[dwActual]->Release();
  653. RequestList[dwActual] = NULL;
  654. }
  655. //
  656. // Clean up
  657. //
  658. if (RequestList)
  659. {
  660. MemoryBlockFree(pdnObject,RequestList);
  661. RequestList = NULL;
  662. }
  663. hResultCode = DPN_OK;
  664. Exit:
  665. DNASSERT(RequestList == NULL);
  666. DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
  667. return(hResultCode);
  668. Failure:
  669. if (RequestList)
  670. {
  671. MemoryBlockFree(pdnObject,RequestList);
  672. RequestList = NULL;
  673. }
  674. goto Exit;
  675. }
  676. // DNWaitForCancel
  677. //
  678. // This will strip a cancel event off an async op if it exists, wait on it, and then return it to the pool
  679. #undef DPF_MODNAME
  680. #define DPF_MODNAME "DNWaitForCancel"
  681. void DNWaitForCancel(CAsyncOp *const pAsyncOp)
  682. {
  683. DPFX(DPFPREP, 6,"Parameters: pAsyncOp [0x%p]",pAsyncOp);
  684. CSyncEvent *pSyncEvent;
  685. DNASSERT(pAsyncOp != NULL);
  686. pSyncEvent = NULL;
  687. //
  688. // Get (and clear) sync event from async op
  689. //
  690. pAsyncOp->Lock();
  691. pSyncEvent = pAsyncOp->GetCancelEvent();
  692. if (pSyncEvent)
  693. {
  694. // Only pull the SyncEvent out if we are going to wait on it
  695. if (pAsyncOp->GetCancelThreadID() == GetCurrentThreadId())
  696. {
  697. // The other side of this will clean it up
  698. DPFX(DPFPREP,7,"Cancel called on current thread - ignoring wait and continuing");
  699. pSyncEvent = NULL;
  700. }
  701. else
  702. {
  703. // We are pulling it out, so we will clean it up
  704. pAsyncOp->SetCancelEvent( NULL );
  705. }
  706. }
  707. pAsyncOp->Unlock();
  708. //
  709. // If there was a sync event,
  710. // - wait on it
  711. // - return it to the pool
  712. //
  713. if (pSyncEvent)
  714. {
  715. DPFX(DPFPREP,7,"Waiting on sync event [0x%p]",pSyncEvent);
  716. pSyncEvent->WaitForEvent();
  717. DPFX(DPFPREP,7,"Returning sync event [0x%p]",pSyncEvent);
  718. pSyncEvent->ReturnSelfToPool();
  719. pSyncEvent = NULL;
  720. }
  721. DNASSERT(pSyncEvent == NULL);
  722. DPFX(DPFPREP, 6,"Returning");
  723. }