⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vfdctl.c

📁 Virtual Floppy Driver
💻 C
📖 第 1 页 / 共 3 页
字号:
		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 + -