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

📄 vfdctl.c

📁 Virtual Floppy Driver
💻 C
📖 第 1 页 / 共 3 页
字号:
	//	Connect to the Service Control Manager

	hScManager = OpenSCManager(NULL, NULL, 0);

	if (hScManager == NULL) {
		ret = GetLastError();

		DEBUG_TRACE1("VfdGetDriverInfo: OpenSCManager() - %s", ErrMsg(ret));

		return ret;
	}

	//	Open Existing Service Object

	hService = OpenService(
		hScManager,						// Service control manager
		VFD_DEVICE_BASENAME,			// service name
		SERVICE_QUERY_CONFIG);			// service access mode

	if (hService == NULL) {
		ret = GetLastError();

		DEBUG_TRACE1("VfdGetDriverInfo: OpenService(SERVICE_QUERY_CONFIG) - %s",
			ErrMsg(ret));

		goto cleanup;
	}

	//	Get the size of config information

	if (!QueryServiceConfig(hService, NULL, 0, &size)) {
		ret = GetLastError();

		if (ret == ERROR_INSUFFICIENT_BUFFER) {
			ret = ERROR_SUCCESS;
		}
		else {
			DEBUG_TRACE1("VfdGetDriverInfo: QueryServiceConfig() - %s",
				ErrMsg(ret));

			goto cleanup;
		}
	}

	//	allocate a required buffer

	config = malloc(size);

	if (config == NULL) {
		ret = GetLastError();

		DEBUG_TRACE2("VfdGetDriverInfo: malloc(%lu) - %s\n",
			size, ErrMsg(ret));

		goto cleanup;
	}

	//	get the config information

	if (!QueryServiceConfig(hService, config, size, &size)) {
		ret = GetLastError();

		DEBUG_TRACE1("VfdGetDriverInfo: QueryServiceConfig() - %s",
			ErrMsg(ret));

		goto cleanup;
	}

	//	copy information to output buffer

	if (driver_path) {
		if (strncmp(config->lpBinaryPathName, "\\??\\", 4) == 0) {
			strncpy(
				driver_path,
				config->lpBinaryPathName + 4,
				MAX_PATH);
		}
		else {
			strncpy(
				driver_path,
				config->lpBinaryPathName,
				MAX_PATH);
		}
	}

	if (start_type) {
		*start_type = config->dwStartType;
	}

cleanup:
	//	Free service config buffer

	if (config) {
		free(config);
	}

	//	Close the service object handle

	if (hService) {
		CloseServiceHandle(hService);
	}

	//	Close handle to the service control manager.

	if (hScManager) {
		CloseServiceHandle(hScManager);
	}

	return ret;
}

//
//	Get Virtual FD driver state
//
DWORD VfdGetDriverState(
	LPDWORD current_state)
{
	SC_HANDLE		hScManager = NULL;	// Service Control Manager
	SC_HANDLE		hService = NULL;	// Service (= Driver)
	SERVICE_STATUS	status;
	DWORD			ret = ERROR_SUCCESS;

	if (current_state) {
		*current_state = 0;
	}

	//	Connect to the Service Control Manager

	hScManager = OpenSCManager(NULL, NULL, 0);

	if (hScManager == NULL) {
		ret = GetLastError();

		DEBUG_TRACE1("VfdGetDriverState: OpenSCManager() - %s",
			ErrMsg(ret));

		return ret;
	}

	//	Open Existing Service Object

	hService = OpenService(
		hScManager,						// Service control manager
		VFD_DEVICE_BASENAME,			// service name
		SERVICE_QUERY_STATUS);			// service access mode

	if (hService == NULL) {
		ret = GetLastError();

		DEBUG_TRACE1(
			"VfdGetDriverState: OpenService(SERVICE_QUERY_STATUS) - %s",
			ErrMsg(ret));

		if (ret == ERROR_SERVICE_DOES_NOT_EXIST) {
			if (current_state) {
				*current_state = VFD_NOT_INSTALLED;
			}
			ret = ERROR_SUCCESS;
		}

		goto cleanup;
	}

	//	Get current driver status

	memset(&status, 0, sizeof(status));

	if (!QueryServiceStatus(hService, &status)) {
		ret = GetLastError();

		DEBUG_TRACE1("VfdGetDriverState: QueryServiceStatus() - %s",
			ErrMsg(ret));

		goto cleanup;
	}

	if (current_state) {
		*current_state = status.dwCurrentState;
	}

cleanup:
	//	Close the service object handle

	if (hService) {
		CloseServiceHandle(hService);
	}

	//	Close handle to the service control manager.

	if (hScManager) {
		CloseServiceHandle(hScManager);
	}

	return ret;
}

