[NTOS]
[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_PTR)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_PTR)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 {
1065 ULONG DataUsed = 0;
1066 Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)(
1067 Request.Handle.AddressHandle,
1068 DgramInfo->SendDatagramInformation,
1069 DataBuffer,
1070 BufferSize,
1071 &DataUsed);
1072 Irp->IoStatus.Information = DataUsed;
1073 }
1074 else
1075 Status = STATUS_UNSUCCESSFUL;
1076 }
1077
1078 done:
1079 TcpipRecursiveMutexLeave( &TCPLock );
1080
1081 if (Status != STATUS_PENDING) {
1082 DispDataRequestComplete(Irp, Status, Irp->IoStatus.Information);
1083 } else
1084 IoMarkIrpPending(Irp);
1085
1086 TI_DbgPrint(DEBUG_IRP, ("Leaving.\n"));
1087
1088 return Status;
1089 }
1090
1091
1092 NTSTATUS DispTdiSetEventHandler(PIRP Irp)
1093 /*
1094 * FUNCTION: TDI_SET_EVENT_HANDER handler
1095 * ARGUMENTS:
1096 * Irp = Pointer to a I/O request packet
1097 * RETURNS:
1098 * Status of operation
1099 */
1100 {
1101 PTDI_REQUEST_KERNEL_SET_EVENT Parameters;
1102 PTRANSPORT_CONTEXT TranContext;
1103 PIO_STACK_LOCATION IrpSp;
1104 PADDRESS_FILE AddrFile;
1105 NTSTATUS Status;
1106 KIRQL OldIrql;
1107
1108 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1109
1110 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1111
1112 /* Get associated address file object. Quit if none exists */
1113
1114 TranContext = IrpSp->FileObject->FsContext;
1115 if (!TranContext) {
1116 TI_DbgPrint(MIN_TRACE, ("Bad transport context.\n"));
1117 return STATUS_INVALID_PARAMETER;
1118 }
1119
1120 AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
1121 if (!AddrFile) {
1122 TI_DbgPrint(MIN_TRACE, ("No address file object.\n"));
1123 return STATUS_INVALID_PARAMETER;
1124 }
1125
1126 Parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters;
1127 Status = STATUS_SUCCESS;
1128
1129 TcpipAcquireSpinLock(&AddrFile->Lock, &OldIrql);
1130
1131 /* Set the event handler. if an event handler is associated with
1132 a specific event, it's flag (RegisteredXxxHandler) is TRUE.
1133 If an event handler is not used it's flag is FALSE */
1134 switch (Parameters->EventType) {
1135 case TDI_EVENT_CONNECT:
1136 if (!Parameters->EventHandler) {
1137 AddrFile->ConnectHandlerContext = NULL;
1138 AddrFile->RegisteredConnectHandler = FALSE;
1139 } else {
1140 AddrFile->ConnectHandler =
1141 (PTDI_IND_CONNECT)Parameters->EventHandler;
1142 AddrFile->ConnectHandlerContext = Parameters->EventContext;
1143 AddrFile->RegisteredConnectHandler = TRUE;
1144 }
1145 break;
1146
1147 case TDI_EVENT_DISCONNECT:
1148 if (!Parameters->EventHandler) {
1149 AddrFile->DisconnectHandlerContext = NULL;
1150 AddrFile->RegisteredDisconnectHandler = FALSE;
1151 } else {
1152 AddrFile->DisconnectHandler =
1153 (PTDI_IND_DISCONNECT)Parameters->EventHandler;
1154 AddrFile->DisconnectHandlerContext = Parameters->EventContext;
1155 AddrFile->RegisteredDisconnectHandler = TRUE;
1156 }
1157 break;
1158
1159 case TDI_EVENT_ERROR:
1160 if (Parameters->EventHandler == NULL) {
1161 AddrFile->ErrorHandlerContext = NULL;
1162 AddrFile->RegisteredErrorHandler = FALSE;
1163 } else {
1164 AddrFile->ErrorHandler =
1165 (PTDI_IND_ERROR)Parameters->EventHandler;
1166 AddrFile->ErrorHandlerContext = Parameters->EventContext;
1167 AddrFile->RegisteredErrorHandler = TRUE;
1168 }
1169 break;
1170
1171 case TDI_EVENT_RECEIVE:
1172 if (Parameters->EventHandler == NULL) {
1173 AddrFile->ReceiveHandlerContext = NULL;
1174 AddrFile->RegisteredReceiveHandler = FALSE;
1175 } else {
1176 AddrFile->ReceiveHandler =
1177 (PTDI_IND_RECEIVE)Parameters->EventHandler;
1178 AddrFile->ReceiveHandlerContext = Parameters->EventContext;
1179 AddrFile->RegisteredReceiveHandler = TRUE;
1180 }
1181 break;
1182
1183 case TDI_EVENT_RECEIVE_DATAGRAM:
1184 if (Parameters->EventHandler == NULL) {
1185 AddrFile->ReceiveDatagramHandlerContext = NULL;
1186 AddrFile->RegisteredReceiveDatagramHandler = FALSE;
1187 } else {
1188 AddrFile->ReceiveDatagramHandler =
1189 (PTDI_IND_RECEIVE_DATAGRAM)Parameters->EventHandler;
1190 AddrFile->ReceiveDatagramHandlerContext = Parameters->EventContext;
1191 AddrFile->RegisteredReceiveDatagramHandler = TRUE;
1192 }
1193 break;
1194
1195 case TDI_EVENT_RECEIVE_EXPEDITED:
1196 if (Parameters->EventHandler == NULL) {
1197 AddrFile->ExpeditedReceiveHandlerContext = NULL;
1198 AddrFile->RegisteredExpeditedReceiveHandler = FALSE;
1199 } else {
1200 AddrFile->ExpeditedReceiveHandler =
1201 (PTDI_IND_RECEIVE_EXPEDITED)Parameters->EventHandler;
1202 AddrFile->ExpeditedReceiveHandlerContext = Parameters->EventContext;
1203 AddrFile->RegisteredExpeditedReceiveHandler = TRUE;
1204 }
1205 break;
1206
1207 case TDI_EVENT_CHAINED_RECEIVE:
1208 if (Parameters->EventHandler == NULL) {
1209 AddrFile->ChainedReceiveHandlerContext = NULL;
1210 AddrFile->RegisteredChainedReceiveHandler = FALSE;
1211 } else {
1212 AddrFile->ChainedReceiveHandler =
1213 (PTDI_IND_CHAINED_RECEIVE)Parameters->EventHandler;
1214 AddrFile->ChainedReceiveHandlerContext = Parameters->EventContext;
1215 AddrFile->RegisteredChainedReceiveHandler = TRUE;
1216 }
1217 break;
1218
1219 case TDI_EVENT_CHAINED_RECEIVE_DATAGRAM:
1220 if (Parameters->EventHandler == NULL) {
1221 AddrFile->ChainedReceiveDatagramHandlerContext = NULL;
1222 AddrFile->RegisteredChainedReceiveDatagramHandler = FALSE;
1223 } else {
1224 AddrFile->ChainedReceiveDatagramHandler =
1225 (PTDI_IND_CHAINED_RECEIVE_DATAGRAM)Parameters->EventHandler;
1226 AddrFile->ChainedReceiveDatagramHandlerContext = Parameters->EventContext;
1227 AddrFile->RegisteredChainedReceiveDatagramHandler = TRUE;
1228 }
1229 break;
1230
1231 case TDI_EVENT_CHAINED_RECEIVE_EXPEDITED:
1232 if (Parameters->EventHandler == NULL) {
1233 AddrFile->ChainedReceiveExpeditedHandlerContext = NULL;
1234 AddrFile->RegisteredChainedReceiveExpeditedHandler = FALSE;
1235 } else {
1236 AddrFile->ChainedReceiveExpeditedHandler =
1237 (PTDI_IND_CHAINED_RECEIVE_EXPEDITED)Parameters->EventHandler;
1238 AddrFile->ChainedReceiveExpeditedHandlerContext = Parameters->EventContext;
1239 AddrFile->RegisteredChainedReceiveExpeditedHandler = TRUE;
1240 }
1241 break;
1242
1243 default:
1244 TI_DbgPrint(MIN_TRACE, ("Unknown event type (0x%X).\n",
1245 Parameters->EventType));
1246
1247 Status = STATUS_INVALID_PARAMETER;
1248 }
1249
1250 TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);
1251
1252 return Status;
1253 }
1254
1255
1256 NTSTATUS DispTdiSetInformation(
1257 PIRP Irp)
1258 /*
1259 * FUNCTION: TDI_SET_INFORMATION handler
1260 * ARGUMENTS:
1261 * Irp = Pointer to an I/O request packet
1262 * RETURNS:
1263 * Status of operation
1264 */
1265 {
1266 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1267
1268 return STATUS_NOT_IMPLEMENTED;
1269 }
1270
1271
1272 VOID DispTdiQueryInformationExComplete(
1273 PVOID Context,
1274 ULONG Status,
1275 UINT ByteCount)
1276 /*
1277 * FUNCTION: Completes a TDI QueryInformationEx request
1278 * ARGUMENTS:
1279 * Context = Pointer to the IRP for the request
1280 * Status = TDI status of the request
1281 * ByteCount = Number of bytes returned in output buffer
1282 */
1283 {
1284 PTI_QUERY_CONTEXT QueryContext;
1285 UINT Count = 0;
1286
1287 QueryContext = (PTI_QUERY_CONTEXT)Context;
1288 if (NT_SUCCESS(Status)) {
1289 Count = CopyBufferToBufferChain(
1290 QueryContext->InputMdl,
1291 FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context),
1292 (PCHAR)&QueryContext->QueryInfo.Context,
1293 CONTEXT_SIZE);
1294 }
1295
1296 MmUnlockPages(QueryContext->InputMdl);
1297 IoFreeMdl(QueryContext->InputMdl);
1298 if( QueryContext->OutputMdl ) {
1299 MmUnlockPages(QueryContext->OutputMdl);
1300 IoFreeMdl(QueryContext->OutputMdl);
1301 }
1302
1303 QueryContext->Irp->IoStatus.Information = ByteCount;
1304 QueryContext->Irp->IoStatus.Status = Status;
1305
1306 exFreePool(QueryContext);
1307 }
1308
1309
1310 NTSTATUS DispTdiQueryInformationEx(
1311 PIRP Irp,
1312 PIO_STACK_LOCATION IrpSp)
1313 /*
1314 * FUNCTION: TDI QueryInformationEx handler
1315 * ARGUMENTS:
1316 * Irp = Pointer to I/O request packet
1317 * IrpSp = Pointer to current stack location of Irp
1318 * RETURNS:
1319 * Status of operation
1320 */
1321 {
1322 PTCP_REQUEST_QUERY_INFORMATION_EX InputBuffer;
1323 PTRANSPORT_CONTEXT TranContext;
1324 PTI_QUERY_CONTEXT QueryContext;
1325 PVOID OutputBuffer;
1326 TDI_REQUEST Request;
1327 UINT Size;
1328 UINT InputBufferLength;
1329 UINT OutputBufferLength;
1330 BOOLEAN InputMdlLocked = FALSE;
1331 BOOLEAN OutputMdlLocked = FALSE;
1332 PMDL InputMdl = NULL;
1333 PMDL OutputMdl = NULL;
1334 NTSTATUS Status = STATUS_SUCCESS;
1335
1336 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1337
1338 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
1339
1340 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
1341 case TDI_TRANSPORT_ADDRESS_FILE:
1342 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
1343 break;
1344
1345 case TDI_CONNECTION_FILE:
1346 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
1347 break;
1348
1349 case TDI_CONTROL_CHANNEL_FILE:
1350 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
1351 break;
1352
1353 default:
1354 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
1355 return STATUS_INVALID_PARAMETER;
1356 }
1357
1358 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
1359 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
1360
1361 /* Validate parameters */
1362 if ((InputBufferLength == sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)) &&
1363 (OutputBufferLength != 0)) {
1364
1365 InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
1366 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
1367 OutputBuffer = Irp->UserBuffer;
1368
1369 QueryContext = exAllocatePool(NonPagedPool, sizeof(TI_QUERY_CONTEXT));
1370 if (QueryContext) {
1371 _SEH2_TRY {
1372 InputMdl = IoAllocateMdl(InputBuffer,
1373 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
1374 FALSE, TRUE, NULL);
1375
1376 OutputMdl = IoAllocateMdl(OutputBuffer,
1377 OutputBufferLength, FALSE, TRUE, NULL);
1378
1379 if (InputMdl && OutputMdl) {
1380
1381 MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
1382 IoModifyAccess);
1383
1384 InputMdlLocked = TRUE;
1385
1386 MmProbeAndLockPages(OutputMdl, Irp->RequestorMode,
1387 IoWriteAccess);
1388
1389 OutputMdlLocked = TRUE;
1390
1391 RtlCopyMemory(&QueryContext->QueryInfo,
1392 InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
1393 } else
1394 Status = STATUS_INSUFFICIENT_RESOURCES;
1395 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
1396 Status = _SEH2_GetExceptionCode();
1397 } _SEH2_END;
1398
1399 if (NT_SUCCESS(Status)) {
1400 Size = MmGetMdlByteCount(OutputMdl);
1401
1402 QueryContext->Irp = Irp;
1403 QueryContext->InputMdl = InputMdl;
1404 QueryContext->OutputMdl = OutputMdl;
1405
1406 Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
1407 Request.RequestContext = QueryContext;
1408 Status = InfoTdiQueryInformationEx(&Request,
1409 &QueryContext->QueryInfo.ID, OutputMdl,
1410 &Size, &QueryContext->QueryInfo.Context);
1411 DispTdiQueryInformationExComplete(QueryContext, Status, Size);
1412
1413 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1414
1415 return Status;
1416 }
1417
1418 /* An error occurred if we get here */
1419
1420 if (InputMdl) {
1421 if (InputMdlLocked)
1422 MmUnlockPages(InputMdl);
1423 IoFreeMdl(InputMdl);
1424 }
1425
1426 if (OutputMdl) {
1427 if (OutputMdlLocked)
1428 MmUnlockPages(OutputMdl);
1429 IoFreeMdl(OutputMdl);
1430 }
1431
1432 exFreePool(QueryContext);
1433 } else
1434 Status = STATUS_INSUFFICIENT_RESOURCES;
1435 } else if( InputBufferLength ==
1436 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX) ) {
1437 /* Handle the case where the user is probing the buffer for length */
1438 TI_DbgPrint(MAX_TRACE, ("InputBufferLength %d OutputBufferLength %d\n",
1439 InputBufferLength, OutputBufferLength));
1440 InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
1441 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
1442
1443 Size = 0;
1444
1445 QueryContext = exAllocatePool(NonPagedPool, sizeof(TI_QUERY_CONTEXT));
1446 if (!QueryContext) return STATUS_INSUFFICIENT_RESOURCES;
1447
1448 _SEH2_TRY {
1449 InputMdl = IoAllocateMdl(InputBuffer,
1450 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
1451 FALSE, TRUE, NULL);
1452
1453 MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
1454 IoModifyAccess);
1455
1456 InputMdlLocked = TRUE;
1457 Status = STATUS_SUCCESS;
1458 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
1459 TI_DbgPrint(MAX_TRACE, ("Failed to acquire client buffer\n"));
1460 Status = _SEH2_GetExceptionCode();
1461 } _SEH2_END;
1462
1463 if( !NT_SUCCESS(Status) || !InputMdl ) {
1464 if( InputMdl ) IoFreeMdl( InputMdl );
1465 exFreePool(QueryContext);
1466 return Status;
1467 }
1468
1469 RtlCopyMemory(&QueryContext->QueryInfo,
1470 InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
1471
1472 QueryContext->Irp = Irp;
1473 QueryContext->InputMdl = InputMdl;
1474 QueryContext->OutputMdl = NULL;
1475
1476 Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
1477 Request.RequestContext = QueryContext;
1478 Status = InfoTdiQueryInformationEx(&Request,
1479 &QueryContext->QueryInfo.ID,
1480 NULL,
1481 &Size,
1482 &QueryContext->QueryInfo.Context);
1483 DispTdiQueryInformationExComplete(QueryContext, Status, Size);
1484 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1485 } else Status = STATUS_INVALID_PARAMETER;
1486
1487 TI_DbgPrint(MIN_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1488
1489 return Status;
1490 }
1491
1492
1493 NTSTATUS DispTdiSetInformationEx(
1494 PIRP Irp,
1495 PIO_STACK_LOCATION IrpSp)
1496 /*
1497 * FUNCTION: TDI SetInformationEx handler
1498 * ARGUMENTS:
1499 * Irp = Pointer to I/O request packet
1500 * IrpSp = Pointer to current stack location of Irp
1501 * RETURNS:
1502 * Status of operation
1503 */
1504 {
1505 PTRANSPORT_CONTEXT TranContext;
1506 PTCP_REQUEST_SET_INFORMATION_EX Info;
1507 TDI_REQUEST Request;
1508 TDI_STATUS Status;
1509
1510 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1511
1512 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
1513 Info = (PTCP_REQUEST_SET_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer;
1514
1515 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
1516 case TDI_TRANSPORT_ADDRESS_FILE:
1517 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
1518 break;
1519
1520 case TDI_CONNECTION_FILE:
1521 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
1522 break;
1523
1524 case TDI_CONTROL_CHANNEL_FILE:
1525 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
1526 break;
1527
1528 default:
1529 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1530 Irp->IoStatus.Information = 0;
1531
1532 TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
1533
1534 return Irp->IoStatus.Status;
1535 }
1536
1537 Status = DispPrepareIrpForCancel(TranContext, Irp, NULL);
1538 if (NT_SUCCESS(Status)) {
1539 Request.RequestNotifyObject = DispDataRequestComplete;
1540 Request.RequestContext = Irp;
1541
1542 Status = InfoTdiSetInformationEx(&Request, &Info->ID,
1543 &Info->Buffer, Info->BufferSize);
1544 }
1545
1546 return Status;
1547 }
1548
1549 /* TODO: Support multiple addresses per interface.
1550 * For now just set the nte context to the interface index.
1551 *
1552 * Later on, create an NTE context and NTE instance
1553 */
1554
1555 NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
1556 NTSTATUS Status = STATUS_DEVICE_DOES_NOT_EXIST;
1557 PIP_SET_ADDRESS IpAddrChange =
1558 (PIP_SET_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
1559 IF_LIST_ITER(IF);
1560
1561 TI_DbgPrint(MID_TRACE,("Setting IP Address for adapter %d\n",
1562 IpAddrChange->NteIndex));
1563
1564 ForEachInterface(IF) {
1565 TI_DbgPrint(MID_TRACE,("Looking at adapter %d\n", IF->Index));
1566
1567 if( IF->Unicast.Address.IPv4Address == IpAddrChange->Address ) {
1568 Status = STATUS_DUPLICATE_OBJECTID;
1569 break;
1570 }
1571 if( IF->Index == IpAddrChange->NteIndex ) {
1572 IPRemoveInterfaceRoute( IF );
1573
1574 IF->Unicast.Type = IP_ADDRESS_V4;
1575 IF->Unicast.Address.IPv4Address = IpAddrChange->Address;
1576 IF->Netmask.Type = IP_ADDRESS_V4;
1577 IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask;
1578 IF->Broadcast.Type = IP_ADDRESS_V4;
1579 IF->Broadcast.Address.IPv4Address =
1580 IF->Unicast.Address.IPv4Address |
1581 ~IF->Netmask.Address.IPv4Address;
1582
1583 TI_DbgPrint(MID_TRACE,("New Unicast Address: %x\n",
1584 IF->Unicast.Address.IPv4Address));
1585 TI_DbgPrint(MID_TRACE,("New Netmask : %x\n",
1586 IF->Netmask.Address.IPv4Address));
1587
1588 IPAddInterfaceRoute( IF );
1589
1590 IpAddrChange->Address = IF->Index;
1591 Status = STATUS_SUCCESS;
1592 Irp->IoStatus.Information = IF->Index;
1593 break;
1594 }
1595 } EndFor(IF);
1596
1597 Irp->IoStatus.Status = Status;
1598 return Status;
1599 }
1600
1601 NTSTATUS DispTdiDeleteIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
1602 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1603 PUSHORT NteIndex = Irp->AssociatedIrp.SystemBuffer;
1604 IF_LIST_ITER(IF);
1605
1606 ForEachInterface(IF) {
1607 if( IF->Index == *NteIndex ) {
1608 IPRemoveInterfaceRoute( IF );
1609 IF->Unicast.Type = IP_ADDRESS_V4;
1610 IF->Unicast.Address.IPv4Address = 0;
1611 IF->Netmask.Type = IP_ADDRESS_V4;
1612 IF->Netmask.Address.IPv4Address = 0;
1613 IF->Broadcast.Type = IP_ADDRESS_V4;
1614 IF->Broadcast.Address.IPv4Address = 0;
1615 Status = STATUS_SUCCESS;
1616 }
1617 } EndFor(IF);
1618
1619 Irp->IoStatus.Status = Status;
1620 return Status;
1621 }
1622
1623 /* EOF */