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