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