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