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