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