📄 vfdctl.c
字号:
else {
strcpy(file_name, file_info->FileName);
}
}
if (read_only) {
*read_only = file_info->ReadOnly;
}
if (file_size) {
*file_size = file_info->FileSize;
}
cleanup:
if (hDevice != INVALID_HANDLE_VALUE) {
CloseHandle(hDevice);
}
if (file_info) {
free(file_info);
}
return ret;
}
//
// Get current media state (mounted / write protected)
//
DWORD VfdGetMediaState()
{
HANDLE hDevice;
DWORD size;
DWORD ret = ERROR_SUCCESS;
// Open Virtual FD device
hDevice = VfdOpenDevice();
if (hDevice == INVALID_HANDLE_VALUE) {
ret = GetLastError();
DEBUG_TRACE1("VfdGetMediaState: CreateFile(" VFD_DEVICE_DOSNAME ") - %s",
ErrMsg(ret));
return ret;
}
// Query file information
if (!DeviceIoControl(
hDevice,
IOCTL_DISK_IS_WRITABLE,
NULL,
0,
NULL,
0,
&size,
NULL))
{
ret = GetLastError();
if (ret != ERROR_NOT_READY) {
DEBUG_TRACE1(
"VfdGetFileInfo: DeviceIoControl(IOCTL_DISK_IS_WRITABLE) - %s",
ErrMsg(ret));
}
}
CloseHandle(hDevice);
return ret;
}
//
// Assign a DOS drive letter to Virtual Floppy Drive
//
DWORD VfdSetDriveLetter(
TCHAR drive_letter)
{
DWORD ret = ERROR_SUCCESS;
TCHAR dos_device[] = " :";
TCHAR device_name[MAX_PATH];
if (!isalpha(drive_letter)) {
return ERROR_INVALID_DRIVE;
}
dos_device[0] = (TCHAR)toupper(drive_letter);
// Check if the drive letter is already in use
if (QueryDosDevice(dos_device, device_name, sizeof(device_name))) {
if (strcmp(device_name, VFD_DEVICE_FULLNAME) == 0) {
return ERROR_SUCCESS;
}
else {
DEBUG_TRACE2(
"VfdLink: Drive letter '%c' is linked to '%s'\n",
dos_device[0], device_name);
return ERROR_ALREADY_ASSIGNED;
}
}
else {
if ((ret = GetLastError()) != ERROR_FILE_NOT_FOUND) {
DEBUG_TRACE2(
"VfdLink: QueryDosDevice(%s) - %lu\n",
dos_device, ErrMsg(ret));
return ret;
}
}
// Check if the Virtual FD drive has a DriveLetter already assigned
if ((ret = VfdGetDriveLetter(&drive_letter)) != ERROR_SUCCESS) {
DEBUG_TRACE1("VfdLink: VfdGetDriveLetter - %s",
ErrMsg(ret));
return ret;
}
if (isalpha(drive_letter)) {
if (drive_letter == dos_device[0]) {
return ERROR_SUCCESS;
}
else {
DEBUG_TRACE1("Drive Letter '%c' is already assigned\n",
drive_letter);
return VFD_ERROR_ALREADY_LINKED;
}
}
// Assign the new drive letter
if (DefineDosDevice(DDD_RAW_TARGET_PATH, dos_device, VFD_DEVICE_FULLNAME)) {
// operation successfull
VfdNotify(VFD_OPERATION_LINK, 0);
}
else {
ret = GetLastError();
DEBUG_TRACE2("VfdLink: DefineDosDevice(%s) - %s\n",
dos_device, ErrMsg(ret));
}
return ret;
}
//
// Remove Dos Drive Letter
//
DWORD VfdDelDriveLetter(
TCHAR drive_letter)
{
TCHAR dos_device[] = " :";
DWORD ret = ERROR_SUCCESS;
if (!isalpha(drive_letter)) {
return ERROR_INVALID_DRIVE;
}
dos_device[0] = drive_letter;
if (DefineDosDevice(
(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE),
dos_device,
VFD_DEVICE_FULLNAME)) {
// operation successfull
VfdNotify(VFD_OPERATION_ULINK, 0);
}
else {
ret = GetLastError();
DEBUG_TRACE2(
"VfdUnlink: DefineDosDevice(%s) - %s\n",
dos_device, ErrMsg(ret));
}
return ret;
}
//
// Get Virtual FD drive letter
//
DWORD VfdGetDriveLetter(
TCHAR *drive_letter)
{
DWORD logical_drives;
TCHAR dos_device[] = " :";
TCHAR device_name[MAX_PATH];
DWORD ret = ERROR_SUCCESS;
if (!drive_letter) {
return ERROR_INVALID_PARAMETER;
}
*drive_letter = '\0';
logical_drives = GetLogicalDrives();
if (logical_drives == 0) {
ret = GetLastError();
DEBUG_TRACE1(
"VfdGetDriveLetter: GetLogicalDrives - %s", ErrMsg(ret));
return ret;
}
dos_device[0] = 'A';
while (logical_drives) {
if (logical_drives & 0x01) {
if (QueryDosDevice(dos_device, device_name, sizeof(device_name))) {
if (_stricmp(device_name, VFD_DEVICE_FULLNAME) == 0) {
*drive_letter = dos_device[0];
return ERROR_SUCCESS;
}
}
else {
ret = GetLastError();
DEBUG_TRACE2(
"VfdGetDriveLetter: QueryDosDevice(%s) - %s\n",
dos_device, ErrMsg(ret));
return ret;
}
}
logical_drives >>= 1;
dos_device[0]++;
}
return ret;
}
//
// Check if specified file is valid VFD driver
//
DWORD VfdCheckDriverFile(
LPCTSTR driver_path)
{
DWORD size;
DWORD dummy;
LPVOID info;
VS_FIXEDFILEINFO *fixedinfo;
DWORD ret = ERROR_SUCCESS;
LPTSTR str;
// Check parameter
if (!driver_path || !*driver_path) {
return ERROR_INVALID_PARAMETER;
}
// Check if the driver file is accessible?
{
HANDLE hFile = CreateFile(
driver_path,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE) {
ret = GetLastError();
return ret;
}
CloseHandle(hFile);
}
// Ensure that the driver binary is located on a local drive
// because device driver cannot be started on network drives.
if (*driver_path == '\\' && *(driver_path + 1) == '\\') {
// full path is a UNC path -- \\server\dir\...
DEBUG_TRACE0( "VfdCheckDriverFile: Driver is located on a network drive\n");
return VFD_ERROR_DRIVER_LOCATION;
}
else {
// ensure that the drive letter is not a network drive
char root[] = " :\\";
root[0] = *driver_path;
if (GetDriveType(root) == DRIVE_REMOTE) {
// the drive is a network drive
DEBUG_TRACE0( "VfdCheckDriverFile: Driver is located on a network drive\n");
return VFD_ERROR_DRIVER_LOCATION;
}
}
// check file version
size = GetFileVersionInfoSize((LPTSTR)driver_path, &dummy);
if (size == 0) {
ret = VFD_ERROR_DRIVER_FILE;
DEBUG_TRACE0(
"VfdCheckDriverFile: GetFileVersionInfoSize == 0\n");
return ret;
}
if ((info = malloc(size)) == NULL) {
ret = GetLastError();
DEBUG_TRACE2(
"VfdCheckDriverFile: malloc(%lu) - %s\n", size, ErrMsg(ret));
return ret;
}
if (!GetFileVersionInfo((LPTSTR)driver_path, 0, size, info)) {
ret = GetLastError();
DEBUG_TRACE1(
"VfdCheckDriverFile: GetFileVersionInfo - %s", ErrMsg(ret));
goto cleanup;
}
size = sizeof(fixedinfo);
if (!VerQueryValue(info, "\\", &fixedinfo, (PUINT)&size)) {
ret = GetLastError();
DEBUG_TRACE1(
"VfdCheckDriverFile: VerQueryValue(\"\\\") - %s", ErrMsg(ret));
goto cleanup;
}
if (fixedinfo->dwFileOS != VOS_NT_WINDOWS32 ||
fixedinfo->dwFileType != VFT_DRV ||
fixedinfo->dwFileSubtype != VFT2_DRV_SYSTEM) {
DEBUG_TRACE0(
"VfdCheckDriverFile: Invalid file type flags\n");
ret = VFD_ERROR_DRIVER_FILE;
goto cleanup;
}
if (!VerQueryValue(info, "\\StringFileInfo\\000004b0\\OriginalFileName", &str, (PUINT)&size)) {
ret = GetLastError();
DEBUG_TRACE1(
"VfdCheckDriverFile: VerQueryValue(\"OriginalFileName\") - %s",
ErrMsg(ret));
goto cleanup;
}
if (strcmp(str, "vfd.sys")) {
DEBUG_TRACE0(
"VfdCheckDriverFile: Invalid original file name\n");
ret = VFD_ERROR_DRIVER_FILE;
goto cleanup;
}
if (fixedinfo->dwFileVersionMS < 0x00010000 ||
fixedinfo->dwProductVersionMS < 0x00010000) {
DEBUG_TRACE2(
"VfdCheckDriverFile: Invalid version values - file:%08x, prod: %08x\n",
fixedinfo->dwFileVersionMS, fixedinfo->dwProductVersionMS);
ret = VFD_ERROR_DRIVER_VERSION;
goto cleanup;
}
cleanup:
free(info);
return ret;
}
//
// check if specified path is valid for image file
//
DWORD VfdCheckImageFile(
LPCTSTR file_name,
ULONG *file_size,
BOOL *read_only)
{
WIN32_FILE_ATTRIBUTE_DATA attrib;
HANDLE hFile;
DWORD ret = ERROR_SUCCESS;
if (!file_name) {
return ERROR_INVALID_PARAMETER;
}
// check file attribute
if (!GetFileAttributesEx(file_name, GetFileExInfoStandard, &attrib)) {
ret = GetLastError();
if (ret != ERROR_FILE_NOT_FOUND) {
DEBUG_TRACE2(
"VfdCheckImageFile: GetFileAttributesEx(%s) - %s\n",
file_name, ErrMsg(ret));
}
return ret;
}
if ((attrib.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
return VFD_ERROR_DIRECTORY;
}
if ((attrib.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) ||
(attrib.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED))
{
return VFD_ERROR_IMAGE_ATTRIBUTE;
}
if (attrib.nFileSizeHigh != 0 ||
(attrib.nFileSizeLow != VFD_FILESIZE_720KB &&
attrib.nFileSizeLow != VFD_FILESIZE_1P44MB &&
attrib.nFileSizeLow != VFD_FILESIZE_2P88MB))
{
return VFD_ERROR_IMAGE_SIZE;
}
if (file_size) {
*file_size = attrib.nFileSizeLow;
}
// check if file can be opened
hFile = CreateFile(file_name,
(read_only && *read_only) ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
(read_only && *read_only) ? FILE_SHARE_READ : 0,
NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
CloseHandle(hFile);
return ERROR_SUCCESS;
}
// failed to open
ret = GetLastError();
if (ret != ERROR_ACCESS_DENIED || (read_only && *read_only)) {
return ret;
}
// try opening it read-only
hFile = CreateFile(file_name, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
// cannot open even read-only
ret = GetLastError();
DEBUG_TRACE2(
"VfdCheckImageFile: CreateFile(%s) - %s\n",
file_name, ErrMsg(ret));
return ret;
}
CloseHandle(hFile);
// file can be opened read-only
if (read_only) {
*read_only = TRUE;
}
return ERROR_SUCCESS;
}
//
// Format an error message from error code
//
int VfdErrorMessage(DWORD err, LPTSTR buf, DWORD size)
{
int len;
if (IS_VFD_ERROR(err)) {
len = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE,
DLL_INSTANCE, err, 0, buf, size, NULL);
if (len == 0) {
len = sprintf(buf, "Unknown VFD error %lu\n", err);
}
}
else {
len = FormatMessage(
(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM),
NULL, err, 0, buf, size, NULL);
if (len == 0) {
len = sprintf(buf, "Unknown system error %lu\n", err);
}
}
return len;
}
// End Of File
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -