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.

2989 lines
82 KiB

  1. /*++
  2. Copyright (c) 1991-2000 Microsoft Corporation
  3. Module Name:
  4. ntirp.c
  5. Abstract:
  6. NT specific routines for dispatching and handling IRPs.
  7. Author:
  8. Mike Massa (mikemas) Aug 13, 1993
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. mikemas 08-13-93 created
  13. Notes:
  14. --*/
  15. #include "precomp.h"
  16. #include "iproute.h"
  17. #include "icmp.h"
  18. #include "arpdef.h"
  19. #include "info.h"
  20. #include "ipstatus.h"
  21. #include "tcpipbuf.h"
  22. //
  23. // Local structures.
  24. //
  25. typedef struct pending_irp {
  26. LIST_ENTRY Linkage;
  27. PIRP Irp;
  28. PFILE_OBJECT FileObject;
  29. PVOID Context;
  30. } PENDING_IRP, *PPENDING_IRP;
  31. DEFINE_LOCK_STRUCTURE(AddChangeLock)
  32. DEFINE_LOCK_STRUCTURE(ClientNotifyLock)
  33. //
  34. // Global variables
  35. //
  36. LIST_ENTRY PendingEchoList;
  37. LIST_ENTRY PendingIPSetNTEAddrList;
  38. PIRP PendingIPGetIPEventRequest;
  39. LIST_ENTRY PendingEnableRouterList;
  40. LIST_ENTRY PendingMediaSenseRequestList;
  41. LIST_ENTRY PendingArpSendList;
  42. IP_STATUS ARPResolve(IPAddr DestAddress, IPAddr SourceAddress,
  43. ARPControlBlock * ControlBlock, ArpRtn Callback);
  44. VOID CompleteArpResolveRequest(void *ControlBlock, IP_STATUS ipstatus);
  45. extern Interface *IFList;
  46. //
  47. // External prototypes
  48. //
  49. IP_STATUS ICMPEchoRequest(void *InputBuffer, uint InputBufferLength,
  50. EchoControl * ControlBlock, EchoRtn Callback);
  51. ulong ICMPEchoComplete(EchoControl * ControlBlock, IP_STATUS Status,
  52. void *Data, uint DataSize, IPOptInfo *OptionInfo);
  53. #if defined(_WIN64)
  54. ulong ICMPEchoComplete32(EchoControl * ControlBlock, IP_STATUS Status,
  55. void *Data, uint DataSize, IPOptInfo *OptionInfo);
  56. #endif // _WIN64
  57. IP_STATUS IPSetNTEAddrEx(uint Index, IPAddr Addr, IPMask Mask,
  58. SetAddrControl * ControlBlock, SetAddrRtn Callback, USHORT Type);
  59. IP_STATUS IPAddDynamicNTE(ulong InterfaceContext, PUNICODE_STRING InterfaceName,
  60. int InterfaceNameLen, IPAddr NewAddr, IPMask NewMask,
  61. ushort * NTEContext, ulong * NTEInstance);
  62. IP_STATUS IPDeleteDynamicNTE(ushort NTEContext);
  63. uint IPGetNTEInfo(ushort NTEContext, ulong * NTEInstance, IPAddr * Address,
  64. IPMask * SubnetMask, ushort * NTEFlags);
  65. uint SetDHCPNTE(uint Context);
  66. NTSTATUS SetIFPromiscuous(ULONG Index, UCHAR Type, UCHAR Add);
  67. extern void NotifyAddrChange(IPAddr Addr, IPMask Mask, void *Context,
  68. ushort IPContext, PVOID * Handle,
  69. PNDIS_STRING ConfigName, PNDIS_STRING IFName,
  70. uint Added);
  71. extern NTSTATUS IPStatusToNTStatus(IP_STATUS ipStatus);
  72. extern int IPEnableRouterRefCount;
  73. extern int IPEnableRouterWithRefCount(LOGICAL Enable);
  74. extern NTSTATUS IPGetCapability(ULONG Context, uchar* buf, uint cap);
  75. extern int IPEnableMediaSense(LOGICAL Enable, KIRQL *irql);
  76. extern uint DisableMediaSense;
  77. NTSTATUS FlushArpTable(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  78. //
  79. // Local prototypes
  80. //
  81. NTSTATUS IPDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
  82. NTSTATUS IPDispatchDeviceControl(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  83. NTSTATUS IPDispatchInternalDeviceControl(IN PIRP Irp,
  84. IN PIO_STACK_LOCATION IrpSp);
  85. NTSTATUS IPCreate(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  86. NTSTATUS IPCleanup(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  87. NTSTATUS IPClose(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  88. NTSTATUS DispatchEchoRequest(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  89. NTSTATUS DispatchARPRequest(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  90. NTSTATUS RtChangeNotifyRequest(PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  91. NTSTATUS RtChangeNotifyRequestEx(PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  92. NTSTATUS AddrChangeNotifyRequest(PIRP Irp, PIO_STACK_LOCATION IrpSp);
  93. NTSTATUS CancelChangeNotifyRequest(PIRP Irp, PIO_STACK_LOCATION IrpSp,
  94. PVOID ApcContext);
  95. #if MILLEN
  96. NTSTATUS IfChangeNotifyRequest(PIRP Irp, PIO_STACK_LOCATION IrpSp);
  97. #endif // MILLEN
  98. NTSTATUS IPEnableRouterRequest(PIRP Irp, PIO_STACK_LOCATION IrpSp);
  99. NTSTATUS IPUnenableRouterRequest(PIRP Irp, PIO_STACK_LOCATION IrpSp,
  100. PVOID ApcContext);
  101. VOID CancelIPEnableRouterRequest(IN PDEVICE_OBJECT Device, IN PIRP Irp);
  102. NTSTATUS IPGetBestInterfaceIndex(IN IPAddr Address, OUT PULONG pIndex,
  103. OUT PULONG pMetric);
  104. extern NTSTATUS GetBestInterfaceId(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  105. extern NTSTATUS IPGetBestInterface(IN IPAddr Address, OUT PVOID * ppIF);
  106. extern NTSTATUS GetInterfaceInfo(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  107. extern NTSTATUS GetIgmpList(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  108. extern NTSTATUS DispatchIPSetBlockofRoutes(IN PIRP Irp,
  109. IN PIO_STACK_LOCATION IrpSp);
  110. extern NTSTATUS DispatchIPSetRouteWithRef(IN PIRP Irp,
  111. IN PIO_STACK_LOCATION IrpSp);
  112. extern NTSTATUS DispatchIPSetMultihopRoute(IN PIRP Irp,
  113. IN PIO_STACK_LOCATION IrpSp);
  114. void CompleteEchoRequest(void *Context, IP_STATUS Status, void *Data,
  115. uint DataSize, IPOptInfo *OptionInfo);
  116. NTSTATUS DispatchIPSetNTEAddrRequest(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  117. void CompleteIPSetNTEAddrRequest(void *Context, IP_STATUS Status);
  118. NTSTATUS IPGetIfIndex(IN PIRP pIrp, IN PIO_STACK_LOCATION pIrpSp);
  119. NTSTATUS IPGetIfName(IN PIRP pIrp, IN PIO_STACK_LOCATION pIrpSp);
  120. NTSTATUS DispatchIPGetIPEvent(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  121. NTSTATUS IPGetMcastCounters(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp);
  122. NTSTATUS
  123. IPEnableMediaSenseRequest(PIRP Irp, PIO_STACK_LOCATION IrpSp, PVOID ApcContext);
  124. NTSTATUS
  125. IPDisableMediaSenseRequest(PIRP Irp, PIO_STACK_LOCATION IrpSp );
  126. VOID
  127. CancelIPEnableMediaSenseRequest(IN PDEVICE_OBJECT Device, IN PIRP Irp);
  128. //
  129. // All of this code is pageable.
  130. //
  131. #if !MILLEN
  132. #ifdef ALLOC_PRAGMA
  133. #pragma alloc_text(PAGE, IPDispatch)
  134. #pragma alloc_text(PAGE, IPDispatchInternalDeviceControl)
  135. #pragma alloc_text(PAGE, IPCreate)
  136. #pragma alloc_text(PAGE, IPClose)
  137. #pragma alloc_text(PAGE, DispatchEchoRequest)
  138. #pragma alloc_text(PAGE, DispatchARPRequest)
  139. #endif // ALLOC_PRAGMA
  140. #endif // !MILLEN
  141. //
  142. // Dispatch function definitions
  143. //
  144. NTSTATUS
  145. IPDispatch(
  146. IN PDEVICE_OBJECT DeviceObject,
  147. IN PIRP Irp
  148. )
  149. /*++
  150. Routine Description:
  151. This is the dispatch routine for IP.
  152. Arguments:
  153. DeviceObject - Pointer to device object for target device
  154. Irp - Pointer to I/O request packet
  155. Return Value:
  156. NTSTATUS -- Indicates whether the request was successfully queued.
  157. --*/
  158. {
  159. PIO_STACK_LOCATION irpSp;
  160. NTSTATUS status;
  161. UNREFERENCED_PARAMETER(DeviceObject);
  162. PAGED_CODE();
  163. irpSp = IoGetCurrentIrpStackLocation(Irp);
  164. DEBUGMSG(DBG_TRACE && DBG_IP && DBG_VERBOSE,
  165. (DTEXT("+IPDispatch(%x, %x) MajorFunction %x\n"),
  166. DeviceObject, Irp, irpSp->MajorFunction));
  167. switch (irpSp->MajorFunction) {
  168. case IRP_MJ_DEVICE_CONTROL:
  169. return IPDispatchDeviceControl(Irp, irpSp);
  170. case IRP_MJ_INTERNAL_DEVICE_CONTROL:
  171. return IPDispatchDeviceControl(Irp, irpSp);
  172. case IRP_MJ_CREATE:
  173. status = IPCreate(Irp, irpSp);
  174. break;
  175. case IRP_MJ_CLEANUP:
  176. status = IPCleanup(Irp, irpSp);
  177. break;
  178. case IRP_MJ_CLOSE:
  179. status = IPClose(Irp, irpSp);
  180. break;
  181. default:
  182. DEBUGMSG(DBG_ERROR,
  183. (DTEXT("IPDispatch: Invalid major function. IRP %x MajorFunc %x\n"),
  184. Irp, irpSp->MajorFunction));
  185. status = STATUS_NOT_IMPLEMENTED;
  186. break;
  187. }
  188. Irp->IoStatus.Status = status;
  189. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  190. DEBUGMSG(DBG_TRACE && DBG_IP && DBG_VERBOSE, (DTEXT("-IPDispatch [%x]\n"), status));
  191. return (status);
  192. }
  193. NTSTATUS
  194. IPDispatchDeviceControl(
  195. IN PIRP Irp,
  196. IN PIO_STACK_LOCATION IrpSp
  197. )
  198. /*++
  199. Routine Description:
  200. Arguments:
  201. Irp - Pointer to I/O request packet
  202. IrpSp - Pointer to the current stack location in the Irp.
  203. Return Value:
  204. NTSTATUS -- Indicates whether the request was successfully queued.
  205. --*/
  206. {
  207. NTSTATUS status;
  208. ULONG code;
  209. Irp->IoStatus.Information = 0;
  210. code = IrpSp->Parameters.DeviceIoControl.IoControlCode;
  211. DEBUGMSG(DBG_TRACE && DBG_IP,
  212. (DTEXT("+IPDispatchDeviceControl(%x, %x) IoControlCode %x\n"),
  213. Irp, IrpSp, code));
  214. switch (code) {
  215. case IOCTL_ICMP_ECHO_REQUEST:
  216. return (DispatchEchoRequest(Irp, IrpSp));
  217. case IOCTL_ARP_SEND_REQUEST:
  218. return (DispatchARPRequest(Irp, IrpSp));
  219. case IOCTL_IP_INTERFACE_INFO:
  220. return (GetInterfaceInfo(Irp, IrpSp));
  221. case IOCTL_IP_GET_IGMPLIST:
  222. return (GetIgmpList(Irp, IrpSp));
  223. case IOCTL_IP_GET_BEST_INTERFACE:
  224. return (GetBestInterfaceId(Irp, IrpSp));
  225. case IOCTL_IP_SET_ADDRESS:
  226. case IOCTL_IP_SET_ADDRESS_EX:
  227. return (DispatchIPSetNTEAddrRequest(Irp, IrpSp));
  228. case IOCTL_IP_SET_BLOCKOFROUTES:
  229. return (DispatchIPSetBlockofRoutes(Irp, IrpSp));
  230. case IOCTL_IP_SET_ROUTEWITHREF:
  231. return (DispatchIPSetRouteWithRef(Irp, IrpSp));
  232. case IOCTL_IP_SET_MULTIHOPROUTE:
  233. return (DispatchIPSetMultihopRoute(Irp, IrpSp));
  234. case IOCTL_IP_ADD_NTE:
  235. {
  236. PIP_ADD_NTE_REQUEST request;
  237. PIP_ADD_NTE_RESPONSE response;
  238. IP_STATUS ipStatus;
  239. int InterfaceNameLen = 0;
  240. UNICODE_STRING InterfaceName;
  241. BOOLEAN requestValid = FALSE;
  242. request = Irp->AssociatedIrp.SystemBuffer;
  243. response = (PIP_ADD_NTE_RESPONSE) request;
  244. //
  245. // Validate input parameters
  246. //
  247. if ((IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  248. sizeof(IP_ADD_NTE_REQUEST_OLD)) &&
  249. (IrpSp->Parameters.DeviceIoControl.OutputBufferLength >=
  250. sizeof(IP_ADD_NTE_RESPONSE))) {
  251. #if defined(_WIN64)
  252. PIP_ADD_NTE_REQUEST32 request32;
  253. if (IoIs32bitProcess(Irp)) {
  254. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  255. sizeof(IP_ADD_NTE_REQUEST32)) {
  256. requestValid = TRUE;
  257. request32 = Irp->AssociatedIrp.SystemBuffer;
  258. InterfaceName.Length = request32->InterfaceName.Length;
  259. InterfaceName.MaximumLength =
  260. request32->InterfaceName.MaximumLength;
  261. InterfaceName.Buffer =
  262. (PWCHAR)request32->InterfaceNameBuffer;
  263. InterfaceNameLen =
  264. IrpSp->Parameters.DeviceIoControl.InputBufferLength
  265. - FIELD_OFFSET(IP_ADD_NTE_REQUEST32,
  266. InterfaceNameBuffer);
  267. }
  268. } else {
  269. #endif // _WIN64
  270. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  271. sizeof(IP_ADD_NTE_REQUEST)) {
  272. requestValid = TRUE;
  273. InterfaceName = request->InterfaceName;
  274. InterfaceName.Buffer = (PWCHAR)request->InterfaceNameBuffer;
  275. InterfaceNameLen =
  276. IrpSp->Parameters.DeviceIoControl.InputBufferLength -
  277. FIELD_OFFSET(IP_ADD_NTE_REQUEST, InterfaceNameBuffer);
  278. }
  279. #if defined(_WIN64)
  280. }
  281. #endif // _WIN64
  282. if (requestValid) {
  283. ipStatus = IPAddDynamicNTE(
  284. request->InterfaceContext,
  285. &InterfaceName,
  286. InterfaceNameLen,
  287. request->Address,
  288. request->SubnetMask,
  289. &(response->Context),
  290. &(response->Instance)
  291. );
  292. } else {
  293. ipStatus = IPAddDynamicNTE(
  294. request->InterfaceContext,
  295. NULL,
  296. 0,
  297. request->Address,
  298. request->SubnetMask,
  299. &(response->Context),
  300. &(response->Instance)
  301. );
  302. }
  303. status = IPStatusToNTStatus(ipStatus);
  304. if (status == STATUS_SUCCESS) {
  305. Irp->IoStatus.Information = sizeof(IP_ADD_NTE_RESPONSE);
  306. }
  307. } else {
  308. status = STATUS_INVALID_PARAMETER;
  309. }
  310. }
  311. break;
  312. case IOCTL_IP_DELETE_NTE:
  313. {
  314. PIP_DELETE_NTE_REQUEST request;
  315. IP_STATUS ipStatus;
  316. request = Irp->AssociatedIrp.SystemBuffer;
  317. //
  318. // Validate input parameters
  319. //
  320. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  321. sizeof(IP_DELETE_NTE_REQUEST)
  322. ) {
  323. ipStatus = IPDeleteDynamicNTE(
  324. request->Context
  325. );
  326. status = IPStatusToNTStatus(ipStatus);
  327. } else {
  328. status = STATUS_INVALID_PARAMETER;
  329. }
  330. }
  331. break;
  332. case IOCTL_IP_GET_NTE_INFO:
  333. {
  334. PIP_GET_NTE_INFO_REQUEST request;
  335. PIP_GET_NTE_INFO_RESPONSE response;
  336. BOOLEAN retval;
  337. ushort nteFlags;
  338. request = Irp->AssociatedIrp.SystemBuffer;
  339. response = (PIP_GET_NTE_INFO_RESPONSE) request;
  340. //
  341. // Validate input parameters
  342. //
  343. if ((IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  344. sizeof(IP_GET_NTE_INFO_REQUEST)
  345. )
  346. &&
  347. (IrpSp->Parameters.DeviceIoControl.OutputBufferLength >=
  348. sizeof(IP_GET_NTE_INFO_RESPONSE))
  349. ) {
  350. retval = (BOOLEAN) IPGetNTEInfo(
  351. request->Context,
  352. &(response->Instance),
  353. &(response->Address),
  354. &(response->SubnetMask),
  355. &nteFlags
  356. );
  357. if (retval == FALSE) {
  358. status = STATUS_UNSUCCESSFUL;
  359. } else {
  360. status = STATUS_SUCCESS;
  361. Irp->IoStatus.Information =
  362. sizeof(IP_GET_NTE_INFO_RESPONSE);
  363. response->Flags = 0;
  364. if (nteFlags & NTE_DYNAMIC) {
  365. response->Flags |= IP_NTE_DYNAMIC;
  366. }
  367. }
  368. } else {
  369. status = STATUS_INVALID_PARAMETER;
  370. }
  371. }
  372. break;
  373. case IOCTL_IP_SET_DHCP_INTERFACE:
  374. {
  375. PIP_SET_DHCP_INTERFACE_REQUEST request;
  376. BOOLEAN retval;
  377. request = Irp->AssociatedIrp.SystemBuffer;
  378. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IP_SET_DHCP_INTERFACE_REQUEST)) {
  379. retval = (BOOLEAN) SetDHCPNTE(
  380. request->Context
  381. );
  382. if (retval == FALSE) {
  383. status = STATUS_UNSUCCESSFUL;
  384. } else {
  385. status = STATUS_SUCCESS;
  386. }
  387. } else {
  388. status = STATUS_INVALID_PARAMETER;
  389. }
  390. }
  391. break;
  392. case IOCTL_IP_SET_IF_CONTEXT:
  393. {
  394. status = STATUS_NOT_SUPPORTED;
  395. }
  396. break;
  397. case IOCTL_IP_SET_IF_PROMISCUOUS:
  398. {
  399. PIP_SET_IF_PROMISCUOUS_INFO info;
  400. info = Irp->AssociatedIrp.SystemBuffer;
  401. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IP_SET_IF_PROMISCUOUS_INFO)) {
  402. status = SetIFPromiscuous(info->Index,
  403. info->Type,
  404. info->Add);
  405. } else {
  406. status = STATUS_BUFFER_TOO_SMALL;
  407. }
  408. break;
  409. }
  410. case IOCTL_IP_GET_BESTINTFC_FUNC_ADDR:
  411. if (Irp->RequestorMode != KernelMode) {
  412. status = STATUS_ACCESS_DENIED;
  413. break;
  414. }
  415. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "ip:Getbestinterfacequery\n"));
  416. status = STATUS_INVALID_PARAMETER;
  417. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ulong)) {
  418. PULONG_PTR ptr;
  419. ptr = Irp->AssociatedIrp.SystemBuffer;
  420. if (ptr) {
  421. *ptr = (ULONG_PTR) IPGetBestInterfaceIndex;
  422. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL, "ip:returning address of Getbestinterface %x\n", *ptr));
  423. Irp->IoStatus.Information = sizeof(ULONG_PTR);
  424. status = STATUS_SUCCESS;
  425. }
  426. }
  427. break;
  428. case IOCTL_IP_SET_FILTER_POINTER:
  429. {
  430. PIP_SET_FILTER_HOOK_INFO info;
  431. if (Irp->RequestorMode != KernelMode) {
  432. status = STATUS_ACCESS_DENIED;
  433. break;
  434. }
  435. info = Irp->AssociatedIrp.SystemBuffer;
  436. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IP_SET_FILTER_HOOK_INFO)) {
  437. status = (NTSTATUS) SetFilterPtr(info->FilterPtr);
  438. if (status != IP_SUCCESS) {
  439. ASSERT(status != IP_PENDING);
  440. //
  441. // Map status
  442. //
  443. status = STATUS_UNSUCCESSFUL;
  444. } else {
  445. status = STATUS_SUCCESS;
  446. }
  447. } else {
  448. status = STATUS_INVALID_PARAMETER;
  449. }
  450. }
  451. break;
  452. case IOCTL_IP_SET_FIREWALL_HOOK:
  453. {
  454. PIP_SET_FIREWALL_HOOK_INFO info;
  455. if (Irp->RequestorMode != KernelMode) {
  456. status = STATUS_ACCESS_DENIED;
  457. break;
  458. }
  459. info = Irp->AssociatedIrp.SystemBuffer;
  460. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IP_SET_FIREWALL_HOOK_INFO)) {
  461. status = (NTSTATUS) SetFirewallHook(info);
  462. if (status != IP_SUCCESS) {
  463. ASSERT(status != IP_PENDING);
  464. //
  465. // Map status
  466. //
  467. status = STATUS_UNSUCCESSFUL;
  468. } else {
  469. status = STATUS_SUCCESS;
  470. }
  471. } else {
  472. status = STATUS_INVALID_PARAMETER;
  473. }
  474. }
  475. break;
  476. case IOCTL_IP_SET_MAP_ROUTE_POINTER:
  477. {
  478. PIP_SET_MAP_ROUTE_HOOK_INFO info;
  479. if (Irp->RequestorMode != KernelMode) {
  480. status = STATUS_ACCESS_DENIED;
  481. break;
  482. }
  483. info = Irp->AssociatedIrp.SystemBuffer;
  484. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IP_SET_MAP_ROUTE_HOOK_INFO)) {
  485. status = (NTSTATUS) SetMapRoutePtr(info->MapRoutePtr);
  486. if (status != IP_SUCCESS) {
  487. ASSERT(status != IP_PENDING);
  488. //
  489. // Map status
  490. //
  491. status = STATUS_UNSUCCESSFUL;
  492. } else {
  493. status = STATUS_SUCCESS;
  494. }
  495. } else {
  496. status = STATUS_INVALID_PARAMETER;
  497. }
  498. }
  499. break;
  500. case IOCTL_IP_RTCHANGE_NOTIFY_REQUEST:
  501. {
  502. status = RtChangeNotifyRequest(Irp, IrpSp);
  503. break;
  504. }
  505. case IOCTL_IP_RTCHANGE_NOTIFY_REQUEST_EX:
  506. {
  507. status = RtChangeNotifyRequestEx(Irp, IrpSp);
  508. break;
  509. }
  510. case IOCTL_IP_ADDCHANGE_NOTIFY_REQUEST:
  511. {
  512. status = AddrChangeNotifyRequest(Irp, IrpSp);
  513. break;
  514. }
  515. #if MILLEN
  516. case IOCTL_IP_IFCHANGE_NOTIFY_REQUEST:
  517. {
  518. status = IfChangeNotifyRequest(Irp, IrpSp);
  519. break;
  520. }
  521. // For non-MILLEN, will default and return NOT_IMPLEMENTED.
  522. #endif // MILLEN
  523. case IOCTL_IP_CANCEL_CHANGE_NOTIFY:
  524. {
  525. PVOID ApcContext = NULL;
  526. status = STATUS_SUCCESS;
  527. #if defined(_WIN64)
  528. if (IoIs32bitProcess(Irp)) {
  529. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength !=
  530. sizeof(VOID * POINTER_32)) {
  531. status = STATUS_INVALID_BUFFER_SIZE;
  532. } else {
  533. ApcContext =
  534. (PVOID)*(VOID * POINTER_32 *)
  535. Irp->AssociatedIrp.SystemBuffer;
  536. }
  537. } else {
  538. #endif // _WIN64
  539. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength !=
  540. sizeof(PVOID)) {
  541. status = STATUS_INVALID_BUFFER_SIZE;
  542. } else {
  543. ApcContext = *(PVOID*)Irp->AssociatedIrp.SystemBuffer;
  544. }
  545. #if defined(_WIN64)
  546. }
  547. #endif // _WIN64
  548. if (NT_SUCCESS(status)) {
  549. status = CancelChangeNotifyRequest(Irp, IrpSp, ApcContext);
  550. }
  551. break;
  552. }
  553. case IOCTL_IP_UNIDIRECTIONAL_ADAPTER_ADDRESS:
  554. {
  555. Interface *pIf;
  556. ULONG cUniIF;
  557. ULONG cbRequired;
  558. PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pUniAdapterAddress;
  559. IPAddr *pUniIpAddr;
  560. CTELockHandle Handle;
  561. CTEGetLock(&RouteTableLock.Lock, &Handle);
  562. //
  563. // First off, count the number of unidirectional interfaces
  564. // and bytes required.
  565. //
  566. cUniIF = 0;
  567. cbRequired = FIELD_OFFSET(IP_UNIDIRECTIONAL_ADAPTER_ADDRESS, Address);
  568. for (pIf = IFList; pIf != NULL; pIf = pIf->if_next) {
  569. if (pIf->if_flags & IF_FLAGS_UNI) {
  570. cUniIF++;
  571. }
  572. }
  573. cbRequired = FIELD_OFFSET(IP_UNIDIRECTIONAL_ADAPTER_ADDRESS, Address[cUniIF]);
  574. if (cUniIF == 0) {
  575. cbRequired = sizeof(IP_UNIDIRECTIONAL_ADAPTER_ADDRESS);
  576. }
  577. //
  578. // Validate output buffer length and copy.
  579. //
  580. if (cbRequired <= IrpSp->Parameters.DeviceIoControl.OutputBufferLength) {
  581. pUniAdapterAddress = Irp->AssociatedIrp.SystemBuffer;
  582. pUniAdapterAddress->NumAdapters = cUniIF;
  583. pUniIpAddr = &pUniAdapterAddress->Address[0];
  584. if (cUniIF) {
  585. for (pIf = IFList; pIf != NULL; pIf = pIf->if_next) {
  586. if (pIf->if_flags & IF_FLAGS_UNI) {
  587. *pUniIpAddr++ = net_long(pIf->if_index);
  588. }
  589. }
  590. } else {
  591. //
  592. // In the case of 0 unidirectional interfaces, we should still
  593. // set the ip address instead of exposing some random kernel content
  594. //
  595. *pUniIpAddr = 0;
  596. }
  597. Irp->IoStatus.Information = cbRequired;
  598. status = STATUS_SUCCESS;
  599. } else {
  600. Irp->IoStatus.Information = 0;
  601. status = STATUS_BUFFER_OVERFLOW;
  602. }
  603. CTEFreeLock(&RouteTableLock.Lock, Handle);
  604. break;
  605. }
  606. case IOCTL_IP_GET_PNP_ARP_POINTERS:
  607. {
  608. PIP_GET_PNP_ARP_POINTERS info = (PIP_GET_PNP_ARP_POINTERS) Irp->AssociatedIrp.SystemBuffer;
  609. if (Irp->RequestorMode != KernelMode) {
  610. status = STATUS_ACCESS_DENIED;
  611. break;
  612. }
  613. info->IPAddInterface = (IPAddInterfacePtr) IPAddInterface;
  614. info->IPDelInterface = (IPDelInterfacePtr) IPDelInterface;
  615. Irp->IoStatus.Status = STATUS_SUCCESS;
  616. Irp->IoStatus.Information = sizeof(IP_GET_PNP_ARP_POINTERS);
  617. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  618. return STATUS_SUCCESS;;
  619. }
  620. break;
  621. case IOCTL_IP_WAKEUP_PATTERN:
  622. {
  623. PIP_WAKEUP_PATTERN_REQUEST Info = (PIP_WAKEUP_PATTERN_REQUEST) Irp->AssociatedIrp.SystemBuffer;
  624. if (Irp->RequestorMode != KernelMode) {
  625. status = STATUS_ACCESS_DENIED;
  626. break;
  627. }
  628. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  629. sizeof(IP_WAKEUP_PATTERN_REQUEST)) {
  630. status = IPWakeupPattern(
  631. Info->InterfaceContext,
  632. Info->PtrnDesc,
  633. Info->AddPattern);
  634. } else {
  635. status = STATUS_INVALID_PARAMETER;
  636. }
  637. }
  638. break;
  639. case IOCTL_IP_GET_WOL_CAPABILITY:
  640. {
  641. PULONG request, response;
  642. request = Irp->AssociatedIrp.SystemBuffer;
  643. response = request;
  644. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  645. sizeof(*request) &&
  646. IrpSp->Parameters.DeviceIoControl.OutputBufferLength >=
  647. sizeof(*response)) {
  648. status = IPGetCapability(*request, (uchar*)response,
  649. IF_WOL_CAP);
  650. } else {
  651. status = STATUS_BUFFER_TOO_SMALL;
  652. }
  653. if (status == STATUS_SUCCESS) {
  654. Irp->IoStatus.Information = sizeof(*response);
  655. }
  656. break;
  657. }
  658. case IOCTL_IP_GET_OFFLOAD_CAPABILITY:
  659. {
  660. PULONG request;
  661. IFOffloadCapability* response;
  662. request = Irp->AssociatedIrp.SystemBuffer;
  663. response = (IFOffloadCapability*)request;
  664. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  665. sizeof(*request) &&
  666. IrpSp->Parameters.DeviceIoControl.OutputBufferLength >=
  667. sizeof(*response)) {
  668. status = IPGetCapability(*request, (uchar*)response,
  669. IF_OFFLOAD_CAP);
  670. } else {
  671. status = STATUS_BUFFER_TOO_SMALL;
  672. }
  673. if (status == STATUS_SUCCESS) {
  674. Irp->IoStatus.Information = sizeof(*response);
  675. }
  676. break;
  677. }
  678. case IOCTL_IP_GET_IP_EVENT:
  679. return (DispatchIPGetIPEvent(Irp, IrpSp));
  680. case IOCTL_IP_FLUSH_ARP_TABLE:
  681. status = FlushArpTable(Irp, IrpSp);
  682. break;
  683. case IOCTL_IP_GET_IF_INDEX:
  684. status = IPGetIfIndex(Irp,
  685. IrpSp);
  686. break;
  687. case IOCTL_IP_GET_IF_NAME:
  688. status = IPGetIfName(Irp,
  689. IrpSp);
  690. break;
  691. case IOCTL_IP_GET_MCAST_COUNTERS:
  692. return (IPGetMcastCounters(Irp,IrpSp));
  693. case IOCTL_IP_ENABLE_ROUTER_REQUEST:
  694. status = IPEnableRouterRequest(Irp, IrpSp);
  695. break;
  696. case IOCTL_IP_UNENABLE_ROUTER_REQUEST: {
  697. PVOID ApcContext = NULL;
  698. status = STATUS_SUCCESS;
  699. #if defined(_WIN64)
  700. if (IoIs32bitProcess(Irp)) {
  701. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength !=
  702. sizeof(VOID * POINTER_32) ||
  703. IrpSp->Parameters.DeviceIoControl.OutputBufferLength !=
  704. sizeof(ULONG)) {
  705. status = STATUS_INVALID_BUFFER_SIZE;
  706. } else {
  707. ApcContext =
  708. (PVOID)*(VOID * POINTER_32 *)
  709. Irp->AssociatedIrp.SystemBuffer;
  710. }
  711. } else {
  712. #endif // _WIN64
  713. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength !=
  714. sizeof(PVOID) ||
  715. IrpSp->Parameters.DeviceIoControl.OutputBufferLength !=
  716. sizeof(ULONG)) {
  717. status = STATUS_INVALID_BUFFER_SIZE;
  718. } else {
  719. ApcContext = *(PVOID*)Irp->AssociatedIrp.SystemBuffer;
  720. }
  721. #if defined(_WIN64)
  722. }
  723. #endif // _WIN64
  724. if (NT_SUCCESS(status)) {
  725. status = IPUnenableRouterRequest(Irp, IrpSp, ApcContext);
  726. }
  727. break;
  728. }
  729. #if DBG_MAP_BUFFER
  730. case IOCTL_IP_DBG_TEST_FAIL_MAP_BUFFER:
  731. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(ULONG)) {
  732. status = STATUS_INVALID_BUFFER_SIZE;
  733. } else {
  734. PULONG pBuf = (PULONG) Irp->AssociatedIrp.SystemBuffer;
  735. status = DbgTestFailMapBuffers(
  736. *pBuf);
  737. }
  738. break;
  739. #endif // DBG_MAP_BUFFER
  740. case IOCTL_IP_ENABLE_MEDIA_SENSE_REQUEST: {
  741. PVOID ApcContext = NULL;
  742. status = STATUS_SUCCESS;
  743. #if defined(_WIN64)
  744. if (IoIs32bitProcess(Irp)) {
  745. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength !=
  746. sizeof(VOID* POINTER_32) ||
  747. IrpSp->Parameters.DeviceIoControl.OutputBufferLength !=
  748. sizeof(ULONG)) {
  749. status = STATUS_INVALID_BUFFER_SIZE;
  750. } else {
  751. ApcContext = (PVOID)*(VOID * POINTER_32 *)
  752. Irp->AssociatedIrp.SystemBuffer;
  753. }
  754. } else {
  755. #endif // _WIN64
  756. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength !=
  757. sizeof(PVOID) ||
  758. IrpSp->Parameters.DeviceIoControl.OutputBufferLength !=
  759. sizeof(ULONG)) {
  760. status = STATUS_INVALID_BUFFER_SIZE;
  761. } else {
  762. ApcContext = *(PVOID*)Irp->AssociatedIrp.SystemBuffer;
  763. }
  764. #if defined(_WIN64)
  765. }
  766. #endif // _WIN64
  767. if (NT_SUCCESS(status)) {
  768. status = IPEnableMediaSenseRequest(Irp, IrpSp, ApcContext);
  769. }
  770. break;
  771. }
  772. case IOCTL_IP_DISABLE_MEDIA_SENSE_REQUEST:
  773. status = IPDisableMediaSenseRequest(Irp, IrpSp);
  774. break;
  775. default:
  776. status = STATUS_NOT_IMPLEMENTED;
  777. break;
  778. }
  779. if ((status != IP_PENDING) && (status != STATUS_PENDING)) {
  780. Irp->IoStatus.Status = status;
  781. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  782. }
  783. return status;
  784. }
  785. NTSTATUS
  786. IPDispatchInternalDeviceControl(
  787. IN PIRP Irp,
  788. IN PIO_STACK_LOCATION IrpSp
  789. )
  790. /*++
  791. Routine Description:
  792. Arguments:
  793. Irp - Pointer to I/O request packet
  794. IrpSp - Pointer to the current stack location in the Irp.
  795. Return Value:
  796. NTSTATUS -- Indicates whether the request was successfully queued.
  797. --*/
  798. {
  799. NTSTATUS status;
  800. UNREFERENCED_PARAMETER(IrpSp);
  801. PAGED_CODE();
  802. status = STATUS_SUCCESS;
  803. Irp->IoStatus.Status = status;
  804. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  805. return status;
  806. }
  807. NTSTATUS
  808. IPCreate(
  809. IN PIRP Irp,
  810. IN PIO_STACK_LOCATION IrpSp
  811. )
  812. /*++
  813. Routine Description:
  814. Arguments:
  815. Irp - Pointer to I/O request packet
  816. IrpSp - Pointer to the current stack location in the Irp.
  817. Return Value:
  818. NTSTATUS -- Indicates whether the request was successfully queued.
  819. --*/
  820. {
  821. UNREFERENCED_PARAMETER(Irp);
  822. UNREFERENCED_PARAMETER(IrpSp);
  823. PAGED_CODE();
  824. return (STATUS_SUCCESS);
  825. }
  826. NTSTATUS
  827. IPCleanup(
  828. IN PIRP Irp,
  829. IN PIO_STACK_LOCATION IrpSp
  830. )
  831. /*++
  832. Routine Description:
  833. Arguments:
  834. Irp - Pointer to I/O request packet
  835. IrpSp - Pointer to the current stack location in the Irp.
  836. Return Value:
  837. NTSTATUS -- Indicates whether the request was successfully queued.
  838. --*/
  839. {
  840. PPENDING_IRP pendingIrp;
  841. PLIST_ENTRY entry, nextEntry;
  842. KIRQL oldIrql;
  843. LIST_ENTRY completeList;
  844. PIRP cancelledIrp;
  845. UNREFERENCED_PARAMETER(Irp);
  846. InitializeListHead(&completeList);
  847. //
  848. // Collect all of the pending IRPs on this file object.
  849. //
  850. IoAcquireCancelSpinLock(&oldIrql);
  851. entry = PendingArpSendList.Flink;
  852. while (entry != &PendingArpSendList) {
  853. pendingIrp = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  854. if (pendingIrp->FileObject == IrpSp->FileObject) {
  855. nextEntry = entry->Flink;
  856. RemoveEntryList(entry);
  857. IoSetCancelRoutine(pendingIrp->Irp, NULL);
  858. InsertTailList(&completeList, &(pendingIrp->Linkage));
  859. entry = nextEntry;
  860. } else {
  861. entry = entry->Flink;
  862. }
  863. }
  864. IoReleaseCancelSpinLock(oldIrql);
  865. //
  866. // Complete them.
  867. //
  868. entry = completeList.Flink;
  869. while (entry != &completeList) {
  870. pendingIrp = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  871. cancelledIrp = pendingIrp->Irp;
  872. entry = entry->Flink;
  873. //
  874. // Free the PENDING_IRP structure. The control block will be freed
  875. // when the request completes.
  876. //
  877. CTEFreeMem(pendingIrp);
  878. //
  879. // Complete the IRP.
  880. //
  881. cancelledIrp->IoStatus.Information = 0;
  882. cancelledIrp->IoStatus.Status = STATUS_CANCELLED;
  883. IoCompleteRequest(cancelledIrp, IO_NETWORK_INCREMENT);
  884. }
  885. InitializeListHead(&completeList);
  886. //
  887. // Collect all of the pending IRPs on this file object.
  888. //
  889. IoAcquireCancelSpinLock(&oldIrql);
  890. entry = PendingEchoList.Flink;
  891. while (entry != &PendingEchoList) {
  892. pendingIrp = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  893. if (pendingIrp->FileObject == IrpSp->FileObject) {
  894. nextEntry = entry->Flink;
  895. RemoveEntryList(entry);
  896. IoSetCancelRoutine(pendingIrp->Irp, NULL);
  897. InsertTailList(&completeList, &(pendingIrp->Linkage));
  898. entry = nextEntry;
  899. } else {
  900. entry = entry->Flink;
  901. }
  902. }
  903. IoReleaseCancelSpinLock(oldIrql);
  904. //
  905. // Complete them.
  906. //
  907. entry = completeList.Flink;
  908. while (entry != &completeList) {
  909. pendingIrp = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  910. cancelledIrp = pendingIrp->Irp;
  911. entry = entry->Flink;
  912. //
  913. // Free the PENDING_IRP structure. The control block will be freed
  914. // when the request completes.
  915. //
  916. CTEFreeMem(pendingIrp);
  917. //
  918. // Complete the IRP.
  919. //
  920. cancelledIrp->IoStatus.Information = 0;
  921. cancelledIrp->IoStatus.Status = STATUS_CANCELLED;
  922. IoCompleteRequest(cancelledIrp, IO_NETWORK_INCREMENT);
  923. }
  924. InitializeListHead(&completeList);
  925. //
  926. // Collect all of the pending IRPs on this file object.
  927. //
  928. IoAcquireCancelSpinLock(&oldIrql);
  929. entry = PendingIPSetNTEAddrList.Flink;
  930. while (entry != &PendingIPSetNTEAddrList) {
  931. pendingIrp = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  932. if (pendingIrp->FileObject == IrpSp->FileObject) {
  933. nextEntry = entry->Flink;
  934. RemoveEntryList(entry);
  935. IoSetCancelRoutine(pendingIrp->Irp, NULL);
  936. InsertTailList(&completeList, &(pendingIrp->Linkage));
  937. entry = nextEntry;
  938. } else {
  939. entry = entry->Flink;
  940. }
  941. }
  942. IoReleaseCancelSpinLock(oldIrql);
  943. //
  944. // Complete them.
  945. //
  946. entry = completeList.Flink;
  947. while (entry != &completeList) {
  948. pendingIrp = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  949. cancelledIrp = pendingIrp->Irp;
  950. entry = entry->Flink;
  951. //
  952. // Free the PENDING_IRP structure. The control block will be freed
  953. // when the request completes.
  954. //
  955. CTEFreeMem(pendingIrp);
  956. //
  957. // Complete the IRP.
  958. //
  959. cancelledIrp->IoStatus.Information = 0;
  960. cancelledIrp->IoStatus.Status = STATUS_CANCELLED;
  961. IoCompleteRequest(cancelledIrp, IO_NETWORK_INCREMENT);
  962. }
  963. //
  964. // complete the pending irp for media sense
  965. //
  966. cancelledIrp = NULL;
  967. IoAcquireCancelSpinLock(&oldIrql);
  968. if (PendingIPGetIPEventRequest && IoGetCurrentIrpStackLocation(PendingIPGetIPEventRequest)->FileObject == IrpSp->FileObject) {
  969. cancelledIrp = PendingIPGetIPEventRequest;
  970. PendingIPGetIPEventRequest = NULL;
  971. IoSetCancelRoutine(cancelledIrp, NULL);
  972. }
  973. IoReleaseCancelSpinLock(oldIrql);
  974. if (cancelledIrp) {
  975. cancelledIrp->IoStatus.Information = 0;
  976. cancelledIrp->IoStatus.Status = STATUS_CANCELLED;
  977. IoCompleteRequest(cancelledIrp, IO_NETWORK_INCREMENT);
  978. }
  979. return (STATUS_SUCCESS);
  980. }
  981. NTSTATUS
  982. IPClose(
  983. IN PIRP Irp,
  984. IN PIO_STACK_LOCATION IrpSp
  985. )
  986. /*++
  987. Routine Description:
  988. Arguments:
  989. Irp - Pointer to I/O request packet
  990. IrpSp - Pointer to the current stack location in the Irp.
  991. Return Value:
  992. NTSTATUS -- Indicates whether the request was successfully queued.
  993. --*/
  994. {
  995. UNREFERENCED_PARAMETER(Irp);
  996. UNREFERENCED_PARAMETER(IrpSp);
  997. PAGED_CODE();
  998. return (STATUS_SUCCESS);
  999. }
  1000. //
  1001. // ARP send function definitions
  1002. //
  1003. VOID
  1004. CancelArpSendRequest(
  1005. IN PDEVICE_OBJECT Device,
  1006. IN PIRP Irp
  1007. )
  1008. /*++
  1009. Routine Description:
  1010. Cancels an outstanding ARP request Irp.
  1011. Arguments:
  1012. Device - The device on which the request was issued.
  1013. Irp - Pointer to I/O request packet to cancel.
  1014. Return Value:
  1015. None.
  1016. Notes:
  1017. This function is called with cancel spinlock held. It must be
  1018. released before the function returns.
  1019. The ARP control block associated with this request cannot be
  1020. freed until the request completes. The completion routine will
  1021. free it.
  1022. --*/
  1023. {
  1024. PPENDING_IRP pendingIrp = NULL;
  1025. PPENDING_IRP item;
  1026. PLIST_ENTRY entry;
  1027. UNREFERENCED_PARAMETER(Device);
  1028. for (entry = PendingArpSendList.Flink;
  1029. entry != &PendingArpSendList;
  1030. entry = entry->Flink
  1031. ) {
  1032. item = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  1033. if (item->Irp == Irp) {
  1034. pendingIrp = item;
  1035. RemoveEntryList(entry);
  1036. break;
  1037. }
  1038. }
  1039. IoReleaseCancelSpinLock(Irp->CancelIrql);
  1040. if (pendingIrp != NULL) {
  1041. //
  1042. // Free the PENDING_IRP structure. The control block will be freed
  1043. // when the request completes.
  1044. //
  1045. CTEFreeMem(pendingIrp);
  1046. //
  1047. // Complete the IRP.
  1048. //
  1049. Irp->IoStatus.Information = 0;
  1050. Irp->IoStatus.Status = STATUS_CANCELLED;
  1051. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  1052. }
  1053. return;
  1054. }
  1055. NTSTATUS
  1056. RtChangeNotifyRequest(
  1057. PIRP Irp,
  1058. IN PIO_STACK_LOCATION IrpSp
  1059. )
  1060. {
  1061. CTELockHandle TableHandle;
  1062. KIRQL OldIrq;
  1063. NTSTATUS status;
  1064. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength &&
  1065. IrpSp->Parameters.DeviceIoControl.InputBufferLength <
  1066. sizeof(IPNotifyData)) {
  1067. status = STATUS_INVALID_PARAMETER;
  1068. goto done;
  1069. }
  1070. #if MILLEN
  1071. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength &&
  1072. IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1073. sizeof(IP_RTCHANGE_NOTIFY)) {
  1074. status = STATUS_INVALID_PARAMETER;
  1075. goto done;
  1076. }
  1077. #endif // MILLEN
  1078. IoAcquireCancelSpinLock(&OldIrq);
  1079. CTEGetLock(&RouteTableLock.Lock, &TableHandle);
  1080. Irp->Tail.Overlay.DriverContext[0] = IrpSp->FileObject;
  1081. InsertTailList(&RtChangeNotifyQueue, &Irp->Tail.Overlay.ListEntry);
  1082. if (Irp->Cancel) {
  1083. RemoveTailList(&RtChangeNotifyQueue);
  1084. status = STATUS_CANCELLED;
  1085. } else {
  1086. IoMarkIrpPending(Irp);
  1087. IoSetCancelRoutine(Irp, RtChangeNotifyCancel);
  1088. status = STATUS_PENDING;
  1089. }
  1090. Irp->IoStatus.Information = 0;
  1091. CTEFreeLock(&RouteTableLock.Lock, TableHandle);
  1092. IoReleaseCancelSpinLock(OldIrq);
  1093. done:
  1094. return status;
  1095. }
  1096. NTSTATUS
  1097. RtChangeNotifyRequestEx(
  1098. PIRP Irp,
  1099. IN PIO_STACK_LOCATION IrpSp
  1100. )
  1101. {
  1102. CTELockHandle TableHandle;
  1103. KIRQL OldIrq;
  1104. NTSTATUS status;
  1105. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength &&
  1106. IrpSp->Parameters.DeviceIoControl.InputBufferLength <
  1107. sizeof(IPNotifyData)) {
  1108. status = STATUS_INVALID_PARAMETER;
  1109. goto done;
  1110. }
  1111. #if MILLEN
  1112. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength &&
  1113. IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1114. sizeof(IP_RTCHANGE_NOTIFY)) {
  1115. status = STATUS_INVALID_PARAMETER;
  1116. goto done;
  1117. }
  1118. #endif // MILLEN
  1119. IoAcquireCancelSpinLock(&OldIrq);
  1120. CTEGetLock(&RouteTableLock.Lock, &TableHandle);
  1121. Irp->Tail.Overlay.DriverContext[0] = IrpSp->FileObject;
  1122. InsertTailList(&RtChangeNotifyQueueEx, &Irp->Tail.Overlay.ListEntry);
  1123. if (Irp->Cancel) {
  1124. RemoveTailList(&RtChangeNotifyQueueEx);
  1125. status = STATUS_CANCELLED;
  1126. } else {
  1127. IoMarkIrpPending(Irp);
  1128. IoSetCancelRoutine(Irp, RtChangeNotifyCancelEx);
  1129. status = STATUS_PENDING;
  1130. }
  1131. Irp->IoStatus.Information = 0;
  1132. CTEFreeLock(&RouteTableLock.Lock, TableHandle);
  1133. IoReleaseCancelSpinLock(OldIrq);
  1134. done:
  1135. return status;
  1136. }
  1137. NTSTATUS
  1138. AddrChangeNotifyRequest(PIRP Irp, PIO_STACK_LOCATION pIrpSp)
  1139. {
  1140. CTELockHandle TableHandle;
  1141. KIRQL OldIrq;
  1142. NTSTATUS status;
  1143. UNREFERENCED_PARAMETER(pIrpSp);
  1144. DEBUGMSG(DBG_TRACE && DBG_NOTIFY,
  1145. (DTEXT("AddrChangeNotifyRequest(%x, %x)\n"), Irp, pIrpSp));
  1146. #if MILLEN
  1147. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength) {
  1148. PIP_ADDCHANGE_NOTIFY pNotify = Irp->AssociatedIrp.SystemBuffer;
  1149. DEBUGMSG(DBG_INFO && DBG_NOTIFY,
  1150. (DTEXT("AddrChangeNotifyRequest OutputLen %d, MaxCfgName %d\n"),
  1151. pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  1152. pNotify->ConfigName.MaximumLength));
  1153. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1154. (FIELD_OFFSET(IP_ADDCHANGE_NOTIFY, NameData) + (ULONG) pNotify->ConfigName.MaximumLength)) {
  1155. DEBUGMSG(DBG_ERROR,
  1156. (DTEXT("AddrChangeNotifyRequest: INVALID output buffer length.\n")));
  1157. status = STATUS_INVALID_PARAMETER;
  1158. goto done;
  1159. }
  1160. }
  1161. #endif // MILLEN
  1162. IoAcquireCancelSpinLock(&OldIrq);
  1163. CTEGetLock(&AddChangeLock, &TableHandle);
  1164. Irp->Tail.Overlay.DriverContext[0] = pIrpSp->FileObject;
  1165. InsertTailList(
  1166. &AddChangeNotifyQueue,
  1167. &(Irp->Tail.Overlay.ListEntry)
  1168. );
  1169. if (Irp->Cancel) {
  1170. (VOID) RemoveTailList(&AddChangeNotifyQueue);
  1171. status = STATUS_CANCELLED;
  1172. } else {
  1173. IoMarkIrpPending(Irp);
  1174. IoSetCancelRoutine(Irp, AddChangeNotifyCancel);
  1175. status = STATUS_PENDING;
  1176. }
  1177. Irp->IoStatus.Information = 0;
  1178. CTEFreeLock(&AddChangeLock, TableHandle);
  1179. IoReleaseCancelSpinLock(OldIrq);
  1180. #if MILLEN
  1181. done:
  1182. #endif // MILLEN
  1183. DEBUGMSG(DBG_TRACE && DBG_NOTIFY,
  1184. (DTEXT("-AddrChangeNotifyRequest [%x]\n"), status));
  1185. return status;
  1186. }
  1187. #if MILLEN
  1188. void
  1189. IfChangeNotifyCancel(
  1190. IN PDEVICE_OBJECT pDeviceObject,
  1191. IN PIRP pIrp
  1192. )
  1193. {
  1194. DEBUGMSG(DBG_TRACE && DBG_NOTIFY,
  1195. (DTEXT("IfChangeNotifyCancel(%x, %x)\n"), pDeviceObject, pIrp));
  1196. CancelNotify(pIrp, &IfChangeNotifyQueue, &IfChangeLock);
  1197. return;
  1198. }
  1199. NTSTATUS
  1200. IfChangeNotifyRequest(
  1201. PIRP pIrp,
  1202. PIO_STACK_LOCATION pIrpSp
  1203. )
  1204. {
  1205. CTELockHandle TableHandle;
  1206. KIRQL OldIrq;
  1207. NTSTATUS NtStatus;
  1208. DEBUGMSG(DBG_TRACE && DBG_NOTIFY,
  1209. (DTEXT("+IfChangeNotifyRequest(%x, %x)\n"), pIrp, pIrpSp));
  1210. //
  1211. // Check output buffer length. Output buffer will store the
  1212. // NTE context and whether the interface was added or deleted.
  1213. //
  1214. if (pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(IP_IFCHANGE_NOTIFY)) {
  1215. NtStatus = STATUS_INVALID_PARAMETER;
  1216. pIrp->IoStatus.Status = NtStatus;
  1217. pIrp->IoStatus.Information = 0;
  1218. goto done;
  1219. }
  1220. //
  1221. // Set cancel routine, mark IRP as pending and put on our interface
  1222. // notify list.
  1223. //
  1224. IoAcquireCancelSpinLock(&OldIrq);
  1225. IoMarkIrpPending(pIrp);
  1226. CTEGetLock(&IfChangeLock, &TableHandle);
  1227. InsertTailList(
  1228. &IfChangeNotifyQueue,
  1229. &(pIrp->Tail.Overlay.ListEntry)
  1230. );
  1231. if (pIrp->Cancel) {
  1232. RemoveTailList(&IfChangeNotifyQueue);
  1233. NtStatus = STATUS_CANCELLED;
  1234. } else {
  1235. IoSetCancelRoutine(pIrp, IfChangeNotifyCancel);
  1236. NtStatus = STATUS_PENDING;
  1237. }
  1238. pIrp->IoStatus.Information = 0;
  1239. CTEFreeLock(&IfChangeLock, TableHandle);
  1240. IoReleaseCancelSpinLock(OldIrq);
  1241. done:
  1242. DEBUGMSG(DBG_TRACE && DBG_NOTIFY,
  1243. (DTEXT("-IfChangeNotifyRequest [%x]\n"), NtStatus));
  1244. return NtStatus;
  1245. }
  1246. #endif // MILLEN
  1247. NTSTATUS
  1248. CancelChangeNotifyRequest(
  1249. PIRP Irp,
  1250. PIO_STACK_LOCATION IrpSp,
  1251. PVOID ApcContext
  1252. )
  1253. {
  1254. KIRQL CancelIrql;
  1255. UNREFERENCED_PARAMETER(Irp);
  1256. IoAcquireCancelSpinLock(&CancelIrql);
  1257. if (CancelNotifyByContext(IrpSp->FileObject, ApcContext,
  1258. &RtChangeNotifyQueue, &RouteTableLock) ||
  1259. CancelNotifyByContext(IrpSp->FileObject, ApcContext,
  1260. &RtChangeNotifyQueueEx, &RouteTableLock) ||
  1261. CancelNotifyByContext(IrpSp->FileObject, ApcContext,
  1262. &AddChangeNotifyQueue, &AddChangeLock)) {
  1263. KeLowerIrql(CancelIrql);
  1264. return STATUS_SUCCESS;
  1265. }
  1266. IoReleaseCancelSpinLock(CancelIrql);
  1267. return STATUS_INVALID_PARAMETER;
  1268. }
  1269. NTSTATUS
  1270. IPEnableRouterRequest(
  1271. PIRP Irp,
  1272. PIO_STACK_LOCATION IrpSp
  1273. )
  1274. {
  1275. KIRQL OldIrql;
  1276. NTSTATUS status;
  1277. IoAcquireCancelSpinLock(&OldIrql);
  1278. if (Irp->Cancel) {
  1279. status = STATUS_CANCELLED;
  1280. } else {
  1281. IoMarkIrpPending(Irp);
  1282. IoSetCancelRoutine(Irp, CancelIPEnableRouterRequest);
  1283. // Increment the routing-enabled reference count.
  1284. // When the count rises above zero routing is enabled.
  1285. // This reference will be dropped when the IRP is cancelled.
  1286. CTEGetLockAtDPC(&RouteTableLock.Lock);
  1287. Irp->Tail.Overlay.DriverContext[0] = IrpSp->FileObject;
  1288. InsertTailList(&PendingEnableRouterList, &Irp->Tail.Overlay.ListEntry);
  1289. IPEnableRouterWithRefCount(TRUE);
  1290. CTEFreeLockFromDPC(&RouteTableLock.Lock);
  1291. status = STATUS_PENDING;
  1292. }
  1293. Irp->IoStatus.Information = 0;
  1294. IoReleaseCancelSpinLock(OldIrql);
  1295. return status;
  1296. }
  1297. VOID
  1298. CancelIPEnableRouterRequest(
  1299. IN PDEVICE_OBJECT Device,
  1300. IN PIRP Irp
  1301. )
  1302. {
  1303. CTELockHandle TableHandle;
  1304. UNREFERENCED_PARAMETER(Device);
  1305. IoReleaseCancelSpinLock(Irp->CancelIrql);
  1306. // Decrement the routing-enabled reference count.
  1307. // If the count drops to zero routing is disabled.
  1308. CTEGetLock(&RouteTableLock.Lock, &TableHandle);
  1309. RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
  1310. IPEnableRouterWithRefCount(FALSE);
  1311. CTEFreeLock(&RouteTableLock.Lock, TableHandle);
  1312. Irp->IoStatus.Information = 0;
  1313. Irp->IoStatus.Status = STATUS_CANCELLED;
  1314. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  1315. }
  1316. NTSTATUS
  1317. IPUnenableRouterRequest(
  1318. PIRP Irp,
  1319. PIO_STACK_LOCATION IrpSp,
  1320. PVOID ApcContext
  1321. )
  1322. {
  1323. PLIST_ENTRY entry;
  1324. KIRQL CancelIrql;
  1325. int RefCount;
  1326. CTELockHandle TableHandle;
  1327. // Locate the pending IRP for the request corresponding to the caller's
  1328. // disable-request. Drop the routing-enabled reference-count, complete
  1329. // the corresponding IRP, and tell the caller what the reference-count's
  1330. // current value is.
  1331. IoAcquireCancelSpinLock(&CancelIrql);
  1332. CTEGetLock(&RouteTableLock.Lock, &TableHandle);
  1333. for (entry = PendingEnableRouterList.Flink;
  1334. entry != &PendingEnableRouterList;
  1335. entry = entry->Flink
  1336. ) {
  1337. PIRP EnableIrp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
  1338. if (EnableIrp->Tail.Overlay.DriverContext[0] == IrpSp->FileObject &&
  1339. EnableIrp->Overlay.AsynchronousParameters.UserApcContext ==
  1340. ApcContext) {
  1341. RemoveEntryList(&EnableIrp->Tail.Overlay.ListEntry);
  1342. RefCount = IPEnableRouterWithRefCount(FALSE);
  1343. CTEFreeLock(&RouteTableLock.Lock, TableHandle);
  1344. IoSetCancelRoutine(EnableIrp, NULL);
  1345. IoReleaseCancelSpinLock(CancelIrql);
  1346. EnableIrp->IoStatus.Status = STATUS_SUCCESS;
  1347. EnableIrp->IoStatus.Information = 0;
  1348. IoCompleteRequest(EnableIrp, IO_NETWORK_INCREMENT);
  1349. *(PULONG)Irp->AssociatedIrp.SystemBuffer = (ULONG)RefCount;
  1350. Irp->IoStatus.Information = sizeof(ULONG);
  1351. return STATUS_SUCCESS;
  1352. }
  1353. }
  1354. CTEFreeLock(&RouteTableLock.Lock, TableHandle);
  1355. IoReleaseCancelSpinLock(CancelIrql);
  1356. return STATUS_INVALID_PARAMETER;
  1357. }
  1358. //
  1359. // ICMP Echo function definitions
  1360. //
  1361. VOID
  1362. CancelEchoRequest(
  1363. IN PDEVICE_OBJECT Device,
  1364. IN PIRP Irp
  1365. )
  1366. /*++
  1367. Routine Description:
  1368. Cancels an outstanding Echo request Irp.
  1369. Arguments:
  1370. Device - The device on which the request was issued.
  1371. Irp - Pointer to I/O request packet to cancel.
  1372. Return Value:
  1373. None.
  1374. Notes:
  1375. This function is called with cancel spinlock held. It must be
  1376. released before the function returns.
  1377. The echo control block associated with this request cannot be
  1378. freed until the request completes. The completion routine will
  1379. free it.
  1380. --*/
  1381. {
  1382. PPENDING_IRP pendingIrp = NULL;
  1383. PPENDING_IRP item;
  1384. PLIST_ENTRY entry;
  1385. UNREFERENCED_PARAMETER(Device);
  1386. for (entry = PendingEchoList.Flink;
  1387. entry != &PendingEchoList;
  1388. entry = entry->Flink
  1389. ) {
  1390. item = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  1391. if (item->Irp == Irp) {
  1392. pendingIrp = item;
  1393. RemoveEntryList(entry);
  1394. break;
  1395. }
  1396. }
  1397. IoReleaseCancelSpinLock(Irp->CancelIrql);
  1398. if (pendingIrp != NULL) {
  1399. //
  1400. // Free the PENDING_IRP structure. The control block will be freed
  1401. // when the request completes.
  1402. //
  1403. CTEFreeMem(pendingIrp);
  1404. //
  1405. // Complete the IRP.
  1406. //
  1407. Irp->IoStatus.Information = 0;
  1408. Irp->IoStatus.Status = STATUS_CANCELLED;
  1409. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  1410. }
  1411. return;
  1412. }
  1413. //
  1414. // IP Set Addr function definitions
  1415. //
  1416. VOID
  1417. CancelIPSetNTEAddrRequest(
  1418. IN PDEVICE_OBJECT Device,
  1419. IN PIRP Irp
  1420. )
  1421. /*++
  1422. Routine Description:
  1423. Cancels an outstanding IP Set Addr request Irp.
  1424. Arguments:
  1425. Device - The device on which the request was issued.
  1426. Irp - Pointer to I/O request packet to cancel.
  1427. Return Value:
  1428. None.
  1429. Notes:
  1430. This function is called with cancel spinlock held. It must be
  1431. released before the function returns.
  1432. The IP Set Addr control block associated with this request cannot be
  1433. freed until the request completes. The completion routine will
  1434. free it.
  1435. --*/
  1436. {
  1437. PPENDING_IRP pendingIrp = NULL;
  1438. PPENDING_IRP item;
  1439. PLIST_ENTRY entry;
  1440. UNREFERENCED_PARAMETER(Device);
  1441. for (entry = PendingIPSetNTEAddrList.Flink;
  1442. entry != &PendingIPSetNTEAddrList;
  1443. entry = entry->Flink
  1444. ) {
  1445. item = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  1446. if (item->Irp == Irp) {
  1447. pendingIrp = item;
  1448. RemoveEntryList(entry);
  1449. break;
  1450. }
  1451. }
  1452. IoReleaseCancelSpinLock(Irp->CancelIrql);
  1453. if (pendingIrp != NULL) {
  1454. //
  1455. // Free the PENDING_IRP structure. The control block will be freed
  1456. // when the request completes.
  1457. //
  1458. CTEFreeMem(pendingIrp);
  1459. //
  1460. // Complete the IRP.
  1461. //
  1462. Irp->IoStatus.Information = 0;
  1463. Irp->IoStatus.Status = STATUS_CANCELLED;
  1464. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  1465. }
  1466. return;
  1467. }
  1468. VOID
  1469. CancelIPGetIPEventRequest(
  1470. IN PDEVICE_OBJECT Device,
  1471. IN PIRP Irp
  1472. )
  1473. /*++
  1474. Routine Description:
  1475. Cancels IPGetIPEvent function.
  1476. Arguments:
  1477. Device - The device on which the request was issued.
  1478. Irp - Pointer to I/O request packet to cancel.
  1479. Return Value:
  1480. None.
  1481. Notes:
  1482. This function is called with cancel spinlock held. It must be
  1483. released before the function returns.
  1484. The IP Set Addr control block associated with this request cannot be
  1485. freed until the request completes. The completion routine will
  1486. free it.
  1487. --*/
  1488. {
  1489. PIRP pendingIrp = NULL;
  1490. UNREFERENCED_PARAMETER(Device);
  1491. //
  1492. // We need to make sure that we are not completing this irp
  1493. // while we are in this cancel code. If we are completing
  1494. // this irp, the PendingIPGetIPEventRequest will either be
  1495. // NULL or contain next irp.
  1496. //
  1497. if (PendingIPGetIPEventRequest == Irp) {
  1498. pendingIrp = Irp;
  1499. PendingIPGetIPEventRequest = NULL;
  1500. }
  1501. IoReleaseCancelSpinLock(Irp->CancelIrql);
  1502. if (pendingIrp != NULL) {
  1503. pendingIrp->IoStatus.Information = 0;
  1504. pendingIrp->IoStatus.Status = STATUS_CANCELLED;
  1505. IoCompleteRequest(pendingIrp, IO_NETWORK_INCREMENT);
  1506. }
  1507. return;
  1508. }
  1509. void
  1510. CompleteEchoRequest(
  1511. EchoControl *controlBlock,
  1512. IP_STATUS Status,
  1513. void *Data, OPTIONAL
  1514. uint DataSize,
  1515. struct IPOptInfo *OptionInfo OPTIONAL
  1516. )
  1517. /*++
  1518. Routine Description:
  1519. Handles the completion of an ICMP Echo request
  1520. Arguments:
  1521. Context - Pointer to the EchoControl structure for this request.
  1522. Status - The IP status of the transmission.
  1523. Data - A pointer to data returned in the echo reply.
  1524. DataSize - The length of the returned data.
  1525. OptionInfo - A pointer to the IP options in the echo reply.
  1526. Return Value:
  1527. None.
  1528. --*/
  1529. {
  1530. KIRQL oldIrql;
  1531. PIRP irp = NULL;
  1532. PIO_STACK_LOCATION irpSp;
  1533. PPENDING_IRP pendingIrp = NULL;
  1534. PPENDING_IRP item;
  1535. PLIST_ENTRY entry;
  1536. ULONG bytesReturned;
  1537. //
  1538. // Find the echo request IRP on the pending list.
  1539. //
  1540. IoAcquireCancelSpinLock(&oldIrql);
  1541. for (entry = PendingEchoList.Flink;
  1542. entry != &PendingEchoList;
  1543. entry = entry->Flink
  1544. ) {
  1545. item = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  1546. if (item->Context == controlBlock) {
  1547. pendingIrp = item;
  1548. irp = pendingIrp->Irp;
  1549. IoSetCancelRoutine(irp, NULL);
  1550. RemoveEntryList(entry);
  1551. break;
  1552. }
  1553. }
  1554. IoReleaseCancelSpinLock(oldIrql);
  1555. if (pendingIrp == NULL) {
  1556. //
  1557. // IRP must have been cancelled. PENDING_IRP struct
  1558. // was freed by cancel routine. Free control block.
  1559. //
  1560. CTEFreeMem(controlBlock);
  1561. return;
  1562. }
  1563. irpSp = IoGetCurrentIrpStackLocation(irp);
  1564. #if defined(_WIN64)
  1565. if (IoIs32bitProcess(irp)) {
  1566. bytesReturned = ICMPEchoComplete32(controlBlock, Status, Data, DataSize,
  1567. OptionInfo);
  1568. } else {
  1569. #endif // _WIN64
  1570. bytesReturned = ICMPEchoComplete(controlBlock, Status, Data, DataSize,
  1571. OptionInfo);
  1572. #if defined(_WIN64)
  1573. }
  1574. #endif // _WIN64
  1575. CTEFreeMem(pendingIrp);
  1576. CTEFreeMem(controlBlock);
  1577. //
  1578. // Complete the IRP.
  1579. //
  1580. irp->IoStatus.Information = (ULONG) bytesReturned;
  1581. irp->IoStatus.Status = STATUS_SUCCESS;
  1582. IoCompleteRequest(irp, IO_NETWORK_INCREMENT);
  1583. return;
  1584. }
  1585. void
  1586. CompleteIPSetNTEAddrRequest(
  1587. void *Context,
  1588. IP_STATUS Status
  1589. )
  1590. /*++
  1591. Routine Description:
  1592. Handles the completion of an IP Set Addr request
  1593. Arguments:
  1594. Context - Pointer to the SetAddrControl structure for this request.
  1595. Status - The IP status of the transmission.
  1596. Return Value:
  1597. None.
  1598. --*/
  1599. {
  1600. KIRQL oldIrql;
  1601. PIRP irp = NULL;
  1602. SetAddrControl *controlBlock;
  1603. PPENDING_IRP pendingIrp = NULL;
  1604. PPENDING_IRP item;
  1605. PLIST_ENTRY entry;
  1606. controlBlock = (SetAddrControl *) Context;
  1607. //
  1608. // Find the echo request IRP on the pending list.
  1609. //
  1610. IoAcquireCancelSpinLock(&oldIrql);
  1611. for (entry = PendingIPSetNTEAddrList.Flink;
  1612. entry != &PendingIPSetNTEAddrList;
  1613. entry = entry->Flink
  1614. ) {
  1615. item = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  1616. if (item->Context == controlBlock) {
  1617. pendingIrp = item;
  1618. irp = pendingIrp->Irp;
  1619. IoSetCancelRoutine(irp, NULL);
  1620. RemoveEntryList(entry);
  1621. break;
  1622. }
  1623. }
  1624. IoReleaseCancelSpinLock(oldIrql);
  1625. if (pendingIrp == NULL) {
  1626. //
  1627. // IRP must have been cancelled. PENDING_IRP struct
  1628. // was freed by cancel routine. Free control block.
  1629. //
  1630. CTEFreeMem(controlBlock);
  1631. return;
  1632. }
  1633. CTEFreeMem(pendingIrp);
  1634. //
  1635. // Complete the IRP.
  1636. //
  1637. irp->IoStatus.Information = 0;
  1638. Status = IPStatusToNTStatus(Status);
  1639. irp->IoStatus.Status = Status;
  1640. CTEFreeMem(controlBlock);
  1641. IoCompleteRequest(irp, IO_NETWORK_INCREMENT);
  1642. return;
  1643. }
  1644. void
  1645. CheckSetAddrRequestOnInterface(
  1646. Interface *IF
  1647. )
  1648. /*++
  1649. Routine Description:
  1650. Handles the completion of an IP Set Addr request on an interface
  1651. that is getting unbound
  1652. Arguments:
  1653. IF - Pointer to the interface whish is getting deleted
  1654. Return Value:
  1655. None.
  1656. --*/
  1657. {
  1658. KIRQL oldIrql;
  1659. PIRP irp;
  1660. PPENDING_IRP pendingIrp = NULL;
  1661. PLIST_ENTRY entry, nextEntry;
  1662. LIST_ENTRY completeList;
  1663. SetAddrControl *controlBlock;
  1664. InitializeListHead(&completeList);
  1665. //
  1666. // Find pending set addr requests on this interface
  1667. //
  1668. IoAcquireCancelSpinLock(&oldIrql);
  1669. entry = PendingIPSetNTEAddrList.Flink;
  1670. while (entry != &PendingIPSetNTEAddrList) {
  1671. pendingIrp = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  1672. controlBlock = pendingIrp->Context;
  1673. if (controlBlock->interface == IF) {
  1674. // remove this entry
  1675. nextEntry = entry->Flink;
  1676. irp = pendingIrp->Irp;
  1677. IoSetCancelRoutine(irp, NULL);
  1678. RemoveEntryList(entry);
  1679. // reinsert this in to completelist
  1680. InsertTailList(&completeList, &(pendingIrp->Linkage));
  1681. entry = nextEntry;
  1682. } else {
  1683. entry = entry->Flink;
  1684. }
  1685. }
  1686. IoReleaseCancelSpinLock(oldIrql);
  1687. //
  1688. // Complete them.
  1689. //
  1690. entry = completeList.Flink;
  1691. while (entry != &completeList) {
  1692. pendingIrp = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  1693. irp = pendingIrp->Irp;
  1694. entry = entry->Flink;
  1695. //
  1696. // Free the PENDING_IRP structure
  1697. // control block will be freed
  1698. // when addaddrcomplete is called
  1699. CTEFreeMem(pendingIrp);
  1700. //
  1701. // Complete the IRP.
  1702. //
  1703. irp->IoStatus.Information = 0;
  1704. irp->IoStatus.Status = STATUS_CANCELLED;
  1705. IoCompleteRequest(irp, IO_NETWORK_INCREMENT);
  1706. }
  1707. return;
  1708. }
  1709. BOOLEAN
  1710. PrepareArpSendIrpForCancel(
  1711. PIRP Irp,
  1712. PPENDING_IRP PendingIrp
  1713. )
  1714. /*++
  1715. Routine Description:
  1716. Prepares an Arp Send IRP for cancellation.
  1717. Arguments:
  1718. Irp - Pointer to I/O request packet to initialize for cancellation.
  1719. PendingIrp - Pointer to the PENDING_IRP structure for this IRP.
  1720. Return Value:
  1721. TRUE if the IRP was cancelled before this routine was called.
  1722. FALSE otherwise.
  1723. --*/
  1724. {
  1725. BOOLEAN cancelled = TRUE;
  1726. KIRQL oldIrql;
  1727. IoAcquireCancelSpinLock(&oldIrql);
  1728. ASSERT(Irp->CancelRoutine == NULL);
  1729. if (!Irp->Cancel) {
  1730. IoSetCancelRoutine(Irp, CancelArpSendRequest);
  1731. InsertTailList(&PendingArpSendList, &(PendingIrp->Linkage));
  1732. cancelled = FALSE;
  1733. }
  1734. IoReleaseCancelSpinLock(oldIrql);
  1735. return (cancelled);
  1736. }
  1737. void
  1738. CompleteArpResolveRequest(
  1739. void *Context,
  1740. IP_STATUS Status
  1741. )
  1742. /*++
  1743. Routine Description:
  1744. Handles the completion of an ICMP Echo request
  1745. Arguments:
  1746. Context - Pointer to the EchoControl structure for this request.
  1747. Status - The IP status of the transmission.
  1748. Return Value:
  1749. None.
  1750. --*/
  1751. {
  1752. KIRQL oldIrql;
  1753. PIRP irp = NULL;
  1754. PIO_STACK_LOCATION irpSp;
  1755. ARPControlBlock *controlBlock;
  1756. PPENDING_IRP pendingIrp = NULL;
  1757. PPENDING_IRP item;
  1758. PLIST_ENTRY entry;
  1759. controlBlock = (ARPControlBlock *) Context;
  1760. //
  1761. // Find the echo request IRP on the pending list.
  1762. //
  1763. IoAcquireCancelSpinLock(&oldIrql);
  1764. for (entry = PendingArpSendList.Flink;
  1765. entry != &PendingArpSendList;
  1766. entry = entry->Flink
  1767. ) {
  1768. item = CONTAINING_RECORD(entry, PENDING_IRP, Linkage);
  1769. if (item->Context == controlBlock) {
  1770. pendingIrp = item;
  1771. irp = pendingIrp->Irp;
  1772. IoSetCancelRoutine(irp, NULL);
  1773. RemoveEntryList(entry);
  1774. break;
  1775. }
  1776. }
  1777. IoReleaseCancelSpinLock(oldIrql);
  1778. if (pendingIrp == NULL) {
  1779. //
  1780. // IRP must have been cancelled. PENDING_IRP struct
  1781. // was freed by cancel routine. Free control block.
  1782. //
  1783. CTEFreeMem(controlBlock->PhyAddr);
  1784. CTEFreeMem(controlBlock);
  1785. return;
  1786. }
  1787. irpSp = IoGetCurrentIrpStackLocation(irp);
  1788. //set the right length
  1789. //
  1790. // Complete the IRP.
  1791. //
  1792. irp->IoStatus.Status = IPStatusToNTStatus(Status);
  1793. irp->IoStatus.Information = controlBlock->PhyAddrLen;
  1794. RtlCopyMemory(irp->AssociatedIrp.SystemBuffer, controlBlock->PhyAddr,
  1795. controlBlock->PhyAddrLen);
  1796. CTEFreeMem(controlBlock->PhyAddr);
  1797. CTEFreeMem(pendingIrp);
  1798. CTEFreeMem(controlBlock);
  1799. if (Status != IP_SUCCESS) {
  1800. irp->IoStatus.Information = 0;
  1801. }
  1802. IoCompleteRequest(irp, IO_NETWORK_INCREMENT);
  1803. return;
  1804. }
  1805. BOOLEAN
  1806. PrepareEchoIrpForCancel(
  1807. PIRP Irp,
  1808. PPENDING_IRP PendingIrp
  1809. )
  1810. /*++
  1811. Routine Description:
  1812. Prepares an Echo IRP for cancellation.
  1813. Arguments:
  1814. Irp - Pointer to I/O request packet to initialize for cancellation.
  1815. PendingIrp - Pointer to the PENDING_IRP structure for this IRP.
  1816. Return Value:
  1817. TRUE if the IRP was cancelled before this routine was called.
  1818. FALSE otherwise.
  1819. --*/
  1820. {
  1821. BOOLEAN cancelled = TRUE;
  1822. KIRQL oldIrql;
  1823. IoAcquireCancelSpinLock(&oldIrql);
  1824. ASSERT(Irp->CancelRoutine == NULL);
  1825. if (!Irp->Cancel) {
  1826. IoSetCancelRoutine(Irp, CancelEchoRequest);
  1827. InsertTailList(&PendingEchoList, &(PendingIrp->Linkage));
  1828. cancelled = FALSE;
  1829. }
  1830. IoReleaseCancelSpinLock(oldIrql);
  1831. return (cancelled);
  1832. }
  1833. BOOLEAN
  1834. PrepareIPSetNTEAddrIrpForCancel(
  1835. PIRP Irp,
  1836. PPENDING_IRP PendingIrp
  1837. )
  1838. /*++
  1839. Routine Description:
  1840. Prepares an IPSetNTEAddr IRP for cancellation.
  1841. Arguments:
  1842. Irp - Pointer to I/O request packet to initialize for cancellation.
  1843. PendingIrp - Pointer to the PENDING_IRP structure for this IRP.
  1844. Return Value:
  1845. TRUE if the IRP was cancelled before this routine was called.
  1846. FALSE otherwise.
  1847. --*/
  1848. {
  1849. BOOLEAN cancelled = TRUE;
  1850. KIRQL oldIrql;
  1851. IoAcquireCancelSpinLock(&oldIrql);
  1852. ASSERT(Irp->CancelRoutine == NULL);
  1853. if (!Irp->Cancel) {
  1854. IoSetCancelRoutine(Irp, CancelIPSetNTEAddrRequest);
  1855. InsertTailList(&PendingIPSetNTEAddrList, &(PendingIrp->Linkage));
  1856. cancelled = FALSE;
  1857. }
  1858. IoReleaseCancelSpinLock(oldIrql);
  1859. return (cancelled);
  1860. }
  1861. NTSTATUS
  1862. DispatchARPRequest(
  1863. IN PIRP Irp,
  1864. IN PIO_STACK_LOCATION IrpSp
  1865. )
  1866. {
  1867. NTSTATUS ntStatus = STATUS_SUCCESS;
  1868. IP_STATUS ipStatus;
  1869. PPENDING_IRP pendingIrp;
  1870. ARPControlBlock *controlBlock;
  1871. IPAddr DestAddress, SourceAddress;
  1872. BOOLEAN cancelled;
  1873. PARP_SEND_REPLY RequestBuffer;
  1874. PAGED_CODE();
  1875. IoMarkIrpPending(Irp);
  1876. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength !=
  1877. sizeof(ARP_SEND_REPLY) ||
  1878. IrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0) {
  1879. ntStatus = STATUS_INVALID_BUFFER_SIZE;
  1880. goto arp_error;
  1881. }
  1882. pendingIrp = CTEAllocMemN(sizeof(PENDING_IRP), 'gICT');
  1883. if (pendingIrp == NULL) {
  1884. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1885. goto arp_error;
  1886. }
  1887. controlBlock = CTEAllocMemN(sizeof(ARPControlBlock), 'hICT');
  1888. if (controlBlock == NULL) {
  1889. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1890. CTEFreeMem(pendingIrp);
  1891. goto arp_error;
  1892. }
  1893. pendingIrp->Irp = Irp;
  1894. pendingIrp->FileObject = IrpSp->FileObject;
  1895. pendingIrp->Context = controlBlock;
  1896. controlBlock->PhyAddrLen =
  1897. MIN(IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  1898. ARP_802_ADDR_LENGTH);
  1899. controlBlock->PhyAddr = CTEAllocMemN(controlBlock->PhyAddrLen, 'gICT');
  1900. if (controlBlock->PhyAddr == NULL) {
  1901. CTEFreeMem(controlBlock);
  1902. CTEFreeMem(pendingIrp);
  1903. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1904. goto arp_error;
  1905. }
  1906. RequestBuffer = Irp->AssociatedIrp.SystemBuffer;
  1907. controlBlock->next = 0;
  1908. DestAddress = RequestBuffer->DestAddress;
  1909. SourceAddress = RequestBuffer->SrcAddress;
  1910. cancelled = PrepareArpSendIrpForCancel(Irp, pendingIrp);
  1911. if (!cancelled) {
  1912. ipStatus = ARPResolve(
  1913. DestAddress,
  1914. SourceAddress,
  1915. controlBlock,
  1916. CompleteArpResolveRequest
  1917. );
  1918. if (ipStatus != IP_PENDING) {
  1919. //
  1920. // An internal error of some kind occurred. Complete the
  1921. // request.
  1922. //
  1923. CompleteArpResolveRequest(controlBlock, ipStatus);
  1924. }
  1925. return STATUS_PENDING;
  1926. }
  1927. //
  1928. // Irp has already been cancelled.
  1929. //
  1930. ntStatus = STATUS_CANCELLED;
  1931. CTEFreeMem(pendingIrp);
  1932. CTEFreeMem(controlBlock->PhyAddr);
  1933. CTEFreeMem(controlBlock);
  1934. arp_error:
  1935. Irp->IoStatus.Information = 0;
  1936. Irp->IoStatus.Status = ntStatus;
  1937. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  1938. //
  1939. // Irp is marked as pending.
  1940. //
  1941. return STATUS_PENDING;
  1942. }
  1943. NTSTATUS
  1944. DispatchEchoRequest(
  1945. IN PIRP Irp,
  1946. IN PIO_STACK_LOCATION IrpSp
  1947. )
  1948. /*++
  1949. Routine Description:
  1950. Processes an ICMP request.
  1951. Arguments:
  1952. Irp - Pointer to I/O request packet
  1953. IrpSp - Pointer to the current stack location in the Irp.
  1954. Return Value:
  1955. NTSTATUS -- Indicates whether NT-specific processing of the request was
  1956. successful. The status of the actual request is returned in
  1957. the request buffers.
  1958. --*/
  1959. {
  1960. NTSTATUS ntStatus = STATUS_SUCCESS;
  1961. IP_STATUS ipStatus;
  1962. PPENDING_IRP pendingIrp;
  1963. EchoControl *controlBlock;
  1964. BOOLEAN cancelled;
  1965. PAGED_CODE();
  1966. IoMarkIrpPending(Irp);
  1967. pendingIrp = CTEAllocMemN(sizeof(PENDING_IRP), 'iICT');
  1968. if (pendingIrp == NULL) {
  1969. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1970. goto echo_error;
  1971. }
  1972. controlBlock = CTEAllocMemN(sizeof(EchoControl), 'jICT');
  1973. if (controlBlock == NULL) {
  1974. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1975. CTEFreeMem(pendingIrp);
  1976. goto echo_error;
  1977. }
  1978. #if defined(_WIN64)
  1979. if (IoIs32bitProcess(Irp)) {
  1980. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1981. sizeof(ICMP_ECHO_REPLY32)) {
  1982. ntStatus = STATUS_INVALID_PARAMETER;
  1983. CTEFreeMem(controlBlock);
  1984. CTEFreeMem(pendingIrp);
  1985. goto echo_error;
  1986. }
  1987. } else {
  1988. #endif // _WIN64
  1989. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  1990. sizeof(ICMP_ECHO_REPLY)) {
  1991. ntStatus = STATUS_INVALID_PARAMETER;
  1992. CTEFreeMem(controlBlock);
  1993. CTEFreeMem(pendingIrp);
  1994. goto echo_error;
  1995. }
  1996. #if defined(_WIN64)
  1997. }
  1998. #endif // _WIN64
  1999. pendingIrp->Irp = Irp;
  2000. pendingIrp->FileObject = IrpSp->FileObject;
  2001. pendingIrp->Context = controlBlock;
  2002. controlBlock->ec_starttime = KeQueryPerformanceCounter(NULL);
  2003. controlBlock->ec_replybuf = Irp->AssociatedIrp.SystemBuffer;
  2004. controlBlock->ec_replybuflen =
  2005. IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  2006. controlBlock->ec_src = 0;
  2007. cancelled = PrepareEchoIrpForCancel(Irp, pendingIrp);
  2008. if (!cancelled) {
  2009. ipStatus =
  2010. ICMPEchoRequest(Irp->AssociatedIrp.SystemBuffer,
  2011. IrpSp->Parameters.DeviceIoControl.InputBufferLength,
  2012. controlBlock, CompleteEchoRequest);
  2013. if (ipStatus != IP_PENDING) {
  2014. //
  2015. // An internal error of some kind occurred. Complete the
  2016. // request.
  2017. //
  2018. CompleteEchoRequest(controlBlock, ipStatus, NULL, 0, NULL);
  2019. }
  2020. return STATUS_PENDING;
  2021. }
  2022. //
  2023. // Irp has already been cancelled.
  2024. //
  2025. ntStatus = STATUS_CANCELLED;
  2026. CTEFreeMem(pendingIrp);
  2027. CTEFreeMem(controlBlock);
  2028. echo_error:
  2029. Irp->IoStatus.Information = 0;
  2030. Irp->IoStatus.Status = ntStatus;
  2031. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  2032. //
  2033. // Irp is marked as pending.
  2034. //
  2035. return STATUS_PENDING;
  2036. }
  2037. NTSTATUS
  2038. DispatchIPSetNTEAddrRequest(
  2039. IN PIRP Irp,
  2040. IN PIO_STACK_LOCATION IrpSp
  2041. )
  2042. /*++
  2043. Routine Description:
  2044. Processes an IP Set Addr request.
  2045. Arguments:
  2046. Irp - Pointer to I/O request packet
  2047. IrpSp - Pointer to the current stack location in the Irp.
  2048. Return Value:
  2049. NTSTATUS -- Indicates whether NT-specific processing of the request was
  2050. successful. The status of the actual request is returned in
  2051. the request buffers.
  2052. --*/
  2053. {
  2054. NTSTATUS ntStatus = STATUS_SUCCESS;
  2055. IP_STATUS ipStatus;
  2056. PPENDING_IRP pendingIrp;
  2057. SetAddrControl *controlBlock;
  2058. BOOLEAN cancelled;
  2059. PAGED_CODE();
  2060. pendingIrp = CTEAllocMemN(sizeof(PENDING_IRP), 'kICT');
  2061. if (pendingIrp == NULL) {
  2062. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  2063. goto setnteaddr_error;
  2064. }
  2065. controlBlock = CTEAllocMemN(sizeof(SetAddrControl), 'lICT');
  2066. if (controlBlock == NULL) {
  2067. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  2068. CTEFreeMem(pendingIrp);
  2069. goto setnteaddr_error;
  2070. }
  2071. RtlZeroMemory(controlBlock, sizeof(SetAddrControl));
  2072. pendingIrp->Irp = Irp;
  2073. pendingIrp->FileObject = IrpSp->FileObject;
  2074. pendingIrp->Context = controlBlock;
  2075. IoMarkIrpPending(Irp);
  2076. cancelled = PrepareIPSetNTEAddrIrpForCancel(Irp, pendingIrp);
  2077. if (!cancelled) {
  2078. PIP_SET_ADDRESS_REQUEST request;
  2079. USHORT AddrType = 0;
  2080. request = Irp->AssociatedIrp.SystemBuffer;
  2081. if (IrpSp->Parameters.DeviceIoControl.InputBufferLength >=
  2082. sizeof(IP_SET_ADDRESS_REQUEST)) {
  2083. if (IrpSp->Parameters.DeviceIoControl.IoControlCode ==
  2084. IOCTL_IP_SET_ADDRESS_EX) {
  2085. AddrType = ((PIP_SET_ADDRESS_REQUEST_EX)request)->Type;
  2086. }
  2087. ipStatus = IPSetNTEAddrEx(
  2088. request->Context,
  2089. request->Address,
  2090. request->SubnetMask,
  2091. controlBlock,
  2092. CompleteIPSetNTEAddrRequest,
  2093. AddrType
  2094. );
  2095. } else {
  2096. ipStatus = IP_GENERAL_FAILURE;
  2097. }
  2098. if (ipStatus != IP_PENDING) {
  2099. //
  2100. // A request completed which did not pend.
  2101. //
  2102. CompleteIPSetNTEAddrRequest(controlBlock, ipStatus);
  2103. }
  2104. // Since IoMarkIrpPending was called, return pending.
  2105. return STATUS_PENDING;
  2106. }
  2107. //
  2108. // Irp has already been cancelled.
  2109. //
  2110. ntStatus = STATUS_CANCELLED;
  2111. CTEFreeMem(pendingIrp);
  2112. CTEFreeMem(controlBlock);
  2113. setnteaddr_error:
  2114. Irp->IoStatus.Information = 0;
  2115. Irp->IoStatus.Status = ntStatus;
  2116. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  2117. //
  2118. // Irp is marked as pending.
  2119. //
  2120. return STATUS_PENDING;
  2121. }
  2122. NTSTATUS
  2123. DispatchIPGetIPEvent(
  2124. IN PIRP Irp,
  2125. IN PIO_STACK_LOCATION IrpSp
  2126. )
  2127. /*++
  2128. Routine Description:
  2129. Registers the ioctl for the clients to receive the media sense
  2130. events.
  2131. Arguments:
  2132. Irp - Pointer to I/O request packet
  2133. IrpSp - Pointer to the current stack location in the Irp.
  2134. Return Value:
  2135. NTSTATUS -- Indicates whether NT-specific processing of the request was
  2136. successful. The status of the actual request is returned in
  2137. the request buffers.
  2138. --*/
  2139. {
  2140. NTSTATUS ntStatus = STATUS_SUCCESS;
  2141. KIRQL oldIrql;
  2142. //
  2143. // Mark the irp as pending, later when we complete this irp in
  2144. // the same thread, we will unmark it.
  2145. //
  2146. MARK_REQUEST_PENDING(Irp);
  2147. Irp->IoStatus.Information = 0;
  2148. Irp->IoStatus.Status = STATUS_PENDING;
  2149. //
  2150. // Make sure the buffer size is valid.
  2151. //
  2152. #if defined(_WIN64)
  2153. if (IoIs32bitProcess(Irp)) {
  2154. ntStatus = STATUS_NOT_IMPLEMENTED;
  2155. } else {
  2156. #endif // _WIN64
  2157. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
  2158. sizeof(IP_GET_IP_EVENT_RESPONSE)) {
  2159. ntStatus = STATUS_INVALID_PARAMETER;
  2160. } else {
  2161. IoAcquireCancelSpinLock(&oldIrql);
  2162. ASSERT(Irp->CancelRoutine == NULL);
  2163. //
  2164. // Check if the irp is already cancelled or not.
  2165. //
  2166. if (Irp->Cancel) {
  2167. ntStatus = STATUS_CANCELLED;
  2168. //
  2169. // We only allow one irp pending.
  2170. //
  2171. } else if (PendingIPGetIPEventRequest) {
  2172. ntStatus = STATUS_DEVICE_BUSY;
  2173. } else {
  2174. IoSetCancelRoutine(Irp, CancelIPGetIPEventRequest);
  2175. PendingIPGetIPEventRequest = Irp;
  2176. ntStatus = STATUS_SUCCESS;
  2177. }
  2178. IoReleaseCancelSpinLock(oldIrql);
  2179. if (STATUS_SUCCESS == ntStatus) {
  2180. //
  2181. // IPGetIPEventEx will either complete the request
  2182. // or return pending.
  2183. //
  2184. ntStatus = IPGetIPEventEx(Irp, IrpSp);
  2185. if (ntStatus == STATUS_CANCELLED) {
  2186. //
  2187. // Since the cancel routine has been installed at this point,
  2188. // the IRP will have already been completed, and can no longer
  2189. // be referenced.
  2190. //
  2191. ntStatus = STATUS_PENDING;
  2192. }
  2193. }
  2194. }
  2195. #if defined(_WIN64)
  2196. }
  2197. #endif // _WIN64
  2198. if (ntStatus != STATUS_PENDING) {
  2199. Irp->IoStatus.Status = ntStatus;
  2200. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  2201. }
  2202. //
  2203. // Irp is marked as pending.
  2204. //
  2205. return STATUS_PENDING;
  2206. }
  2207. VOID
  2208. CancelIPEnableMediaSenseRequest(
  2209. IN PDEVICE_OBJECT Device,
  2210. IN PIRP Irp
  2211. )
  2212. {
  2213. CTELockHandle TableHandle;
  2214. UNREFERENCED_PARAMETER(Device);
  2215. IoSetCancelRoutine(Irp, NULL);
  2216. IoReleaseCancelSpinLock(Irp->CancelIrql);
  2217. // Decrement the mediasense-enabled reference count.
  2218. // If the count drops to zero media-sense is disabled.
  2219. CTEGetLock(&RouteTableLock.Lock, &TableHandle);
  2220. RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
  2221. IPEnableMediaSense(TRUE, &TableHandle);
  2222. CTEFreeLock(&RouteTableLock.Lock, TableHandle);
  2223. Irp->IoStatus.Information = 0;
  2224. Irp->IoStatus.Status = STATUS_CANCELLED;
  2225. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  2226. }
  2227. NTSTATUS
  2228. IPDisableMediaSenseRequest(
  2229. PIRP Irp,
  2230. PIO_STACK_LOCATION IrpSp
  2231. )
  2232. {
  2233. KIRQL OldIrql;
  2234. NTSTATUS status;
  2235. IoAcquireCancelSpinLock(&OldIrql);
  2236. IoMarkIrpPending(Irp);
  2237. IoSetCancelRoutine(Irp, CancelIPEnableMediaSenseRequest);
  2238. if (Irp->Cancel) {
  2239. IoSetCancelRoutine(Irp, NULL);
  2240. status = STATUS_CANCELLED;
  2241. Irp->IoStatus.Information = 0;
  2242. IoReleaseCancelSpinLock(OldIrql);
  2243. } else {
  2244. // Increment the mediasense-enabled reference count.
  2245. // When the count rises above zero media-sense is enabled.
  2246. // This reference will be dropped when the IRP is cancelled.
  2247. CTEGetLockAtDPC(&RouteTableLock.Lock);
  2248. Irp->Tail.Overlay.DriverContext[0] = IrpSp->FileObject;
  2249. InsertTailList(&PendingMediaSenseRequestList, &Irp->Tail.Overlay.ListEntry);
  2250. Irp->IoStatus.Information = 0;
  2251. IoReleaseCancelSpinLock(DISPATCH_LEVEL);
  2252. IPEnableMediaSense(FALSE, &OldIrql);
  2253. CTEFreeLock(&RouteTableLock.Lock, OldIrql);
  2254. status = STATUS_PENDING;
  2255. }
  2256. return status;
  2257. }
  2258. NTSTATUS
  2259. IPEnableMediaSenseRequest(
  2260. PIRP Irp,
  2261. PIO_STACK_LOCATION IrpSp,
  2262. PVOID ApcContext
  2263. )
  2264. {
  2265. PLIST_ENTRY entry;
  2266. KIRQL CancelIrql;
  2267. int RefCount;
  2268. // Locate the pending IRP for the request corresponding to the caller's
  2269. // disable-request. Drop the mediasense-enabled reference-count, complete
  2270. // the corresponding IRP, and tell the caller what the reference-count's
  2271. // current value is.
  2272. IoAcquireCancelSpinLock(&CancelIrql);
  2273. CTEGetLockAtDPC(&RouteTableLock.Lock);
  2274. for (entry = PendingMediaSenseRequestList.Flink;
  2275. entry != &PendingMediaSenseRequestList;
  2276. entry = entry->Flink
  2277. ) {
  2278. PIRP EnableIrp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
  2279. if (EnableIrp->Tail.Overlay.DriverContext[0] == IrpSp->FileObject &&
  2280. EnableIrp->Overlay.AsynchronousParameters.UserApcContext == ApcContext) {
  2281. RemoveEntryList(&EnableIrp->Tail.Overlay.ListEntry);
  2282. IoSetCancelRoutine(EnableIrp, NULL);
  2283. EnableIrp->IoStatus.Status = STATUS_SUCCESS;
  2284. EnableIrp->IoStatus.Information = 0;
  2285. *(PULONG) Irp->AssociatedIrp.SystemBuffer = (ULONG) DisableMediaSense+1;
  2286. Irp->IoStatus.Information = sizeof(ULONG);
  2287. IoReleaseCancelSpinLock(DISPATCH_LEVEL);
  2288. IoCompleteRequest(EnableIrp, IO_NETWORK_INCREMENT);
  2289. RefCount = IPEnableMediaSense(TRUE, &CancelIrql);
  2290. CTEFreeLock(&RouteTableLock.Lock, CancelIrql);
  2291. return STATUS_SUCCESS;
  2292. }
  2293. }
  2294. CTEFreeLockFromDPC(&RouteTableLock.Lock);
  2295. IoReleaseCancelSpinLock(CancelIrql);
  2296. return STATUS_INVALID_PARAMETER;
  2297. }