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