reactos/modules/rosapps/drivers/vfd/vfdlink.c
Pierre Schweitzer 25c7e1a8d0
[VFD] Import the VFD project (Virtual Floppy Drive) which allows creating virtual
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
2017-12-16 21:48:34 +01:00

227 lines
5 KiB
C

/*
vfdlink.c
Virtual Floppy Drive for Windows NT platform
Kernel mode driver: persistent drive letter functions
Copyright (C) 2003-2005 Ken Kato
*/
#include "imports.h"
#include "vfddrv.h"
#include "vfddbg.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, VfdSetLink)
#pragma alloc_text(PAGE, VfdLoadLink)
#pragma alloc_text(PAGE, VfdStoreLink)
#endif // ALLOC_PRAGMA
//
// create or remove the persistent drive letter (Windows NT)
//
NTSTATUS
VfdSetLink(
IN PDEVICE_EXTENSION DeviceExtension,
IN CHAR DriveLetter)
{
UNICODE_STRING unicode_name;
WCHAR name_buf[15];
NTSTATUS status = STATUS_SUCCESS;
VFDTRACE(VFDINFO, ("[VFD] VfdSetLink - IN\n"));
// convert lower case into upper case
if (DriveLetter >= 'a' && DriveLetter <= 'z') {
DriveLetter -= ('a' - 'A');
}
// check the drive letter range
if (DriveLetter != 0 &&
(DriveLetter < 'A' || DriveLetter > 'Z')) {
return STATUS_INVALID_PARAMETER;
}
if (DeviceExtension->DriveLetter &&
DeviceExtension->DriveLetter != DriveLetter) {
//
// Delete the old drive letter
//
name_buf[sizeof(name_buf) - 1] = UNICODE_NULL;
_snwprintf(name_buf, sizeof(name_buf) - 1,
L"\\??\\%wc:", DeviceExtension->DriveLetter);
RtlInitUnicodeString(&unicode_name, name_buf);
status = IoDeleteSymbolicLink(&unicode_name);
if (NT_SUCCESS(status)) {
VFDTRACE(VFDINFO,
("[VFD] Link %ws deleted\n", name_buf));
DeviceExtension->DriveLetter = 0;
}
else if (status != STATUS_OBJECT_NAME_NOT_FOUND) {
// the driver letter did not exist in the first place
VFDTRACE(VFDINFO,
("[VFD] Link %ws not found\n", name_buf));
DeviceExtension->DriveLetter = 0;
status = STATUS_SUCCESS;
}
else {
VFDTRACE(VFDWARN,
("[VFD] IoDeleteSymbolicLink %ws - %s\n",
name_buf, GetStatusName(status)));
}
}
if (NT_SUCCESS(status) && DriveLetter) {
//
// Create a new drive letter
//
name_buf[sizeof(name_buf) - 1] = UNICODE_NULL;
_snwprintf(name_buf, sizeof(name_buf) - 1,
(OsMajorVersion >= 5) ?
L"\\??\\Global\\%wc:" : L"\\??\\%wc:",
DriveLetter);
RtlInitUnicodeString(&unicode_name, name_buf);
status = IoCreateSymbolicLink(
&unicode_name, &(DeviceExtension->DeviceName));
if (NT_SUCCESS(status)) {
VFDTRACE(VFDINFO, ("[VFD] Link %ws created\n", name_buf));
DeviceExtension->DriveLetter = DriveLetter;
}
else {
VFDTRACE(VFDWARN,
("[VFD] IoCreateSymbolicLink %ws - %s\n",
name_buf, GetStatusName(status)));
}
}
VFDTRACE(VFDINFO,
("[VFD] VfdSetLink - %s\n", GetStatusName(status)));
return status;
}
//
// load the persistent drive letter from the registry
//
NTSTATUS
VfdLoadLink(
IN PDEVICE_EXTENSION DeviceExtension,
IN PWSTR RegistryPath)
{
RTL_QUERY_REGISTRY_TABLE params[2];
WCHAR name_buf[20];
ULONG letter;
ULONG zero = 0;
NTSTATUS status;
VFDTRACE(VFDINFO, ("[VFD] VfdLoadLink - IN\n"));
RtlZeroMemory(params, sizeof(params));
name_buf[sizeof(name_buf) - 1] = UNICODE_NULL;
_snwprintf(name_buf, sizeof(name_buf) - 1,
VFD_REG_DRIVE_LETTER L"%lu",
DeviceExtension->DeviceNumber);
params[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
params[0].Name = name_buf;
params[0].EntryContext = &letter;
params[0].DefaultType = REG_DWORD;
params[0].DefaultData = &zero;
params[0].DefaultLength = sizeof(ULONG);
status = RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
RegistryPath, &params[0], NULL, NULL);
VFDTRACE(VFDINFO,
("[VFD] Drive letter '%wc' loaded from the registry\n",
letter ? letter : ' '));
DeviceExtension->DriveLetter = (CHAR)letter;
VFDTRACE(VFDINFO,
("[VFD] VfdLoadLink - %s\n", GetStatusName(status)));
return status;
}
//
// store the persistent drive letter into the registry
//
NTSTATUS
VfdStoreLink(
IN PDEVICE_EXTENSION DeviceExtension)
{
PVFD_DRIVER_EXTENSION driver_extension;
WCHAR name_buf[20];
ULONG letter;
NTSTATUS status;
VFDTRACE(VFDINFO, ("[VFD] VfdStoreLink - IN\n"));
#ifdef VFD_PNP
driver_extension = IoGetDriverObjectExtension(
DeviceExtension->device_object->DriverObject,
VFD_DRIVER_EXTENSION_ID);
#else // VFD_PNP
driver_extension = DeviceExtension->DriverExtension;
#endif // VFD_PNP
if (!driver_extension ||
!driver_extension->RegistryPath.Buffer) {
VFDTRACE(VFDWARN, ("[VFD] Registry Path not present.\n"));
VFDTRACE(VFDINFO, ("[VFD] VfdStoreLinks - OUT\n"));
return STATUS_DRIVER_INTERNAL_ERROR;
}
name_buf[sizeof(name_buf) - 1] = UNICODE_NULL;
_snwprintf(name_buf, sizeof(name_buf) - 1,
VFD_REG_DRIVE_LETTER L"%lu",
DeviceExtension->DeviceNumber);
letter = DeviceExtension->DriveLetter;
status = RtlWriteRegistryValue(
RTL_REGISTRY_ABSOLUTE,
driver_extension->RegistryPath.Buffer,
name_buf,
REG_DWORD,
&letter,
sizeof(ULONG));
if (!NT_SUCCESS(status)) {
VFDTRACE(VFDWARN,
("[VFD] RtlWriteRegistryValue - %s\n",
GetStatusName(status)));
}
else {
VFDTRACE(VFDINFO,
("[VFD] Drive letter '%wc' stored into the registry\n",
letter ? letter : L' '));
}
VFDTRACE(VFDINFO,
("[VFD] VfdStoreLink - %s\n", GetStatusName(status)));
return status;
}