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