Added networking code from Casper Hornstrup
[reactos.git] / reactos / drivers / net / tcpip / tcpip / dispatch.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: tcpip/dispatch.h
5 * PURPOSE: TDI dispatch routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/08-2000 Created
9 */
10 #include <tcpip.h>
11 #include <dispatch.h>
12 #include <routines.h>
13 #include <datagram.h>
14 #include <info.h>
15
16
17 NTSTATUS DispPrepareIrpForCancel(
18 PTRANSPORT_CONTEXT Context,
19 PIRP Irp,
20 PDRIVER_CANCEL CancelRoutine)
21 /*
22 * FUNCTION: Prepare an IRP for cancellation
23 * ARGUMENTS:
24 * Context = Pointer to context information
25 * Irp = Pointer to an I/O request packet
26 * CancelRoutine = Routine to be called when I/O request is cancelled
27 * RETURNS:
28 * Status of operation
29 */
30 {
31 KIRQL OldIrql;
32
33 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
34
35 IoAcquireCancelSpinLock(&OldIrql);
36
37 if (!Irp->Cancel) {
38 IoMarkIrpPending(Irp);
39 IoSetCancelRoutine(Irp, CancelRoutine);
40 Context->RefCount++;
41 IoReleaseCancelSpinLock(OldIrql);
42
43 TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP at 0x%X can now be cancelled).\n", Irp));
44
45 return STATUS_SUCCESS;
46 }
47
48 /* IRP has already been cancelled */
49
50 IoReleaseCancelSpinLock(OldIrql);
51
52 Irp->IoStatus.Status = STATUS_CANCELLED;
53 Irp->IoStatus.Information = 0;
54
55 TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
56
57 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
58
59 TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP was already cancelled).\n"));
60
61 return STATUS_CANCELLED;
62 }
63
64
65 VOID DispCancelComplete(
66 PVOID Context)
67 /*
68 * FUNCTION: Completes a cancel request
69 * ARGUMENTS:
70 * Context = Pointer to context information (FILE_OBJECT)
71 */
72 {
73 KIRQL OldIrql;
74 PFILE_OBJECT FileObject;
75 PTRANSPORT_CONTEXT TranContext;
76
77 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
78
79 FileObject = (PFILE_OBJECT)Context;
80 TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext;
81
82 IoAcquireCancelSpinLock(&OldIrql);
83
84 /* Remove the reference placed on the endpoint by the cancel routine.
85 The cancelled IRP will be completed by the completion routine for
86 the request */
87 TranContext->RefCount--;
88
89 if (TranContext->RefCount == 0) {
90 TI_DbgPrint(DEBUG_IRP, ("Setting TranContext->CleanupEvent to signaled.\n"));
91 /* Set the cleanup event */
92 KeSetEvent(&TranContext->CleanupEvent, 0, FALSE);
93 }
94
95 TI_DbgPrint(DEBUG_REFCOUNT, ("TranContext->RefCount (%d).\n", TranContext->RefCount));
96
97 IoReleaseCancelSpinLock(OldIrql);
98
99 TI_DbgPrint(DEBUG_IRP, ("Leaving.\n"));
100 }
101
102
103 VOID DispCancelRequest(
104 PDEVICE_OBJECT Device,
105 PIRP Irp)
106 /*
107 * FUNCTION: Cancels an IRP
108 * ARGUMENTS:
109 * Device = Pointer to device object
110 * Irp = Pointer to an I/O request packet
111 */
112 {
113 PIO_STACK_LOCATION IrpSp;
114 PTRANSPORT_CONTEXT TranContext;
115 PFILE_OBJECT FileObject;
116 UCHAR MinorFunction;
117 NTSTATUS Status = STATUS_SUCCESS;
118
119 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
120
121 IrpSp = IoGetCurrentIrpStackLocation(Irp);
122 FileObject = IrpSp->FileObject;
123 TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext;
124 MinorFunction = IrpSp->MinorFunction;
125
126 TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X) MinorFunction (0x%X) IrpSp (0x%X).\n", Irp, MinorFunction, IrpSp));
127
128 #ifdef DBG
129 if (!Irp->Cancel)
130 TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n"));
131 #endif
132
133 /* Increase reference count to prevent accidential closure
134 of the object while inside the cancel routine */
135 TranContext->RefCount++;
136
137 IoReleaseCancelSpinLock(Irp->CancelIrql);
138
139 /* Try canceling the request */
140 switch(MinorFunction) {
141 case TDI_SEND:
142
143 case TDI_RECEIVE:
144 /* FIXME: Close connection */
145 break;
146
147 case TDI_SEND_DATAGRAM:
148 if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
149 TI_DbgPrint(MIN_TRACE, ("TDI_SEND_DATAGRAM, but no address file.\n"));
150 break;
151 }
152
153 DGCancelSendRequest(TranContext->Handle.AddressHandle, Irp);
154 break;
155
156 case TDI_RECEIVE_DATAGRAM:
157 if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
158 TI_DbgPrint(MIN_TRACE, ("TDI_RECEIVE_DATAGRAM, but no address file.\n"));
159 break;
160 }
161
162 DGCancelReceiveRequest(TranContext->Handle.AddressHandle, Irp);
163 break;
164
165 default:
166 TI_DbgPrint(MIN_TRACE, ("Unknown IRP. MinorFunction (0x%X).\n", MinorFunction));
167 break;
168 }
169
170 if (Status != STATUS_PENDING)
171 DispCancelComplete(FileObject);
172
173 TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
174 }
175
176
177 VOID DispDataRequestComplete(
178 PVOID Context,
179 NTSTATUS Status,
180 ULONG Count)
181 /*
182 * FUNCTION: Completes a send/receive IRP
183 * ARGUMENTS:
184 * Context = Pointer to context information (IRP)
185 * Status = Status of the request
186 * Count = Number of bytes sent or received
187 */
188 {
189 PIRP Irp;
190 PIO_STACK_LOCATION IrpSp;
191 PTRANSPORT_CONTEXT TranContext;
192 KIRQL OldIrql;
193
194 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
195
196 Irp = (PIRP)Context;
197 IrpSp = IoGetCurrentIrpStackLocation(Irp);
198 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
199
200 IoAcquireCancelSpinLock(&OldIrql);
201
202 IoSetCancelRoutine(Irp, NULL);
203 TranContext->RefCount--;
204 TI_DbgPrint(DEBUG_REFCOUNT, ("TranContext->RefCount (%d).\n", TranContext->RefCount));
205 if (TranContext->RefCount == 0) {
206 TI_DbgPrint(DEBUG_IRP, ("Setting TranContext->CleanupEvent to signaled.\n"));
207
208 KeSetEvent(&TranContext->CleanupEvent, 0, FALSE);
209 }
210
211 if (Irp->Cancel || TranContext->CancelIrps) {
212 /* The IRP has been cancelled */
213
214 TI_DbgPrint(DEBUG_IRP, ("IRP is cancelled.\n"));
215
216 Status = STATUS_CANCELLED;
217 Count = 0;
218 }
219
220 IoReleaseCancelSpinLock(OldIrql);
221
222 Irp->IoStatus.Status = Status;
223 Irp->IoStatus.Information = Count;
224
225 TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
226
227 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
228 }
229
230
231 NTSTATUS DispTdiAccept(
232 PIRP Irp)
233 /*
234 * FUNCTION: TDI_ACCEPT handler
235 * ARGUMENTS:
236 * Irp = Pointer to an I/O request packet
237 * RETURNS:
238 * Status of operation
239 */
240 {
241 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
242
243 return STATUS_NOT_IMPLEMENTED;
244 }
245
246
247 NTSTATUS DispTdiAssociateAddress(
248 PIRP Irp)
249 /*
250 * FUNCTION: TDI_ASSOCIATE_ADDRESS handler
251 * ARGUMENTS:
252 * Irp = Pointer to an I/O request packet
253 * RETURNS:
254 * Status of operation
255 */
256 {
257 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
258
259 return STATUS_NOT_IMPLEMENTED;
260 }
261
262
263 NTSTATUS DispTdiConnect(
264 PIRP Irp)
265 /*
266 * FUNCTION: TDI_CONNECT handler
267 * ARGUMENTS:
268 * Irp = Pointer to an I/O request packet
269 * RETURNS:
270 * Status of operation
271 */
272 {
273 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
274
275 return STATUS_NOT_IMPLEMENTED;
276 }
277
278
279 NTSTATUS DispTdiDisassociateAddress(
280 PIRP Irp)
281 /*
282 * FUNCTION: TDI_DISASSOCIATE_ADDRESS handler
283 * ARGUMENTS:
284 * Irp = Pointer to an I/O request packet
285 * RETURNS:
286 * Status of operation
287 */
288 {
289 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
290
291 return STATUS_NOT_IMPLEMENTED;
292 }
293
294
295 NTSTATUS DispTdiDisconnect(
296 PIRP Irp)
297 /*
298 * FUNCTION: TDI_DISCONNECT handler
299 * ARGUMENTS:
300 * Irp = Pointer to an I/O request packet
301 * RETURNS:
302 * Status of operation
303 */
304 {
305 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
306
307 return STATUS_NOT_IMPLEMENTED;
308 }
309
310
311 NTSTATUS DispTdiListen(
312 PIRP Irp)
313 /*
314 * FUNCTION: TDI_LISTEN handler
315 * ARGUMENTS:
316 * Irp = Pointer to an I/O request packet
317 * RETURNS:
318 * Status of operation
319 */
320 {
321 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
322
323 return STATUS_NOT_IMPLEMENTED;
324 }
325
326
327 NTSTATUS DispTdiQueryInformation(
328 PDEVICE_OBJECT DeviceObject,
329 PIRP Irp)
330 /*
331 * FUNCTION: TDI_QUERY_INFORMATION handler
332 * ARGUMENTS:
333 * DeviceObject = Pointer to device object structure
334 * Irp = Pointer to an I/O request packet
335 * RETURNS:
336 * Status of operation
337 */
338 {
339 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
340
341 return STATUS_NOT_IMPLEMENTED;
342 }
343
344
345 NTSTATUS DispTdiReceive(
346 PIRP Irp)
347 /*
348 * FUNCTION: TDI_RECEIVE handler
349 * ARGUMENTS:
350 * Irp = Pointer to an I/O request packet
351 * RETURNS:
352 * Status of operation
353 */
354 {
355 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
356
357 return STATUS_NOT_IMPLEMENTED;
358 }
359
360
361 NTSTATUS DispTdiReceiveDatagram(
362 PIRP Irp)
363 /*
364 * FUNCTION: TDI_RECEIVE_DATAGRAM handler
365 * ARGUMENTS:
366 * Irp = Pointer to an I/O request packet
367 * RETURNS:
368 * Status of operation
369 */
370 {
371 PIO_STACK_LOCATION IrpSp;
372 PTDI_REQUEST_KERNEL_RECEIVEDG DgramInfo;
373 PTRANSPORT_CONTEXT TranContext;
374 TDI_REQUEST Request;
375 NTSTATUS Status;
376 ULONG BytesReceived;
377
378 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
379
380 IrpSp = IoGetCurrentIrpStackLocation(Irp);
381 DgramInfo = (PTDI_REQUEST_KERNEL_RECEIVEDG)&(IrpSp->Parameters);
382
383 TranContext = IrpSp->FileObject->FsContext;
384 /* Initialize a receive request */
385 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
386 Request.RequestNotifyObject = DispDataRequestComplete;
387 Request.RequestContext = Irp;
388 Status = DispPrepareIrpForCancel(IrpSp->FileObject->FsContext, Irp, (PDRIVER_CANCEL)DispCancelRequest);
389 if (NT_SUCCESS(Status)) {
390 Status = UDPReceiveDatagram(&Request,
391 DgramInfo->ReceiveDatagramInformation,
392 (PNDIS_BUFFER)Irp->MdlAddress,
393 DgramInfo->ReceiveLength,
394 DgramInfo->ReceiveFlags,
395 DgramInfo->ReturnDatagramInformation,
396 &BytesReceived);
397 if (Status != STATUS_PENDING) {
398 DispDataRequestComplete(Irp, Status, BytesReceived);
399 /* Return STATUS_PENDING because DispPrepareIrpForCancel marks Irp as pending */
400 Status = STATUS_PENDING;
401 }
402 }
403
404 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
405
406 return Status;
407 }
408
409
410 NTSTATUS DispTdiSend(
411 PIRP Irp)
412 /*
413 * FUNCTION: TDI_SEND handler
414 * ARGUMENTS:
415 * Irp = Pointer to an I/O request packet
416 * RETURNS:
417 * Status of operation
418 */
419 {
420 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
421
422 return STATUS_NOT_IMPLEMENTED;
423 }
424
425
426 NTSTATUS DispTdiSendDatagram(
427 PIRP Irp)
428 /*
429 * FUNCTION: TDI_SEND_DATAGRAM handler
430 * ARGUMENTS:
431 * Irp = Pointer to an I/O request packet
432 * RETURNS:
433 * Status of operation
434 */
435 {
436 PIO_STACK_LOCATION IrpSp;
437 TDI_REQUEST Request;
438 PTDI_REQUEST_KERNEL_SENDDG DgramInfo;
439 PTRANSPORT_CONTEXT TranContext;
440 NTSTATUS Status;
441
442 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
443
444 IrpSp = IoGetCurrentIrpStackLocation(Irp);
445 DgramInfo = (PTDI_REQUEST_KERNEL_SENDDG)&(IrpSp->Parameters);
446
447 TranContext = IrpSp->FileObject->FsContext;
448 /* Initialize a send request */
449 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
450 Request.RequestNotifyObject = DispDataRequestComplete;
451 Request.RequestContext = Irp;
452
453 Status = DispPrepareIrpForCancel(IrpSp->FileObject->FsContext, Irp, (PDRIVER_CANCEL)DispCancelRequest);
454 if (NT_SUCCESS(Status)) {
455
456 /* FIXME: DgramInfo->SendDatagramInformation->RemoteAddress
457 must be of type PTDI_ADDRESS_IP */
458
459 Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)(
460 &Request, DgramInfo->SendDatagramInformation,
461 (PNDIS_BUFFER)Irp->MdlAddress, DgramInfo->SendLength);
462 if (Status != STATUS_PENDING) {
463 DispDataRequestComplete(Irp, Status, 0);
464 /* Return STATUS_PENDING because DispPrepareIrpForCancel marks Irp as pending */
465 Status = STATUS_PENDING;
466 }
467 }
468
469 TI_DbgPrint(DEBUG_IRP, ("Leaving.\n"));
470
471 return Status;
472 }
473
474
475 NTSTATUS DispTdiSetEventHandler(
476 PIRP Irp)
477 /*
478 * FUNCTION: TDI_SET_EVENT_HANDER handler
479 * ARGUMENTS:
480 * Irp = Pointer to a I/O request packet
481 * RETURNS:
482 * Status of operation
483 */
484 {
485 #ifdef _MSC_VER
486 PTDI_REQUEST_KERNEL_SET_EVENT Parameters;
487 PTRANSPORT_CONTEXT TranContext;
488 PIO_STACK_LOCATION IrpSp;
489 PADDRESS_FILE AddrFile;
490 NTSTATUS Status;
491 KIRQL OldIrql;
492
493 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
494
495 IrpSp = IoGetCurrentIrpStackLocation(Irp);
496
497 /* Get associated address file object. Quit if none exists */
498 TranContext = IrpSp->FileObject->FsContext;
499 if (!TranContext) {
500 TI_DbgPrint(MIN_TRACE, ("Bad transport context.\n"));
501 return STATUS_INVALID_PARAMETER;
502 }
503
504 AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
505 if (!AddrFile) {
506 TI_DbgPrint(MIN_TRACE, ("No address file object.\n"));
507 return STATUS_INVALID_PARAMETER;
508 }
509
510 Parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters;
511 Status = STATUS_SUCCESS;
512
513 KeAcquireSpinLock(&AddrFile->Lock, &OldIrql);
514
515 /* Set the event handler. if an event handler is associated with
516 a specific event, it's flag (RegisteredXxxHandler) is TRUE.
517 If an event handler is not used it's flag is FALSE */
518 switch (Parameters->EventType) {
519 case TDI_EVENT_CONNECT:
520 if (!Parameters->EventHandler) {
521 AddrFile->ConnectionHandler =
522 (PTDI_IND_CONNECT)TdiDefaultConnectHandler;
523 AddrFile->ConnectionHandlerContext = NULL;
524 AddrFile->RegisteredConnectionHandler = FALSE;
525 } else {
526 AddrFile->ConnectionHandler =
527 (PTDI_IND_CONNECT)Parameters->EventHandler;
528 AddrFile->ConnectionHandlerContext = Parameters->EventContext;
529 AddrFile->RegisteredConnectionHandler = TRUE;
530 }
531 break;
532
533 case TDI_EVENT_DISCONNECT:
534 if (!Parameters->EventHandler) {
535 AddrFile->DisconnectHandler =
536 (PTDI_IND_DISCONNECT)TdiDefaultDisconnectHandler;
537 AddrFile->DisconnectHandlerContext = NULL;
538 AddrFile->RegisteredDisconnectHandler = FALSE;
539 } else {
540 AddrFile->DisconnectHandler =
541 (PTDI_IND_DISCONNECT)Parameters->EventHandler;
542 AddrFile->DisconnectHandlerContext = Parameters->EventContext;
543 AddrFile->RegisteredDisconnectHandler = TRUE;
544 }
545 break;
546
547 case TDI_EVENT_RECEIVE:
548 if (Parameters->EventHandler == NULL) {
549 AddrFile->ReceiveHandler =
550 (PTDI_IND_RECEIVE)TdiDefaultReceiveHandler;
551 AddrFile->ReceiveHandlerContext = NULL;
552 AddrFile->RegisteredReceiveHandler = FALSE;
553 } else {
554 AddrFile->ReceiveHandler =
555 (PTDI_IND_RECEIVE)Parameters->EventHandler;
556 AddrFile->ReceiveHandlerContext = Parameters->EventContext;
557 AddrFile->RegisteredReceiveHandler = TRUE;
558 }
559 break;
560
561 case TDI_EVENT_RECEIVE_EXPEDITED:
562 if (Parameters->EventHandler == NULL) {
563 AddrFile->ExpeditedReceiveHandler =
564 (PTDI_IND_RECEIVE_EXPEDITED)TdiDefaultRcvExpeditedHandler;
565 AddrFile->ExpeditedReceiveHandlerContext = NULL;
566 AddrFile->RegisteredExpeditedReceiveHandler = FALSE;
567 } else {
568 AddrFile->ExpeditedReceiveHandler =
569 (PTDI_IND_RECEIVE_EXPEDITED)Parameters->EventHandler;
570 AddrFile->ExpeditedReceiveHandlerContext = Parameters->EventContext;
571 AddrFile->RegisteredExpeditedReceiveHandler = TRUE;
572 }
573 break;
574
575 case TDI_EVENT_RECEIVE_DATAGRAM:
576 if (Parameters->EventHandler == NULL) {
577 AddrFile->ReceiveDatagramHandler =
578 (PTDI_IND_RECEIVE_DATAGRAM)TdiDefaultRcvDatagramHandler;
579 AddrFile->ReceiveDatagramHandlerContext = NULL;
580 AddrFile->RegisteredReceiveDatagramHandler = FALSE;
581 } else {
582 AddrFile->ReceiveDatagramHandler =
583 (PTDI_IND_RECEIVE_DATAGRAM)Parameters->EventHandler;
584 AddrFile->ReceiveDatagramHandlerContext = Parameters->EventContext;
585 AddrFile->RegisteredReceiveDatagramHandler = TRUE;
586 }
587 break;
588
589 case TDI_EVENT_ERROR:
590 if (Parameters->EventHandler == NULL) {
591 AddrFile->ErrorHandler =
592 (PTDI_IND_ERROR)TdiDefaultErrorHandler;
593 AddrFile->ErrorHandlerContext = NULL;
594 AddrFile->RegisteredErrorHandler = FALSE;
595 } else {
596 AddrFile->ErrorHandler =
597 (PTDI_IND_ERROR)Parameters->EventHandler;
598 AddrFile->ErrorHandlerContext = Parameters->EventContext;
599 AddrFile->RegisteredErrorHandler = TRUE;
600 }
601 break;
602
603 default:
604 Status = STATUS_INVALID_PARAMETER;
605 }
606
607 KeReleaseSpinLock(&AddrFile->Lock, OldIrql);
608
609 return Status;
610 #else
611 return STATUS_NOT_IMPLEMENTED;
612 #endif
613 }
614
615
616 NTSTATUS DispTdiSetInformation(
617 PIRP Irp)
618 /*
619 * FUNCTION: TDI_SET_INFORMATION handler
620 * ARGUMENTS:
621 * Irp = Pointer to an I/O request packet
622 * RETURNS:
623 * Status of operation
624 */
625 {
626 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
627
628 return STATUS_NOT_IMPLEMENTED;
629 }
630
631
632 VOID DispTdiQueryInformationExComplete(
633 PVOID Context,
634 ULONG Status,
635 UINT ByteCount)
636 /*
637 * FUNCTION: Completes a TDI QueryInformationEx request
638 * ARGUMENTS:
639 * Context = Pointer to the IRP for the request
640 * Status = TDI status of the request
641 * ByteCount = Number of bytes returned in output buffer
642 */
643 {
644 PTI_QUERY_CONTEXT QueryContext;
645 UINT Count = 0;
646
647 QueryContext = (PTI_QUERY_CONTEXT)Context;
648 if (NT_SUCCESS(Status)) {
649 Count = CopyBufferToBufferChain(
650 QueryContext->InputMdl,
651 FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context),
652 (PUCHAR)&QueryContext->QueryInfo.Context,
653 CONTEXT_SIZE);
654 }
655
656 MmUnlockPages(QueryContext->InputMdl);
657 IoFreeMdl(QueryContext->InputMdl);
658 MmUnlockPages(QueryContext->OutputMdl);
659 IoFreeMdl(QueryContext->OutputMdl);
660
661 QueryContext->Irp->IoStatus.Information = Count;
662 QueryContext->Irp->IoStatus.Status = Status;
663
664 ExFreePool(QueryContext);
665 }
666
667
668 NTSTATUS DispTdiQueryInformationEx(
669 PIRP Irp,
670 PIO_STACK_LOCATION IrpSp)
671 /*
672 * FUNCTION: TDI QueryInformationEx handler
673 * ARGUMENTS:
674 * Irp = Pointer to I/O request packet
675 * IrpSp = Pointer to current stack location of Irp
676 * RETURNS:
677 * Status of operation
678 */
679 {
680 PTCP_REQUEST_QUERY_INFORMATION_EX InputBuffer;
681 PTRANSPORT_CONTEXT TranContext;
682 PTI_QUERY_CONTEXT QueryContext;
683 PVOID OutputBuffer;
684 TDI_REQUEST Request;
685 UINT Size;
686 UINT InputBufferLength;
687 UINT OutputBufferLength;
688 BOOLEAN InputMdlLocked = FALSE;
689 BOOLEAN OutputMdlLocked = FALSE;
690 PMDL InputMdl = NULL;
691 PMDL OutputMdl = NULL;
692 NTSTATUS Status = STATUS_SUCCESS;
693
694 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
695
696 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
697
698 switch ((ULONG)IrpSp->FileObject->FsContext2) {
699 case TDI_TRANSPORT_ADDRESS_FILE:
700 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
701 break;
702
703 case TDI_CONNECTION_FILE:
704 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
705 break;
706
707 case TDI_CONTROL_CHANNEL_FILE:
708 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
709 break;
710
711 default:
712 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
713 return STATUS_INVALID_PARAMETER;
714 }
715
716 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
717 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
718
719 /* Validate parameters */
720 if ((InputBufferLength == sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)) &&
721 (OutputBufferLength != 0)) {
722
723 InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
724 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
725 OutputBuffer = Irp->UserBuffer;
726
727 QueryContext = ExAllocatePool(NonPagedPool, sizeof(TI_QUERY_CONTEXT));
728 if (QueryContext) {
729 #ifdef _MSC_VER
730 try {
731 #endif
732 InputMdl = IoAllocateMdl(InputBuffer,
733 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
734 FALSE, TRUE, NULL);
735
736 OutputMdl = IoAllocateMdl(OutputBuffer,
737 OutputBufferLength, FALSE, TRUE, NULL);
738
739 if (InputMdl && OutputMdl) {
740
741 MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
742 IoModifyAccess);
743
744 InputMdlLocked = TRUE;
745
746 MmProbeAndLockPages(OutputMdl, Irp->RequestorMode,
747 IoWriteAccess);
748
749 OutputMdlLocked = TRUE;
750
751 RtlCopyMemory(&QueryContext->QueryInfo,
752 InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
753
754 } else
755 Status = STATUS_INSUFFICIENT_RESOURCES;
756 #ifdef _MSC_VER
757 } except(EXCEPTION_EXECUTE_HANDLER) {
758 Status = GetExceptionCode();
759 }
760 #endif
761 if (NT_SUCCESS(Status)) {
762 Size = MmGetMdlByteCount(OutputMdl);
763
764 QueryContext->Irp = Irp;
765 QueryContext->InputMdl = InputMdl;
766 QueryContext->OutputMdl = OutputMdl;
767
768 Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
769 Request.RequestContext = QueryContext;
770 Status = InfoTdiQueryInformationEx(&Request,
771 &QueryContext->QueryInfo.ID, OutputMdl,
772 &Size, &QueryContext->QueryInfo.Context);
773 DispTdiQueryInformationExComplete(QueryContext, Status, Size);
774
775 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));
776
777 return Status;
778 }
779
780 /* An error occurred if we get here */
781
782 if (InputMdl) {
783 if (InputMdlLocked)
784 MmUnlockPages(InputMdl);
785 IoFreeMdl(InputMdl);
786 }
787
788 if (OutputMdl) {
789 if (OutputMdlLocked)
790 MmUnlockPages(OutputMdl);
791 IoFreeMdl(OutputMdl);
792 }
793
794 ExFreePool(QueryContext);
795 } else
796 Status = STATUS_INSUFFICIENT_RESOURCES;
797 } else
798 Status = STATUS_INVALID_PARAMETER;
799
800 TI_DbgPrint(MIN_TRACE, ("Leaving. Status = (0x%X)\n", Status));
801
802 return Status;
803 }
804
805
806 NTSTATUS DispTdiSetInformationEx(
807 PIRP Irp,
808 PIO_STACK_LOCATION IrpSp)
809 /*
810 * FUNCTION: TDI SetInformationEx handler
811 * ARGUMENTS:
812 * Irp = Pointer to I/O request packet
813 * IrpSp = Pointer to current stack location of Irp
814 * RETURNS:
815 * Status of operation
816 */
817 {
818 PTRANSPORT_CONTEXT TranContext;
819 PTCP_REQUEST_SET_INFORMATION_EX Info;
820 TDI_REQUEST Request;
821 TDI_STATUS Status;
822 KIRQL OldIrql;
823
824 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
825
826 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
827 Info = (PTCP_REQUEST_SET_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer;
828
829 switch ((ULONG)IrpSp->FileObject->FsContext2) {
830 case TDI_TRANSPORT_ADDRESS_FILE:
831 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
832 break;
833
834 case TDI_CONNECTION_FILE:
835 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
836 break;
837
838 case TDI_CONTROL_CHANNEL_FILE:
839 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
840 break;
841
842 default:
843 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
844 Irp->IoStatus.Information = 0;
845
846 TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
847
848 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
849
850 return STATUS_INVALID_PARAMETER;
851 }
852
853 Status = DispPrepareIrpForCancel(TranContext, Irp, NULL);
854 if (NT_SUCCESS(Status)) {
855 Request.RequestNotifyObject = DispDataRequestComplete;
856 Request.RequestContext = Irp;
857
858 Status = InfoTdiSetInformationEx(&Request, &Info->ID,
859 &Info->Buffer, Info->BufferSize);
860
861 if (Status != STATUS_PENDING) {
862 IoAcquireCancelSpinLock(&OldIrql);
863 IoSetCancelRoutine(Irp, NULL);
864 IoReleaseCancelSpinLock(OldIrql);
865 }
866 }
867
868 return Status;
869 }
870
871 /* EOF */