xref: /reactos/modules/rosapps/drivers/vfd/vfdmnt.c (revision 3ff08b64)
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