- Stop using the TCPLock to protect all entries into the IP lib
[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)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)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 Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)(
989 Request.Handle.AddressHandle,
990 DgramInfo->SendDatagramInformation,
991 DataBuffer,
992 BufferSize,
993 &Irp->IoStatus.Information);
994 else
995 Status = STATUS_UNSUCCESSFUL;
996 }
997
998 done:
999 if (Status != STATUS_PENDING) {
1000 DispDataRequestComplete(Irp, Status, Irp->IoStatus.Information);
1001 } else
1002 IoMarkIrpPending(Irp);
1003
1004 TI_DbgPrint(DEBUG_IRP, ("Leaving.\n"));
1005
1006 return Status;
1007 }
1008
1009
1010 NTSTATUS DispTdiSetEventHandler(PIRP Irp)
1011 /*
1012 * FUNCTION: TDI_SET_EVENT_HANDER handler
1013 * ARGUMENTS:
1014 * Irp = Pointer to a I/O request packet
1015 * RETURNS:
1016 * Status of operation
1017 */
1018 {
1019 PTDI_REQUEST_KERNEL_SET_EVENT Parameters;
1020 PTRANSPORT_CONTEXT TranContext;
1021 PIO_STACK_LOCATION IrpSp;
1022 PADDRESS_FILE AddrFile;
1023 NTSTATUS Status;
1024 KIRQL OldIrql;
1025
1026 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1027
1028 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1029
1030 /* Get associated address file object. Quit if none exists */
1031
1032 TranContext = IrpSp->FileObject->FsContext;
1033 if (!TranContext) {
1034 TI_DbgPrint(MIN_TRACE, ("Bad transport context.\n"));
1035 return STATUS_INVALID_PARAMETER;
1036 }
1037
1038 AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
1039 if (!AddrFile) {
1040 TI_DbgPrint(MIN_TRACE, ("No address file object.\n"));
1041 return STATUS_INVALID_PARAMETER;
1042 }
1043
1044 Parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters;
1045 Status = STATUS_SUCCESS;
1046
1047 TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
1048
1049 /* Set the event handler. if an event handler is associated with
1050 a specific event, it's flag (RegisteredXxxHandler) is TRUE.
1051 If an event handler is not used it's flag is FALSE */
1052 switch (Parameters->EventType) {
1053 case TDI_EVENT_CONNECT:
1054 if (!Parameters->EventHandler) {
1055 AddrFile->ConnectHandlerContext = NULL;
1056 AddrFile->RegisteredConnectHandler = FALSE;
1057 } else {
1058 AddrFile->ConnectHandler =
1059 (PTDI_IND_CONNECT)Parameters->EventHandler;
1060 AddrFile->ConnectHandlerContext = Parameters->EventContext;
1061 AddrFile->RegisteredConnectHandler = TRUE;
1062 }
1063 break;
1064
1065 case TDI_EVENT_DISCONNECT:
1066 if (!Parameters->EventHandler) {
1067 AddrFile->DisconnectHandlerContext = NULL;
1068 AddrFile->RegisteredDisconnectHandler = FALSE;
1069 } else {
1070 AddrFile->DisconnectHandler =
1071 (PTDI_IND_DISCONNECT)Parameters->EventHandler;
1072 AddrFile->DisconnectHandlerContext = Parameters->EventContext;
1073 AddrFile->RegisteredDisconnectHandler = TRUE;
1074 }
1075 break;
1076
1077 case TDI_EVENT_ERROR:
1078 if (Parameters->EventHandler == NULL) {
1079 AddrFile->ErrorHandlerContext = NULL;
1080 AddrFile->RegisteredErrorHandler = FALSE;
1081 } else {
1082 AddrFile->ErrorHandler =
1083 (PTDI_IND_ERROR)Parameters->EventHandler;
1084 AddrFile->ErrorHandlerContext = Parameters->EventContext;
1085 AddrFile->RegisteredErrorHandler = TRUE;
1086 }
1087 break;
1088
1089 case TDI_EVENT_RECEIVE:
1090 if (Parameters->EventHandler == NULL) {
1091 AddrFile->ReceiveHandlerContext = NULL;
1092 AddrFile->RegisteredReceiveHandler = FALSE;
1093 } else {
1094 AddrFile->ReceiveHandler =
1095 (PTDI_IND_RECEIVE)Parameters->EventHandler;
1096 AddrFile->ReceiveHandlerContext = Parameters->EventContext;
1097 AddrFile->RegisteredReceiveHandler = TRUE;
1098 }
1099 break;
1100
1101 case TDI_EVENT_RECEIVE_DATAGRAM:
1102 if (Parameters->EventHandler == NULL) {
1103 AddrFile->ReceiveDatagramHandlerContext = NULL;
1104 AddrFile->RegisteredReceiveDatagramHandler = FALSE;
1105 } else {
1106 AddrFile->ReceiveDatagramHandler =
1107 (PTDI_IND_RECEIVE_DATAGRAM)Parameters->EventHandler;
1108 AddrFile->ReceiveDatagramHandlerContext = Parameters->EventContext;
1109 AddrFile->RegisteredReceiveDatagramHandler = TRUE;
1110 }
1111 break;
1112
1113 case TDI_EVENT_RECEIVE_EXPEDITED:
1114 if (Parameters->EventHandler == NULL) {
1115 AddrFile->ExpeditedReceiveHandlerContext = NULL;
1116 AddrFile->RegisteredExpeditedReceiveHandler = FALSE;
1117 } else {
1118 AddrFile->ExpeditedReceiveHandler =
1119 (PTDI_IND_RECEIVE_EXPEDITED)Parameters->EventHandler;
1120 AddrFile->ExpeditedReceiveHandlerContext = Parameters->EventContext;
1121 AddrFile->RegisteredExpeditedReceiveHandler = TRUE;
1122 }
1123 break;
1124
1125 case TDI_EVENT_CHAINED_RECEIVE:
1126 if (Parameters->EventHandler == NULL) {
1127 AddrFile->ChainedReceiveHandlerContext = NULL;
1128 AddrFile->RegisteredChainedReceiveHandler = FALSE;
1129 } else {
1130 AddrFile->ChainedReceiveHandler =
1131 (PTDI_IND_CHAINED_RECEIVE)Parameters->EventHandler;
1132 AddrFile->ChainedReceiveHandlerContext = Parameters->EventContext;
1133 AddrFile->RegisteredChainedReceiveHandler = TRUE;
1134 }
1135 break;
1136
1137 case TDI_EVENT_CHAINED_RECEIVE_DATAGRAM:
1138 if (Parameters->EventHandler == NULL) {
1139 AddrFile->ChainedReceiveDatagramHandlerContext = NULL;
1140 AddrFile->RegisteredChainedReceiveDatagramHandler = FALSE;
1141 } else {
1142 AddrFile->ChainedReceiveDatagramHandler =
1143 (PTDI_IND_CHAINED_RECEIVE_DATAGRAM)Parameters->EventHandler;
1144 AddrFile->ChainedReceiveDatagramHandlerContext = Parameters->EventContext;
1145 AddrFile->RegisteredChainedReceiveDatagramHandler = TRUE;
1146 }
1147 break;
1148
1149 case TDI_EVENT_CHAINED_RECEIVE_EXPEDITED:
1150 if (Parameters->EventHandler == NULL) {
1151 AddrFile->ChainedReceiveExpeditedHandlerContext = NULL;
1152 AddrFile->RegisteredChainedReceiveExpeditedHandler = FALSE;
1153 } else {
1154 AddrFile->ChainedReceiveExpeditedHandler =
1155 (PTDI_IND_CHAINED_RECEIVE_EXPEDITED)Parameters->EventHandler;
1156 AddrFile->ChainedReceiveExpeditedHandlerContext = Parameters->EventContext;
1157 AddrFile->RegisteredChainedReceiveExpeditedHandler = TRUE;
1158 }
1159 break;
1160
1161 default:
1162 TI_DbgPrint(MIN_TRACE, ("Unknown event type (0x%X).\n",
1163 Parameters->EventType));
1164
1165 Status = STATUS_INVALID_PARAMETER;
1166 }
1167
1168 TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
1169
1170 return Status;
1171 }
1172
1173
1174 NTSTATUS DispTdiSetInformation(
1175 PIRP Irp)
1176 /*
1177 * FUNCTION: TDI_SET_INFORMATION handler
1178 * ARGUMENTS:
1179 * Irp = Pointer to an I/O request packet
1180 * RETURNS:
1181 * Status of operation
1182 */
1183 {
1184 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1185
1186 return STATUS_NOT_IMPLEMENTED;
1187 }
1188
1189
1190 VOID DispTdiQueryInformationExComplete(
1191 PVOID Context,
1192 ULONG Status,
1193 UINT ByteCount)
1194 /*
1195 * FUNCTION: Completes a TDI QueryInformationEx request
1196 * ARGUMENTS:
1197 * Context = Pointer to the IRP for the request
1198 * Status = TDI status of the request
1199 * ByteCount = Number of bytes returned in output buffer
1200 */
1201 {
1202 PTI_QUERY_CONTEXT QueryContext;
1203 UINT Count = 0;
1204
1205 QueryContext = (PTI_QUERY_CONTEXT)Context;
1206 if (NT_SUCCESS(Status)) {
1207 Count = CopyBufferToBufferChain(
1208 QueryContext->InputMdl,
1209 FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context),
1210 (PCHAR)&QueryContext->QueryInfo.Context,
1211 CONTEXT_SIZE);
1212 }
1213
1214 MmUnlockPages(QueryContext->InputMdl);
1215 IoFreeMdl(QueryContext->InputMdl);
1216 if( QueryContext->OutputMdl ) {
1217 MmUnlockPages(QueryContext->OutputMdl);
1218 IoFreeMdl(QueryContext->OutputMdl);
1219 }
1220
1221 QueryContext->Irp->IoStatus.Information = ByteCount;
1222 QueryContext->Irp->IoStatus.Status = Status;
1223
1224 exFreePool(QueryContext);
1225 }
1226
1227
1228 NTSTATUS DispTdiQueryInformationEx(
1229 PIRP Irp,
1230 PIO_STACK_LOCATION IrpSp)
1231 /*
1232 * FUNCTION: TDI QueryInformationEx handler
1233 * ARGUMENTS:
1234 * Irp = Pointer to I/O request packet
1235 * IrpSp = Pointer to current stack location of Irp
1236 * RETURNS:
1237 * Status of operation
1238 */
1239 {
1240 PTCP_REQUEST_QUERY_INFORMATION_EX InputBuffer;
1241 PTRANSPORT_CONTEXT TranContext;
1242 PTI_QUERY_CONTEXT QueryContext;
1243 PVOID OutputBuffer;
1244 TDI_REQUEST Request;
1245 UINT Size;
1246 UINT InputBufferLength;
1247 UINT OutputBufferLength;
1248 BOOLEAN InputMdlLocked = FALSE;
1249 BOOLEAN OutputMdlLocked = FALSE;
1250 PMDL InputMdl = NULL;
1251 PMDL OutputMdl = NULL;
1252 NTSTATUS Status = STATUS_SUCCESS;
1253
1254 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1255
1256 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
1257
1258 switch ((ULONG)IrpSp->FileObject->FsContext2) {
1259 case TDI_TRANSPORT_ADDRESS_FILE:
1260 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
1261 break;
1262
1263 case TDI_CONNECTION_FILE:
1264 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
1265 break;
1266
1267 case TDI_CONTROL_CHANNEL_FILE:
1268 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
1269 break;
1270
1271 default:
1272 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
1273 return STATUS_INVALID_PARAMETER;
1274 }
1275
1276 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
1277 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
1278
1279 /* Validate parameters */
1280 if ((InputBufferLength == sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)) &&
1281 (OutputBufferLength != 0)) {
1282
1283 InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
1284 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
1285 OutputBuffer = Irp->UserBuffer;
1286
1287 QueryContext = exAllocatePool(NonPagedPool, sizeof(TI_QUERY_CONTEXT));
1288 if (QueryContext) {
1289 _SEH2_TRY {
1290 InputMdl = IoAllocateMdl(InputBuffer,
1291 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
1292 FALSE, TRUE, NULL);
1293
1294 OutputMdl = IoAllocateMdl(OutputBuffer,
1295 OutputBufferLength, FALSE, TRUE, NULL);
1296
1297 if (InputMdl && OutputMdl) {
1298
1299 MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
1300 IoModifyAccess);
1301
1302 InputMdlLocked = TRUE;
1303
1304 MmProbeAndLockPages(OutputMdl, Irp->RequestorMode,
1305 IoWriteAccess);
1306
1307 OutputMdlLocked = TRUE;
1308
1309 RtlCopyMemory(&QueryContext->QueryInfo,
1310 InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
1311 } else
1312 Status = STATUS_INSUFFICIENT_RESOURCES;
1313 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
1314 Status = _SEH2_GetExceptionCode();
1315 } _SEH2_END;
1316
1317 if (NT_SUCCESS(Status)) {
1318 Size = MmGetMdlByteCount(OutputMdl);
1319
1320 QueryContext->Irp = Irp;
1321 QueryContext->InputMdl = InputMdl;
1322 QueryContext->OutputMdl = OutputMdl;
1323
1324 Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
1325 Request.RequestContext = QueryContext;
1326 Status = InfoTdiQueryInformationEx(&Request,
1327 &QueryContext->QueryInfo.ID, OutputMdl,
1328 &Size, &QueryContext->QueryInfo.Context);
1329 DispTdiQueryInformationExComplete(QueryContext, Status, Size);
1330
1331 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1332
1333 return Status;
1334 }
1335
1336 /* An error occurred if we get here */
1337
1338 if (InputMdl) {
1339 if (InputMdlLocked)
1340 MmUnlockPages(InputMdl);
1341 IoFreeMdl(InputMdl);
1342 }
1343
1344 if (OutputMdl) {
1345 if (OutputMdlLocked)
1346 MmUnlockPages(OutputMdl);
1347 IoFreeMdl(OutputMdl);
1348 }
1349
1350 exFreePool(QueryContext);
1351 } else
1352 Status = STATUS_INSUFFICIENT_RESOURCES;
1353 } else if( InputBufferLength ==
1354 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX) ) {
1355 /* Handle the case where the user is probing the buffer for length */
1356 TI_DbgPrint(MAX_TRACE, ("InputBufferLength %d OutputBufferLength %d\n",
1357 InputBufferLength, OutputBufferLength));
1358 InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
1359 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
1360
1361 Size = 0;
1362
1363 QueryContext = exAllocatePool(NonPagedPool, sizeof(TI_QUERY_CONTEXT));
1364 if (!QueryContext) return STATUS_INSUFFICIENT_RESOURCES;
1365
1366 _SEH2_TRY {
1367 InputMdl = IoAllocateMdl(InputBuffer,
1368 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
1369 FALSE, TRUE, NULL);
1370
1371 MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
1372 IoModifyAccess);
1373
1374 InputMdlLocked = TRUE;
1375 Status = STATUS_SUCCESS;
1376 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
1377 TI_DbgPrint(MAX_TRACE, ("Failed to acquire client buffer\n"));
1378 Status = _SEH2_GetExceptionCode();
1379 } _SEH2_END;
1380
1381 if( !NT_SUCCESS(Status) || !InputMdl ) {
1382 if( InputMdl ) IoFreeMdl( InputMdl );
1383 exFreePool(QueryContext);
1384 return Status;
1385 }
1386
1387 RtlCopyMemory(&QueryContext->QueryInfo,
1388 InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
1389
1390 QueryContext->Irp = Irp;
1391 QueryContext->InputMdl = InputMdl;
1392 QueryContext->OutputMdl = NULL;
1393
1394 Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
1395 Request.RequestContext = QueryContext;
1396 Status = InfoTdiQueryInformationEx(&Request,
1397 &QueryContext->QueryInfo.ID,
1398 NULL,
1399 &Size,
1400 &QueryContext->QueryInfo.Context);
1401 DispTdiQueryInformationExComplete(QueryContext, Status, Size);
1402 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1403 } else Status = STATUS_INVALID_PARAMETER;
1404
1405 TI_DbgPrint(MIN_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1406
1407 return Status;
1408 }
1409
1410
1411 NTSTATUS DispTdiSetInformationEx(
1412 PIRP Irp,
1413 PIO_STACK_LOCATION IrpSp)
1414 /*
1415 * FUNCTION: TDI SetInformationEx handler
1416 * ARGUMENTS:
1417 * Irp = Pointer to I/O request packet
1418 * IrpSp = Pointer to current stack location of Irp
1419 * RETURNS:
1420 * Status of operation
1421 */
1422 {
1423 PTRANSPORT_CONTEXT TranContext;
1424 PTCP_REQUEST_SET_INFORMATION_EX Info;
1425 TDI_REQUEST Request;
1426 TDI_STATUS Status;
1427
1428 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1429
1430 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
1431 Info = (PTCP_REQUEST_SET_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer;
1432
1433 switch ((ULONG)IrpSp->FileObject->FsContext2) {
1434 case TDI_TRANSPORT_ADDRESS_FILE:
1435 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
1436 break;
1437
1438 case TDI_CONNECTION_FILE:
1439 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
1440 break;
1441
1442 case TDI_CONTROL_CHANNEL_FILE:
1443 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
1444 break;
1445
1446 default:
1447 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1448 Irp->IoStatus.Information = 0;
1449
1450 TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
1451
1452 return Irp->IoStatus.Status;
1453 }
1454
1455 Status = DispPrepareIrpForCancel(TranContext, Irp, NULL);
1456 if (NT_SUCCESS(Status)) {
1457 Request.RequestNotifyObject = DispDataRequestComplete;
1458 Request.RequestContext = Irp;
1459
1460 Status = InfoTdiSetInformationEx(&Request, &Info->ID,
1461 &Info->Buffer, Info->BufferSize);
1462 }
1463
1464 return Status;
1465 }
1466
1467 /* TODO: Support multiple addresses per interface.
1468 * For now just set the nte context to the interface index.
1469 *
1470 * Later on, create an NTE context and NTE instance
1471 */
1472
1473 NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
1474 NTSTATUS Status = STATUS_DEVICE_DOES_NOT_EXIST;
1475 PIP_SET_ADDRESS IpAddrChange =
1476 (PIP_SET_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
1477 IF_LIST_ITER(IF);
1478
1479 TI_DbgPrint(MID_TRACE,("Setting IP Address for adapter %d\n",
1480 IpAddrChange->NteIndex));
1481
1482 ForEachInterface(IF) {
1483 TI_DbgPrint(MID_TRACE,("Looking at adapter %d\n", IF->Index));
1484
1485 if( IF->Unicast.Address.IPv4Address == IpAddrChange->Address ) {
1486 Status = STATUS_DUPLICATE_OBJECTID;
1487 break;
1488 }
1489 if( IF->Index == IpAddrChange->NteIndex ) {
1490 IPRemoveInterfaceRoute( IF );
1491
1492 IF->Unicast.Type = IP_ADDRESS_V4;
1493 IF->Unicast.Address.IPv4Address = IpAddrChange->Address;
1494 IF->Netmask.Type = IP_ADDRESS_V4;
1495 IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask;
1496 IF->Broadcast.Type = IP_ADDRESS_V4;
1497 IF->Broadcast.Address.IPv4Address =
1498 IF->Unicast.Address.IPv4Address |
1499 ~IF->Netmask.Address.IPv4Address;
1500
1501 TI_DbgPrint(MID_TRACE,("New Unicast Address: %x\n",
1502 IF->Unicast.Address.IPv4Address));
1503 TI_DbgPrint(MID_TRACE,("New Netmask : %x\n",
1504 IF->Netmask.Address.IPv4Address));
1505
1506 IPAddInterfaceRoute( IF );
1507
1508 IpAddrChange->Address = IF->Index;
1509 Status = STATUS_SUCCESS;
1510 Irp->IoStatus.Information = IF->Index;
1511 break;
1512 }
1513 } EndFor(IF);
1514
1515 Irp->IoStatus.Status = Status;
1516 return Status;
1517 }
1518
1519 NTSTATUS DispTdiDeleteIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
1520 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1521 PUSHORT NteIndex = Irp->AssociatedIrp.SystemBuffer;
1522 IF_LIST_ITER(IF);
1523
1524 ForEachInterface(IF) {
1525 if( IF->Index == *NteIndex ) {
1526 IPRemoveInterfaceRoute( IF );
1527 IF->Unicast.Type = IP_ADDRESS_V4;
1528 IF->Unicast.Address.IPv4Address = 0;
1529 IF->Netmask.Type = IP_ADDRESS_V4;
1530 IF->Netmask.Address.IPv4Address = 0;
1531 IF->Broadcast.Type = IP_ADDRESS_V4;
1532 IF->Broadcast.Address.IPv4Address = 0;
1533 Status = STATUS_SUCCESS;
1534 }
1535 } EndFor(IF);
1536
1537 Irp->IoStatus.Status = Status;
1538 return Status;
1539 }
1540
1541 /* EOF */