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