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