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.

1377 lines
34 KiB

  1. /*++
  2. Copyright (c) 1989, 1990, 1991 Microsoft Corporation
  3. Module Name:
  4. request.c
  5. Abstract:
  6. This module contains code which implements the TP_REQUEST object.
  7. Routines are provided to create, destroy, reference, and dereference,
  8. transport request objects.
  9. Author:
  10. David Beaver (dbeaver) 1 July 1991
  11. Environment:
  12. Kernel mode
  13. Revision History:
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #ifdef RASAUTODIAL
  18. #include <acd.h>
  19. #include <acdapi.h>
  20. #endif // RASAUTODIAL
  21. //
  22. // External variables
  23. //
  24. #ifdef RASAUTODIAL
  25. extern BOOLEAN fAcdLoadedG;
  26. extern ACD_DRIVER AcdDriverG;
  27. //
  28. // Imported routines
  29. //
  30. VOID
  31. NbfNoteNewConnection(
  32. PTP_CONNECTION Connection,
  33. PDEVICE_CONTEXT DeviceContext
  34. );
  35. #endif // RASAUTODIAL
  36. VOID
  37. NbfTdiRequestTimeoutHandler(
  38. IN PKDPC Dpc,
  39. IN PVOID DeferredContext,
  40. IN PVOID SystemArgument1,
  41. IN PVOID SystemArgument2
  42. )
  43. /*++
  44. Routine Description:
  45. This routine is executed as a DPC at DISPATCH_LEVEL when a request
  46. such as TdiSend, TdiReceive, TdiSendDatagram, TdiReceiveDatagram, etc.,
  47. encounters a timeout. This routine cleans up the activity and cancels it.
  48. Arguments:
  49. Dpc - Pointer to a system DPC object.
  50. DeferredContext - Pointer to the TP_REQUEST block representing the
  51. request that has timed out.
  52. SystemArgument1 - Not used.
  53. SystemArgument2 - Not used.
  54. Return Value:
  55. none.
  56. --*/
  57. {
  58. KIRQL oldirql;
  59. PTP_REQUEST Request;
  60. PTP_CONNECTION Connection;
  61. #if DBG
  62. LARGE_INTEGER time, difference;
  63. #endif
  64. PIO_STACK_LOCATION IrpSp;
  65. PTDI_REQUEST_KERNEL_QUERY_INFORMATION query;
  66. PDEVICE_CONTEXT DeviceContext;
  67. Dpc, SystemArgument1, SystemArgument2; // prevent compiler warnings
  68. ENTER_NBF;
  69. Request = (PTP_REQUEST)DeferredContext;
  70. IF_NBFDBG (NBF_DEBUG_REQUEST) {
  71. NbfPrint1 ("RequestTimeoutHandler: Entered, Request %lx\n", Request);
  72. }
  73. ACQUIRE_SPIN_LOCK (&Request->SpinLock, &oldirql);
  74. Request->Flags &= ~REQUEST_FLAGS_TIMER;
  75. if ((Request->Flags & REQUEST_FLAGS_STOPPING) == 0) {
  76. #if DBG
  77. KeQuerySystemTime (&time);
  78. difference.QuadPart = time.QuadPart - (Request->Time).QuadPart;
  79. NbfPrint1 ("RequestTimeoutHandler: Request timed out, queued for %ld seconds\n",
  80. difference.LowPart / SECONDS);
  81. #endif
  82. //
  83. // find reason for timeout
  84. //
  85. IrpSp = IoGetCurrentIrpStackLocation (Request->IoRequestPacket);
  86. if (IrpSp->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL) {
  87. switch (IrpSp->MinorFunction) {
  88. //
  89. // none of these should time out.
  90. //
  91. case TDI_SEND:
  92. case TDI_ACCEPT:
  93. case TDI_SET_INFORMATION:
  94. case TDI_SET_EVENT_HANDLER:
  95. case TDI_SEND_DATAGRAM:
  96. case TDI_RECEIVE_DATAGRAM:
  97. case TDI_RECEIVE:
  98. #if DBG
  99. NbfPrint1 ("RequestTimeoutHandler: Request: %lx Timed out, and shouldn't have!\n",
  100. Request);
  101. #endif
  102. ASSERT (FALSE);
  103. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  104. NbfCompleteRequest (Request, STATUS_IO_TIMEOUT, 0);
  105. break;
  106. case TDI_LISTEN:
  107. case TDI_CONNECT:
  108. #if DBG
  109. NbfPrint2 ("RequestTimeoutHandler: %s Failed, Request: %lx\n",
  110. IrpSp->MinorFunction == TDI_LISTEN ?
  111. "Listen" :
  112. IrpSp->MinorFunction == TDI_CONNECT ?
  113. "Connect" : "Disconnect",
  114. Request);
  115. #endif
  116. Connection = (PTP_CONNECTION)(Request->Context);
  117. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  118. //
  119. // Since these requests are part of the connection
  120. // itself, we just stop the connection and the
  121. // request will get torn down then. If we get the
  122. // situation where the request times out before
  123. // it is queued to the connection, then the code
  124. // that is about to queue it will check the STOPPING
  125. // flag and complete it then.
  126. //
  127. // Don't stop the connection if an automatic connection
  128. // is in progress.
  129. //
  130. #if DBG
  131. DbgPrint("RequestTimeoutHandler: AUTOCONNECTING=0x%x\n", Connection->Flags2 & CONNECTION_FLAGS2_AUTOCONNECTING);
  132. #endif
  133. if (!(Connection->Flags2 & CONNECTION_FLAGS2_AUTOCONNECTING))
  134. NbfStopConnection (Connection, STATUS_IO_TIMEOUT);
  135. break;
  136. case TDI_DISCONNECT:
  137. //
  138. // We don't create requests for TDI_DISCONNECT any more.
  139. //
  140. ASSERT(FALSE);
  141. break;
  142. case TDI_QUERY_INFORMATION:
  143. DeviceContext = (PDEVICE_CONTEXT)IrpSp->FileObject->DeviceObject;
  144. query = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&IrpSp->Parameters;
  145. IF_NBFDBG (NBF_DEBUG_DEVCTX) {
  146. NbfPrint1 ("RequestTimeout: %lx:\n", DeviceContext);
  147. }
  148. //
  149. // Determine if the request is done, or if we should
  150. // requeue it.
  151. //
  152. --Request->Retries;
  153. if (Request->Retries > 0) {
  154. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  155. //
  156. // Send another packet out, and restart the timer.
  157. //
  158. if (query->QueryType == TDI_QUERY_FIND_NAME) {
  159. NbfSendQueryFindName (
  160. DeviceContext,
  161. Request);
  162. } else if (query->QueryType == TDI_QUERY_ADAPTER_STATUS) {
  163. PUCHAR SingleSR;
  164. UINT SingleSRLength;
  165. //
  166. // Send the STATUS_QUERY frames out as
  167. // single-route source routing.
  168. //
  169. // On a second status query this should
  170. // really be sent directed, but currently we
  171. // don't record the address anywhere.
  172. //
  173. MacReturnSingleRouteSR(
  174. &DeviceContext->MacInfo,
  175. &SingleSR,
  176. &SingleSRLength);
  177. NbfSendStatusQuery (
  178. DeviceContext,
  179. Request,
  180. &DeviceContext->NetBIOSAddress,
  181. SingleSR,
  182. SingleSRLength);
  183. } else {
  184. ASSERT (FALSE);
  185. }
  186. } else {
  187. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  188. //
  189. // That's it, we retried enough, complete it.
  190. //
  191. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock,&oldirql);
  192. RemoveEntryList (&Request->Linkage);
  193. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  194. if (Request->BytesWritten > 0) {
  195. NbfCompleteRequest (Request, STATUS_SUCCESS, Request->BytesWritten);
  196. } else {
  197. NbfCompleteRequest (Request, STATUS_IO_TIMEOUT, Request->BytesWritten);
  198. }
  199. }
  200. break;
  201. default:
  202. #if DBG
  203. NbfPrint2 ("RequestTimeoutHandler: Unknown Request Timed out, Request: %lx Type: %x\n",
  204. Request, IrpSp->MinorFunction);
  205. #endif
  206. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  207. break;
  208. } // end of switch
  209. } else {
  210. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  211. }
  212. NbfDereferenceRequest ("Timeout", Request, RREF_TIMER); // for the timeout
  213. } else {
  214. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  215. NbfDereferenceRequest ("Timeout: stopping", Request, RREF_TIMER); // for the timeout
  216. }
  217. LEAVE_NBF;
  218. return;
  219. } /* RequestTimeoutHandler */
  220. VOID
  221. NbfAllocateRequest(
  222. IN PDEVICE_CONTEXT DeviceContext,
  223. OUT PTP_REQUEST *TransportRequest
  224. )
  225. /*++
  226. Routine Description:
  227. This routine allocates a request packet from nonpaged pool and initializes
  228. it to a known state.
  229. NOTE: This routine is called with the device context spinlock
  230. held, or at such a time as synchronization is unnecessary.
  231. Arguments:
  232. DeviceContext - Pointer to the device context (which is really just
  233. the device object with its extension) to be associated with the
  234. address.
  235. TransportRequest - Pointer to a place where this routine will return
  236. a pointer to a transport request structure. It returns NULL if no
  237. storage can be allocated.
  238. Return Value:
  239. None.
  240. --*/
  241. {
  242. PTP_REQUEST Request;
  243. if ((DeviceContext->MemoryLimit != 0) &&
  244. ((DeviceContext->MemoryUsage + sizeof(TP_REQUEST)) >
  245. DeviceContext->MemoryLimit)) {
  246. PANIC("NBF: Could not allocate request: limit\n");
  247. NbfWriteResourceErrorLog(
  248. DeviceContext,
  249. EVENT_TRANSPORT_RESOURCE_LIMIT,
  250. 104,
  251. sizeof(TP_REQUEST),
  252. REQUEST_RESOURCE_ID);
  253. *TransportRequest = NULL;
  254. return;
  255. }
  256. Request = (PTP_REQUEST)ExAllocatePoolWithTag (
  257. NonPagedPool,
  258. sizeof (TP_REQUEST),
  259. NBF_MEM_TAG_TP_REQUEST);
  260. if (Request == NULL) {
  261. PANIC("NBF: Could not allocate request: no pool\n");
  262. NbfWriteResourceErrorLog(
  263. DeviceContext,
  264. EVENT_TRANSPORT_RESOURCE_POOL,
  265. 204,
  266. sizeof(TP_REQUEST),
  267. REQUEST_RESOURCE_ID);
  268. *TransportRequest = NULL;
  269. return;
  270. }
  271. RtlZeroMemory (Request, sizeof(TP_REQUEST));
  272. DeviceContext->MemoryUsage += sizeof(TP_REQUEST);
  273. ++DeviceContext->RequestAllocated;
  274. Request->Type = NBF_REQUEST_SIGNATURE;
  275. Request->Size = sizeof (TP_REQUEST);
  276. Request->ResponseBuffer = NULL;
  277. Request->Provider = DeviceContext;
  278. Request->ProviderInterlock = &DeviceContext->Interlock;
  279. KeInitializeSpinLock (&Request->SpinLock);
  280. KeInitializeDpc (&Request->Dpc, NbfTdiRequestTimeoutHandler, (PVOID)Request);
  281. KeInitializeTimer (&Request->Timer); // set to not-signaled state.
  282. *TransportRequest = Request;
  283. } /* NbfAllocateRequest */
  284. VOID
  285. NbfDeallocateRequest(
  286. IN PDEVICE_CONTEXT DeviceContext,
  287. IN PTP_REQUEST TransportRequest
  288. )
  289. /*++
  290. Routine Description:
  291. This routine frees a request packet.
  292. NOTE: This routine is called with the device context spinlock
  293. held, or at such a time as synchronization is unnecessary.
  294. Arguments:
  295. DeviceContext - Pointer to the device context (which is really just
  296. the device object with its extension) to be associated with the
  297. address.
  298. TransportRequest - Pointer to a transport request structure.
  299. Return Value:
  300. None.
  301. --*/
  302. {
  303. ExFreePool (TransportRequest);
  304. --DeviceContext->RequestAllocated;
  305. DeviceContext->MemoryUsage -= sizeof(TP_REQUEST);
  306. } /* NbfDeallocateRequest */
  307. NTSTATUS
  308. NbfCreateRequest(
  309. IN PIRP Irp,
  310. IN PVOID Context,
  311. IN ULONG Flags,
  312. IN PMDL Buffer2,
  313. IN ULONG Buffer2Length,
  314. IN LARGE_INTEGER Timeout,
  315. OUT PTP_REQUEST * TpRequest
  316. )
  317. /*++
  318. Routine Description:
  319. This routine creates a transport request and associates it with the
  320. specified IRP, context, and queue. All major requests, including
  321. TdiSend, TdiSendDatagram, TdiReceive, and TdiReceiveDatagram requests,
  322. are composed in this manner.
  323. Arguments:
  324. Irp - Pointer to an IRP which was received by the transport for this
  325. request.
  326. Context - Pointer to anything to associate this request with. This
  327. value is not interpreted except at request cancelation time.
  328. Flags - A set of bitflags indicating the disposition of this request.
  329. Timeout - Timeout value (if non-zero) to start a timer for this request.
  330. If zero, then no timer is activated for the request.
  331. TpRequest - If the function returns STATUS_SUCCESS, this will return
  332. pointer to the TP_REQUEST structure allocated.
  333. Return Value:
  334. NTSTATUS - status of operation.
  335. --*/
  336. {
  337. KIRQL oldirql;
  338. PDEVICE_CONTEXT DeviceContext;
  339. PTP_REQUEST Request;
  340. PLIST_ENTRY p;
  341. PIO_STACK_LOCATION irpSp;
  342. #if DBG
  343. LARGE_INTEGER Time;
  344. #endif
  345. IF_NBFDBG (NBF_DEBUG_REQUEST) {
  346. NbfPrint0 ("NbfCreateRequest: Entered.\n");
  347. }
  348. irpSp = IoGetCurrentIrpStackLocation(Irp);
  349. DeviceContext = (PDEVICE_CONTEXT)irpSp->FileObject->DeviceObject;
  350. #if DBG
  351. if (!MmIsNonPagedSystemAddressValid (DeviceContext->RequestPool.Flink)) {
  352. NbfPrint2 ("NbfCreateRequest: RequestList hosed: %lx DeviceContext: %lx\n",
  353. &DeviceContext->RequestPool, DeviceContext);
  354. }
  355. #endif
  356. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
  357. p = RemoveHeadList (&DeviceContext->RequestPool);
  358. if (p == &DeviceContext->RequestPool) {
  359. if ((DeviceContext->RequestMaxAllocated == 0) ||
  360. (DeviceContext->RequestAllocated < DeviceContext->RequestMaxAllocated)) {
  361. NbfAllocateRequest (DeviceContext, &Request);
  362. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  363. NbfPrint1 ("NBF: Allocated request at %lx\n", Request);
  364. }
  365. } else {
  366. NbfWriteResourceErrorLog(
  367. DeviceContext,
  368. EVENT_TRANSPORT_RESOURCE_SPECIFIC,
  369. 404,
  370. sizeof(TP_REQUEST),
  371. REQUEST_RESOURCE_ID);
  372. Request = NULL;
  373. }
  374. if (Request == NULL) {
  375. ++DeviceContext->RequestExhausted;
  376. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  377. PANIC ("NbfCreateConnection: Could not allocate request object!\n");
  378. return STATUS_INSUFFICIENT_RESOURCES;
  379. }
  380. } else {
  381. Request = CONTAINING_RECORD (p, TP_REQUEST, Linkage);
  382. }
  383. ++DeviceContext->RequestInUse;
  384. if (DeviceContext->RequestInUse > DeviceContext->RequestMaxInUse) {
  385. ++DeviceContext->RequestMaxInUse;
  386. }
  387. DeviceContext->RequestTotal += DeviceContext->RequestInUse;
  388. ++DeviceContext->RequestSamples;
  389. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  390. //
  391. // fill out the request.
  392. //
  393. // Request->Provider = DeviceContext;
  394. Request->IoRequestPacket = Irp;
  395. Request->Buffer2 = Buffer2;
  396. Request->Buffer2Length = Buffer2Length;
  397. Request->Flags = Flags;
  398. Request->Context = Context;
  399. Request->ReferenceCount = 1; // initialize reference count.
  400. #if DBG
  401. {
  402. UINT Counter;
  403. for (Counter = 0; Counter < NUMBER_OF_RREFS; Counter++) {
  404. Request->RefTypes[Counter] = 0;
  405. }
  406. // This reference is removed by NbfCompleteRequest
  407. Request->RefTypes[RREF_CREATION] = 1;
  408. }
  409. #endif
  410. #if DBG
  411. Request->Completed = FALSE;
  412. Request->Destroyed = FALSE;
  413. Request->TotalReferences = 0;
  414. Request->TotalDereferences = 0;
  415. Request->NextRefLoc = 0;
  416. ExInterlockedInsertHeadList (&NbfGlobalRequestList, &Request->GlobalLinkage, &NbfGlobalInterlock);
  417. StoreRequestHistory (Request, TRUE);
  418. #endif
  419. #if DBG
  420. KeQuerySystemTime (&Time); // ugly, but effective
  421. Request->Time.LowPart = Time.LowPart;
  422. Request->Time.HighPart = Time.HighPart;
  423. #endif
  424. IF_NBFDBG (NBF_DEBUG_IRP) {
  425. if (Irp->MdlAddress != NULL) {
  426. PMDL mdl;
  427. NbfPrint2 ("NbfCreateRequest: Map request %lx Irp %lx MdlChain \n",
  428. Request, Request->IoRequestPacket);
  429. mdl = Request->Buffer2;
  430. while (mdl != NULL) {
  431. NbfPrint4 ("Mdl %lx Va %lx StartVa %lx Flags %x\n",
  432. mdl, MmGetSystemAddressForMdl(mdl), MmGetMdlVirtualAddress(mdl),
  433. mdl->MdlFlags);
  434. mdl = mdl->Next;
  435. }
  436. }
  437. }
  438. IF_NBFDBG (NBF_DEBUG_REQUEST) {
  439. NbfPrint3 ("NbfCreateRequest: Request %lx Buffer2: %lx Irp: %lx\n", Request,
  440. Buffer2, Irp);
  441. }
  442. if ((Timeout.LowPart == 0) && (Timeout.HighPart == 0)) {
  443. // no timeout
  444. } else {
  445. IF_NBFDBG (NBF_DEBUG_REQUEST) {
  446. NbfPrint3 ("NbfCreateRequest: Starting timer %lx%lx Flags %lx\n",
  447. Timeout.HighPart, Timeout.LowPart, Request->Flags);
  448. }
  449. Request->Flags |= REQUEST_FLAGS_TIMER; // there is a timeout on this request.
  450. KeInitializeTimer (&Request->Timer); // set to not-signaled state.
  451. NbfReferenceRequest ("Create: timer", Request, RREF_TIMER); // one for the timer
  452. KeSetTimer (&Request->Timer, Timeout, &Request->Dpc);
  453. }
  454. *TpRequest = Request;
  455. return STATUS_SUCCESS;
  456. } /* NbfCreateRequest */
  457. VOID
  458. NbfDestroyRequest(
  459. IN PTP_REQUEST Request
  460. )
  461. /*++
  462. Routine Description:
  463. This routine returns a request block to the free pool.
  464. Arguments:
  465. Request - Pointer to a TP_REQUEST block to return to the free pool.
  466. Return Value:
  467. NTSTATUS - status of operation.
  468. --*/
  469. {
  470. KIRQL oldirql;
  471. PIO_STACK_LOCATION irpSp;
  472. PDEVICE_CONTEXT DeviceContext;
  473. IF_NBFDBG (NBF_DEBUG_REQUEST) {
  474. NbfPrint0 ("NbfDestroyRequest: Entered.\n");
  475. }
  476. #if DBG
  477. if (Request->Destroyed) {
  478. NbfPrint1 ("attempt to destroy already-destroyed request 0x%lx\n", Request);
  479. DbgBreakPoint ();
  480. }
  481. Request->Destroyed = TRUE;
  482. #if 1
  483. ACQUIRE_SPIN_LOCK (&NbfGlobalInterlock, &oldirql);
  484. RemoveEntryList (&Request->GlobalLinkage);
  485. RELEASE_SPIN_LOCK (&NbfGlobalInterlock, oldirql);
  486. #else
  487. ExInterlockedRemoveHeadList (Request->GlobalLinkage.Blink, &NbfGlobalInterlock);
  488. #endif
  489. #endif
  490. ASSERT(Request->Completed);
  491. //
  492. // Return the request to the caller with whatever status is in the IRP.
  493. //
  494. IF_NBFDBG (NBF_DEBUG_IRP) {
  495. NbfPrint1 ("NbfCompleteRequest: Completing IRP: %lx\n",
  496. Request->IoRequestPacket);
  497. }
  498. //
  499. // Now dereference the owner of this request so that we are safe when
  500. // we finally tear down the {connection, address}. The problem we're
  501. // facing here is that we can't allow the user to assume semantics;
  502. // the end of life for a connection must truly be the real end of life.
  503. // for that to occur, we reference the owning object when the request is
  504. // created and we dereference it just before we return it to the pool.
  505. //
  506. switch (Request->Owner) {
  507. case ConnectionType:
  508. NbfDereferenceConnection ("Removing Connection",((PTP_CONNECTION)Request->Context), CREF_REQUEST);
  509. break;
  510. #if DBG
  511. case AddressType:
  512. ASSERT (FALSE);
  513. NbfDereferenceAddress ("Removing Address", ((PTP_ADDRESS)Request->Context), AREF_REQUEST);
  514. break;
  515. #endif
  516. case DeviceContextType:
  517. NbfDereferenceDeviceContext ("Removing Address", ((PDEVICE_CONTEXT)Request->Context), DCREF_REQUEST);
  518. break;
  519. }
  520. //
  521. // Unmap a possibly mapped buffer. We've only mapped the buffer if the
  522. // Irp Major function is not method 0. (of 0, 1, 2, and 3.)
  523. //
  524. IF_NBFDBG (NBF_DEBUG_IRP) {
  525. {
  526. PMDL mdl;
  527. NbfPrint2 ("NbfDestroyRequest: Unmap request %lx Irp %lx MdlChain \n",
  528. Request, Request->IoRequestPacket);
  529. mdl = Request->Buffer2;
  530. while (mdl != NULL) {
  531. NbfPrint4 ("Mdl %lx Va %lx StartVa %lx Flags %x\n",
  532. mdl, MmGetSystemAddressForMdl(mdl), MmGetMdlVirtualAddress(mdl),
  533. mdl->MdlFlags);
  534. mdl = mdl->Next;
  535. }
  536. }
  537. }
  538. irpSp = IoGetCurrentIrpStackLocation (Request->IoRequestPacket);
  539. DeviceContext = Request->Provider;
  540. LEAVE_NBF;
  541. IoCompleteRequest (Request->IoRequestPacket, IO_NETWORK_INCREMENT);
  542. ENTER_NBF;
  543. ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql);
  544. //
  545. // Put the request back on the free list. NOTE: we have the
  546. // lock held here.
  547. //
  548. DeviceContext->RequestTotal += DeviceContext->RequestInUse;
  549. ++DeviceContext->RequestSamples;
  550. --DeviceContext->RequestInUse;
  551. if ((DeviceContext->RequestAllocated - DeviceContext->RequestInUse) >
  552. DeviceContext->RequestInitAllocated) {
  553. NbfDeallocateRequest (DeviceContext, Request);
  554. IF_NBFDBG (NBF_DEBUG_DYNAMIC) {
  555. NbfPrint1 ("NBF: Deallocated request at %lx\n", Request);
  556. }
  557. } else {
  558. InsertTailList (&DeviceContext->RequestPool, &Request->Linkage);
  559. }
  560. RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql);
  561. } /* NbfDestroyRequest */
  562. #if DBG
  563. VOID
  564. NbfRefRequest(
  565. IN PTP_REQUEST Request
  566. )
  567. /*++
  568. Routine Description:
  569. This routine increments the reference count on a transport request.
  570. Arguments:
  571. Request - Pointer to a TP_REQUEST block.
  572. Return Value:
  573. none.
  574. --*/
  575. {
  576. LONG result;
  577. IF_NBFDBG (NBF_DEBUG_REQUEST) {
  578. NbfPrint1 ("NbfRefRequest: Entered, ReferenceCount: %x\n",
  579. Request->ReferenceCount);
  580. }
  581. #if DBG
  582. StoreRequestHistory( Request, TRUE );
  583. #endif
  584. ASSERT (Request->ReferenceCount > 0);
  585. result = InterlockedIncrement (&Request->ReferenceCount);
  586. } /* NbfRefRequest */
  587. #endif
  588. VOID
  589. NbfDerefRequest(
  590. IN PTP_REQUEST Request
  591. )
  592. /*++
  593. Routine Description:
  594. This routine dereferences a transport request by decrementing the
  595. reference count contained in the structure. If, after being
  596. decremented, the reference count is zero, then this routine calls
  597. NbfDestroyRequest to remove it from the system.
  598. Arguments:
  599. Request - Pointer to a transport request object.
  600. Return Value:
  601. none.
  602. --*/
  603. {
  604. LONG result;
  605. IF_NBFDBG (NBF_DEBUG_REQUEST) {
  606. NbfPrint1 ("NbfDerefRequest: Entered, ReferenceCount: %x\n",
  607. Request->ReferenceCount);
  608. }
  609. #if DBG
  610. StoreRequestHistory( Request, FALSE );
  611. #endif
  612. result = InterlockedDecrement (&Request->ReferenceCount);
  613. ASSERT (result >= 0);
  614. //
  615. // If we have deleted all references to this request, then we can
  616. // destroy the object. It is okay to have already released the spin
  617. // lock at this point because there is no possible way that another
  618. // stream of execution has access to the request any longer.
  619. //
  620. if (result == 0) {
  621. NbfDestroyRequest (Request);
  622. }
  623. } /* NbfDerefRequest */
  624. VOID
  625. NbfCompleteRequest(
  626. IN PTP_REQUEST Request,
  627. IN NTSTATUS Status,
  628. IN ULONG Information
  629. )
  630. /*++
  631. Routine Description:
  632. This routine completes a transport request object, completing the I/O,
  633. stopping the timeout, and freeing up the request object itself.
  634. Arguments:
  635. Request - Pointer to a transport request object.
  636. Status - Actual return status to be assigned to the request. This
  637. value may be overridden if the timed-out bitflag is set in the request.
  638. Information - the information field for the I/O Status Block.
  639. Return Value:
  640. none.
  641. --*/
  642. {
  643. KIRQL oldirql;
  644. PIRP Irp;
  645. PIO_STACK_LOCATION IrpSp;
  646. NTSTATUS FinalStatus = Status;
  647. NTSTATUS CopyStatus;
  648. BOOLEAN TimerWasSet;
  649. ASSERT (Status != STATUS_PENDING);
  650. IF_NBFDBG (NBF_DEBUG_REQUEST) {
  651. NbfPrint2 ("NbfCompleteRequest: Entered Request %lx, Request->Flags %lx\n",
  652. Request, Request->Flags);
  653. }
  654. #if DBG
  655. if (Request->Completed) {
  656. NbfPrint1 ("attempt to completed already-completed request 0x%lx\n", Request);
  657. DbgBreakPoint ();
  658. }
  659. Request->Completed = TRUE;
  660. #endif
  661. ACQUIRE_SPIN_LOCK (&Request->SpinLock, &oldirql);
  662. if ((Request->Flags & REQUEST_FLAGS_STOPPING) == 0) {
  663. Request->Flags |= REQUEST_FLAGS_STOPPING;
  664. //
  665. // Cancel the pending timeout on this request. Not all requests
  666. // have their timer set. If this request has the TIMER bit set,
  667. // then the timer needs to be cancelled. If it cannot be cancelled,
  668. // then the timer routine will be run, so we just return and let
  669. // the timer routine worry about cleaning up this request.
  670. //
  671. if ((Request->Flags & REQUEST_FLAGS_TIMER) != 0) {
  672. Request->Flags &= ~REQUEST_FLAGS_TIMER;
  673. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  674. TimerWasSet = KeCancelTimer (&Request->Timer);
  675. if (TimerWasSet) {
  676. NbfDereferenceRequest ("Complete: stop timer", Request, RREF_TIMER);
  677. IF_NBFDBG (NBF_DEBUG_REQUEST) {
  678. NbfPrint1 ("NbfCompleteRequest: Canceled timer: %lx.\n", &Request->Timer);
  679. }
  680. }
  681. } else {
  682. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  683. }
  684. Irp = Request->IoRequestPacket;
  685. #ifdef RASAUTODIAL
  686. //
  687. // If this is a connect operation that has
  688. // returned with either STATUS_SUCCESS or
  689. // STATUS_BAD_NETWORK_PATH, then
  690. // inform the automatic connection driver.
  691. //
  692. if (fAcdLoadedG) {
  693. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  694. if (IrpSp->MinorFunction == TDI_CONNECT &&
  695. FinalStatus == STATUS_SUCCESS)
  696. {
  697. KIRQL adirql;
  698. BOOLEAN fEnabled;
  699. ACQUIRE_SPIN_LOCK(&AcdDriverG.SpinLock, &adirql);
  700. fEnabled = AcdDriverG.fEnabled;
  701. RELEASE_SPIN_LOCK(&AcdDriverG.SpinLock, adirql);
  702. if (fEnabled) {
  703. NbfNoteNewConnection(
  704. IrpSp->FileObject->FsContext,
  705. (PDEVICE_CONTEXT)IrpSp->FileObject->DeviceObject);
  706. }
  707. }
  708. }
  709. #endif // RASAUTODIAL
  710. //
  711. // For requests associated with a device context, we need
  712. // to copy the data from the temp buffer to the MDL and
  713. // free the temp buffer.
  714. //
  715. if (Request->ResponseBuffer != NULL) {
  716. if ((FinalStatus == STATUS_SUCCESS) ||
  717. (FinalStatus == STATUS_BUFFER_OVERFLOW)) {
  718. CopyStatus = TdiCopyBufferToMdl (
  719. Request->ResponseBuffer,
  720. 0L,
  721. Information,
  722. Irp->MdlAddress,
  723. 0,
  724. &Information);
  725. if (CopyStatus != STATUS_SUCCESS) {
  726. FinalStatus = CopyStatus;
  727. }
  728. }
  729. ExFreePool (Request->ResponseBuffer);
  730. Request->ResponseBuffer = NULL;
  731. }
  732. //
  733. // Install the return code in the IRP so that when we call NbfDestroyRequest,
  734. // it will get completed with the proper return status.
  735. //
  736. Irp->IoStatus.Status = FinalStatus;
  737. Irp->IoStatus.Information = Information;
  738. //
  739. // The entire transport is done with this request.
  740. //
  741. NbfDereferenceRequest ("Complete", Request, RREF_CREATION); // remove creation reference.
  742. } else {
  743. RELEASE_SPIN_LOCK (&Request->SpinLock, oldirql);
  744. }
  745. } /* NbfCompleteRequest */
  746. #if DBG
  747. VOID
  748. NbfRefSendIrp(
  749. IN PIO_STACK_LOCATION IrpSp
  750. )
  751. /*++
  752. Routine Description:
  753. This routine increments the reference count on a send IRP.
  754. Arguments:
  755. IrpSp - Pointer to the IRP's stack location.
  756. Return Value:
  757. none.
  758. --*/
  759. {
  760. IF_NBFDBG (NBF_DEBUG_REQUEST) {
  761. NbfPrint1 ("NbfRefSendIrp: Entered, ReferenceCount: %x\n",
  762. IRP_SEND_REFCOUNT(IrpSp));
  763. }
  764. ASSERT (IRP_SEND_REFCOUNT(IrpSp) > 0);
  765. InterlockedIncrement (&IRP_SEND_REFCOUNT(IrpSp));
  766. } /* NbfRefSendIrp */
  767. VOID
  768. NbfDerefSendIrp(
  769. IN PIO_STACK_LOCATION IrpSp
  770. )
  771. /*++
  772. Routine Description:
  773. This routine dereferences a transport send IRP by decrementing the
  774. reference count contained in the structure. If, after being
  775. decremented, the reference count is zero, then this routine calls
  776. IoCompleteRequest to actually complete the IRP.
  777. Arguments:
  778. Request - Pointer to a transport send IRP's stack location.
  779. Return Value:
  780. none.
  781. --*/
  782. {
  783. LONG result;
  784. IF_NBFDBG (NBF_DEBUG_REQUEST) {
  785. NbfPrint1 ("NbfDerefSendIrp: Entered, ReferenceCount: %x\n",
  786. IRP_SEND_REFCOUNT(IrpSp));
  787. }
  788. result = InterlockedDecrement (&IRP_SEND_REFCOUNT(IrpSp));
  789. ASSERT (result >= 0);
  790. //
  791. // If we have deleted all references to this request, then we can
  792. // destroy the object. It is okay to have already released the spin
  793. // lock at this point because there is no possible way that another
  794. // stream of execution has access to the request any longer.
  795. //
  796. if (result == 0) {
  797. PIRP Irp = IRP_SEND_IRP(IrpSp);
  798. IRP_SEND_REFCOUNT(IrpSp) = 0;
  799. IRP_SEND_IRP (IrpSp) = NULL;
  800. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  801. }
  802. } /* NbfDerefSendIrp */
  803. #endif
  804. VOID
  805. NbfCompleteSendIrp(
  806. IN PIRP Irp,
  807. IN NTSTATUS Status,
  808. IN ULONG Information
  809. )
  810. /*++
  811. Routine Description:
  812. This routine completes a transport send IRP.
  813. Arguments:
  814. Irp - Pointer to a send IRP.
  815. Status - Actual return status to be assigned to the request. This
  816. value may be overridden if the timed-out bitflag is set in the request.
  817. Information - the information field for the I/O Status Block.
  818. Return Value:
  819. none.
  820. --*/
  821. {
  822. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  823. PTP_CONNECTION Connection;
  824. ASSERT (Status != STATUS_PENDING);
  825. Connection = IRP_SEND_CONNECTION(IrpSp);
  826. IF_NBFDBG (NBF_DEBUG_REQUEST) {
  827. NbfPrint2 ("NbfCompleteSendIrp: Entered IRP %lx, connection %lx\n",
  828. Irp, Connection);
  829. }
  830. Irp->IoStatus.Status = Status;
  831. Irp->IoStatus.Information = Information;
  832. NbfDereferenceSendIrp ("Complete", IrpSp, RREF_CREATION); // remove creation reference.
  833. NbfDereferenceConnectionMacro ("Removing Connection", Connection, CREF_SEND_IRP);
  834. } /* NbfCompleteSendIrp */
  835. #if DBG
  836. VOID
  837. NbfRefReceiveIrpLocked(
  838. IN PIO_STACK_LOCATION IrpSp
  839. )
  840. /*++
  841. Routine Description:
  842. This routine increments the reference count on a receive IRP.
  843. Arguments:
  844. IrpSp - Pointer to the IRP's stack location.
  845. Return Value:
  846. none.
  847. --*/
  848. {
  849. IF_NBFDBG (NBF_DEBUG_REQUEST) {
  850. NbfPrint1 ("NbfRefReceiveIrpLocked: Entered, ReferenceCount: %x\n",
  851. IRP_RECEIVE_REFCOUNT(IrpSp));
  852. }
  853. ASSERT (IRP_RECEIVE_REFCOUNT(IrpSp) > 0);
  854. IRP_RECEIVE_REFCOUNT(IrpSp)++;
  855. } /* NbfRefReceiveIrpLocked */
  856. #endif
  857. VOID
  858. NbfDerefReceiveIrp(
  859. IN PIO_STACK_LOCATION IrpSp
  860. )
  861. /*++
  862. Routine Description:
  863. This routine dereferences a transport receive IRP by decrementing the
  864. reference count contained in the structure. If, after being
  865. decremented, the reference count is zero, then this routine calls
  866. IoCompleteRequest to actually complete the IRP.
  867. Arguments:
  868. Request - Pointer to a transport receive IRP's stack location.
  869. Return Value:
  870. none.
  871. --*/
  872. {
  873. ULONG result;
  874. IF_NBFDBG (NBF_DEBUG_REQUEST) {
  875. NbfPrint1 ("NbfDerefReceiveIrp: Entered, ReferenceCount: %x\n",
  876. IRP_RECEIVE_REFCOUNT(IrpSp));
  877. }
  878. result = ExInterlockedAddUlong (
  879. (PULONG)&IRP_RECEIVE_REFCOUNT(IrpSp),
  880. (ULONG)-1,
  881. (IRP_RECEIVE_CONNECTION(IrpSp)->LinkSpinLock));
  882. ASSERT (result > 0);
  883. //
  884. // If we have deleted all references to this request, then we can
  885. // destroy the object. It is okay to have already released the spin
  886. // lock at this point because there is no possible way that another
  887. // stream of execution has access to the request any longer.
  888. //
  889. if (result == 1) {
  890. PIRP Irp = IRP_RECEIVE_IRP(IrpSp);
  891. ExInterlockedInsertTailList(
  892. &(IRP_DEVICE_CONTEXT(IrpSp)->IrpCompletionQueue),
  893. &Irp->Tail.Overlay.ListEntry,
  894. &(IRP_DEVICE_CONTEXT(IrpSp)->Interlock));
  895. }
  896. } /* NbfDerefReceiveIrp */
  897. #if DBG
  898. VOID
  899. NbfDerefReceiveIrpLocked(
  900. IN PIO_STACK_LOCATION IrpSp
  901. )
  902. /*++
  903. Routine Description:
  904. This routine dereferences a transport receive IRP by decrementing the
  905. reference count contained in the structure. If, after being
  906. decremented, the reference count is zero, then this routine calls
  907. IoCompleteRequest to actually complete the IRP.
  908. Arguments:
  909. Request - Pointer to a transport receive IRP's stack location.
  910. Return Value:
  911. none.
  912. --*/
  913. {
  914. ULONG result;
  915. IF_NBFDBG (NBF_DEBUG_REQUEST) {
  916. NbfPrint1 ("NbfDerefReceiveIrpLocked: Entered, ReferenceCount: %x\n",
  917. IRP_RECEIVE_REFCOUNT(IrpSp));
  918. }
  919. result = IRP_RECEIVE_REFCOUNT(IrpSp)--;
  920. ASSERT (result > 0);
  921. //
  922. // If we have deleted all references to this request, then we can
  923. // destroy the object. It is okay to have already released the spin
  924. // lock at this point because there is no possible way that another
  925. // stream of execution has access to the request any longer.
  926. //
  927. if (result == 1) {
  928. PIRP Irp = IRP_RECEIVE_IRP(IrpSp);
  929. ExInterlockedInsertTailList(
  930. &(IRP_DEVICE_CONTEXT(IrpSp)->IrpCompletionQueue),
  931. &Irp->Tail.Overlay.ListEntry,
  932. &(IRP_DEVICE_CONTEXT(IrpSp)->Interlock));
  933. }
  934. } /* NbfDerefReceiveIrpLocked */
  935. #endif
  936. VOID
  937. NbfCompleteReceiveIrp(
  938. IN PIRP Irp,
  939. IN NTSTATUS Status,
  940. IN ULONG Information
  941. )
  942. /*++
  943. Routine Description:
  944. This routine completes a transport receive IRP.
  945. NOTE: THIS ROUTINE MUST BE CALLED WITH THE CONNECTION SPINLOCK
  946. HELD.
  947. Arguments:
  948. Irp - Pointer to a receive IRP.
  949. Status - Actual return status to be assigned to the request. This
  950. value may be overridden if the timed-out bitflag is set in the request.
  951. Information - the information field for the I/O Status Block.
  952. Return Value:
  953. none.
  954. --*/
  955. {
  956. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  957. PTP_CONNECTION Connection;
  958. ASSERT (Status != STATUS_PENDING);
  959. Connection = IRP_RECEIVE_CONNECTION(IrpSp);
  960. IF_NBFDBG (NBF_DEBUG_REQUEST) {
  961. NbfPrint2 ("NbfCompleteReceiveIrp: Entered IRP %lx, connection %lx\n",
  962. Irp, Connection);
  963. }
  964. Irp->IoStatus.Status = Status;
  965. Irp->IoStatus.Information = Information;
  966. NbfDereferenceReceiveIrpLocked ("Complete", IrpSp, RREF_CREATION); // remove creation reference.
  967. } /* NbfCompleteReceiveIrp */
  968.