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