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