75c1cfba41dde55f24de7f0b09cbccec2a23dd54
[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, LastConnection;
448 PTRANSPORT_CONTEXT TranContext;
449 PIO_STACK_LOCATION IrpSp;
450 KIRQL OldIrql;
451 NTSTATUS Status;
452
453 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
454
455 IrpSp = IoGetCurrentIrpStackLocation(Irp);
456
457 /* Get associated connection endpoint file object. Quit if none exists */
458
459 TranContext = IrpSp->FileObject->FsContext;
460 if (!TranContext) {
461 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
462 return STATUS_INVALID_PARAMETER;
463 }
464
465 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
466 if (!Connection) {
467 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
468 return STATUS_INVALID_PARAMETER;
469 }
470
471 LockObject(Connection, &OldIrql);
472
473 if (!Connection->AddressFile) {
474 UnlockObject(Connection, OldIrql);
475 TI_DbgPrint(MID_TRACE, ("No address file is asscociated.\n"));
476 return STATUS_INVALID_PARAMETER;
477 }
478
479 LockObjectAtDpcLevel(Connection->AddressFile);
480
481 /* Unlink this connection from the address file */
482 if (Connection->AddressFile->Connection == Connection)
483 {
484 Connection->AddressFile->Connection = Connection->Next;
485 DereferenceObject(Connection);
486 Status = STATUS_SUCCESS;
487 }
488 else
489 {
490 LastConnection = Connection->AddressFile->Connection;
491 while (LastConnection->Next != Connection && LastConnection->Next != NULL)
492 LastConnection = LastConnection->Next;
493 if (LastConnection->Next == Connection)
494 {
495 LastConnection->Next = Connection->Next;
496 DereferenceObject(Connection);
497 Status = STATUS_SUCCESS;
498 }
499 else
500 {
501 Status = STATUS_INVALID_PARAMETER;
502 }
503 }
504
505 UnlockObjectFromDpcLevel(Connection->AddressFile);
506
507 if (Status == STATUS_SUCCESS)
508 {
509 /* Remove the address file from this connection */
510 DereferenceObject(Connection->AddressFile);
511 Connection->AddressFile = NULL;
512 }
513
514 UnlockObject(Connection, OldIrql);
515
516 return Status;
517 }
518
519
520 NTSTATUS DispTdiDisconnect(
521 PIRP Irp)
522 /*
523 * FUNCTION: TDI_DISCONNECT handler
524 * ARGUMENTS:
525 * Irp = Pointer to an I/O request packet
526 * RETURNS:
527 * Status of operation
528 */
529 {
530 NTSTATUS Status;
531 PTDI_REQUEST_KERNEL_DISCONNECT DisReq;
532 PCONNECTION_ENDPOINT Connection;
533 PTRANSPORT_CONTEXT TranContext;
534 PIO_STACK_LOCATION IrpSp;
535
536 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
537
538 IrpSp = IoGetCurrentIrpStackLocation(Irp);
539 DisReq = (PTDI_REQUEST_KERNEL_DISCONNECT)&IrpSp->Parameters;
540
541 /* Get associated connection endpoint file object. Quit if none exists */
542
543 TranContext = IrpSp->FileObject->FsContext;
544 if (!TranContext) {
545 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
546 Status = STATUS_INVALID_PARAMETER;
547 goto done;
548 }
549
550 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
551 if (!Connection) {
552 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
553 Status = STATUS_INVALID_PARAMETER;
554 goto done;
555 }
556
557 Status = DispPrepareIrpForCancel
558 (TranContext->Handle.ConnectionContext,
559 Irp,
560 (PDRIVER_CANCEL)DispCancelRequest);
561
562 if (NT_SUCCESS(Status))
563 {
564 Status = TCPDisconnect(TranContext->Handle.ConnectionContext,
565 DisReq->RequestFlags,
566 DisReq->RequestSpecific,
567 DisReq->RequestConnectionInformation,
568 DisReq->ReturnConnectionInformation,
569 DispDataRequestComplete,
570 Irp);
571 }
572
573 done:
574 if (Status != STATUS_PENDING) {
575 DispDataRequestComplete(Irp, Status, 0);
576 } else
577 IoMarkIrpPending(Irp);
578
579 TI_DbgPrint(MAX_TRACE, ("TCP Disconnect returned %08x\n", Status));
580
581 return Status;
582 }
583
584
585 NTSTATUS DispTdiListen(
586 PIRP Irp)
587 /*
588 * FUNCTION: TDI_LISTEN handler
589 * ARGUMENTS:
590 * Irp = Pointer to an I/O request packet
591 * RETURNS:
592 * Status of operation
593 */
594 {
595 PCONNECTION_ENDPOINT Connection;
596 PTDI_REQUEST_KERNEL Parameters;
597 PTRANSPORT_CONTEXT TranContext;
598 PIO_STACK_LOCATION IrpSp;
599 NTSTATUS Status = STATUS_SUCCESS;
600 KIRQL OldIrql;
601
602 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
603
604 IrpSp = IoGetCurrentIrpStackLocation(Irp);
605
606 /* Get associated connection endpoint file object. Quit if none exists */
607
608 TranContext = IrpSp->FileObject->FsContext;
609 if (TranContext == NULL)
610 {
611 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
612 Status = STATUS_INVALID_PARAMETER;
613 goto done;
614 }
615
616 Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
617 if (Connection == NULL)
618 {
619 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
620 Status = STATUS_INVALID_PARAMETER;
621 goto done;
622 }
623
624 Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
625
626 Status = DispPrepareIrpForCancel
627 (TranContext->Handle.ConnectionContext,
628 Irp,
629 (PDRIVER_CANCEL)DispCancelListenRequest);
630
631 LockObject(Connection, &OldIrql);
632
633 if (Connection->AddressFile == NULL)
634 {
635 TI_DbgPrint(MID_TRACE, ("No associated address file\n"));
636 UnlockObject(Connection, OldIrql);
637 Status = STATUS_INVALID_PARAMETER;
638 goto done;
639 }
640
641 LockObjectAtDpcLevel(Connection->AddressFile);
642
643 /* Listening will require us to create a listening socket and store it in
644 * the address file. It will be signalled, and attempt to complete an irp
645 * when a new connection arrives. */
646 /* The important thing to note here is that the irp we'll complete belongs
647 * to the socket to be accepted onto, not the listener */
648 if( NT_SUCCESS(Status) && !Connection->AddressFile->Listener ) {
649 Connection->AddressFile->Listener =
650 TCPAllocateConnectionEndpoint( NULL );
651
652 if( !Connection->AddressFile->Listener )
653 Status = STATUS_NO_MEMORY;
654
655 if( NT_SUCCESS(Status) ) {
656 Connection->AddressFile->Listener->AddressFile =
657 Connection->AddressFile;
658
659 Status = TCPSocket( Connection->AddressFile->Listener,
660 Connection->AddressFile->Family,
661 SOCK_STREAM,
662 Connection->AddressFile->Protocol );
663 }
664
665 if( NT_SUCCESS(Status) )
666 Status = TCPListen( Connection->AddressFile->Listener, 1024 );
667 /* BACKLOG */
668 }
669
670 if( NT_SUCCESS(Status) ) {
671 Status = TCPAccept
672 ( (PTDI_REQUEST)Parameters,
673 Connection->AddressFile->Listener,
674 Connection,
675 DispDataRequestComplete,
676 Irp );
677 }
678
679 UnlockObjectFromDpcLevel(Connection->AddressFile);
680 UnlockObject(Connection, OldIrql);
681
682 done:
683 if (Status != STATUS_PENDING) {
684 DispDataRequestComplete(Irp, Status, 0);
685 } else
686 IoMarkIrpPending(Irp);
687
688 TI_DbgPrint(MID_TRACE,("Leaving %x\n", Status));
689
690 return Status;
691 }
692
693
694 NTSTATUS DispTdiQueryInformation(
695 PDEVICE_OBJECT DeviceObject,
696 PIRP Irp)
697 /*
698 * FUNCTION: TDI_QUERY_INFORMATION handler
699 * ARGUMENTS:
700 * DeviceObject = Pointer to device object structure
701 * Irp = Pointer to an I/O request packet
702 * RETURNS:
703 * Status of operation
704 */
705 {
706 PTDI_REQUEST_KERNEL_QUERY_INFORMATION Parameters;
707 PTRANSPORT_CONTEXT TranContext;
708 PIO_STACK_LOCATION IrpSp;
709
710 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
711
712 IrpSp = IoGetCurrentIrpStackLocation(Irp);
713 Parameters = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&IrpSp->Parameters;
714
715 TranContext = IrpSp->FileObject->FsContext;
716 if (!TranContext) {
717 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
718 return STATUS_INVALID_PARAMETER;
719 }
720
721 switch (Parameters->QueryType)
722 {
723 case TDI_QUERY_ADDRESS_INFO:
724 {
725 PTDI_ADDRESS_INFO AddressInfo;
726 PADDRESS_FILE AddrFile;
727 PTA_IP_ADDRESS Address;
728 PCONNECTION_ENDPOINT Endpoint = NULL;
729
730
731 if (MmGetMdlByteCount(Irp->MdlAddress) <
732 (FIELD_OFFSET(TDI_ADDRESS_INFO, Address.Address[0].Address) +
733 sizeof(TDI_ADDRESS_IP))) {
734 TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n"));
735 return STATUS_BUFFER_TOO_SMALL;
736 }
737
738 AddressInfo = (PTDI_ADDRESS_INFO)MmGetSystemAddressForMdl(Irp->MdlAddress);
739 Address = (PTA_IP_ADDRESS)&AddressInfo->Address;
740
741 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
742 case TDI_TRANSPORT_ADDRESS_FILE:
743 AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
744
745 Address->TAAddressCount = 1;
746 Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
747 Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
748 Address->Address[0].Address[0].sin_port = AddrFile->Port;
749 Address->Address[0].Address[0].in_addr = AddrFile->Address.Address.IPv4Address;
750 RtlZeroMemory(
751 &Address->Address[0].Address[0].sin_zero,
752 sizeof(Address->Address[0].Address[0].sin_zero));
753 return STATUS_SUCCESS;
754
755 case TDI_CONNECTION_FILE:
756 Endpoint =
757 (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
758
759 Address->TAAddressCount = 1;
760 Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
761 Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
762 Address->Address[0].Address[0].sin_port = Endpoint->AddressFile->Port;
763 Address->Address[0].Address[0].in_addr = Endpoint->AddressFile->Address.Address.IPv4Address;
764 RtlZeroMemory(
765 &Address->Address[0].Address[0].sin_zero,
766 sizeof(Address->Address[0].Address[0].sin_zero));
767 return STATUS_SUCCESS;
768
769 default:
770 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
771 return STATUS_INVALID_PARAMETER;
772 }
773 }
774
775 case TDI_QUERY_CONNECTION_INFO:
776 {
777 PTDI_CONNECTION_INFO ConnectionInfo;
778 PCONNECTION_ENDPOINT Endpoint;
779
780 if (MmGetMdlByteCount(Irp->MdlAddress) < sizeof(*ConnectionInfo)) {
781 TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n"));
782 return STATUS_BUFFER_TOO_SMALL;
783 }
784
785 ConnectionInfo = (PTDI_CONNECTION_INFO)
786 MmGetSystemAddressForMdl(Irp->MdlAddress);
787
788 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
789 case TDI_CONNECTION_FILE:
790 Endpoint =
791 (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
792 RtlZeroMemory(ConnectionInfo, sizeof(*ConnectionInfo));
793 return STATUS_SUCCESS;
794
795 default:
796 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
797 return STATUS_INVALID_PARAMETER;
798 }
799 }
800
801 case TDI_QUERY_MAX_DATAGRAM_INFO:
802 {
803 PTDI_MAX_DATAGRAM_INFO MaxDatagramInfo;
804
805 if (MmGetMdlByteCount(Irp->MdlAddress) < sizeof(*MaxDatagramInfo)) {
806 TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n"));
807 return STATUS_BUFFER_TOO_SMALL;
808 }
809
810 MaxDatagramInfo = (PTDI_MAX_DATAGRAM_INFO)
811 MmGetSystemAddressForMdl(Irp->MdlAddress);
812
813 MaxDatagramInfo->MaxDatagramSize = 0xFFFF;
814
815 return STATUS_SUCCESS;
816 }
817 }
818
819 return STATUS_NOT_IMPLEMENTED;
820 }
821
822
823 NTSTATUS DispTdiReceive(
824 PIRP Irp)
825 /*
826 * FUNCTION: TDI_RECEIVE handler
827 * ARGUMENTS:
828 * Irp = Pointer to an I/O request packet
829 * RETURNS:
830 * Status of operation
831 */
832 {
833 PIO_STACK_LOCATION IrpSp;
834 PTDI_REQUEST_KERNEL_RECEIVE ReceiveInfo;
835 PTRANSPORT_CONTEXT TranContext;
836 NTSTATUS Status;
837 ULONG BytesReceived = 0;
838
839 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
840
841 IrpSp = IoGetCurrentIrpStackLocation(Irp);
842 ReceiveInfo = (PTDI_REQUEST_KERNEL_RECEIVE)&(IrpSp->Parameters);
843
844 TranContext = IrpSp->FileObject->FsContext;
845 if (TranContext == NULL)
846 {
847 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
848 Status = STATUS_INVALID_PARAMETER;
849 goto done;
850 }
851
852 if (TranContext->Handle.ConnectionContext == NULL)
853 {
854 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
855 Status = STATUS_INVALID_PARAMETER;
856 goto done;
857 }
858
859 /* Initialize a receive request */
860 Status = DispPrepareIrpForCancel
861 (TranContext->Handle.ConnectionContext,
862 Irp,
863 (PDRIVER_CANCEL)DispCancelRequest);
864
865 TI_DbgPrint(MID_TRACE,("TCPIP<<< Got an MDL: %x\n", Irp->MdlAddress));
866 if (NT_SUCCESS(Status))
867 {
868 Status = TCPReceiveData(
869 TranContext->Handle.ConnectionContext,
870 (PNDIS_BUFFER)Irp->MdlAddress,
871 ReceiveInfo->ReceiveLength,
872 &BytesReceived,
873 ReceiveInfo->ReceiveFlags,
874 DispDataRequestComplete,
875 Irp);
876 }
877
878 done:
879 if (Status != STATUS_PENDING) {
880 DispDataRequestComplete(Irp, Status, BytesReceived);
881 } else
882 IoMarkIrpPending(Irp);
883
884 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
885
886 return Status;
887 }
888
889
890 NTSTATUS DispTdiReceiveDatagram(
891 PIRP Irp)
892 /*
893 * FUNCTION: TDI_RECEIVE_DATAGRAM handler
894 * ARGUMENTS:
895 * Irp = Pointer to an I/O request packet
896 * RETURNS:
897 * Status of operation
898 */
899 {
900 PIO_STACK_LOCATION IrpSp;
901 PTDI_REQUEST_KERNEL_RECEIVEDG DgramInfo;
902 PTRANSPORT_CONTEXT TranContext;
903 TDI_REQUEST Request;
904 NTSTATUS Status;
905 ULONG BytesReceived = 0;
906
907 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
908
909 IrpSp = IoGetCurrentIrpStackLocation(Irp);
910 DgramInfo = (PTDI_REQUEST_KERNEL_RECEIVEDG)&(IrpSp->Parameters);
911
912 TranContext = IrpSp->FileObject->FsContext;
913 if (TranContext == NULL)
914 {
915 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
916 Status = STATUS_INVALID_PARAMETER;
917 goto done;
918 }
919
920 /* Initialize a receive request */
921 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
922 Request.RequestNotifyObject = DispDataRequestComplete;
923 Request.RequestContext = Irp;
924
925 Status = DispPrepareIrpForCancel(
926 IrpSp->FileObject->FsContext,
927 Irp,
928 (PDRIVER_CANCEL)DispCancelRequest);
929
930 if (NT_SUCCESS(Status))
931 {
932 PVOID DataBuffer;
933 UINT BufferSize;
934
935 NdisQueryBuffer( (PNDIS_BUFFER)Irp->MdlAddress,
936 &DataBuffer,
937 &BufferSize );
938
939 Status = DGReceiveDatagram(
940 Request.Handle.AddressHandle,
941 DgramInfo->ReceiveDatagramInformation,
942 DataBuffer,
943 DgramInfo->ReceiveLength,
944 DgramInfo->ReceiveFlags,
945 DgramInfo->ReturnDatagramInformation,
946 &BytesReceived,
947 (PDATAGRAM_COMPLETION_ROUTINE)DispDataRequestComplete,
948 Irp,
949 Irp);
950 }
951
952 done:
953 if (Status != STATUS_PENDING) {
954 DispDataRequestComplete(Irp, Status, BytesReceived);
955 } else
956 IoMarkIrpPending(Irp);
957
958 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
959
960 return Status;
961 }
962
963
964 NTSTATUS DispTdiSend(
965 PIRP Irp)
966 /*
967 * FUNCTION: TDI_SEND handler
968 * ARGUMENTS:
969 * Irp = Pointer to an I/O request packet
970 * RETURNS:
971 * Status of operation
972 */
973 {
974 PIO_STACK_LOCATION IrpSp;
975 PTDI_REQUEST_KERNEL_SEND SendInfo;
976 PTRANSPORT_CONTEXT TranContext;
977 NTSTATUS Status;
978 ULONG BytesSent = 0;
979
980 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
981
982 IrpSp = IoGetCurrentIrpStackLocation(Irp);
983 SendInfo = (PTDI_REQUEST_KERNEL_SEND)&(IrpSp->Parameters);
984
985 TranContext = IrpSp->FileObject->FsContext;
986 if (TranContext == NULL)
987 {
988 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
989 Status = STATUS_INVALID_PARAMETER;
990 goto done;
991 }
992
993 if (TranContext->Handle.ConnectionContext == NULL)
994 {
995 TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
996 Status = STATUS_INVALID_PARAMETER;
997 goto done;
998 }
999
1000 Status = DispPrepareIrpForCancel(
1001 IrpSp->FileObject->FsContext,
1002 Irp,
1003 (PDRIVER_CANCEL)DispCancelRequest);
1004
1005 TI_DbgPrint(MID_TRACE,("TCPIP<<< Got an MDL: %x\n", Irp->MdlAddress));
1006 if (NT_SUCCESS(Status))
1007 {
1008 PVOID Data;
1009 UINT Len;
1010
1011 NdisQueryBuffer( Irp->MdlAddress, &Data, &Len );
1012
1013 TI_DbgPrint(MID_TRACE,("About to TCPSendData\n"));
1014 Status = TCPSendData(
1015 TranContext->Handle.ConnectionContext,
1016 Data,
1017 SendInfo->SendLength,
1018 &BytesSent,
1019 SendInfo->SendFlags,
1020 DispDataRequestComplete,
1021 Irp);
1022 }
1023
1024 done:
1025 if (Status != STATUS_PENDING) {
1026 DispDataRequestComplete(Irp, Status, BytesSent);
1027 } else
1028 IoMarkIrpPending(Irp);
1029
1030 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
1031
1032 return Status;
1033 }
1034
1035
1036 NTSTATUS DispTdiSendDatagram(
1037 PIRP Irp)
1038 /*
1039 * FUNCTION: TDI_SEND_DATAGRAM handler
1040 * ARGUMENTS:
1041 * Irp = Pointer to an I/O request packet
1042 * RETURNS:
1043 * Status of operation
1044 */
1045 {
1046 PIO_STACK_LOCATION IrpSp;
1047 TDI_REQUEST Request;
1048 PTDI_REQUEST_KERNEL_SENDDG DgramInfo;
1049 PTRANSPORT_CONTEXT TranContext;
1050 NTSTATUS Status;
1051
1052 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1053
1054 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1055 DgramInfo = (PTDI_REQUEST_KERNEL_SENDDG)&(IrpSp->Parameters);
1056
1057 TranContext = IrpSp->FileObject->FsContext;
1058 if (TranContext == NULL)
1059 {
1060 TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
1061 Status = STATUS_INVALID_PARAMETER;
1062 goto done;
1063 }
1064
1065 /* Initialize a send request */
1066 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
1067 Request.RequestNotifyObject = DispDataRequestComplete;
1068 Request.RequestContext = Irp;
1069
1070 Status = DispPrepareIrpForCancel(
1071 IrpSp->FileObject->FsContext,
1072 Irp,
1073 (PDRIVER_CANCEL)DispCancelRequest);
1074
1075 if (NT_SUCCESS(Status)) {
1076 PVOID DataBuffer;
1077 UINT BufferSize;
1078
1079 TI_DbgPrint(MID_TRACE,("About to query buffer %x\n", Irp->MdlAddress));
1080
1081 NdisQueryBuffer( (PNDIS_BUFFER)Irp->MdlAddress,
1082 &DataBuffer,
1083 &BufferSize );
1084
1085 /* FIXME: DgramInfo->SendDatagramInformation->RemoteAddress
1086 must be of type PTDI_ADDRESS_IP */
1087 TI_DbgPrint(MID_TRACE,
1088 ("About to call send routine %x\n",
1089 (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)));
1090
1091 if( (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send != NULL) )
1092 {
1093 ULONG DataUsed = 0;
1094 Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)(
1095 Request.Handle.AddressHandle,
1096 DgramInfo->SendDatagramInformation,
1097 DataBuffer,
1098 BufferSize,
1099 &DataUsed);
1100 Irp->IoStatus.Information = DataUsed;
1101 }
1102 else {
1103 Status = STATUS_UNSUCCESSFUL;
1104 ASSERT(FALSE);
1105 }
1106 }
1107
1108 done:
1109 if (Status != STATUS_PENDING) {
1110 DispDataRequestComplete(Irp, Status, Irp->IoStatus.Information);
1111 } else
1112 IoMarkIrpPending(Irp);
1113
1114 TI_DbgPrint(DEBUG_IRP, ("Leaving.\n"));
1115
1116 return Status;
1117 }
1118
1119
1120 NTSTATUS DispTdiSetEventHandler(PIRP Irp)
1121 /*
1122 * FUNCTION: TDI_SET_EVENT_HANDER handler
1123 * ARGUMENTS:
1124 * Irp = Pointer to a I/O request packet
1125 * RETURNS:
1126 * Status of operation
1127 */
1128 {
1129 PTDI_REQUEST_KERNEL_SET_EVENT Parameters;
1130 PTRANSPORT_CONTEXT TranContext;
1131 PIO_STACK_LOCATION IrpSp;
1132 PADDRESS_FILE AddrFile;
1133 NTSTATUS Status;
1134 KIRQL OldIrql;
1135
1136 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1137
1138 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1139
1140 /* Get associated address file object. Quit if none exists */
1141
1142 TranContext = IrpSp->FileObject->FsContext;
1143 if (!TranContext) {
1144 TI_DbgPrint(MIN_TRACE, ("Bad transport context.\n"));
1145 return STATUS_INVALID_PARAMETER;
1146 }
1147
1148 AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
1149 if (!AddrFile) {
1150 TI_DbgPrint(MIN_TRACE, ("No address file object.\n"));
1151 return STATUS_INVALID_PARAMETER;
1152 }
1153
1154 Parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters;
1155 Status = STATUS_SUCCESS;
1156
1157 LockObject(AddrFile, &OldIrql);
1158
1159 /* Set the event handler. if an event handler is associated with
1160 a specific event, it's flag (RegisteredXxxHandler) is TRUE.
1161 If an event handler is not used it's flag is FALSE */
1162 switch (Parameters->EventType) {
1163 case TDI_EVENT_CONNECT:
1164 if (!Parameters->EventHandler) {
1165 AddrFile->ConnectHandlerContext = NULL;
1166 AddrFile->RegisteredConnectHandler = FALSE;
1167 } else {
1168 AddrFile->ConnectHandler =
1169 (PTDI_IND_CONNECT)Parameters->EventHandler;
1170 AddrFile->ConnectHandlerContext = Parameters->EventContext;
1171 AddrFile->RegisteredConnectHandler = TRUE;
1172 }
1173 break;
1174
1175 case TDI_EVENT_DISCONNECT:
1176 if (!Parameters->EventHandler) {
1177 AddrFile->DisconnectHandlerContext = NULL;
1178 AddrFile->RegisteredDisconnectHandler = FALSE;
1179 } else {
1180 AddrFile->DisconnectHandler =
1181 (PTDI_IND_DISCONNECT)Parameters->EventHandler;
1182 AddrFile->DisconnectHandlerContext = Parameters->EventContext;
1183 AddrFile->RegisteredDisconnectHandler = TRUE;
1184 }
1185 break;
1186
1187 case TDI_EVENT_ERROR:
1188 if (Parameters->EventHandler == NULL) {
1189 AddrFile->ErrorHandlerContext = NULL;
1190 AddrFile->RegisteredErrorHandler = FALSE;
1191 } else {
1192 AddrFile->ErrorHandler =
1193 (PTDI_IND_ERROR)Parameters->EventHandler;
1194 AddrFile->ErrorHandlerContext = Parameters->EventContext;
1195 AddrFile->RegisteredErrorHandler = TRUE;
1196 }
1197 break;
1198
1199 case TDI_EVENT_RECEIVE:
1200 if (Parameters->EventHandler == NULL) {
1201 AddrFile->ReceiveHandlerContext = NULL;
1202 AddrFile->RegisteredReceiveHandler = FALSE;
1203 } else {
1204 AddrFile->ReceiveHandler =
1205 (PTDI_IND_RECEIVE)Parameters->EventHandler;
1206 AddrFile->ReceiveHandlerContext = Parameters->EventContext;
1207 AddrFile->RegisteredReceiveHandler = TRUE;
1208 }
1209 break;
1210
1211 case TDI_EVENT_RECEIVE_DATAGRAM:
1212 if (Parameters->EventHandler == NULL) {
1213 AddrFile->ReceiveDatagramHandlerContext = NULL;
1214 AddrFile->RegisteredReceiveDatagramHandler = FALSE;
1215 } else {
1216 AddrFile->ReceiveDatagramHandler =
1217 (PTDI_IND_RECEIVE_DATAGRAM)Parameters->EventHandler;
1218 AddrFile->ReceiveDatagramHandlerContext = Parameters->EventContext;
1219 AddrFile->RegisteredReceiveDatagramHandler = TRUE;
1220 }
1221 break;
1222
1223 case TDI_EVENT_RECEIVE_EXPEDITED:
1224 if (Parameters->EventHandler == NULL) {
1225 AddrFile->ExpeditedReceiveHandlerContext = NULL;
1226 AddrFile->RegisteredExpeditedReceiveHandler = FALSE;
1227 } else {
1228 AddrFile->ExpeditedReceiveHandler =
1229 (PTDI_IND_RECEIVE_EXPEDITED)Parameters->EventHandler;
1230 AddrFile->ExpeditedReceiveHandlerContext = Parameters->EventContext;
1231 AddrFile->RegisteredExpeditedReceiveHandler = TRUE;
1232 }
1233 break;
1234
1235 case TDI_EVENT_CHAINED_RECEIVE:
1236 if (Parameters->EventHandler == NULL) {
1237 AddrFile->ChainedReceiveHandlerContext = NULL;
1238 AddrFile->RegisteredChainedReceiveHandler = FALSE;
1239 } else {
1240 AddrFile->ChainedReceiveHandler =
1241 (PTDI_IND_CHAINED_RECEIVE)Parameters->EventHandler;
1242 AddrFile->ChainedReceiveHandlerContext = Parameters->EventContext;
1243 AddrFile->RegisteredChainedReceiveHandler = TRUE;
1244 }
1245 break;
1246
1247 case TDI_EVENT_CHAINED_RECEIVE_DATAGRAM:
1248 if (Parameters->EventHandler == NULL) {
1249 AddrFile->ChainedReceiveDatagramHandlerContext = NULL;
1250 AddrFile->RegisteredChainedReceiveDatagramHandler = FALSE;
1251 } else {
1252 AddrFile->ChainedReceiveDatagramHandler =
1253 (PTDI_IND_CHAINED_RECEIVE_DATAGRAM)Parameters->EventHandler;
1254 AddrFile->ChainedReceiveDatagramHandlerContext = Parameters->EventContext;
1255 AddrFile->RegisteredChainedReceiveDatagramHandler = TRUE;
1256 }
1257 break;
1258
1259 case TDI_EVENT_CHAINED_RECEIVE_EXPEDITED:
1260 if (Parameters->EventHandler == NULL) {
1261 AddrFile->ChainedReceiveExpeditedHandlerContext = NULL;
1262 AddrFile->RegisteredChainedReceiveExpeditedHandler = FALSE;
1263 } else {
1264 AddrFile->ChainedReceiveExpeditedHandler =
1265 (PTDI_IND_CHAINED_RECEIVE_EXPEDITED)Parameters->EventHandler;
1266 AddrFile->ChainedReceiveExpeditedHandlerContext = Parameters->EventContext;
1267 AddrFile->RegisteredChainedReceiveExpeditedHandler = TRUE;
1268 }
1269 break;
1270
1271 default:
1272 TI_DbgPrint(MIN_TRACE, ("Unknown event type (0x%X).\n",
1273 Parameters->EventType));
1274
1275 Status = STATUS_INVALID_PARAMETER;
1276 }
1277
1278 UnlockObject(AddrFile, OldIrql);
1279
1280 return Status;
1281 }
1282
1283
1284 NTSTATUS DispTdiSetInformation(
1285 PIRP Irp)
1286 /*
1287 * FUNCTION: TDI_SET_INFORMATION handler
1288 * ARGUMENTS:
1289 * Irp = Pointer to an I/O request packet
1290 * RETURNS:
1291 * Status of operation
1292 */
1293 {
1294 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1295
1296 return STATUS_NOT_IMPLEMENTED;
1297 }
1298
1299
1300 VOID DispTdiQueryInformationExComplete(
1301 PVOID Context,
1302 ULONG Status,
1303 UINT ByteCount)
1304 /*
1305 * FUNCTION: Completes a TDI QueryInformationEx request
1306 * ARGUMENTS:
1307 * Context = Pointer to the IRP for the request
1308 * Status = TDI status of the request
1309 * ByteCount = Number of bytes returned in output buffer
1310 */
1311 {
1312 PTI_QUERY_CONTEXT QueryContext;
1313
1314 QueryContext = (PTI_QUERY_CONTEXT)Context;
1315 if (NT_SUCCESS(Status)) {
1316 CopyBufferToBufferChain(
1317 QueryContext->InputMdl,
1318 FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context),
1319 (PCHAR)&QueryContext->QueryInfo.Context,
1320 CONTEXT_SIZE);
1321 }
1322
1323 MmUnlockPages(QueryContext->InputMdl);
1324 IoFreeMdl(QueryContext->InputMdl);
1325 if( QueryContext->OutputMdl ) {
1326 MmUnlockPages(QueryContext->OutputMdl);
1327 IoFreeMdl(QueryContext->OutputMdl);
1328 }
1329
1330 QueryContext->Irp->IoStatus.Information = ByteCount;
1331 QueryContext->Irp->IoStatus.Status = Status;
1332
1333 ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG);
1334 }
1335
1336
1337 NTSTATUS DispTdiQueryInformationEx(
1338 PIRP Irp,
1339 PIO_STACK_LOCATION IrpSp)
1340 /*
1341 * FUNCTION: TDI QueryInformationEx handler
1342 * ARGUMENTS:
1343 * Irp = Pointer to I/O request packet
1344 * IrpSp = Pointer to current stack location of Irp
1345 * RETURNS:
1346 * Status of operation
1347 */
1348 {
1349 PTCP_REQUEST_QUERY_INFORMATION_EX InputBuffer;
1350 PTRANSPORT_CONTEXT TranContext;
1351 PTI_QUERY_CONTEXT QueryContext;
1352 PVOID OutputBuffer;
1353 TDI_REQUEST Request;
1354 UINT Size;
1355 UINT InputBufferLength;
1356 UINT OutputBufferLength;
1357 BOOLEAN InputMdlLocked = FALSE;
1358 BOOLEAN OutputMdlLocked = FALSE;
1359 PMDL InputMdl = NULL;
1360 PMDL OutputMdl = NULL;
1361 NTSTATUS Status = STATUS_SUCCESS;
1362
1363 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1364
1365 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
1366
1367 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
1368 case TDI_TRANSPORT_ADDRESS_FILE:
1369 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
1370 break;
1371
1372 case TDI_CONNECTION_FILE:
1373 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
1374 break;
1375
1376 case TDI_CONTROL_CHANNEL_FILE:
1377 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
1378 break;
1379
1380 default:
1381 TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
1382 return STATUS_INVALID_PARAMETER;
1383 }
1384
1385 InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
1386 OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
1387
1388 /* Validate parameters */
1389 if ((InputBufferLength == sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)) &&
1390 (OutputBufferLength != 0)) {
1391
1392 InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
1393 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
1394 OutputBuffer = Irp->UserBuffer;
1395
1396 QueryContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(TI_QUERY_CONTEXT), QUERY_CONTEXT_TAG);
1397 if (QueryContext) {
1398 _SEH2_TRY {
1399 InputMdl = IoAllocateMdl(InputBuffer,
1400 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
1401 FALSE, TRUE, NULL);
1402
1403 OutputMdl = IoAllocateMdl(OutputBuffer,
1404 OutputBufferLength, FALSE, TRUE, NULL);
1405
1406 if (InputMdl && OutputMdl) {
1407
1408 MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
1409 IoModifyAccess);
1410
1411 InputMdlLocked = TRUE;
1412
1413 MmProbeAndLockPages(OutputMdl, Irp->RequestorMode,
1414 IoWriteAccess);
1415
1416 OutputMdlLocked = TRUE;
1417
1418 RtlCopyMemory(&QueryContext->QueryInfo,
1419 InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
1420 } else
1421 Status = STATUS_INSUFFICIENT_RESOURCES;
1422 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
1423 Status = _SEH2_GetExceptionCode();
1424 } _SEH2_END;
1425
1426 if (NT_SUCCESS(Status)) {
1427 Size = MmGetMdlByteCount(OutputMdl);
1428
1429 QueryContext->Irp = Irp;
1430 QueryContext->InputMdl = InputMdl;
1431 QueryContext->OutputMdl = OutputMdl;
1432
1433 Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
1434 Request.RequestContext = QueryContext;
1435 Status = InfoTdiQueryInformationEx(&Request,
1436 &QueryContext->QueryInfo.ID, OutputMdl,
1437 &Size, &QueryContext->QueryInfo.Context);
1438 DispTdiQueryInformationExComplete(QueryContext, Status, Size);
1439
1440 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1441
1442 return Status;
1443 }
1444
1445 /* An error occurred if we get here */
1446
1447 if (InputMdl) {
1448 if (InputMdlLocked)
1449 MmUnlockPages(InputMdl);
1450 IoFreeMdl(InputMdl);
1451 }
1452
1453 if (OutputMdl) {
1454 if (OutputMdlLocked)
1455 MmUnlockPages(OutputMdl);
1456 IoFreeMdl(OutputMdl);
1457 }
1458
1459 ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG);
1460 } else
1461 Status = STATUS_INSUFFICIENT_RESOURCES;
1462 } else if( InputBufferLength ==
1463 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX) ) {
1464 /* Handle the case where the user is probing the buffer for length */
1465 TI_DbgPrint(MAX_TRACE, ("InputBufferLength %d OutputBufferLength %d\n",
1466 InputBufferLength, OutputBufferLength));
1467 InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
1468 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
1469
1470 Size = 0;
1471
1472 QueryContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(TI_QUERY_CONTEXT), QUERY_CONTEXT_TAG);
1473 if (!QueryContext) return STATUS_INSUFFICIENT_RESOURCES;
1474
1475 _SEH2_TRY {
1476 InputMdl = IoAllocateMdl(InputBuffer,
1477 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
1478 FALSE, TRUE, NULL);
1479
1480 MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
1481 IoModifyAccess);
1482
1483 InputMdlLocked = TRUE;
1484 Status = STATUS_SUCCESS;
1485 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
1486 TI_DbgPrint(MAX_TRACE, ("Failed to acquire client buffer\n"));
1487 Status = _SEH2_GetExceptionCode();
1488 } _SEH2_END;
1489
1490 if( !NT_SUCCESS(Status) || !InputMdl ) {
1491 if( InputMdl ) IoFreeMdl( InputMdl );
1492 ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG);
1493 return Status;
1494 }
1495
1496 RtlCopyMemory(&QueryContext->QueryInfo,
1497 InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
1498
1499 QueryContext->Irp = Irp;
1500 QueryContext->InputMdl = InputMdl;
1501 QueryContext->OutputMdl = NULL;
1502
1503 Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
1504 Request.RequestContext = QueryContext;
1505 Status = InfoTdiQueryInformationEx(&Request,
1506 &QueryContext->QueryInfo.ID,
1507 NULL,
1508 &Size,
1509 &QueryContext->QueryInfo.Context);
1510 DispTdiQueryInformationExComplete(QueryContext, Status, Size);
1511 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1512 } else Status = STATUS_INVALID_PARAMETER;
1513
1514 TI_DbgPrint(MIN_TRACE, ("Leaving. Status = (0x%X)\n", Status));
1515
1516 return Status;
1517 }
1518
1519
1520 NTSTATUS DispTdiSetInformationEx(
1521 PIRP Irp,
1522 PIO_STACK_LOCATION IrpSp)
1523 /*
1524 * FUNCTION: TDI SetInformationEx handler
1525 * ARGUMENTS:
1526 * Irp = Pointer to I/O request packet
1527 * IrpSp = Pointer to current stack location of Irp
1528 * RETURNS:
1529 * Status of operation
1530 */
1531 {
1532 PTRANSPORT_CONTEXT TranContext;
1533 PTCP_REQUEST_SET_INFORMATION_EX Info;
1534 TDI_REQUEST Request;
1535 TDI_STATUS Status;
1536
1537 TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
1538
1539 TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
1540 Info = (PTCP_REQUEST_SET_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer;
1541
1542 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
1543 case TDI_TRANSPORT_ADDRESS_FILE:
1544 Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
1545 break;
1546
1547 case TDI_CONNECTION_FILE:
1548 Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
1549 break;
1550
1551 case TDI_CONTROL_CHANNEL_FILE:
1552 Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
1553 break;
1554
1555 default:
1556 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1557 Irp->IoStatus.Information = 0;
1558
1559 TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
1560
1561 return Irp->IoStatus.Status;
1562 }
1563
1564 Status = DispPrepareIrpForCancel(TranContext, Irp, NULL);
1565 if (NT_SUCCESS(Status)) {
1566 Request.RequestNotifyObject = DispDataRequestComplete;
1567 Request.RequestContext = Irp;
1568
1569 Status = InfoTdiSetInformationEx(&Request, &Info->ID,
1570 &Info->Buffer, Info->BufferSize);
1571 }
1572
1573 return Status;
1574 }
1575
1576 /* TODO: Support multiple addresses per interface.
1577 * For now just set the nte context to the interface index.
1578 *
1579 * Later on, create an NTE context and NTE instance
1580 */
1581
1582 NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
1583 NTSTATUS Status = STATUS_DEVICE_DOES_NOT_EXIST;
1584 PIP_SET_ADDRESS IpAddrChange =
1585 (PIP_SET_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
1586 IF_LIST_ITER(IF);
1587
1588 TI_DbgPrint(MID_TRACE,("Setting IP Address for adapter %d\n",
1589 IpAddrChange->NteIndex));
1590
1591 ForEachInterface(IF) {
1592 TI_DbgPrint(MID_TRACE,("Looking at adapter %d\n", IF->Index));
1593
1594 if( IF->Unicast.Address.IPv4Address == IpAddrChange->Address ) {
1595 Status = STATUS_DUPLICATE_OBJECTID;
1596 break;
1597 }
1598 if( IF->Index == IpAddrChange->NteIndex ) {
1599 IPRemoveInterfaceRoute( IF );
1600
1601 IF->Unicast.Type = IP_ADDRESS_V4;
1602 IF->Unicast.Address.IPv4Address = IpAddrChange->Address;
1603 IF->Netmask.Type = IP_ADDRESS_V4;
1604 IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask;
1605 IF->Broadcast.Type = IP_ADDRESS_V4;
1606 IF->Broadcast.Address.IPv4Address =
1607 IF->Unicast.Address.IPv4Address |
1608 ~IF->Netmask.Address.IPv4Address;
1609
1610 TI_DbgPrint(MID_TRACE,("New Unicast Address: %x\n",
1611 IF->Unicast.Address.IPv4Address));
1612 TI_DbgPrint(MID_TRACE,("New Netmask : %x\n",
1613 IF->Netmask.Address.IPv4Address));
1614
1615 IPAddInterfaceRoute( IF );
1616
1617 IpAddrChange->Address = IF->Index;
1618 Status = STATUS_SUCCESS;
1619 Irp->IoStatus.Information = IF->Index;
1620 break;
1621 }
1622 } EndFor(IF);
1623
1624 Irp->IoStatus.Status = Status;
1625 return Status;
1626 }
1627
1628 NTSTATUS DispTdiDeleteIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
1629 NTSTATUS Status = STATUS_UNSUCCESSFUL;
1630 PUSHORT NteIndex = Irp->AssociatedIrp.SystemBuffer;
1631 IF_LIST_ITER(IF);
1632
1633 ForEachInterface(IF) {
1634 if( IF->Index == *NteIndex ) {
1635 IPRemoveInterfaceRoute( IF );
1636 IF->Unicast.Type = IP_ADDRESS_V4;
1637 IF->Unicast.Address.IPv4Address = 0;
1638 IF->Netmask.Type = IP_ADDRESS_V4;
1639 IF->Netmask.Address.IPv4Address = 0;
1640 IF->Broadcast.Type = IP_ADDRESS_V4;
1641 IF->Broadcast.Address.IPv4Address = 0;
1642 Status = STATUS_SUCCESS;
1643 }
1644 } EndFor(IF);
1645
1646 Irp->IoStatus.Status = Status;
1647 return Status;
1648 }
1649
1650 /* EOF */