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