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