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