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.

2971 lines
66 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. D:\nt\private\ntos\tdi\rawwan\core\ntentry.c
  5. Abstract:
  6. NT specific entry points for dispatching and handling TDI IRPs. Based on
  7. TCP source.
  8. Revision History:
  9. Who When What
  10. -------- -------- ----------------------------------------------
  11. arvindm 04-21-97 Created
  12. Notes:
  13. --*/
  14. #include <precomp.h>
  15. #define _FILENUMBER 'IDTN'
  16. #define RWAN_COMPLETE_IRP(_pIrp, _Status, _Info) \
  17. { \
  18. (_pIrp)->IoStatus.Status = (NTSTATUS)(_Status); \
  19. (_pIrp)->IoStatus.Information = (_Info); \
  20. IoCompleteRequest(_pIrp, IO_NETWORK_INCREMENT); \
  21. }
  22. NTSTATUS
  23. DriverEntry(
  24. IN PDRIVER_OBJECT pDriverObject,
  25. IN PUNICODE_STRING pRegistryPath
  26. )
  27. /*++
  28. Routine Description:
  29. This is the "init" routine called by the system when Raw WAN
  30. is loaded. We initialize all our global objects, fill in our
  31. Dispatch and Unload routine addresses in the driver object.
  32. We initialize the media/AF specific modules, and they register support
  33. for TDI protocols, at which time we create device objects.
  34. Arguments:
  35. pDriverObject - Pointer to the driver object created by the system.
  36. pRegistryPath - Pointer to our global registry path. This is ignored.
  37. Return Value:
  38. NT Status code: STATUS_SUCCESS if successful, error code otherwise.
  39. --*/
  40. {
  41. NTSTATUS Status;
  42. RWAN_STATUS RWanStatus;
  43. PDEVICE_OBJECT pDeviceObject;
  44. UNICODE_STRING DeviceName;
  45. INT i;
  46. RWANDEBUGP(DL_FATAL, DC_WILDCARD,
  47. ("RWanDebugLevel is %d, &RWanDebugLevel at %p\n",
  48. RWanDebugLevel, &RWanDebugLevel));
  49. RWANDEBUGP(DL_FATAL, DC_WILDCARD,
  50. ("RWanDebugComp is x%x, &RWanDebugComp at %p\n",
  51. RWanDebugComp, &RWanDebugComp));
  52. RWANDEBUGP(DL_FATAL, DC_WILDCARD,
  53. ("RWanGlobals at %p\n", &RWanGlobals));
  54. #if DBG
  55. RWANDEBUGP(DL_FATAL, DC_WILDCARD,
  56. ("To skip everything set RWanSkipAll at %p to 1\n", &RWanSkipAll));
  57. if (RWanSkipAll)
  58. {
  59. RWANDEBUGP(DL_FATAL, DC_WILDCARD,
  60. ("Aborting DriverEntry\n"));
  61. return (STATUS_UNSUCCESSFUL);
  62. }
  63. NdisAllocateSpinLock(&RWanDbgLogLock);
  64. #if DBG_LOG_PACKETS
  65. NdisAllocateSpinLock(&RWanDPacketLogLock);
  66. #endif
  67. #endif // DBG
  68. RWanStatus = RWanInitGlobals(pDriverObject);
  69. if (RWanStatus != RWAN_STATUS_SUCCESS)
  70. {
  71. return (STATUS_UNSUCCESSFUL);
  72. }
  73. //
  74. // Register as an NDIS protocol.
  75. //
  76. RWAN_ZERO_MEM(&RWanNdisProtocolCharacteristics, sizeof(RWanNdisProtocolCharacteristics));
  77. RWanNdisProtocolCharacteristics.MajorNdisVersion = RWAN_NDIS_MAJOR_VERSION;
  78. RWanNdisProtocolCharacteristics.MinorNdisVersion = RWAN_NDIS_MINOR_VERSION;
  79. RWanNdisProtocolCharacteristics.OpenAdapterCompleteHandler = RWanNdisOpenAdapterComplete;
  80. RWanNdisProtocolCharacteristics.CloseAdapterCompleteHandler = RWanNdisCloseAdapterComplete;
  81. RWanNdisProtocolCharacteristics.SendCompleteHandler = RWanNdisSendComplete;
  82. RWanNdisProtocolCharacteristics.TransferDataCompleteHandler = RWanNdisTransferDataComplete;
  83. RWanNdisProtocolCharacteristics.ResetCompleteHandler = RWanNdisResetComplete;
  84. RWanNdisProtocolCharacteristics.RequestCompleteHandler = RWanNdisRequestComplete;
  85. RWanNdisProtocolCharacteristics.ReceiveHandler = RWanNdisReceive;
  86. RWanNdisProtocolCharacteristics.ReceiveCompleteHandler = RWanNdisReceiveComplete;
  87. RWanNdisProtocolCharacteristics.StatusHandler = RWanNdisStatus;
  88. RWanNdisProtocolCharacteristics.StatusCompleteHandler = RWanNdisStatusComplete;
  89. NdisInitUnicodeString(
  90. &RWanNdisProtocolCharacteristics.Name,
  91. RWAN_NAME
  92. );
  93. RWanNdisProtocolCharacteristics.ReceivePacketHandler = RWanNdisReceivePacket;
  94. RWanNdisProtocolCharacteristics.BindAdapterHandler = RWanNdisBindAdapter;
  95. RWanNdisProtocolCharacteristics.PnPEventHandler = RWanNdisPnPEvent;
  96. RWanNdisProtocolCharacteristics.UnbindAdapterHandler = RWanNdisUnbindAdapter;
  97. RWanNdisProtocolCharacteristics.UnloadHandler = (UNLOAD_PROTOCOL_HANDLER)RWanUnloadProtocol;
  98. #ifdef _PNP_POWER_
  99. RWanNdisProtocolCharacteristics.PnpEventHandler = RWanNdisPnPEvent;
  100. #endif // _PNP_POWER_
  101. RWanNdisProtocolCharacteristics.CoSendCompleteHandler = RWanNdisCoSendComplete;
  102. RWanNdisProtocolCharacteristics.CoStatusHandler = RWanNdisCoStatus;
  103. RWanNdisProtocolCharacteristics.CoReceivePacketHandler = RWanNdisCoReceivePacket;
  104. #if 0
  105. RWanNdisProtocolCharacteristics.CoRequestHandler = RWanNdisCoRequest;
  106. RWanNdisProtocolCharacteristics.CoRequestCompleteHandler = RWanNdisCoRequestComplete;
  107. #endif
  108. RWanNdisProtocolCharacteristics.CoAfRegisterNotifyHandler = RWanNdisAfRegisterNotify;
  109. RWAN_ZERO_MEM(&RWanNdisClientCharacteristics, sizeof(RWanNdisClientCharacteristics));
  110. RWanNdisClientCharacteristics.MajorVersion = RWAN_NDIS_MAJOR_VERSION;
  111. RWanNdisClientCharacteristics.MinorVersion = RWAN_NDIS_MINOR_VERSION;
  112. RWanNdisClientCharacteristics.ClCreateVcHandler = RWanNdisCreateVc;
  113. RWanNdisClientCharacteristics.ClDeleteVcHandler = RWanNdisDeleteVc;
  114. RWanNdisClientCharacteristics.ClOpenAfCompleteHandler = RWanNdisOpenAddressFamilyComplete;
  115. RWanNdisClientCharacteristics.ClCloseAfCompleteHandler = RWanNdisCloseAddressFamilyComplete;
  116. RWanNdisClientCharacteristics.ClRegisterSapCompleteHandler = RWanNdisRegisterSapComplete;
  117. RWanNdisClientCharacteristics.ClDeregisterSapCompleteHandler = RWanNdisDeregisterSapComplete;
  118. RWanNdisClientCharacteristics.ClMakeCallCompleteHandler = RWanNdisMakeCallComplete;
  119. RWanNdisClientCharacteristics.ClModifyCallQoSCompleteHandler = RWanNdisModifyQoSComplete;
  120. RWanNdisClientCharacteristics.ClCloseCallCompleteHandler = RWanNdisCloseCallComplete;
  121. RWanNdisClientCharacteristics.ClAddPartyCompleteHandler = RWanNdisAddPartyComplete;
  122. RWanNdisClientCharacteristics.ClDropPartyCompleteHandler = RWanNdisDropPartyComplete;
  123. RWanNdisClientCharacteristics.ClIncomingCallHandler = RWanNdisIncomingCall;
  124. RWanNdisClientCharacteristics.ClIncomingCallQoSChangeHandler = (CL_INCOMING_CALL_QOS_CHANGE_HANDLER)NULL;
  125. RWanNdisClientCharacteristics.ClIncomingCloseCallHandler = RWanNdisIncomingCloseCall;
  126. RWanNdisClientCharacteristics.ClIncomingDropPartyHandler = RWanNdisIncomingDropParty;
  127. RWanNdisClientCharacteristics.ClCallConnectedHandler = RWanNdisCallConnected;
  128. #if 1
  129. RWanNdisClientCharacteristics.ClRequestHandler = RWanNdisCoRequest;
  130. RWanNdisClientCharacteristics.ClRequestCompleteHandler = RWanNdisCoRequestComplete;
  131. #endif
  132. NdisRegisterProtocol(
  133. &Status,
  134. &(pRWanGlobal->ProtocolHandle),
  135. &RWanNdisProtocolCharacteristics,
  136. sizeof(RWanNdisProtocolCharacteristics)
  137. );
  138. if (Status != NDIS_STATUS_SUCCESS)
  139. {
  140. return (Status);
  141. }
  142. #if DBG
  143. if (RWanSkipAll)
  144. {
  145. RWANDEBUGP(DL_FATAL, DC_WILDCARD,
  146. ("Aborting DriverEntry\n"));
  147. NdisDeregisterProtocol(
  148. &Status,
  149. pRWanGlobal->ProtocolHandle
  150. );
  151. return (STATUS_UNSUCCESSFUL);
  152. }
  153. #endif // DBG
  154. //
  155. // Tell all media-specific modules to initialize.
  156. //
  157. RWanStatus = RWanInitMediaSpecific();
  158. if (RWanStatus != RWAN_STATUS_SUCCESS)
  159. {
  160. NdisDeregisterProtocol(
  161. &Status,
  162. pRWanGlobal->ProtocolHandle
  163. );
  164. return (STATUS_UNSUCCESSFUL);
  165. }
  166. #if !BINARY_COMPATIBLE
  167. //
  168. // Initialize the Driver Object.
  169. //
  170. pDriverObject->DriverUnload = RWanUnload;
  171. pDriverObject->FastIoDispatch = NULL;
  172. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
  173. {
  174. pDriverObject->MajorFunction[i] = RWanDispatch;
  175. }
  176. pDriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
  177. RWanDispatchInternalDeviceControl;
  178. #endif // !BINARY_COMPATIBLE
  179. return (STATUS_SUCCESS);
  180. }
  181. VOID
  182. RWanUnload(
  183. IN PDRIVER_OBJECT pDriverObject
  184. )
  185. /*++
  186. Routine Description:
  187. This is called by the system prior to unloading us. Undo everything
  188. we did in DriverEntry.
  189. Arguments:
  190. pDriverObject - Pointer to the driver object representing us.
  191. Return Value:
  192. None
  193. --*/
  194. {
  195. #if DBG
  196. RWanDebugLevel = DL_EXTRA_LOUD;
  197. RWanDebugComp = DC_WILDCARD;
  198. #endif
  199. RWANDEBUGP(DC_DISPATCH, DL_INFO,
  200. ("RWanUnload entered: RWanGlobals at %p\n", &RWanGlobals));
  201. RWanUnloadProtocol();
  202. RWANDEBUGP(DC_DISPATCH, DL_INFO,
  203. ("RWanUnload exiting\n"));
  204. }
  205. VOID
  206. RWanUnloadProtocol(
  207. VOID
  208. )
  209. /*++
  210. Routine Description:
  211. Unloads the Raw WAN protocol module. We unbind from all adapters,
  212. and shut down all media specific modules.
  213. Arguments:
  214. None
  215. Return Value:
  216. None
  217. --*/
  218. {
  219. NDIS_STATUS Status;
  220. PRWAN_NDIS_ADAPTER pAdapter;
  221. #if DBG
  222. RWAN_IRQL EntryIrq, ExitIrq;
  223. #endif // DBG
  224. RWAN_GET_ENTRY_IRQL(EntryIrq);
  225. RWAN_ACQUIRE_GLOBAL_LOCK();
  226. if (pRWanGlobal->UnloadDone)
  227. {
  228. RWANDEBUGP(DL_INFO, DC_WILDCARD,
  229. ("UnloadProtocol: already done!\n"));
  230. RWAN_RELEASE_GLOBAL_LOCK();
  231. return;
  232. }
  233. pRWanGlobal->UnloadDone = TRUE;
  234. RWAN_RELEASE_GLOBAL_LOCK();
  235. RWAN_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  236. RWANDEBUGP(DL_FATAL, DC_DISPATCH,
  237. ("RWanUnloadProtocol: will deregister protocol now\n"));
  238. NdisDeregisterProtocol(
  239. &Status,
  240. pRWanGlobal->ProtocolHandle
  241. );
  242. RWANDEBUGP(DL_FATAL, DC_DISPATCH,
  243. ("UnloadProtocol: dereg protocol done\n"));
  244. RWanDeinitGlobals();
  245. RWAN_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  246. RWanShutdownMediaSpecific();
  247. RWAN_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  248. #if DBG
  249. RWanAuditShutdown();
  250. #endif // DBG
  251. RWAN_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  252. }
  253. NTSTATUS
  254. RWanDispatch(
  255. IN PDEVICE_OBJECT pDeviceObject,
  256. IN PIRP pIrp
  257. )
  258. /*++
  259. Routine Description:
  260. System entry point for all IRPs dispatched to Raw WAN device objects.
  261. Arguments:
  262. pDeviceObject - Points to a device object created by RawWan. This
  263. device object identifies a supported Winsock 2 triple
  264. <Address Family, Type, Proto>.
  265. pIrp - Pointer to the IRP
  266. Return Value:
  267. NTSTATUS - STATUS_SUCCESS for immediate requests (such as create) that
  268. we successfully process, STATUS_PENDING for queued IRPs, and STATUS_XXX
  269. error codes for any failures.
  270. --*/
  271. {
  272. PIO_STACK_LOCATION pIrpSp;
  273. NTSTATUS Status;
  274. #if DBG
  275. RWAN_IRQL EntryIrq, ExitIrq;
  276. #endif // DBG
  277. RWAN_GET_ENTRY_IRQL(EntryIrq);
  278. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  279. pIrp->IoStatus.Information = 0;
  280. RWAN_ASSERT(pIrpSp->MajorFunction != IRP_MJ_INTERNAL_DEVICE_CONTROL);
  281. switch (pIrpSp->MajorFunction)
  282. {
  283. case IRP_MJ_CREATE:
  284. Status = RWanCreate(pDeviceObject, pIrp, pIrpSp);
  285. break;
  286. case IRP_MJ_CLEANUP:
  287. Status = RWanCleanup(pDeviceObject, pIrp, pIrpSp);
  288. break;
  289. case IRP_MJ_CLOSE:
  290. Status = RWanClose(pDeviceObject, pIrp, pIrpSp);
  291. break;
  292. case IRP_MJ_DEVICE_CONTROL:
  293. Status = TdiMapUserRequest(pDeviceObject, pIrp, pIrpSp);
  294. //
  295. // TBD - get rid of the call to TdiMapUserRequest - AFD will be
  296. // fixed so that we shouldn't see TDI commands come this way.
  297. //
  298. if (Status == STATUS_SUCCESS)
  299. {
  300. if (pIrpSp->MinorFunction == TDI_ASSOCIATE_ADDRESS ||
  301. pIrpSp->MinorFunction == TDI_DISASSOCIATE_ADDRESS)
  302. {
  303. return (RWanDispatchInternalDeviceControl(pDeviceObject, pIrp));
  304. }
  305. else
  306. {
  307. Status = STATUS_ACCESS_DENIED;
  308. }
  309. }
  310. else
  311. {
  312. return (RWanDispatchPrivateDeviceControl(pIrp, pIrpSp));
  313. }
  314. break;
  315. case IRP_MJ_READ:
  316. case IRP_MJ_WRITE:
  317. default:
  318. RWANDEBUGP(DL_WARN, DC_DISPATCH,
  319. ("RWanDispatch: Unknown MajorFunction x%x\n", pIrpSp->MajorFunction));
  320. Status = STATUS_INVALID_DEVICE_REQUEST;
  321. break;
  322. }
  323. RWAN_ASSERT(Status != TDI_PENDING);
  324. RWAN_COMPLETE_IRP(pIrp, Status, 0);
  325. RWANDEBUGP(DL_VERY_LOUD, DC_DISPATCH,
  326. ("RWanDispatch: pIrp %p, MajorFunc %d, returning Status x%x, Info %d\n",
  327. pIrp, pIrpSp->MajorFunction, Status, pIrp->IoStatus.Information));
  328. RWAN_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  329. return (Status);
  330. }
  331. NTSTATUS
  332. RWanCreate(
  333. IN PDEVICE_OBJECT pDeviceObject,
  334. IN PIRP pIrp,
  335. PIO_STACK_LOCATION pIrpSp
  336. )
  337. /*++
  338. Routine Description:
  339. This is called when a TDI client calls CreateFile. We allocate an
  340. ENDPOINT structure as our context for this endpoint. Based on
  341. parameters in the IRP, this is either an Address object, Connection
  342. object, or a Control channel.
  343. Arguments:
  344. pDeviceObject - Identifies the protocol being CreateFile'd
  345. pIrp - Pointer to IRP
  346. pIrpSp - IRP Stack location
  347. Return Value:
  348. NTSTATUS - STATUS_SUCCESS if we create the endpoint successfully,
  349. STATUS_INSUFFICIENT_RESOURCES if we fail to allocate, and
  350. STATUS_INVALID_PARAMETER if we find any parameter incorrect.
  351. --*/
  352. {
  353. NTSTATUS Status;
  354. FILE_FULL_EA_INFORMATION * pEa;
  355. FILE_FULL_EA_INFORMATION UNALIGNED * pTargetEa;
  356. //
  357. // Device being accessed.
  358. //
  359. PRWAN_DEVICE_OBJECT pRWanDevice;
  360. //
  361. // Endpoint to represent this object creation.
  362. //
  363. PRWAN_ENDPOINT pEndpoint;
  364. //
  365. // TDI Request to be passed down to our TDI layer.
  366. //
  367. TDI_REQUEST TdiRequest;
  368. //
  369. // Parameters to be passed down to our TDI layer.
  370. //
  371. UINT Protocol;
  372. UCHAR OptionsBuffer[3];
  373. PUCHAR pOptions;
  374. PAGED_CODE();
  375. //
  376. // Initialize.
  377. //
  378. pEndpoint = NULL_PRWAN_ENDPOINT;
  379. do
  380. {
  381. //
  382. // Locate the TDI Protocol being opened.
  383. //
  384. pRWanDevice = *(PRWAN_DEVICE_OBJECT *)(pDeviceObject->DeviceExtension);
  385. if (pRWanDevice == NULL)
  386. {
  387. Status = STATUS_NO_SUCH_DEVICE;
  388. break;
  389. }
  390. //
  391. // Allocate and initialize an Endpoint to represent
  392. // this newly created object.
  393. //
  394. RWAN_ALLOC_MEM(pEndpoint, RWAN_ENDPOINT, sizeof(RWAN_ENDPOINT));
  395. if (pEndpoint == NULL_PRWAN_ENDPOINT)
  396. {
  397. Status = STATUS_INSUFFICIENT_RESOURCES;
  398. break;
  399. }
  400. RWAN_ZERO_MEM(pEndpoint, sizeof(RWAN_ENDPOINT));
  401. RWAN_SET_SIGNATURE(pEndpoint, nep);
  402. pEndpoint->RefCount = 1;
  403. pEndpoint->bCancelIrps = FALSE;
  404. KeInitializeEvent(&pEndpoint->CleanupEvent, SynchronizationEvent, FALSE);
  405. pEndpoint->pProtocol = pRWanDevice->pProtocol;
  406. RWAN_EP_DBGLOG_SET_SIGNATURE(pEndpoint);
  407. pEa = (PFILE_FULL_EA_INFORMATION)pIrp->AssociatedIrp.SystemBuffer;
  408. //
  409. // See if this is a Control Channel.
  410. //
  411. if (!pEa)
  412. {
  413. RWANDEBUGP(DL_LOUD, DC_DISPATCH,
  414. ("RWanCreate: pIrp %p, File obj %p, Control Channel\n",
  415. pIrp, pIrpSp->FileObject));
  416. RWAN_ASSERT(pRWanDevice->pProtocol);
  417. pEndpoint->Handle.ControlChannel = pRWanDevice->pProtocol;
  418. pIrpSp->FileObject->FsContext = pEndpoint;
  419. pIrpSp->FileObject->FsContext2 = (PVOID)TDI_CONTROL_CHANNEL_FILE;
  420. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'CCrC', 0, 0);
  421. Status = STATUS_SUCCESS;
  422. break;
  423. }
  424. //
  425. // See if this is an Address Object.
  426. //
  427. pTargetEa = RWanFindEa(
  428. pEa,
  429. TdiTransportAddress,
  430. TDI_TRANSPORT_ADDRESS_LENGTH
  431. );
  432. if (pTargetEa != NULL)
  433. {
  434. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'OArC', 0, 0);
  435. if (pTargetEa->EaValueLength < sizeof(TRANSPORT_ADDRESS))
  436. {
  437. Status = STATUS_INVALID_PARAMETER;
  438. break;
  439. }
  440. if (!pRWanDevice->pProtocol->bAllowAddressObjects)
  441. {
  442. Status = STATUS_INVALID_DEVICE_REQUEST;
  443. break;
  444. }
  445. Protocol = pRWanDevice->pProtocol->SockProtocol;
  446. pOptions = OptionsBuffer;
  447. if ((pIrpSp->Parameters.Create.ShareAccess & FILE_SHARE_READ) ||
  448. (pIrpSp->Parameters.Create.ShareAccess & FILE_SHARE_WRITE))
  449. {
  450. *pOptions = TDI_ADDRESS_OPTION_REUSE;
  451. pOptions++;
  452. }
  453. *pOptions = TDI_OPTION_EOL;
  454. //
  455. // Call our TDI entry point.
  456. //
  457. Status = RWanTdiOpenAddress(
  458. &TdiRequest,
  459. (TRANSPORT_ADDRESS UNALIGNED *)
  460. &(pTargetEa->EaName[pTargetEa->EaNameLength + 1]),
  461. pTargetEa->EaValueLength,
  462. Protocol,
  463. OptionsBuffer
  464. );
  465. if (NT_SUCCESS(Status))
  466. {
  467. pEndpoint->Handle.AddressHandle = TdiRequest.Handle.AddressHandle;
  468. pIrpSp->FileObject->FsContext = pEndpoint;
  469. pIrpSp->FileObject->FsContext2 = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
  470. }
  471. break;
  472. }
  473. //
  474. // See if this is a Connection Object.
  475. //
  476. pTargetEa = RWanFindEa(
  477. pEa,
  478. TdiConnectionContext,
  479. TDI_CONNECTION_CONTEXT_LENGTH
  480. );
  481. if (pTargetEa != NULL)
  482. {
  483. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'OCrC', 0, 0);
  484. if (pTargetEa->EaValueLength < sizeof(CONNECTION_CONTEXT))
  485. {
  486. Status = STATUS_INVALID_PARAMETER;
  487. break;
  488. }
  489. if (!pRWanDevice->pProtocol->bAllowConnObjects)
  490. {
  491. Status = STATUS_INVALID_DEVICE_REQUEST;
  492. break;
  493. }
  494. //
  495. // Call our TDI entry point for opening a Connection object.
  496. //
  497. Status = RWanTdiOpenConnection(
  498. &TdiRequest,
  499. *((CONNECTION_CONTEXT UNALIGNED *)
  500. &(pTargetEa->EaName[pTargetEa->EaNameLength + 1]))
  501. );
  502. if (NT_SUCCESS(Status))
  503. {
  504. #if DBG
  505. pEndpoint->pConnObject = RWanTdiDbgGetConnObject(
  506. TdiRequest.Handle.ConnectionContext
  507. );
  508. #endif
  509. pEndpoint->Handle.ConnectionContext = TdiRequest.Handle.ConnectionContext;
  510. pIrpSp->FileObject->FsContext = pEndpoint;
  511. pIrpSp->FileObject->FsContext2 = (PVOID)TDI_CONNECTION_FILE;
  512. }
  513. break;
  514. }
  515. Status = STATUS_INVALID_DEVICE_REQUEST;
  516. break;
  517. }
  518. while (FALSE);
  519. if (Status != STATUS_SUCCESS)
  520. {
  521. //
  522. // Clean up.
  523. //
  524. if (pEndpoint != NULL)
  525. {
  526. RWAN_FREE_MEM(pEndpoint);
  527. pEndpoint = NULL;
  528. }
  529. }
  530. RWANDEBUGP(DL_VERY_LOUD, DC_DISPATCH,
  531. ("RWanCreate: pIrp %p, pEndpoint %p, Status x%x\n",
  532. pIrp, pEndpoint, Status));
  533. return (Status);
  534. }
  535. NTSTATUS
  536. RWanCleanup(
  537. IN PDEVICE_OBJECT pDeviceObject,
  538. IN PIRP pIrp,
  539. IN PIO_STACK_LOCATION pIrpSp
  540. )
  541. /*++
  542. Routine Description:
  543. Called to process an MJ_CLEANUP IRP. All outstanding IRPs are cancelled
  544. by calling the appropriate close routine for the object.
  545. We block until all outstanding IRPs are completed.
  546. Arguments:
  547. pDeviceObject - Not used
  548. pIrp - Pointer to IRP
  549. pIrpSp - IRP Stack location
  550. Return Value:
  551. NTSTATUS - this is the final clean-up status.
  552. --*/
  553. {
  554. RWAN_IRQL OldIrql;
  555. PIRP pCancelIrp;
  556. PRWAN_ENDPOINT pEndpoint;
  557. TDI_REQUEST TdiRequest;
  558. NTSTATUS Status;
  559. UNREFERENCED_PARAMETER(pDeviceObject);
  560. pEndpoint = (PRWAN_ENDPOINT) pIrpSp->FileObject->FsContext;
  561. RWAN_STRUCT_ASSERT(pEndpoint, nep);
  562. IoAcquireCancelSpinLock(&OldIrql);
  563. pEndpoint->bCancelIrps = TRUE;
  564. KeResetEvent(&(pEndpoint->CleanupEvent));
  565. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'ealC', pIrp, pEndpoint->RefCount);
  566. IoReleaseCancelSpinLock(OldIrql);
  567. //
  568. // Prepare a Close request for the TDI layer.
  569. //
  570. TdiRequest.RequestNotifyObject = RWanCloseObjectComplete;
  571. TdiRequest.RequestContext = pIrp;
  572. switch ((INT)PtrToUint(pIrpSp->FileObject->FsContext2))
  573. {
  574. case TDI_TRANSPORT_ADDRESS_FILE:
  575. TdiRequest.Handle.AddressHandle = pEndpoint->Handle.AddressHandle;
  576. Status = RWanTdiCloseAddress(&TdiRequest);
  577. break;
  578. case TDI_CONNECTION_FILE:
  579. TdiRequest.Handle.ConnectionContext = pEndpoint->Handle.ConnectionContext;
  580. Status = RWanTdiCloseConnection(&TdiRequest);
  581. break;
  582. case TDI_CONTROL_CHANNEL_FILE:
  583. Status = STATUS_SUCCESS;
  584. break;
  585. default:
  586. RWAN_ASSERT(FALSE);
  587. IoAcquireCancelSpinLock(&OldIrql);
  588. pEndpoint->bCancelIrps = FALSE;
  589. IoReleaseCancelSpinLock(OldIrql);
  590. return (STATUS_INVALID_PARAMETER);
  591. }
  592. if (Status != TDI_PENDING)
  593. {
  594. RWanCloseObjectComplete(pIrp, Status, 0);
  595. }
  596. //
  597. // Wait until all IRPs are completed.
  598. //
  599. Status = KeWaitForSingleObject(
  600. &(pEndpoint->CleanupEvent),
  601. UserRequest,
  602. KernelMode,
  603. FALSE,
  604. NULL
  605. );
  606. RWAN_ASSERT(NT_SUCCESS(Status));
  607. RWANDEBUGP(DL_VERY_LOUD, DC_DISPATCH,
  608. ("RWanCleanup: pIrp %p, Context2 %d, pEndpoint %p, returning Status x%x\n",
  609. pIrp,
  610. (INT)PtrToUint(pIrpSp->FileObject->FsContext2),
  611. pEndpoint,
  612. pIrp->IoStatus.Status));
  613. return (pIrp->IoStatus.Status);
  614. }
  615. NTSTATUS
  616. RWanClose(
  617. IN PDEVICE_OBJECT pDeviceObject,
  618. IN PIRP pIrp,
  619. IN PIO_STACK_LOCATION pIrpSp
  620. )
  621. /*++
  622. Routine Description:
  623. Called to destroy an endpoint that was created via MJ_CREATE.
  624. We'd have already processed and completed an MJ_CLEANUP,
  625. meaning that there would be no pending IRPs on this endpoint.
  626. All we need to do is deallocate the endpoint.
  627. Arguments:
  628. pDeviceObject - Identifies the protocol (not used)
  629. pIrp - Pointer to IRP
  630. pIrpSp - IRP Stack location
  631. Return Value:
  632. NT_STATUS - always STATUS_SUCCESS
  633. --*/
  634. {
  635. PRWAN_ENDPOINT pEndpoint;
  636. KIRQL OldIrql;
  637. UNREFERENCED_PARAMETER(pDeviceObject);
  638. pEndpoint = (PRWAN_ENDPOINT) pIrpSp->FileObject->FsContext;
  639. RWAN_STRUCT_ASSERT(pEndpoint, nep);
  640. RWANDEBUGP(DL_LOUD, DC_DISPATCH,
  641. ("RWanClose: pIrp %p, pEndpoint %p\n", pIrp, pEndpoint));
  642. RWAN_FREE_MEM(pEndpoint);
  643. return (STATUS_SUCCESS);
  644. }
  645. NTSTATUS
  646. RWanDispatchInternalDeviceControl(
  647. IN PDEVICE_OBJECT pDeviceObject,
  648. IN PIRP pIrp
  649. )
  650. /*++
  651. Routine Description:
  652. Called to handle MJ_DEVICE_CONTROL IRPs sent to us. These IRPs
  653. carry TDI primitives (e.g. CONNECT, DISCONNECT, SEND, RECEIVE).
  654. We call the appropriate TDI routine to handle the specified
  655. primitive.
  656. Arguments:
  657. pDeviceObject - Identifies the protocol (Not used here)
  658. pIrp - Pointer to IRP
  659. Return Value:
  660. NTSTATUS - this is STATUS_PENDING if the IRP was successfully
  661. queued for processing, STATUS_NOT_IMPLEMENTED for unsupported
  662. TDI commands, and STATUS_INVALID_DEVICE_REQUEST for unknown
  663. commands.
  664. --*/
  665. {
  666. PRWAN_ENDPOINT pEndpoint;
  667. KIRQL OldIrql;
  668. PIO_STACK_LOCATION pIrpSp;
  669. NTSTATUS Status;
  670. BOOLEAN bDone;
  671. #if DBG
  672. RWAN_IRQL EntryIrq, ExitIrq;
  673. #endif // DBG
  674. RWAN_GET_ENTRY_IRQL(EntryIrq);
  675. UNREFERENCED_PARAMETER(pDeviceObject);
  676. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  677. pEndpoint = (PRWAN_ENDPOINT) pIrpSp->FileObject->FsContext;
  678. RWAN_STRUCT_ASSERT(pEndpoint, nep);
  679. RWANDEBUGP(DL_VERY_LOUD, DC_DISPATCH,
  680. ("RWanDispatchInternalDevCtl: pIrp %p, pIrpSp %p, pEndpoint %p, Ctx2 %d\n",
  681. pIrp, pIrpSp, pEndpoint,
  682. (INT)PtrToUint(pIrpSp->FileObject->FsContext2)));
  683. do
  684. {
  685. if (((INT)PtrToUint(pIrpSp->FileObject->FsContext2)) == TDI_CONNECTION_FILE)
  686. {
  687. if (pIrpSp->MinorFunction == TDI_SEND)
  688. {
  689. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'dneS', 0, 0);
  690. Status = RWanSendData(pIrp, pIrpSp);
  691. break;
  692. }
  693. if (pIrpSp->MinorFunction == TDI_RECEIVE)
  694. {
  695. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'vceR', 0, 0);
  696. Status = RWanReceiveData(pIrp, pIrpSp);
  697. break;
  698. }
  699. bDone = TRUE;
  700. switch (pIrpSp->MinorFunction)
  701. {
  702. case TDI_ASSOCIATE_ADDRESS:
  703. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'AssA', pIrp, pEndpoint->RefCount);
  704. Status = RWanAssociateAddress(pIrp, pIrpSp);
  705. RWAN_COMPLETE_IRP(pIrp, Status, 0);
  706. break;
  707. case TDI_DISASSOCIATE_ADDRESS:
  708. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'AsiD', pIrp, pEndpoint->RefCount);
  709. Status = RWanDisassociateAddress(pIrp, pIrpSp);
  710. break;
  711. case TDI_CONNECT:
  712. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'nnoC', pIrp, pEndpoint->RefCount);
  713. Status = RWanConnect(pIrp, pIrpSp);
  714. break;
  715. case TDI_DISCONNECT:
  716. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'csiD', pIrp, pEndpoint->RefCount);
  717. Status = RWanDisconnect(pIrp, pIrpSp);
  718. break;
  719. case TDI_LISTEN:
  720. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'tsiL', pIrp, pEndpoint->RefCount);
  721. Status = RWanListen(pIrp, pIrpSp);
  722. break;
  723. case TDI_ACCEPT:
  724. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'eccA', pIrp, pEndpoint->RefCount);
  725. Status = RWanAccept(pIrp, pIrpSp);
  726. break;
  727. default:
  728. bDone = FALSE;
  729. #if 0
  730. // Allow TDI_QUERY_INFORMATION on Conn endpoints to fall through
  731. RWANDEBUGP(DL_WARN, DC_DISPATCH,
  732. ("RWanDispatchInternalDevCtl: pIrp %p, pIrpSp %p, unknown func x%x\n",
  733. pIrp, pIrpSp, pIrpSp->MinorFunction));
  734. Status = STATUS_INVALID_DEVICE_REQUEST;
  735. RWAN_COMPLETE_IRP(pIrp, Status, 0);
  736. #else
  737. bDone = FALSE;
  738. #endif
  739. break;
  740. }
  741. if (bDone)
  742. {
  743. break;
  744. }
  745. //
  746. // else fall through - may be something common to all types
  747. // of endpoints.
  748. //
  749. }
  750. else if (((INT)PtrToUint(pIrpSp->FileObject->FsContext2)) == TDI_TRANSPORT_ADDRESS_FILE)
  751. {
  752. if (pIrpSp->MinorFunction == TDI_SET_EVENT_HANDLER)
  753. {
  754. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'EteS', 0, 0);
  755. Status = RWanSetEventHandler(pIrp, pIrpSp);
  756. RWAN_COMPLETE_IRP(pIrp, Status, 0);
  757. break;
  758. }
  759. }
  760. RWAN_ASSERT(
  761. (((INT)PtrToUint(pIrpSp->FileObject->FsContext2)) == TDI_TRANSPORT_ADDRESS_FILE)
  762. ||
  763. (((INT)PtrToUint(pIrpSp->FileObject->FsContext2)) == TDI_CONNECTION_FILE)
  764. ||
  765. (((INT)PtrToUint(pIrpSp->FileObject->FsContext2)) == TDI_CONTROL_CHANNEL_FILE)
  766. );
  767. //
  768. // Check if this is a function common to all types of endpoints.
  769. //
  770. switch (pIrpSp->MinorFunction)
  771. {
  772. case TDI_QUERY_INFORMATION:
  773. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'IyrQ', 0, 0);
  774. Status = RWanQueryInformation(pIrp, pIrpSp);
  775. break;
  776. case TDI_SET_INFORMATION:
  777. case TDI_ACTION:
  778. RWANDEBUGP(DL_INFO, DC_DISPATCH,
  779. ("RWanDispatchInternalDevCtl: SET_INFO/ACTION not supported\n"));
  780. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'IteS', 0, 0);
  781. Status = STATUS_NOT_IMPLEMENTED;
  782. RWAN_COMPLETE_IRP(pIrp, Status, 0);
  783. break;
  784. default:
  785. Status = STATUS_INVALID_DEVICE_REQUEST;
  786. RWAN_COMPLETE_IRP(pIrp, Status, 0);
  787. break;
  788. }
  789. break;
  790. }
  791. while (FALSE);
  792. RWANDEBUGP(DL_VERY_LOUD, DC_DISPATCH,
  793. ("RWanDispatchInternalDevCtl: pIrp %p, pIrpSp %p, Maj/Min %d/%d, Status x%x\n",
  794. pIrp, pIrpSp, pIrpSp->MajorFunction, pIrpSp->MinorFunction, Status));
  795. RWAN_CHECK_EXIT_IRQL(EntryIrq, ExitIrq);
  796. return (Status);
  797. }
  798. NTSTATUS
  799. RWanDispatchPrivateDeviceControl(
  800. IN PIRP pIrp,
  801. IN PIO_STACK_LOCATION pIrpSp
  802. )
  803. /*++
  804. Routine Description:
  805. Called to handle MJ_DEVICE_CONTROL IRPs sent to us that contain
  806. non-TDI primitives.
  807. Arguments:
  808. pIrp - Pointer to IRP
  809. pIrpSp - IRP Stack location
  810. Return Value:
  811. NTSTATUS - this is STATUS_PENDING if the IRP was successfully
  812. queued for processing, STATUS_NOT_IMPLEMENTED for unsupported
  813. commands, and STATUS_INVALID_DEVICE_REQUEST for unknown
  814. commands.
  815. --*/
  816. {
  817. PRWAN_ENDPOINT pEndpoint;
  818. KIRQL OldIrql;
  819. RWAN_STATUS RWanStatus;
  820. NTSTATUS Status;
  821. PRWAN_NDIS_AF_CHARS pAfChars;
  822. PVOID pInputBuffer;
  823. PVOID pOutputBuffer;
  824. ULONG InputBufferLength;
  825. ULONG OutputBufferLength;
  826. PAGED_CODE();
  827. pEndpoint = (PRWAN_ENDPOINT) pIrpSp->FileObject->FsContext;
  828. RWAN_STRUCT_ASSERT(pEndpoint, nep);
  829. //
  830. // Initialize.
  831. //
  832. pIrp->IoStatus.Information = 0;
  833. Status = STATUS_INVALID_DEVICE_REQUEST;
  834. //
  835. // Get some parameters from the IRP.
  836. //
  837. pInputBuffer = pIrp->AssociatedIrp.SystemBuffer;
  838. pOutputBuffer = pIrp->AssociatedIrp.SystemBuffer;
  839. InputBufferLength = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
  840. OutputBufferLength = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  841. RWANDEBUGP(DL_INFO, DC_DISPATCH,
  842. ("PrivateDevCtl: pEndpoint %p, CtlCode x%x, InBuf %p/%d, OutBuf %p/%d\n",
  843. pEndpoint,
  844. pIrpSp->Parameters.DeviceIoControl.IoControlCode,
  845. pInputBuffer,
  846. InputBufferLength,
  847. pOutputBuffer,
  848. OutputBufferLength));
  849. switch (pIrpSp->Parameters.DeviceIoControl.IoControlCode)
  850. {
  851. case IOCTL_RWAN_GENERIC_GLOBAL_QUERY:
  852. case IOCTL_RWAN_GENERIC_GLOBAL_SET:
  853. Status = STATUS_NOT_IMPLEMENTED;
  854. break;
  855. case IOCTL_RWAN_GENERIC_CONN_HANDLE_QUERY:
  856. if (((INT)PtrToUint(pIrpSp->FileObject->FsContext2)) != TDI_CONNECTION_FILE)
  857. {
  858. Status = STATUS_INVALID_DEVICE_REQUEST;
  859. break;
  860. }
  861. RWanStatus = RWanHandleGenericConnQryInfo(
  862. pEndpoint->Handle.ConnectionContext,
  863. pInputBuffer,
  864. InputBufferLength,
  865. pOutputBuffer,
  866. &OutputBufferLength
  867. );
  868. Status = RWanToNTStatus(RWanStatus);
  869. if (Status != STATUS_SUCCESS)
  870. {
  871. OutputBufferLength = 0;
  872. }
  873. break;
  874. case IOCTL_RWAN_GENERIC_ADDR_HANDLE_QUERY:
  875. case IOCTL_RWAN_GENERIC_CONN_HANDLE_SET:
  876. Status = STATUS_NOT_IMPLEMENTED;
  877. break;
  878. case IOCTL_RWAN_GENERIC_ADDR_HANDLE_SET:
  879. if (((INT)PtrToUint(pIrpSp->FileObject->FsContext2)) != TDI_TRANSPORT_ADDRESS_FILE)
  880. {
  881. Status = STATUS_INVALID_DEVICE_REQUEST;
  882. break;
  883. }
  884. RWanStatus = RWanHandleGenericAddrSetInfo(
  885. pEndpoint->Handle.AddressHandle,
  886. pInputBuffer,
  887. InputBufferLength
  888. );
  889. Status = RWanToNTStatus(RWanStatus);
  890. OutputBufferLength = 0;
  891. break;
  892. case IOCTL_RWAN_MEDIA_SPECIFIC_GLOBAL_QUERY:
  893. //
  894. // Get the media-specific module's QueryInfo handler.
  895. //
  896. pAfChars = &(pEndpoint->pProtocol->pAfInfo->AfChars);
  897. if (pAfChars->pAfSpQueryGlobalInfo != NULL)
  898. {
  899. RWanStatus = (*pAfChars->pAfSpQueryGlobalInfo)(
  900. pEndpoint->pProtocol->pAfInfo->AfSpContext,
  901. pInputBuffer,
  902. InputBufferLength,
  903. pOutputBuffer,
  904. &OutputBufferLength
  905. );
  906. Status = RWanToNTStatus(RWanStatus);
  907. if (Status != STATUS_SUCCESS)
  908. {
  909. OutputBufferLength = 0;
  910. }
  911. }
  912. else
  913. {
  914. Status = STATUS_NOT_IMPLEMENTED;
  915. }
  916. break;
  917. case IOCTL_RWAN_MEDIA_SPECIFIC_GLOBAL_SET:
  918. //
  919. // Get the media-specific module's SetInfo handler.
  920. //
  921. pAfChars = &(pEndpoint->pProtocol->pAfInfo->AfChars);
  922. if (pAfChars->pAfSpSetGlobalInfo != NULL)
  923. {
  924. RWanStatus = (*pAfChars->pAfSpSetGlobalInfo)(
  925. pEndpoint->pProtocol->pAfInfo->AfSpContext,
  926. pInputBuffer,
  927. InputBufferLength
  928. );
  929. Status = RWanToNTStatus(RWanStatus);
  930. }
  931. else
  932. {
  933. Status = STATUS_NOT_IMPLEMENTED;
  934. }
  935. OutputBufferLength = 0;
  936. break;
  937. case IOCTL_RWAN_MEDIA_SPECIFIC_CONN_HANDLE_QUERY:
  938. if ((INT)PtrToUint(pIrpSp->FileObject->FsContext2) != TDI_CONNECTION_FILE)
  939. {
  940. Status = STATUS_INVALID_DEVICE_REQUEST;
  941. break;
  942. }
  943. RWanStatus = RWanHandleMediaSpecificConnQryInfo(
  944. pEndpoint->Handle.ConnectionContext,
  945. pInputBuffer,
  946. InputBufferLength,
  947. pOutputBuffer,
  948. &OutputBufferLength
  949. );
  950. Status = RWanToNTStatus(RWanStatus);
  951. break;
  952. case IOCTL_RWAN_MEDIA_SPECIFIC_ADDR_HANDLE_QUERY:
  953. case IOCTL_RWAN_MEDIA_SPECIFIC_CONN_HANDLE_SET:
  954. Status = STATUS_NOT_IMPLEMENTED;
  955. break;
  956. case IOCTL_RWAN_MEDIA_SPECIFIC_ADDR_HANDLE_SET:
  957. if ((INT)PtrToUint(pIrpSp->FileObject->FsContext2) != TDI_TRANSPORT_ADDRESS_FILE)
  958. {
  959. Status = STATUS_INVALID_DEVICE_REQUEST;
  960. break;
  961. }
  962. RWanStatus = RWanHandleMediaSpecificAddrSetInfo(
  963. pEndpoint->Handle.AddressHandle,
  964. pInputBuffer,
  965. InputBufferLength
  966. );
  967. Status = RWanToNTStatus(RWanStatus);
  968. OutputBufferLength = 0;
  969. break;
  970. default:
  971. OutputBufferLength = 0;
  972. Status = STATUS_INVALID_DEVICE_REQUEST;
  973. break;
  974. }
  975. RWAN_ASSERT(Status != STATUS_PENDING);
  976. RWAN_COMPLETE_IRP(pIrp, Status, OutputBufferLength);
  977. return (Status);
  978. }
  979. FILE_FULL_EA_INFORMATION UNALIGNED *
  980. RWanFindEa(
  981. IN FILE_FULL_EA_INFORMATION * pStartEa,
  982. IN CHAR * pTargetName,
  983. IN USHORT TargetNameLength
  984. )
  985. /*++
  986. Routine Description:
  987. Searches for a target name in an Extended Attribute list
  988. and returns it.
  989. Arguments:
  990. pStartEa - Start of the attribute list
  991. pTargetName - Pointer to name to look for
  992. TargetNameLength- Length of name
  993. Return Value:
  994. Pointer to attribute matching the target name, if found;
  995. NULL otherwise.
  996. --*/
  997. {
  998. FILE_FULL_EA_INFORMATION UNALIGNED * pEa;
  999. FILE_FULL_EA_INFORMATION UNALIGNED * pNextEa;
  1000. BOOLEAN Found;
  1001. USHORT i;
  1002. PAGED_CODE();
  1003. pNextEa = pStartEa;
  1004. Found = FALSE;
  1005. do
  1006. {
  1007. pEa = pNextEa;
  1008. pNextEa = (FILE_FULL_EA_INFORMATION UNALIGNED *)
  1009. ((PUCHAR)pNextEa + pNextEa->NextEntryOffset);
  1010. if (pEa->EaNameLength == TargetNameLength)
  1011. {
  1012. for (i = 0; i < TargetNameLength; i++)
  1013. {
  1014. if (pEa->EaName[i] != pTargetName[i])
  1015. {
  1016. break;
  1017. }
  1018. }
  1019. if (i == TargetNameLength)
  1020. {
  1021. Found = TRUE;
  1022. break;
  1023. }
  1024. }
  1025. }
  1026. while (pEa->NextEntryOffset != 0);
  1027. return (Found? pEa: NULL);
  1028. }
  1029. NTSTATUS
  1030. RWanSendData(
  1031. IN PIRP pIrp,
  1032. IN PIO_STACK_LOCATION pIrpSp
  1033. )
  1034. /*++
  1035. Routine Description:
  1036. Convert an IRP containing a TDI_SEND request to a call to our TDI
  1037. dispatch routine for sends. We retain enough context to be able
  1038. to complete the IRP when the send completes.
  1039. Arguments:
  1040. pIrp - Pointer to IRP
  1041. pIrpSp - IRP Stack location
  1042. Return Value:
  1043. NTSTATUS - STATUS_PENDING if we managed to queue the send successfully,
  1044. STATUS_CANCELLED if the IRP was cancelled.
  1045. STATUS_SUCCESS if the send completed successfully, immediately.
  1046. --*/
  1047. {
  1048. PRWAN_ENDPOINT pEndpoint;
  1049. KIRQL OldIrql;
  1050. PTDI_REQUEST_KERNEL_SEND pSendRequest;
  1051. TDI_REQUEST TdiRequest;
  1052. NTSTATUS Status;
  1053. pEndpoint = (PRWAN_ENDPOINT) pIrpSp->FileObject->FsContext;
  1054. RWAN_STRUCT_ASSERT(pEndpoint, nep);
  1055. pSendRequest = (PTDI_REQUEST_KERNEL_SEND) &(pIrpSp->Parameters);
  1056. //
  1057. // Prepare a TDI Send request.
  1058. //
  1059. TdiRequest.Handle.ConnectionContext = pEndpoint->Handle.ConnectionContext;
  1060. TdiRequest.RequestNotifyObject = (PVOID) RWanDataRequestComplete;
  1061. TdiRequest.RequestContext = (PVOID) pIrp;
  1062. IoAcquireCancelSpinLock(&OldIrql);
  1063. if (!pIrp->Cancel)
  1064. {
  1065. //
  1066. // The IRP hasn't been cancelled. Set it up so that we are
  1067. // informed if it does get cancelled later.
  1068. //
  1069. IoMarkIrpPending(pIrp);
  1070. IoSetCancelRoutine(pIrp, RWanCancelRequest);
  1071. RWAN_INCR_EP_REF_CNT(pEndpoint, SendIncr); // Send ref
  1072. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'DneS', pIrp, pEndpoint->RefCount);
  1073. IoReleaseCancelSpinLock(OldIrql);
  1074. Status = RWanTdiSendData(
  1075. &TdiRequest,
  1076. (USHORT)pSendRequest->SendFlags,
  1077. pSendRequest->SendLength,
  1078. (PNDIS_BUFFER) pIrp->MdlAddress
  1079. );
  1080. if (Status != TDI_PENDING)
  1081. {
  1082. //
  1083. // The Send either completed immediately, or failed.
  1084. //
  1085. pIrpSp->Control &= ~SL_PENDING_RETURNED;
  1086. if (Status == TDI_SUCCESS)
  1087. {
  1088. //
  1089. // Examples of immediate successful completion:
  1090. // - A zero length send
  1091. //
  1092. RWanDataRequestComplete(pIrp, Status, pSendRequest->SendLength);
  1093. }
  1094. else
  1095. {
  1096. //
  1097. // The Send failed, could be a resource problem.
  1098. //
  1099. RWANDEBUGP(DL_INFO, DC_DATA_TX,
  1100. ("RWanSendData: pIrp %p, pEndpoint %p, TDI send fail: x%x\n",
  1101. pIrp, pEndpoint, Status));
  1102. RWanDataRequestComplete(pIrp, Status, 0);
  1103. }
  1104. }
  1105. }
  1106. else
  1107. {
  1108. //
  1109. // The IRP has been cancelled before it could reach us.
  1110. //
  1111. IoReleaseCancelSpinLock(OldIrql);
  1112. Status = STATUS_CANCELLED;
  1113. RWAN_COMPLETE_IRP(pIrp, Status, 0);
  1114. }
  1115. RWANDEBUGP(DL_LOUD, DC_DATA_TX,
  1116. ("RWanSendData: pIrp %p, pEndpoint %p, ret Status x%x\n",
  1117. pIrp, pEndpoint, Status));
  1118. return (Status);
  1119. }
  1120. NTSTATUS
  1121. RWanReceiveData(
  1122. IN PIRP pIrp,
  1123. IN PIO_STACK_LOCATION pIrpSp
  1124. )
  1125. /*++
  1126. Routine Description:
  1127. Convert an IRP containing a TDI_RECEIVE request to a call to our TDI
  1128. dispatch routine for receives. We retain enough context to be able
  1129. to complete the IRP when the receive completes.
  1130. The FileObject within the IRP refers to the connection endpoint.
  1131. Arguments:
  1132. pIrp - Pointer to IRP
  1133. pIrpSp - IRP Stack location
  1134. Return Value:
  1135. NTSTATUS - STATUS_PENDING if we managed to queue the receive successfully,
  1136. STATUS_CANCELLED if the IRP was cancelled.
  1137. --*/
  1138. {
  1139. PRWAN_ENDPOINT pEndpoint;
  1140. KIRQL OldIrql;
  1141. PTDI_REQUEST_KERNEL_RECEIVE pReceiveRequest;
  1142. TDI_REQUEST TdiRequest;
  1143. NTSTATUS Status;
  1144. pEndpoint = (PRWAN_ENDPOINT) pIrpSp->FileObject->FsContext;
  1145. RWAN_STRUCT_ASSERT(pEndpoint, nep);
  1146. pReceiveRequest = (PTDI_REQUEST_KERNEL_RECEIVE) &(pIrpSp->Parameters);
  1147. //
  1148. // Prepare a TDI Receive request.
  1149. //
  1150. TdiRequest.Handle.ConnectionContext = pEndpoint->Handle.ConnectionContext;
  1151. TdiRequest.RequestNotifyObject = (PVOID) RWanDataRequestComplete;
  1152. TdiRequest.RequestContext = (PVOID) pIrp;
  1153. IoAcquireCancelSpinLock(&OldIrql);
  1154. if (!pIrp->Cancel)
  1155. {
  1156. //
  1157. // The IRP hasn't been cancelled. Set it up so that we are
  1158. // informed if it does get cancelled later.
  1159. //
  1160. IoMarkIrpPending(pIrp);
  1161. IoSetCancelRoutine(pIrp, RWanCancelRequest);
  1162. RWAN_INCR_EP_REF_CNT(pEndpoint, RecvIncr); // Receive ref
  1163. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'DvcR', pIrp, pEndpoint->RefCount);
  1164. IoReleaseCancelSpinLock(OldIrql);
  1165. Status = RWanTdiReceive(
  1166. &TdiRequest,
  1167. (USHORT *) &(pReceiveRequest->ReceiveFlags),
  1168. &(pReceiveRequest->ReceiveLength),
  1169. (PNDIS_BUFFER) pIrp->MdlAddress
  1170. );
  1171. if (Status != TDI_PENDING)
  1172. {
  1173. //
  1174. // The Receive either completed immediately, or failed.
  1175. //
  1176. pIrpSp->Control &= ~SL_PENDING_RETURNED;
  1177. RWANDEBUGP(DL_WARN, DC_DATA_TX,
  1178. ("RWanReceiveData: pIrp %p, pEndpoint %p, TDI recv didnt pend: x%x\n",
  1179. pIrp, pEndpoint, Status));
  1180. RWanDataRequestComplete(pIrp, Status, 0);
  1181. }
  1182. }
  1183. else
  1184. {
  1185. //
  1186. // The IRP has been cancelled before it could reach us.
  1187. //
  1188. IoReleaseCancelSpinLock(OldIrql);
  1189. Status = STATUS_CANCELLED;
  1190. RWAN_COMPLETE_IRP(pIrp, Status, 0);
  1191. }
  1192. RWANDEBUGP(DL_LOUD, DC_DATA_TX,
  1193. ("RWanReceiveData: pIrp %p, pEndpoint %p, ret Status x%x\n",
  1194. pIrp, pEndpoint, Status));
  1195. return (Status);
  1196. }
  1197. NTSTATUS
  1198. RWanAssociateAddress(
  1199. IN PIRP pIrp,
  1200. IN PIO_STACK_LOCATION pIrpSp
  1201. )
  1202. /*++
  1203. Routine Description:
  1204. Converts a TDI_ASSOCIATE_ADDRESS IRP to a call to our AssociateAddress
  1205. entry point.
  1206. The FileObject in the IRP refers to the Connection Object, and the
  1207. AddressHandle field within the kernel request refers to the Address
  1208. Object.
  1209. Arguments:
  1210. pIrp - Pointer to IRP
  1211. pIrpSp - IRP Stack location
  1212. Return Value:
  1213. NTSTATUS - STATUS_SUCCESS if successful, STATUS_XXX error code otherwise.
  1214. --*/
  1215. {
  1216. PRWAN_ENDPOINT pConnEndpoint;
  1217. PRWAN_ENDPOINT pAddrEndpoint;
  1218. PTDI_REQUEST_KERNEL_ASSOCIATE pAssociateRequest;
  1219. TDI_REQUEST TdiRequest;
  1220. PFILE_OBJECT pFileObject;
  1221. NTSTATUS Status;
  1222. PAGED_CODE();
  1223. pConnEndpoint = (PRWAN_ENDPOINT) pIrpSp->FileObject->FsContext;
  1224. RWAN_STRUCT_ASSERT(pConnEndpoint, nep);
  1225. //
  1226. // Prepare a TDI Associate Request
  1227. //
  1228. TdiRequest.Handle.ConnectionContext = pConnEndpoint->Handle.ConnectionContext;
  1229. pAssociateRequest = (PTDI_REQUEST_KERNEL_ASSOCIATE) &(pIrpSp->Parameters);
  1230. //
  1231. // Reference the file corresponding to the Address object.
  1232. // This is just so that it doesn't go away while we're processing
  1233. // the Associate.
  1234. //
  1235. // The Address object is identified by its handle buried inside
  1236. // the Associate request.
  1237. //
  1238. Status = ObReferenceObjectByHandle(
  1239. pAssociateRequest->AddressHandle,
  1240. GENERIC_ALL,
  1241. *IoFileObjectType,
  1242. pIrp->RequestorMode,
  1243. &pFileObject,
  1244. NULL
  1245. );
  1246. if (NT_SUCCESS(Status) &&
  1247. (pFileObject->DeviceObject->DriverObject == pRWanGlobal->pDriverObject))
  1248. {
  1249. //
  1250. // Found the file object. See if it is an Address object.
  1251. //
  1252. if ((INT)PtrToUint(pFileObject->FsContext2) == TDI_TRANSPORT_ADDRESS_FILE)
  1253. {
  1254. //
  1255. // Get our endpoint representing this address object.
  1256. //
  1257. pAddrEndpoint = (PRWAN_ENDPOINT) pFileObject->FsContext;
  1258. RWAN_STRUCT_ASSERT(pAddrEndpoint, nep);
  1259. //
  1260. // Dispatch this to the TDI layer.
  1261. //
  1262. Status = RWanTdiAssociateAddress(
  1263. &TdiRequest,
  1264. pAddrEndpoint->Handle.AddressHandle
  1265. );
  1266. RWAN_ASSERT(Status != TDI_PENDING);
  1267. ObDereferenceObject(pFileObject);
  1268. }
  1269. else
  1270. {
  1271. ObDereferenceObject(pFileObject);
  1272. RWANDEBUGP(DC_ADDRESS, DL_WARN,
  1273. ("RWanAssociateAddress: pIrp %p, pConnEp %p, bad Context2 %d\n",
  1274. pIrp, pConnEndpoint,
  1275. (INT)PtrToUint(pFileObject->FsContext2)));
  1276. Status = STATUS_INVALID_HANDLE;
  1277. }
  1278. }
  1279. else
  1280. {
  1281. RWANDEBUGP(DL_WARN, DC_ADDRESS,
  1282. ("RWanAssociateAddress: pIrp %p, pConnEp %p, bad addr handle %p\n",
  1283. pIrp, pConnEndpoint, pAssociateRequest->AddressHandle));
  1284. //
  1285. // Clean up properly.
  1286. //
  1287. if (NT_SUCCESS(Status))
  1288. {
  1289. ObDereferenceObject(pFileObject);
  1290. Status = STATUS_INVALID_HANDLE;
  1291. }
  1292. }
  1293. RWANDEBUGP(DL_VERY_LOUD, DC_ADDRESS,
  1294. ("RWanAssociateAddress: pIrp %p, pConnEp %p, Addr Handle %p, Status x%x\n",
  1295. pIrp, pConnEndpoint, pAssociateRequest->AddressHandle, Status));
  1296. return (Status);
  1297. }
  1298. NTSTATUS
  1299. RWanDisassociateAddress(
  1300. IN PIRP pIrp,
  1301. IN PIO_STACK_LOCATION pIrpSp
  1302. )
  1303. /*++
  1304. Routine Description:
  1305. Converts a TDI_DISASSOCIATE_ADDRESS IRP to a call to our DisassociateAddress
  1306. entry point.
  1307. The FileObject in the IRP refers to the Connection Object that is
  1308. to be disassociated.
  1309. Arguments:
  1310. pIrp - Pointer to IRP
  1311. pIrpSp - IRP Stack location
  1312. Return Value:
  1313. None
  1314. --*/
  1315. {
  1316. PRWAN_ENDPOINT pConnEndpoint;
  1317. TDI_REQUEST TdiRequest;
  1318. NTSTATUS Status;
  1319. PAGED_CODE();
  1320. pConnEndpoint = (PRWAN_ENDPOINT) pIrpSp->FileObject->FsContext;
  1321. RWAN_STRUCT_ASSERT(pConnEndpoint, nep);
  1322. //
  1323. // Prepare a TDI Disassociate Request
  1324. //
  1325. TdiRequest.Handle.ConnectionContext = pConnEndpoint->Handle.ConnectionContext;
  1326. TdiRequest.RequestNotifyObject = (PVOID)RWanRequestComplete;
  1327. TdiRequest.RequestContext = (PVOID)pIrp;
  1328. Status = RWanPrepareIrpForCancel(pConnEndpoint, pIrp, RWanCancelRequest);
  1329. if (NT_SUCCESS(Status))
  1330. {
  1331. Status = RWanTdiDisassociateAddress(&TdiRequest);
  1332. if (Status != TDI_PENDING)
  1333. {
  1334. RWanRequestComplete(pIrp, Status, 0);
  1335. Status = TDI_PENDING;
  1336. }
  1337. }
  1338. RWANDEBUGP(DL_VERY_LOUD, DC_ADDRESS,
  1339. ("RWanDisassociateAddr: pIrp %p, pEndp %p, Status x%x\n",
  1340. pIrp, pConnEndpoint, Status));
  1341. return (Status);
  1342. }
  1343. NTSTATUS
  1344. RWanConnect(
  1345. IN PIRP pIrp,
  1346. IN PIO_STACK_LOCATION pIrpSp
  1347. )
  1348. /*++
  1349. Routine Description:
  1350. Convert a TDI Connect IRP to a call to our Connect entry point.
  1351. The FileObject in the IRP refers to the Connection Object on which
  1352. the outgoing call is to be placed.
  1353. Arguments:
  1354. pIrp - Pointer to IRP
  1355. pIrpSp - IRP Stack location
  1356. Return Value:
  1357. NTSTATUS - STATUS_PENDING if a call was initiated, STATUS_XXX error
  1358. code otherwise.
  1359. --*/
  1360. {
  1361. PRWAN_ENDPOINT pConnEndpoint;
  1362. TDI_REQUEST TdiRequest;
  1363. PTDI_CONNECTION_INFORMATION pRequestInformation;
  1364. PTDI_CONNECTION_INFORMATION pReturnInformation;
  1365. PTDI_REQUEST_KERNEL_CONNECT pConnectRequest;
  1366. NTSTATUS Status;
  1367. PLARGE_INTEGER pRequestTimeout;
  1368. LARGE_INTEGER MillisecondTimeout;
  1369. ULONG Remainder;
  1370. pConnEndpoint = (PRWAN_ENDPOINT) pIrpSp->FileObject->FsContext;
  1371. RWAN_STRUCT_ASSERT(pConnEndpoint, nep);
  1372. //
  1373. // Grab all parameters from the IRP.
  1374. //
  1375. pConnectRequest = (PTDI_REQUEST_KERNEL_CONNECT) &(pIrpSp->Parameters);
  1376. pRequestInformation = pConnectRequest->RequestConnectionInformation;
  1377. pReturnInformation = pConnectRequest->ReturnConnectionInformation;
  1378. //
  1379. // Prepare a TDI CONNECT Request
  1380. //
  1381. TdiRequest.Handle.ConnectionContext = pConnEndpoint->Handle.ConnectionContext;
  1382. TdiRequest.RequestNotifyObject = (PVOID)RWanRequestComplete;
  1383. TdiRequest.RequestContext = (PVOID)pIrp;
  1384. pRequestTimeout = (PLARGE_INTEGER)pConnectRequest->RequestSpecific;
  1385. if (pRequestTimeout != NULL)
  1386. {
  1387. MillisecondTimeout = RWAN_CONVERT_100NS_TO_MS(*pRequestTimeout, &Remainder);
  1388. }
  1389. else
  1390. {
  1391. MillisecondTimeout.LowPart = 0;
  1392. MillisecondTimeout.HighPart = 0;
  1393. }
  1394. Status = RWanPrepareIrpForCancel(pConnEndpoint, pIrp, RWanCancelRequest);
  1395. if (NT_SUCCESS(Status))
  1396. {
  1397. Status = RWanTdiConnect(
  1398. &TdiRequest,
  1399. ((MillisecondTimeout.LowPart != 0)?
  1400. &(MillisecondTimeout.LowPart): NULL),
  1401. pRequestInformation,
  1402. pReturnInformation
  1403. );
  1404. if (Status != TDI_PENDING)
  1405. {
  1406. RWanRequestComplete(pIrp, Status, 0);
  1407. Status = STATUS_PENDING;
  1408. }
  1409. }
  1410. RWANDEBUGP(DL_LOUD, DC_CONNECT,
  1411. ("RWanConnect: pIrp %p, pEndp %p, Status x%x\n",
  1412. pIrp, pConnEndpoint, Status));
  1413. return (Status);
  1414. }
  1415. NTSTATUS
  1416. RWanDisconnect(
  1417. IN PIRP pIrp,
  1418. IN PIO_STACK_LOCATION pIrpSp
  1419. )
  1420. /*++
  1421. Routine Description:
  1422. Convert a TDI Connect IRP to a call to our Connect entry point.
  1423. The FileObject in the IRP refers to the Connection Object hosting
  1424. the connection to be disconnected.
  1425. Arguments:
  1426. pIrp - Pointer to IRP
  1427. pIrpSp - IRP Stack location
  1428. Return Value:
  1429. NTSTATUS - STATUS_PENDING if a disconnect was initiated, STATUS_XXX error
  1430. code otherwise.
  1431. --*/
  1432. {
  1433. PRWAN_ENDPOINT pConnEndpoint;
  1434. TDI_REQUEST TdiRequest;
  1435. PTDI_CONNECTION_INFORMATION pRequestInformation;
  1436. PTDI_CONNECTION_INFORMATION pReturnInformation;
  1437. PTDI_REQUEST_KERNEL_DISCONNECT pDisconnectRequest;
  1438. NTSTATUS Status;
  1439. PLARGE_INTEGER pRequestTimeout;
  1440. LARGE_INTEGER MillisecondTimeout;
  1441. BOOLEAN bAbortiveDisconnect;
  1442. pConnEndpoint = (PRWAN_ENDPOINT) pIrpSp->FileObject->FsContext;
  1443. RWAN_STRUCT_ASSERT(pConnEndpoint, nep);
  1444. //
  1445. // Grab all parameters from the IRP.
  1446. //
  1447. pDisconnectRequest = (PTDI_REQUEST_KERNEL_DISCONNECT) &(pIrpSp->Parameters);
  1448. pRequestInformation = pDisconnectRequest->RequestConnectionInformation;
  1449. pReturnInformation = pDisconnectRequest->ReturnConnectionInformation;
  1450. //
  1451. // Prepare a TDI DISCONNECT Request
  1452. //
  1453. TdiRequest.Handle.ConnectionContext = pConnEndpoint->Handle.ConnectionContext;
  1454. TdiRequest.RequestContext = (PVOID)pIrp;
  1455. pRequestTimeout = (PLARGE_INTEGER)pDisconnectRequest->RequestSpecific;
  1456. if (pRequestTimeout != NULL)
  1457. {
  1458. ULONG Remainder;
  1459. MillisecondTimeout = RWAN_CONVERT_100NS_TO_MS(*pRequestTimeout, &Remainder);
  1460. #if 0
  1461. if ((pRequestTimeout->LowPart == -1) &&
  1462. (pRequestTimeout->HighPart == -1))
  1463. {
  1464. MillisecondTimeout.LowPart = pRequestTimeout->LowPart;
  1465. MillisecondTimeout.HighPart = 0;
  1466. }
  1467. else
  1468. {
  1469. MillisecondTimeout.QuadPart = -((*pRequestTimeout).QuadPart);
  1470. MillisecondTimeout = RWAN_CONVERT_100NS_TO_MS(MillisecondTimeout);
  1471. }
  1472. RWAN_ASSERT(MillisecondTimeout.HighPart == 0);
  1473. #endif // 0
  1474. }
  1475. else
  1476. {
  1477. MillisecondTimeout.LowPart = 0;
  1478. MillisecondTimeout.HighPart = 0;
  1479. }
  1480. if (pDisconnectRequest->RequestFlags & TDI_DISCONNECT_ABORT)
  1481. {
  1482. //
  1483. // Use non-generic completion routine for abortive disconnects,
  1484. // because they cannot be cancelled.
  1485. //
  1486. bAbortiveDisconnect = TRUE;
  1487. IoMarkIrpPending(pIrp);
  1488. TdiRequest.RequestNotifyObject = (PVOID)RWanNonCancellableRequestComplete;
  1489. Status = STATUS_SUCCESS;
  1490. }
  1491. else
  1492. {
  1493. //
  1494. // Non-abortive disconnect.
  1495. //
  1496. bAbortiveDisconnect = FALSE;
  1497. Status = RWanPrepareIrpForCancel(pConnEndpoint, pIrp, RWanCancelRequest);
  1498. TdiRequest.RequestNotifyObject = (PVOID)RWanRequestComplete;
  1499. }
  1500. if (NT_SUCCESS(Status))
  1501. {
  1502. Status = RWanTdiDisconnect(
  1503. &TdiRequest,
  1504. ((MillisecondTimeout.LowPart != 0)?
  1505. &(MillisecondTimeout.LowPart): NULL),
  1506. (USHORT)pDisconnectRequest->RequestFlags,
  1507. pRequestInformation,
  1508. pReturnInformation
  1509. );
  1510. if (Status != TDI_PENDING)
  1511. {
  1512. if (bAbortiveDisconnect)
  1513. {
  1514. RWanNonCancellableRequestComplete(pIrp, Status, 0);
  1515. }
  1516. else
  1517. {
  1518. RWanRequestComplete(pIrp, Status, 0);
  1519. }
  1520. Status = STATUS_PENDING;
  1521. }
  1522. }
  1523. RWANDEBUGP(DL_LOUD, DC_DISCON,
  1524. ("RWanDisconnect: pIrp %p, pEndp %p, Abortive %d, Status x%x\n",
  1525. pIrp, pConnEndpoint, (INT)bAbortiveDisconnect, Status));
  1526. return (Status);
  1527. }
  1528. NTSTATUS
  1529. RWanListen(
  1530. IN PIRP pIrp,
  1531. IN PIO_STACK_LOCATION pIrpSp
  1532. )
  1533. /*++
  1534. Routine Description:
  1535. Convert a TDI Listen IRP to a call to our Listen entry point.
  1536. The FileObject in the IRP refers to the Connection Object on which
  1537. this Listen is posted.
  1538. Arguments:
  1539. pIrp - Pointer to IRP
  1540. pIrpSp - IRP Stack location
  1541. Return Value:
  1542. NTSTATUS - STATUS_PENDING if a Listen was initiated, STATUS_XXX error
  1543. code otherwise.
  1544. --*/
  1545. {
  1546. PRWAN_ENDPOINT pConnEndpoint;
  1547. TDI_REQUEST TdiRequest;
  1548. PTDI_CONNECTION_INFORMATION pRequestInformation;
  1549. PTDI_CONNECTION_INFORMATION pReturnInformation;
  1550. PTDI_REQUEST_KERNEL_LISTEN pListenRequest;
  1551. NTSTATUS Status;
  1552. pConnEndpoint = (PRWAN_ENDPOINT) pIrpSp->FileObject->FsContext;
  1553. RWAN_STRUCT_ASSERT(pConnEndpoint, nep);
  1554. //
  1555. // Grab all parameters from the IRP.
  1556. //
  1557. pListenRequest = (PTDI_REQUEST_KERNEL_LISTEN) &(pIrpSp->Parameters);
  1558. pRequestInformation = pListenRequest->RequestConnectionInformation;
  1559. pReturnInformation = pListenRequest->ReturnConnectionInformation;
  1560. //
  1561. // Prepare a TDI LISTEN Request
  1562. //
  1563. TdiRequest.Handle.ConnectionContext = pConnEndpoint->Handle.ConnectionContext;
  1564. TdiRequest.RequestNotifyObject = (PVOID)RWanRequestComplete;
  1565. TdiRequest.RequestContext = (PVOID)pIrp;
  1566. Status = RWanPrepareIrpForCancel(pConnEndpoint, pIrp, RWanCancelRequest);
  1567. if (NT_SUCCESS(Status))
  1568. {
  1569. Status = RWanTdiListen(
  1570. &TdiRequest,
  1571. (USHORT)pListenRequest->RequestFlags,
  1572. pRequestInformation,
  1573. pReturnInformation
  1574. );
  1575. if (Status != TDI_PENDING)
  1576. {
  1577. RWanRequestComplete(pIrp, Status, 0);
  1578. Status = STATUS_PENDING;
  1579. }
  1580. }
  1581. RWANDEBUGP(DL_LOUD, DC_CONNECT,
  1582. ("RWanListen: pIrp %p, pEndp %p, Status x%x\n",
  1583. pIrp, pConnEndpoint, Status));
  1584. return (Status);
  1585. }
  1586. NTSTATUS
  1587. RWanAccept(
  1588. IN PIRP pIrp,
  1589. IN PIO_STACK_LOCATION pIrpSp
  1590. )
  1591. /*++
  1592. Routine Description:
  1593. Convert a TDI Accept IRP to a call to our Accept entry point.
  1594. Arguments:
  1595. pIrp - Pointer to IRP
  1596. pIrpSp - IRP Stack location
  1597. Return Value:
  1598. NTSTATUS - STATUS_PENDING if an Accept was initiated, STATUS_XXX error
  1599. code otherwise.
  1600. --*/
  1601. {
  1602. PRWAN_ENDPOINT pConnEndpoint;
  1603. TDI_REQUEST TdiRequest;
  1604. PTDI_CONNECTION_INFORMATION pRequestInformation;
  1605. PTDI_CONNECTION_INFORMATION pReturnInformation;
  1606. PTDI_REQUEST_KERNEL_ACCEPT pAcceptRequest;
  1607. NTSTATUS Status;
  1608. pConnEndpoint = (PRWAN_ENDPOINT) pIrpSp->FileObject->FsContext;
  1609. RWAN_STRUCT_ASSERT(pConnEndpoint, nep);
  1610. //
  1611. // Grab all parameters from the IRP.
  1612. //
  1613. pAcceptRequest = (PTDI_REQUEST_KERNEL_ACCEPT) &(pIrpSp->Parameters);
  1614. pRequestInformation = pAcceptRequest->RequestConnectionInformation;
  1615. pReturnInformation = pAcceptRequest->ReturnConnectionInformation;
  1616. //
  1617. // Prepare a TDI ACCEPT Request
  1618. //
  1619. TdiRequest.Handle.ConnectionContext = pConnEndpoint->Handle.ConnectionContext;
  1620. TdiRequest.RequestNotifyObject = (PVOID)RWanRequestComplete;
  1621. TdiRequest.RequestContext = (PVOID)pIrp;
  1622. Status = RWanPrepareIrpForCancel(pConnEndpoint, pIrp, RWanCancelRequest);
  1623. if (NT_SUCCESS(Status))
  1624. {
  1625. Status = RWanTdiAccept(
  1626. &TdiRequest,
  1627. pRequestInformation,
  1628. pReturnInformation
  1629. );
  1630. if (Status != TDI_PENDING)
  1631. {
  1632. RWanRequestComplete(pIrp, Status, 0);
  1633. Status = STATUS_PENDING;
  1634. }
  1635. }
  1636. RWANDEBUGP(DL_LOUD, DC_CONNECT,
  1637. ("RWanAccept: pIrp %p, pEndp %p, Status x%x\n",
  1638. pIrp, pConnEndpoint, Status));
  1639. return (Status);
  1640. }
  1641. NTSTATUS
  1642. RWanSetEventHandler(
  1643. IN PIRP pIrp,
  1644. IN PIO_STACK_LOCATION pIrpSp
  1645. )
  1646. /*++
  1647. Routine Description:
  1648. Convert a TDI Set Event Handler IRP to a call to our set event handler
  1649. entry point.
  1650. Arguments:
  1651. pIrp - Pointer to IRP
  1652. pIrpSp - IRP Stack location
  1653. Return Value:
  1654. NTSTATUS - STATUS_SUCCESS if the request was successful, STATUS_XXX error
  1655. code otherwise.
  1656. --*/
  1657. {
  1658. PRWAN_ENDPOINT pEndpoint;
  1659. PTDI_REQUEST_KERNEL_SET_EVENT pSetEvent;
  1660. NTSTATUS Status;
  1661. PAGED_CODE();
  1662. pEndpoint = (PRWAN_ENDPOINT) pIrpSp->FileObject->FsContext;
  1663. RWAN_STRUCT_ASSERT(pEndpoint, nep);
  1664. pSetEvent = (PTDI_REQUEST_KERNEL_SET_EVENT) &(pIrpSp->Parameters);
  1665. Status = RWanTdiSetEvent(
  1666. pEndpoint->Handle.AddressHandle,
  1667. pSetEvent->EventType,
  1668. pSetEvent->EventHandler,
  1669. pSetEvent->EventContext
  1670. );
  1671. RWAN_ASSERT(Status != STATUS_PENDING);
  1672. RWANDEBUGP(DL_LOUD, DC_DISPATCH,
  1673. ("RWanSetEventHandler: pIrp %p, pEndp %p, Type x%x, Status x%x\n",
  1674. pIrp, pEndpoint, pSetEvent->EventType, Status));
  1675. return (Status);
  1676. }
  1677. NTSTATUS
  1678. RWanQueryInformation(
  1679. IN PIRP pIrp,
  1680. IN PIO_STACK_LOCATION pIrpSp
  1681. )
  1682. /*++
  1683. Routine Description:
  1684. Converts a TDI Query Information IRP to a call to the QueryInformation
  1685. TDI entry point.
  1686. Arguments:
  1687. pIrp - Pointer to IRP
  1688. pIrpSp - IRP Stack location
  1689. Return Value:
  1690. NTSTATUS - this is STATUS_SUCCESS if the query was completed successfully,
  1691. STATUS_PENDING if it will be completed later, STATUS_XXX error code otherwise.
  1692. --*/
  1693. {
  1694. TDI_REQUEST TdiRequest;
  1695. NTSTATUS Status;
  1696. PRWAN_ENDPOINT pEndpoint;
  1697. PTDI_REQUEST_KERNEL_QUERY_INFORMATION pQueryInfo;
  1698. UINT IsConnection;
  1699. UINT DataSize;
  1700. IsConnection = FALSE;
  1701. DataSize = 0;
  1702. pEndpoint = (PRWAN_ENDPOINT) pIrpSp->FileObject->FsContext;
  1703. RWAN_STRUCT_ASSERT(pEndpoint, nep);
  1704. pQueryInfo = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION) &(pIrpSp->Parameters);
  1705. TdiRequest.RequestNotifyObject = RWanDataRequestComplete;
  1706. TdiRequest.RequestContext = pIrp;
  1707. Status = STATUS_SUCCESS;
  1708. switch (pQueryInfo->QueryType)
  1709. {
  1710. case TDI_QUERY_BROADCAST_ADDRESS:
  1711. Status = STATUS_NOT_IMPLEMENTED;
  1712. break;
  1713. case TDI_QUERY_PROVIDER_INFO:
  1714. TdiRequest.Handle.ControlChannel = pEndpoint->Handle.ControlChannel;
  1715. break;
  1716. case TDI_QUERY_ADDRESS_INFO:
  1717. if (((INT)PtrToUint(pIrpSp->FileObject->FsContext2)) == TDI_CONNECTION_FILE)
  1718. {
  1719. IsConnection = TRUE;
  1720. TdiRequest.Handle.ConnectionContext = pEndpoint->Handle.ConnectionContext;
  1721. }
  1722. else
  1723. {
  1724. //
  1725. // Must be an address object.
  1726. //
  1727. RWAN_ASSERT(((INT) PtrToUint(pIrpSp->FileObject->FsContext2))
  1728. == TDI_TRANSPORT_ADDRESS_FILE);
  1729. TdiRequest.Handle.AddressHandle = pEndpoint->Handle.AddressHandle;
  1730. }
  1731. break;
  1732. case TDI_QUERY_CONNECTION_INFO:
  1733. //
  1734. // Must be a connection object.
  1735. //
  1736. RWAN_ASSERT(((INT) PtrToUint(pIrpSp->FileObject->FsContext2)) == TDI_CONNECTION_FILE);
  1737. IsConnection = TRUE;
  1738. TdiRequest.Handle.ConnectionContext = pEndpoint->Handle.ConnectionContext;
  1739. break;
  1740. case TDI_QUERY_PROVIDER_STATISTICS:
  1741. //
  1742. // Must be a control channel.
  1743. //
  1744. RWAN_ASSERT(((INT) PtrToUint(pIrpSp->FileObject->FsContext2))
  1745. == TDI_CONTROL_CHANNEL_FILE);
  1746. TdiRequest.Handle.ControlChannel = pEndpoint->Handle.ControlChannel;
  1747. break;
  1748. default:
  1749. Status = STATUS_NOT_IMPLEMENTED;
  1750. break;
  1751. }
  1752. if (NT_SUCCESS(Status))
  1753. {
  1754. Status = RWanPrepareIrpForCancel(pEndpoint, pIrp, NULL);
  1755. if (NT_SUCCESS(Status))
  1756. {
  1757. DataSize = RWanGetMdlChainLength(pIrp->MdlAddress);
  1758. Status = RWanTdiQueryInformation(
  1759. &TdiRequest,
  1760. pQueryInfo->QueryType,
  1761. pIrp->MdlAddress,
  1762. &DataSize,
  1763. IsConnection
  1764. );
  1765. RWANDEBUGP(DL_LOUD, DC_DISPATCH,
  1766. ("RWanQueryInformation: pIrp %p, pEndp %p, Type x%x, Status x%x\n",
  1767. pIrp, pEndpoint, pQueryInfo->QueryType, Status));
  1768. if (Status != TDI_PENDING)
  1769. {
  1770. RWanDataRequestComplete(pIrp, Status, DataSize);
  1771. }
  1772. return (STATUS_PENDING);
  1773. }
  1774. else
  1775. {
  1776. return (Status);
  1777. }
  1778. }
  1779. RWAN_COMPLETE_IRP(pIrp, Status, 0);
  1780. return (Status);
  1781. }
  1782. VOID
  1783. RWanCloseObjectComplete(
  1784. IN PVOID Context,
  1785. IN UINT Status,
  1786. IN UINT Unused
  1787. )
  1788. /*++
  1789. Routine Description:
  1790. This is the call-back routine that processes a CloseConnection
  1791. or CloseAddress completion. This is called by the core TDI
  1792. provider. We dereference the endpoint; if it goes to 0, we
  1793. wake up the thread that's running the CLEANUP.
  1794. Arguments:
  1795. Context - A pointer to the IRP for this request.
  1796. Status - Final TDI status for the CloseConnection/CloseAddress
  1797. Unused - Not used for this completion
  1798. Return Value:
  1799. None
  1800. --*/
  1801. {
  1802. KIRQL OldIrql;
  1803. PIRP pIrp;
  1804. PIO_STACK_LOCATION pIrpSp;
  1805. PRWAN_ENDPOINT pEndpoint;
  1806. UNREFERENCED_PARAMETER(Unused);
  1807. pIrp = (PIRP)Context;
  1808. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  1809. pIrp->IoStatus.Status = Status;
  1810. pEndpoint = (PRWAN_ENDPOINT) pIrpSp->FileObject->FsContext;
  1811. RWAN_STRUCT_ASSERT(pEndpoint, nep);
  1812. IoAcquireCancelSpinLock(&OldIrql);
  1813. IoSetCancelRoutine(pIrp, NULL);
  1814. RWAN_DECR_EP_REF_CNT(pEndpoint, CloseComplDecr); // CloseComplete deref
  1815. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'pmCC', pIrp, pEndpoint->RefCount);
  1816. if (pEndpoint->RefCount == 0)
  1817. {
  1818. //
  1819. // The endpoint must be cleaning up.
  1820. //
  1821. RWANDEBUGP(DL_LOUD, DC_DISPATCH,
  1822. ("RWanCloseObjectComplete: pIrp %p, pEndpoint %p ref count 0\n",
  1823. pIrp, pEndpoint));
  1824. KeSetEvent(&(pEndpoint->CleanupEvent), 0, FALSE);
  1825. }
  1826. IoReleaseCancelSpinLock(OldIrql);
  1827. return;
  1828. }
  1829. VOID
  1830. RWanDataRequestComplete(
  1831. IN PVOID Context,
  1832. IN UINT Status,
  1833. IN UINT ByteCount
  1834. )
  1835. /*++
  1836. Routine Description:
  1837. This is the call-back routine that processes a Send/Receive completion.
  1838. This is called by the core TDI provider. We complete the send/receive
  1839. IRP appropriately, and dereference our endpoint.
  1840. Arguments:
  1841. Context - A pointer to the IRP for this request.
  1842. Status - Final TDI status for send/receive
  1843. ByteCount - Actual bytes sent/received.
  1844. Return Value:
  1845. None
  1846. --*/
  1847. {
  1848. KIRQL OldIrql;
  1849. PIRP pIrp;
  1850. PIO_STACK_LOCATION pIrpSp;
  1851. PRWAN_ENDPOINT pEndpoint;
  1852. pIrp = (PIRP)Context;
  1853. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  1854. pEndpoint = (PRWAN_ENDPOINT) pIrpSp->FileObject->FsContext;
  1855. RWAN_STRUCT_ASSERT(pEndpoint, nep);
  1856. IoAcquireCancelSpinLock(&OldIrql);
  1857. IoSetCancelRoutine(pIrp, NULL);
  1858. RWAN_DECR_EP_REF_CNT(pEndpoint, DataReqComplDecr); // Send/Receive deref
  1859. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'CerD', pIrp, pEndpoint->RefCount);
  1860. RWANDEBUGP(DL_EXTRA_LOUD, DC_DATA_TX|DC_DATA_RX|DC_CONNECT|DC_DISCON,
  1861. ("RWanDataReq compl: pIrp %p, pEndpoint %p, RefCnt %d, Sts x%x, ByteCnt %d\n",
  1862. pIrp, pEndpoint, pEndpoint->RefCount, Status, ByteCount));
  1863. if (pEndpoint->RefCount == 0)
  1864. {
  1865. //
  1866. // The endpoint must be cleaning up.
  1867. //
  1868. RWANDEBUGP(DL_LOUD, DC_DISPATCH,
  1869. ("RWanDataRequestComplete: pIrp %p, pEndpoint %p ref count 0\n",
  1870. pIrp, pEndpoint));
  1871. KeSetEvent(&(pEndpoint->CleanupEvent), 0, FALSE);
  1872. }
  1873. //
  1874. // If the IRP was cancelled or we are cleaning up,
  1875. // update the completion status.
  1876. //
  1877. if (pIrp->Cancel || pEndpoint->bCancelIrps)
  1878. {
  1879. Status = (UINT)STATUS_CANCELLED;
  1880. ByteCount = 0;
  1881. }
  1882. IoReleaseCancelSpinLock(OldIrql);
  1883. RWAN_COMPLETE_IRP(pIrp, Status, ByteCount);
  1884. return;
  1885. }
  1886. VOID
  1887. RWanRequestComplete(
  1888. IN PVOID Context,
  1889. IN UINT Status,
  1890. IN UINT Unused
  1891. )
  1892. /*++
  1893. Routine Description:
  1894. This is our call-back routine for completing requests that don't
  1895. include data. IRP processing is the same as that for data, except
  1896. that the ByteCount is 0.
  1897. Arguments:
  1898. Context - A pointer to the IRP for this request.
  1899. Status - Final TDI status for the request.
  1900. Unused - Not used.
  1901. Return Value:
  1902. None
  1903. --*/
  1904. {
  1905. UNREFERENCED_PARAMETER(Unused);
  1906. RWanDataRequestComplete(Context, Status, 0);
  1907. }
  1908. VOID
  1909. RWanNonCancellableRequestComplete(
  1910. IN PVOID Context,
  1911. IN UINT Status,
  1912. IN UINT Unused
  1913. )
  1914. /*++
  1915. Routine Description:
  1916. This is our call-back routine for completing requests based
  1917. on non-cancellable IRPs (e.g. Abortive Disconnect).
  1918. Arguments:
  1919. Context - A pointer to the IRP for this request.
  1920. Status - Final TDI status for the request.
  1921. Unused - Not used.
  1922. Return Value:
  1923. None
  1924. --*/
  1925. {
  1926. PIRP pIrp;
  1927. PIO_STACK_LOCATION pIrpSp;
  1928. UNREFERENCED_PARAMETER(Unused);
  1929. pIrp = (PIRP)Context;
  1930. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  1931. //
  1932. // Complete the IRP
  1933. //
  1934. RWAN_COMPLETE_IRP(pIrp, Status, 0);
  1935. return;
  1936. }
  1937. VOID
  1938. RWanCancelComplete(
  1939. IN PVOID Context,
  1940. IN UINT Unused1,
  1941. IN UINT Unused2
  1942. )
  1943. /*++
  1944. Routine Description:
  1945. This is called to process internal completion of an IRP cancellation.
  1946. All we need to do here is to dereference the endpoint on which this
  1947. happened.
  1948. Arguments:
  1949. Context - A pointer to the file object representing the
  1950. endpoint on which the IRP was cancelled.
  1951. Unused[1-2] - Not used
  1952. Return Value:
  1953. None
  1954. --*/
  1955. {
  1956. PFILE_OBJECT pFileObject;
  1957. PRWAN_ENDPOINT pEndpoint;
  1958. KIRQL OldIrql;
  1959. UNREFERENCED_PARAMETER(Unused1);
  1960. UNREFERENCED_PARAMETER(Unused2);
  1961. pFileObject = (PFILE_OBJECT)Context;
  1962. pEndpoint = (PRWAN_ENDPOINT)(pFileObject->FsContext);
  1963. RWAN_STRUCT_ASSERT(pEndpoint, nep);
  1964. IoAcquireCancelSpinLock(&OldIrql);
  1965. RWAN_DECR_EP_REF_CNT(pEndpoint, CancelComplDecr); // CancelComplete deref
  1966. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'CnaC', 0, pEndpoint->RefCount);
  1967. RWANDEBUGP(DL_EXTRA_LOUD, DC_DISPATCH,
  1968. ("RWanCancelComplete: pEndpoint %p, RefCount %d\n",
  1969. pEndpoint, pEndpoint->RefCount));
  1970. if (pEndpoint->RefCount == 0)
  1971. {
  1972. //
  1973. // Wake up the thread waiting for IRPs to complete
  1974. //
  1975. KeSetEvent(&(pEndpoint->CleanupEvent), 0, FALSE);
  1976. }
  1977. IoReleaseCancelSpinLock(OldIrql);
  1978. return;
  1979. }
  1980. VOID
  1981. RWanCancelRequest(
  1982. IN PDEVICE_OBJECT pDeviceObject,
  1983. IN PIRP pIrp
  1984. )
  1985. /*++
  1986. Routine Description:
  1987. This is the cancel routine we attach to IRPs that we queue. This
  1988. is supposed to cancel the IRP.
  1989. Arguments:
  1990. pDeviceObject - Pointer to the device object for this IRP
  1991. pIrp - Pointer to request packet
  1992. Return Value:
  1993. None
  1994. --*/
  1995. {
  1996. PFILE_OBJECT pFileObject;
  1997. PIO_STACK_LOCATION pIrpSp;
  1998. PRWAN_ENDPOINT pEndpoint;
  1999. NTSTATUS Status;
  2000. TDI_REQUEST TdiRequest;
  2001. UCHAR MinorFunction;
  2002. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  2003. pFileObject = pIrpSp->FileObject;
  2004. MinorFunction = pIrpSp->MinorFunction;
  2005. pEndpoint = (PRWAN_ENDPOINT) pFileObject->FsContext;
  2006. RWAN_STRUCT_ASSERT(pEndpoint, nep);
  2007. //
  2008. // This routine is entered with Cancel SpinLock acquired.
  2009. //
  2010. RWAN_ASSERT(pIrp->Cancel);
  2011. IoSetCancelRoutine(pIrp, NULL);
  2012. //
  2013. // Make sure that the endpoint doesn't go away when
  2014. // we release the Cancel Spinlock.
  2015. //
  2016. RWAN_INCR_EP_REF_CNT(pEndpoint, CancelIncr); // Cancel ref
  2017. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'RnaC', pIrp, pEndpoint->RefCount);
  2018. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  2019. RWANDEBUGP(DL_LOUD, DC_DISPATCH,
  2020. ("RWanCancelRequest: pIrp %p, MinorFunc %d, pEndpoint %p\n",
  2021. pIrp, MinorFunction, pEndpoint));
  2022. Status = STATUS_SUCCESS;
  2023. switch (MinorFunction)
  2024. {
  2025. case TDI_SEND:
  2026. case TDI_RECEIVE:
  2027. RWanAbortConnection(
  2028. pEndpoint->Handle.ConnectionContext
  2029. );
  2030. break;
  2031. case TDI_DISASSOCIATE_ADDRESS:
  2032. break;
  2033. case TDI_LISTEN:
  2034. //
  2035. // Initiate an Unlisten.
  2036. //
  2037. TdiRequest.Handle.ConnectionContext = pEndpoint->Handle.ConnectionContext;
  2038. TdiRequest.RequestNotifyObject = (PVOID)RWanCancelComplete;
  2039. TdiRequest.RequestContext = (PVOID)pFileObject;
  2040. Status = RWanTdiUnListen(
  2041. &TdiRequest
  2042. );
  2043. break;
  2044. default:
  2045. //
  2046. // Initiate a Disconnect.
  2047. //
  2048. TdiRequest.Handle.ConnectionContext = pEndpoint->Handle.ConnectionContext;
  2049. TdiRequest.RequestNotifyObject = (PVOID)RWanCancelComplete;
  2050. TdiRequest.RequestContext = (PVOID)pFileObject;
  2051. Status = RWanTdiDisconnect(
  2052. &TdiRequest,
  2053. NULL,
  2054. TDI_DISCONNECT_ABORT,
  2055. NULL,
  2056. NULL
  2057. );
  2058. break;
  2059. }
  2060. if (Status != TDI_PENDING)
  2061. {
  2062. RWanCancelComplete(pFileObject, 0, 0);
  2063. }
  2064. return;
  2065. }
  2066. NTSTATUS
  2067. RWanPrepareIrpForCancel(
  2068. IN PRWAN_ENDPOINT pEndpoint,
  2069. IN PIRP pIrp,
  2070. IN PDRIVER_CANCEL pCancelRoutine
  2071. )
  2072. /*++
  2073. Routine Description:
  2074. Check if an IRP has been cancelled. If so, complete it with the
  2075. right status. Otherwise, set it up so that the supplied cancel
  2076. routine is called if it is cancelled.
  2077. This is called for non-data IRPs that are potentially going to
  2078. pend.
  2079. Arguments:
  2080. pEndpoint - Pointer to endpoint on which this IRP arrived
  2081. pIrp - Pointer to request packet
  2082. pCancelRoutine - Cancellation routine to be tacked on to the IRP
  2083. Return Value:
  2084. NTSTATUS - this is STATUS_CANCELLED if the IRP has been cancelled
  2085. already, STATUS_SUCCESS otherwise.
  2086. --*/
  2087. {
  2088. KIRQL OldIrql;
  2089. NTSTATUS Status;
  2090. IoAcquireCancelSpinLock(&OldIrql);
  2091. RWAN_ASSERT(pIrp->CancelRoutine == NULL);
  2092. if (!pIrp->Cancel)
  2093. {
  2094. //
  2095. // This IRP hasn't been cancelled. Mark it as pending, because
  2096. // it's going to be queued (by the caller).
  2097. //
  2098. IoMarkIrpPending(pIrp);
  2099. IoSetCancelRoutine(pIrp, pCancelRoutine);
  2100. //
  2101. // Add a reference for this IRP on the endpoint.
  2102. //
  2103. RWAN_INCR_EP_REF_CNT(pEndpoint, NonDataIncr); // Non data IRP ref
  2104. RWAN_EP_DBGLOG_ENTRY(pEndpoint, 'DnoN', pIrp, pEndpoint->RefCount);
  2105. IoReleaseCancelSpinLock(OldIrql);
  2106. Status = STATUS_SUCCESS;
  2107. }
  2108. else
  2109. {
  2110. //
  2111. // The IRP has been cancelled already. Simply complete it.
  2112. //
  2113. IoReleaseCancelSpinLock(OldIrql);
  2114. Status = STATUS_CANCELLED;
  2115. RWAN_COMPLETE_IRP(pIrp, Status, 0);
  2116. }
  2117. RWANDEBUGP(DL_VERY_LOUD, DC_DISPATCH,
  2118. ("RWanPrepareIrpForCancel: pIrp %p, pEndp %p, ret Status x%x\n",
  2119. pIrp, pEndpoint, Status));
  2120. return (Status);
  2121. }
  2122. ULONG
  2123. RWanGetMdlChainLength(
  2124. IN PMDL pMdl
  2125. )
  2126. /*++
  2127. Routine Description:
  2128. Return the total byte count of all MDLs in a chain.
  2129. Arguments:
  2130. pMdl - Points to start of MDL chain.
  2131. Return Value:
  2132. Byte count of the MDL chain.
  2133. --*/
  2134. {
  2135. ULONG Count = 0;
  2136. while (pMdl != NULL)
  2137. {
  2138. Count += MmGetMdlByteCount(pMdl);
  2139. pMdl = pMdl->Next;
  2140. }
  2141. return (Count);
  2142. }
  2143. NTSTATUS
  2144. RWanToNTStatus(
  2145. IN RWAN_STATUS RWanStatus
  2146. )
  2147. /*++
  2148. Routine Description:
  2149. Map from a Raw-WAN status code to an equivalent NT status code.
  2150. Arguments:
  2151. RWanStatus - The RAW WAN status code.
  2152. Return Value:
  2153. The NT Status code.
  2154. --*/
  2155. {
  2156. NTSTATUS Status;
  2157. switch (RWanStatus)
  2158. {
  2159. case RWAN_STATUS_SUCCESS:
  2160. Status = STATUS_SUCCESS;
  2161. break;
  2162. case RWAN_STATUS_BAD_ADDRESS:
  2163. Status = STATUS_INVALID_ADDRESS;
  2164. break;
  2165. case RWAN_STATUS_BAD_PARAMETER:
  2166. Status = STATUS_INVALID_PARAMETER;
  2167. break;
  2168. case RWAN_STATUS_MISSING_PARAMETER:
  2169. Status = STATUS_INVALID_PARAMETER;
  2170. break;
  2171. case RWAN_STATUS_RESOURCES:
  2172. Status = STATUS_INSUFFICIENT_RESOURCES;
  2173. break;
  2174. case RWAN_STATUS_FAILURE:
  2175. default:
  2176. Status = STATUS_UNSUCCESSFUL;
  2177. break;
  2178. }
  2179. return (Status);
  2180. }