Virtual disk + DefineDosDevice + Windows 7

Тема в разделе "WASM.NT.KERNEL", создана пользователем jakegreen, 14 мар 2012.

  1. jakegreen

    jakegreen New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2010
    Сообщения:
    3
    Добрый день!
    Есть драйвер виртуального диска (тип устройства FILE_DEVICE_DISK, обрабатываю IRP_MJ_READ, IRP_MJ_WRITE, IOCTL_DISK_* и др.), букву тома ассоциирую с именем устройства юзермодной функцией DefineDosDevice().
    В Windows Xp диск виден в explorer, есть возможность отформатировать его в нужную ФС и работать с ним.
    В Windows 7 следующие проблемы:
    1) Диск виден в explorer только в случае вызовы DefineDosDevice() из под процесса не имеющего привилегий UAC
    2) При попытке отформативароть диск выскакивает сообщение "Windows can't format J. Check to see that the disk and drive are connected properly, make sure that the disk is not read-only, and then try again. For more information, search Help for read-only files and how to change them"
    Может кто-то уже сталкивался с подобным. Заранее спасибо за помощь.
     
  2. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Legacy что ли?
    Ололо, намучаешься ты с ним.
    Я бы переписал на WDM, пока не поздно.

    Ещё бы.

    И это ещё не все проблемы, которые могут вылезти.

    Эту фразу что-то я не догоняю. Т.е. я правильно понимаю, что UAC включён (какой уровень, кстати?), ты вызываешь DefineDosDevice() из процесса, запущенного "от имени администратора", и при этом твой виртуальный том не появляется в Проводнике, так? Или нет? Поясни.

    Обычно, при вызове IoCreateDevice() система создаёт девайс, который имеет стандартный дескриптор безопасности. В таком дескрипторе нет ничего на тему текущего пользователя, там есть только сильно урезанные права для "Все" и полные права для админов и системы. Я, в своё время, решил проблему просто: после создания девайса я беру токен текущего потока (т.е. потока, который принадлежит процессу моего управляющего приложения, в контексте которого шлётся IOCTL, заставляя драйвер создать том) и добавляю запись (ACE) в его дескриптор безопасности о том, что де такому-то пользователю разрешить FILE_ALL_ACCESS. Насколько я помню, этого достаточно, хотя может я и ещё что-то там крутил, не могу сказать точно, надо в исходниках копаться.
     
  3. jakegreen

    jakegreen New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2010
    Сообщения:
    3
    Аналог filedisk

    ага, уровень UAC дефолтный. p.s. диск виден в случае рестарта explorer "от имени администратора", нужно думать как выполнять DefineDosDevice() от имени текущего пользователя...

    думаю, может предварительно форматировать контейнер своими силами как truecrypt сделано появилась возможность форматировать диск через оболочку после добавления нотификации из приложения:
    Код (Text):
    1. SHChangeNotify(SHCNE_DRIVEADD, SHCNF_PATH, "X:\\", NULL);
     
  4. jakegreen

    jakegreen New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2010
    Сообщения:
    3
    Другая проблема, которая затрагивает все системы, - мой минифильтр ФС (аналог WinDDK\7600.16385.1\src\filesys\miniFilter\passThrough), "не видит" этот виртуальный диск. На минильтр грешить не стоит, т.к. у него нет проблем с другими дисками, в т.ч. виртуальными от трукрипта. Есть идеи, может в драйвере виртуального диска нужно обрабатывать IRP_MJ_PNP или что-то подобное? Если это как-то поможет, минифильтр и виртуальный диск представляют один девайс и физически располагаются в одном файле.

    add: очень много запросов IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, может в его обработчике бока:
    Код (Text):
    1. case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
    2.     {
    3.         if(pIrpStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(USHORT) + sizeof(SERVICE_DEVICE))
    4.         {
    5.             ((PMOUNTDEV_NAME)pIrp->AssociatedIrp.SystemBuffer)->NameLength = sizeof(SERVICE_DEVICE);
    6.             RtlCopyMemory(((PMOUNTDEV_NAME)pIrp->AssociatedIrp.SystemBuffer)->Name, SERVICE_DEVICE, sizeof(SERVICE_DEVICE));
    7.             NtStatus = STATUS_SUCCESS;
    8.             pIrp->IoStatus.Information = sizeof(USHORT) + sizeof(SERVICE_DEVICE);
    9.         }
    10.         else
    11.         {
    12.             NtStatus = STATUS_BUFFER_TOO_SMALL;
    13.             pIrp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
    14.         }
    15.         DbgPrint("IOCTL_MOUNTDEV_QUERY_DEVICE_NAME: NtStatus=%.08X\n", NtStatus);
    16.         break;
    17.     }
    В принципе, можно в минифильтре ФС индентифицировать виртуальный диск по адресу его девайса, но решение не очень...
     
  5. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    jakegreen
    Файловый фильтр будет "видеть" виртуальный том только если на нём монтируется какая-либо файловая система, т.е. если ты его ещё не отформатировал, то чего ж ты хочешь от фильтра, что фильтровать-то? Запросы IRP_MJ_PNP обрабатывать стоит, но для других целей, а к твоей проблеме это отношения, думаю, что не имеет. Что значит "представляют один девайс" - это вообще ересь какая-то. По поводу IOCTL_MOUNTDEV_QUERY_DEVICE_NAME - да, обрабатываешь неправильно, там в случае, когда часть данных (но не все) помещается в выходном буфере, следует возвращать статус STATUS_BUFFER_OVERFLOW, а не STATUS_SUCCESS, тогда Mount Manager пошлёт второй запрос с этим же кодом, но с буфером достаточного размера. Статус STATUS_BUFFER_TOO_SMALL можно возвращать только тогда, когда вообще никаких данных записать в буфер не удаётся. Кроме того, если ты возвращаешь любой ошибочный статус (т.е. статус, для которого NT_ERROR(...) равно TRUE), то заполнять IoStatus.Information не имеет смысла, лучше сразу 0 туда ставить. Вообще, общение с Mount Manager-ом достаточно строгое, чуть не то ему отправишь, что он ожидает, и всё, эффекта не получишь.