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