xref: /reactos/sdk/lib/tdilib/enum.c (revision b5218987)
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS TDI interface
4  * FILE:        enum.c
5  * PURPOSE:     TDI entity enumeration
6  */
7 
8 #include "precomp.h"
9 
10 #include "tdilib.h"
11 
12 /* A generic thing-getting function which interacts in the right way with
13  * TDI.  This may seem oblique, but I'm using it to reduce code and hopefully
14  * make this thing easier to debug.
15  *
16  * The things returned can be any of:
17  *   TDIEntityID
18  *   TDIObjectID
19  *   IFEntry
20  *   IPSNMPInfo
21  *   IPAddrEntry
22  *   IPInterfaceInfo
23  */
24 NTSTATUS tdiGetSetOfThings( HANDLE tcpFile,
25                             DWORD toiClass,
26                             DWORD toiType,
27                             DWORD toiId,
28                             DWORD teiEntity,
29                             DWORD teiInstance,
30                             DWORD fixedPart,
31                             DWORD entrySize,
32                             PVOID *tdiEntitySet,
33                             PDWORD numEntries ) {
34     TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
35     PVOID entitySet = 0;
36     NTSTATUS status = STATUS_SUCCESS;
37     DWORD allocationSizeForEntityArray = entrySize * MAX_TDI_ENTITIES;
38     IO_STATUS_BLOCK Iosb;
39 
40     req.ID.toi_class                = toiClass;
41     req.ID.toi_type                 = toiType;
42     req.ID.toi_id                   = toiId;
43     req.ID.toi_entity.tei_entity    = teiEntity;
44     req.ID.toi_entity.tei_instance  = teiInstance;
45 
46     /* There's a subtle problem here...
47      * If an interface is added at this exact instant, (as if by a PCMCIA
48      * card insertion), the array will still not have enough entries after
49      * have allocated it after the first DeviceIoControl call.
50      *
51      * We'll get around this by repeating until the number of interfaces
52      * stabilizes.
53      */
54     do {
55         status = NtDeviceIoControlFile( tcpFile,
56                                         NULL,
57                                         NULL,
58                                         NULL,
59                                         &Iosb,
60                                         IOCTL_TCP_QUERY_INFORMATION_EX,
61                                         &req,
62                                         sizeof(req),
63                                         NULL,
64                                         0);
65         if (status == STATUS_PENDING)
66         {
67             status = NtWaitForSingleObject(tcpFile, FALSE, NULL);
68             if (NT_SUCCESS(status)) status = Iosb.Status;
69         }
70 
71         if(!NT_SUCCESS(status))
72         {
73             return status;
74         }
75 
76         allocationSizeForEntityArray = Iosb.Information;
77         entitySet = HeapAlloc( GetProcessHeap(), 0, allocationSizeForEntityArray );
78 
79         if( !entitySet ) {
80             status = STATUS_INSUFFICIENT_RESOURCES;
81             return status;
82         }
83 
84         status = NtDeviceIoControlFile( tcpFile,
85                                         NULL,
86                                         NULL,
87                                         NULL,
88                                         &Iosb,
89                                         IOCTL_TCP_QUERY_INFORMATION_EX,
90                                         &req,
91                                         sizeof(req),
92                                         entitySet,
93                                         allocationSizeForEntityArray);
94         if (status == STATUS_PENDING)
95         {
96             status = NtWaitForSingleObject(tcpFile, FALSE, NULL);
97             if (NT_SUCCESS(status)) status = Iosb.Status;
98         }
99 
100         /* This is why we have the loop -- we might have added an adapter */
101         if( Iosb.Information == allocationSizeForEntityArray )
102             break;
103 
104         HeapFree( GetProcessHeap(), 0, entitySet );
105         entitySet = 0;
106 
107         if(!NT_SUCCESS(status))
108             return status;
109     } while( TRUE ); /* We break if the array we received was the size we
110                       * expected.  Therefore, we got here because it wasn't */
111 
112     *numEntries = (allocationSizeForEntityArray - fixedPart) / entrySize;
113     *tdiEntitySet = entitySet;
114 
115     return STATUS_SUCCESS;
116 }
117 
118 VOID tdiFreeThingSet( PVOID things ) {
119     HeapFree( GetProcessHeap(), 0, things );
120 }
121 
122 NTSTATUS tdiGetEntityIDSet( HANDLE tcpFile,
123                             TDIEntityID **entitySet,
124                             PDWORD numEntities ) {
125     NTSTATUS status = tdiGetSetOfThings( tcpFile,
126                                          INFO_CLASS_GENERIC,
127                                          INFO_TYPE_PROVIDER,
128                                          ENTITY_LIST_ID,
129                                          GENERIC_ENTITY,
130                                          0,
131                                          0,
132                                          sizeof(TDIEntityID),
133                                          (PVOID *)entitySet,
134                                          numEntities );
135 
136     return status;
137 }
138 
139