📄 vfdctl.c
字号:
/*
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 + -