сначала в CreateFile
мы можем использовать любое имя из пространства имен NT, если префикс его с \\?\globalroot
или даже лучше \\?\global\globalroot
префикс.скажем, если мы хотим открыть \Device\0000006f
, мы можем использовать \\?\globalroot\Device\0000006f
или \\?\global\globalroot\Device\0000006f
имя.система win32 при преобразовании пути win32 в NT-путь - если префикс '\? `view - просто преобразует его в \??\
.поэтому путь nt будет выглядеть как \??\[global\]globalroot\Device\0000006f
.\??
- это виртуальный каталог - он не существует на самом деле.Диспетчер объектов ищет в Локальные и глобальные имена устройств MS-DOS при просмотре \??\
.сначала в локальном (который выглядит как \Sessions\0\DosDevices\<luid>
) и, если не найден в глобальном - \GLOBAL??
.однако в любом локальном каталоге устройства DOS существует символическая ссылка Global
, которая указывает на \Global??
.в результате после разбора \??\global
мы будем перенаправлены на \Global??
.затем в папке \Global??
существует символическая ссылка GLOBALROOT
, которая пуста - указывает на корень пространства имен NT.в результате после разбора \\?\global\globalroot\Device\0000006f
будет повторно проанализирован до \Device\0000006f
и \\?\globalroot\Device\0000006f
также, если в пространстве имен локального устройства нет объекта globalroot
(обычно его не существует, но вдруг кто-то его создает).
Теперь о том, как открыть монитор устройства.мы не должны жестко кодировать любое имя устройства.вместо этого нам нужен поиск устройств, которые поддерживают GUID_DEVINTERFACE_MONITOR
по вызову CM_Get_Device_Interface_ListW
и использовать возвращенное имя в вызове CreateFile
#include <ntddvdeo.h>
CONFIGRET EnumMonitors()
{
CONFIGRET err;
static volatile UCHAR guz;
PVOID stack = alloca(guz);
ULONG BufferLen = 0, NeedLen = 128;
union {
PVOID buf;
PWSTR pszDeviceInterface;
};
for(;;)
{
if (BufferLen < NeedLen)
{
BufferLen = RtlPointerToOffset(buf = alloca((NeedLen - BufferLen) * sizeof(WCHAR)), stack) / sizeof(WCHAR);
}
switch (err = CM_Get_Device_Interface_ListW(const_cast<PGUID>(&GUID_DEVINTERFACE_MONITOR),
0, pszDeviceInterface, BufferLen, CM_GET_DEVICE_INTERFACE_LIST_PRESENT))
{
case CR_BUFFER_SMALL:
if (err = CM_Get_Device_Interface_List_SizeW(&NeedLen, const_cast<PGUID>(&GUID_DEVINTERFACE_MONITOR),
0, CM_GET_DEVICE_INTERFACE_LIST_PRESENT))
{
default:
return err;
}
continue;
case CR_SUCCESS:
while (*pszDeviceInterface)
{
HANDLE hFile = CreateFileW(pszDeviceInterface, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, 0,
OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
OVERLAPPED ov = {};
DISPLAY_BRIGHTNESS db;
DeviceIoControl(hFile, IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS, 0, 0,
&db, sizeof(db), 0, &ov);
CloseHandle(hFile);
DbgPrint("(%x,%x,%x) %S\n", db.ucDisplayPolicy, db.ucACBrightness, db.ucDCBrightness, pszDeviceInterface);
}
pszDeviceInterface += 1 + wcslen(pszDeviceInterface);
}
return 0;
}
}
}