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.

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