mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
nic enumerator
svn path=/trunk/; revision=5971
This commit is contained in:
parent
8a5da02367
commit
a26b8ceda1
1 changed files with 453 additions and 0 deletions
453
reactos/drivers/net/ndis/ndis/enum.c
Normal file
453
reactos/drivers/net/ndis/ndis/enum.c
Normal file
|
@ -0,0 +1,453 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS NDIS library
|
||||
* FILE: ndis/config.c
|
||||
* PURPOSE: NDIS Configuration Services
|
||||
* PROGRAMMERS: Vizzini (vizzini@plasmic.com)
|
||||
* REVISIONS:
|
||||
* Vizzini 08-20-2003 Created
|
||||
* NOTES:
|
||||
* - Currently this only supports enumeration of Root and PCI devices
|
||||
* - This whole thing is really just a band-aid until we have real PnP
|
||||
* - Strictly speaking, I'm not even sure it's my job to call
|
||||
* HalAssignSlotResources(), but the vmware nic driver likes it
|
||||
* - Please send me feedback if there is a better way :)
|
||||
* TODO:
|
||||
* - Break these functions up a bit; i hate 200-line functions
|
||||
*/
|
||||
|
||||
#include <ndissys.h>
|
||||
#include <miniport.h>
|
||||
|
||||
/* Registry path to the enumeration database */
|
||||
#define ENUM_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum"
|
||||
|
||||
/* Registry path to the services database */
|
||||
#define SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services"
|
||||
|
||||
/*
|
||||
* This has to be big enough to hold enumerated registry paths until
|
||||
* registry accesses are properly re-coded
|
||||
*/
|
||||
#define KEY_INFORMATION_SIZE 512
|
||||
|
||||
/* same sort of deal as above */
|
||||
#define VALUE_INFORMATION_SIZE 100
|
||||
|
||||
/*
|
||||
* NET class GUID, as defined by Microsoft, used to tell if a
|
||||
* device belongs to NDIS or not.
|
||||
*/
|
||||
#define NET_GUID L"{4D36E972-E325-11CE-BFC1-08002BE10318}"
|
||||
|
||||
#define RZ() do { DbgPrint("%s:%i Checking RedZone\n", __FILE__, __LINE__ ); ExAllocatePool(PagedPool,0); } while (0);
|
||||
|
||||
/* see miniport.c */
|
||||
extern LIST_ENTRY OrphanAdapterListHead;
|
||||
extern KSPIN_LOCK OrphanAdapterListLock;
|
||||
|
||||
|
||||
BOOLEAN NdisFindDevicePci(UINT VendorID, UINT DeviceID, PUINT BusNumber, PUINT SlotNumber)
|
||||
/*
|
||||
* FUNCTION: Find a PCI device given its Vendor and Device IDs
|
||||
* ARGUMENTS:
|
||||
* VendorID: The card's PCI Vendor ID
|
||||
* DeviceID: The card's PCI Device ID
|
||||
* BusNumber: The card's bus number on success
|
||||
* SlotNumber: The card's slot number on success
|
||||
* RETURNS:
|
||||
* TRUE if the card is fouund
|
||||
* FALSE Otherwise
|
||||
* NOTES:
|
||||
* - This only finds the first card of a type
|
||||
* - This doesn't handle function enumeration correctly
|
||||
* - Based loosely on Dekker & Newcomer examples
|
||||
*/
|
||||
{
|
||||
PCI_COMMON_CONFIG PciData;
|
||||
int i, j, k;
|
||||
|
||||
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
||||
|
||||
/* dekker says there are 256 possible PCI buses */
|
||||
for(i = 0; i < 256; i++)
|
||||
{
|
||||
for(j = 0; j < PCI_MAX_DEVICES; j++)
|
||||
{
|
||||
for(k = 0; k < PCI_MAX_FUNCTION; k++)
|
||||
{
|
||||
/* TODO: figure out what to do with k */
|
||||
|
||||
if(HalGetBusData(PCIConfiguration, i, j, &PciData, sizeof(PciData)))
|
||||
{
|
||||
if(PciData.VendorID == 0xffff) /* Is this handled right? */
|
||||
continue;
|
||||
|
||||
if(PciData.VendorID == VendorID && PciData.DeviceID == DeviceID)
|
||||
{
|
||||
if(BusNumber)
|
||||
*BusNumber = i;
|
||||
if(SlotNumber)
|
||||
*SlotNumber = j;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NDIS_DbgPrint(MAX_TRACE, ("Didn't find device 0x%x:0x%x\n", VendorID, DeviceID));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
VOID NdisStartDriver(PUNICODE_STRING uBusName, PUNICODE_STRING uDeviceId, PUNICODE_STRING uServiceName)
|
||||
/*
|
||||
* FUNCTION: Starts an NDIS driver
|
||||
* ARGUMENTS:
|
||||
* uBusName: the card's bus type, by name, as extracted from the
|
||||
* enumeration database in the registry
|
||||
* uDeviceId: the card's device ID
|
||||
* uServiceName: the driver (scm db entry) associated with the card
|
||||
* NOTES:
|
||||
* - This doesn't prooperly handle multiple instances of the same card or driver
|
||||
* - for PCI cards, this finds the card and creates an "orphan" adapter object for
|
||||
* it. This object is tagged with the registry key to the driver and includes
|
||||
* the slot number and bus number of the card. NOTE that some stupid nic drivers
|
||||
* still depend on a registry key for slot number, so this isn't always enough.
|
||||
* Whatever the case, all of the card's resources are enumerated and assigned
|
||||
* via HalAssignSlotResources() and the orphan adapter is put onto the list.
|
||||
* When the miniport calls NdisMRegisterMiniport(), ndis loops through the list
|
||||
* of orphans and associates any orphans that belong to that miniport with
|
||||
* its corresponding LOGICAL_ADAPTER objects.
|
||||
*/
|
||||
{
|
||||
ULONG VendorId;
|
||||
ULONG DeviceId;
|
||||
UINT SlotNumber;
|
||||
UINT BusNumber;
|
||||
UNICODE_STRING Temp;
|
||||
UNICODE_STRING ServiceKey;
|
||||
PWCHAR ServiceKeyStr;
|
||||
NTSTATUS NtStatus;
|
||||
PORPHAN_ADAPTER OrphanAdapter;
|
||||
|
||||
NDIS_DbgPrint(MAX_TRACE, ("Called; Starting %wZ\n", uServiceName));
|
||||
|
||||
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
||||
|
||||
/* prepare a services key */
|
||||
ServiceKeyStr = ExAllocatePool(PagedPool, sizeof(SERVICES_KEY) + sizeof(WCHAR) + uServiceName->Length);
|
||||
if(!ServiceKeyStr)
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Insufficient Resources.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
wcscpy(ServiceKeyStr, SERVICES_KEY);
|
||||
wcscat(ServiceKeyStr, L"\\");
|
||||
wcsncat(ServiceKeyStr, uServiceName->Buffer, uServiceName->Length/sizeof(WCHAR));
|
||||
ServiceKeyStr[wcslen(SERVICES_KEY)+1+uServiceName->Length/sizeof(WCHAR)] = 0;
|
||||
|
||||
RtlInitUnicodeString(&ServiceKey, ServiceKeyStr);
|
||||
|
||||
if(!wcsncmp(uBusName->Buffer, L"PCI", uBusName->Length))
|
||||
{
|
||||
/*
|
||||
* first see if a card with the requested id exists.
|
||||
* PCI IDs are formatted VEN_ABCD&DEV_ABCD[&...]
|
||||
*/
|
||||
|
||||
if(wcsncmp(uDeviceId->Buffer, L"VEN_", 4))
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Bogus uDeviceId parsing VEN\n"));
|
||||
ExFreePool(ServiceKeyStr);
|
||||
return;
|
||||
}
|
||||
|
||||
Temp.Buffer = &(uDeviceId->Buffer[4]); /* offset of vendor id */
|
||||
Temp.Length = Temp.MaximumLength = 4 * sizeof(WCHAR); /* 4-digit id */
|
||||
|
||||
NtStatus = RtlUnicodeStringToInteger(&Temp, 16, &VendorId);
|
||||
if(!NT_SUCCESS(NtStatus))
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("RtlUnicodeStringToInteger returned 0x%x\n", NtStatus));
|
||||
ExFreePool(ServiceKeyStr);
|
||||
return;
|
||||
}
|
||||
|
||||
if(wcsncmp(&(uDeviceId->Buffer[9]), L"DEV_", 4))
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Bogus uDeviceId parsing DEV\n"));
|
||||
ExFreePool(ServiceKeyStr);
|
||||
return;
|
||||
}
|
||||
|
||||
Temp.Buffer = &(uDeviceId->Buffer[13]); /* offset of device id */
|
||||
Temp.Length = 4 * sizeof(WCHAR); /* 4-dight id */
|
||||
|
||||
NtStatus = RtlUnicodeStringToInteger(&Temp, 16, &DeviceId);
|
||||
if(!NT_SUCCESS(NtStatus))
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("RtlUnicodeStringToInteger returned 0x%x\n", NtStatus));
|
||||
ExFreePool(ServiceKeyStr);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!NdisFindDevicePci(VendorId, DeviceId, &BusNumber, &SlotNumber))
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Didn't find a configured card 0x%x 0x%x\n", VendorId, DeviceId));
|
||||
ExFreePool(ServiceKeyStr);
|
||||
return;
|
||||
}
|
||||
|
||||
NDIS_DbgPrint(MAX_TRACE, ("Found a card 0x%x 0x%x at bus 0x%x slot 0x%x\n", VendorId, DeviceId, BusNumber, SlotNumber));
|
||||
|
||||
OrphanAdapter = ExAllocatePool(PagedPool, sizeof(ORPHAN_ADAPTER));
|
||||
if(!OrphanAdapter)
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Insufficient Resources.\n"));
|
||||
ExFreePool(ServiceKeyStr);
|
||||
return;
|
||||
}
|
||||
|
||||
OrphanAdapter->RegistryPath.Buffer = ExAllocatePool(PagedPool, Temp.MaximumLength);
|
||||
if(!OrphanAdapter->RegistryPath.Buffer)
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Insufficient Resources.\n"));
|
||||
ExFreePool(ServiceKeyStr);
|
||||
return;
|
||||
}
|
||||
|
||||
OrphanAdapter->RegistryPath.Length = Temp.Length;
|
||||
OrphanAdapter->RegistryPath.MaximumLength = Temp.MaximumLength;
|
||||
memcpy(OrphanAdapter->RegistryPath.Buffer, Temp.Buffer, Temp.Length);
|
||||
|
||||
OrphanAdapter->BusType = PCIBus;
|
||||
OrphanAdapter->BusNumber = BusNumber;
|
||||
OrphanAdapter->SlotNumber = SlotNumber;
|
||||
|
||||
ExInterlockedInsertTailList(&OrphanAdapterListHead, &OrphanAdapter->ListEntry, &OrphanAdapterListLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* found a card; start its driver. this should be done from a
|
||||
* system thread, after NDIS.SYS's DriverEntry returns, but I
|
||||
* really don't know how to block on DriverEntry returning, so
|
||||
* what the hell.
|
||||
*/
|
||||
|
||||
NDIS_DbgPrint(MID_TRACE, ("Loading driver %wZ\n", &ServiceKey));
|
||||
ZwLoadDriver(&ServiceKey);
|
||||
|
||||
ExFreePool(ServiceKeyStr);
|
||||
}
|
||||
|
||||
|
||||
VOID NdisStartDevices()
|
||||
/*
|
||||
* FUNCTION: Find and start all NDIS Net class devices
|
||||
* NOTES:
|
||||
* - Not sure if this handles multiple instances of the same
|
||||
* device or driver correctly yet
|
||||
*/
|
||||
{
|
||||
HANDLE EnumHandle;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING KeyName;
|
||||
NTSTATUS NtStatus;
|
||||
ULONG EnumIndex = 0;
|
||||
ULONG ResultLength;
|
||||
PKEY_BASIC_INFORMATION KeyInformation;
|
||||
ULONG KeyInformationLength;
|
||||
|
||||
NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
|
||||
|
||||
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
||||
|
||||
RtlInitUnicodeString(&KeyName, ENUM_KEY);
|
||||
InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, 0, 0);
|
||||
NtStatus = ZwOpenKey(&EnumHandle, KEY_ALL_ACCESS, &ObjectAttributes);
|
||||
if(!NT_SUCCESS(NtStatus))
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Unable to open the Enum key\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
NDIS_DbgPrint(MAX_TRACE, ("Opened the enum key\n"));
|
||||
|
||||
KeyInformation = ExAllocatePool(PagedPool, KEY_INFORMATION_SIZE); // should be enough for most key names?
|
||||
if(!KeyInformation)
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
KeyInformationLength = KEY_INFORMATION_SIZE;
|
||||
|
||||
while(NT_SUCCESS(ZwEnumerateKey(EnumHandle, EnumIndex,
|
||||
KeyBasicInformation, KeyInformation, KeyInformationLength, &ResultLength)))
|
||||
{
|
||||
/* iterate through each enumerator (PCI, Root, ISAPNP, etc) */
|
||||
|
||||
HANDLE EnumeratorHandle;
|
||||
WCHAR *EnumeratorStr;
|
||||
UINT EnumeratorIndex = 0;
|
||||
|
||||
NDIS_DbgPrint(MAX_TRACE, ("Enum iteration 0x%x\n", EnumIndex));
|
||||
|
||||
EnumIndex++;
|
||||
|
||||
EnumeratorStr = ExAllocatePool(PagedPool, sizeof(WCHAR) + KeyInformation->NameLength);
|
||||
if(!EnumeratorStr)
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
wcsncpy(EnumeratorStr, KeyInformation->Name, KeyInformation->NameLength/sizeof(WCHAR));
|
||||
EnumeratorStr[KeyInformation->NameLength/sizeof(WCHAR)] = 0;
|
||||
|
||||
RtlInitUnicodeString(&KeyName, EnumeratorStr);
|
||||
InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, EnumHandle, 0);
|
||||
if(!NT_SUCCESS(ZwOpenKey(&EnumeratorHandle, KEY_ALL_ACCESS, &ObjectAttributes)))
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Failed to open key %wZ\n", &KeyName));
|
||||
return;
|
||||
}
|
||||
|
||||
while(NT_SUCCESS(ZwEnumerateKey(EnumeratorHandle, EnumeratorIndex, KeyBasicInformation,
|
||||
KeyInformation, KeyInformationLength, &ResultLength)))
|
||||
{
|
||||
/* iterate through each device id */
|
||||
|
||||
HANDLE DeviceHandle;
|
||||
WCHAR *DeviceStr;
|
||||
UINT DeviceIndex = 0;
|
||||
UNICODE_STRING BusName;
|
||||
|
||||
BusName.Buffer = KeyName.Buffer;
|
||||
BusName.Length = KeyName.Length;
|
||||
BusName.MaximumLength = KeyName.MaximumLength;
|
||||
|
||||
EnumeratorIndex++;
|
||||
|
||||
DeviceStr = ExAllocatePool(PagedPool, KeyInformation->NameLength + sizeof(WCHAR));
|
||||
if(!DeviceStr)
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
wcsncpy(DeviceStr, KeyInformation->Name, KeyInformation->NameLength/sizeof(WCHAR));
|
||||
DeviceStr[KeyInformation->NameLength/sizeof(WCHAR)] = 0;
|
||||
|
||||
RtlInitUnicodeString(&KeyName, DeviceStr);
|
||||
InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, EnumeratorHandle, 0);
|
||||
if(!NT_SUCCESS(ZwOpenKey(&DeviceHandle, KEY_ALL_ACCESS, &ObjectAttributes)))
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Failed to open key %wZ\n", &KeyName));
|
||||
return;
|
||||
}
|
||||
|
||||
while(NT_SUCCESS(ZwEnumerateKey(DeviceHandle, DeviceIndex, KeyBasicInformation,
|
||||
KeyInformation, KeyInformationLength, &ResultLength)))
|
||||
{
|
||||
/* iterate through each instance id, starting drivers in the process */
|
||||
HANDLE InstanceHandle;
|
||||
WCHAR *InstanceStr;
|
||||
UNICODE_STRING ValueName;
|
||||
UNICODE_STRING ServiceName;
|
||||
PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
|
||||
ULONG KeyValueInformationLength;
|
||||
UNICODE_STRING DeviceId;
|
||||
|
||||
DeviceId.Buffer = KeyName.Buffer;
|
||||
DeviceId.Length = KeyName.Length;
|
||||
DeviceId.MaximumLength = KeyName.MaximumLength;
|
||||
|
||||
DeviceIndex++;
|
||||
|
||||
InstanceStr = ExAllocatePool(PagedPool, KeyInformation->NameLength + sizeof(WCHAR));
|
||||
if(!InstanceStr)
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
wcsncpy(InstanceStr, KeyInformation->Name, KeyInformation->NameLength/sizeof(WCHAR));
|
||||
InstanceStr[KeyInformation->NameLength/sizeof(WCHAR)] = 0;
|
||||
|
||||
NDIS_DbgPrint(MAX_TRACE, ("NameLength = 0x%x and InstanceStr: %ws\n", KeyInformation->NameLength, InstanceStr));
|
||||
|
||||
RtlInitUnicodeString(&KeyName, InstanceStr);
|
||||
InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, DeviceHandle, 0);
|
||||
if(!NT_SUCCESS(ZwOpenKey(&InstanceHandle, KEY_ALL_ACCESS, &ObjectAttributes)))
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Failed to open key %wZ\n", &KeyName));
|
||||
return;
|
||||
}
|
||||
|
||||
/* read class, looking for net guid */
|
||||
RtlInitUnicodeString(&ValueName, L"ClassGUID");
|
||||
|
||||
NDIS_DbgPrint(MAX_TRACE, ("About to ask for 0x%x bytes\n", VALUE_INFORMATION_SIZE));
|
||||
|
||||
KeyValueInformation = ExAllocatePool(PagedPool, VALUE_INFORMATION_SIZE);
|
||||
if(!KeyValueInformation)
|
||||
{
|
||||
NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
KeyValueInformationLength = VALUE_INFORMATION_SIZE;
|
||||
|
||||
NtStatus = ZwQueryValueKey(InstanceHandle, &ValueName, KeyValuePartialInformation,
|
||||
KeyValueInformation, KeyValueInformationLength, &ResultLength);
|
||||
if(!NT_SUCCESS(NtStatus))
|
||||
{
|
||||
/* this isn't fatal, it just means that this device isn't ours */
|
||||
NDIS_DbgPrint(MID_TRACE, ("Failed to query value %wZ from key %wZ\n", &ValueName, &KeyName));
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!wcsncmp(NET_GUID, (PWCHAR)KeyValueInformation->Data, KeyValueInformation->DataLength/sizeof(WCHAR)))
|
||||
{
|
||||
RtlInitUnicodeString(&ValueName, L"Service");
|
||||
|
||||
NtStatus = ZwQueryValueKey(InstanceHandle, &ValueName, KeyValuePartialInformation,
|
||||
KeyValueInformation, KeyValueInformationLength, &ResultLength);
|
||||
if(!NT_SUCCESS(NtStatus))
|
||||
{
|
||||
/* non-fatal also */
|
||||
NDIS_DbgPrint(MID_TRACE, ("Failed to query value %wZ from key %wZ\n", &ValueName, &KeyName));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* this is a net driver; start it */
|
||||
ServiceName.Length = ServiceName.MaximumLength = KeyValueInformation->DataLength;
|
||||
ServiceName.Buffer = (PWCHAR)KeyValueInformation->Data;
|
||||
NdisStartDriver(&BusName, &DeviceId, &ServiceName);
|
||||
}
|
||||
else
|
||||
NDIS_DbgPrint(MAX_TRACE, ("...this device is not ours\n"));
|
||||
|
||||
ExFreePool(KeyValueInformation);
|
||||
ExFreePool(InstanceStr);
|
||||
ZwClose(InstanceHandle);
|
||||
}
|
||||
|
||||
ExFreePool(DeviceStr);
|
||||
ZwClose(DeviceHandle);
|
||||
}
|
||||
|
||||
ExFreePool(EnumeratorStr);
|
||||
ZwClose(EnumeratorHandle);
|
||||
}
|
||||
|
||||
ZwClose(EnumHandle);
|
||||
ExFreePool(KeyInformation);
|
||||
}
|
||||
|
Loading…
Reference in a new issue