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