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