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