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

📄 vfdctl.c

📁 Virtual Floppy Driver
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
	vfdctl.c

	Virtual Floppy Disk driver control routines
	Copyright (C) 2003 Kenji Kato
*/

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#pragma warning(push, 3)
#include <winioctl.h>
#pragma warning(pop)

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <stdio.h>

#include "vfdctl.h"
#include "vfdutil.h"

//
//	DOS device name (\\.\VirtualFD)
//
#define VFD_DEVICE_DOSNAME		"\\\\.\\"	VFD_DEVICE_BASENAME

//
//	local functions
//
static void VfdNotify(WPARAM operation, LPARAM param);
static HANDLE VfdOpenDevice();

#ifdef DLL_EXPORTS
//
//	handle to this module instance
//
static HINSTANCE DLL_INSTANCE = NULL;

//
//	DLL entry point
//
BOOL APIENTRY DllMain(
	HANDLE hModule,
	DWORD  reason,
	LPVOID lpReserved)
{
	UNREFERENCED_PARAMETER(lpReserved);

	if (reason == DLL_PROCESS_ATTACH) {
		//	save this DLL's module instance handle

		DLL_INSTANCE = (HINSTANCE)hModule;
	}

	return TRUE;
}
#else	// DLL_EXPORTS
#define DLL_INSTANCE	NULL
#endif	// DLL_EXPORTS

//
//	broadcast state change to all the top level windows
//
void VfdNotify(WPARAM operation, LPARAM param)
{
	static UINT uVfdMsg = 0;

	if (uVfdMsg == 0) {
		//	register VFD message

		uVfdMsg = RegisterWindowMessage(VFD_BROADCAST_MSG_STR);
	}

	//	send/post the broadcast message

	SendNotifyMessage(HWND_BROADCAST, uVfdMsg, operation, param);
}

//
//	open the Virtual FD device without showing the "Insert Floppy"
//	dialog when the drive is empty.
//
HANDLE VfdOpenDevice()
{
	HANDLE hDevice = NULL;

	// change error mode in order to avoid "Insert Floppy" dialog

	UINT err_mode = SetErrorMode(SEM_FAILCRITICALERRORS);

	//	open the Virtual FD device

	hDevice = CreateFile(
		VFD_DEVICE_DOSNAME,
		GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		NULL,
		OPEN_EXISTING,
		FILE_FLAG_NO_BUFFERING,
		NULL);

	//	revert to the previous error mode

	SetErrorMode(err_mode);

	//	return the handle to the Virtual FD device

	return hDevice;
}

//
//	Install Virtual Floppy Driver dynamically
//
DWORD VfdInstall(
	LPCTSTR		driver_path,
	BOOL		auto_start)
{
	SC_HANDLE	hScManager;				// Service Control Manager
	SC_HANDLE	hService;				// Service (= Driver)
	TCHAR		full_path[MAX_PATH];
	DWORD		ret = ERROR_SUCCESS;

	//	Prepare driver binary's full path

	if (driver_path == NULL || *driver_path == '\0') {

		// default driver file is vfd.sys in the same directory as executable

		DWORD len = GetModuleFileName(
			NULL, full_path, sizeof(full_path));

		if (len == 0) {
			ret = GetLastError();

			DEBUG_TRACE1("VfdInstall: GetModuleFileName - %s",
				ErrMsg(ret));

			return ret;
		}

		//	search the last '\' char

		while (len > 0 && full_path[len - 1] != '\\') {
			len --;
		}

		strcpy(&full_path[len], "vfd.sys");
	}
	else {
		//	ensure that tha path is absolute full path

		LPTSTR file_part;

		if (GetFullPathName(
			driver_path,
			sizeof(full_path),
			full_path,
			&file_part) == 0)
		{
			ret = GetLastError();

			DEBUG_TRACE2("VfdInstall: GetFullPathName(%s) - %s\n",
				driver_path, ErrMsg(ret));

			return ret;
		}
	}

	//	Check if the file is a valid Virtual FD driver

	ret = VfdCheckDriverFile(full_path);

	if (ret != ERROR_SUCCESS) {
		DEBUG_TRACE1("VfdInstall: VfdCheckDriverFile(%s)\n", full_path);

		return ret;
	}

	//	If the path is under %SystemRoot% make it relative to %SystemRoot%
	{
		TCHAR windir[MAX_PATH];
		int len;

		len = GetEnvironmentVariable("SystemRoot", windir, sizeof(windir));

		if (len > sizeof(windir)) {
			DEBUG_TRACE0(
				"VfdInstall: %%SystemRoot%% contains too long text\n");

			return ERROR_BAD_ENVIRONMENT;
		}
		else if (len && _strnicmp(windir, full_path, len) == 0) {
			memmove(full_path, full_path + len + 1, strlen(full_path) - len);
		}
	}

	//	Connect to the Service Control Manager

	hScManager = OpenSCManager(
		NULL,							// local machine
		NULL,							// local database
		SC_MANAGER_CREATE_SERVICE);		// access required

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

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

		return ret;
	}

	//	Create a new service object

	hService = CreateService(
		hScManager,						// service control manager
		VFD_DEVICE_BASENAME,			// internal service name
		VFD_DEVICE_BASENAME,			// display name
		SERVICE_ALL_ACCESS,				// access mode
		SERVICE_KERNEL_DRIVER,			// service type
		auto_start
			? SERVICE_AUTO_START
			: SERVICE_DEMAND_START,		// service start type
		SERVICE_ERROR_NORMAL,			// start error sevirity
		full_path,						// service image file path
		NULL,							// service group
		NULL,							// service tag
		NULL,							// service dependency
		NULL,							// use LocalSystem account
		NULL							// password for the account
	);

	if (!hService) {
		// Failed to create a service object
		ret = GetLastError();

		DEBUG_TRACE1("VfdInstall: CreateService() - %s", ErrMsg(ret));

		goto cleanup;
	}

