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