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