Может ли функция CreateFile открыть дескриптор для устройств, которые перечислены только в списке «Глобальные»?каталог в утилите WinObj? - PullRequest
0 голосов
/ 31 мая 2018

Вы знаете - в C ++ вы можете получить дескриптор устройства ввода-вывода, передав его путь в качестве первого параметра в вызове функции CreateFile.Но мне интересно, как CreateFile находит и идентифицирует устройство по указанному пути.Однажды я узнал кое-что об этой теме с помощью утилиты WinObj, что, вероятно, является правдой.
В WinObj есть каталог с именем Global ?? , который находится в корневом каталоге и может бытьвидно на левой панели.Этот каталог содержит множество элементов типа «SymbolicLink».
Когда вы передаете путь к устройству ввода-вывода (например, «\. \ C:» или «\. \ Changer0») в качестве первого параметра вПри вызове функции CreateFile функция CreateFile анализирует путь и удаляет из него «\. \», чтобы найти часть пути.Затем он ищет в каталоге Global ?? SymbolicLink с тем же именем, что и эта часть.Затем он находит адрес, на который ссылается символическая ссылка, который является основным именем объекта физического устройства (например, "\ Device \ CdRom0").
Итак, верно ли мое обнаружение?Являются ли устройства, содержащиеся в каталоге Global ?? , единственными устройствами, которые может открыть функция CreateFile?Просто упомянуть кое-что: не все элементы в каталоге Global ?? относятся к устройству, я полагаю.

Вторая часть моего вопроса

Однажды я захотел программно уменьшить яркость экрана моего монитора, отправив контрольный код IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS на мой монитор.Проблема заключалась в том, что я не знал, что указать для первого параметра функции CreateFile.Поэтому я сделал следующее:

  1. Я открыл Диспетчер устройств и обнаружил мое устройство монитора в списке.Имя этого устройства было «Универсальный монитор без PnP».
  2. Я щелкнул правой кнопкой мыши по этому элементу списка и нажал на Свойства .
  3. В СвойствахВ окне я нажал на вкладку Подробно .Затем я выбрал Имя объекта физического устройства из раскрывающегося списка Свойство .
  4. В разделе значений я нашел текст "\ Device \ 0000006f".
  5. В WinObj я искал каталог Global ?? для SymbolicLink, который ссылается на "\ Device \ 0000006f".Имя этого SymbolicLink было длинным:

DISPLAY # Default_Monitor # 5 & 1193a8c7 & 0 & UID100663553 # {866519b5-3f07-4c97-b7df-24c5d8a8ccb8}

Затем я поставил «\. \» Перед вышеупомянутым именем SymbolicLink и указал его в качестве первого параметра функции CreateFile.

Есть идеи о том, как выполнить все эти операции программно?Я хочу, чтобы моя программа сама получила значение параметра lpFileName.Я не помещаю эту строку непосредственно в исходный код моей программы.

1 Ответ

0 голосов
/ 31 мая 2018

сначала в 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;
        }
    }
}
...