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