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