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