1147 lines
37 KiB
C
1147 lines
37 KiB
C
/*++
|
||
|
||
Copyright (c) 1995 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
pnpsubs.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the plug-and-play IO system APIs.
|
||
|
||
Author:
|
||
|
||
Shie-Lin Tzong (shielint) 3-Jan-1995
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
#include "iop.h"
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(PAGE, IoQueryDeviceEnumInfo)
|
||
#pragma alloc_text(PAGE, IoOpenDeviceInstanceKey)
|
||
#pragma alloc_text(PAGE, IopQueryDeviceConfiguration)
|
||
#if _PNP_POWER_STUB_ENABLED_
|
||
#pragma alloc_text(PAGE, IoQuerySystemInformation)
|
||
#pragma alloc_text(PAGE, IoGetDeviceProperty)
|
||
#pragma alloc_text(PAGE, IoSetDeviceProperty)
|
||
#pragma alloc_text(PAGE, IoRegisterPlugPlayNotification)
|
||
#pragma alloc_text(PAGE, IoUnregisterPlugPlayNotification)
|
||
#pragma alloc_text(PAGE, IoReportDeviceStatus)
|
||
#endif // _PNP_POWER_STUB_ENABLED_
|
||
#endif // ALLOC_PRAGMA
|
||
|
||
NTSTATUS
|
||
IoQueryDeviceEnumInfo(
|
||
IN PUNICODE_STRING ServiceKeyName,
|
||
OUT PULONG Count
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine opens ServiceKeyName key and returns the number of device
|
||
instances found at enumeration time to variable Count.
|
||
|
||
Note the device count returned from this function may include disabled
|
||
devices. It is the device driver's responsibility to check each device
|
||
before creating it to ensure that it is not disabled.= (vai the
|
||
DeviceStatus value returned from IoQueryConfiguration and
|
||
IoQueryDeviceConfigurationVector). Disabled devices must be ignored.
|
||
|
||
Parameters:
|
||
|
||
ServiceKeyName - Supplies the name of the subkey in the system service
|
||
list (HKEY_LOCAL_MACHINE\CurrentControlSet\Services)
|
||
that caused the driver to load.
|
||
|
||
Count - Receives the number of device instances found at enumeration whose
|
||
Enum data indicate that ServiceKeyName is for their device driver.
|
||
A driver can use this as the limit for a loop around calls to
|
||
IoQueryDeviceConfiguration.
|
||
|
||
Return Value:
|
||
|
||
Status code that indicates whether or not the function was successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS status;
|
||
HANDLE enumHandle;
|
||
ULONG instanceCount = 0;
|
||
PKEY_VALUE_FULL_INFORMATION keyValueInformation;
|
||
|
||
KeEnterCriticalRegion();
|
||
ExAcquireResourceShared(&PpRegistryDeviceResource, TRUE);
|
||
|
||
//
|
||
// Open System\CurrentControlSet\Services
|
||
//
|
||
|
||
status = IopOpenServiceEnumKeys (
|
||
ServiceKeyName,
|
||
KEY_READ,
|
||
NULL,
|
||
&enumHandle,
|
||
FALSE
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
goto exit1;
|
||
}
|
||
|
||
//
|
||
// Read value of Count if present. If it is not present, a value of
|
||
// zero will be returned.
|
||
//
|
||
|
||
status = IopGetRegistryValue(enumHandle, REGSTR_VALUE_COUNT, &keyValueInformation);
|
||
if (NT_SUCCESS(status)) {
|
||
if (keyValueInformation->DataLength != 0) {
|
||
instanceCount = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
|
||
}
|
||
ExFreePool(keyValueInformation);
|
||
} else if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
|
||
status = STATUS_SUCCESS;
|
||
}
|
||
ZwClose(enumHandle);
|
||
|
||
exit1:
|
||
ExReleaseResource(&PpRegistryDeviceResource);
|
||
KeLeaveCriticalRegion();
|
||
*Count = instanceCount;
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
IoOpenDeviceInstanceKey(
|
||
IN PUNICODE_STRING ServiceKeyName,
|
||
IN ULONG InstanceNumber,
|
||
IN ULONG DevInstKeyType,
|
||
IN ACCESS_MASK DesiredAccess,
|
||
OUT PHANDLE DevInstRegKey
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
THis routine returns a handle to an opened registry key that the driver
|
||
may use to store/retrieve configuration information specific to a particular
|
||
device instance.
|
||
|
||
The driver must call ZwClose to close the handle returned from this api
|
||
when access is no longer required.
|
||
|
||
BUGBUG (lonnym): For SUR, we inform a driver calling IoQueryEnumDeviceInfo of
|
||
_all_ device instances associated with its service entry, not just those devices
|
||
that are currently present and enabled. To keep the driver from creating device
|
||
objects for these 'non-live' devices, we will fail the driver's subsequent call to
|
||
IoOpenDeviceInstanceKey with STATUS_PLUGPLAY_NO_DEVICE for such devices.
|
||
|
||
Parameters:
|
||
|
||
ServiceKeyName - Supplies the name of the subkey in the system service
|
||
list (HKEY_LOCAL_MACHINE\CurrentControlSet\Services)
|
||
that caused the driver to load.
|
||
|
||
InstanceNumber - Supplies an ordinal value indicating the device instance
|
||
to open a registry storage key for. For enumerated devices,
|
||
this value may be from 0 to n-1, where n is the Count value
|
||
returned from the original call to IoQueryDeviceEnumInfo.
|
||
|
||
DevInstKeyType - Supplies flags specifying which storage key associated with
|
||
the device instance is to be opened. May be a combination of
|
||
the following value:
|
||
|
||
PLUGPLAY_REGKEY_DEVICE - Open a key for storing device specific
|
||
(driver-independent) information relating to the device instance.
|
||
The flag may not be specified with PLUGPLAY_REGKEY_DRIVER.
|
||
|
||
PLUGPLAY_REGKEY_DRIVER - Open a key for storing driver-specific
|
||
information relating to the device instance, This flag may
|
||
not be specified with PLUGPLAY_REGKEY_DEVICE.
|
||
|
||
PLUGPLAY_REGKEY_CURRENT_HWPROFILE - If this flag is specified,
|
||
then a key in the current hardware profile branch will be
|
||
opened for the specified storage type. This allows the driver
|
||
to access configuration information that is hardware profile
|
||
specific.
|
||
|
||
DesiredAccess - Specifies the access mask for the key to be opened.
|
||
|
||
DevInstRegKey - Supplies the address of a variable that receives a handle to the
|
||
opened key for the specified registry storage location.
|
||
|
||
Return Value:
|
||
|
||
Status code that indicates whether or not the function was successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS status;
|
||
HANDLE classHandle, instanceHandle, handle;
|
||
UNICODE_STRING unicodeKeyName, unicodeString;
|
||
PKEY_VALUE_FULL_INFORMATION keyValueInformation;
|
||
ULONG csConfigFlags;
|
||
|
||
//
|
||
// Make sure the DevInstKeyType argument is valid.
|
||
//
|
||
|
||
if (((DevInstKeyType & PLUGPLAY_REGKEY_DEVICE) &&
|
||
(DevInstKeyType & PLUGPLAY_REGKEY_DRIVER)) ||
|
||
!(DevInstKeyType & (PLUGPLAY_REGKEY_DEVICE + PLUGPLAY_REGKEY_DRIVER)) ) {
|
||
return STATUS_INVALID_PARAMETER_3;
|
||
}
|
||
|
||
unicodeKeyName.Buffer = NULL;
|
||
classHandle = NULL;
|
||
|
||
KeEnterCriticalRegion();
|
||
ExAcquireResourceShared(&PpRegistryDeviceResource, TRUE);
|
||
|
||
//
|
||
// First determine whether this device is present and enabled (otherwise, fail
|
||
// the call now with STATUS_PLUGPLAY_NO_DEVICE).
|
||
//
|
||
status = IopGetDeviceInstanceCsConfigFlags(ServiceKeyName, InstanceNumber, &csConfigFlags);
|
||
|
||
if(NT_SUCCESS(status) &&
|
||
(csConfigFlags & (CSCONFIGFLAG_DISABLED | CSCONFIGFLAG_DO_NOT_CREATE | CSCONFIGFLAG_DO_NOT_START))) {
|
||
//
|
||
// This device is disabled or not present.
|
||
//
|
||
status = STATUS_PLUGPLAY_NO_DEVICE;
|
||
goto exit_Local0;
|
||
}
|
||
|
||
status = IopOpenServiceEnumKeys (
|
||
ServiceKeyName,
|
||
KEY_READ,
|
||
&handle,
|
||
NULL,
|
||
FALSE
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
goto exit_Local0;
|
||
}
|
||
|
||
//
|
||
// Check if caller wants the global device/driver key or the one specific
|
||
// to hardware profile.
|
||
//
|
||
|
||
if (DevInstKeyType & PLUGPLAY_REGKEY_CURRENT_HWPROFILE) {
|
||
|
||
//
|
||
// Get the device instance path form instance number of ServiceName\Enum.
|
||
//
|
||
|
||
status = IopServiceInstanceToDeviceInstance (handle,
|
||
NULL,
|
||
InstanceNumber,
|
||
&unicodeKeyName,
|
||
NULL,
|
||
KEY_READ
|
||
);
|
||
ZwClose(handle);
|
||
if (!NT_SUCCESS(status)) {
|
||
goto exit_Local0;
|
||
}
|
||
|
||
//
|
||
// Open current hardware profile key
|
||
//
|
||
|
||
status = IopOpenRegistryKey(&classHandle,
|
||
NULL,
|
||
&CmRegistryMachineSystemCurrentControlSetHardwareProfilesCurrent,
|
||
DesiredAccess,
|
||
FALSE
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
goto exit_Local1;
|
||
}
|
||
|
||
//
|
||
// Open system\CurrentControlSet under current hardware profile key
|
||
//
|
||
|
||
PiWstrToUnicodeString(&unicodeString, REGSTR_PATH_CURRENTCONTROLSET);
|
||
status = IopOpenRegistryKey(&handle,
|
||
classHandle,
|
||
&unicodeString,
|
||
DesiredAccess,
|
||
FALSE
|
||
);
|
||
ZwClose(classHandle);
|
||
classHandle = NULL;
|
||
if (!NT_SUCCESS(status)) {
|
||
goto exit_Local1;
|
||
}
|
||
|
||
//
|
||
// Open the Control\Class key if regkey-driver is specified
|
||
//
|
||
|
||
if (DevInstKeyType & PLUGPLAY_REGKEY_DRIVER) {
|
||
PiWstrToUnicodeString(&unicodeString, REGSTR_PATH_CONTROL_CLASS);
|
||
status = IopOpenRegistryKey(&classHandle,
|
||
handle,
|
||
&unicodeString,
|
||
DesiredAccess,
|
||
FALSE
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
ZwClose(handle);
|
||
goto exit_Local1;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Open Enum subkey
|
||
//
|
||
|
||
PiWstrToUnicodeString(&unicodeString, REGSTR_KEY_ENUM);
|
||
status = IopOpenRegistryKey(&instanceHandle,
|
||
handle,
|
||
&unicodeString,
|
||
KEY_READ,
|
||
FALSE
|
||
);
|
||
ZwClose(handle);
|
||
if (!NT_SUCCESS(status)) {
|
||
goto exit_Local2;
|
||
}
|
||
|
||
handle = instanceHandle;
|
||
|
||
//
|
||
// open the device instance path under current hardware profile's Enum key
|
||
//
|
||
|
||
status = IopOpenRegistryKey(&instanceHandle,
|
||
handle,
|
||
&unicodeKeyName,
|
||
DesiredAccess,
|
||
FALSE
|
||
);
|
||
ZwClose(handle);
|
||
if (!NT_SUCCESS(status)) {
|
||
goto exit_Local2;
|
||
}
|
||
|
||
|
||
} else {
|
||
|
||
//
|
||
// Open the subkey specified by ServiceName\Enum instance number under
|
||
// System\CurrentControlSet\Enum subtree.
|
||
//
|
||
|
||
status = IopServiceInstanceToDeviceInstance (handle,
|
||
NULL,
|
||
InstanceNumber,
|
||
NULL,
|
||
&instanceHandle,
|
||
KEY_READ
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
ZwClose(handle);
|
||
goto exit_Local0;
|
||
}
|
||
|
||
if (DevInstKeyType & PLUGPLAY_REGKEY_DRIVER) {
|
||
|
||
//
|
||
// Open global control\class key
|
||
//
|
||
|
||
status = IopOpenRegistryKey(&classHandle,
|
||
NULL,
|
||
&CmRegistryMachineSystemCurrentControlSetControlClass,
|
||
DesiredAccess,
|
||
FALSE
|
||
);
|
||
ZwClose(handle);
|
||
if (!NT_SUCCESS(status)) {
|
||
ZwClose(instanceHandle);
|
||
goto exit_Local0;
|
||
}
|
||
} else {
|
||
ZwClose(handle);
|
||
}
|
||
}
|
||
|
||
if (DevInstKeyType & PLUGPLAY_REGKEY_DEVICE) {
|
||
|
||
//
|
||
// Open the "Device Parameters" subkey under the device instance key.
|
||
//
|
||
|
||
PiWstrToUnicodeString(&unicodeString, REGSTR_KEY_DEVICEPARAMETERS);
|
||
status = IopOpenRegistryKeyPersist(&handle,
|
||
instanceHandle,
|
||
&unicodeString,
|
||
DesiredAccess,
|
||
TRUE,
|
||
NULL
|
||
);
|
||
if (NT_SUCCESS(status)) {
|
||
*DevInstRegKey = handle;
|
||
}
|
||
}
|
||
|
||
if (DevInstKeyType & PLUGPLAY_REGKEY_DRIVER) {
|
||
|
||
//
|
||
// Open the class GUID key under control\class\
|
||
//
|
||
|
||
status = IopGetRegistryValue(instanceHandle,
|
||
REGSTR_VALUE_DRIVER,
|
||
&keyValueInformation
|
||
);
|
||
if ((status == STATUS_OBJECT_NAME_NOT_FOUND) ||
|
||
(status == STATUS_OBJECT_PATH_NOT_FOUND)) {
|
||
|
||
UNICODE_STRING unicodeName, unicodeInstanceName, unicodeValue;
|
||
HANDLE guidHandle;
|
||
ULONG instance;
|
||
UCHAR unicodeBuffer[20];
|
||
|
||
//
|
||
// The "Driver=" value name and its key have not been created yet. We need
|
||
// to create them before returning the handle to the key.
|
||
//
|
||
|
||
//
|
||
// Create a device instance under CCS\Control\Class\Guid Unknown
|
||
//
|
||
|
||
PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_UNKNOWN_CLASS_GUID);
|
||
status = IopOpenRegistryKeyPersist(&guidHandle,
|
||
classHandle,
|
||
&unicodeName,
|
||
KEY_ALL_ACCESS,
|
||
TRUE,
|
||
NULL
|
||
);
|
||
if (NT_SUCCESS(status)) {
|
||
|
||
//
|
||
// Find the instance number to represent the key name
|
||
//
|
||
|
||
instance = 0;
|
||
while (TRUE) {
|
||
PiUlongToInstanceKeyUnicodeString(&unicodeInstanceName,
|
||
unicodeBuffer + sizeof(WCHAR),
|
||
20 - sizeof(WCHAR),
|
||
instance
|
||
);
|
||
status = IopOpenRegistryKey(&handle,
|
||
guidHandle,
|
||
&unicodeInstanceName,
|
||
KEY_READ,
|
||
FALSE
|
||
);
|
||
if ((status == STATUS_OBJECT_PATH_NOT_FOUND) ||
|
||
(status == STATUS_OBJECT_NAME_NOT_FOUND)) {
|
||
break;
|
||
} else {
|
||
if (NT_SUCCESS(status)) {
|
||
ZwClose(handle);
|
||
}
|
||
instance++;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Next open/create the key and initialize "Driver=" value name under
|
||
// current device instance key.
|
||
//
|
||
|
||
status = IopOpenRegistryKeyPersist(&handle,
|
||
guidHandle,
|
||
&unicodeInstanceName,
|
||
KEY_ALL_ACCESS,
|
||
TRUE,
|
||
NULL
|
||
);
|
||
ZwClose(guidHandle);
|
||
if (NT_SUCCESS(status)) {
|
||
*(PWSTR)unicodeBuffer = OBJ_NAME_PATH_SEPARATOR;
|
||
unicodeInstanceName.Buffer = (PWSTR)unicodeBuffer;
|
||
unicodeInstanceName.Length += sizeof(WCHAR);
|
||
unicodeInstanceName.MaximumLength += sizeof(WCHAR);
|
||
IopConcatenateUnicodeStrings(&unicodeValue, &unicodeName, &unicodeInstanceName);
|
||
|
||
PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_DRIVER);
|
||
ZwSetValueKey(instanceHandle,
|
||
&unicodeName,
|
||
TITLE_INDEX_VALUE,
|
||
REG_SZ,
|
||
unicodeValue.Buffer,
|
||
unicodeValue.Length + sizeof(UNICODE_NULL)
|
||
);
|
||
RtlFreeUnicodeString(&unicodeValue);
|
||
*DevInstRegKey = handle;
|
||
}
|
||
}
|
||
} else if (NT_SUCCESS(status)) {
|
||
status = STATUS_OBJECT_PATH_NOT_FOUND;
|
||
if (keyValueInformation->DataLength != 0) {
|
||
if (keyValueInformation->Type == REG_SZ) {
|
||
IopRegistryDataToUnicodeString(&unicodeString,
|
||
(PWSTR)KEY_VALUE_DATA(keyValueInformation),
|
||
keyValueInformation->DataLength
|
||
);
|
||
|
||
//
|
||
// Open the desired registry key
|
||
//
|
||
|
||
status = IopOpenRegistryKey(&handle,
|
||
classHandle,
|
||
&unicodeString,
|
||
DesiredAccess,
|
||
FALSE
|
||
);
|
||
if (NT_SUCCESS(status)) {
|
||
*DevInstRegKey = handle;
|
||
}
|
||
}
|
||
}
|
||
ExFreePool(keyValueInformation);
|
||
}
|
||
}
|
||
|
||
ZwClose(instanceHandle);
|
||
exit_Local2:
|
||
if (classHandle) {
|
||
ZwClose(classHandle);
|
||
}
|
||
exit_Local1:
|
||
if (unicodeKeyName.Buffer) {
|
||
RtlFreeUnicodeString(&unicodeKeyName);
|
||
}
|
||
exit_Local0:
|
||
ExReleaseResource(&PpRegistryDeviceResource);
|
||
KeLeaveCriticalRegion();
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
IopQueryDeviceConfiguration(
|
||
IN PUNICODE_STRING ServiceKeyName,
|
||
IN ULONG InstanceOrdinal,
|
||
OUT PHAL_BUS_INFORMATION BusInfo,
|
||
OUT PULONG DeviceInstanceFlags,
|
||
OUT PCM_RESOURCE_LIST Configuration,
|
||
IN ULONG BufferSize,
|
||
OUT PULONG ActualBufferSize
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine reads and returns the device hardware information
|
||
specified by ServiceKeyName and InstanceOrdinal.
|
||
|
||
Parameters:
|
||
|
||
|
||
ServiceKeyName - Supplies the name of the subkey in the system service
|
||
list (HKEY_LOCAL_MACHINE\CurrentControlSet\Services) that caused
|
||
the driver to load.
|
||
|
||
InstanceOrdinal - Supplies an ordinal that uniquely identifies the device
|
||
instance.
|
||
|
||
BusInfo - Receives bus information about the bus on which the device
|
||
is located.
|
||
|
||
DeviceInstanceFlags- Receives a ULONG containing status flags pertaining
|
||
to this device instance. The possible returned flags are:
|
||
DEVINSTANCE_FLAG_HWPROFILE_DISABLED
|
||
DEVINSTANCE_FLAG_PNP_ENUMERATED
|
||
|
||
Configuration - Receives the last known configuration. This will be
|
||
the configuration assigned to the device by the PnP BIOS (PnP
|
||
devices), ARC firmware, or the last known configuration (non-PnP
|
||
devices).
|
||
|
||
BufferSize - Supplies the size in bytes of the buffer pointed to by
|
||
Configuration.
|
||
|
||
ActualBufferSize - Supplies a variable to receive the size of data written
|
||
to Configuration buffer. In case of output buffer too small error,
|
||
it will contain the minimum required buffer size.
|
||
|
||
Return Value:
|
||
|
||
Status code that indicates whether or not the function was successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS status;
|
||
HANDLE serviceHandle, handle, sysEnumHandle = NULL;
|
||
PKEY_VALUE_FULL_INFORMATION keyValueInformation;
|
||
UNICODE_STRING unicodeKeyName;
|
||
ULONG foundAtEnum = 0, instanceFlags = 0;
|
||
|
||
KeEnterCriticalRegion();
|
||
ExAcquireResourceShared(&PpRegistryDeviceResource, TRUE);
|
||
|
||
status = IopOpenServiceEnumKeys (
|
||
ServiceKeyName,
|
||
KEY_READ,
|
||
&serviceHandle,
|
||
NULL,
|
||
FALSE
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
goto exit_Local0;
|
||
}
|
||
|
||
//
|
||
// Open the subkey specified by ServiceName\Enum instance number under
|
||
// System\Enum subtree.
|
||
//
|
||
|
||
status = IopServiceInstanceToDeviceInstance (serviceHandle,
|
||
NULL,
|
||
InstanceOrdinal,
|
||
NULL,
|
||
&handle,
|
||
KEY_READ
|
||
);
|
||
ZwClose(serviceHandle);
|
||
if (!NT_SUCCESS(status)) {
|
||
goto exit_Local0;
|
||
}
|
||
|
||
//
|
||
// Now determine DeviceInstance flags and return the data
|
||
//
|
||
|
||
IopGetDeviceInstanceCsConfigFlags(
|
||
ServiceKeyName,
|
||
InstanceOrdinal,
|
||
&instanceFlags
|
||
);
|
||
|
||
if (instanceFlags & CSCONFIGFLAG_DO_NOT_CREATE ||
|
||
instanceFlags & CSCONFIGFLAG_DISABLED) {
|
||
instanceFlags = DEVINSTANCE_FLAG_HWPROFILE_DISABLED;
|
||
}
|
||
status = IopGetRegistryValue (handle,
|
||
REGSTR_VALUE_FOUNDATENUM,
|
||
&keyValueInformation
|
||
);
|
||
if (NT_SUCCESS(status)) {
|
||
if (keyValueInformation->DataLength != 0) {
|
||
foundAtEnum = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
|
||
}
|
||
ExFreePool(keyValueInformation);
|
||
} else if (status != STATUS_OBJECT_NAME_NOT_FOUND) {
|
||
goto exit_Local;
|
||
}
|
||
|
||
if (foundAtEnum) {
|
||
instanceFlags |= DEVINSTANCE_FLAG_PNP_ENUMERATED;
|
||
}
|
||
*DeviceInstanceFlags = instanceFlags;
|
||
|
||
//
|
||
// Read Configuration = value and return the data
|
||
//
|
||
|
||
status = IopGetRegistryValue (handle,
|
||
REGSTR_VALUE_CONFIGURATION,
|
||
&keyValueInformation);
|
||
if (NT_SUCCESS(status)) {
|
||
*ActualBufferSize = keyValueInformation->DataLength;
|
||
if (keyValueInformation->DataLength > BufferSize) {
|
||
status = STATUS_BUFFER_TOO_SMALL;
|
||
} else {
|
||
RtlMoveMemory((PUCHAR)Configuration,
|
||
KEY_VALUE_DATA(keyValueInformation),
|
||
keyValueInformation->DataLength
|
||
);
|
||
}
|
||
ExFreePool(keyValueInformation);
|
||
} else if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
|
||
|
||
//
|
||
// If no "Configuration=" value entry, we next check
|
||
// "DetectSignature".
|
||
//
|
||
|
||
status = IopGetRegistryValue (handle,
|
||
REGSTR_VALUE_DETECTSIGNATURE,
|
||
&keyValueInformation);
|
||
if (NT_SUCCESS(status)) {
|
||
*ActualBufferSize = keyValueInformation->DataLength;
|
||
if (keyValueInformation->DataLength > BufferSize) {
|
||
status = STATUS_BUFFER_TOO_SMALL;
|
||
} else {
|
||
RtlMoveMemory((PUCHAR)Configuration,
|
||
KEY_VALUE_DATA(keyValueInformation),
|
||
keyValueInformation->DataLength
|
||
);
|
||
}
|
||
ExFreePool(keyValueInformation);
|
||
} else if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
|
||
|
||
//
|
||
// If no "Configuration=" or "DetectSignature" value entries,
|
||
// we return success with output buffer filled with zero.
|
||
//
|
||
|
||
*ActualBufferSize = 0;
|
||
RtlFillMemory((PUCHAR)Configuration, BufferSize, 0);
|
||
status = STATUS_SUCCESS;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Now read Bus information and return the installed bus information.
|
||
//
|
||
|
||
BusInfo->BusNumber = 0xffffffff;
|
||
BusInfo->BusType = MaximumInterfaceType;
|
||
BusInfo->ConfigurationType = MaximumBusDataType;
|
||
|
||
//
|
||
// Try to find the bus device current device is attached to.
|
||
// Traverse the BaseDevicePath to the bus node to get the information.
|
||
// (In fact, the device handler contains the hidden information.)
|
||
//
|
||
|
||
while (1) {
|
||
status = IopGetRegistryValue (handle,
|
||
REGSTR_VALUE_BASEDEVICEPATH,
|
||
&keyValueInformation
|
||
);
|
||
if (NT_SUCCESS(status)) {
|
||
if (keyValueInformation->Type == REG_SZ) {
|
||
IopRegistryDataToUnicodeString(&unicodeKeyName,
|
||
(PWSTR)KEY_VALUE_DATA(keyValueInformation),
|
||
keyValueInformation->DataLength
|
||
);
|
||
ExFreePool(keyValueInformation);
|
||
|
||
//
|
||
// Open the device path pointed by BaseDevicePath
|
||
//
|
||
|
||
ZwClose(handle);
|
||
if (sysEnumHandle == NULL) {
|
||
status = IopOpenRegistryKey(
|
||
&sysEnumHandle,
|
||
NULL,
|
||
&CmRegistryMachineSystemCurrentControlSetEnumName,
|
||
KEY_READ,
|
||
FALSE
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
goto exit_Local0;
|
||
}
|
||
}
|
||
|
||
status = IopOpenRegistryKey (
|
||
&handle,
|
||
sysEnumHandle,
|
||
&unicodeKeyName,
|
||
KEY_READ,
|
||
FALSE
|
||
);
|
||
if (!NT_SUCCESS(status)) {
|
||
ZwClose(sysEnumHandle);
|
||
goto exit_Local0;
|
||
} else {
|
||
continue;
|
||
}
|
||
} else {
|
||
|
||
//
|
||
// The registry data is bogus. Fail the call.
|
||
//
|
||
|
||
ExFreePool(keyValueInformation);
|
||
goto exit_Local;
|
||
}
|
||
} else if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
|
||
break;
|
||
} else {
|
||
goto exit_Local;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Now reach the bus node (the node without BaseDevicePath value key),
|
||
// retrieve its bus information.
|
||
//
|
||
|
||
status = IopGetRegistryValue (handle,
|
||
REGSTR_VALUE_INTERFACETYPE,
|
||
&keyValueInformation
|
||
);
|
||
if (NT_SUCCESS(status)) {
|
||
if (keyValueInformation->DataLength != 0) {
|
||
BusInfo->BusType = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
|
||
}
|
||
ExFreePool(keyValueInformation);
|
||
}
|
||
|
||
status = IopGetRegistryValue (handle,
|
||
REGSTR_VALUE_SYSTEMBUSNUMBER,
|
||
&keyValueInformation
|
||
);
|
||
if (NT_SUCCESS(status)) {
|
||
if (keyValueInformation->DataLength != 0) {
|
||
BusInfo->BusNumber = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
|
||
}
|
||
ExFreePool(keyValueInformation);
|
||
}
|
||
|
||
status = IopGetRegistryValue (handle,
|
||
REGSTR_VALUE_BUSDATATYPE,
|
||
&keyValueInformation
|
||
);
|
||
if (NT_SUCCESS(status)) {
|
||
if (keyValueInformation->DataLength != 0) {
|
||
BusInfo->ConfigurationType = *(PULONG)KEY_VALUE_DATA(keyValueInformation);
|
||
}
|
||
ExFreePool(keyValueInformation);
|
||
}
|
||
|
||
exit_Local:
|
||
ZwClose(handle);
|
||
exit_Local0:
|
||
ExReleaseResource(&PpRegistryDeviceResource);
|
||
KeLeaveCriticalRegion();
|
||
return status;
|
||
}
|
||
#if _PNP_POWER_STUB_ENABLED_
|
||
|
||
NTSTATUS
|
||
IoQuerySystemInformation(
|
||
IN OUT PIO_SYSTEM_INFORMATION SystemInformation
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Parameters:
|
||
|
||
SystemInformation - Supplies the a pointer to the SYSTEM_INFORMATION
|
||
structure which receives the information about the
|
||
system. Note, the Size field of the SYSTEM_INFORMATION
|
||
structure must be initialized by caller.
|
||
|
||
Return Value:
|
||
|
||
Status code that indicates whether or not the function was successful.
|
||
--*/
|
||
|
||
{
|
||
|
||
SystemInformation->OS = OS_WINDOWS_NT;
|
||
SystemInformation->OSVersion = 0x0400;
|
||
SystemInformation->NumberProcessors = KeNumberProcessors;
|
||
SystemInformation->ProcessorArchitecture = KeProcessorArchitecture;
|
||
SystemInformation->ProcessorLevel = KeProcessorLevel;
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
NTSTATUS
|
||
IoReportDeviceStatus(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN ULONG DeviceStatus
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
PnP device drivers call this API to report any changes in status that
|
||
they detect for a device (e.g., a driver discovers that an adapter has
|
||
been removed when it tries to power it back up after having previously
|
||
powered down the device for power management). When the device status
|
||
is changed, the user mode PnP manager will be notified to take action.
|
||
|
||
Parameters:
|
||
DeviceObject - Supplies the device object whoes device status is to be
|
||
reported. This device object should be the one directly
|
||
associated with the physical device instance. Normally,
|
||
it is the device object created by the HAL bus extender.
|
||
|
||
DeviceStatus - Supplies an ordinala device status code indicating the new
|
||
status of the device. The DeviceStatus code from 0 to
|
||
0x7FFFFFFF are reserved for the system and the code from
|
||
0x80000000 to 0xFFFFFFFF are for private use and will not
|
||
be interpreted by PnP manager.
|
||
|
||
Device Status Codes:
|
||
|
||
#define DEVICE_STATUS_OK 0x00000000
|
||
#define DEVICE_STATUS_MALFUNCTIONED 0x00000001
|
||
#define DEVICE_STATUS_REMOVED 0x00000002
|
||
#define DEVICE_STATUS_DISABLED 0x00000003
|
||
|
||
Return Value:
|
||
|
||
Status code that indicates whether or not the function was successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
#if _PNP_POWER_
|
||
|
||
// Add code here
|
||
|
||
return STATUS_NOT_IMPLEMENTED;
|
||
|
||
#else
|
||
return STATUS_NOT_IMPLEMENTED;
|
||
#endif // _PNP_POWER_
|
||
}
|
||
|
||
NTSTATUS
|
||
IoGetDeviceProperty(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
|
||
IN ULONG BufferLength,
|
||
IN PVOID PropertyBuffer,
|
||
OUT PULONG ResultLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine lets drivers query the registry properties associated with the
|
||
specified device.
|
||
|
||
Parameters:
|
||
|
||
DeviceObject - Supplies the device object whoes registry property is to be
|
||
returned. This device object should be the one created by
|
||
a bus driver.
|
||
|
||
DeviceProperty - Specifies what device property to get.
|
||
|
||
BufferLength - Specifies the length, in byte, of the PropertyBuffer.
|
||
|
||
PropertyBuffer - Supplies a pointer to a buffer to receive property data.
|
||
|
||
ResultLength - Supplies a pointer to a variable to receive the size of the
|
||
property data returned.
|
||
|
||
ReturnValue:
|
||
|
||
Status code that indicates whether or not the function was successful. If
|
||
PropertyBuffer is not big enough to hold requested data, STATUS_BUFFER_OVERFLOW
|
||
will be returned and ResultLength will be set to the number of bytes actually
|
||
required.
|
||
|
||
--*/
|
||
|
||
{
|
||
#if _PNP_POWER_
|
||
|
||
// Add code here
|
||
|
||
return STATUS_NOT_IMPLEMENTED;
|
||
|
||
#else
|
||
|
||
return STATUS_NOT_IMPLEMENTED;
|
||
|
||
#endif // _PNP_POWER_
|
||
}
|
||
|
||
NTSTATUS
|
||
IoSetDeviceProperty(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
|
||
IN PVOID PropertyBuffer,
|
||
IN ULONG BufferLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine lets drivers change the registry properties associated with the
|
||
specified device.
|
||
|
||
Parameters:
|
||
|
||
DeviceObject - Supplies the device object whoes registry property is to be
|
||
returned. This device object should be the one created by
|
||
a bus driver.
|
||
|
||
DeviceProperty - Specifies what device property to set (see below).
|
||
|
||
BufferLength - Specifies the length, in byte, of the PropertyBuffer.
|
||
|
||
PropertyBuffer - Supplies a pointer to a property data buffer.
|
||
|
||
ReturnValue:
|
||
|
||
Status code that indicates whether or not the function was successful.
|
||
This routine returns STATUS_ACCESS_DENIED if it is requested to set a
|
||
read-only property.
|
||
|
||
--*/
|
||
|
||
{
|
||
#if _PNP_POWER_
|
||
|
||
// Add code here
|
||
|
||
return STATUS_NOT_IMPLEMENTED;
|
||
|
||
#else
|
||
|
||
return STATUS_NOT_IMPLEMENTED;
|
||
|
||
#endif // _PNP_POWER_
|
||
}
|
||
|
||
NTSTATUS
|
||
IoRegisterPlugPlayNotification(
|
||
IN IO_NOTIFICATION_EVENT_CATEGORY Event,
|
||
IN LPGUID ResourceType, OPTIONAL
|
||
IN PVOID ResourceDescription, OPTIONAL
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PDRIVER_NOTIFICATION_ENTRY NotificationEntry,
|
||
IN PVOID Context
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This API registers a driver's callback function for a specified pnp event.
|
||
The registered notification record stays registered even after the registered
|
||
event occurred. To remove a registered notification record, the caller must
|
||
call IoUnRegisterPlugPlayNotification.
|
||
|
||
Parameters:
|
||
|
||
Event - Specifies the hardware event catagory that the driver is to be registered.
|
||
|
||
ResourceType - a pointer to a 128 bit GUID specifying the type of resource. If
|
||
HardwareProfileChange is specified for Event, this parameter
|
||
is not used and should be NULL.
|
||
|
||
ResourceDescription - Supplies a pointer to a buffer containing the resource.
|
||
If HardwareProfileChange is specified for Event, this parameter
|
||
is not used and should be NULL.
|
||
|
||
DeviceObject - Specifies a pointer to a device object. This device object
|
||
prevents the driver from being unloaded while it is registered to
|
||
be notified.
|
||
|
||
NotificationEntry - Supplies a pointer to a function which is to be executed
|
||
when the notification occurs.
|
||
|
||
Context - Supplies a pointer to a data structure that is passed to the driver's
|
||
notification entry.
|
||
|
||
Return Value:
|
||
|
||
Status code that indicates whether or not the function was successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
#if _PNP_POWER_
|
||
|
||
// Add code here
|
||
|
||
return STATUS_NOT_IMPLEMENTED;
|
||
|
||
#else
|
||
|
||
return STATUS_NOT_IMPLEMENTED;
|
||
|
||
#endif // _PNP_POWER_
|
||
}
|
||
|
||
NTSTATUS
|
||
IoUnregisterPlugPlayNotification(
|
||
IN IO_NOTIFICATION_EVENT_CATEGORY Event,
|
||
IN LPGUID ResourceType, OPTIONAL
|
||
IN PVOID ResourceDescription, OPTIONAL
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PDRIVER_NOTIFICATION_ENTRY NotificationEntry
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This API removes the event notification registration established via
|
||
IoRegisterPlugPlayNotification API.
|
||
|
||
Parameters:
|
||
|
||
Event - Specifies the hardware event that the driver is to be registered.
|
||
|
||
ResourceType - a 128 bit GUID specifying the type of resource. If
|
||
HardwareProfileChange is specified for Event, this parameter
|
||
is not used and should be NULL.
|
||
|
||
ResourceDescription - Supplies a pointer to a buffer containing the resource.
|
||
If HardwareProfileChange is specified for Event, this parameter
|
||
is not used and should be NULL.
|
||
|
||
DeviceObject - Specifies a pointer to the a device object which passed to the
|
||
IoRegisterPlugPlayNotification.
|
||
|
||
NotificationEntry - Supplies a pointer to a function which is to be executed
|
||
when the notification occurs.
|
||
|
||
|
||
Return Value:
|
||
|
||
Status code that indicates whether or not the function was successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
#if _PNP_POWER_
|
||
|
||
// Add code here
|
||
|
||
return STATUS_NOT_IMPLEMENTED;
|
||
|
||
#else
|
||
|
||
return STATUS_NOT_IMPLEMENTED;
|
||
|
||
#endif // _PNP_POWER_
|
||
}
|
||
#endif // _PNP_POWER_STUB_ENABLED_
|