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