mirror of
https://github.com/reactos/reactos.git
synced 2024-10-31 20:02:55 +00:00
139 lines
4.8 KiB
C
139 lines
4.8 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS TDI interface
|
|
* FILE: enum.c
|
|
* PURPOSE: TDI entity enumeration
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#include "tdilib.h"
|
|
|
|
/* A generic thing-getting function which interacts in the right way with
|
|
* TDI. This may seem oblique, but I'm using it to reduce code and hopefully
|
|
* make this thing easier to debug.
|
|
*
|
|
* The things returned can be any of:
|
|
* TDIEntityID
|
|
* TDIObjectID
|
|
* IFEntry
|
|
* IPSNMPInfo
|
|
* IPAddrEntry
|
|
* IPInterfaceInfo
|
|
*/
|
|
NTSTATUS tdiGetSetOfThings( HANDLE tcpFile,
|
|
DWORD toiClass,
|
|
DWORD toiType,
|
|
DWORD toiId,
|
|
DWORD teiEntity,
|
|
DWORD teiInstance,
|
|
DWORD fixedPart,
|
|
DWORD entrySize,
|
|
PVOID *tdiEntitySet,
|
|
PDWORD numEntries ) {
|
|
TCP_REQUEST_QUERY_INFORMATION_EX req = TCP_REQUEST_QUERY_INFORMATION_INIT;
|
|
PVOID entitySet = 0;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
DWORD allocationSizeForEntityArray = entrySize * MAX_TDI_ENTITIES;
|
|
IO_STATUS_BLOCK Iosb;
|
|
|
|
req.ID.toi_class = toiClass;
|
|
req.ID.toi_type = toiType;
|
|
req.ID.toi_id = toiId;
|
|
req.ID.toi_entity.tei_entity = teiEntity;
|
|
req.ID.toi_entity.tei_instance = teiInstance;
|
|
|
|
/* There's a subtle problem here...
|
|
* If an interface is added at this exact instant, (as if by a PCMCIA
|
|
* card insertion), the array will still not have enough entries after
|
|
* have allocated it after the first DeviceIoControl call.
|
|
*
|
|
* We'll get around this by repeating until the number of interfaces
|
|
* stabilizes.
|
|
*/
|
|
do {
|
|
status = NtDeviceIoControlFile( tcpFile,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&Iosb,
|
|
IOCTL_TCP_QUERY_INFORMATION_EX,
|
|
&req,
|
|
sizeof(req),
|
|
NULL,
|
|
0);
|
|
if (status == STATUS_PENDING)
|
|
{
|
|
status = NtWaitForSingleObject(tcpFile, FALSE, NULL);
|
|
if (NT_SUCCESS(status)) status = Iosb.Status;
|
|
}
|
|
|
|
if(!NT_SUCCESS(status))
|
|
{
|
|
return status;
|
|
}
|
|
|
|
allocationSizeForEntityArray = Iosb.Information;
|
|
entitySet = HeapAlloc( GetProcessHeap(), 0, allocationSizeForEntityArray );
|
|
|
|
if( !entitySet ) {
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
return status;
|
|
}
|
|
|
|
status = NtDeviceIoControlFile( tcpFile,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&Iosb,
|
|
IOCTL_TCP_QUERY_INFORMATION_EX,
|
|
&req,
|
|
sizeof(req),
|
|
entitySet,
|
|
allocationSizeForEntityArray);
|
|
if (status == STATUS_PENDING)
|
|
{
|
|
status = NtWaitForSingleObject(tcpFile, FALSE, NULL);
|
|
if (NT_SUCCESS(status)) status = Iosb.Status;
|
|
}
|
|
|
|
/* This is why we have the loop -- we might have added an adapter */
|
|
if( Iosb.Information == allocationSizeForEntityArray )
|
|
break;
|
|
|
|
HeapFree( GetProcessHeap(), 0, entitySet );
|
|
entitySet = 0;
|
|
|
|
if(!NT_SUCCESS(status))
|
|
return status;
|
|
} while( TRUE ); /* We break if the array we received was the size we
|
|
* expected. Therefore, we got here because it wasn't */
|
|
|
|
*numEntries = (allocationSizeForEntityArray - fixedPart) / entrySize;
|
|
*tdiEntitySet = entitySet;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID tdiFreeThingSet( PVOID things ) {
|
|
HeapFree( GetProcessHeap(), 0, things );
|
|
}
|
|
|
|
NTSTATUS tdiGetEntityIDSet( HANDLE tcpFile,
|
|
TDIEntityID **entitySet,
|
|
PDWORD numEntities ) {
|
|
NTSTATUS status = tdiGetSetOfThings( tcpFile,
|
|
INFO_CLASS_GENERIC,
|
|
INFO_TYPE_PROVIDER,
|
|
ENTITY_LIST_ID,
|
|
GENERIC_ENTITY,
|
|
0,
|
|
0,
|
|
sizeof(TDIEntityID),
|
|
(PVOID *)entitySet,
|
|
numEntities );
|
|
|
|
return status;
|
|
}
|
|
|