mirror of
https://github.com/reactos/reactos.git
synced 2024-08-28 14:18:41 +00:00
![Pierre Schweitzer](/assets/img/avatar_default.png)
floppy drives in ReactOS and mount images on them. Only the cmd got imported. The GUI interface may come later on. Note that, as for vcdrom, the driver is left disabled and you need to explicitely start it through vfd command line interface. CORE-14090
666 lines
16 KiB
C
666 lines
16 KiB
C
/*
|
|
vfdmnt.c
|
|
|
|
Virtual Floppy Drive for Windows NT platform
|
|
Kernel mode driver mount manager functions
|
|
|
|
Copyright (C) 2003-2005 Ken Kato
|
|
*/
|
|
|
|
#ifndef VFD_MOUNT_MANAGER
|
|
/*
|
|
Not in working order for the time being
|
|
so DO NOT define VFD_MOUNT_MANAGER macro
|
|
unless you know exactly what you are doing...
|
|
*/
|
|
#ifdef _MSC_VER
|
|
// suppress empty compile unit warning
|
|
#pragma warning (disable: 4206)
|
|
#pragma message ("Mount Manager support feature is disabled.")
|
|
#endif
|
|
|
|
#else // VFD_MOUNT_MANAGER
|
|
/*
|
|
The flow of the drive letter assignment via the Mount Manager
|
|
during the VFD driver start up
|
|
|
|
1) IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION VFD -> MM
|
|
notifies the mount manager of VFD devices.
|
|
|
|
2) IOCTL_MOUNTDEV_QUERY_DEVICE_NAME VFD <- MM
|
|
device name (\Device\Floppy<x>) VFD -> MM
|
|
|
|
3) IOCTL_MOUNTDEV_QUERY_UNIQUE_ID VFD <- MM
|
|
device unique ID (\??\VirtualFD<x>) VFD -> MM
|
|
|
|
4) IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME VFD <- MM
|
|
drive letter link (\DosDevices\<x>:) VFD -> MM
|
|
|
|
5) The mount manager creates the drive letter link
|
|
|
|
6) IOCTL_MOUNTDEV_LINK_CREATED VFD <- MM
|
|
The driver stores the created drive letter
|
|
|
|
The flow of the drive letter operation with IOCTL_VFD_SET_LINK
|
|
|
|
1) IOCTL_MOUNTMGR_CREATE_POINT or
|
|
IOCTL_MOUNTMGR_DELETE_POINTS VFD -> MM
|
|
|
|
2) The mount manager creates/deletes the drive letter link
|
|
|
|
3) IOCTL_MOUNTDEV_LINK_CREATED or
|
|
IOCTL_MOUNTDEV_LINK_DELETED VFD <- MM
|
|
The driver stores the created/deleted drive letter
|
|
*/
|
|
|
|
#include "imports.h"
|
|
#include "vfddrv.h"
|
|
#include "vfddbg.h"
|
|
|
|
//
|
|
// Call the mount manager with an IO control IRP
|
|
//
|
|
static NTSTATUS
|
|
VfdMountMgrSendRequest(
|
|
ULONG ControlCode,
|
|
PVOID InputBuffer,
|
|
ULONG InputLength,
|
|
PVOID OutputBuffer,
|
|
ULONG OutputLength);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
//#pragma alloc_text(PAGE, VfdRegisterMountManager)
|
|
#pragma alloc_text(PAGE, VfdMountMgrNotifyVolume)
|
|
#pragma alloc_text(PAGE, VfdMountMgrMountPoint)
|
|
#pragma alloc_text(PAGE, VfdMountMgrSendRequest)
|
|
#pragma alloc_text(PAGE, VfdMountDevUniqueId)
|
|
#pragma alloc_text(PAGE, VfdMountDevDeviceName)
|
|
#pragma alloc_text(PAGE, VfdMountDevSuggestedLink)
|
|
#pragma alloc_text(PAGE, VfdMountDevLinkModified)
|
|
#endif // ALLOC_PRAGMA
|
|
|
|
/*
|
|
#include <initguid.h>
|
|
#include <mountmgr.h>
|
|
//
|
|
// register a device to the mount manager interface
|
|
// does not work...
|
|
//
|
|
NTSTATUS
|
|
VfdRegisterMountManager(
|
|
PDEVICE_EXTENSION DeviceExtension)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
UNICODE_STRING interface;
|
|
UNICODE_STRING interface2;
|
|
|
|
VFDTRACE(VFDINFO,
|
|
("[VFD] Registering %ws to the Mount Manager Interface\n",
|
|
DeviceExtension->DeviceName.Buffer));
|
|
|
|
RtlInitUnicodeString(&interface, NULL);
|
|
|
|
status = IoRegisterDeviceInterface(
|
|
DeviceExtension->DeviceObject,
|
|
(LPGUID)&MOUNTDEV_MOUNTED_DEVICE_GUID,
|
|
NULL,
|
|
&interface);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
VFDTRACE(0,
|
|
("[VFD] IoRegisterDeviceInterface - %s\n",
|
|
GetStatusName(status)));
|
|
return status;
|
|
}
|
|
|
|
status = IoSetDeviceInterfaceState(&interface, TRUE);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
if (VfdCopyUnicode(&interface2, &interface)) {
|
|
VFDTRACE(VFDINFO,
|
|
("[VFD] Interface: %ws\n", interface2.Buffer));
|
|
}
|
|
else {
|
|
VFDTRACE(0,
|
|
("[VFD] Failed to allocate an interface name buffer\n"));
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
}
|
|
else {
|
|
VFDTRACE(0,
|
|
("[VFD] IoSetDeviceInterfaceState - %s\n",
|
|
GetStatusName(status)));
|
|
}
|
|
|
|
RtlFreeUnicodeString(&interface);
|
|
VfdFreeUnicode(&interface2);
|
|
|
|
return status;
|
|
}
|
|
*/
|
|
|
|
//
|
|
// informs the Mount Manager of a new VFD device
|
|
//
|
|
NTSTATUS
|
|
VfdMountMgrNotifyVolume(
|
|
PDEVICE_EXTENSION DeviceExtension)
|
|
{
|
|
PMOUNTMGR_TARGET_NAME target_name;
|
|
USHORT target_name_buf[MAXIMUM_FILENAME_LENGTH];
|
|
NTSTATUS status;
|
|
|
|
VFDTRACE(VFDINFO,
|
|
("[VFD] VfdMountMgrNotifyVolume - %ws\n",
|
|
DeviceExtension->DeviceName.Buffer));
|
|
|
|
target_name = (PMOUNTMGR_TARGET_NAME)target_name_buf;
|
|
|
|
target_name->DeviceNameLength =
|
|
DeviceExtension->DeviceName.Length;
|
|
|
|
RtlCopyMemory(
|
|
target_name->DeviceName,
|
|
DeviceExtension->DeviceName.Buffer,
|
|
DeviceExtension->DeviceName.Length);
|
|
|
|
status = VfdMountMgrSendRequest(
|
|
IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION,
|
|
target_name,
|
|
sizeof(target_name->DeviceNameLength) + target_name->DeviceNameLength,
|
|
NULL,
|
|
0);
|
|
|
|
VFDTRACE(VFDINFO,
|
|
("[VFD] VfdMountMgrNotifyVolume - %s\n",
|
|
GetStatusName(status)));
|
|
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// Create / remove a drive letter via the Mount Manager
|
|
//
|
|
NTSTATUS
|
|
VfdMountMgrMountPoint(
|
|
PDEVICE_EXTENSION DeviceExtension,
|
|
CHAR DriveLetter)
|
|
{
|
|
ULONG alloc_size;
|
|
UNICODE_STRING link_name;
|
|
WCHAR link_buf[20];
|
|
NTSTATUS status;
|
|
|
|
VFDTRACE(VFDINFO, ("[VFD] VfdMountMgrMountPoint - IN\n"));
|
|
|
|
// convert lower case into upper case
|
|
|
|
if (DriveLetter >= 'a' && DriveLetter <= 'z') {
|
|
DriveLetter -= ('a' - 'A');
|
|
}
|
|
|
|
if (DriveLetter >= 'A' && DriveLetter <= 'Z') {
|
|
|
|
// Create a new drive letter
|
|
|
|
PMOUNTMGR_CREATE_POINT_INPUT create;
|
|
|
|
swprintf(link_buf, L"\\DosDevices\\%wc:", DriveLetter);
|
|
|
|
RtlInitUnicodeString(&link_name, link_buf);
|
|
|
|
VFDTRACE(VFDINFO,
|
|
("[VFD] Creating a link: %ws => %ws\n",
|
|
link_buf, DeviceExtension->DeviceName.Buffer));
|
|
|
|
// allocate buffer for MOUNTMGR_CREATE_POINT_INPUT
|
|
|
|
alloc_size = sizeof(MOUNTMGR_CREATE_POINT_INPUT) +
|
|
link_name.Length + DeviceExtension->DeviceName.Length;
|
|
|
|
create = (PMOUNTMGR_CREATE_POINT_INPUT)ExAllocatePoolWithTag(
|
|
NonPagedPool, alloc_size, VFD_POOL_TAG);
|
|
|
|
if (!create) {
|
|
VFDTRACE(0, ("[VFD] Failed to allocate mount point input\n"));
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
// set the symbolic link name
|
|
|
|
create->SymbolicLinkNameOffset = sizeof(MOUNTMGR_CREATE_POINT_INPUT);
|
|
create->SymbolicLinkNameLength = link_name.Length;
|
|
|
|
RtlCopyMemory(
|
|
(PCHAR)create + create->SymbolicLinkNameOffset,
|
|
link_name.Buffer,
|
|
link_name.Length);
|
|
|
|
// set the target device name
|
|
|
|
create->DeviceNameOffset = (USHORT)
|
|
(create->SymbolicLinkNameOffset + create->SymbolicLinkNameLength);
|
|
create->DeviceNameLength = DeviceExtension->DeviceName.Length;
|
|
|
|
RtlCopyMemory(
|
|
(PCHAR)create + create->DeviceNameOffset,
|
|
DeviceExtension->DeviceName.Buffer,
|
|
DeviceExtension->DeviceName.Length);
|
|
|
|
// call the mount manager with the IO control request
|
|
|
|
status = VfdMountMgrSendRequest(
|
|
IOCTL_MOUNTMGR_CREATE_POINT,
|
|
create, alloc_size, NULL, 0);
|
|
|
|
ExFreePool(create);
|
|
|
|
// no need to set the new drive letter into the
|
|
// DeviceExtension because the mount manager will issue an
|
|
// IOCTL_MOUNTDEV_LINK_CREATED and it will be processed then
|
|
}
|
|
else if (DriveLetter == 0) {
|
|
|
|
// Delete the existing drive letter
|
|
|
|
PMOUNTMGR_MOUNT_POINT mount;
|
|
PMOUNTMGR_MOUNT_POINTS points;
|
|
UNICODE_STRING unique_id;
|
|
WCHAR unique_buf[20];
|
|
|
|
swprintf(link_buf, L"\\DosDevices\\%wc:",
|
|
DeviceExtension->DriveLetter);
|
|
|
|
VFDTRACE(VFDINFO,
|
|
("[VFD] Deleting link: %ws\n", link_buf));
|
|
|
|
RtlInitUnicodeString(&link_name, link_buf);
|
|
|
|
swprintf(unique_buf, L"\\??\\" VFD_DEVICE_BASENAME L"%lu",
|
|
DeviceExtension->DeviceNumber);
|
|
|
|
RtlInitUnicodeString(&unique_id, unique_buf);
|
|
|
|
// allocate buffer for MOUNTMGR_MOUNT_POINT
|
|
|
|
alloc_size = sizeof(MOUNTMGR_MOUNT_POINT) +
|
|
link_name.Length +
|
|
unique_id.Length +
|
|
DeviceExtension->DeviceName.Length;
|
|
|
|
mount = (PMOUNTMGR_MOUNT_POINT)ExAllocatePoolWithTag(
|
|
NonPagedPool, alloc_size, VFD_POOL_TAG);
|
|
|
|
if (!mount) {
|
|
VFDTRACE(0, ("[VFD] Failed to allocate mount point input\n"));
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlZeroMemory(mount, alloc_size + sizeof(WCHAR));
|
|
|
|
// set the symbolic link name
|
|
|
|
mount->SymbolicLinkNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
|
|
mount->SymbolicLinkNameLength = link_name.Length;
|
|
|
|
RtlCopyMemory(
|
|
(PCHAR)mount + mount->SymbolicLinkNameOffset,
|
|
link_name.Buffer, link_name.Length);
|
|
|
|
// set the unique id
|
|
|
|
mount->UniqueIdOffset =
|
|
mount->SymbolicLinkNameOffset +
|
|
mount->SymbolicLinkNameLength;
|
|
mount->UniqueIdLength = unique_id.Length;
|
|
|
|
RtlCopyMemory(
|
|
(PCHAR)mount + mount->UniqueIdOffset,
|
|
unique_id.Buffer, unique_id.Length);
|
|
|
|
// set the target device name
|
|
|
|
mount->DeviceNameOffset =
|
|
mount->UniqueIdOffset +
|
|
mount->UniqueIdLength;
|
|
mount->DeviceNameLength =
|
|
DeviceExtension->DeviceName.Length;
|
|
|
|
RtlCopyMemory(
|
|
(PCHAR)mount + mount->DeviceNameOffset,
|
|
DeviceExtension->DeviceName.Buffer,
|
|
DeviceExtension->DeviceName.Length);
|
|
|
|
// prepare the output buffer
|
|
|
|
points = (PMOUNTMGR_MOUNT_POINTS)ExAllocatePoolWithTag(
|
|
NonPagedPool, alloc_size * 2, VFD_POOL_TAG);
|
|
|
|
status = VfdMountMgrSendRequest(
|
|
IOCTL_MOUNTMGR_DELETE_POINTS,
|
|
mount, alloc_size, points, alloc_size * 2);
|
|
|
|
ExFreePool(mount);
|
|
ExFreePool(points);
|
|
|
|
if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
|
|
// the drive letter did not exist in the first place
|
|
DeviceExtension->DriveLetter = 0;
|
|
}
|
|
|
|
// no need to clear the drive letter in the
|
|
// DeviceExtension because the mount manager will issue an
|
|
// IOCTL_MOUNTDEV_LINK_DELETED and it will be processed then
|
|
}
|
|
else {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
VFDTRACE(VFDINFO, ("[VFD] VfdMountMgrMountPoint - %s\n",
|
|
GetStatusName(status)));
|
|
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// send a request to the Mount Manager
|
|
//
|
|
NTSTATUS
|
|
VfdMountMgrSendRequest(
|
|
ULONG ControlCode,
|
|
PVOID InputBuffer,
|
|
ULONG InputLength,
|
|
PVOID OutputBuffer,
|
|
ULONG OutputLength)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
UNICODE_STRING mntmgr_name;
|
|
PDEVICE_OBJECT mntmgr_dev;
|
|
PFILE_OBJECT mntmgr_file;
|
|
IO_STATUS_BLOCK io_status;
|
|
KEVENT event;
|
|
PIRP irp;
|
|
|
|
// Obtain a pointer to the Mount Manager device object
|
|
|
|
RtlInitUnicodeString(
|
|
&mntmgr_name,
|
|
MOUNTMGR_DEVICE_NAME);
|
|
|
|
status = IoGetDeviceObjectPointer(
|
|
&mntmgr_name,
|
|
FILE_READ_ATTRIBUTES,
|
|
&mntmgr_file,
|
|
&mntmgr_dev);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
VFDTRACE(VFDWARN,
|
|
("[VFD] IoGetDeviceObjectPointer - %s\n", GetStatusName(status)));
|
|
return status;
|
|
}
|
|
|
|
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
|
|
|
// Create an IRP request block
|
|
|
|
irp = IoBuildDeviceIoControlRequest(
|
|
ControlCode,
|
|
mntmgr_dev,
|
|
InputBuffer,
|
|
InputLength,
|
|
OutputBuffer,
|
|
OutputLength,
|
|
FALSE,
|
|
&event,
|
|
&io_status);
|
|
|
|
if (!irp) {
|
|
VFDTRACE(VFDWARN,
|
|
("[VFD] IoBuildDeviceIoControlRequest\n"));
|
|
ObDereferenceObject(mntmgr_file);
|
|
return STATUS_DRIVER_INTERNAL_ERROR;
|
|
}
|
|
|
|
// Call the mount manager
|
|
|
|
status = IoCallDriver(mntmgr_dev, irp);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
VFDTRACE(VFDWARN,
|
|
("[VFD] IoCallDriver - %s\n", GetStatusName(status)));
|
|
}
|
|
|
|
if (status == STATUS_PENDING) {
|
|
|
|
// Wait for the operation to complete
|
|
|
|
KeWaitForSingleObject(
|
|
&event, Executive, KernelMode, FALSE, NULL);
|
|
|
|
status = io_status.Status;
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
VFDTRACE(VFDWARN,
|
|
("[VFD] IoCallDriver - %s\n", GetStatusName(status)));
|
|
}
|
|
}
|
|
|
|
ObDereferenceObject(mntmgr_file);
|
|
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
|
|
// -- use the device interface link (\??\VirtualFD<x>) as the unique ID
|
|
//
|
|
NTSTATUS
|
|
VfdMountDevUniqueId(
|
|
PDEVICE_EXTENSION DeviceExtension,
|
|
PMOUNTDEV_UNIQUE_ID UniqueId,
|
|
ULONG OutputLength,
|
|
PIO_STATUS_BLOCK IoStatus)
|
|
{
|
|
WCHAR buf[20];
|
|
UNICODE_STRING unicode;
|
|
|
|
if (OutputLength < sizeof(MOUNTDEV_UNIQUE_ID)) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
swprintf(buf,
|
|
L"\\??\\" VFD_DEVICE_BASENAME L"%lu",
|
|
DeviceExtension->DeviceNumber);
|
|
|
|
RtlInitUnicodeString(&unicode, buf);
|
|
|
|
UniqueId->UniqueIdLength = unicode.Length;
|
|
|
|
if (OutputLength <
|
|
sizeof(UniqueId->UniqueIdLength) + UniqueId->UniqueIdLength) {
|
|
|
|
IoStatus->Information = sizeof(MOUNTDEV_UNIQUE_ID);
|
|
return STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
RtlCopyMemory(
|
|
UniqueId->UniqueId, buf, unicode.Length);
|
|
|
|
IoStatus->Information =
|
|
sizeof(UniqueId->UniqueIdLength) + UniqueId->UniqueIdLength;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
|
|
// Returns the device name of the target device (\Device\Floppy<n>)
|
|
//
|
|
NTSTATUS
|
|
VfdMountDevDeviceName(
|
|
PDEVICE_EXTENSION DeviceExtension,
|
|
PMOUNTDEV_NAME DeviceName,
|
|
ULONG OutputLength,
|
|
PIO_STATUS_BLOCK IoStatus)
|
|
{
|
|
if (OutputLength < sizeof(MOUNTDEV_NAME)) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
DeviceName->NameLength = DeviceExtension->DeviceName.Length;
|
|
|
|
if (OutputLength <
|
|
sizeof(DeviceName->NameLength) + DeviceName->NameLength) {
|
|
|
|
IoStatus->Information = sizeof(MOUNTDEV_NAME);
|
|
return STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
RtlCopyMemory(
|
|
DeviceName->Name,
|
|
DeviceExtension->DeviceName.Buffer,
|
|
DeviceName->NameLength);
|
|
|
|
IoStatus->Information =
|
|
sizeof(DeviceName->NameLength) + DeviceName->NameLength;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
|
|
// Returns the drive letter link which we want the mount manager
|
|
// to create. This request is issued in response to the volume
|
|
// arrival notification, and the mount manager will create the
|
|
// symbolic link.
|
|
//
|
|
NTSTATUS
|
|
VfdMountDevSuggestedLink(
|
|
PDEVICE_EXTENSION DeviceExtension,
|
|
PMOUNTDEV_SUGGESTED_LINK_NAME LinkName,
|
|
ULONG OutputLength,
|
|
PIO_STATUS_BLOCK IoStatus)
|
|
{
|
|
WCHAR buf[20];
|
|
UNICODE_STRING unicode;
|
|
|
|
if (OutputLength < sizeof(MOUNTDEV_SUGGESTED_LINK_NAME)) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
LinkName->UseOnlyIfThereAreNoOtherLinks = TRUE;
|
|
|
|
if (!DeviceExtension->DriveLetter) {
|
|
|
|
// No persistent drive letter stored in the registry
|
|
VFDTRACE(VFDINFO, ("[VFD] suggested link : none\n"));
|
|
|
|
LinkName->NameLength = 0;
|
|
|
|
IoStatus->Information = sizeof(MOUNTDEV_SUGGESTED_LINK_NAME);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
// A persistent drive letter exists
|
|
|
|
swprintf(buf, L"\\DosDevices\\%wc:",
|
|
DeviceExtension->DriveLetter);
|
|
|
|
VFDTRACE(VFDINFO, ("[VFD] suggested link : %ws\n", buf));
|
|
|
|
RtlInitUnicodeString(&unicode, buf);
|
|
|
|
LinkName->NameLength = unicode.Length;
|
|
|
|
if (OutputLength <
|
|
sizeof(MOUNTDEV_SUGGESTED_LINK_NAME) +
|
|
LinkName->NameLength - sizeof(WCHAR)) {
|
|
|
|
IoStatus->Information = sizeof(MOUNTDEV_SUGGESTED_LINK_NAME);
|
|
return STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
RtlCopyMemory(LinkName->Name, buf, unicode.Length);
|
|
|
|
IoStatus->Information =
|
|
sizeof(MOUNTDEV_SUGGESTED_LINK_NAME) +
|
|
LinkName->NameLength - sizeof(WCHAR);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// IOCTL_MOUNTDEV_LINK_CREATED / IOCTL_MOUNTDEV_LINK_DELETED
|
|
// Issued after the mount manager created/deleted a symbolic link
|
|
// If the link is a drive letter, store the new value into the
|
|
// registry as the new drive letter
|
|
//
|
|
NTSTATUS
|
|
VfdMountDevLinkModified(
|
|
PDEVICE_EXTENSION DeviceExtension,
|
|
PMOUNTDEV_NAME LinkName,
|
|
ULONG InputLength,
|
|
ULONG ControlCode)
|
|
{
|
|
if (InputLength < sizeof(MOUNTDEV_NAME)) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (InputLength < sizeof(MOUNTDEV_NAME) +
|
|
LinkName->NameLength - sizeof(WCHAR)) {
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
#if DBG
|
|
{ // Print the reported link name
|
|
PWSTR buf = ExAllocatePoolWithTag(
|
|
PagedPool, LinkName->NameLength + sizeof(WCHAR), VFD_POOL_TAG);
|
|
|
|
if (buf) {
|
|
RtlZeroMemory(buf, LinkName->NameLength + sizeof(WCHAR));
|
|
RtlCopyMemory(buf, LinkName->Name, LinkName->NameLength);
|
|
VFDTRACE(VFDINFO, ("[VFD] %ws\n", buf));
|
|
ExFreePool(buf);
|
|
}
|
|
}
|
|
#endif // DBG
|
|
|
|
if (LinkName->NameLength == 28 &&
|
|
LinkName->Name[0] == L'\\' &&
|
|
LinkName->Name[1] == L'D' &&
|
|
LinkName->Name[2] == L'o' &&
|
|
LinkName->Name[3] == L's' &&
|
|
LinkName->Name[4] == L'D' &&
|
|
LinkName->Name[5] == L'e' &&
|
|
LinkName->Name[6] == L'v' &&
|
|
LinkName->Name[7] == L'i' &&
|
|
LinkName->Name[8] == L'c' &&
|
|
LinkName->Name[9] == L'e' &&
|
|
LinkName->Name[10] == L's' &&
|
|
LinkName->Name[11] == L'\\' &&
|
|
LinkName->Name[12] >= L'A' &&
|
|
LinkName->Name[12] <= L'Z' &&
|
|
LinkName->Name[13] == L':') {
|
|
|
|
// The link is a drive letter
|
|
|
|
if (ControlCode == IOCTL_MOUNTDEV_LINK_CREATED) {
|
|
// link is created - store the new drive letter
|
|
DeviceExtension->DriveLetter = (CHAR)LinkName->Name[12];
|
|
}
|
|
else {
|
|
// link is deleted - clear the drive letter
|
|
DeviceExtension->DriveLetter = 0;
|
|
}
|
|
|
|
// Store the value into the registry
|
|
|
|
VfdStoreLink(DeviceExtension);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
#endif // VFD_MOUNT_MANAGER
|