//
//	Mount Virtual Floppy Image File
//
DWORD VfdMount(
	LPCTSTR	file_name,
	BOOL	read_only,
	ULONG	file_size)
{
	PVFD_FILE_INFO	fileinfo;
	LPCTSTR			prefix;
	TCHAR			abspath[MAX_PATH];
	DWORD			length;
	HANDLE			hDevice;
	DWORD			ret = ERROR_SUCCESS;

	//	Check image file

	if (file_name && *file_name) {
		ret = VfdCheckImageFile(file_name, &file_size, &read_only);

		if (ret == ERROR_FILE_NOT_FOUND) {
			//	If file does not exist, filesize must be specified
			//	and read-only option must *not* be specified

			if (file_size != VFD_FILESIZE_720KB &&
				file_size != VFD_FILESIZE_1P44MB &&
				file_size != VFD_FILESIZE_2P88MB)
			{
				DEBUG_TRACE1("VfdMount: Invalid file size - %lu\n",
					file_size);
				return VFD_ERROR_IMAGE_SIZE;
			}

			if (read_only) {
				DEBUG_TRACE0( "VfdMount: Create read-only\n");
				return VFD_ERROR_CREATE_READONLY;
			}

			ret = ERROR_SUCCESS;
		}
		else if (ret != ERROR_SUCCESS) {
			return ret;
		}

		//	Prepare absolute path in WIN32 namespace

		if (*file_name == '\\' && *(file_name + 1) == '\\') {

			// \\server\share\path\floppy.img

			prefix = "\\??\\UNC";
			file_name++;			// omit first '\'
		}
		else {
			LPTSTR file_part;

			if (GetFullPathName(file_name, sizeof(abspath), abspath, &file_part) == 0) {
				ret =  GetLastError();

				DEBUG_TRACE2("VfdMount: GetFullPathName(%s) - %s\n",
					file_name, ErrMsg(ret));

				return ret;
			}

			prefix = "\\??\\";
			file_name = abspath;
		}

		length = strlen(prefix) + strlen(file_name);
	}
	else {
		prefix = NULL;
		length = 0;
	}

	//	prepare VFD_FILE_INFO structure

	fileinfo = malloc(sizeof(VFD_FILE_INFO) + length);

	if (fileinfo == NULL) {
		ret = GetLastError();

		DEBUG_TRACE2("VfdMount: malloc(%lu) - %s\n",
			sizeof(VFD_FILE_INFO) + length, ErrMsg(ret));

		return ret;
	}

	memset(fileinfo, 0, sizeof(VFD_FILE_INFO) + length);

	if (length) {
		sprintf((char *)fileinfo->FileName, "%s%s", prefix, file_name);
	}
	fileinfo->FileNameLength = (USHORT)length;

	fileinfo->ReadOnly = (BOOLEAN)read_only;
	fileinfo->FileSize = file_size;

	DEBUG_TRACE3("Mounting file \"%s\" %lu bytes %s\n",
		fileinfo->FileName, file_size, read_only ? "ro" : "");

	//	Open Virtual FD device
	hDevice = VfdOpenDevice();

	if (hDevice == INVALID_HANDLE_VALUE) {
		ret = GetLastError();

		DEBUG_TRACE1("VfdMount: CreateFile(" VFD_DEVICE_DOSNAME ") - %s",
			ErrMsg(ret));

		goto cleanup;
	}

	//	Mount image file

	if (!DeviceIoControl(
		hDevice,
		IOCTL_VFD_OPEN_FILE,
		fileinfo,
		sizeof(VFD_FILE_INFO) + fileinfo->FileNameLength,
		NULL,
		0,
		&length,
		NULL))
	{
		ret = GetLastError();

		DEBUG_TRACE1("VfdMount: DeviceIoControl(IOCTL_VFD_MOUNT_FILE) - %s",
			ErrMsg(ret));

		goto cleanup;
	}

cleanup:
	if (hDevice != INVALID_HANDLE_VALUE) {
		CloseHandle(hDevice);
	}

	if (fileinfo) {
		free(fileinfo);
	}

	//	Broadcast the successful operation
	if (ret == ERROR_SUCCESS) {
		VfdNotify(VFD_OPERATION_MOUNT, 0);
	}

	return ret;
}

