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