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