Как взаимодействовать с диспетчером монтирования NT, чтобы назначить букву диска? - PullRequest
4 голосов
/ 30 марта 2012

Я пытаюсь заменить какой-то устаревший код DefineDosDevice пользовательского пространства (который не работает в Vista с пользователями Администратора из-за того, что повышенный и обычный сеанс представлен различными хранилищами DosDevice, поэтому создается довольно странный сценарий что диск виден, если он создан из неуровневых процессов, но невидим, если он создан из процесса с повышенными правами).

Замена этого, как я выяснил из проверки источника Truecrypt и этого примера WDM , заключается в выдаче IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION сообщений на mountmgr.sys, а затем IOCTL_MOUNTMGR_CREATE_POINT / IOCTL_MOUNTMGR_DELETE_POINT.

Так вот, что я делаю - мой код выглядит так:

Во-первых, различные местные жители:

NTSTATUS ntStatus;
PDEVICE_EXTENSION device_extension;
UNICODE_STRING uVolumeName;

ULONG mntNameLen = 0;
ULONG mntPointLen = 0;
PMOUNTMGR_TARGET_NAME mntName = NULL;
PMOUNTMGR_CREATE_POINT_INPUT mntPoint =  NULL;

Затем я строю и делаю два моих запроса. Первый сбой с указанным кодом состояния. Второй сбой с другим кодом состояния (но он не будет работать, если первый сбой).

mntNameLen = sizeof(MOUNTMGR_TARGET_NAME) + device_extension->sDevName.Length;
mntName = ExAllocatePool(PagedPool, mntNameLen);

mntName->DeviceNameLength = device_extension->sDevName.Length;
RtlCopyMemory(mntName->DeviceName, device_extension->sDevName.Buffer, 
              mntName->DeviceNameLength);

ntStatus = MakeDeviceIoRequest (MOUNTMGR_DEVICE_NAME, 
    IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION,
    mntName, mntNameLen, 0, 0);

mntPointLen = sizeof(PMOUNTMGR_CREATE_POINT_INPUT) + 
    device_extension->sDevName.Length + uVolumeName.Length;
mntPoint = ExAllocatePool(PagedPool, mntPointLen);

mntPoint->SymbolicLinkNameOffset = sizeof (MOUNTMGR_CREATE_POINT_INPUT);
RtlCopyMemory(&mntPoint+mntPoint->SymbolicLinkNameOffset, 
    uVolumeName.Buffer, uVolumeName.Length * sizeof(WCHAR));
mntPoint->SymbolicLinkNameLength = uVolumeName.Length;

mntPoint->DeviceNameOffset = mntPoint->SymbolicLinkNameOffset + 
    mntPoint->SymbolicLinkNameLength;
RtlCopyMemory(&mntPoint+mntPoint->DeviceNameOffset, 
    device_extension->sDevName.Buffer, device_extension->sDevName.Length);
mntPoint->DeviceNameLength = device_extension->sDevName.Length;

ntStatus = MakeDeviceIoRequest(MOUNTMGR_DEVICE_NAME, 
    IOCTL_MOUNTMGR_CREATE_POINT, mntPoint,
mntPointLen, 0, 0);

Затем я создаю символическую ссылку \ GLOBAL ?? \ L: -> \ Device \ DeviceName

ntStatus = IoCreateSymbolicLink(&uVolumeName, &(device_extension->sDevName));
DbgPrint("Mapped %wZ -> %wZ\n", &uVolumeName, &(device_extension->sDevName));
RtlFreeUnicodeString(&uVolumeName);
if ( mntName != NULL )
{
    ExFreePool(mntName);
}
if ( mntPoint != NULL)
{
    ExFreePool(mntPoint);
}

Тем не менее, ntStatus ответ от менеджера монтирования - 0xC0000010 STATUS_INVALID_DEVICE_REQUEST; строка моего устройства имеет вид \Device\DevName и отвечает каждому из:

  • IOCTL_VOLUME_ONLINE
  • IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
  • IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
  • IOCTL_MOUNTDEV_QUERY_DEVICE_NAME

и список других IOCTL, ожидаемых для устройства хранения. Однако на всех этих подпрограммах установлены точки останова, и ни одна из них не достигнута.

Мое устройство создано с помощью этого небольшого фрагмента:

// Security descriptor
RtlInitUnicodeString(&sddl,
     _T("D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;BU)(A;;GA;;;WD)"));

// named device
status = IoCreateDeviceSecure(
    DriverObject, 
    sizeof(DEVICE_EXTENSION),
    &device_name,     // \Device\DeviceName
    DeviceType,       // valid devicetype.
    0,
    FALSE,
    &sddl,            // security descriptor
    NULL,             // no idea what this does.
    &device_object    // output device object.
);

Итак, перейдем к некоторым вопросам:

  1. Правильно ли я создаю сообщения для менеджера монтирования? Вызов MakeDeviceIoRequest в основном охватывает IoCallDriver, и я достаточно уверен, что это не проблема.
  2. Что-то, что я делаю с CreateDevice, является проблемой? Я спрашиваю, потому что я прочитал эту запись в блоге , которая подразумевает что-то об именах устройств, FDO и PDO, что я, честно говоря, не совсем понимаю.
  3. Если мне кажется, что я слишком глубоко, есть ли шанс уточнить мое понимание того, как все это работает?

Примечания : У меня есть некоторые ограничения. Код, над которым я работаю, довольно унаследован, поэтому я включаю ntddk.h and wdmsec.h; На данном этапе я не могу изменить их на wdm.h или ntifs.h.

1 Ответ

2 голосов
/ 30 марта 2012

Прежде чем углубляться в это, есть ли шанс, что вы сможете перевести свои звонки в DefineDosDevice в службу?Вызов из службы помещает ссылку в глобальный каталог, который полностью избавит вас от проблемы с алиасами, которая у вас есть.

Если вы не можете этого сделать, я думаю, что вы не обрабатываетекакой-то другой требуемый менеджер монтирования IOCTL.Я знаю, что у вас есть точки останова на всех конкретных IOCTL, но есть ли у вас точка останова в обработчике по умолчанию?Обычно именно отсюда происходит STATUS_INVALID_DEVICE_REQUEST.

...