125c7e1a8SPierre Schweitzer /*
225c7e1a8SPierre Schweitzer vfdmnt.c
325c7e1a8SPierre Schweitzer
425c7e1a8SPierre Schweitzer Virtual Floppy Drive for Windows NT platform
525c7e1a8SPierre Schweitzer Kernel mode driver mount manager functions
625c7e1a8SPierre Schweitzer
725c7e1a8SPierre Schweitzer Copyright (C) 2003-2005 Ken Kato
825c7e1a8SPierre Schweitzer */
925c7e1a8SPierre Schweitzer
1025c7e1a8SPierre Schweitzer #ifndef VFD_MOUNT_MANAGER
1125c7e1a8SPierre Schweitzer /*
1225c7e1a8SPierre Schweitzer Not in working order for the time being
1325c7e1a8SPierre Schweitzer so DO NOT define VFD_MOUNT_MANAGER macro
1425c7e1a8SPierre Schweitzer unless you know exactly what you are doing...
1525c7e1a8SPierre Schweitzer */
16*3ff08b64SSerge Gautherie #if !defined(__REACTOS__) || defined(_MSC_VER)
1725c7e1a8SPierre Schweitzer // suppress empty compile unit warning
1825c7e1a8SPierre Schweitzer #pragma warning (disable: 4206)
1925c7e1a8SPierre Schweitzer #pragma message ("Mount Manager support feature is disabled.")
2025c7e1a8SPierre Schweitzer #endif
2125c7e1a8SPierre Schweitzer
2225c7e1a8SPierre Schweitzer #else // VFD_MOUNT_MANAGER
2325c7e1a8SPierre Schweitzer /*
2425c7e1a8SPierre Schweitzer The flow of the drive letter assignment via the Mount Manager
2525c7e1a8SPierre Schweitzer during the VFD driver start up
2625c7e1a8SPierre Schweitzer
2725c7e1a8SPierre Schweitzer 1) IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION VFD -> MM
2825c7e1a8SPierre Schweitzer notifies the mount manager of VFD devices.
2925c7e1a8SPierre Schweitzer
3025c7e1a8SPierre Schweitzer 2) IOCTL_MOUNTDEV_QUERY_DEVICE_NAME VFD <- MM
3125c7e1a8SPierre Schweitzer device name (\Device\Floppy<x>) VFD -> MM
3225c7e1a8SPierre Schweitzer
3325c7e1a8SPierre Schweitzer 3) IOCTL_MOUNTDEV_QUERY_UNIQUE_ID VFD <- MM
3425c7e1a8SPierre Schweitzer device unique ID (\??\VirtualFD<x>) VFD -> MM
3525c7e1a8SPierre Schweitzer
3625c7e1a8SPierre Schweitzer 4) IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME VFD <- MM
3725c7e1a8SPierre Schweitzer drive letter link (\DosDevices\<x>:) VFD -> MM
3825c7e1a8SPierre Schweitzer
3925c7e1a8SPierre Schweitzer 5) The mount manager creates the drive letter link
4025c7e1a8SPierre Schweitzer
4125c7e1a8SPierre Schweitzer 6) IOCTL_MOUNTDEV_LINK_CREATED VFD <- MM
4225c7e1a8SPierre Schweitzer The driver stores the created drive letter
4325c7e1a8SPierre Schweitzer
4425c7e1a8SPierre Schweitzer The flow of the drive letter operation with IOCTL_VFD_SET_LINK
4525c7e1a8SPierre Schweitzer
4625c7e1a8SPierre Schweitzer 1) IOCTL_MOUNTMGR_CREATE_POINT or
4725c7e1a8SPierre Schweitzer IOCTL_MOUNTMGR_DELETE_POINTS VFD -> MM
4825c7e1a8SPierre Schweitzer
4925c7e1a8SPierre Schweitzer 2) The mount manager creates/deletes the drive letter link
5025c7e1a8SPierre Schweitzer
5125c7e1a8SPierre Schweitzer 3) IOCTL_MOUNTDEV_LINK_CREATED or
5225c7e1a8SPierre Schweitzer IOCTL_MOUNTDEV_LINK_DELETED VFD <- MM
5325c7e1a8SPierre Schweitzer The driver stores the created/deleted drive letter
5425c7e1a8SPierre Schweitzer */
5525c7e1a8SPierre Schweitzer
5625c7e1a8SPierre Schweitzer #include "imports.h"
5725c7e1a8SPierre Schweitzer #include "vfddrv.h"
5825c7e1a8SPierre Schweitzer #include "vfddbg.h"
5925c7e1a8SPierre Schweitzer
6025c7e1a8SPierre Schweitzer //
6125c7e1a8SPierre Schweitzer // Call the mount manager with an IO control IRP
6225c7e1a8SPierre Schweitzer //
6325c7e1a8SPierre Schweitzer static NTSTATUS
6425c7e1a8SPierre Schweitzer VfdMountMgrSendRequest(
6525c7e1a8SPierre Schweitzer ULONG ControlCode,
6625c7e1a8SPierre Schweitzer PVOID InputBuffer,
6725c7e1a8SPierre Schweitzer ULONG InputLength,
6825c7e1a8SPierre Schweitzer PVOID OutputBuffer,
6925c7e1a8SPierre Schweitzer ULONG OutputLength);
7025c7e1a8SPierre Schweitzer
7125c7e1a8SPierre Schweitzer #ifdef ALLOC_PRAGMA
7225c7e1a8SPierre Schweitzer //#pragma alloc_text(PAGE, VfdRegisterMountManager)
7325c7e1a8SPierre Schweitzer #pragma alloc_text(PAGE, VfdMountMgrNotifyVolume)
7425c7e1a8SPierre Schweitzer #pragma alloc_text(PAGE, VfdMountMgrMountPoint)
7525c7e1a8SPierre Schweitzer #pragma alloc_text(PAGE, VfdMountMgrSendRequest)
7625c7e1a8SPierre Schweitzer #pragma alloc_text(PAGE, VfdMountDevUniqueId)
7725c7e1a8SPierre Schweitzer #pragma alloc_text(PAGE, VfdMountDevDeviceName)
7825c7e1a8SPierre Schweitzer #pragma alloc_text(PAGE, VfdMountDevSuggestedLink)
7925c7e1a8SPierre Schweitzer #pragma alloc_text(PAGE, VfdMountDevLinkModified)
8025c7e1a8SPierre Schweitzer #endif // ALLOC_PRAGMA
8125c7e1a8SPierre Schweitzer
8225c7e1a8SPierre Schweitzer /*
8325c7e1a8SPierre Schweitzer #include <initguid.h>
8425c7e1a8SPierre Schweitzer #include <mountmgr.h>
8525c7e1a8SPierre Schweitzer //
8625c7e1a8SPierre Schweitzer // register a device to the mount manager interface
8725c7e1a8SPierre Schweitzer // does not work...
8825c7e1a8SPierre Schweitzer //
8925c7e1a8SPierre Schweitzer NTSTATUS
9025c7e1a8SPierre Schweitzer VfdRegisterMountManager(
9125c7e1a8SPierre Schweitzer PDEVICE_EXTENSION DeviceExtension)
9225c7e1a8SPierre Schweitzer {
9325c7e1a8SPierre Schweitzer NTSTATUS status = STATUS_SUCCESS;
9425c7e1a8SPierre Schweitzer UNICODE_STRING interface;
9525c7e1a8SPierre Schweitzer UNICODE_STRING interface2;
9625c7e1a8SPierre Schweitzer
9725c7e1a8SPierre Schweitzer VFDTRACE(VFDINFO,
9825c7e1a8SPierre Schweitzer ("[VFD] Registering %ws to the Mount Manager Interface\n",
9925c7e1a8SPierre Schweitzer DeviceExtension->DeviceName.Buffer));
10025c7e1a8SPierre Schweitzer
10125c7e1a8SPierre Schweitzer RtlInitUnicodeString(&interface, NULL);
10225c7e1a8SPierre Schweitzer
10325c7e1a8SPierre Schweitzer status = IoRegisterDeviceInterface(
10425c7e1a8SPierre Schweitzer DeviceExtension->DeviceObject,
10525c7e1a8SPierre Schweitzer (LPGUID)&MOUNTDEV_MOUNTED_DEVICE_GUID,
10625c7e1a8SPierre Schweitzer NULL,
10725c7e1a8SPierre Schweitzer &interface);
10825c7e1a8SPierre Schweitzer
10925c7e1a8SPierre Schweitzer if (!NT_SUCCESS(status)) {
11025c7e1a8SPierre Schweitzer VFDTRACE(0,
11125c7e1a8SPierre Schweitzer ("[VFD] IoRegisterDeviceInterface - %s\n",
11225c7e1a8SPierre Schweitzer GetStatusName(status)));
11325c7e1a8SPierre Schweitzer return status;
11425c7e1a8SPierre Schweitzer }
11525c7e1a8SPierre Schweitzer
11625c7e1a8SPierre Schweitzer status = IoSetDeviceInterfaceState(&interface, TRUE);
11725c7e1a8SPierre Schweitzer
11825c7e1a8SPierre Schweitzer if (NT_SUCCESS(status)) {
11925c7e1a8SPierre Schweitzer if (VfdCopyUnicode(&interface2, &interface)) {
12025c7e1a8SPierre Schweitzer VFDTRACE(VFDINFO,
12125c7e1a8SPierre Schweitzer ("[VFD] Interface: %ws\n", interface2.Buffer));
12225c7e1a8SPierre Schweitzer }
12325c7e1a8SPierre Schweitzer else {
12425c7e1a8SPierre Schweitzer VFDTRACE(0,
12525c7e1a8SPierre Schweitzer ("[VFD] Failed to allocate an interface name buffer\n"));
12625c7e1a8SPierre Schweitzer status = STATUS_INSUFFICIENT_RESOURCES;
12725c7e1a8SPierre Schweitzer }
12825c7e1a8SPierre Schweitzer }
12925c7e1a8SPierre Schweitzer else {
13025c7e1a8SPierre Schweitzer VFDTRACE(0,
13125c7e1a8SPierre Schweitzer ("[VFD] IoSetDeviceInterfaceState - %s\n",
13225c7e1a8SPierre Schweitzer GetStatusName(status)));
13325c7e1a8SPierre Schweitzer }
13425c7e1a8SPierre Schweitzer
13525c7e1a8SPierre Schweitzer RtlFreeUnicodeString(&interface);
13625c7e1a8SPierre Schweitzer VfdFreeUnicode(&interface2);
13725c7e1a8SPierre Schweitzer
13825c7e1a8SPierre Schweitzer return status;
13925c7e1a8SPierre Schweitzer }
14025c7e1a8SPierre Schweitzer */
14125c7e1a8SPierre Schweitzer
14225c7e1a8SPierre Schweitzer //
14325c7e1a8SPierre Schweitzer // informs the Mount Manager of a new VFD device
14425c7e1a8SPierre Schweitzer //
14525c7e1a8SPierre Schweitzer NTSTATUS
VfdMountMgrNotifyVolume(PDEVICE_EXTENSION DeviceExtension)14625c7e1a8SPierre Schweitzer VfdMountMgrNotifyVolume(
14725c7e1a8SPierre Schweitzer PDEVICE_EXTENSION DeviceExtension)
14825c7e1a8SPierre Schweitzer {
14925c7e1a8SPierre Schweitzer PMOUNTMGR_TARGET_NAME target_name;
15025c7e1a8SPierre Schweitzer USHORT target_name_buf[MAXIMUM_FILENAME_LENGTH];
15125c7e1a8SPierre Schweitzer NTSTATUS status;
15225c7e1a8SPierre Schweitzer
15325c7e1a8SPierre Schweitzer VFDTRACE(VFDINFO,
15425c7e1a8SPierre Schweitzer ("[VFD] VfdMountMgrNotifyVolume - %ws\n",
15525c7e1a8SPierre Schweitzer DeviceExtension->DeviceName.Buffer));
15625c7e1a8SPierre Schweitzer
15725c7e1a8SPierre Schweitzer target_name = (PMOUNTMGR_TARGET_NAME)target_name_buf;
15825c7e1a8SPierre Schweitzer
15925c7e1a8SPierre Schweitzer target_name->DeviceNameLength =
16025c7e1a8SPierre Schweitzer DeviceExtension->DeviceName.Length;
16125c7e1a8SPierre Schweitzer
16225c7e1a8SPierre Schweitzer RtlCopyMemory(
16325c7e1a8SPierre Schweitzer target_name->DeviceName,
16425c7e1a8SPierre Schweitzer DeviceExtension->DeviceName.Buffer,
16525c7e1a8SPierre Schweitzer DeviceExtension->DeviceName.Length);
16625c7e1a8SPierre Schweitzer
16725c7e1a8SPierre Schweitzer status = VfdMountMgrSendRequest(
16825c7e1a8SPierre Schweitzer IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION,
16925c7e1a8SPierre Schweitzer target_name,
17025c7e1a8SPierre Schweitzer sizeof(target_name->DeviceNameLength) + target_name->DeviceNameLength,
17125c7e1a8SPierre Schweitzer NULL,
17225c7e1a8SPierre Schweitzer 0);
17325c7e1a8SPierre Schweitzer
17425c7e1a8SPierre Schweitzer VFDTRACE(VFDINFO,
17525c7e1a8SPierre Schweitzer ("[VFD] VfdMountMgrNotifyVolume - %s\n",
17625c7e1a8SPierre Schweitzer GetStatusName(status)));
17725c7e1a8SPierre Schweitzer
17825c7e1a8SPierre Schweitzer return status;
17925c7e1a8SPierre Schweitzer }
18025c7e1a8SPierre Schweitzer
18125c7e1a8SPierre Schweitzer //
18225c7e1a8SPierre Schweitzer // Create / remove a drive letter via the Mount Manager
18325c7e1a8SPierre Schweitzer //
18425c7e1a8SPierre Schweitzer NTSTATUS
VfdMountMgrMountPoint(PDEVICE_EXTENSION DeviceExtension,CHAR DriveLetter)18525c7e1a8SPierre Schweitzer VfdMountMgrMountPoint(
18625c7e1a8SPierre Schweitzer PDEVICE_EXTENSION DeviceExtension,
18725c7e1a8SPierre Schweitzer CHAR DriveLetter)
18825c7e1a8SPierre Schweitzer {
18925c7e1a8SPierre Schweitzer ULONG alloc_size;
19025c7e1a8SPierre Schweitzer UNICODE_STRING link_name;
19125c7e1a8SPierre Schweitzer WCHAR link_buf[20];
19225c7e1a8SPierre Schweitzer NTSTATUS status;
19325c7e1a8SPierre Schweitzer
19425c7e1a8SPierre Schweitzer VFDTRACE(VFDINFO, ("[VFD] VfdMountMgrMountPoint - IN\n"));
19525c7e1a8SPierre Schweitzer
19625c7e1a8SPierre Schweitzer // convert lower case into upper case
19725c7e1a8SPierre Schweitzer
19825c7e1a8SPierre Schweitzer if (DriveLetter >= 'a' && DriveLetter <= 'z') {
19925c7e1a8SPierre Schweitzer DriveLetter -= ('a' - 'A');
20025c7e1a8SPierre Schweitzer }
20125c7e1a8SPierre Schweitzer
20225c7e1a8SPierre Schweitzer if (DriveLetter >= 'A' && DriveLetter <= 'Z') {
20325c7e1a8SPierre Schweitzer
20425c7e1a8SPierre Schweitzer // Create a new drive letter
20525c7e1a8SPierre Schweitzer
20625c7e1a8SPierre Schweitzer PMOUNTMGR_CREATE_POINT_INPUT create;
20725c7e1a8SPierre Schweitzer
20825c7e1a8SPierre Schweitzer swprintf(link_buf, L"\\DosDevices\\%wc:", DriveLetter);
20925c7e1a8SPierre Schweitzer
21025c7e1a8SPierre Schweitzer RtlInitUnicodeString(&link_name, link_buf);
21125c7e1a8SPierre Schweitzer
21225c7e1a8SPierre Schweitzer VFDTRACE(VFDINFO,
21325c7e1a8SPierre Schweitzer ("[VFD] Creating a link: %ws => %ws\n",
21425c7e1a8SPierre Schweitzer link_buf, DeviceExtension->DeviceName.Buffer));
21525c7e1a8SPierre Schweitzer
21625c7e1a8SPierre Schweitzer // allocate buffer for MOUNTMGR_CREATE_POINT_INPUT
21725c7e1a8SPierre Schweitzer
21825c7e1a8SPierre Schweitzer alloc_size = sizeof(MOUNTMGR_CREATE_POINT_INPUT) +
21925c7e1a8SPierre Schweitzer link_name.Length + DeviceExtension->DeviceName.Length;
22025c7e1a8SPierre Schweitzer
22125c7e1a8SPierre Schweitzer create = (PMOUNTMGR_CREATE_POINT_INPUT)ExAllocatePoolWithTag(
22225c7e1a8SPierre Schweitzer NonPagedPool, alloc_size, VFD_POOL_TAG);
22325c7e1a8SPierre Schweitzer
22425c7e1a8SPierre Schweitzer if (!create) {
22525c7e1a8SPierre Schweitzer VFDTRACE(0, ("[VFD] Failed to allocate mount point input\n"));
22625c7e1a8SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES;
22725c7e1a8SPierre Schweitzer }
22825c7e1a8SPierre Schweitzer
22925c7e1a8SPierre Schweitzer // set the symbolic link name
23025c7e1a8SPierre Schweitzer
23125c7e1a8SPierre Schweitzer create->SymbolicLinkNameOffset = sizeof(MOUNTMGR_CREATE_POINT_INPUT);
23225c7e1a8SPierre Schweitzer create->SymbolicLinkNameLength = link_name.Length;
23325c7e1a8SPierre Schweitzer
23425c7e1a8SPierre Schweitzer RtlCopyMemory(
23525c7e1a8SPierre Schweitzer (PCHAR)create + create->SymbolicLinkNameOffset,
23625c7e1a8SPierre Schweitzer link_name.Buffer,
23725c7e1a8SPierre Schweitzer link_name.Length);
23825c7e1a8SPierre Schweitzer
23925c7e1a8SPierre Schweitzer // set the target device name
24025c7e1a8SPierre Schweitzer
24125c7e1a8SPierre Schweitzer create->DeviceNameOffset = (USHORT)
24225c7e1a8SPierre Schweitzer (create->SymbolicLinkNameOffset + create->SymbolicLinkNameLength);
24325c7e1a8SPierre Schweitzer create->DeviceNameLength = DeviceExtension->DeviceName.Length;
24425c7e1a8SPierre Schweitzer
24525c7e1a8SPierre Schweitzer RtlCopyMemory(
24625c7e1a8SPierre Schweitzer (PCHAR)create + create->DeviceNameOffset,
24725c7e1a8SPierre Schweitzer DeviceExtension->DeviceName.Buffer,
24825c7e1a8SPierre Schweitzer DeviceExtension->DeviceName.Length);
24925c7e1a8SPierre Schweitzer
25025c7e1a8SPierre Schweitzer // call the mount manager with the IO control request
25125c7e1a8SPierre Schweitzer
25225c7e1a8SPierre Schweitzer status = VfdMountMgrSendRequest(
25325c7e1a8SPierre Schweitzer IOCTL_MOUNTMGR_CREATE_POINT,
25425c7e1a8SPierre Schweitzer create, alloc_size, NULL, 0);
25525c7e1a8SPierre Schweitzer
25625c7e1a8SPierre Schweitzer ExFreePool(create);
25725c7e1a8SPierre Schweitzer
25825c7e1a8SPierre Schweitzer // no need to set the new drive letter into the
25925c7e1a8SPierre Schweitzer // DeviceExtension because the mount manager will issue an
26025c7e1a8SPierre Schweitzer // IOCTL_MOUNTDEV_LINK_CREATED and it will be processed then
26125c7e1a8SPierre Schweitzer }
26225c7e1a8SPierre Schweitzer else if (DriveLetter == 0) {
26325c7e1a8SPierre Schweitzer
26425c7e1a8SPierre Schweitzer // Delete the existing drive letter
26525c7e1a8SPierre Schweitzer
26625c7e1a8SPierre Schweitzer PMOUNTMGR_MOUNT_POINT mount;
26725c7e1a8SPierre Schweitzer PMOUNTMGR_MOUNT_POINTS points;
26825c7e1a8SPierre Schweitzer UNICODE_STRING unique_id;
26925c7e1a8SPierre Schweitzer WCHAR unique_buf[20];
27025c7e1a8SPierre Schweitzer
27125c7e1a8SPierre Schweitzer swprintf(link_buf, L"\\DosDevices\\%wc:",
27225c7e1a8SPierre Schweitzer DeviceExtension->DriveLetter);
27325c7e1a8SPierre Schweitzer
27425c7e1a8SPierre Schweitzer VFDTRACE(VFDINFO,
27525c7e1a8SPierre Schweitzer ("[VFD] Deleting link: %ws\n", link_buf));
27625c7e1a8SPierre Schweitzer
27725c7e1a8SPierre Schweitzer RtlInitUnicodeString(&link_name, link_buf);
27825c7e1a8SPierre Schweitzer
27925c7e1a8SPierre Schweitzer swprintf(unique_buf, L"\\??\\" VFD_DEVICE_BASENAME L"%lu",
28025c7e1a8SPierre Schweitzer DeviceExtension->DeviceNumber);
28125c7e1a8SPierre Schweitzer
28225c7e1a8SPierre Schweitzer RtlInitUnicodeString(&unique_id, unique_buf);
28325c7e1a8SPierre Schweitzer
28425c7e1a8SPierre Schweitzer // allocate buffer for MOUNTMGR_MOUNT_POINT
28525c7e1a8SPierre Schweitzer
28625c7e1a8SPierre Schweitzer alloc_size = sizeof(MOUNTMGR_MOUNT_POINT) +
28725c7e1a8SPierre Schweitzer link_name.Length +
28825c7e1a8SPierre Schweitzer unique_id.Length +
28925c7e1a8SPierre Schweitzer DeviceExtension->DeviceName.Length;
29025c7e1a8SPierre Schweitzer
29125c7e1a8SPierre Schweitzer mount = (PMOUNTMGR_MOUNT_POINT)ExAllocatePoolWithTag(
29225c7e1a8SPierre Schweitzer NonPagedPool, alloc_size, VFD_POOL_TAG);
29325c7e1a8SPierre Schweitzer
29425c7e1a8SPierre Schweitzer if (!mount) {
29525c7e1a8SPierre Schweitzer VFDTRACE(0, ("[VFD] Failed to allocate mount point input\n"));
29625c7e1a8SPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES;
29725c7e1a8SPierre Schweitzer }
29825c7e1a8SPierre Schweitzer
29925c7e1a8SPierre Schweitzer RtlZeroMemory(mount, alloc_size + sizeof(WCHAR));
30025c7e1a8SPierre Schweitzer
30125c7e1a8SPierre Schweitzer // set the symbolic link name
30225c7e1a8SPierre Schweitzer
30325c7e1a8SPierre Schweitzer mount->SymbolicLinkNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
30425c7e1a8SPierre Schweitzer mount->SymbolicLinkNameLength = link_name.Length;
30525c7e1a8SPierre Schweitzer
30625c7e1a8SPierre Schweitzer RtlCopyMemory(
30725c7e1a8SPierre Schweitzer (PCHAR)mount + mount->SymbolicLinkNameOffset,
30825c7e1a8SPierre Schweitzer link_name.Buffer, link_name.Length);
30925c7e1a8SPierre Schweitzer
31025c7e1a8SPierre Schweitzer // set the unique id
31125c7e1a8SPierre Schweitzer
31225c7e1a8SPierre Schweitzer mount->UniqueIdOffset =
31325c7e1a8SPierre Schweitzer mount->SymbolicLinkNameOffset +
31425c7e1a8SPierre Schweitzer mount->SymbolicLinkNameLength;
31525c7e1a8SPierre Schweitzer mount->UniqueIdLength = unique_id.Length;
31625c7e1a8SPierre Schweitzer
31725c7e1a8SPierre Schweitzer RtlCopyMemory(
31825c7e1a8SPierre Schweitzer (PCHAR)mount + mount->UniqueIdOffset,
31925c7e1a8SPierre Schweitzer unique_id.Buffer, unique_id.Length);
32025c7e1a8SPierre Schweitzer
32125c7e1a8SPierre Schweitzer // set the target device name
32225c7e1a8SPierre Schweitzer
32325c7e1a8SPierre Schweitzer mount->DeviceNameOffset =
32425c7e1a8SPierre Schweitzer mount->UniqueIdOffset +
32525c7e1a8SPierre Schweitzer mount->UniqueIdLength;
32625c7e1a8SPierre Schweitzer mount->DeviceNameLength =
32725c7e1a8SPierre Schweitzer DeviceExtension->DeviceName.Length;
32825c7e1a8SPierre Schweitzer
32925c7e1a8SPierre Schweitzer RtlCopyMemory(
33025c7e1a8SPierre Schweitzer (PCHAR)mount + mount->DeviceNameOffset,
33125c7e1a8SPierre Schweitzer DeviceExtension->DeviceName.Buffer,
33225c7e1a8SPierre Schweitzer DeviceExtension->DeviceName.Length);
33325c7e1a8SPierre Schweitzer
33425c7e1a8SPierre Schweitzer // prepare the output buffer
33525c7e1a8SPierre Schweitzer
33625c7e1a8SPierre Schweitzer points = (PMOUNTMGR_MOUNT_POINTS)ExAllocatePoolWithTag(
33725c7e1a8SPierre Schweitzer NonPagedPool, alloc_size * 2, VFD_POOL_TAG);
33825c7e1a8SPierre Schweitzer
33925c7e1a8SPierre Schweitzer status = VfdMountMgrSendRequest(
34025c7e1a8SPierre Schweitzer IOCTL_MOUNTMGR_DELETE_POINTS,
34125c7e1a8SPierre Schweitzer mount, alloc_size, points, alloc_size * 2);
34225c7e1a8SPierre Schweitzer
34325c7e1a8SPierre Schweitzer ExFreePool(mount);
34425c7e1a8SPierre Schweitzer ExFreePool(points);
34525c7e1a8SPierre Schweitzer
34625c7e1a8SPierre Schweitzer if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
34725c7e1a8SPierre Schweitzer // the drive letter did not exist in the first place
34825c7e1a8SPierre Schweitzer DeviceExtension->DriveLetter = 0;
34925c7e1a8SPierre Schweitzer }
35025c7e1a8SPierre Schweitzer
35125c7e1a8SPierre Schweitzer // no need to clear the drive letter in the
35225c7e1a8SPierre Schweitzer // DeviceExtension because the mount manager will issue an
35325c7e1a8SPierre Schweitzer // IOCTL_MOUNTDEV_LINK_DELETED and it will be processed then
35425c7e1a8SPierre Schweitzer }
35525c7e1a8SPierre Schweitzer else {
35625c7e1a8SPierre Schweitzer return STATUS_INVALID_PARAMETER;
35725c7e1a8SPierre Schweitzer }
35825c7e1a8SPierre Schweitzer
35925c7e1a8SPierre Schweitzer VFDTRACE(VFDINFO, ("[VFD] VfdMountMgrMountPoint - %s\n",
36025c7e1a8SPierre Schweitzer GetStatusName(status)));
36125c7e1a8SPierre Schweitzer
36225c7e1a8SPierre Schweitzer return status;
36325c7e1a8SPierre Schweitzer }
36425c7e1a8SPierre Schweitzer
36525c7e1a8SPierre Schweitzer //
36625c7e1a8SPierre Schweitzer // send a request to the Mount Manager
36725c7e1a8SPierre Schweitzer //
36825c7e1a8SPierre Schweitzer NTSTATUS
VfdMountMgrSendRequest(ULONG ControlCode,PVOID InputBuffer,ULONG InputLength,PVOID OutputBuffer,ULONG OutputLength)36925c7e1a8SPierre Schweitzer VfdMountMgrSendRequest(
37025c7e1a8SPierre Schweitzer ULONG ControlCode,
37125c7e1a8SPierre Schweitzer PVOID InputBuffer,
37225c7e1a8SPierre Schweitzer ULONG InputLength,
37325c7e1a8SPierre Schweitzer PVOID OutputBuffer,
37425c7e1a8SPierre Schweitzer ULONG OutputLength)
37525c7e1a8SPierre Schweitzer {
37625c7e1a8SPierre Schweitzer NTSTATUS status = STATUS_SUCCESS;
37725c7e1a8SPierre Schweitzer UNICODE_STRING mntmgr_name;
37825c7e1a8SPierre Schweitzer PDEVICE_OBJECT mntmgr_dev;
37925c7e1a8SPierre Schweitzer PFILE_OBJECT mntmgr_file;
38025c7e1a8SPierre Schweitzer IO_STATUS_BLOCK io_status;
38125c7e1a8SPierre Schweitzer KEVENT event;
38225c7e1a8SPierre Schweitzer PIRP irp;
38325c7e1a8SPierre Schweitzer
38425c7e1a8SPierre Schweitzer // Obtain a pointer to the Mount Manager device object
38525c7e1a8SPierre Schweitzer
38625c7e1a8SPierre Schweitzer RtlInitUnicodeString(
38725c7e1a8SPierre Schweitzer &mntmgr_name,
38825c7e1a8SPierre Schweitzer MOUNTMGR_DEVICE_NAME);
38925c7e1a8SPierre Schweitzer
39025c7e1a8SPierre Schweitzer status = IoGetDeviceObjectPointer(
39125c7e1a8SPierre Schweitzer &mntmgr_name,
39225c7e1a8SPierre Schweitzer FILE_READ_ATTRIBUTES,
39325c7e1a8SPierre Schweitzer &mntmgr_file,
39425c7e1a8SPierre Schweitzer &mntmgr_dev);
39525c7e1a8SPierre Schweitzer
39625c7e1a8SPierre Schweitzer if (!NT_SUCCESS(status)) {
39725c7e1a8SPierre Schweitzer VFDTRACE(VFDWARN,
39825c7e1a8SPierre Schweitzer ("[VFD] IoGetDeviceObjectPointer - %s\n", GetStatusName(status)));
39925c7e1a8SPierre Schweitzer return status;
40025c7e1a8SPierre Schweitzer }
40125c7e1a8SPierre Schweitzer
40225c7e1a8SPierre Schweitzer KeInitializeEvent(&event, NotificationEvent, FALSE);
40325c7e1a8SPierre Schweitzer
40425c7e1a8SPierre Schweitzer // Create an IRP request block
40525c7e1a8SPierre Schweitzer
40625c7e1a8SPierre Schweitzer irp = IoBuildDeviceIoControlRequest(
40725c7e1a8SPierre Schweitzer ControlCode,
40825c7e1a8SPierre Schweitzer mntmgr_dev,
40925c7e1a8SPierre Schweitzer InputBuffer,
41025c7e1a8SPierre Schweitzer InputLength,
41125c7e1a8SPierre Schweitzer OutputBuffer,
41225c7e1a8SPierre Schweitzer OutputLength,
41325c7e1a8SPierre Schweitzer FALSE,
41425c7e1a8SPierre Schweitzer &event,
41525c7e1a8SPierre Schweitzer &io_status);
41625c7e1a8SPierre Schweitzer
41725c7e1a8SPierre Schweitzer if (!irp) {
41825c7e1a8SPierre Schweitzer VFDTRACE(VFDWARN,
41925c7e1a8SPierre Schweitzer ("[VFD] IoBuildDeviceIoControlRequest\n"));
42025c7e1a8SPierre Schweitzer ObDereferenceObject(mntmgr_file);
42125c7e1a8SPierre Schweitzer return STATUS_DRIVER_INTERNAL_ERROR;
42225c7e1a8SPierre Schweitzer }
42325c7e1a8SPierre Schweitzer
42425c7e1a8SPierre Schweitzer // Call the mount manager
42525c7e1a8SPierre Schweitzer
42625c7e1a8SPierre Schweitzer status = IoCallDriver(mntmgr_dev, irp);
42725c7e1a8SPierre Schweitzer
42825c7e1a8SPierre Schweitzer if (!NT_SUCCESS(status)) {
42925c7e1a8SPierre Schweitzer VFDTRACE(VFDWARN,
43025c7e1a8SPierre Schweitzer ("[VFD] IoCallDriver - %s\n", GetStatusName(status)));
43125c7e1a8SPierre Schweitzer }
43225c7e1a8SPierre Schweitzer
43325c7e1a8SPierre Schweitzer if (status == STATUS_PENDING) {
43425c7e1a8SPierre Schweitzer
43525c7e1a8SPierre Schweitzer // Wait for the operation to complete
43625c7e1a8SPierre Schweitzer
43725c7e1a8SPierre Schweitzer KeWaitForSingleObject(
43825c7e1a8SPierre Schweitzer &event, Executive, KernelMode, FALSE, NULL);
43925c7e1a8SPierre Schweitzer
44025c7e1a8SPierre Schweitzer status = io_status.Status;
44125c7e1a8SPierre Schweitzer
44225c7e1a8SPierre Schweitzer if (!NT_SUCCESS(status)) {
44325c7e1a8SPierre Schweitzer VFDTRACE(VFDWARN,
44425c7e1a8SPierre Schweitzer ("[VFD] IoCallDriver - %s\n", GetStatusName(status)));
44525c7e1a8SPierre Schweitzer }
44625c7e1a8SPierre Schweitzer }
44725c7e1a8SPierre Schweitzer
44825c7e1a8SPierre Schweitzer ObDereferenceObject(mntmgr_file);
44925c7e1a8SPierre Schweitzer
45025c7e1a8SPierre Schweitzer return status;
45125c7e1a8SPierre Schweitzer }
45225c7e1a8SPierre Schweitzer
45325c7e1a8SPierre Schweitzer //
45425c7e1a8SPierre Schweitzer // IOCTL_MOUNTDEV_QUERY_UNIQUE_ID
45525c7e1a8SPierre Schweitzer // -- use the device interface link (\??\VirtualFD<x>) as the unique ID
45625c7e1a8SPierre Schweitzer //
45725c7e1a8SPierre Schweitzer NTSTATUS
VfdMountDevUniqueId(PDEVICE_EXTENSION DeviceExtension,PMOUNTDEV_UNIQUE_ID UniqueId,ULONG OutputLength,PIO_STATUS_BLOCK IoStatus)45825c7e1a8SPierre Schweitzer VfdMountDevUniqueId(
45925c7e1a8SPierre Schweitzer PDEVICE_EXTENSION DeviceExtension,
46025c7e1a8SPierre Schweitzer PMOUNTDEV_UNIQUE_ID UniqueId,
46125c7e1a8SPierre Schweitzer ULONG OutputLength,
46225c7e1a8SPierre Schweitzer PIO_STATUS_BLOCK IoStatus)
46325c7e1a8SPierre Schweitzer {
46425c7e1a8SPierre Schweitzer WCHAR buf[20];
46525c7e1a8SPierre Schweitzer UNICODE_STRING unicode;
46625c7e1a8SPierre Schweitzer
46725c7e1a8SPierre Schweitzer if (OutputLength < sizeof(MOUNTDEV_UNIQUE_ID)) {
46825c7e1a8SPierre Schweitzer return STATUS_INVALID_PARAMETER;
46925c7e1a8SPierre Schweitzer }
47025c7e1a8SPierre Schweitzer
47125c7e1a8SPierre Schweitzer swprintf(buf,
47225c7e1a8SPierre Schweitzer L"\\??\\" VFD_DEVICE_BASENAME L"%lu",
47325c7e1a8SPierre Schweitzer DeviceExtension->DeviceNumber);
47425c7e1a8SPierre Schweitzer
47525c7e1a8SPierre Schweitzer RtlInitUnicodeString(&unicode, buf);
47625c7e1a8SPierre Schweitzer
47725c7e1a8SPierre Schweitzer UniqueId->UniqueIdLength = unicode.Length;
47825c7e1a8SPierre Schweitzer
47925c7e1a8SPierre Schweitzer if (OutputLength <
48025c7e1a8SPierre Schweitzer sizeof(UniqueId->UniqueIdLength) + UniqueId->UniqueIdLength) {
48125c7e1a8SPierre Schweitzer
48225c7e1a8SPierre Schweitzer IoStatus->Information = sizeof(MOUNTDEV_UNIQUE_ID);
48325c7e1a8SPierre Schweitzer return STATUS_BUFFER_OVERFLOW;
48425c7e1a8SPierre Schweitzer }
48525c7e1a8SPierre Schweitzer
48625c7e1a8SPierre Schweitzer RtlCopyMemory(
48725c7e1a8SPierre Schweitzer UniqueId->UniqueId, buf, unicode.Length);
48825c7e1a8SPierre Schweitzer
48925c7e1a8SPierre Schweitzer IoStatus->Information =
49025c7e1a8SPierre Schweitzer sizeof(UniqueId->UniqueIdLength) + UniqueId->UniqueIdLength;
49125c7e1a8SPierre Schweitzer
49225c7e1a8SPierre Schweitzer return STATUS_SUCCESS;
49325c7e1a8SPierre Schweitzer }
49425c7e1a8SPierre Schweitzer
49525c7e1a8SPierre Schweitzer //
49625c7e1a8SPierre Schweitzer // IOCTL_MOUNTDEV_QUERY_DEVICE_NAME
49725c7e1a8SPierre Schweitzer // Returns the device name of the target device (\Device\Floppy<n>)
49825c7e1a8SPierre Schweitzer //
49925c7e1a8SPierre Schweitzer NTSTATUS
VfdMountDevDeviceName(PDEVICE_EXTENSION DeviceExtension,PMOUNTDEV_NAME DeviceName,ULONG OutputLength,PIO_STATUS_BLOCK IoStatus)50025c7e1a8SPierre Schweitzer VfdMountDevDeviceName(
50125c7e1a8SPierre Schweitzer PDEVICE_EXTENSION DeviceExtension,
50225c7e1a8SPierre Schweitzer PMOUNTDEV_NAME DeviceName,
50325c7e1a8SPierre Schweitzer ULONG OutputLength,
50425c7e1a8SPierre Schweitzer PIO_STATUS_BLOCK IoStatus)
50525c7e1a8SPierre Schweitzer {
50625c7e1a8SPierre Schweitzer if (OutputLength < sizeof(MOUNTDEV_NAME)) {
50725c7e1a8SPierre Schweitzer return STATUS_INVALID_PARAMETER;
50825c7e1a8SPierre Schweitzer }
50925c7e1a8SPierre Schweitzer
51025c7e1a8SPierre Schweitzer DeviceName->NameLength = DeviceExtension->DeviceName.Length;
51125c7e1a8SPierre Schweitzer
51225c7e1a8SPierre Schweitzer if (OutputLength <
51325c7e1a8SPierre Schweitzer sizeof(DeviceName->NameLength) + DeviceName->NameLength) {
51425c7e1a8SPierre Schweitzer
51525c7e1a8SPierre Schweitzer IoStatus->Information = sizeof(MOUNTDEV_NAME);
51625c7e1a8SPierre Schweitzer return STATUS_BUFFER_OVERFLOW;
51725c7e1a8SPierre Schweitzer }
51825c7e1a8SPierre Schweitzer
51925c7e1a8SPierre Schweitzer RtlCopyMemory(
52025c7e1a8SPierre Schweitzer DeviceName->Name,
52125c7e1a8SPierre Schweitzer DeviceExtension->DeviceName.Buffer,
52225c7e1a8SPierre Schweitzer DeviceName->NameLength);
52325c7e1a8SPierre Schweitzer
52425c7e1a8SPierre Schweitzer IoStatus->Information =
52525c7e1a8SPierre Schweitzer sizeof(DeviceName->NameLength) + DeviceName->NameLength;
52625c7e1a8SPierre Schweitzer
52725c7e1a8SPierre Schweitzer return STATUS_SUCCESS;
52825c7e1a8SPierre Schweitzer }
52925c7e1a8SPierre Schweitzer
53025c7e1a8SPierre Schweitzer //
53125c7e1a8SPierre Schweitzer // IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME
53225c7e1a8SPierre Schweitzer // Returns the drive letter link which we want the mount manager
53325c7e1a8SPierre Schweitzer // to create. This request is issued in response to the volume
53425c7e1a8SPierre Schweitzer // arrival notification, and the mount manager will create the
53525c7e1a8SPierre Schweitzer // symbolic link.
53625c7e1a8SPierre Schweitzer //
53725c7e1a8SPierre Schweitzer NTSTATUS
VfdMountDevSuggestedLink(PDEVICE_EXTENSION DeviceExtension,PMOUNTDEV_SUGGESTED_LINK_NAME LinkName,ULONG OutputLength,PIO_STATUS_BLOCK IoStatus)53825c7e1a8SPierre Schweitzer VfdMountDevSuggestedLink(
53925c7e1a8SPierre Schweitzer PDEVICE_EXTENSION DeviceExtension,
54025c7e1a8SPierre Schweitzer PMOUNTDEV_SUGGESTED_LINK_NAME LinkName,
54125c7e1a8SPierre Schweitzer ULONG OutputLength,
54225c7e1a8SPierre Schweitzer PIO_STATUS_BLOCK IoStatus)
54325c7e1a8SPierre Schweitzer {
54425c7e1a8SPierre Schweitzer WCHAR buf[20];
54525c7e1a8SPierre Schweitzer UNICODE_STRING unicode;
54625c7e1a8SPierre Schweitzer
54725c7e1a8SPierre Schweitzer if (OutputLength < sizeof(MOUNTDEV_SUGGESTED_LINK_NAME)) {
54825c7e1a8SPierre Schweitzer return STATUS_INVALID_PARAMETER;
54925c7e1a8SPierre Schweitzer }
55025c7e1a8SPierre Schweitzer
55125c7e1a8SPierre Schweitzer LinkName->UseOnlyIfThereAreNoOtherLinks = TRUE;
55225c7e1a8SPierre Schweitzer
55325c7e1a8SPierre Schweitzer if (!DeviceExtension->DriveLetter) {
55425c7e1a8SPierre Schweitzer
55525c7e1a8SPierre Schweitzer // No persistent drive letter stored in the registry
55625c7e1a8SPierre Schweitzer VFDTRACE(VFDINFO, ("[VFD] suggested link : none\n"));
55725c7e1a8SPierre Schweitzer
55825c7e1a8SPierre Schweitzer LinkName->NameLength = 0;
55925c7e1a8SPierre Schweitzer
56025c7e1a8SPierre Schweitzer IoStatus->Information = sizeof(MOUNTDEV_SUGGESTED_LINK_NAME);
56125c7e1a8SPierre Schweitzer return STATUS_SUCCESS;
56225c7e1a8SPierre Schweitzer }
56325c7e1a8SPierre Schweitzer
56425c7e1a8SPierre Schweitzer // A persistent drive letter exists
56525c7e1a8SPierre Schweitzer
56625c7e1a8SPierre Schweitzer swprintf(buf, L"\\DosDevices\\%wc:",
56725c7e1a8SPierre Schweitzer DeviceExtension->DriveLetter);
56825c7e1a8SPierre Schweitzer
56925c7e1a8SPierre Schweitzer VFDTRACE(VFDINFO, ("[VFD] suggested link : %ws\n", buf));
57025c7e1a8SPierre Schweitzer
57125c7e1a8SPierre Schweitzer RtlInitUnicodeString(&unicode, buf);
57225c7e1a8SPierre Schweitzer
57325c7e1a8SPierre Schweitzer LinkName->NameLength = unicode.Length;
57425c7e1a8SPierre Schweitzer
57525c7e1a8SPierre Schweitzer if (OutputLength <
57625c7e1a8SPierre Schweitzer sizeof(MOUNTDEV_SUGGESTED_LINK_NAME) +
57725c7e1a8SPierre Schweitzer LinkName->NameLength - sizeof(WCHAR)) {
57825c7e1a8SPierre Schweitzer
57925c7e1a8SPierre Schweitzer IoStatus->Information = sizeof(MOUNTDEV_SUGGESTED_LINK_NAME);
58025c7e1a8SPierre Schweitzer return STATUS_BUFFER_OVERFLOW;
58125c7e1a8SPierre Schweitzer }
58225c7e1a8SPierre Schweitzer
58325c7e1a8SPierre Schweitzer RtlCopyMemory(LinkName->Name, buf, unicode.Length);
58425c7e1a8SPierre Schweitzer
58525c7e1a8SPierre Schweitzer IoStatus->Information =
58625c7e1a8SPierre Schweitzer sizeof(MOUNTDEV_SUGGESTED_LINK_NAME) +
58725c7e1a8SPierre Schweitzer LinkName->NameLength - sizeof(WCHAR);
58825c7e1a8SPierre Schweitzer
58925c7e1a8SPierre Schweitzer return STATUS_SUCCESS;
59025c7e1a8SPierre Schweitzer }
59125c7e1a8SPierre Schweitzer
59225c7e1a8SPierre Schweitzer //
59325c7e1a8SPierre Schweitzer // IOCTL_MOUNTDEV_LINK_CREATED / IOCTL_MOUNTDEV_LINK_DELETED
59425c7e1a8SPierre Schweitzer // Issued after the mount manager created/deleted a symbolic link
59525c7e1a8SPierre Schweitzer // If the link is a drive letter, store the new value into the
59625c7e1a8SPierre Schweitzer // registry as the new drive letter
59725c7e1a8SPierre Schweitzer //
59825c7e1a8SPierre Schweitzer NTSTATUS
VfdMountDevLinkModified(PDEVICE_EXTENSION DeviceExtension,PMOUNTDEV_NAME LinkName,ULONG InputLength,ULONG ControlCode)59925c7e1a8SPierre Schweitzer VfdMountDevLinkModified(
60025c7e1a8SPierre Schweitzer PDEVICE_EXTENSION DeviceExtension,
60125c7e1a8SPierre Schweitzer PMOUNTDEV_NAME LinkName,
60225c7e1a8SPierre Schweitzer ULONG InputLength,
60325c7e1a8SPierre Schweitzer ULONG ControlCode)
60425c7e1a8SPierre Schweitzer {
60525c7e1a8SPierre Schweitzer if (InputLength < sizeof(MOUNTDEV_NAME)) {
60625c7e1a8SPierre Schweitzer return STATUS_INVALID_PARAMETER;
60725c7e1a8SPierre Schweitzer }
60825c7e1a8SPierre Schweitzer
60925c7e1a8SPierre Schweitzer if (InputLength < sizeof(MOUNTDEV_NAME) +
61025c7e1a8SPierre Schweitzer LinkName->NameLength - sizeof(WCHAR)) {
61125c7e1a8SPierre Schweitzer
61225c7e1a8SPierre Schweitzer return STATUS_INVALID_PARAMETER;
61325c7e1a8SPierre Schweitzer }
61425c7e1a8SPierre Schweitzer
61525c7e1a8SPierre Schweitzer #if DBG
61625c7e1a8SPierre Schweitzer { // Print the reported link name
61725c7e1a8SPierre Schweitzer PWSTR buf = ExAllocatePoolWithTag(
61825c7e1a8SPierre Schweitzer PagedPool, LinkName->NameLength + sizeof(WCHAR), VFD_POOL_TAG);
61925c7e1a8SPierre Schweitzer
62025c7e1a8SPierre Schweitzer if (buf) {
62125c7e1a8SPierre Schweitzer RtlZeroMemory(buf, LinkName->NameLength + sizeof(WCHAR));
62225c7e1a8SPierre Schweitzer RtlCopyMemory(buf, LinkName->Name, LinkName->NameLength);
62325c7e1a8SPierre Schweitzer VFDTRACE(VFDINFO, ("[VFD] %ws\n", buf));
62425c7e1a8SPierre Schweitzer ExFreePool(buf);
62525c7e1a8SPierre Schweitzer }
62625c7e1a8SPierre Schweitzer }
62725c7e1a8SPierre Schweitzer #endif // DBG
62825c7e1a8SPierre Schweitzer
62925c7e1a8SPierre Schweitzer if (LinkName->NameLength == 28 &&
63025c7e1a8SPierre Schweitzer LinkName->Name[0] == L'\\' &&
63125c7e1a8SPierre Schweitzer LinkName->Name[1] == L'D' &&
63225c7e1a8SPierre Schweitzer LinkName->Name[2] == L'o' &&
63325c7e1a8SPierre Schweitzer LinkName->Name[3] == L's' &&
63425c7e1a8SPierre Schweitzer LinkName->Name[4] == L'D' &&
63525c7e1a8SPierre Schweitzer LinkName->Name[5] == L'e' &&
63625c7e1a8SPierre Schweitzer LinkName->Name[6] == L'v' &&
63725c7e1a8SPierre Schweitzer LinkName->Name[7] == L'i' &&
63825c7e1a8SPierre Schweitzer LinkName->Name[8] == L'c' &&
63925c7e1a8SPierre Schweitzer LinkName->Name[9] == L'e' &&
64025c7e1a8SPierre Schweitzer LinkName->Name[10] == L's' &&
64125c7e1a8SPierre Schweitzer LinkName->Name[11] == L'\\' &&
64225c7e1a8SPierre Schweitzer LinkName->Name[12] >= L'A' &&
64325c7e1a8SPierre Schweitzer LinkName->Name[12] <= L'Z' &&
64425c7e1a8SPierre Schweitzer LinkName->Name[13] == L':') {
64525c7e1a8SPierre Schweitzer
64625c7e1a8SPierre Schweitzer // The link is a drive letter
64725c7e1a8SPierre Schweitzer
64825c7e1a8SPierre Schweitzer if (ControlCode == IOCTL_MOUNTDEV_LINK_CREATED) {
64925c7e1a8SPierre Schweitzer // link is created - store the new drive letter
65025c7e1a8SPierre Schweitzer DeviceExtension->DriveLetter = (CHAR)LinkName->Name[12];
65125c7e1a8SPierre Schweitzer }
65225c7e1a8SPierre Schweitzer else {
65325c7e1a8SPierre Schweitzer // link is deleted - clear the drive letter
65425c7e1a8SPierre Schweitzer DeviceExtension->DriveLetter = 0;
65525c7e1a8SPierre Schweitzer }
65625c7e1a8SPierre Schweitzer
65725c7e1a8SPierre Schweitzer // Store the value into the registry
65825c7e1a8SPierre Schweitzer
65925c7e1a8SPierre Schweitzer VfdStoreLink(DeviceExtension);
66025c7e1a8SPierre Schweitzer }
66125c7e1a8SPierre Schweitzer
66225c7e1a8SPierre Schweitzer return STATUS_SUCCESS;
66325c7e1a8SPierre Schweitzer }
66425c7e1a8SPierre Schweitzer
66525c7e1a8SPierre Schweitzer #endif // VFD_MOUNT_MANAGER
666