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