//
//	Unmount Image File
//
DWORD VfdUmount()
{
	HANDLE	hDevice;
	DWORD	size;
	DWORD	ret = ERROR_SUCCESS;

	//	Open Virtual FD device
	hDevice = VfdOpenDevice();

	if (hDevice == INVALID_HANDLE_VALUE) {
		ret = GetLastError();

		DEBUG_TRACE1("VfdUmount: CreateFile(" VFD_DEVICE_DOSNAME ") - %s",
			ErrMsg(ret));

		return ret;
	}

	if (!DeviceIoControl(
		hDevice,
		FSCTL_LOCK_VOLUME,
		NULL,
		0,
		NULL,
		0,
		&size,
		NULL))
	{
		ret = GetLastError();

		DEBUG_TRACE1("VfdUmount: DeviceIoControl(FSCTL_LOCK_VOLUME) - %s",
			ErrMsg(ret));

		goto cleanup;
	}

	if (!DeviceIoControl(
		hDevice,
		IOCTL_VFD_CLOSE_FILE,
		NULL,
		0,
		NULL,
		0,
		&size,
		NULL))
	{
		ret = GetLastError();

		DEBUG_TRACE1("VfdUmount: DeviceIoControl(IOCTL_VFD_UNMOUNT_FILE) - %s",
			ErrMsg(ret));

		goto cleanup;
	}

	if (!DeviceIoControl(
		hDevice,
		FSCTL_DISMOUNT_VOLUME,
		NULL,
		0,
		NULL,
		0,
		&size,
		NULL))
	{
		ret = GetLastError();

		DEBUG_TRACE1("VfdUmount: DeviceIoControl(FSCTL_DISMOUNT_VOLUME) - %s",
			ErrMsg(ret));

		goto cleanup;
	}

	if (!DeviceIoControl(
		hDevice,
		FSCTL_UNLOCK_VOLUME,
		NULL,
		0,
		NULL,
		0,
		&size,
		NULL))
	{
		ret = GetLastError();

		DEBUG_TRACE1("VfdUmount: DeviceIoControl(FSCTL_UNLOCK_VOLUME) - %s",
			ErrMsg(ret));

		goto cleanup;
	}

cleanup:
	if (hDevice != INVALID_HANDLE_VALUE) {
		CloseHandle(hDevice);
	}

	//	Broadcast the successful operation
	if (ret == ERROR_SUCCESS) {
		VfdNotify(VFD_OPERATION_UMOUNT, 0);
	}

	return ret;
}

//
//	Get Virtual FD image file info
//
DWORD VfdGetFileInfo(
	LPTSTR	file_name,
	ULONG	*file_size,
	BOOL	*read_only)
{
	HANDLE			hDevice;
	PVFD_FILE_INFO	file_info;
	DWORD			size;
	DWORD			ret = ERROR_SUCCESS;

	if ((file_info = malloc(sizeof(VFD_FILE_INFO) + MAX_PATH)) == NULL) {
		ret = GetLastError();

		DEBUG_TRACE2("VfdGetFileInfo: malloc(%lu) - %s\n",
			sizeof(VFD_FILE_INFO) + MAX_PATH, ErrMsg(ret));

		return ret;
	}

	memset(file_info, 0, sizeof(VFD_FILE_INFO) + MAX_PATH);

	//	Open Virtual FD device
	hDevice = VfdOpenDevice();

	if (hDevice == INVALID_HANDLE_VALUE) {
		ret = GetLastError();

		DEBUG_TRACE1("VfdGetFileInfo: CreateFile(" VFD_DEVICE_DOSNAME ") - %s",
			ErrMsg(ret));

		goto cleanup;;
	}

	//	Query file information

	if (!DeviceIoControl(
		hDevice,
		IOCTL_VFD_QUERY_FILE,
		NULL,
		0,
		file_info,
		sizeof(VFD_FILE_INFO) + MAX_PATH,
		&size,
		NULL))
	{
		ret = GetLastError();

		DEBUG_TRACE1("VfdGetFileInfo: DeviceIoControl(IOCTL_VFD_QUERY_FILE) - %s",
			ErrMsg(ret));

		goto cleanup;
	}

	//	copy obtained information to output buffer

	if (file_name) {
		//	if filename is too long, clip it
		if (file_info->FileNameLength >= MAX_PATH) {
			file_info->FileNameLength = MAX_PATH - 1;
		}
		// ensure the name is properly terminated
		file_info->FileName[file_info->FileNameLength] = '\0';

		if (strncmp(file_info->FileName, "\\??\\UNC", 7) == 0) {
			*file_name = '\\';
			strcpy(file_name + 1, file_info->FileName + 7);
		}
		else if (strncmp(file_info->FileName, "\\??\\", 4) == 0) {
			strcpy(file_name, file_info->FileName + 4);
		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -