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