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