remove whitespace from end of lines
[reactos.git] / reactos / drivers / net / afd / afd / tdi.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Ancillary Function Driver
4 * FILE: afd/tdi.c
5 * PURPOSE: Transport Driver Interface functions
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/09-2000 Created
9 */
10 #include <afd.h>
11 #ifndef _MSC_VER
12 #include <pseh.h>
13 #endif
14 #include "debug.h"
15 #include "tdiconn.h"
16
17 #ifdef DBG
18 VOID DisplayBuffer(
19 PVOID Buffer,
20 ULONG Size)
21 {
22 ULONG i;
23 PCHAR p;
24
25 if ((DebugTraceLevel & MAX_TRACE) == 0)
26 return;
27
28 if (!Buffer) {
29 AFD_DbgPrint(MIN_TRACE, ("Cannot display null buffer.\n"));
30 return;
31 }
32
33 AFD_DbgPrint(MIN_TRACE, ("Displaying buffer at (0x%X) Size (%d).\n", Buffer, Size));
34
35 p = (PCHAR)Buffer;
36 for (i = 0; i < Size; i++) {
37 if (i % 16 == 0)
38 DbgPrint("\n");
39 DbgPrint("%02X ", (p[i]) & 0xFF);
40 }
41 DbgPrint("\n");
42 }
43 #endif /* DBG */
44
45 NTSTATUS TdiCall(
46 PIRP Irp,
47 PDEVICE_OBJECT DeviceObject,
48 PKEVENT Event,
49 PIO_STATUS_BLOCK Iosb)
50 /*
51 * FUNCTION: Calls a transport driver device
52 * ARGUMENTS:
53 * Irp = Pointer to I/O Request Packet
54 * DeviceObject = Pointer to device object to call
55 * Event = An optional pointer to an event handle that will be
56 * waited upon
57 * Iosb = Pointer to an IO status block
58 * RETURNS:
59 * Status of operation
60 */
61 {
62 NTSTATUS Status;
63
64 AFD_DbgPrint(MID_TRACE, ("Called\n"));
65
66 AFD_DbgPrint(MID_TRACE, ("Irp->UserEvent = %x\n", Irp->UserEvent));
67
68 Status = IoCallDriver(DeviceObject, Irp);
69 AFD_DbgPrint(MID_TRACE, ("IoCallDriver: %08x\n", Status));
70
71 if ((Status == STATUS_PENDING) && (Event != NULL)) {
72 AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
73 KeWaitForSingleObject(
74 Event,
75 Executive,
76 UserMode,
77 FALSE,
78 NULL);
79 Status = Iosb->Status;
80 }
81
82 AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
83
84 return Status;
85 }
86
87
88 NTSTATUS TdiOpenDevice(
89 PUNICODE_STRING DeviceName,
90 ULONG EaLength,
91 PFILE_FULL_EA_INFORMATION EaInfo,
92 PHANDLE Handle,
93 PFILE_OBJECT *Object)
94 /*
95 * FUNCTION: Opens a device
96 * ARGUMENTS:
97 * DeviceName = Pointer to counted string with name of device
98 * EaLength = Length of EA information
99 * EaInfo = Pointer to buffer with EA information
100 * Handle = Address of buffer to place device handle
101 * Object = Address of buffer to place device object
102 * RETURNS:
103 * Status of operation
104 */
105 {
106 OBJECT_ATTRIBUTES Attr;
107 IO_STATUS_BLOCK Iosb;
108 NTSTATUS Status;
109
110 AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ)\n", DeviceName));
111
112 InitializeObjectAttributes(&Attr, /* Attribute buffer */
113 DeviceName, /* Device name */
114 OBJ_CASE_INSENSITIVE, /* Attributes */
115 NULL, /* Root directory */
116 NULL); /* Security descriptor */
117
118 Status = ZwCreateFile(Handle, /* Return file handle */
119 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, /* Desired access */
120 &Attr, /* Object attributes */
121 &Iosb, /* IO status */
122 0, /* Initial allocation size */
123 FILE_ATTRIBUTE_NORMAL, /* File attributes */
124 FILE_SHARE_READ | FILE_SHARE_WRITE, /* Share access */
125 FILE_OPEN_IF, /* Create disposition */
126 0, /* Create options */
127 EaInfo, /* EA buffer */
128 EaLength); /* EA length */
129 if (NT_SUCCESS(Status)) {
130 Status = ObReferenceObjectByHandle(*Handle, /* Handle to open file */
131 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, /* Access mode */
132 NULL, /* Object type */
133 KernelMode, /* Access mode */
134 (PVOID*)Object, /* Pointer to object */
135 NULL); /* Handle information */
136 if (!NT_SUCCESS(Status)) {
137 AFD_DbgPrint(MIN_TRACE, ("ObReferenceObjectByHandle() failed with status (0x%X).\n", Status));
138 ZwClose(*Handle);
139 } else {
140 AFD_DbgPrint(MAX_TRACE, ("Got handle (0x%X) Object (0x%X)\n",
141 *Handle, *Object));
142 }
143 } else {
144 AFD_DbgPrint(MIN_TRACE, ("ZwCreateFile() failed with status (0x%X)\n", Status));
145 }
146
147 return Status;
148 }
149
150
151 NTSTATUS TdiCloseDevice(
152 HANDLE Handle,
153 PFILE_OBJECT FileObject)
154 {
155 AFD_DbgPrint(MAX_TRACE, ("Called. Handle (0x%X) FileObject (0x%X)\n",
156 Handle, FileObject));
157
158 if (Handle)
159 ZwClose(Handle);
160
161 if (FileObject)
162 ObDereferenceObject(FileObject);
163
164 return STATUS_SUCCESS;
165 }
166
167
168 NTSTATUS TdiOpenAddressFile(
169 PUNICODE_STRING DeviceName,
170 PTRANSPORT_ADDRESS Name,
171 PHANDLE AddressHandle,
172 PFILE_OBJECT *AddressObject)
173 /*
174 * FUNCTION: Opens an IPv4 address file object
175 * ARGUMENTS:
176 * DeviceName = Pointer to counted string with name of device
177 * Name = Pointer to socket name (IPv4 address family)
178 * AddressHandle = Address of buffer to place address file handle
179 * AddressObject = Address of buffer to place address file object
180 * RETURNS:
181 * Status of operation
182 */
183 {
184 PFILE_FULL_EA_INFORMATION EaInfo;
185 NTSTATUS Status;
186 ULONG EaLength;
187 PTRANSPORT_ADDRESS Address;
188
189 AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ) Name (0x%X)\n",
190 DeviceName, Name));
191
192 /* EaName must be 0-terminated, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
193 EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
194 TDI_TRANSPORT_ADDRESS_LENGTH +
195 TaLengthOfTransportAddress( Name ) + 1;
196 EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength);
197 if (!EaInfo)
198 return STATUS_INSUFFICIENT_RESOURCES;
199
200 RtlZeroMemory(EaInfo, EaLength);
201 EaInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
202 /* Don't copy the terminating 0; we have already zeroed it */
203 RtlCopyMemory(EaInfo->EaName,
204 TdiTransportAddress,
205 TDI_TRANSPORT_ADDRESS_LENGTH);
206 EaInfo->EaValueLength = sizeof(TA_IP_ADDRESS);
207 Address =
208 (PTRANSPORT_ADDRESS)(EaInfo->EaName + TDI_TRANSPORT_ADDRESS_LENGTH + 1); /* 0-terminated */
209 TaCopyTransportAddressInPlace( Address, Name );
210
211 Status = TdiOpenDevice(DeviceName,
212 EaLength,
213 EaInfo,
214 AddressHandle,
215 AddressObject);
216 ExFreePool(EaInfo);
217 return Status;
218 }
219
220
221 NTSTATUS TdiOpenConnectionEndpointFile(
222 PUNICODE_STRING DeviceName,
223 PHANDLE ConnectionHandle,
224 PFILE_OBJECT *ConnectionObject)
225 /*
226 * FUNCTION: Opens a connection endpoint file object
227 * ARGUMENTS:
228 * DeviceName = Pointer to counted string with name of device
229 * ConnectionHandle = Address of buffer to place connection endpoint file handle
230 * ConnectionObject = Address of buffer to place connection endpoint file object
231 * RETURNS:
232 * Status of operation
233 */
234 {
235 PFILE_FULL_EA_INFORMATION EaInfo;
236 PVOID *ContextArea;
237 NTSTATUS Status;
238 ULONG EaLength;
239
240 AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ)\n", DeviceName));
241
242 /* EaName must be 0-terminated, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
243 EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
244 TDI_CONNECTION_CONTEXT_LENGTH +
245 sizeof(PVOID) + 1;
246
247 EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength);
248 if (!EaInfo)
249 return STATUS_INSUFFICIENT_RESOURCES;
250
251 RtlZeroMemory(EaInfo, EaLength);
252 EaInfo->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
253 /* Don't copy the terminating 0; we have already zeroed it */
254 RtlCopyMemory(EaInfo->EaName,
255 TdiConnectionContext,
256 TDI_CONNECTION_CONTEXT_LENGTH);
257 EaInfo->EaValueLength = sizeof(PVOID);
258 ContextArea = (PVOID*)(EaInfo->EaName + TDI_CONNECTION_CONTEXT_LENGTH + 1); /* 0-terminated */
259 /* FIXME: Allocate context area */
260 *ContextArea = NULL;
261 Status = TdiOpenDevice(DeviceName,
262 EaLength,
263 EaInfo,
264 ConnectionHandle,
265 ConnectionObject);
266 ExFreePool(EaInfo);
267 return Status;
268 }
269
270
271 NTSTATUS TdiConnect(
272 PIRP *Irp,
273 PFILE_OBJECT ConnectionObject,
274 PTDI_CONNECTION_INFORMATION RemoteAddress,
275 PIO_STATUS_BLOCK Iosb,
276 PIO_COMPLETION_ROUTINE CompletionRoutine,
277 PVOID CompletionContext)
278 /*
279 * FUNCTION: Connect a connection endpoint to a remote peer
280 * ARGUMENTS:
281 * ConnectionObject = Pointer to connection endpoint file object
282 * RemoteAddress = Pointer to remote address
283 * RETURNS:
284 * Status of operation
285 */
286 {
287 PDEVICE_OBJECT DeviceObject;
288 NTSTATUS Status;
289
290 AFD_DbgPrint(MAX_TRACE, ("Called\n"));
291
292 assert(ConnectionObject);
293
294 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
295
296 *Irp = TdiBuildInternalDeviceControlIrp(TDI_CONNECT, /* Sub function */
297 DeviceObject, /* Device object */
298 ConnectionObject, /* File object */
299 NULL, /* Event */
300 Iosb); /* Status */
301 if (!*Irp) {
302 return STATUS_INSUFFICIENT_RESOURCES;
303 }
304
305 TdiBuildConnect(*Irp, /* IRP */
306 DeviceObject, /* Device object */
307 ConnectionObject, /* File object */
308 CompletionRoutine, /* Completion routine */
309 CompletionContext, /* Completion routine context */
310 NULL, /* Time */
311 RemoteAddress, /* Request connection information */
312 RemoteAddress); /* Return connection information */
313
314 Status = TdiCall(*Irp, DeviceObject, NULL, Iosb);
315
316 return Status;
317 }
318
319
320 NTSTATUS TdiAssociateAddressFile(
321 HANDLE AddressHandle,
322 PFILE_OBJECT ConnectionObject)
323 /*
324 * FUNCTION: Associates a connection endpoint to an address file object
325 * ARGUMENTS:
326 * AddressHandle = Handle to address file object
327 * ConnectionObject = Connection endpoint file object
328 * RETURNS:
329 * Status of operation
330 */
331 {
332 PDEVICE_OBJECT DeviceObject;
333 IO_STATUS_BLOCK Iosb;
334 NTSTATUS Status;
335 KEVENT Event;
336 PIRP Irp;
337
338 AFD_DbgPrint(MAX_TRACE, ("Called. AddressHandle (0x%X) ConnectionObject (0x%X)\n",
339 AddressHandle, ConnectionObject));
340
341 assert(ConnectionObject);
342
343 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
344
345 KeInitializeEvent(&Event, NotificationEvent, FALSE);
346
347 Irp = TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS, /* Sub function */
348 DeviceObject, /* Device object */
349 ConnectionObject, /* File object */
350 &Event, /* Event */
351 &Iosb); /* Status */
352 if (!Irp)
353 return STATUS_INSUFFICIENT_RESOURCES;
354
355 TdiBuildAssociateAddress(Irp,
356 DeviceObject,
357 ConnectionObject,
358 NULL,
359 NULL,
360 AddressHandle);
361
362 Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
363
364 return Status;
365 }
366
367
368 NTSTATUS TdiListen
369 ( PIRP *Irp,
370 PFILE_OBJECT ConnectionObject,
371 PTDI_CONNECTION_INFORMATION *RequestConnectionInfo,
372 PTDI_CONNECTION_INFORMATION *ReturnConnectionInfo,
373 PIO_STATUS_BLOCK Iosb,
374 PIO_COMPLETION_ROUTINE CompletionRoutine,
375 PVOID CompletionContext)
376 /*
377 * FUNCTION: Listen on a connection endpoint for a connection request from a remote peer
378 * ARGUMENTS:
379 * CompletionRoutine = Routine to be called when IRP is completed
380 * CompletionContext = Context for CompletionRoutine
381 * RETURNS:
382 * Status of operation
383 * May return STATUS_PENDING
384 */
385 {
386 PDEVICE_OBJECT DeviceObject;
387 NTSTATUS Status;
388
389 AFD_DbgPrint(MAX_TRACE, ("Called\n"));
390
391 DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
392
393 Status = TdiBuildNullConnectionInfo(RequestConnectionInfo,
394 TDI_ADDRESS_TYPE_IP);
395 if (!NT_SUCCESS(Status))
396 return Status;
397
398 *Irp = TdiBuildInternalDeviceControlIrp(TDI_LISTEN, /* Sub function */
399 DeviceObject, /* Device object */
400 ConnectionObject, /* File object */
401 NULL, /* Event */
402 Iosb); /* Status */
403 if (*Irp == NULL)
404 {
405 ExFreePool(*RequestConnectionInfo);
406 return STATUS_INSUFFICIENT_RESOURCES;
407 }
408
409 TdiBuildListen(*Irp, /* IRP */
410 DeviceObject, /* Device object */
411 ConnectionObject, /* File object */
412 CompletionRoutine, /* Completion routine */
413 CompletionContext, /* Completion routine context */
414 0, /* Flags */
415 *RequestConnectionInfo, /* Request connection information */
416 *ReturnConnectionInfo); /* Return connection information */
417
418 Status = TdiCall(*Irp, DeviceObject, NULL /* Don't wait for completion */, Iosb);
419
420 return Status;
421 }
422
423
424 NTSTATUS TdiSetEventHandler(
425 PFILE_OBJECT FileObject,
426 LONG EventType,
427 PVOID Handler,
428 PVOID Context)
429 /*
430 * FUNCTION: Sets or resets an event handler
431 * ARGUMENTS:
432 * FileObject = Pointer to file object
433 * EventType = Event code
434 * Handler = Event handler to be called when the event occurs
435 * Context = Context input to handler when the event occurs
436 * RETURNS:
437 * Status of operation
438 * NOTES:
439 * Specify NULL for Handler to stop calling event handler
440 */
441 {
442 PDEVICE_OBJECT DeviceObject;
443 IO_STATUS_BLOCK Iosb;
444 NTSTATUS Status;
445 KEVENT Event;
446 PIRP Irp;
447
448 AFD_DbgPrint(MAX_TRACE, ("Called\n"));
449
450 assert(FileObject);
451
452 DeviceObject = IoGetRelatedDeviceObject(FileObject);
453
454 KeInitializeEvent(&Event, NotificationEvent, FALSE);
455
456 Irp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, /* Sub function */
457 DeviceObject, /* Device object */
458 FileObject, /* File object */
459 &Event, /* Event */
460 &Iosb); /* Status */
461 if (!Irp)
462 return STATUS_INSUFFICIENT_RESOURCES;
463
464
465
466 TdiBuildSetEventHandler(Irp,
467 DeviceObject,
468 FileObject,
469 NULL,
470 NULL,
471 EventType,
472 Handler,
473 Context);
474
475 Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
476
477 return Status;
478 }
479
480
481 NTSTATUS TdiQueryDeviceControl(
482 PFILE_OBJECT FileObject,
483 ULONG IoControlCode,
484 PVOID InputBuffer,
485 ULONG InputBufferLength,
486 PVOID OutputBuffer,
487 ULONG OutputBufferLength,
488 PULONG Return)
489 /*
490 * FUNCTION: Queries a device for information
491 * ARGUMENTS:
492 * FileObject = Pointer to file object
493 * IoControlCode = I/O control code
494 * InputBuffer = Pointer to buffer with input data
495 * InputBufferLength = Length of InputBuffer
496 * OutputBuffer = Address of buffer to place output data
497 * OutputBufferLength = Length of OutputBuffer
498 * RETURNS:
499 * Status of operation
500 */
501 {
502 PDEVICE_OBJECT DeviceObject;
503 IO_STATUS_BLOCK Iosb;
504 NTSTATUS Status;
505 KEVENT Event;
506 PIRP Irp;
507
508 DeviceObject = IoGetRelatedDeviceObject(FileObject);
509
510 KeInitializeEvent(&Event, NotificationEvent, FALSE);
511
512 Irp = IoBuildDeviceIoControlRequest(IoControlCode,
513 DeviceObject,
514 InputBuffer,
515 InputBufferLength,
516 OutputBuffer,
517 OutputBufferLength,
518 FALSE,
519 &Event,
520 &Iosb);
521 if (!Irp)
522 return STATUS_INSUFFICIENT_RESOURCES;
523
524 Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
525
526 if (Return)
527 *Return = Iosb.Information;
528
529 return Status;
530 }
531
532
533 NTSTATUS TdiQueryInformation(
534 PFILE_OBJECT FileObject,
535 LONG QueryType,
536 PMDL MdlBuffer)
537 /*
538 * FUNCTION: Query for information
539 * ARGUMENTS:
540 * FileObject = Pointer to file object
541 * QueryType = Query type
542 * MdlBuffer = Pointer to MDL buffer specific for query type
543 * RETURNS:
544 * Status of operation
545 */
546 {
547 PDEVICE_OBJECT DeviceObject;
548 IO_STATUS_BLOCK Iosb;
549 NTSTATUS Status;
550 KEVENT Event;
551 PIRP Irp;
552
553 DeviceObject = IoGetRelatedDeviceObject(FileObject);
554
555 KeInitializeEvent(&Event, NotificationEvent, FALSE);
556
557 Irp = TdiBuildInternalDeviceControlIrp(IOCTL_TCP_QUERY_INFORMATION, /* Sub function */
558 DeviceObject, /* Device object */
559 ConnectionObject, /* File object */
560 &Event, /* Event */
561 &Iosb); /* Status */
562 if (!Irp) {
563 return STATUS_INSUFFICIENT_RESOURCES;
564 }
565
566 TdiBuildQueryInformation(
567 Irp,
568 DeviceObject,
569 FileObject,
570 NULL,
571 NULL,
572 QueryType,
573 MdlBuffer);
574
575 Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
576
577 return Status;
578 }
579
580 #if 0
581 NTSTATUS TdiQueryInformationEx(
582 PFILE_OBJECT FileObject,
583 ULONG Entity,
584 ULONG Instance,
585 ULONG Class,
586 ULONG Type,
587 ULONG Id,
588 PVOID OutputBuffer,
589 PULONG OutputLength)
590 /*
591 * FUNCTION: Extended query for information
592 * ARGUMENTS:
593 * FileObject = Pointer to file object
594 * Entity = Entity
595 * Instance = Instance
596 * Class = Entity class
597 * Type = Entity type
598 * Id = Entity id
599 * OutputBuffer = Address of buffer to place data
600 * OutputLength = Address of buffer with length of OutputBuffer (updated)
601 * RETURNS:
602 * Status of operation
603 */
604 {
605 TCP_REQUEST_QUERY_INFORMATION_EX QueryInfo;
606
607 RtlZeroMemory(&QueryInfo, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
608 QueryInfo.ID.toi_entity.tei_entity = Entity;
609 QueryInfo.ID.toi_entity.tei_instance = Instance;
610 QueryInfo.ID.toi_class = Class;
611 QueryInfo.ID.toi_type = Type;
612 QueryInfo.ID.toi_id = Id;
613
614 return TdiQueryDeviceControl(FileObject, /* Transport/connection object */
615 IOCTL_TCP_QUERY_INFORMATION_EX, /* Control code */
616 &QueryInfo, /* Input buffer */
617 sizeof(TCP_REQUEST_QUERY_INFORMATION_EX), /* Input buffer length */
618 OutputBuffer, /* Output buffer */
619 *OutputLength, /* Output buffer length */
620 OutputLength); /* Return information */
621 }
622
623 NTSTATUS TdiQueryAddress(
624 PFILE_OBJECT FileObject,
625 PULONG Address)
626 /*
627 * FUNCTION: Queries for a local IP address
628 * ARGUMENTS:
629 * FileObject = Pointer to file object
630 * Address = Address of buffer to place local address
631 * RETURNS:
632 * Status of operation
633 */
634 {
635 UINT i;
636 TDIEntityID *Entities;
637 ULONG EntityCount;
638 ULONG EntityType;
639 IPSNMP_INFO SnmpInfo;
640 PIPADDR_ENTRY IpAddress;
641 ULONG BufferSize;
642 NTSTATUS Status = STATUS_SUCCESS;
643
644 AFD_DbgPrint(MAX_TRACE, ("Called\n"));
645
646 BufferSize = sizeof(TDIEntityID) * 20;
647 Entities = (TDIEntityID*)ExAllocatePool(NonPagedPool, BufferSize);
648 if (!Entities) {
649 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
650 return STATUS_INSUFFICIENT_RESOURCES;
651 }
652
653 /* Query device for supported entities */
654
655 Status = TdiQueryInformationEx(FileObject, /* File object */
656 GENERIC_ENTITY, /* Entity */
657 TL_INSTANCE, /* Instance */
658 INFO_CLASS_GENERIC, /* Entity class */
659 INFO_TYPE_PROVIDER, /* Entity type */
660 ENTITY_LIST_ID, /* Entity id */
661 Entities, /* Output buffer */
662 &BufferSize); /* Output buffer size */
663 if (!NT_SUCCESS(Status)) {
664 AFD_DbgPrint(MIN_TRACE, ("Unable to get list of supported entities (Status = 0x%X).\n", Status));
665 ExFreePool(Entities);
666 return Status;
667 }
668
669 /* Locate an IP entity */
670 EntityCount = BufferSize / sizeof(TDIEntityID);
671
672 AFD_DbgPrint(MAX_TRACE, ("EntityCount = %d\n", EntityCount));
673
674 for (i = 0; i < EntityCount; i++) {
675 if (Entities[i].tei_entity == CL_NL_ENTITY) {
676 /* Query device for entity type */
677
678 BufferSize = sizeof(EntityType);
679 Status = TdiQueryInformationEx(FileObject, /* File object */
680 CL_NL_ENTITY, /* Entity */
681 Entities[i].tei_instance, /* Instance */
682 INFO_CLASS_GENERIC, /* Entity class */
683 INFO_TYPE_PROVIDER, /* Entity type */
684 ENTITY_TYPE_ID, /* Entity id */
685 &EntityType, /* Output buffer */
686 &BufferSize); /* Output buffer size */
687 if (!NT_SUCCESS(Status) || (EntityType != CL_NL_IP)) {
688 AFD_DbgPrint(MIN_TRACE, ("Unable to get entity of type IP (Status = 0x%X).\n", Status));
689 break;
690 }
691
692 /* Query device for SNMP information */
693
694 BufferSize = sizeof(SnmpInfo);
695 Status = TdiQueryInformationEx(FileObject, /* File object */
696 CL_NL_ENTITY, /* Entity */
697 Entities[i].tei_instance, /* Instance */
698 INFO_CLASS_PROTOCOL, /* Entity class */
699 INFO_TYPE_PROVIDER, /* Entity type */
700 IP_MIB_STATS_ID, /* Entity id */
701 &SnmpInfo, /* Output buffer */
702 &BufferSize); /* Output buffer size */
703 if (!NT_SUCCESS(Status) || (SnmpInfo.NumAddr == 0)) {
704 AFD_DbgPrint(MIN_TRACE, ("Unable to get SNMP information or no IP addresses available (Status = 0x%X).\n", Status));
705 break;
706 }
707
708 /* Query device for all IP addresses */
709
710 if (SnmpInfo.NumAddr != 0) {
711 BufferSize = SnmpInfo.NumAddr * sizeof(IPADDR_ENTRY);
712 IpAddress = (PIPADDR_ENTRY)ExAllocatePool(NonPagedPool, BufferSize);
713 if (!IpAddress) {
714 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
715 break;
716 }
717
718 Status = TdiQueryInformationEx(FileObject, /* File object */
719 CL_NL_ENTITY, /* Entity */
720 Entities[i].tei_instance, /* Instance */
721 INFO_CLASS_PROTOCOL, /* Entity class */
722 INFO_TYPE_PROVIDER, /* Entity type */
723 IP_MIB_ADDRTABLE_ENTRY_ID, /* Entity id */
724 IpAddress, /* Output buffer */
725 &BufferSize); /* Output buffer size */
726 if (!NT_SUCCESS(Status)) {
727 AFD_DbgPrint(MIN_TRACE, ("Unable to get IP address (Status = 0x%X).\n", Status));
728 ExFreePool(IpAddress);
729 break;
730 }
731
732 if (SnmpInfo.NumAddr != 1) {
733 /* Skip loopback address */
734 PIPADDR_ENTRY IpAddressEntry = (PIPADDR_ENTRY)
735 ((PCHAR)IpAddress) + sizeof(IPADDR_ENTRY);
736 *Address = DN2H(IpAddressEntry->Addr);
737 } else {
738 /* Select the first address returned */
739 *Address = DN2H(IpAddress->Addr);
740 }
741
742 ExFreePool(IpAddress);
743 } else {
744 Status = STATUS_UNSUCCESSFUL;
745 break;
746 }
747 }
748 }
749
750 ExFreePool(Entities);
751
752 AFD_DbgPrint(MAX_TRACE, ("Leaving\n"));
753
754 return Status;
755 }
756 #endif
757
758 NTSTATUS TdiSend
759 ( PIRP *Irp,
760 PFILE_OBJECT TransportObject,
761 USHORT Flags,
762 PCHAR Buffer,
763 UINT BufferLength,
764 PIO_STATUS_BLOCK Iosb,
765 PIO_COMPLETION_ROUTINE CompletionRoutine,
766 PVOID CompletionContext )
767 {
768 PDEVICE_OBJECT DeviceObject;
769 NTSTATUS Status = STATUS_SUCCESS;
770 PMDL Mdl;
771
772 DeviceObject = IoGetRelatedDeviceObject(TransportObject);
773 if (!DeviceObject) {
774 AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
775 return STATUS_INVALID_PARAMETER;
776 }
777
778 *Irp = TdiBuildInternalDeviceControlIrp
779 ( TDI_SEND, /* Sub function */
780 DeviceObject, /* Device object */
781 TransportObject, /* File object */
782 NULL, /* Event */
783 Iosb ); /* Status */
784
785 if (!*Irp) {
786 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
787 return STATUS_INSUFFICIENT_RESOURCES;
788 }
789
790 AFD_DbgPrint(MID_TRACE, ("Allocating irp for %x:%d\n", Buffer,BufferLength));
791
792 Mdl = IoAllocateMdl(Buffer, /* Virtual address */
793 BufferLength, /* Length of buffer */
794 FALSE, /* Not secondary */
795 FALSE, /* Don't charge quota */
796 *Irp); /* use IRP */
797 if (!Mdl) {
798 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
799 IoFreeIrp(*Irp);
800 return STATUS_INSUFFICIENT_RESOURCES;
801 }
802
803 _SEH_TRY {
804 MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
805 } _SEH_HANDLE {
806 AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
807 IoFreeIrp(*Irp);
808 Status = STATUS_INSUFFICIENT_RESOURCES;
809 } _SEH_END;
810
811 if( !NT_SUCCESS(Status) ) {
812 IoFreeIrp(*Irp);
813 return Status;
814 }
815
816 AFD_DbgPrint(MID_TRACE,("AFD>>> Got an MDL: %x\n", Mdl));
817
818 TdiBuildSend(*Irp, /* I/O Request Packet */
819 DeviceObject, /* Device object */
820 TransportObject, /* File object */
821 CompletionRoutine, /* Completion routine */
822 CompletionContext, /* Completion context */
823 Mdl, /* Data buffer */
824 Flags, /* Flags */
825 BufferLength); /* Length of data */
826
827 Status = TdiCall(*Irp, DeviceObject, NULL, Iosb);
828 /* Does not block... The MDL is deleted in the receive completion
829 routine. */
830
831 return Status;
832 }
833
834 NTSTATUS TdiReceive(
835 PIRP *Irp,
836 PFILE_OBJECT TransportObject,
837 USHORT Flags,
838 PCHAR Buffer,
839 UINT BufferLength,
840 PIO_STATUS_BLOCK Iosb,
841 PIO_COMPLETION_ROUTINE CompletionRoutine,
842 PVOID CompletionContext)
843 {
844 NTSTATUS Status = STATUS_SUCCESS;
845 PDEVICE_OBJECT DeviceObject;
846 PMDL Mdl;
847
848 DeviceObject = IoGetRelatedDeviceObject(TransportObject);
849 if (!DeviceObject) {
850 AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
851 return STATUS_INVALID_PARAMETER;
852 }
853
854 *Irp = TdiBuildInternalDeviceControlIrp
855 ( TDI_RECEIVE, /* Sub function */
856 DeviceObject, /* Device object */
857 TransportObject, /* File object */
858 NULL, /* Event */
859 Iosb ); /* Status */
860
861 if (!*Irp) {
862 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
863 return STATUS_INSUFFICIENT_RESOURCES;
864 }
865
866 AFD_DbgPrint(MID_TRACE, ("Allocating irp for %x:%d\n", Buffer,BufferLength));
867
868 Mdl = IoAllocateMdl(Buffer, /* Virtual address */
869 BufferLength, /* Length of buffer */
870 FALSE, /* Not secondary */
871 FALSE, /* Don't charge quota */
872 *Irp); /* Don't use IRP */
873 if (!Mdl) {
874 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
875 IoFreeIrp(*Irp);
876 return STATUS_INSUFFICIENT_RESOURCES;
877 }
878
879 _SEH_TRY {
880 AFD_DbgPrint(MIN_TRACE, ("probe and lock\n"));
881 MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
882 AFD_DbgPrint(MIN_TRACE, ("probe and lock done\n"));
883 } _SEH_HANDLE {
884 AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
885 IoFreeIrp(*Irp);
886 Status = STATUS_INSUFFICIENT_RESOURCES;
887 } _SEH_END;
888
889 if( !NT_SUCCESS(Status) ) {
890 IoFreeIrp(*Irp);
891 return Status;
892 }
893
894 AFD_DbgPrint(MID_TRACE,("AFD>>> Got an MDL: %x\n", Mdl));
895
896 TdiBuildReceive(*Irp, /* I/O Request Packet */
897 DeviceObject, /* Device object */
898 TransportObject, /* File object */
899 CompletionRoutine, /* Completion routine */
900 CompletionContext, /* Completion context */
901 Mdl, /* Data buffer */
902 Flags, /* Flags */
903 BufferLength); /* Length of data */
904
905
906 Status = TdiCall(*Irp, DeviceObject, NULL, Iosb);
907 /* Does not block... The MDL is deleted in the receive completion
908 routine. */
909
910 AFD_DbgPrint(MID_TRACE,("Status %x Information %d\n",
911 Status, Iosb->Information));
912
913 return Status;
914 }
915
916
917 NTSTATUS TdiReceiveDatagram(
918 PIRP *Irp,
919 PFILE_OBJECT TransportObject,
920 USHORT Flags,
921 PCHAR Buffer,
922 UINT BufferLength,
923 PTDI_CONNECTION_INFORMATION Addr,
924 PIO_STATUS_BLOCK Iosb,
925 PIO_COMPLETION_ROUTINE CompletionRoutine,
926 PVOID CompletionContext)
927 /*
928 * FUNCTION: Receives a datagram
929 * ARGUMENTS:
930 * TransportObject = Pointer to transport object
931 * From = Receive filter (NULL if none)
932 * Address = Address of buffer to place remote address
933 * Buffer = Address of buffer to place received data
934 * BufferSize = Address of buffer with length of Buffer (updated)
935 * RETURNS:
936 * Status of operation
937 */
938 {
939 PDEVICE_OBJECT DeviceObject;
940 NTSTATUS Status;
941 PMDL Mdl;
942
943 DeviceObject = IoGetRelatedDeviceObject(TransportObject);
944 if (!DeviceObject) {
945 AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
946 return STATUS_INVALID_PARAMETER;
947 }
948
949 *Irp = TdiBuildInternalDeviceControlIrp
950 ( TDI_RECEIVE_DATAGRAM, /* Sub function */
951 DeviceObject, /* Device object */
952 TransportObject, /* File object */
953 NULL, /* Event */
954 Iosb ); /* Status */
955
956 if (!*Irp) {
957 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
958 return STATUS_INSUFFICIENT_RESOURCES;
959 }
960
961 AFD_DbgPrint(MID_TRACE, ("Allocating irp for %x:%d\n", Buffer,BufferLength));
962
963 Mdl = IoAllocateMdl(Buffer, /* Virtual address */
964 BufferLength, /* Length of buffer */
965 FALSE, /* Not secondary */
966 FALSE, /* Don't charge quota */
967 *Irp); /* Don't use IRP */
968 if (!Mdl) {
969 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
970 IoFreeIrp(*Irp);
971 return STATUS_INSUFFICIENT_RESOURCES;
972 }
973
974 _SEH_TRY {
975 MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
976 } _SEH_HANDLE {
977 AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
978 IoFreeIrp(*Irp);
979 return STATUS_INSUFFICIENT_RESOURCES;
980 } _SEH_END;
981
982 AFD_DbgPrint(MID_TRACE,("AFD>>> Got an MDL: %x\n", Mdl));
983
984 TdiBuildReceiveDatagram
985 (*Irp, /* I/O Request Packet */
986 DeviceObject, /* Device object */
987 TransportObject, /* File object */
988 CompletionRoutine, /* Completion routine */
989 CompletionContext, /* Completion context */
990 Mdl, /* Data buffer */
991 BufferLength,
992 Addr,
993 Addr,
994 Flags); /* Length of data */
995
996 Status = TdiCall(*Irp, DeviceObject, NULL, Iosb);
997 /* Does not block... The MDL is deleted in the receive completion
998 routine. */
999
1000 return Status;
1001 }
1002
1003
1004 NTSTATUS TdiSendDatagram(
1005 PIRP *Irp,
1006 PFILE_OBJECT TransportObject,
1007 PCHAR Buffer,
1008 UINT BufferLength,
1009 PTDI_CONNECTION_INFORMATION Addr,
1010 PIO_STATUS_BLOCK Iosb,
1011 PIO_COMPLETION_ROUTINE CompletionRoutine,
1012 PVOID CompletionContext)
1013 /*
1014 * FUNCTION: Sends a datagram
1015 * ARGUMENTS:
1016 * TransportObject = Pointer to transport object
1017 * From = Send filter (NULL if none)
1018 * Address = Address of buffer to place remote address
1019 * Buffer = Address of buffer to place send data
1020 * BufferSize = Address of buffer with length of Buffer (updated)
1021 * RETURNS:
1022 * Status of operation
1023 */
1024 {
1025 PDEVICE_OBJECT DeviceObject;
1026 NTSTATUS Status;
1027 PMDL Mdl;
1028
1029 AFD_DbgPrint(MID_TRACE,("Called(TransportObject %x)\n", TransportObject));
1030
1031 DeviceObject = IoGetRelatedDeviceObject(TransportObject);
1032 if (!DeviceObject) {
1033 AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
1034 return STATUS_INVALID_PARAMETER;
1035 }
1036
1037 *Irp = TdiBuildInternalDeviceControlIrp
1038 ( TDI_SEND_DATAGRAM, /* Sub function */
1039 DeviceObject, /* Device object */
1040 TransportObject, /* File object */
1041 NULL, /* Event */
1042 Iosb ); /* Status */
1043
1044 if (!*Irp) {
1045 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1046 return STATUS_INSUFFICIENT_RESOURCES;
1047 }
1048
1049 AFD_DbgPrint(MID_TRACE, ("Allocating irp for %x:%d\n", Buffer,BufferLength));
1050
1051 Mdl = IoAllocateMdl(Buffer, /* Virtual address */
1052 BufferLength, /* Length of buffer */
1053 FALSE, /* Not secondary */
1054 FALSE, /* Don't charge quota */
1055 *Irp); /* Don't use IRP */
1056
1057 if (!Mdl) {
1058 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1059 IoFreeIrp(*Irp);
1060 return STATUS_INSUFFICIENT_RESOURCES;
1061 }
1062
1063 _SEH_TRY {
1064 MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
1065 } _SEH_HANDLE {
1066 AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
1067 IoFreeIrp(*Irp);
1068 return STATUS_INSUFFICIENT_RESOURCES;
1069 } _SEH_END;
1070
1071 AFD_DbgPrint(MID_TRACE,("AFD>>> Got an MDL: %x\n", Mdl));
1072
1073 TdiBuildSendDatagram
1074 (*Irp, /* I/O Request Packet */
1075 DeviceObject, /* Device object */
1076 TransportObject, /* File object */
1077 CompletionRoutine, /* Completion routine */
1078 CompletionContext, /* Completion context */
1079 Mdl, /* Data buffer */
1080 BufferLength, /* Bytes to send */
1081 Addr); /* Address */
1082
1083 Status = TdiCall(*Irp, DeviceObject, NULL, Iosb);
1084 /* Does not block... The MDL is deleted in the send completion
1085 routine. */
1086
1087 return Status;
1088 }
1089
1090 NTSTATUS TdiDisconnect(
1091 PFILE_OBJECT TransportObject,
1092 PLARGE_INTEGER Time,
1093 USHORT Flags,
1094 PIO_STATUS_BLOCK Iosb,
1095 PIO_COMPLETION_ROUTINE CompletionRoutine,
1096 PVOID CompletionContext,
1097 PTDI_CONNECTION_INFORMATION RequestConnectionInfo,
1098 PTDI_CONNECTION_INFORMATION ReturnConnectionInfo) {
1099 PDEVICE_OBJECT DeviceObject;
1100 NTSTATUS Status;
1101 KEVENT Event;
1102 PIRP Irp;
1103
1104 DeviceObject = IoGetRelatedDeviceObject(TransportObject);
1105
1106 KeInitializeEvent(&Event, NotificationEvent, FALSE);
1107
1108 AFD_DbgPrint(MID_TRACE,("Called(TransportObject %x)\n", TransportObject));
1109
1110 DeviceObject = IoGetRelatedDeviceObject(TransportObject);
1111 if (!DeviceObject) {
1112 AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
1113 return STATUS_INVALID_PARAMETER;
1114 }
1115
1116 Irp = TdiBuildInternalDeviceControlIrp
1117 ( TDI_SEND_DATAGRAM, /* Sub function */
1118 DeviceObject, /* Device object */
1119 TransportObject, /* File object */
1120 &Event, /* Event */
1121 Iosb ); /* Status */
1122
1123 if (!Irp) {
1124 AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
1125 return STATUS_INSUFFICIENT_RESOURCES;
1126 }
1127
1128 TdiBuildDisconnect
1129 (Irp, /* I/O Request Packet */
1130 DeviceObject, /* Device object */
1131 TransportObject, /* File object */
1132 CompletionRoutine, /* Completion routine */
1133 CompletionContext, /* Completion context */
1134 Time, /* Time */
1135 Flags, /* Disconnect flags */
1136 RequestConnectionInfo, /* Indication of who to disconnect */
1137 ReturnConnectionInfo); /* Indication of who disconnected */
1138
1139 Status = TdiCall(Irp, DeviceObject, &Event, Iosb);
1140
1141 return Status;
1142 }
1143
1144 /* EOF */