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