cleanup:
	//	Close the service object handle

	if (hService) {
		CloseServiceHandle(hService);
	}

	//	Close handle to the service control manager.

	if (hScManager) {
		CloseServiceHandle(hScManager);
	}

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

	return ret;
}

//
//	Remove Virtual Floppy Driver entry from system registry
//
DWORD VfdRemove()
{
	SC_HANDLE	hScManager;				// Service Control Manager
	SC_HANDLE	hService;				// Service (= Driver)
	DWORD		ret = ERROR_SUCCESS;

	//	Connect to the Service Control Manager

	hScManager = OpenSCManager(NULL, NULL, 0);

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

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

		return ret;
	}

	//	Open Existing Service Object

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

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

		DEBUG_TRACE1("VfdRemove: OpenService(DELETE) - %s", ErrMsg(ret));

		goto cleanup;
	}

	//	Remove driver entry from registry

	if (!DeleteService(hService)) {
		ret = GetLastError();

		DEBUG_TRACE1("VfdRemove: DeleteService() - %s", ErrMsg(ret));

		goto cleanup;
	}

cleanup:
	//	Close the service object handle

	if (hService) {
		CloseServiceHandle(hService);
	}

	//	Close handle to the service control manager.

	if (hScManager) {
		CloseServiceHandle(hScManager);
	}

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

	return ret;
}

//
//	Start Virtual Floppy Driver
//
DWORD VfdStart(DWORD *state)
{
	SC_HANDLE hScManager;				// Service Control Manager
	SC_HANDLE hService;					// Service (= Driver)
	SERVICE_STATUS	stat;
	DWORD ret = ERROR_SUCCESS;
	int i;

	//	Connect to the Service Control Manager

	hScManager = OpenSCManager(NULL, NULL, 0);

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

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

		return ret;
	}

	//	Open Existing Service Object

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

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

		DEBUG_TRACE1("VfdStart: OpenService(SERVICE_START) - %s", ErrMsg(ret));

		goto cleanup;
	}

	//	Start the driver

	if (!StartService(hService, 0, NULL)) {
		ret = GetLastError();

		DEBUG_TRACE1("VfdStart: StartService() - %s", ErrMsg(ret));

		goto cleanup;
	}

	//	Ensure the driver is started
	for (i = 0;;) {
		if (!QueryServiceStatus(hService, &stat)) {
			ret = GetLastError();

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

			break;
		}

		if (stat.dwCurrentState == SERVICE_RUNNING || ++i == 5) {
			break;
		}

		Sleep(1000);
	}

	if (state) {
		*state = stat.dwCurrentState;
	}

cleanup:
	//	Close the service object handle

	if (hService) {
		CloseServiceHandle(hService);
	}

	//	Close handle to the service control manager.

	if (hScManager) {
		CloseServiceHandle(hScManager);
	}

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

	return ret;
}

//
//	Stop Virtual Floppy Driver
//
DWORD VfdStop(DWORD *state)
{
	SC_HANDLE		hScManager;			// Service Control Manager
	SC_HANDLE		hService;			// Service (= Driver)
	SERVICE_STATUS	stat;
	DWORD			ret = ERROR_SUCCESS;
	int				i = 0;

	//	Connect to the Service Control Manager

	hScManager = OpenSCManager(NULL, NULL, 0);

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

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

		return ret;
	}

	//	Open Existing Service Object

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

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

		DEBUG_TRACE1("VfdStop: OpenService(SERVICE_STOP) - %s", ErrMsg(ret));

		goto cleanup;
	}

	//	Stop the driver

	if (!ControlService(hService, SERVICE_CONTROL_STOP, &stat)) {
		ret = GetLastError();

		DEBUG_TRACE1("VfdStop: ControlService(SERVICE_CONTROL_STOP) - %s",
			ErrMsg(ret));

		goto cleanup;
	}

	//	Ensure the driver is stopped
	while (stat.dwCurrentState != SERVICE_STOPPED && ++i < 5) {
		Sleep(1000);

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

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

			break;
		}
	}

	if (state) {
		*state = stat.dwCurrentState;
	}

cleanup:
	//	Close the service object handle

	if (hService) {
		CloseServiceHandle(hService);
	}

	//	Close handle to the service control manager.

	if (hScManager) {
		CloseServiceHandle(hScManager);
	}

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

	return ret;
}

//
//	Get Virtual FD driver configuration
//
DWORD VfdGetDriverConfig(
	LPTSTR	driver_path,
	LPDWORD	start_type)
{
	SC_HANDLE	hScManager;				// Service Control Manager
	SC_HANDLE	hService;				// Service (= Driver)
	LPQUERY_SERVICE_CONFIG config = NULL;
	DWORD		size;
	DWORD		ret = ERROR_SUCCESS;

	if (driver_path) {
		ZeroMemory(driver_path, MAX_PATH);
	}

⌨️ 快捷键说明

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