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 */
tdiGetSetOfThings(HANDLE tcpFile,DWORD toiClass,DWORD toiType,DWORD toiId,DWORD teiEntity,DWORD teiInstance,DWORD fixedPart,DWORD entrySize,PVOID * tdiEntitySet,PDWORD numEntries)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
tdiFreeThingSet(PVOID things)118 VOID tdiFreeThingSet( PVOID things ) {
119 HeapFree( GetProcessHeap(), 0, things );
120 }
121
tdiGetEntityIDSet(HANDLE tcpFile,TDIEntityID ** entitySet,PDWORD numEntities)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