- Fix a race condition that occurs when an IRP gets cancelled after it is inserted...
[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
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
766 return STATUS_NOT_IMPLEMENTED;
767 }
768
769
770 NTSTATUS DispTdiReceive(
771 PIRP Irp)
772 /*
773 * FUNCTION: TDI_RECEIVE handler
774 * ARGUMENTS:
775 * Irp = Pointer to an I/O request packet
776 * RETURNS:
777 * Status of operation
778 */
779 {
780 PIO_STACK_LOCATION IrpSp;
781 PTDI_REQUEST_KERNEL_RECEIVE ReceiveInfo;
782 PTRANSPORT_CONTEXT TranContext;
783 NTSTATUS Status;
784 ULONG BytesReceived = 0;
785
786 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
787
788 IrpSp = IoGetCurrentIrpStackLocation(Irp);
789 ReceiveInfo = (PTDI_REQUEST_KERNEL_RECEIVE)&(IrpSp->Parameters);
790
791 TranContext = IrpSp->FileObject->FsContext;
792 if (TranContext == NULL)
793 {
794 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
795 Status = STATUS_INVALID_PARAMETER;
796 goto done;
797 }
798
799 if (TranContext->Handle.ConnectionContext == NULL)
800 {
801 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
802 Status = STATUS_INVALID_PARAMETER;
803 goto done;
804 }
805
806 /* Initialize a receive request */
807 Status = DispPrepareIrpForCancel
808 (TranContext->Handle.ConnectionContext,
809 Irp,
810 (PDRIVER_CANCEL)DispCancelRequest);
811
812 TI_DbgPrint(MID_TRACE,("TCPIP<<< Got an MDL: %x\n", Irp->MdlAddress));
813 if (NT_SUCCESS(Status))
814 {
815 Status = TCPReceiveData(
816 TranContext->Handle.ConnectionContext,
817 (PNDIS_BUFFER)Irp->MdlAddress,
818 ReceiveInfo->ReceiveLength,
819 &BytesReceived,
820 ReceiveInfo->ReceiveFlags,
821 DispDataRequestComplete,
822 Irp);
823 }
824
825 done:
826 if (Status != STATUS_PENDING) {
827 DispDataRequestComplete(Irp, Status, BytesReceived);
828 } else
829 IoMarkIrpPending(Irp);
830
831 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
832
833 return Status;
834 }
835
836
837 NTSTATUS DispTdiReceiveDatagram(
838 PIRP Irp)
839 /*
840 * FUNCTION: TDI_RECEIVE_DATAGRAM handler
841 * ARGUMENTS:
842 * Irp = Pointer to an I/O request packet
843 * RETURNS:
844 * Status of operation
845 */
846 {
847 PIO_STACK_LOCATION IrpSp;
848 PTDI_REQUEST_KERNEL_RECEIVEDG DgramInfo;
849 PTRANSPORT_CONTEXT TranContext;
850 TDI_REQUEST Request;
851 NTSTATUS Status;
852 ULONG BytesReceived = 0;
853
854 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
855
856 IrpSp = IoGetCurrentIrpStackLocation(Irp);
857 DgramInfo = (PTDI_REQUEST_KERNEL_RECEIVEDG)&(IrpSp->Parameters);
858
859 TranContext = IrpSp->FileObject->FsContext;
860 if (TranContext == NULL)
861 {
862 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
863 Status = STATUS_INVALID_PARAMETER;
864 goto done;
865 }
866
867 /* Initialize a receive request */
868 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
869 Request.RequestNotifyObject = DispDataRequestComplete;
870 Request.RequestContext = Irp;
871
872 Status = DispPrepareIrpForCancel(
873 IrpSp->FileObject->FsContext,
874 Irp,
875 (PDRIVER_CANCEL)DispCancelRequest);
876
877 if (NT_SUCCESS(Status))
878 {
879 PVOID DataBuffer;
880 UINT BufferSize;
881
882 NdisQueryBuffer( (PNDIS_BUFFER)Irp->MdlAddress,
883 &DataBuffer,
884 &BufferSize );
885
886 Status = DGReceiveDatagram(
887 Request.Handle.AddressHandle,
888 DgramInfo->ReceiveDatagramInformation,
889 DataBuffer,
890 DgramInfo->ReceiveLength,
891 DgramInfo->ReceiveFlags,
892 DgramInfo->ReturnDatagramInformation,
893 &BytesReceived,
894 (PDATAGRAM_COMPLETION_ROUTINE)DispDataRequestComplete,
895 Irp,
896 Irp);
897 }
898
899 done:
900 if (Status != STATUS_PENDING) {
901 DispDataRequestComplete(Irp, Status, BytesReceived);
902 } else
903 IoMarkIrpPending(Irp);
904
905 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
906
907 return Status;
908 }
909
910
911 NTSTATUS DispTdiSend(
912 PIRP Irp)
913 /*
914 * FUNCTION: TDI_SEND handler
915 * ARGUMENTS:
916 * Irp = Pointer to an I/O request packet
917 * RETURNS:
918 * Status of operation
919 */
920 {
921 PIO_STACK_LOCATION IrpSp;
922 PTDI_REQUEST_KERNEL_SEND SendInfo;
923 PTRANSPORT_CONTEXT TranContext;
924 NTSTATUS Status;
925 ULONG BytesSent = 0;
926
927 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
928
929 IrpSp = IoGetCurrentIrpStackLocation(Irp);
930 SendInfo = (PTDI_REQUEST_KERNEL_SEND)&(IrpSp->Parameters);
931
932 TranContext = IrpSp->FileObject->FsContext;
933 if (TranContext == NULL)
934 {
935 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
936 Status = STATUS_INVALID_PARAMETER;
937 goto done;
938 }
939
940 if (TranContext->Handle.ConnectionContext == NULL)
941 {
942 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
943 Status = STATUS_INVALID_PARAMETER;
944 goto done;
945 }
946
947 Status = DispPrepareIrpForCancel(
948 IrpSp->FileObject->FsContext,
949 Irp,
950 (PDRIVER_CANCEL)DispCancelRequest);
951
952 TI_DbgPrint(MID_TRACE,("TCPIP<<< Got an MDL: %x\n", Irp->MdlAddress));
953 if (NT_SUCCESS(Status))
954 {
955 PVOID Data;
956 UINT Len;
957
958 NdisQueryBuffer( Irp->MdlAddress, &Data, &Len );
959
960 TI_DbgPrint(MID_TRACE,("About to TCPSendData\n"));
961 Status = TCPSendData(
962 TranContext->Handle.ConnectionContext,
963 Data,
964 SendInfo->SendLength,
965 &BytesSent,
966 SendInfo->SendFlags,
967 DispDataRequestComplete,
968 Irp);
969 }
970
971 done:
972 if (Status != STATUS_PENDING) {
973 DispDataRequestComplete(Irp, Status, BytesSent);
974 } else
975 IoMarkIrpPending(Irp);
976
977 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
978
979 return Status;
980 }
981
982
983 NTSTATUS DispTdiSendDatagram(
984 PIRP Irp)
985 /*
986 * FUNCTION: TDI_SEND_DATAGRAM handler
987 * ARGUMENTS:
988 * Irp = Pointer to an I/O request packet
989 * RETURNS:
990 * Status of operation
991 */
992 {
993 PIO_STACK_LOCATION IrpSp;
994 TDI_REQUEST Request;
995 PTDI_REQUEST_KERNEL_SENDDG DgramInfo;
996 PTRANSPORT_CONTEXT TranContext;
997 NTSTATUS Status;
998
999 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1000
1001 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1002 DgramInfo = (PTDI_REQUEST_KERNEL_SENDDG)&(IrpSp->Parameters);
1003
1004 TranContext = IrpSp->FileObject->FsContext;
1005 if (TranContext == NULL)
1006 {
1007 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
1008 Status = STATUS_INVALID_PARAMETER;
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 PVOID 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 != NULL) )
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 ASSERT(FALSE);
1048 }
1049 }
1050
1051 done:
1052 if (Status != STATUS_PENDING) {
1053 DispDataRequestComplete(Irp, Status, Irp->IoStatus.Information);
1054 } else
1055 IoMarkIrpPending(Irp);
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 KeAcquireSpinLock(&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 KeReleaseSpinLock(&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
1257 QueryContext = (PTI_QUERY_CONTEXT)Context;
1258 if (NT_SUCCESS(Status)) {
1259 CopyBufferToBufferChain(
1260 QueryContext->InputMdl,
1261 FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context),
1262 (PCHAR)&QueryContext->QueryInfo.Context,
1263 CONTEXT_SIZE);
1264 }
1265
1266 MmUnlockPages(QueryContext->InputMdl);
1267 IoFreeMdl(QueryContext->InputMdl);
1268 if( QueryContext->OutputMdl ) {
1269 MmUnlockPages(QueryContext->OutputMdl);
1270 IoFreeMdl(QueryContext->OutputMdl);
1271 }
1272
1273 QueryContext->Irp->IoStatus.Information = ByteCount;
1274 QueryContext->Irp->IoStatus.Status = Status;
1275
1276 ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG);
1277 }
1278
1279
1280 NTSTATUS DispTdiQueryInformationEx(
1281 PIRP Irp,
1282 PIO_STACK_LOCATION IrpSp)
1283 /*
1284 * FUNCTION: TDI QueryInformationEx handler
1285 * ARGUMENTS:
1286 * Irp = Pointer to I/O request packet
1287 * IrpSp = Pointer to current stack location of Irp
1288 * RETURNS:
1289 * Status of operation
1290 */
1291 {
1292 PTCP_REQUEST_QUERY_INFORMATION_EX InputBuffer;
1293 PTRANSPORT_CONTEXT TranContext;
1294 PTI_QUERY_CONTEXT QueryContext;
1295 PVOID OutputBuffer;
1296 TDI_REQUEST Request;
1297 UINT Size;
1298 UINT InputBufferLength;
1299 UINT OutputBufferLength;
1300 BOOLEAN InputMdlLocked = FALSE;
1301 BOOLEAN OutputMdlLocked = FALSE;
1302 PMDL InputMdl = NULL;
1303 PMDL OutputMdl = NULL;
1304 NTSTATUS Status = STATUS_SUCCESS;
1305
1306 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1307
1308 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
1309
1310 switch ((ULONG)IrpSp->FileObject->FsContext2) {
1311 case TDI_TRANSPORT_ADDRESS_FILE:
1312 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
1313 break;
1314
1315 case TDI_CONNECTION_FILE:
1316 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
1317 break;
1318
1319 case TDI_CONTROL_CHANNEL_FILE:
1320 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
1321 break;
1322
1323 default:
1324 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
1325 return STATUS_INVALID_PARAMETER;
1326 }
1327
1328 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
1329 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
1330
1331 /* Validate parameters */
1332 if ((InputBufferLength == sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)) &&
1333 (OutputBufferLength != 0)) {
1334
1335 InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
1336 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
1337 OutputBuffer = Irp->UserBuffer;
1338
1339 QueryContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(TI_QUERY_CONTEXT), QUERY_CONTEXT_TAG);
1340 if (QueryContext) {
1341 _SEH2_TRY {
1342 InputMdl = IoAllocateMdl(InputBuffer,
1343 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
1344 FALSE, TRUE, NULL);
1345
1346 OutputMdl = IoAllocateMdl(OutputBuffer,
1347 OutputBufferLength, FALSE, TRUE, NULL);
1348
1349 if (InputMdl && OutputMdl) {
1350
1351 MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
1352 IoModifyAccess);
1353
1354 InputMdlLocked = TRUE;
1355
1356 MmProbeAndLockPages(OutputMdl, Irp->RequestorMode,
1357 IoWriteAccess);
1358
1359 OutputMdlLocked = TRUE;
1360
1361 RtlCopyMemory(&QueryContext->QueryInfo,
1362 InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
1363 } else
1364 Status = STATUS_INSUFFICIENT_RESOURCES;
1365 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
1366 Status = _SEH2_GetExceptionCode();
1367 } _SEH2_END;
1368
1369 if (NT_SUCCESS(Status)) {
1370 Size = MmGetMdlByteCount(OutputMdl);
1371
1372 QueryContext->Irp = Irp;
1373 QueryContext->InputMdl = InputMdl;
1374 QueryContext->OutputMdl = OutputMdl;
1375
1376 Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
1377 Request.RequestContext = QueryContext;
1378 Status = InfoTdiQueryInformationEx(&Request,
1379 &QueryContext->QueryInfo.ID, OutputMdl,
1380 &Size, &QueryContext->QueryInfo.Context);
1381 DispTdiQueryInformationExComplete(QueryContext, Status, Size);
1382
1383 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1384
1385 return Status;
1386 }
1387
1388 /* An error occurred if we get here */
1389
1390 if (InputMdl) {
1391 if (InputMdlLocked)
1392 MmUnlockPages(InputMdl);
1393 IoFreeMdl(InputMdl);
1394 }
1395
1396 if (OutputMdl) {
1397 if (OutputMdlLocked)
1398 MmUnlockPages(OutputMdl);
1399 IoFreeMdl(OutputMdl);
1400 }
1401
1402 ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG);
1403 } else
1404 Status = STATUS_INSUFFICIENT_RESOURCES;
1405 } else if( InputBufferLength ==
1406 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX) ) {
1407 /* Handle the case where the user is probing the buffer for length */
1408 TI_DbgPrint(MAX_TRACE, ("InputBufferLength %d OutputBufferLength %d\n",
1409 InputBufferLength, OutputBufferLength));
1410 InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
1411 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
1412
1413 Size = 0;
1414
1415 QueryContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(TI_QUERY_CONTEXT), QUERY_CONTEXT_TAG);
1416 if (!QueryContext) return STATUS_INSUFFICIENT_RESOURCES;
1417
1418 _SEH2_TRY {
1419 InputMdl = IoAllocateMdl(InputBuffer,
1420 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
1421 FALSE, TRUE, NULL);
1422
1423 MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
1424 IoModifyAccess);
1425
1426 InputMdlLocked = TRUE;
1427 Status = STATUS_SUCCESS;
1428 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
1429 TI_DbgPrint(MAX_TRACE, ("Failed to acquire client buffer\n"));
1430 Status = _SEH2_GetExceptionCode();
1431 } _SEH2_END;
1432
1433 if( !NT_SUCCESS(Status) || !InputMdl ) {
1434 if( InputMdl ) IoFreeMdl( InputMdl );
1435 ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG);
1436 return Status;
1437 }
1438
1439 RtlCopyMemory(&QueryContext->QueryInfo,
1440 InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
1441
1442 QueryContext->Irp = Irp;
1443 QueryContext->InputMdl = InputMdl;
1444 QueryContext->OutputMdl = NULL;
1445
1446 Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
1447 Request.RequestContext = QueryContext;
1448 Status = InfoTdiQueryInformationEx(&Request,
1449 &QueryContext->QueryInfo.ID,
1450 NULL,
1451 &Size,
1452 &QueryContext->QueryInfo.Context);
1453 DispTdiQueryInformationExComplete(QueryContext, Status, Size);
1454 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1455 } else Status = STATUS_INVALID_PARAMETER;
1456
1457 TI_DbgPrint(MIN_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1458
1459 return Status;
1460 }
1461
1462
1463 NTSTATUS DispTdiSetInformationEx(
1464 PIRP Irp,
1465 PIO_STACK_LOCATION IrpSp)
1466 /*
1467 * FUNCTION: TDI SetInformationEx handler
1468 * ARGUMENTS:
1469 * Irp = Pointer to I/O request packet
1470 * IrpSp = Pointer to current stack location of Irp
1471 * RETURNS:
1472 * Status of operation
1473 */
1474 {
1475 PTRANSPORT_CONTEXT TranContext;
1476 PTCP_REQUEST_SET_INFORMATION_EX Info;
1477 TDI_REQUEST Request;
1478 TDI_STATUS Status;
1479
1480 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1481
1482 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
1483 Info = (PTCP_REQUEST_SET_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer;
1484
1485 switch ((ULONG)IrpSp->FileObject->FsContext2) {
1486 case TDI_TRANSPORT_ADDRESS_FILE:
1487 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
1488 break;
1489
1490 case TDI_CONNECTION_FILE:
1491 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
1492 break;
1493
1494 case TDI_CONTROL_CHANNEL_FILE:
1495 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
1496 break;
1497
1498 default:
1499 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1500 Irp->IoStatus.Information = 0;
1501
1502 TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
1503
1504 return Irp->IoStatus.Status;
1505 }
1506
1507 Status = DispPrepareIrpForCancel(TranContext, Irp, NULL);
1508 if (NT_SUCCESS(Status)) {
1509 Request.RequestNotifyObject = DispDataRequestComplete;
1510 Request.RequestContext = Irp;
1511
1512 Status = InfoTdiSetInformationEx(&Request, &Info->ID,
1513 &Info->Buffer, Info->BufferSize);
1514 }
1515
1516 return Status;
1517 }
1518
1519 /* TODO: Support multiple addresses per interface.
1520 * For now just set the nte context to the interface index.
1521 *
1522 * Later on, create an NTE context and NTE instance
1523 */
1524
1525 NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
1526 NTSTATUS Status = STATUS_DEVICE_DOES_NOT_EXIST;
1527 PIP_SET_ADDRESS IpAddrChange =
1528 (PIP_SET_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
1529 IF_LIST_ITER(IF);
1530
1531 TI_DbgPrint(MID_TRACE,("Setting IP Address for adapter %d\n",
1532 IpAddrChange->NteIndex));
1533
1534 ForEachInterface(IF) {
1535 TI_DbgPrint(MID_TRACE,("Looking at adapter %d\n", IF->Index));
1536
1537 if( IF->Unicast.Address.IPv4Address == IpAddrChange->Address ) {
1538 Status = STATUS_DUPLICATE_OBJECTID;
1539 break;
1540 }
1541 if( IF->Index == IpAddrChange->NteIndex ) {
1542 IPRemoveInterfaceRoute( IF );
1543
1544 IF->Unicast.Type = IP_ADDRESS_V4;
1545 IF->Unicast.Address.IPv4Address = IpAddrChange->Address;
1546 IF->Netmask.Type = IP_ADDRESS_V4;
1547 IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask;
1548 IF->Broadcast.Type = IP_ADDRESS_V4;
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 IF->Broadcast.Type = IP_ADDRESS_V4;
1584 IF->Broadcast.Address.IPv4Address = 0;
1585 Status = STATUS_SUCCESS;
1586 }
1587 } EndFor(IF);
1588
1589 Irp->IoStatus.Status = Status;
1590 return Status;
1591 }
1592
1593 /* EOF */