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