Merge trunk head (r41474)
[reactos.git] / reactos / drivers / network / tcpip / tcpip / dispatch.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: tcpip/dispatch.h
5 * PURPOSE: TDI dispatch routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/08-2000 Created
9 * TODO: Validate device object in all dispatch routines
10 */
11
12 #include "precomp.h"
13 #include <pseh/pseh2.h>
14
15 NTSTATUS DispPrepareIrpForCancel(
16 PTRANSPORT_CONTEXT Context,
17 PIRP Irp,
18 PDRIVER_CANCEL CancelRoutine)
19 /*
20 * FUNCTION: Prepare an IRP for cancellation
21 * ARGUMENTS:
22 * Context = Pointer to context information
23 * Irp = Pointer to an I/O request packet
24 * CancelRoutine = Routine to be called when I/O request is cancelled
25 * RETURNS:
26 * Status of operation
27 */
28 {
29 KIRQL OldIrql;
30 PIO_STACK_LOCATION IrpSp;
31 PTRANSPORT_CONTEXT TransContext;
32
33 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
34
35 IrpSp = IoGetCurrentIrpStackLocation(Irp);
36 TransContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
37
38 IoAcquireCancelSpinLock(&OldIrql);
39
40 if (!Irp->Cancel && !TransContext->CancelIrps) {
41 (void)IoSetCancelRoutine(Irp, CancelRoutine);
42 IoReleaseCancelSpinLock(OldIrql);
43
44 TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP at 0x%X can now be cancelled).\n", Irp));
45
46 return STATUS_SUCCESS;
47 }
48
49 /* IRP has already been cancelled */
50
51 IoReleaseCancelSpinLock(OldIrql);
52
53 Irp->IoStatus.Status = STATUS_CANCELLED;
54 Irp->IoStatus.Information = 0;
55
56 TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP was already cancelled).\n"));
57
58 return Irp->IoStatus.Status;
59 }
60
61 VOID DispDataRequestComplete(
62 PVOID Context,
63 NTSTATUS Status,
64 ULONG Count)
65 /*
66 * FUNCTION: Completes a send/receive IRP
67 * ARGUMENTS:
68 * Context = Pointer to context information (IRP)
69 * Status = Status of the request
70 * Count = Number of bytes sent or received
71 */
72 {
73 PIRP Irp;
74 PIO_STACK_LOCATION IrpSp;
75 PTRANSPORT_CONTEXT TranContext;
76 KIRQL OldIrql;
77
78 TI_DbgPrint(DEBUG_IRP, ("Called for irp %x (%x, %d).\n",
79 Context, Status, Count));
80
81 Irp = Context;
82 IrpSp = IoGetCurrentIrpStackLocation(Irp);
83 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
84
85 IoAcquireCancelSpinLock(&OldIrql);
86
87 (void)IoSetCancelRoutine(Irp, NULL);
88
89 if (Irp->Cancel || TranContext->CancelIrps) {
90 /* The IRP has been cancelled */
91
92 TI_DbgPrint(DEBUG_IRP, ("IRP is cancelled.\n"));
93
94 Status = STATUS_CANCELLED;
95 Count = 0;
96 }
97
98 IoReleaseCancelSpinLock(OldIrql);
99
100 Irp->IoStatus.Status = Status;
101 Irp->IoStatus.Information = Count;
102
103 TI_DbgPrint(MID_TRACE, ("Irp->IoStatus.Status = %x\n",
104 Irp->IoStatus.Status));
105 TI_DbgPrint(MID_TRACE, ("Irp->IoStatus.Information = %d\n",
106 Irp->IoStatus.Information));
107 TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
108
109 IRPFinish(Irp, Status);
110
111 TI_DbgPrint(DEBUG_IRP, ("Done Completing IRP\n"));
112 }
113
114 typedef struct _DISCONNECT_TYPE {
115 UINT Type;
116 PVOID Context;
117 PIRP Irp;
118 PFILE_OBJECT FileObject;
119 } DISCONNECT_TYPE, *PDISCONNECT_TYPE;
120
121 VOID DispDoDisconnect( PVOID Data ) {
122 PDISCONNECT_TYPE DisType = (PDISCONNECT_TYPE)Data;
123
124 TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect\n"));
125 TCPDisconnect
126 ( DisType->Context,
127 DisType->Type,
128 NULL,
129 NULL,
130 DispDataRequestComplete,
131 DisType->Irp );
132 TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect done\n"));
133
134 DispDataRequestComplete(DisType->Irp, STATUS_CANCELLED, 0);
135 }
136
137 VOID NTAPI DispCancelRequest(
138 PDEVICE_OBJECT Device,
139 PIRP Irp)
140 /*
141 * FUNCTION: Cancels an IRP
142 * ARGUMENTS:
143 * Device = Pointer to device object
144 * Irp = Pointer to an I/O request packet
145 */
146 {
147 PIO_STACK_LOCATION IrpSp;
148 PTRANSPORT_CONTEXT TranContext;
149 PFILE_OBJECT FileObject;
150 UCHAR MinorFunction;
151 DISCONNECT_TYPE DisType;
152 PVOID WorkItem;
153 /*NTSTATUS Status = STATUS_SUCCESS;*/
154
155 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
156
157 IrpSp = IoGetCurrentIrpStackLocation(Irp);
158 FileObject = IrpSp->FileObject;
159 TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext;
160 MinorFunction = IrpSp->MinorFunction;
161
162 TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X) MinorFunction (0x%X) IrpSp (0x%X).\n", Irp, MinorFunction, IrpSp));
163
164 Irp->IoStatus.Status = STATUS_CANCELLED;
165 Irp->IoStatus.Information = 0;
166
167 #if DBG
168 if (!Irp->Cancel)
169 TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n"));
170 #endif
171
172 /* Try canceling the request */
173 switch(MinorFunction) {
174 case TDI_SEND:
175 case TDI_RECEIVE:
176 DisType.Type = TDI_DISCONNECT_RELEASE |
177 ((MinorFunction == TDI_RECEIVE) ? TDI_DISCONNECT_ABORT : 0);
178 DisType.Context = TranContext->Handle.ConnectionContext;
179 DisType.Irp = Irp;
180 DisType.FileObject = FileObject;
181
182 TCPRemoveIRP( TranContext->Handle.ConnectionContext, Irp );
183
184 IoReleaseCancelSpinLock(Irp->CancelIrql);
185
186 if( !ChewCreate( &WorkItem, sizeof(DISCONNECT_TYPE),
187 DispDoDisconnect, &DisType ) )
188 ASSERT(0);
189 return;
190
191 case TDI_SEND_DATAGRAM:
192 if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
193 TI_DbgPrint(MIN_TRACE, ("TDI_SEND_DATAGRAM, but no address file.\n"));
194 break;
195 }
196
197 DGRemoveIRP(TranContext->Handle.AddressHandle, Irp);
198 break;
199
200 case TDI_RECEIVE_DATAGRAM:
201 if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
202 TI_DbgPrint(MIN_TRACE, ("TDI_RECEIVE_DATAGRAM, but no address file.\n"));
203 break;
204 }
205
206 DGRemoveIRP(TranContext->Handle.AddressHandle, Irp);
207 break;
208
209 default:
210 TI_DbgPrint(MIN_TRACE, ("Unknown IRP. MinorFunction (0x%X).\n", MinorFunction));
211 break;
212 }
213
214 IoReleaseCancelSpinLock(Irp->CancelIrql);
215 IRPFinish(Irp, STATUS_CANCELLED);
216
217 TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
218 }
219
220
221 VOID NTAPI DispCancelListenRequest(
222 PDEVICE_OBJECT Device,
223 PIRP Irp)
224 /*
225 * FUNCTION: Cancels a listen IRP
226 * ARGUMENTS:
227 * Device = Pointer to device object
228 * Irp = Pointer to an I/O request packet
229 */
230 {
231 PIO_STACK_LOCATION IrpSp;
232 PTRANSPORT_CONTEXT TranContext;
233 PFILE_OBJECT FileObject;
234 PCONNECTION_ENDPOINT Connection;
235 /*NTSTATUS Status = STATUS_SUCCESS;*/
236
237 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
238
239 IrpSp = IoGetCurrentIrpStackLocation(Irp);
240 FileObject = IrpSp->FileObject;
241 TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext;
242 ASSERT( TDI_LISTEN == IrpSp->MinorFunction);
243
244 TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X).\n", Irp));
245
246 #if DBG
247 if (!Irp->Cancel)
248 TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n"));
249 #endif
250
251 /* Try canceling the request */
252 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
253 TCPAbortListenForSocket(
254 Connection->AddressFile->Listener,
255 Connection );
256
257 IoReleaseCancelSpinLock(Irp->CancelIrql);
258
259 Irp->IoStatus.Information = 0;
260 IRPFinish(Irp, STATUS_CANCELLED);
261
262 TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
263 }
264
265
266 NTSTATUS DispTdiAccept(
267 PIRP Irp)
268 /*
269 * FUNCTION: TDI_ACCEPT handler
270 * ARGUMENTS:
271 * Irp = Pointer to an I/O request packet
272 * RETURNS:
273 * Status of operation
274 */
275 {
276 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
277
278 return STATUS_NOT_IMPLEMENTED;
279 }
280
281
282 NTSTATUS DispTdiAssociateAddress(
283 PIRP Irp)
284 /*
285 * FUNCTION: TDI_ASSOCIATE_ADDRESS handler
286 * ARGUMENTS:
287 * Irp = Pointer to an I/O request packet
288 * RETURNS:
289 * Status of operation
290 */
291 {
292 PTDI_REQUEST_KERNEL_ASSOCIATE Parameters;
293 PTRANSPORT_CONTEXT TranContext;
294 PIO_STACK_LOCATION IrpSp;
295 PCONNECTION_ENDPOINT Connection;
296 PFILE_OBJECT FileObject;
297 PADDRESS_FILE AddrFile = NULL;
298 NTSTATUS Status;
299
300 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
301
302 IrpSp = IoGetCurrentIrpStackLocation(Irp);
303
304 /* Get associated connection endpoint file object. Quit if none exists */
305
306 TranContext = IrpSp->FileObject->FsContext;
307 if (!TranContext) {
308 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
309 return STATUS_INVALID_PARAMETER;
310 }
311
312 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
313 if (!Connection) {
314 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
315 return STATUS_INVALID_PARAMETER;
316 }
317
318 if (Connection->AddressFile) {
319 TI_DbgPrint(MID_TRACE, ("An address file is already asscociated.\n"));
320 return STATUS_INVALID_PARAMETER;
321 }
322
323 Parameters = (PTDI_REQUEST_KERNEL_ASSOCIATE)&IrpSp->Parameters;
324
325 Status = ObReferenceObjectByHandle(
326 Parameters->AddressHandle,
327 0,
328 IoFileObjectType,
329 KernelMode,
330 (PVOID*)&FileObject,
331 NULL);
332 if (!NT_SUCCESS(Status)) {
333 TI_DbgPrint(MID_TRACE, ("Bad address file object handle (0x%X): %x.\n",
334 Parameters->AddressHandle, Status));
335 return STATUS_INVALID_PARAMETER;
336 }
337
338 if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
339 ObDereferenceObject(FileObject);
340 TI_DbgPrint(MID_TRACE, ("Bad address file object. Magic (0x%X).\n",
341 FileObject->FsContext2));
342 return STATUS_INVALID_PARAMETER;
343 }
344
345 /* Get associated address file object. Quit if none exists */
346
347 TranContext = FileObject->FsContext;
348 if (!TranContext) {
349 ObDereferenceObject(FileObject);
350 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
351 return STATUS_INVALID_PARAMETER;
352 }
353
354 AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
355 if (!AddrFile) {
356 ObDereferenceObject(FileObject);
357 TI_DbgPrint(MID_TRACE, ("No address file object.\n"));
358 return STATUS_INVALID_PARAMETER;
359 }
360
361 Connection->AddressFile = AddrFile;
362
363 /* Add connection endpoint to the address file */
364 AddrFile->Connection = Connection;
365
366 /* FIXME: Maybe do this in DispTdiDisassociateAddress() instead? */
367 ObDereferenceObject(FileObject);
368
369 return Status;
370 }
371
372
373 NTSTATUS DispTdiConnect(
374 PIRP Irp)
375 /*
376 * FUNCTION: TDI_CONNECT handler
377 * ARGUMENTS:
378 * Irp = Pointer to an I/O request packet
379 * RETURNS:
380 * Status of operation
381 */
382 {
383 PCONNECTION_ENDPOINT Connection;
384 PTDI_REQUEST_KERNEL Parameters;
385 PTRANSPORT_CONTEXT TranContext;
386 PIO_STACK_LOCATION IrpSp;
387 NTSTATUS Status;
388
389 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
390
391 IrpSp = IoGetCurrentIrpStackLocation(Irp);
392
393 /* Get associated connection endpoint file object. Quit if none exists */
394
395 TcpipRecursiveMutexEnter( &TCPLock, TRUE );
396
397 TranContext = IrpSp->FileObject->FsContext;
398 if (!TranContext) {
399 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
400 Status = STATUS_INVALID_PARAMETER;
401 goto done;
402 }
403
404 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
405 if (!Connection) {
406 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
407 Status = STATUS_INVALID_PARAMETER;
408 goto done;
409 }
410
411 Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
412
413 Status = TCPConnect(
414 TranContext->Handle.ConnectionContext,
415 Parameters->RequestConnectionInformation,
416 Parameters->ReturnConnectionInformation,
417 DispDataRequestComplete,
418 Irp );
419
420 done:
421 if (Status != STATUS_PENDING) {
422 DispDataRequestComplete(Irp, Status, 0);
423 } else
424 IoMarkIrpPending(Irp);
425
426 TcpipRecursiveMutexLeave( &TCPLock );
427
428 TI_DbgPrint(MAX_TRACE, ("TCP Connect returned %08x\n", Status));
429
430 return Status;
431 }
432
433
434 NTSTATUS DispTdiDisassociateAddress(
435 PIRP Irp)
436 /*
437 * FUNCTION: TDI_DISASSOCIATE_ADDRESS handler
438 * ARGUMENTS:
439 * Irp = Pointer to an I/O request packet
440 * RETURNS:
441 * Status of operation
442 */
443 {
444 PCONNECTION_ENDPOINT Connection;
445 PTRANSPORT_CONTEXT TranContext;
446 PIO_STACK_LOCATION IrpSp;
447
448 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
449
450 IrpSp = IoGetCurrentIrpStackLocation(Irp);
451
452 /* Get associated connection endpoint file object. Quit if none exists */
453
454 TranContext = IrpSp->FileObject->FsContext;
455 if (!TranContext) {
456 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
457 return STATUS_INVALID_PARAMETER;
458 }
459
460 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
461 if (!Connection) {
462 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
463 return STATUS_INVALID_PARAMETER;
464 }
465
466 if (!Connection->AddressFile) {
467 TI_DbgPrint(MID_TRACE, ("No address file is asscociated.\n"));
468 return STATUS_INVALID_PARAMETER;
469 }
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 TcpipRecursiveMutexEnter( &TCPLock, TRUE );
497
498 /* Get associated connection endpoint file object. Quit if none exists */
499
500 TranContext = IrpSp->FileObject->FsContext;
501 if (!TranContext) {
502 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
503 Status = STATUS_INVALID_PARAMETER;
504 goto done;
505 }
506
507 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
508 if (!Connection) {
509 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
510 Status = STATUS_INVALID_PARAMETER;
511 goto done;
512 }
513
514 Status = TCPDisconnect(
515 TranContext->Handle.ConnectionContext,
516 DisReq->RequestFlags,
517 DisReq->RequestConnectionInformation,
518 DisReq->ReturnConnectionInformation,
519 DispDataRequestComplete,
520 Irp );
521
522 done:
523 if (Status != STATUS_PENDING) {
524 DispDataRequestComplete(Irp, Status, 0);
525 } else
526 IoMarkIrpPending(Irp);
527
528 TcpipRecursiveMutexLeave( &TCPLock );
529
530 TI_DbgPrint(MAX_TRACE, ("TCP Disconnect returned %08x\n", Status));
531
532 return Status;
533 }
534
535
536 NTSTATUS DispTdiListen(
537 PIRP Irp)
538 /*
539 * FUNCTION: TDI_LISTEN handler
540 * ARGUMENTS:
541 * Irp = Pointer to an I/O request packet
542 * RETURNS:
543 * Status of operation
544 */
545 {
546 PCONNECTION_ENDPOINT Connection;
547 PTDI_REQUEST_KERNEL Parameters;
548 PTRANSPORT_CONTEXT TranContext;
549 PIO_STACK_LOCATION IrpSp;
550 NTSTATUS Status = STATUS_SUCCESS;
551
552 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
553
554 IrpSp = IoGetCurrentIrpStackLocation(Irp);
555
556 /* Get associated connection endpoint file object. Quit if none exists */
557
558 TcpipRecursiveMutexEnter( &TCPLock, TRUE );
559
560 TranContext = IrpSp->FileObject->FsContext;
561 if (TranContext == NULL)
562 {
563 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
564 Status = STATUS_INVALID_PARAMETER;
565 goto done;
566 }
567
568 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
569 if (Connection == NULL)
570 {
571 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
572 Status = STATUS_INVALID_PARAMETER;
573 goto done;
574 }
575
576 Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
577
578 TI_DbgPrint(MIN_TRACE, ("Connection->AddressFile: %x\n",
579 Connection->AddressFile ));
580 if( Connection->AddressFile ) {
581 TI_DbgPrint(MIN_TRACE, ("Connection->AddressFile->Listener: %x\n",
582 Connection->AddressFile->Listener));
583 }
584
585 /* Listening will require us to create a listening socket and store it in
586 * the address file. It will be signalled, and attempt to complete an irp
587 * when a new connection arrives. */
588 /* The important thing to note here is that the irp we'll complete belongs
589 * to the socket to be accepted onto, not the listener */
590 if( !Connection->AddressFile->Listener ) {
591 Connection->AddressFile->Listener =
592 TCPAllocateConnectionEndpoint( NULL );
593
594 if( !Connection->AddressFile->Listener )
595 Status = STATUS_NO_MEMORY;
596
597 if( NT_SUCCESS(Status) ) {
598 Connection->AddressFile->Listener->AddressFile =
599 Connection->AddressFile;
600
601 Status = TCPSocket( Connection->AddressFile->Listener,
602 Connection->AddressFile->Family,
603 SOCK_STREAM,
604 Connection->AddressFile->Protocol );
605 }
606
607 if( NT_SUCCESS(Status) )
608 Status = TCPListen( Connection->AddressFile->Listener, 1024 );
609 /* BACKLOG */
610 }
611 if( NT_SUCCESS(Status) ) {
612 Status = DispPrepareIrpForCancel
613 (TranContext->Handle.ConnectionContext,
614 Irp,
615 (PDRIVER_CANCEL)DispCancelListenRequest);
616 }
617
618 if( NT_SUCCESS(Status) ) {
619 Status = TCPAccept
620 ( (PTDI_REQUEST)Parameters,
621 Connection->AddressFile->Listener,
622 Connection,
623 DispDataRequestComplete,
624 Irp );
625 }
626
627 done:
628 if (Status != STATUS_PENDING) {
629 DispDataRequestComplete(Irp, Status, 0);
630 } else
631 IoMarkIrpPending(Irp);
632
633 TcpipRecursiveMutexLeave( &TCPLock );
634
635 TI_DbgPrint(MID_TRACE,("Leaving %x\n", Status));
636
637 return Status;
638 }
639
640
641 NTSTATUS DispTdiQueryInformation(
642 PDEVICE_OBJECT DeviceObject,
643 PIRP Irp)
644 /*
645 * FUNCTION: TDI_QUERY_INFORMATION handler
646 * ARGUMENTS:
647 * DeviceObject = Pointer to device object structure
648 * Irp = Pointer to an I/O request packet
649 * RETURNS:
650 * Status of operation
651 */
652 {
653 PTDI_REQUEST_KERNEL_QUERY_INFORMATION Parameters;
654 PTRANSPORT_CONTEXT TranContext;
655 PIO_STACK_LOCATION IrpSp;
656
657 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
658
659 IrpSp = IoGetCurrentIrpStackLocation(Irp);
660 Parameters = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&IrpSp->Parameters;
661
662 TranContext = IrpSp->FileObject->FsContext;
663 if (!TranContext) {
664 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
665 return STATUS_INVALID_PARAMETER;
666 }
667
668 switch (Parameters->QueryType)
669 {
670 case TDI_QUERY_ADDRESS_INFO:
671 {
672 PTDI_ADDRESS_INFO AddressInfo;
673 PADDRESS_FILE AddrFile;
674 PTA_IP_ADDRESS Address;
675 PCONNECTION_ENDPOINT Endpoint = NULL;
676
677
678 if (MmGetMdlByteCount(Irp->MdlAddress) <
679 (FIELD_OFFSET(TDI_ADDRESS_INFO, Address.Address[0].Address) +
680 sizeof(TDI_ADDRESS_IP))) {
681 TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n"));
682 return STATUS_BUFFER_TOO_SMALL;
683 }
684
685 AddressInfo = (PTDI_ADDRESS_INFO)MmGetSystemAddressForMdl(Irp->MdlAddress);
686 Address = (PTA_IP_ADDRESS)&AddressInfo->Address;
687
688 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
689 case TDI_TRANSPORT_ADDRESS_FILE:
690 AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
691
692 Address->TAAddressCount = 1;
693 Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
694 Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
695 Address->Address[0].Address[0].sin_port = AddrFile->Port;
696 Address->Address[0].Address[0].in_addr = AddrFile->Address.Address.IPv4Address;
697 RtlZeroMemory(
698 &Address->Address[0].Address[0].sin_zero,
699 sizeof(Address->Address[0].Address[0].sin_zero));
700 return STATUS_SUCCESS;
701
702 case TDI_CONNECTION_FILE:
703 Endpoint =
704 (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
705 TCPGetSockAddress( Endpoint, (PTRANSPORT_ADDRESS)Address, FALSE );
706 DbgPrint("Returning socket address %x\n", Address->Address[0].Address[0].in_addr);
707 RtlZeroMemory(
708 &Address->Address[0].Address[0].sin_zero,
709 sizeof(Address->Address[0].Address[0].sin_zero));
710 return STATUS_SUCCESS;
711
712 default:
713 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
714 return STATUS_INVALID_PARAMETER;
715 }
716
717 if (!AddrFile) {
718 TI_DbgPrint(MID_TRACE, ("No address file object.\n"));
719 return STATUS_INVALID_PARAMETER;
720 }
721
722 return STATUS_SUCCESS;
723 }
724
725 case TDI_QUERY_CONNECTION_INFO:
726 {
727 PTDI_CONNECTION_INFORMATION AddressInfo;
728 PADDRESS_FILE AddrFile;
729 PCONNECTION_ENDPOINT Endpoint = NULL;
730
731 if (MmGetMdlByteCount(Irp->MdlAddress) <
732 (FIELD_OFFSET(TDI_CONNECTION_INFORMATION, RemoteAddress) +
733 sizeof(PVOID))) {
734 TI_DbgPrint(MID_TRACE, ("MDL buffer too small (ptr).\n"));
735 return STATUS_BUFFER_TOO_SMALL;
736 }
737
738 AddressInfo = (PTDI_CONNECTION_INFORMATION)
739 MmGetSystemAddressForMdl(Irp->MdlAddress);
740
741 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
742 case TDI_TRANSPORT_ADDRESS_FILE:
743 AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
744 break;
745
746 case TDI_CONNECTION_FILE:
747 Endpoint =
748 (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
749 break;
750
751 default:
752 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
753 return STATUS_INVALID_PARAMETER;
754 }
755
756 if (!Endpoint) {
757 TI_DbgPrint(MID_TRACE, ("No connection object.\n"));
758 return STATUS_INVALID_PARAMETER;
759 }
760
761 return TCPGetSockAddress( Endpoint, AddressInfo->RemoteAddress, TRUE );
762 }
763 }
764
765 return STATUS_NOT_IMPLEMENTED;
766 }
767
768
769 NTSTATUS DispTdiReceive(
770 PIRP Irp)
771 /*
772 * FUNCTION: TDI_RECEIVE handler
773 * ARGUMENTS:
774 * Irp = Pointer to an I/O request packet
775 * RETURNS:
776 * Status of operation
777 */
778 {
779 PIO_STACK_LOCATION IrpSp;
780 PTDI_REQUEST_KERNEL_RECEIVE ReceiveInfo;
781 PTRANSPORT_CONTEXT TranContext;
782 NTSTATUS Status;
783 ULONG BytesReceived = 0;
784
785 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
786
787 IrpSp = IoGetCurrentIrpStackLocation(Irp);
788 ReceiveInfo = (PTDI_REQUEST_KERNEL_RECEIVE)&(IrpSp->Parameters);
789
790 TcpipRecursiveMutexEnter( &TCPLock, TRUE );
791
792 TranContext = IrpSp->FileObject->FsContext;
793 if (TranContext == NULL)
794 {
795 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
796 Status = STATUS_INVALID_PARAMETER;
797 goto done;
798 }
799
800 if (TranContext->Handle.ConnectionContext == NULL)
801 {
802 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
803 Status = STATUS_INVALID_PARAMETER;
804 goto done;
805 }
806
807 /* Initialize a receive request */
808 Status = DispPrepareIrpForCancel
809 (TranContext->Handle.ConnectionContext,
810 Irp,
811 (PDRIVER_CANCEL)DispCancelRequest);
812
813 TI_DbgPrint(MID_TRACE,("TCPIP<<< Got an MDL: %x\n", Irp->MdlAddress));
814 if (NT_SUCCESS(Status))
815 {
816 Status = TCPReceiveData(
817 TranContext->Handle.ConnectionContext,
818 (PNDIS_BUFFER)Irp->MdlAddress,
819 ReceiveInfo->ReceiveLength,
820 &BytesReceived,
821 ReceiveInfo->ReceiveFlags,
822 DispDataRequestComplete,
823 Irp);
824 }
825
826 done:
827 if (Status != STATUS_PENDING) {
828 DispDataRequestComplete(Irp, Status, BytesReceived);
829 } else
830 IoMarkIrpPending(Irp);
831
832 TcpipRecursiveMutexLeave( &TCPLock );
833
834 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
835
836 return Status;
837 }
838
839
840 NTSTATUS DispTdiReceiveDatagram(
841 PIRP Irp)
842 /*
843 * FUNCTION: TDI_RECEIVE_DATAGRAM handler
844 * ARGUMENTS:
845 * Irp = Pointer to an I/O request packet
846 * RETURNS:
847 * Status of operation
848 */
849 {
850 PIO_STACK_LOCATION IrpSp;
851 PTDI_REQUEST_KERNEL_RECEIVEDG DgramInfo;
852 PTRANSPORT_CONTEXT TranContext;
853 TDI_REQUEST Request;
854 NTSTATUS Status;
855 ULONG BytesReceived = 0;
856
857 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
858
859 IrpSp = IoGetCurrentIrpStackLocation(Irp);
860 DgramInfo = (PTDI_REQUEST_KERNEL_RECEIVEDG)&(IrpSp->Parameters);
861
862 TcpipRecursiveMutexEnter( &TCPLock, TRUE );
863
864 TranContext = IrpSp->FileObject->FsContext;
865 if (TranContext == NULL)
866 {
867 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
868 Status = STATUS_INVALID_PARAMETER;
869 goto done;
870 }
871
872 /* Initialize a receive request */
873 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
874 Request.RequestNotifyObject = DispDataRequestComplete;
875 Request.RequestContext = Irp;
876
877 Status = DispPrepareIrpForCancel(
878 IrpSp->FileObject->FsContext,
879 Irp,
880 (PDRIVER_CANCEL)DispCancelRequest);
881
882 if (NT_SUCCESS(Status))
883 {
884 PVOID DataBuffer;
885 UINT BufferSize;
886
887 NdisQueryBuffer( (PNDIS_BUFFER)Irp->MdlAddress,
888 &DataBuffer,
889 &BufferSize );
890
891 Status = DGReceiveDatagram(
892 Request.Handle.AddressHandle,
893 DgramInfo->ReceiveDatagramInformation,
894 DataBuffer,
895 DgramInfo->ReceiveLength,
896 DgramInfo->ReceiveFlags,
897 DgramInfo->ReturnDatagramInformation,
898 &BytesReceived,
899 (PDATAGRAM_COMPLETION_ROUTINE)DispDataRequestComplete,
900 Irp,
901 Irp);
902 }
903
904 done:
905 if (Status != STATUS_PENDING) {
906 DispDataRequestComplete(Irp, Status, BytesReceived);
907 } else
908 IoMarkIrpPending(Irp);
909
910 TcpipRecursiveMutexLeave( &TCPLock );
911
912 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
913
914 return Status;
915 }
916
917
918 NTSTATUS DispTdiSend(
919 PIRP Irp)
920 /*
921 * FUNCTION: TDI_SEND handler
922 * ARGUMENTS:
923 * Irp = Pointer to an I/O request packet
924 * RETURNS:
925 * Status of operation
926 */
927 {
928 PIO_STACK_LOCATION IrpSp;
929 PTDI_REQUEST_KERNEL_SEND SendInfo;
930 PTRANSPORT_CONTEXT TranContext;
931 NTSTATUS Status;
932 ULONG BytesSent = 0;
933
934 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
935
936 IrpSp = IoGetCurrentIrpStackLocation(Irp);
937 SendInfo = (PTDI_REQUEST_KERNEL_SEND)&(IrpSp->Parameters);
938
939 TcpipRecursiveMutexEnter( &TCPLock, TRUE );
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 TcpipRecursiveMutexLeave( &TCPLock );
987
988 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
989
990 return Status;
991 }
992
993
994 NTSTATUS DispTdiSendDatagram(
995 PIRP Irp)
996 /*
997 * FUNCTION: TDI_SEND_DATAGRAM handler
998 * ARGUMENTS:
999 * Irp = Pointer to an I/O request packet
1000 * RETURNS:
1001 * Status of operation
1002 */
1003 {
1004 PIO_STACK_LOCATION IrpSp;
1005 TDI_REQUEST Request;
1006 PTDI_REQUEST_KERNEL_SENDDG DgramInfo;
1007 PTRANSPORT_CONTEXT TranContext;
1008 NTSTATUS Status;
1009
1010 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1011
1012 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1013 DgramInfo = (PTDI_REQUEST_KERNEL_SENDDG)&(IrpSp->Parameters);
1014
1015 TcpipRecursiveMutexEnter( &TCPLock, TRUE );
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) )
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 }
1065
1066 done:
1067 if (Status != STATUS_PENDING) {
1068 DispDataRequestComplete(Irp, Status, Irp->IoStatus.Information);
1069 } else
1070 IoMarkIrpPending(Irp);
1071
1072 TcpipRecursiveMutexLeave( &TCPLock );
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 TcpipAcquireSpinLock(&AddrFile->Lock, &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 TcpipReleaseSpinLock(&AddrFile->Lock, 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 UINT Count = 0;
1274
1275 QueryContext = (PTI_QUERY_CONTEXT)Context;
1276 if (NT_SUCCESS(Status)) {
1277 Count = CopyBufferToBufferChain(
1278 QueryContext->InputMdl,
1279 FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context),
1280 (PCHAR)&QueryContext->QueryInfo.Context,
1281 CONTEXT_SIZE);
1282 }
1283
1284 MmUnlockPages(QueryContext->InputMdl);
1285 IoFreeMdl(QueryContext->InputMdl);
1286 if( QueryContext->OutputMdl ) {
1287 MmUnlockPages(QueryContext->OutputMdl);
1288 IoFreeMdl(QueryContext->OutputMdl);
1289 }
1290
1291 QueryContext->Irp->IoStatus.Information = ByteCount;
1292 QueryContext->Irp->IoStatus.Status = Status;
1293
1294 exFreePool(QueryContext);
1295 }
1296
1297
1298 NTSTATUS DispTdiQueryInformationEx(
1299 PIRP Irp,
1300 PIO_STACK_LOCATION IrpSp)
1301 /*
1302 * FUNCTION: TDI QueryInformationEx handler
1303 * ARGUMENTS:
1304 * Irp = Pointer to I/O request packet
1305 * IrpSp = Pointer to current stack location of Irp
1306 * RETURNS:
1307 * Status of operation
1308 */
1309 {
1310 PTCP_REQUEST_QUERY_INFORMATION_EX InputBuffer;
1311 PTRANSPORT_CONTEXT TranContext;
1312 PTI_QUERY_CONTEXT QueryContext;
1313 PVOID OutputBuffer;
1314 TDI_REQUEST Request;
1315 UINT Size;
1316 UINT InputBufferLength;
1317 UINT OutputBufferLength;
1318 BOOLEAN InputMdlLocked = FALSE;
1319 BOOLEAN OutputMdlLocked = FALSE;
1320 PMDL InputMdl = NULL;
1321 PMDL OutputMdl = NULL;
1322 NTSTATUS Status = STATUS_SUCCESS;
1323
1324 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1325
1326 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
1327
1328 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
1329 case TDI_TRANSPORT_ADDRESS_FILE:
1330 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
1331 break;
1332
1333 case TDI_CONNECTION_FILE:
1334 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
1335 break;
1336
1337 case TDI_CONTROL_CHANNEL_FILE:
1338 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
1339 break;
1340
1341 default:
1342 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
1343 return STATUS_INVALID_PARAMETER;
1344 }
1345
1346 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
1347 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
1348
1349 /* Validate parameters */
1350 if ((InputBufferLength == sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)) &&
1351 (OutputBufferLength != 0)) {
1352
1353 InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
1354 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
1355 OutputBuffer = Irp->UserBuffer;
1356
1357 QueryContext = exAllocatePool(NonPagedPool, sizeof(TI_QUERY_CONTEXT));
1358 if (QueryContext) {
1359 _SEH2_TRY {
1360 InputMdl = IoAllocateMdl(InputBuffer,
1361 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
1362 FALSE, TRUE, NULL);
1363
1364 OutputMdl = IoAllocateMdl(OutputBuffer,
1365 OutputBufferLength, FALSE, TRUE, NULL);
1366
1367 if (InputMdl && OutputMdl) {
1368
1369 MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
1370 IoModifyAccess);
1371
1372 InputMdlLocked = TRUE;
1373
1374 MmProbeAndLockPages(OutputMdl, Irp->RequestorMode,
1375 IoWriteAccess);
1376
1377 OutputMdlLocked = TRUE;
1378
1379 RtlCopyMemory(&QueryContext->QueryInfo,
1380 InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
1381 } else
1382 Status = STATUS_INSUFFICIENT_RESOURCES;
1383 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
1384 Status = _SEH2_GetExceptionCode();
1385 } _SEH2_END;
1386
1387 if (NT_SUCCESS(Status)) {
1388 Size = MmGetMdlByteCount(OutputMdl);
1389
1390 QueryContext->Irp = Irp;
1391 QueryContext->InputMdl = InputMdl;
1392 QueryContext->OutputMdl = OutputMdl;
1393
1394 Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
1395 Request.RequestContext = QueryContext;
1396 Status = InfoTdiQueryInformationEx(&Request,
1397 &QueryContext->QueryInfo.ID, OutputMdl,
1398 &Size, &QueryContext->QueryInfo.Context);
1399 DispTdiQueryInformationExComplete(QueryContext, Status, Size);
1400
1401 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1402
1403 return Status;
1404 }
1405
1406 /* An error occurred if we get here */
1407
1408 if (InputMdl) {
1409 if (InputMdlLocked)
1410 MmUnlockPages(InputMdl);
1411 IoFreeMdl(InputMdl);
1412 }
1413
1414 if (OutputMdl) {
1415 if (OutputMdlLocked)
1416 MmUnlockPages(OutputMdl);
1417 IoFreeMdl(OutputMdl);
1418 }
1419
1420 exFreePool(QueryContext);
1421 } else
1422 Status = STATUS_INSUFFICIENT_RESOURCES;
1423 } else if( InputBufferLength ==
1424 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX) ) {
1425 /* Handle the case where the user is probing the buffer for length */
1426 TI_DbgPrint(MAX_TRACE, ("InputBufferLength %d OutputBufferLength %d\n",
1427 InputBufferLength, OutputBufferLength));
1428 InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
1429 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
1430
1431 Size = 0;
1432
1433 QueryContext = exAllocatePool(NonPagedPool, sizeof(TI_QUERY_CONTEXT));
1434 if (!QueryContext) return STATUS_INSUFFICIENT_RESOURCES;
1435
1436 _SEH2_TRY {
1437 InputMdl = IoAllocateMdl(InputBuffer,
1438 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
1439 FALSE, TRUE, NULL);
1440
1441 MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
1442 IoModifyAccess);
1443
1444 InputMdlLocked = TRUE;
1445 Status = STATUS_SUCCESS;
1446 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
1447 TI_DbgPrint(MAX_TRACE, ("Failed to acquire client buffer\n"));
1448 Status = _SEH2_GetExceptionCode();
1449 } _SEH2_END;
1450
1451 if( !NT_SUCCESS(Status) || !InputMdl ) {
1452 if( InputMdl ) IoFreeMdl( InputMdl );
1453 exFreePool(QueryContext);
1454 return Status;
1455 }
1456
1457 RtlCopyMemory(&QueryContext->QueryInfo,
1458 InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
1459
1460 QueryContext->Irp = Irp;
1461 QueryContext->InputMdl = InputMdl;
1462 QueryContext->OutputMdl = NULL;
1463
1464 Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
1465 Request.RequestContext = QueryContext;
1466 Status = InfoTdiQueryInformationEx(&Request,
1467 &QueryContext->QueryInfo.ID,
1468 NULL,
1469 &Size,
1470 &QueryContext->QueryInfo.Context);
1471 DispTdiQueryInformationExComplete(QueryContext, Status, Size);
1472 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1473 } else Status = STATUS_INVALID_PARAMETER;
1474
1475 TI_DbgPrint(MIN_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1476
1477 return Status;
1478 }
1479
1480
1481 NTSTATUS DispTdiSetInformationEx(
1482 PIRP Irp,
1483 PIO_STACK_LOCATION IrpSp)
1484 /*
1485 * FUNCTION: TDI SetInformationEx handler
1486 * ARGUMENTS:
1487 * Irp = Pointer to I/O request packet
1488 * IrpSp = Pointer to current stack location of Irp
1489 * RETURNS:
1490 * Status of operation
1491 */
1492 {
1493 PTRANSPORT_CONTEXT TranContext;
1494 PTCP_REQUEST_SET_INFORMATION_EX Info;
1495 TDI_REQUEST Request;
1496 TDI_STATUS Status;
1497
1498 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1499
1500 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
1501 Info = (PTCP_REQUEST_SET_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer;
1502
1503 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
1504 case TDI_TRANSPORT_ADDRESS_FILE:
1505 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
1506 break;
1507
1508 case TDI_CONNECTION_FILE:
1509 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
1510 break;
1511
1512 case TDI_CONTROL_CHANNEL_FILE:
1513 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
1514 break;
1515
1516 default:
1517 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1518 Irp->IoStatus.Information = 0;
1519
1520 TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
1521
1522 return Irp->IoStatus.Status;
1523 }
1524
1525 Status = DispPrepareIrpForCancel(TranContext, Irp, NULL);
1526 if (NT_SUCCESS(Status)) {
1527 Request.RequestNotifyObject = DispDataRequestComplete;
1528 Request.RequestContext = Irp;
1529
1530 Status = InfoTdiSetInformationEx(&Request, &Info->ID,
1531 &Info->Buffer, Info->BufferSize);
1532 }
1533
1534 return Status;
1535 }
1536
1537 /* TODO: Support multiple addresses per interface.
1538 * For now just set the nte context to the interface index.
1539 *
1540 * Later on, create an NTE context and NTE instance
1541 */
1542
1543 NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
1544 NTSTATUS Status = STATUS_DEVICE_DOES_NOT_EXIST;
1545 PIP_SET_ADDRESS IpAddrChange =
1546 (PIP_SET_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
1547 IF_LIST_ITER(IF);
1548
1549 TI_DbgPrint(MID_TRACE,("Setting IP Address for adapter %d\n",
1550 IpAddrChange->NteIndex));
1551
1552 ForEachInterface(IF) {
1553 TI_DbgPrint(MID_TRACE,("Looking at adapter %d\n", IF->Index));
1554
1555 if( IF->Unicast.Address.IPv4Address == IpAddrChange->Address ) {
1556 Status = STATUS_DUPLICATE_OBJECTID;
1557 break;
1558 }
1559 if( IF->Index == IpAddrChange->NteIndex ) {
1560 IPRemoveInterfaceRoute( IF );
1561
1562 IF->Unicast.Type = IP_ADDRESS_V4;
1563 IF->Unicast.Address.IPv4Address = IpAddrChange->Address;
1564 IF->Netmask.Type = IP_ADDRESS_V4;
1565 IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask;
1566 IF->Broadcast.Type = IP_ADDRESS_V4;
1567 IF->Broadcast.Address.IPv4Address =
1568 IF->Unicast.Address.IPv4Address |
1569 ~IF->Netmask.Address.IPv4Address;
1570
1571 TI_DbgPrint(MID_TRACE,("New Unicast Address: %x\n",
1572 IF->Unicast.Address.IPv4Address));
1573 TI_DbgPrint(MID_TRACE,("New Netmask : %x\n",
1574 IF->Netmask.Address.IPv4Address));
1575
1576 IPAddInterfaceRoute( IF );
1577
1578 IpAddrChange->Address = IF->Index;
1579 Status = STATUS_SUCCESS;
1580 Irp->IoStatus.Information = IF->Index;
1581 break;
1582 }
1583 } EndFor(IF);
1584
1585 Irp->IoStatus.Status = Status;
1586 return Status;
1587 }
1588
1589 NTSTATUS DispTdiDeleteIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
1590 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1591 PUSHORT NteIndex = Irp->AssociatedIrp.SystemBuffer;
1592 IF_LIST_ITER(IF);
1593
1594 ForEachInterface(IF) {
1595 if( IF->Index == *NteIndex ) {
1596 IPRemoveInterfaceRoute( IF );
1597 IF->Unicast.Type = IP_ADDRESS_V4;
1598 IF->Unicast.Address.IPv4Address = 0;
1599 IF->Netmask.Type = IP_ADDRESS_V4;
1600 IF->Netmask.Address.IPv4Address = 0;
1601 IF->Broadcast.Type = IP_ADDRESS_V4;
1602 IF->Broadcast.Address.IPv4Address = 0;
1603 Status = STATUS_SUCCESS;
1604 }
1605 } EndFor(IF);
1606
1607 Irp->IoStatus.Status = Status;
1608 return Status;
1609 }
1610
1611 /* EOF */