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