sync trunk head (37032)
[reactos.git] / reactos / drivers / network / 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 * TODO: Validate device object in all dispatch routines
10 */
11
12 #include "precomp.h"
13 #include <pseh/pseh.h>
14
15 NTSTATUS DispPrepareIrpForCancel(
16 PTRANSPORT_CONTEXT Context,
17 PIRP Irp,
18 PDRIVER_CANCEL CancelRoutine)
19 /*
20 * FUNCTION: Prepare an IRP for cancellation
21 * ARGUMENTS:
22 * Context = Pointer to context information
23 * Irp = Pointer to an I/O request packet
24 * CancelRoutine = Routine to be called when I/O request is cancelled
25 * RETURNS:
26 * Status of operation
27 */
28 {
29 KIRQL OldIrql;
30
31 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
32
33 IoAcquireCancelSpinLock(&OldIrql);
34
35 if (!Irp->Cancel) {
36 (void)IoSetCancelRoutine(Irp, CancelRoutine);
37 IoReleaseCancelSpinLock(OldIrql);
38
39 TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP at 0x%X can now be cancelled).\n", Irp));
40
41 return STATUS_SUCCESS;
42 }
43
44 /* IRP has already been cancelled */
45
46 IoReleaseCancelSpinLock(OldIrql);
47
48 Irp->IoStatus.Status = STATUS_CANCELLED;
49 Irp->IoStatus.Information = 0;
50
51 TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP was already cancelled).\n"));
52
53 return Irp->IoStatus.Status;
54 }
55
56 VOID DispDataRequestComplete(
57 PVOID Context,
58 NTSTATUS Status,
59 ULONG Count)
60 /*
61 * FUNCTION: Completes a send/receive IRP
62 * ARGUMENTS:
63 * Context = Pointer to context information (IRP)
64 * Status = Status of the request
65 * Count = Number of bytes sent or received
66 */
67 {
68 PIRP Irp;
69 PIO_STACK_LOCATION IrpSp;
70 PTRANSPORT_CONTEXT TranContext;
71 KIRQL OldIrql;
72
73 TI_DbgPrint(DEBUG_IRP, ("Called for irp %x (%x, %d).\n",
74 Context, Status, Count));
75
76 Irp = Context;
77 IrpSp = IoGetCurrentIrpStackLocation(Irp);
78 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
79
80 IoAcquireCancelSpinLock(&OldIrql);
81
82 (void)IoSetCancelRoutine(Irp, NULL);
83
84 if (Irp->Cancel || TranContext->CancelIrps) {
85 /* The IRP has been cancelled */
86
87 TI_DbgPrint(DEBUG_IRP, ("IRP is cancelled.\n"));
88
89 Status = STATUS_CANCELLED;
90 Count = 0;
91 }
92
93 IoReleaseCancelSpinLock(OldIrql);
94
95 Irp->IoStatus.Status = Status;
96 Irp->IoStatus.Information = Count;
97
98 TI_DbgPrint(MID_TRACE, ("Irp->IoStatus.Status = %x\n",
99 Irp->IoStatus.Status));
100 TI_DbgPrint(MID_TRACE, ("Irp->IoStatus.Information = %d\n",
101 Irp->IoStatus.Information));
102 TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
103
104 IRPFinish(Irp, Irp->IoStatus.Status);
105
106 TI_DbgPrint(DEBUG_IRP, ("Done Completing IRP\n"));
107 }
108
109 typedef struct _DISCONNECT_TYPE {
110 UINT Type;
111 PVOID Context;
112 PIRP Irp;
113 PFILE_OBJECT FileObject;
114 } DISCONNECT_TYPE, *PDISCONNECT_TYPE;
115
116 VOID DispDoDisconnect( PVOID Data ) {
117 PDISCONNECT_TYPE DisType = (PDISCONNECT_TYPE)Data;
118
119 TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect\n"));
120 TCPDisconnect
121 ( DisType->Context,
122 DisType->Type,
123 NULL,
124 NULL,
125 DispDataRequestComplete,
126 DisType->Irp );
127 TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect done\n"));
128
129 DispDataRequestComplete(DisType->Irp, STATUS_CANCELLED, 0);
130 }
131
132 VOID NTAPI DispCancelRequest(
133 PDEVICE_OBJECT Device,
134 PIRP Irp)
135 /*
136 * FUNCTION: Cancels an IRP
137 * ARGUMENTS:
138 * Device = Pointer to device object
139 * Irp = Pointer to an I/O request packet
140 */
141 {
142 PIO_STACK_LOCATION IrpSp;
143 PTRANSPORT_CONTEXT TranContext;
144 PFILE_OBJECT FileObject;
145 UCHAR MinorFunction;
146 DISCONNECT_TYPE DisType;
147 PVOID WorkItem;
148 /*NTSTATUS Status = STATUS_SUCCESS;*/
149
150 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
151
152 IrpSp = IoGetCurrentIrpStackLocation(Irp);
153 FileObject = IrpSp->FileObject;
154 TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext;
155 MinorFunction = IrpSp->MinorFunction;
156
157 TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X) MinorFunction (0x%X) IrpSp (0x%X).\n", Irp, MinorFunction, IrpSp));
158
159 Irp->IoStatus.Status = STATUS_CANCELLED;
160 Irp->IoStatus.Information = 0;
161
162 #ifdef DBG
163 if (!Irp->Cancel)
164 TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n"));
165 #endif
166
167 /* Try canceling the request */
168 switch(MinorFunction) {
169 case TDI_SEND:
170 case TDI_RECEIVE:
171 DisType.Type = TDI_DISCONNECT_RELEASE |
172 ((MinorFunction == TDI_RECEIVE) ? TDI_DISCONNECT_ABORT : 0);
173 DisType.Context = TranContext->Handle.ConnectionContext;
174 DisType.Irp = Irp;
175 DisType.FileObject = FileObject;
176
177 TCPRemoveIRP( TranContext->Handle.ConnectionContext, Irp );
178
179 if( !ChewCreate( &WorkItem, sizeof(DISCONNECT_TYPE),
180 DispDoDisconnect, &DisType ) )
181 ASSERT(0);
182
183 IoReleaseCancelSpinLock(Irp->CancelIrql);
184 return;
185
186 case TDI_SEND_DATAGRAM:
187 if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
188 TI_DbgPrint(MIN_TRACE, ("TDI_SEND_DATAGRAM, but no address file.\n"));
189 break;
190 }
191 break;
192
193 case TDI_RECEIVE_DATAGRAM:
194 if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
195 TI_DbgPrint(MIN_TRACE, ("TDI_RECEIVE_DATAGRAM, but no address file.\n"));
196 break;
197 }
198
199 DGRemoveIRP(TranContext->Handle.AddressHandle, Irp);
200 break;
201
202 default:
203 TI_DbgPrint(MIN_TRACE, ("Unknown IRP. MinorFunction (0x%X).\n", MinorFunction));
204 break;
205 }
206
207 IoReleaseCancelSpinLock(Irp->CancelIrql);
208 IoCompleteRequest(Irp, IO_NO_INCREMENT);
209
210 TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
211 }
212
213
214 VOID NTAPI DispCancelListenRequest(
215 PDEVICE_OBJECT Device,
216 PIRP Irp)
217 /*
218 * FUNCTION: Cancels a listen IRP
219 * ARGUMENTS:
220 * Device = Pointer to device object
221 * Irp = Pointer to an I/O request packet
222 */
223 {
224 PIO_STACK_LOCATION IrpSp;
225 PTRANSPORT_CONTEXT TranContext;
226 PFILE_OBJECT FileObject;
227 PCONNECTION_ENDPOINT Connection;
228 /*NTSTATUS Status = STATUS_SUCCESS;*/
229
230 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
231
232 IrpSp = IoGetCurrentIrpStackLocation(Irp);
233 FileObject = IrpSp->FileObject;
234 TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext;
235 ASSERT( TDI_LISTEN == IrpSp->MinorFunction);
236
237 TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X).\n", Irp));
238
239 #ifdef DBG
240 if (!Irp->Cancel)
241 TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n"));
242 #endif
243
244 /* Try canceling the request */
245 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
246 TCPAbortListenForSocket(
247 Connection->AddressFile->Listener,
248 Connection );
249
250 IoReleaseCancelSpinLock(Irp->CancelIrql);
251
252 DispDataRequestComplete(Irp, STATUS_CANCELLED, 0);
253
254 TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
255 }
256
257
258 NTSTATUS DispTdiAccept(
259 PIRP Irp)
260 /*
261 * FUNCTION: TDI_ACCEPT handler
262 * ARGUMENTS:
263 * Irp = Pointer to an I/O request packet
264 * RETURNS:
265 * Status of operation
266 */
267 {
268 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
269
270 return STATUS_NOT_IMPLEMENTED;
271 }
272
273
274 NTSTATUS DispTdiAssociateAddress(
275 PIRP Irp)
276 /*
277 * FUNCTION: TDI_ASSOCIATE_ADDRESS handler
278 * ARGUMENTS:
279 * Irp = Pointer to an I/O request packet
280 * RETURNS:
281 * Status of operation
282 */
283 {
284 PTDI_REQUEST_KERNEL_ASSOCIATE Parameters;
285 PTRANSPORT_CONTEXT TranContext;
286 PIO_STACK_LOCATION IrpSp;
287 PCONNECTION_ENDPOINT Connection;
288 PFILE_OBJECT FileObject;
289 PADDRESS_FILE AddrFile = NULL;
290 NTSTATUS Status;
291
292 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
293
294 IrpSp = IoGetCurrentIrpStackLocation(Irp);
295
296 /* Get associated connection endpoint file object. Quit if none exists */
297
298 TranContext = IrpSp->FileObject->FsContext;
299 if (!TranContext) {
300 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
301 return STATUS_INVALID_PARAMETER;
302 }
303
304 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
305 if (!Connection) {
306 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
307 return STATUS_INVALID_PARAMETER;
308 }
309
310 if (Connection->AddressFile) {
311 TI_DbgPrint(MID_TRACE, ("An address file is already asscociated.\n"));
312 return STATUS_INVALID_PARAMETER;
313 }
314
315 Parameters = (PTDI_REQUEST_KERNEL_ASSOCIATE)&IrpSp->Parameters;
316
317 Status = ObReferenceObjectByHandle(
318 Parameters->AddressHandle,
319 0,
320 IoFileObjectType,
321 KernelMode,
322 (PVOID*)&FileObject,
323 NULL);
324 if (!NT_SUCCESS(Status)) {
325 TI_DbgPrint(MID_TRACE, ("Bad address file object handle (0x%X): %x.\n",
326 Parameters->AddressHandle, Status));
327 return STATUS_INVALID_PARAMETER;
328 }
329
330 if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
331 ObDereferenceObject(FileObject);
332 TI_DbgPrint(MID_TRACE, ("Bad address file object. Magic (0x%X).\n",
333 FileObject->FsContext2));
334 return STATUS_INVALID_PARAMETER;
335 }
336
337 /* Get associated address file object. Quit if none exists */
338
339 TranContext = FileObject->FsContext;
340 if (!TranContext) {
341 ObDereferenceObject(FileObject);
342 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
343 return STATUS_INVALID_PARAMETER;
344 }
345
346 AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
347 if (!AddrFile) {
348 ObDereferenceObject(FileObject);
349 TI_DbgPrint(MID_TRACE, ("No address file object.\n"));
350 return STATUS_INVALID_PARAMETER;
351 }
352
353 Connection->AddressFile = AddrFile;
354
355 /* Add connection endpoint to the address file */
356 AddrFile->Connection = Connection;
357
358 /* FIXME: Maybe do this in DispTdiDisassociateAddress() instead? */
359 ObDereferenceObject(FileObject);
360
361 return Status;
362 }
363
364
365 NTSTATUS DispTdiConnect(
366 PIRP Irp)
367 /*
368 * FUNCTION: TDI_CONNECT handler
369 * ARGUMENTS:
370 * Irp = Pointer to an I/O request packet
371 * RETURNS:
372 * Status of operation
373 */
374 {
375 PCONNECTION_ENDPOINT Connection;
376 PTDI_REQUEST_KERNEL Parameters;
377 PTRANSPORT_CONTEXT TranContext;
378 PIO_STACK_LOCATION IrpSp;
379 NTSTATUS Status;
380
381 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
382
383 IrpSp = IoGetCurrentIrpStackLocation(Irp);
384
385 /* Get associated connection endpoint file object. Quit if none exists */
386
387 TcpipRecursiveMutexEnter( &TCPLock, TRUE );
388
389 TranContext = IrpSp->FileObject->FsContext;
390 if (!TranContext) {
391 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
392 Status = STATUS_INVALID_CONNECTION;
393 goto done;
394 }
395
396 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
397 if (!Connection) {
398 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
399 Status = STATUS_INVALID_CONNECTION;
400 goto done;
401 }
402
403 Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
404
405 Status = TCPConnect(
406 TranContext->Handle.ConnectionContext,
407 Parameters->RequestConnectionInformation,
408 Parameters->ReturnConnectionInformation,
409 DispDataRequestComplete,
410 Irp );
411
412 done:
413 if (Status != STATUS_PENDING) {
414 DispDataRequestComplete(Irp, Status, 0);
415 } else
416 IoMarkIrpPending(Irp);
417
418 TcpipRecursiveMutexLeave( &TCPLock );
419
420 TI_DbgPrint(MAX_TRACE, ("TCP Connect returned %08x\n", Status));
421
422 return Status;
423 }
424
425
426 NTSTATUS DispTdiDisassociateAddress(
427 PIRP Irp)
428 /*
429 * FUNCTION: TDI_DISASSOCIATE_ADDRESS handler
430 * ARGUMENTS:
431 * Irp = Pointer to an I/O request packet
432 * RETURNS:
433 * Status of operation
434 */
435 {
436 PCONNECTION_ENDPOINT Connection;
437 PTRANSPORT_CONTEXT TranContext;
438 PIO_STACK_LOCATION IrpSp;
439
440 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
441
442 IrpSp = IoGetCurrentIrpStackLocation(Irp);
443
444 /* Get associated connection endpoint file object. Quit if none exists */
445
446 TranContext = IrpSp->FileObject->FsContext;
447 if (!TranContext) {
448 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
449 return STATUS_INVALID_PARAMETER;
450 }
451
452 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
453 if (!Connection) {
454 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
455 return STATUS_INVALID_PARAMETER;
456 }
457
458 if (!Connection->AddressFile) {
459 TI_DbgPrint(MID_TRACE, ("No address file is asscociated.\n"));
460 return STATUS_INVALID_PARAMETER;
461 }
462
463 return STATUS_SUCCESS;
464 }
465
466
467 NTSTATUS DispTdiDisconnect(
468 PIRP Irp)
469 /*
470 * FUNCTION: TDI_DISCONNECT handler
471 * ARGUMENTS:
472 * Irp = Pointer to an I/O request packet
473 * RETURNS:
474 * Status of operation
475 */
476 {
477 NTSTATUS Status;
478 PTDI_REQUEST_KERNEL_DISCONNECT DisReq;
479 PCONNECTION_ENDPOINT Connection;
480 PTRANSPORT_CONTEXT TranContext;
481 PIO_STACK_LOCATION IrpSp;
482
483 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
484
485 IrpSp = IoGetCurrentIrpStackLocation(Irp);
486 DisReq = (PTDI_REQUEST_KERNEL_DISCONNECT)&IrpSp->Parameters;
487
488 TcpipRecursiveMutexEnter( &TCPLock, TRUE );
489
490 /* Get associated connection endpoint file object. Quit if none exists */
491
492 TranContext = IrpSp->FileObject->FsContext;
493 if (!TranContext) {
494 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
495 Status = STATUS_INVALID_CONNECTION;
496 goto done;
497 }
498
499 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
500 if (!Connection) {
501 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
502 Status = STATUS_INVALID_CONNECTION;
503 goto done;
504 }
505
506 Status = TCPDisconnect(
507 TranContext->Handle.ConnectionContext,
508 DisReq->RequestFlags,
509 DisReq->RequestConnectionInformation,
510 DisReq->ReturnConnectionInformation,
511 DispDataRequestComplete,
512 Irp );
513
514 done:
515 if (Status != STATUS_PENDING) {
516 DispDataRequestComplete(Irp, Status, 0);
517 } else
518 IoMarkIrpPending(Irp);
519
520 TcpipRecursiveMutexLeave( &TCPLock );
521
522 TI_DbgPrint(MAX_TRACE, ("TCP Disconnect returned %08x\n", Status));
523
524 return Status;
525 }
526
527
528 NTSTATUS DispTdiListen(
529 PIRP Irp)
530 /*
531 * FUNCTION: TDI_LISTEN handler
532 * ARGUMENTS:
533 * Irp = Pointer to an I/O request packet
534 * RETURNS:
535 * Status of operation
536 */
537 {
538 PCONNECTION_ENDPOINT Connection;
539 PTDI_REQUEST_KERNEL Parameters;
540 PTRANSPORT_CONTEXT TranContext;
541 PIO_STACK_LOCATION IrpSp;
542 NTSTATUS Status = STATUS_SUCCESS;
543
544 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
545
546 IrpSp = IoGetCurrentIrpStackLocation(Irp);
547
548 /* Get associated connection endpoint file object. Quit if none exists */
549
550 TcpipRecursiveMutexEnter( &TCPLock, TRUE );
551
552 TranContext = IrpSp->FileObject->FsContext;
553 if (TranContext == NULL)
554 {
555 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
556 Status = STATUS_INVALID_CONNECTION;
557 goto done;
558 }
559
560 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
561 if (Connection == NULL)
562 {
563 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
564 Status = STATUS_INVALID_CONNECTION;
565 goto done;
566 }
567
568 Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
569
570 TI_DbgPrint(MIN_TRACE, ("Connection->AddressFile: %x\n",
571 Connection->AddressFile ));
572 if( Connection->AddressFile ) {
573 TI_DbgPrint(MIN_TRACE, ("Connection->AddressFile->Listener: %x\n",
574 Connection->AddressFile->Listener));
575 }
576
577 /* Listening will require us to create a listening socket and store it in
578 * the address file. It will be signalled, and attempt to complete an irp
579 * when a new connection arrives. */
580 /* The important thing to note here is that the irp we'll complete belongs
581 * to the socket to be accepted onto, not the listener */
582 if( !Connection->AddressFile->Listener ) {
583 Connection->AddressFile->Listener =
584 TCPAllocateConnectionEndpoint( NULL );
585
586 if( !Connection->AddressFile->Listener )
587 Status = STATUS_NO_MEMORY;
588
589 if( NT_SUCCESS(Status) ) {
590 Connection->AddressFile->Listener->AddressFile =
591 Connection->AddressFile;
592
593 Status = TCPSocket( Connection->AddressFile->Listener,
594 Connection->AddressFile->Family,
595 SOCK_STREAM,
596 Connection->AddressFile->Protocol );
597 }
598
599 if( NT_SUCCESS(Status) )
600 Status = TCPListen( Connection->AddressFile->Listener, 1024 );
601 /* BACKLOG */
602 }
603 if( NT_SUCCESS(Status) ) {
604 Status = DispPrepareIrpForCancel
605 (TranContext->Handle.ConnectionContext,
606 Irp,
607 (PDRIVER_CANCEL)DispCancelListenRequest);
608 }
609
610 if( NT_SUCCESS(Status) ) {
611 Status = TCPAccept
612 ( (PTDI_REQUEST)Parameters,
613 Connection->AddressFile->Listener,
614 Connection,
615 DispDataRequestComplete,
616 Irp );
617 }
618
619 done:
620 if (Status != STATUS_PENDING) {
621 DispDataRequestComplete(Irp, Status, 0);
622 } else
623 IoMarkIrpPending(Irp);
624
625 TcpipRecursiveMutexLeave( &TCPLock );
626
627 TI_DbgPrint(MID_TRACE,("Leaving %x\n", Status));
628
629 return Status;
630 }
631
632
633 NTSTATUS DispTdiQueryInformation(
634 PDEVICE_OBJECT DeviceObject,
635 PIRP Irp)
636 /*
637 * FUNCTION: TDI_QUERY_INFORMATION handler
638 * ARGUMENTS:
639 * DeviceObject = Pointer to device object structure
640 * Irp = Pointer to an I/O request packet
641 * RETURNS:
642 * Status of operation
643 */
644 {
645 PTDI_REQUEST_KERNEL_QUERY_INFORMATION Parameters;
646 PTRANSPORT_CONTEXT TranContext;
647 PIO_STACK_LOCATION IrpSp;
648
649 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
650
651 IrpSp = IoGetCurrentIrpStackLocation(Irp);
652 Parameters = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&IrpSp->Parameters;
653
654 TranContext = IrpSp->FileObject->FsContext;
655 if (!TranContext) {
656 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
657 return STATUS_INVALID_CONNECTION;
658 }
659
660 switch (Parameters->QueryType)
661 {
662 case TDI_QUERY_ADDRESS_INFO:
663 {
664 PTDI_ADDRESS_INFO AddressInfo;
665 PADDRESS_FILE AddrFile;
666 PTA_IP_ADDRESS Address;
667
668 AddressInfo = (PTDI_ADDRESS_INFO)MmGetSystemAddressForMdl(Irp->MdlAddress);
669
670 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
671 case TDI_TRANSPORT_ADDRESS_FILE:
672 AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
673 break;
674
675 case TDI_CONNECTION_FILE:
676 AddrFile =
677 ((PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext)->
678 AddressFile;
679 break;
680
681 default:
682 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
683 return STATUS_INVALID_PARAMETER;
684 }
685
686 if (!AddrFile) {
687 TI_DbgPrint(MID_TRACE, ("No address file object.\n"));
688 return STATUS_INVALID_PARAMETER;
689 }
690
691 if (MmGetMdlByteCount(Irp->MdlAddress) <
692 (FIELD_OFFSET(TDI_ADDRESS_INFO, Address.Address[0].Address) +
693 sizeof(TDI_ADDRESS_IP))) {
694 TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n"));
695 return STATUS_BUFFER_OVERFLOW;
696 }
697
698 Address = (PTA_IP_ADDRESS)&AddressInfo->Address;
699 Address->TAAddressCount = 1;
700 Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
701 Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
702 Address->Address[0].Address[0].sin_port = AddrFile->Port;
703 Address->Address[0].Address[0].in_addr =
704 AddrFile->Address.Address.IPv4Address;
705 RtlZeroMemory(
706 &Address->Address[0].Address[0].sin_zero,
707 sizeof(Address->Address[0].Address[0].sin_zero));
708
709 return STATUS_SUCCESS;
710 }
711
712 case TDI_QUERY_CONNECTION_INFO:
713 {
714 PTDI_CONNECTION_INFORMATION AddressInfo;
715 PADDRESS_FILE AddrFile;
716 PCONNECTION_ENDPOINT Endpoint = NULL;
717
718 AddressInfo = (PTDI_CONNECTION_INFORMATION)
719 MmGetSystemAddressForMdl(Irp->MdlAddress);
720
721 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
722 case TDI_TRANSPORT_ADDRESS_FILE:
723 AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
724 break;
725
726 case TDI_CONNECTION_FILE:
727 Endpoint =
728 (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
729 break;
730
731 default:
732 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
733 return STATUS_INVALID_PARAMETER;
734 }
735
736 if (!Endpoint) {
737 TI_DbgPrint(MID_TRACE, ("No connection object.\n"));
738 return STATUS_INVALID_PARAMETER;
739 }
740
741 if (MmGetMdlByteCount(Irp->MdlAddress) <
742 (FIELD_OFFSET(TDI_CONNECTION_INFORMATION, RemoteAddress) +
743 sizeof(PVOID))) {
744 TI_DbgPrint(MID_TRACE, ("MDL buffer too small (ptr).\n"));
745 return STATUS_BUFFER_OVERFLOW;
746 }
747
748 return TCPGetPeerAddress( Endpoint, AddressInfo->RemoteAddress );
749 }
750 }
751
752 return STATUS_NOT_IMPLEMENTED;
753 }
754
755
756 NTSTATUS DispTdiReceive(
757 PIRP Irp)
758 /*
759 * FUNCTION: TDI_RECEIVE handler
760 * ARGUMENTS:
761 * Irp = Pointer to an I/O request packet
762 * RETURNS:
763 * Status of operation
764 */
765 {
766 PIO_STACK_LOCATION IrpSp;
767 PTDI_REQUEST_KERNEL_RECEIVE ReceiveInfo;
768 PTRANSPORT_CONTEXT TranContext;
769 NTSTATUS Status;
770 ULONG BytesReceived;
771
772 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
773
774 IrpSp = IoGetCurrentIrpStackLocation(Irp);
775 ReceiveInfo = (PTDI_REQUEST_KERNEL_RECEIVE)&(IrpSp->Parameters);
776
777 TcpipRecursiveMutexEnter( &TCPLock, TRUE );
778
779 TranContext = IrpSp->FileObject->FsContext;
780 if (TranContext == NULL)
781 {
782 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
783 Status = STATUS_INVALID_CONNECTION;
784 goto done;
785 }
786
787 if (TranContext->Handle.ConnectionContext == NULL)
788 {
789 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
790 Status = STATUS_INVALID_CONNECTION;
791 goto done;
792 }
793
794 /* Initialize a receive request */
795 Status = DispPrepareIrpForCancel
796 (TranContext->Handle.ConnectionContext,
797 Irp,
798 (PDRIVER_CANCEL)DispCancelRequest);
799
800 TI_DbgPrint(MID_TRACE,("TCPIP<<< Got an MDL: %x\n", Irp->MdlAddress));
801 if (NT_SUCCESS(Status))
802 {
803 Status = TCPReceiveData(
804 TranContext->Handle.ConnectionContext,
805 (PNDIS_BUFFER)Irp->MdlAddress,
806 ReceiveInfo->ReceiveLength,
807 &BytesReceived,
808 ReceiveInfo->ReceiveFlags,
809 DispDataRequestComplete,
810 Irp);
811 }
812
813 done:
814 if (Status != STATUS_PENDING) {
815 DispDataRequestComplete(Irp, Status, BytesReceived);
816 } else
817 IoMarkIrpPending(Irp);
818
819 TcpipRecursiveMutexLeave( &TCPLock );
820
821 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
822
823 return Status;
824 }
825
826
827 NTSTATUS DispTdiReceiveDatagram(
828 PIRP Irp)
829 /*
830 * FUNCTION: TDI_RECEIVE_DATAGRAM handler
831 * ARGUMENTS:
832 * Irp = Pointer to an I/O request packet
833 * RETURNS:
834 * Status of operation
835 */
836 {
837 PIO_STACK_LOCATION IrpSp;
838 PTDI_REQUEST_KERNEL_RECEIVEDG DgramInfo;
839 PTRANSPORT_CONTEXT TranContext;
840 TDI_REQUEST Request;
841 NTSTATUS Status;
842 ULONG BytesReceived;
843
844 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
845
846 IrpSp = IoGetCurrentIrpStackLocation(Irp);
847 DgramInfo = (PTDI_REQUEST_KERNEL_RECEIVEDG)&(IrpSp->Parameters);
848
849 TcpipRecursiveMutexEnter( &TCPLock, TRUE );
850
851 TranContext = IrpSp->FileObject->FsContext;
852 if (TranContext == NULL)
853 {
854 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
855 Status = STATUS_INVALID_CONNECTION;
856 goto done;
857 }
858
859 /* Initialize a receive request */
860 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
861 Request.RequestNotifyObject = DispDataRequestComplete;
862 Request.RequestContext = Irp;
863
864 Status = DispPrepareIrpForCancel(
865 IrpSp->FileObject->FsContext,
866 Irp,
867 (PDRIVER_CANCEL)DispCancelRequest);
868
869 if (NT_SUCCESS(Status))
870 {
871 PCHAR DataBuffer;
872 UINT BufferSize;
873
874 NdisQueryBuffer( (PNDIS_BUFFER)Irp->MdlAddress,
875 &DataBuffer,
876 &BufferSize );
877
878 Status = DGReceiveDatagram(
879 Request.Handle.AddressHandle,
880 DgramInfo->ReceiveDatagramInformation,
881 DataBuffer,
882 DgramInfo->ReceiveLength,
883 DgramInfo->ReceiveFlags,
884 DgramInfo->ReturnDatagramInformation,
885 &BytesReceived,
886 (PDATAGRAM_COMPLETION_ROUTINE)DispDataRequestComplete,
887 Irp,
888 Irp);
889 }
890
891 done:
892 if (Status != STATUS_PENDING) {
893 DispDataRequestComplete(Irp, Status, BytesReceived);
894 } else
895 IoMarkIrpPending(Irp);
896
897 TcpipRecursiveMutexLeave( &TCPLock );
898
899 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
900
901 return Status;
902 }
903
904
905 NTSTATUS DispTdiSend(
906 PIRP Irp)
907 /*
908 * FUNCTION: TDI_SEND handler
909 * ARGUMENTS:
910 * Irp = Pointer to an I/O request packet
911 * RETURNS:
912 * Status of operation
913 */
914 {
915 PIO_STACK_LOCATION IrpSp;
916 PTDI_REQUEST_KERNEL_SEND SendInfo;
917 PTRANSPORT_CONTEXT TranContext;
918 NTSTATUS Status;
919 ULONG BytesSent;
920
921 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
922
923 IrpSp = IoGetCurrentIrpStackLocation(Irp);
924 SendInfo = (PTDI_REQUEST_KERNEL_SEND)&(IrpSp->Parameters);
925
926 TcpipRecursiveMutexEnter( &TCPLock, TRUE );
927
928 TranContext = IrpSp->FileObject->FsContext;
929 if (TranContext == NULL)
930 {
931 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
932 Status = STATUS_INVALID_CONNECTION;
933 goto done;
934 }
935
936 if (TranContext->Handle.ConnectionContext == NULL)
937 {
938 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
939 Status = STATUS_INVALID_CONNECTION;
940 goto done;
941 }
942
943 Status = DispPrepareIrpForCancel(
944 IrpSp->FileObject->FsContext,
945 Irp,
946 (PDRIVER_CANCEL)DispCancelRequest);
947
948 TI_DbgPrint(MID_TRACE,("TCPIP<<< Got an MDL: %x\n", Irp->MdlAddress));
949 if (NT_SUCCESS(Status))
950 {
951 PCHAR Data;
952 UINT Len;
953
954 NdisQueryBuffer( Irp->MdlAddress, &Data, &Len );
955
956 TI_DbgPrint(MID_TRACE,("About to TCPSendData\n"));
957 Status = TCPSendData(
958 TranContext->Handle.ConnectionContext,
959 Data,
960 SendInfo->SendLength,
961 &BytesSent,
962 SendInfo->SendFlags,
963 DispDataRequestComplete,
964 Irp);
965 }
966
967 done:
968 if (Status != STATUS_PENDING) {
969 DispDataRequestComplete(Irp, Status, BytesSent);
970 } else
971 IoMarkIrpPending(Irp);
972
973 TcpipRecursiveMutexLeave( &TCPLock );
974
975 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
976
977 return Status;
978 }
979
980
981 NTSTATUS DispTdiSendDatagram(
982 PIRP Irp)
983 /*
984 * FUNCTION: TDI_SEND_DATAGRAM handler
985 * ARGUMENTS:
986 * Irp = Pointer to an I/O request packet
987 * RETURNS:
988 * Status of operation
989 */
990 {
991 PIO_STACK_LOCATION IrpSp;
992 TDI_REQUEST Request;
993 PTDI_REQUEST_KERNEL_SENDDG DgramInfo;
994 PTRANSPORT_CONTEXT TranContext;
995 NTSTATUS Status;
996
997 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
998
999 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1000 DgramInfo = (PTDI_REQUEST_KERNEL_SENDDG)&(IrpSp->Parameters);
1001
1002 TcpipRecursiveMutexEnter( &TCPLock, TRUE );
1003
1004 TranContext = IrpSp->FileObject->FsContext;
1005 if (TranContext == NULL)
1006 {
1007 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
1008 Status = STATUS_INVALID_CONNECTION;
1009 goto done;
1010 }
1011
1012 /* Initialize a send request */
1013 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
1014 Request.RequestNotifyObject = DispDataRequestComplete;
1015 Request.RequestContext = Irp;
1016
1017 Status = DispPrepareIrpForCancel(
1018 IrpSp->FileObject->FsContext,
1019 Irp,
1020 (PDRIVER_CANCEL)DispCancelRequest);
1021
1022 if (NT_SUCCESS(Status)) {
1023 PCHAR DataBuffer;
1024 UINT BufferSize;
1025
1026 TI_DbgPrint(MID_TRACE,("About to query buffer %x\n", Irp->MdlAddress));
1027
1028 NdisQueryBuffer( (PNDIS_BUFFER)Irp->MdlAddress,
1029 &DataBuffer,
1030 &BufferSize );
1031
1032 /* FIXME: DgramInfo->SendDatagramInformation->RemoteAddress
1033 must be of type PTDI_ADDRESS_IP */
1034 TI_DbgPrint(MID_TRACE,
1035 ("About to call send routine %x\n",
1036 (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)));
1037
1038 if( (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send) )
1039 {
1040 ULONG DataUsed = 0;
1041 Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)(
1042 Request.Handle.AddressHandle,
1043 DgramInfo->SendDatagramInformation,
1044 DataBuffer,
1045 BufferSize,
1046 &DataUsed);
1047 Irp->IoStatus.Information = DataUsed;
1048 }
1049 else
1050 Status = STATUS_UNSUCCESSFUL;
1051 }
1052
1053 done:
1054 if (Status != STATUS_PENDING) {
1055 DispDataRequestComplete(Irp, Status, Irp->IoStatus.Information);
1056 } else
1057 IoMarkIrpPending(Irp);
1058
1059 TcpipRecursiveMutexLeave( &TCPLock );
1060
1061 TI_DbgPrint(DEBUG_IRP, ("Leaving.\n"));
1062
1063 return Status;
1064 }
1065
1066
1067 NTSTATUS DispTdiSetEventHandler(PIRP Irp)
1068 /*
1069 * FUNCTION: TDI_SET_EVENT_HANDER handler
1070 * ARGUMENTS:
1071 * Irp = Pointer to a I/O request packet
1072 * RETURNS:
1073 * Status of operation
1074 */
1075 {
1076 PTDI_REQUEST_KERNEL_SET_EVENT Parameters;
1077 PTRANSPORT_CONTEXT TranContext;
1078 PIO_STACK_LOCATION IrpSp;
1079 PADDRESS_FILE AddrFile;
1080 NTSTATUS Status;
1081 KIRQL OldIrql;
1082
1083 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1084
1085 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1086
1087 /* Get associated address file object. Quit if none exists */
1088
1089 TranContext = IrpSp->FileObject->FsContext;
1090 if (!TranContext) {
1091 TI_DbgPrint(MIN_TRACE, ("Bad transport context.\n"));
1092 return STATUS_INVALID_PARAMETER;
1093 }
1094
1095 AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
1096 if (!AddrFile) {
1097 TI_DbgPrint(MIN_TRACE, ("No address file object.\n"));
1098 return STATUS_INVALID_PARAMETER;
1099 }
1100
1101 Parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters;
1102 Status = STATUS_SUCCESS;
1103
1104 TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
1105
1106 /* Set the event handler. if an event handler is associated with
1107 a specific event, it's flag (RegisteredXxxHandler) is TRUE.
1108 If an event handler is not used it's flag is FALSE */
1109 switch (Parameters->EventType) {
1110 case TDI_EVENT_CONNECT:
1111 if (!Parameters->EventHandler) {
1112 AddrFile->ConnectHandlerContext = NULL;
1113 AddrFile->RegisteredConnectHandler = FALSE;
1114 } else {
1115 AddrFile->ConnectHandler =
1116 (PTDI_IND_CONNECT)Parameters->EventHandler;
1117 AddrFile->ConnectHandlerContext = Parameters->EventContext;
1118 AddrFile->RegisteredConnectHandler = TRUE;
1119 }
1120 break;
1121
1122 case TDI_EVENT_DISCONNECT:
1123 if (!Parameters->EventHandler) {
1124 AddrFile->DisconnectHandlerContext = NULL;
1125 AddrFile->RegisteredDisconnectHandler = FALSE;
1126 } else {
1127 AddrFile->DisconnectHandler =
1128 (PTDI_IND_DISCONNECT)Parameters->EventHandler;
1129 AddrFile->DisconnectHandlerContext = Parameters->EventContext;
1130 AddrFile->RegisteredDisconnectHandler = TRUE;
1131 }
1132 break;
1133
1134 case TDI_EVENT_ERROR:
1135 if (Parameters->EventHandler == NULL) {
1136 AddrFile->ErrorHandlerContext = NULL;
1137 AddrFile->RegisteredErrorHandler = FALSE;
1138 } else {
1139 AddrFile->ErrorHandler =
1140 (PTDI_IND_ERROR)Parameters->EventHandler;
1141 AddrFile->ErrorHandlerContext = Parameters->EventContext;
1142 AddrFile->RegisteredErrorHandler = TRUE;
1143 }
1144 break;
1145
1146 case TDI_EVENT_RECEIVE:
1147 if (Parameters->EventHandler == NULL) {
1148 AddrFile->ReceiveHandlerContext = NULL;
1149 AddrFile->RegisteredReceiveHandler = FALSE;
1150 } else {
1151 AddrFile->ReceiveHandler =
1152 (PTDI_IND_RECEIVE)Parameters->EventHandler;
1153 AddrFile->ReceiveHandlerContext = Parameters->EventContext;
1154 AddrFile->RegisteredReceiveHandler = TRUE;
1155 }
1156 break;
1157
1158 case TDI_EVENT_RECEIVE_DATAGRAM:
1159 if (Parameters->EventHandler == NULL) {
1160 AddrFile->ReceiveDatagramHandlerContext = NULL;
1161 AddrFile->RegisteredReceiveDatagramHandler = FALSE;
1162 } else {
1163 AddrFile->ReceiveDatagramHandler =
1164 (PTDI_IND_RECEIVE_DATAGRAM)Parameters->EventHandler;
1165 AddrFile->ReceiveDatagramHandlerContext = Parameters->EventContext;
1166 AddrFile->RegisteredReceiveDatagramHandler = TRUE;
1167 }
1168 break;
1169
1170 case TDI_EVENT_RECEIVE_EXPEDITED:
1171 if (Parameters->EventHandler == NULL) {
1172 AddrFile->ExpeditedReceiveHandlerContext = NULL;
1173 AddrFile->RegisteredExpeditedReceiveHandler = FALSE;
1174 } else {
1175 AddrFile->ExpeditedReceiveHandler =
1176 (PTDI_IND_RECEIVE_EXPEDITED)Parameters->EventHandler;
1177 AddrFile->ExpeditedReceiveHandlerContext = Parameters->EventContext;
1178 AddrFile->RegisteredExpeditedReceiveHandler = TRUE;
1179 }
1180 break;
1181
1182 case TDI_EVENT_CHAINED_RECEIVE:
1183 if (Parameters->EventHandler == NULL) {
1184 AddrFile->ChainedReceiveHandlerContext = NULL;
1185 AddrFile->RegisteredChainedReceiveHandler = FALSE;
1186 } else {
1187 AddrFile->ChainedReceiveHandler =
1188 (PTDI_IND_CHAINED_RECEIVE)Parameters->EventHandler;
1189 AddrFile->ChainedReceiveHandlerContext = Parameters->EventContext;
1190 AddrFile->RegisteredChainedReceiveHandler = TRUE;
1191 }
1192 break;
1193
1194 case TDI_EVENT_CHAINED_RECEIVE_DATAGRAM:
1195 if (Parameters->EventHandler == NULL) {
1196 AddrFile->ChainedReceiveDatagramHandlerContext = NULL;
1197 AddrFile->RegisteredChainedReceiveDatagramHandler = FALSE;
1198 } else {
1199 AddrFile->ChainedReceiveDatagramHandler =
1200 (PTDI_IND_CHAINED_RECEIVE_DATAGRAM)Parameters->EventHandler;
1201 AddrFile->ChainedReceiveDatagramHandlerContext = Parameters->EventContext;
1202 AddrFile->RegisteredChainedReceiveDatagramHandler = TRUE;
1203 }
1204 break;
1205
1206 case TDI_EVENT_CHAINED_RECEIVE_EXPEDITED:
1207 if (Parameters->EventHandler == NULL) {
1208 AddrFile->ChainedReceiveExpeditedHandlerContext = NULL;
1209 AddrFile->RegisteredChainedReceiveExpeditedHandler = FALSE;
1210 } else {
1211 AddrFile->ChainedReceiveExpeditedHandler =
1212 (PTDI_IND_CHAINED_RECEIVE_EXPEDITED)Parameters->EventHandler;
1213 AddrFile->ChainedReceiveExpeditedHandlerContext = Parameters->EventContext;
1214 AddrFile->RegisteredChainedReceiveExpeditedHandler = TRUE;
1215 }
1216 break;
1217
1218 default:
1219 TI_DbgPrint(MIN_TRACE, ("Unknown event type (0x%X).\n",
1220 Parameters->EventType));
1221
1222 Status = STATUS_INVALID_PARAMETER;
1223 }
1224
1225 TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
1226
1227 return Status;
1228 }
1229
1230
1231 NTSTATUS DispTdiSetInformation(
1232 PIRP Irp)
1233 /*
1234 * FUNCTION: TDI_SET_INFORMATION handler
1235 * ARGUMENTS:
1236 * Irp = Pointer to an I/O request packet
1237 * RETURNS:
1238 * Status of operation
1239 */
1240 {
1241 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1242
1243 return STATUS_NOT_IMPLEMENTED;
1244 }
1245
1246
1247 VOID DispTdiQueryInformationExComplete(
1248 PVOID Context,
1249 ULONG Status,
1250 UINT ByteCount)
1251 /*
1252 * FUNCTION: Completes a TDI QueryInformationEx request
1253 * ARGUMENTS:
1254 * Context = Pointer to the IRP for the request
1255 * Status = TDI status of the request
1256 * ByteCount = Number of bytes returned in output buffer
1257 */
1258 {
1259 PTI_QUERY_CONTEXT QueryContext;
1260 UINT Count = 0;
1261
1262 QueryContext = (PTI_QUERY_CONTEXT)Context;
1263 if (NT_SUCCESS(Status)) {
1264 Count = CopyBufferToBufferChain(
1265 QueryContext->InputMdl,
1266 FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context),
1267 (PCHAR)&QueryContext->QueryInfo.Context,
1268 CONTEXT_SIZE);
1269 }
1270
1271 MmUnlockPages(QueryContext->InputMdl);
1272 IoFreeMdl(QueryContext->InputMdl);
1273 if( QueryContext->OutputMdl ) {
1274 MmUnlockPages(QueryContext->OutputMdl);
1275 IoFreeMdl(QueryContext->OutputMdl);
1276 }
1277
1278 QueryContext->Irp->IoStatus.Information = ByteCount;
1279 QueryContext->Irp->IoStatus.Status = Status;
1280
1281 ExFreePool(QueryContext);
1282 }
1283
1284
1285 NTSTATUS DispTdiQueryInformationEx(
1286 PIRP Irp,
1287 PIO_STACK_LOCATION IrpSp)
1288 /*
1289 * FUNCTION: TDI QueryInformationEx handler
1290 * ARGUMENTS:
1291 * Irp = Pointer to I/O request packet
1292 * IrpSp = Pointer to current stack location of Irp
1293 * RETURNS:
1294 * Status of operation
1295 */
1296 {
1297 PTCP_REQUEST_QUERY_INFORMATION_EX InputBuffer;
1298 PTRANSPORT_CONTEXT TranContext;
1299 PTI_QUERY_CONTEXT QueryContext;
1300 PVOID OutputBuffer;
1301 TDI_REQUEST Request;
1302 UINT Size;
1303 UINT InputBufferLength;
1304 UINT OutputBufferLength;
1305 BOOLEAN InputMdlLocked = FALSE;
1306 BOOLEAN OutputMdlLocked = FALSE;
1307 PMDL InputMdl = NULL;
1308 PMDL OutputMdl = NULL;
1309 NTSTATUS Status = STATUS_SUCCESS;
1310
1311 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1312
1313 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
1314
1315 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
1316 case TDI_TRANSPORT_ADDRESS_FILE:
1317 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
1318 break;
1319
1320 case TDI_CONNECTION_FILE:
1321 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
1322 break;
1323
1324 case TDI_CONTROL_CHANNEL_FILE:
1325 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
1326 break;
1327
1328 default:
1329 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
1330 return STATUS_INVALID_PARAMETER;
1331 }
1332
1333 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
1334 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
1335
1336 /* Validate parameters */
1337 if ((InputBufferLength == sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)) &&
1338 (OutputBufferLength != 0)) {
1339
1340 InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
1341 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
1342 OutputBuffer = Irp->UserBuffer;
1343
1344 QueryContext = ExAllocatePool(NonPagedPool, sizeof(TI_QUERY_CONTEXT));
1345 if (QueryContext) {
1346 _SEH_TRY {
1347 InputMdl = IoAllocateMdl(InputBuffer,
1348 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
1349 FALSE, TRUE, NULL);
1350
1351 OutputMdl = IoAllocateMdl(OutputBuffer,
1352 OutputBufferLength, FALSE, TRUE, NULL);
1353
1354 if (InputMdl && OutputMdl) {
1355
1356 MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
1357 IoModifyAccess);
1358
1359 InputMdlLocked = TRUE;
1360
1361 MmProbeAndLockPages(OutputMdl, Irp->RequestorMode,
1362 IoWriteAccess);
1363
1364 OutputMdlLocked = TRUE;
1365
1366 RtlCopyMemory(&QueryContext->QueryInfo,
1367 InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
1368 } else
1369 Status = STATUS_INSUFFICIENT_RESOURCES;
1370 } _SEH_HANDLE {
1371 Status = _SEH_GetExceptionCode();
1372 } _SEH_END;
1373
1374 if (NT_SUCCESS(Status)) {
1375 Size = MmGetMdlByteCount(OutputMdl);
1376
1377 QueryContext->Irp = Irp;
1378 QueryContext->InputMdl = InputMdl;
1379 QueryContext->OutputMdl = OutputMdl;
1380
1381 Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
1382 Request.RequestContext = QueryContext;
1383 Status = InfoTdiQueryInformationEx(&Request,
1384 &QueryContext->QueryInfo.ID, OutputMdl,
1385 &Size, &QueryContext->QueryInfo.Context);
1386 DispTdiQueryInformationExComplete(QueryContext, Status, Size);
1387
1388 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1389
1390 return Status;
1391 }
1392
1393 /* An error occurred if we get here */
1394
1395 if (InputMdl) {
1396 if (InputMdlLocked)
1397 MmUnlockPages(InputMdl);
1398 IoFreeMdl(InputMdl);
1399 }
1400
1401 if (OutputMdl) {
1402 if (OutputMdlLocked)
1403 MmUnlockPages(OutputMdl);
1404 IoFreeMdl(OutputMdl);
1405 }
1406
1407 ExFreePool(QueryContext);
1408 } else
1409 Status = STATUS_INSUFFICIENT_RESOURCES;
1410 } else if( InputBufferLength ==
1411 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX) ) {
1412 /* Handle the case where the user is probing the buffer for length */
1413 TI_DbgPrint(MAX_TRACE, ("InputBufferLength %d OutputBufferLength %d\n",
1414 InputBufferLength, OutputBufferLength));
1415 InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
1416 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
1417
1418 Size = 0;
1419
1420 QueryContext = ExAllocatePool(NonPagedPool, sizeof(TI_QUERY_CONTEXT));
1421 if (!QueryContext) return STATUS_INSUFFICIENT_RESOURCES;
1422
1423 _SEH_TRY {
1424 InputMdl = IoAllocateMdl(InputBuffer,
1425 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
1426 FALSE, TRUE, NULL);
1427
1428 MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
1429 IoModifyAccess);
1430
1431 InputMdlLocked = TRUE;
1432 Status = STATUS_SUCCESS;
1433 } _SEH_HANDLE {
1434 TI_DbgPrint(MAX_TRACE, ("Failed to acquire client buffer\n"));
1435 Status = _SEH_GetExceptionCode();
1436 } _SEH_END;
1437
1438 if( !NT_SUCCESS(Status) || !InputMdl ) {
1439 if( InputMdl ) IoFreeMdl( InputMdl );
1440 ExFreePool(QueryContext);
1441 return Status;
1442 }
1443
1444 RtlCopyMemory(&QueryContext->QueryInfo,
1445 InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
1446
1447 QueryContext->Irp = Irp;
1448 QueryContext->InputMdl = InputMdl;
1449 QueryContext->OutputMdl = NULL;
1450
1451 Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
1452 Request.RequestContext = QueryContext;
1453 Status = InfoTdiQueryInformationEx(&Request,
1454 &QueryContext->QueryInfo.ID,
1455 NULL,
1456 &Size,
1457 &QueryContext->QueryInfo.Context);
1458 DispTdiQueryInformationExComplete(QueryContext, Status, Size);
1459 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1460 } else Status = STATUS_INVALID_PARAMETER;
1461
1462 TI_DbgPrint(MIN_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1463
1464 return Status;
1465 }
1466
1467
1468 NTSTATUS DispTdiSetInformationEx(
1469 PIRP Irp,
1470 PIO_STACK_LOCATION IrpSp)
1471 /*
1472 * FUNCTION: TDI SetInformationEx handler
1473 * ARGUMENTS:
1474 * Irp = Pointer to I/O request packet
1475 * IrpSp = Pointer to current stack location of Irp
1476 * RETURNS:
1477 * Status of operation
1478 */
1479 {
1480 PTRANSPORT_CONTEXT TranContext;
1481 PTCP_REQUEST_SET_INFORMATION_EX Info;
1482 TDI_REQUEST Request;
1483 TDI_STATUS Status;
1484
1485 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1486
1487 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
1488 Info = (PTCP_REQUEST_SET_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer;
1489
1490 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
1491 case TDI_TRANSPORT_ADDRESS_FILE:
1492 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
1493 break;
1494
1495 case TDI_CONNECTION_FILE:
1496 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
1497 break;
1498
1499 case TDI_CONTROL_CHANNEL_FILE:
1500 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
1501 break;
1502
1503 default:
1504 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1505 Irp->IoStatus.Information = 0;
1506
1507 TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
1508
1509 return Irp->IoStatus.Status;
1510 }
1511
1512 Status = DispPrepareIrpForCancel(TranContext, Irp, NULL);
1513 if (NT_SUCCESS(Status)) {
1514 Request.RequestNotifyObject = DispDataRequestComplete;
1515 Request.RequestContext = Irp;
1516
1517 Status = InfoTdiSetInformationEx(&Request, &Info->ID,
1518 &Info->Buffer, Info->BufferSize);
1519 }
1520
1521 return Status;
1522 }
1523
1524 /* TODO: Support multiple addresses per interface.
1525 * For now just set the nte context to the interface index.
1526 *
1527 * Later on, create an NTE context and NTE instance
1528 */
1529
1530 NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
1531 NTSTATUS Status = STATUS_DEVICE_DOES_NOT_EXIST;
1532 PIP_SET_ADDRESS IpAddrChange =
1533 (PIP_SET_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
1534 IF_LIST_ITER(IF);
1535
1536 TI_DbgPrint(MID_TRACE,("Setting IP Address for adapter %d\n",
1537 IpAddrChange->NteIndex));
1538
1539 ForEachInterface(IF) {
1540 TI_DbgPrint(MID_TRACE,("Looking at adapter %d\n", IF->Index));
1541
1542 if( IF->Unicast.Address.IPv4Address == IpAddrChange->Address ) {
1543 Status = STATUS_DUPLICATE_OBJECTID;
1544 break;
1545 }
1546 if( IF->Index == IpAddrChange->NteIndex ) {
1547 IPRemoveInterfaceRoute( IF );
1548
1549 IF->Unicast.Type = IP_ADDRESS_V4;
1550 IF->Unicast.Address.IPv4Address = IpAddrChange->Address;
1551 IF->Netmask.Type = IP_ADDRESS_V4;
1552 IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask;
1553 IF->Broadcast.Address.IPv4Address =
1554 IF->Unicast.Address.IPv4Address |
1555 ~IF->Netmask.Address.IPv4Address;
1556
1557 TI_DbgPrint(MID_TRACE,("New Unicast Address: %x\n",
1558 IF->Unicast.Address.IPv4Address));
1559 TI_DbgPrint(MID_TRACE,("New Netmask : %x\n",
1560 IF->Netmask.Address.IPv4Address));
1561
1562 IPAddInterfaceRoute( IF );
1563
1564 IpAddrChange->Address = IF->Index;
1565 Status = STATUS_SUCCESS;
1566 Irp->IoStatus.Information = IF->Index;
1567 break;
1568 }
1569 } EndFor(IF);
1570
1571 Irp->IoStatus.Status = Status;
1572 return Status;
1573 }
1574
1575 NTSTATUS DispTdiDeleteIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
1576 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1577 PUSHORT NteIndex = Irp->AssociatedIrp.SystemBuffer;
1578 IF_LIST_ITER(IF);
1579
1580 ForEachInterface(IF) {
1581 if( IF->Index == *NteIndex ) {
1582 IPRemoveInterfaceRoute( IF );
1583 IF->Unicast.Type = IP_ADDRESS_V4;
1584 IF->Unicast.Address.IPv4Address = 0;
1585 IF->Netmask.Type = IP_ADDRESS_V4;
1586 IF->Netmask.Address.IPv4Address = 0;
1587 Status = STATUS_SUCCESS;
1588 }
1589 } EndFor(IF);
1590
1591 Irp->IoStatus.Status = Status;
1592 return Status;
1593 }
1594
1595 /* EOF */