diff --git a/modules/rosapps/CMakeLists.txt b/modules/rosapps/CMakeLists.txt index 7ffa0b4d853..58a32c1c186 100644 --- a/modules/rosapps/CMakeLists.txt +++ b/modules/rosapps/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(applications) add_subdirectory(demos) add_subdirectory(drivers) +add_subdirectory(include) add_subdirectory(lib) add_subdirectory(templates) diff --git a/modules/rosapps/applications/cmdutils/CMakeLists.txt b/modules/rosapps/applications/cmdutils/CMakeLists.txt index 843b2c5be54..6d5488d30a8 100644 --- a/modules/rosapps/applications/cmdutils/CMakeLists.txt +++ b/modules/rosapps/applications/cmdutils/CMakeLists.txt @@ -6,5 +6,6 @@ add_subdirectory(tee) add_subdirectory(touch) add_subdirectory(uptime) add_subdirectory(vcdcli) +add_subdirectory(vfdcmd) add_subdirectory(winspool_print) add_subdirectory(y) diff --git a/modules/rosapps/applications/cmdutils/vfdcmd/CMakeLists.txt b/modules/rosapps/applications/cmdutils/vfdcmd/CMakeLists.txt new file mode 100644 index 00000000000..fa653f18180 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/vfdcmd/CMakeLists.txt @@ -0,0 +1,10 @@ + +add_message_headers(ANSI vfdmsg.mc) + +include_directories(${REACTOS_SOURCE_DIR}/modules/rosapps/include/vfd) +add_executable(vfdcmd vfdcmd.c vfdcmd.rc) +set_module_type(vfdcmd win32cui) +add_importlibs(vfdcmd advapi32 vfd user32 msvcrt kernel32 ntdll) +add_dependencies(vfdcmd vfdmsg) +set_target_properties(vfdcmd PROPERTIES OUTPUT_NAME "vfd") +add_cd_file(TARGET vfdcmd DESTINATION reactos/system32 FOR all) diff --git a/modules/rosapps/applications/cmdutils/vfdcmd/vfdcmd.c b/modules/rosapps/applications/cmdutils/vfdcmd/vfdcmd.c new file mode 100644 index 00000000000..8cd40bfd937 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/vfdcmd/vfdcmd.c @@ -0,0 +1,3498 @@ +/* + vfdcmd.c + + Virtual Floppy Drive for Windows + Driver control program (console version) + + Copyright (C) 2003-2008 Ken Kato +*/ + +#ifdef __cplusplus +#pragma message(__FILE__": Compiled as C++ for testing purpose.") +#endif // __cplusplus + +#define WIN32_LEAN_AND_MEAN +#define _CRTDBG_MAP_ALLOC +#include +#include +#include +#include +#include + +#ifndef INVALID_FILE_ATTRIBUTES +#define INVALID_FILE_ATTRIBUTES ((DWORD)-1) +#endif // INVALID_FILE_ATTRIBUTES + +#include "vfdtypes.h" +#include "vfdapi.h" +#include "vfdver.h" +#include "vfdmsg.h" + +// +// current driver state +// +static DWORD driver_state = VFD_NOT_INSTALLED; + +// +// interactive flag +// +static const char *help_progname = "VFD.EXE "; + +// +// command functions return value +// +#define VFD_OK 0 +#define VFD_NG 1 + +// +// operation mode +// +#define OPERATION_ASK 0 // ask user on error +#define OPERATION_QUIT 1 // quits on error +#define OPERATION_FORCE 2 // force on error + +// +// invalid target number +// +#define TARGET_NONE (ULONG)-1 + +// +// command processing functions +// +typedef int (*cmdfnc)(const char **args); + +static int Install(const char **args); +static int Remove(const char **args); +static int Config(const char **args); +static int Start(const char **args); +static int Stop(const char **args); +static int Shell(const char **args); +static int Open(const char **args); +static int Close(const char **args); +static int Save(const char **args); +static int Protect(const char **args); +static int Format(const char **args); +static int Link(const char **args); +static int Unlink(const char **args); +static int Status(const char **args); +static int Help(const char **args); +static int Version(const char **args); + +// +// Command table +// +static const struct { + char *cmd; // command string + int max_args; // maximum allowed number of argc + cmdfnc func; // command processing function + DWORD hint; // command hint message id +} +Commands[] = { + {"INSTALL", 2, Install, MSG_HINT_INSTALL}, + {"REMOVE", 1, Remove, MSG_HINT_REMOVE }, + {"CONFIG", 1, Config, MSG_HINT_CONFIG }, + {"START", 0, Start, MSG_HINT_START }, + {"STOP", 1, Stop, MSG_HINT_STOP }, + {"SHELL", 1, Shell, MSG_HINT_SHELL }, + {"OPEN", 6, Open, MSG_HINT_OPEN }, + {"CLOSE", 2, Close, MSG_HINT_CLOSE }, + {"SAVE", 3, Save, MSG_HINT_SAVE, }, + {"PROTECT", 2, Protect, MSG_HINT_PROTECT}, + {"FORMAT", 2, Format, MSG_HINT_FORMAT }, + {"LINK", 3, Link, MSG_HINT_LINK }, + {"ULINK", 1, Unlink, MSG_HINT_ULINK }, + {"STATUS", 0, Status, MSG_HINT_STATUS }, + {"HELP", 1, Help, MSG_HELP_HELP }, + {"?", 1, Help, MSG_HELP_HELP }, + {"VERSION", 0, Version, MSG_HINT_VERSION}, + {0, 0, 0, 0} +}; + +// +// Help message table +// +static const struct { + char *keyword; // help keyword + DWORD help; // help message id +} +HelpMsg[] = { + {"GENERAL", MSG_HELP_GENERAL}, + {"CONSOLE", MSG_HELP_CONSOLE}, + {"INSTALL", MSG_HELP_INSTALL}, + {"REMOVE", MSG_HELP_REMOVE }, + {"CONFIG", MSG_HELP_CONFIG }, + {"START", MSG_HELP_START }, + {"STOP", MSG_HELP_STOP }, + {"SHELL", MSG_HELP_SHELL }, + {"OPEN", MSG_HELP_OPEN }, + {"CLOSE", MSG_HELP_CLOSE }, + {"SAVE", MSG_HELP_SAVE }, + {"PROTECT", MSG_HELP_PROTECT}, + {"FORMAT", MSG_HELP_FORMAT }, + {"LINK", MSG_HELP_LINK }, + {"ULINK", MSG_HELP_ULINK }, + {"STATUS", MSG_HELP_STATUS }, + {"HELP", MSG_HELP_HELP }, + {"VERSION", MSG_HINT_VERSION}, + {0, 0} +}; + +// +// local functions +// +static int InteractiveConsole(); +static int ProcessCommandLine(int argc, const char **args); +static int ParseCommand(const char *cmd); +static int ParseHelpTopic(const char *topic); +static int CheckDriver(); +static int InputChar(ULONG msg, PCSTR ans); +static void PrintImageInfo(HANDLE hDevice); +static void PrintDriveLetter(HANDLE hDevice, ULONG nDrive); +static void PrintMessage(UINT msg, ...); +static BOOL ConsolePager(char *pBuffer, BOOL bReset); +static const char *SystemError(DWORD err); +static void ConvertPathCase(char *src, char *dst); + +// +// utility macro +// +#define IS_WINDOWS_NT() ((GetVersion() & 0xff) < 5) + +// +// main +// +int main(int argc, const char **argv) +{ +#ifdef _DEBUG + + // output vfd.exe command reference text + + if (*(argv + 1) && !_stricmp(*(argv + 1), "doc")) { + int idx = 0; + char *buf = ""; + + printf("\r\n VFD.EXE Command Reference\r\n"); + + while (HelpMsg[idx].keyword) { + int len = strlen(HelpMsg[idx].keyword); + + printf( + "\r\n\r\n" + "====================\r\n" + "%*s\r\n" + "====================\r\n" + "\r\n", + (20 + len) / 2, HelpMsg[idx].keyword); + + FormatMessage( + FORMAT_MESSAGE_FROM_HMODULE | + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_ARGUMENT_ARRAY, + NULL, HelpMsg[idx].help, 0, + (LPTSTR)&buf, 0, (va_list *)&help_progname); + + printf("%s", buf); + + LocalFree(buf); + + idx++; + } + + return 0; + } +#endif + + // Reports memory leaks at process termination + + _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); + + // Check the operating system version + + if (!VfdIsValidPlatform()) { + PrintMessage(MSG_WRONG_PLATFORM); + return VFD_NG; + } + + if (argc < 2) { + // If no parameter is given, enter the interactive mode + + return InteractiveConsole(); + } + else { + // Perform a single operation + + return ProcessCommandLine(argc - 1, argv + 1); + } +} + +// +// VFD interactive console +// +int InteractiveConsole() +{ + char input[1024]; // user input buffer + + int argc; // number of args in the user input + char *args[10]; // args to pass to command functions + + char sepa; // argument separator + char *p; // work pointer + + // Disable the system default Ctrl+C handler + + SetConsoleCtrlHandler(NULL, TRUE); + + // Set the console title + + SetConsoleTitle(VFD_PRODUCT_DESC); + + // print version information and the console hint text + + Version(NULL); + + PrintMessage(MSG_CONSOLE_HINT); + + // set interactive flag to exclude "VFD.EXE" from help text + + help_progname = ""; + + // process user input + + for (;;) { + + // print the prompt + + printf("[VFD] "); + fflush(stdout); + + // read user input + + fflush(stdin); + p = fgets(input, sizeof(input), stdin); + + if (p == NULL) { + + // most likely + + printf("exit\n"); + break; + } + + // skip leading blank characters + + while (*p == ' ' || *p == '\t' || *p == '\n') { + p++; + } + + if (*p == '\0') { + + // empty input + + continue; + } + + // handle external commands + + if (!_strnicmp(p, "dir", 3) || + !_strnicmp(p, "attrib", 6)) { + + // special cases - frequently used commands + // pass these to system() even without '.' + + system(p); + printf("\n"); + continue; + } + else if (*p == '.') { + + // external command + + system(p + 1); + printf("\n"); + continue; + } + + // split the input line into parameters (10 parameters max) + + argc = 0; + ZeroMemory(args, sizeof(args)); + + do { + // top of a parameter + + args[argc++] = p; + + // is the parameter quoted? + + if (*p == '\"' || *p == '\'') { + sepa = *(p++); + } + else { + sepa = ' '; + } + + // search the end of the parameter + + while (*p && *p != '\n') { + if (sepa == ' ') { + if (*p == '\t' || *p == ' ') { + break; // tail of a non-quoted parameter + } + } + else { + if (*p == sepa) { + sepa = ' '; // close quote + } + } + p++; + } + + // terminate the parameter + + if (*p) { + *(p++) = '\0'; + } + + // skip trailing blank characters + + while (*p == ' ' || *p == '\t' || *p == '\n') { + p++; + } + + if (*p == '\0') { + + // end of the input line - no more args + + break; + } + } + while (argc < sizeof(args) / sizeof(args[0])); + + // check the first parameter for special commands + + if (!_stricmp(args[0], "exit") || + !_stricmp(args[0], "quit") || + !_stricmp(args[0], "bye")) { + + // exit command + + break; + } + else if (!_stricmp(args[0], "cd") || + !_stricmp(args[0], "chdir")) { + + // internal change directory command + + if (args[1]) { + char path[MAX_PATH]; + int i; + + // ignore the /d option (of the standard cd command) + + if (_stricmp(args[1], "/d")) { + i = 1; + } + else { + i = 2; + } + + p = args[i]; + + if (*p == '\"' || *p == '\'') { + + // the parameter is quoted -- remove quotations + + p++; + + while (*p && *p != *args[i]) { + p++; + } + + args[i]++; // skip a leading quote + *p = '\0'; // remove a trailing quote + } + else { + + // the parameter is not quoted + // -- concatenate params to allow spaces in unquoted path + + while (i < argc - 1) { + *(args[i] + strlen(args[i])) = ' '; + i++; + } + } + + // Match the case of the path to the name on the disk + + ConvertPathCase(p, path); + + if (!SetCurrentDirectory(path)) { + DWORD ret = GetLastError(); + + if (ret == ERROR_FILE_NOT_FOUND) { + ret = ERROR_PATH_NOT_FOUND; + } + + printf("%s", SystemError(ret)); + } + } + else { + if (!GetCurrentDirectory(sizeof(input), input)) { + printf("%s", SystemError(GetLastError())); + } + else { + printf("%s\n", input); + } + } + } + else if (isalpha(*args[0]) && + *(args[0] + 1) == ':' && + *(args[0] + 2) == '\0') { + + // internal change drive command + + *args[0] = (char)toupper(*args[0]); + *(args[0] + 2) = '\\'; + *(args[0] + 3) = '\0'; + + if (!SetCurrentDirectory(args[0])) { + printf("%s", SystemError(GetLastError())); + } + } + else { + + // perform the requested VFD command + + ProcessCommandLine(argc, (const char **)args); + } + + printf("\n"); + } + + return VFD_OK; +} + +// +// process a single command +// +int ProcessCommandLine(int argc, const char **args) +{ + int cmd; + DWORD ret; + + // + // Decide a command to perform + // + cmd = ParseCommand(*args); + + if (cmd < 0) { + + // no matching command + + return VFD_NG; + } + + if (*(++args) && + (!strcmp(*args, "/?") || + !_stricmp(*args, "/h"))) { + + // print a short hint for the command + + PrintMessage(Commands[cmd].hint); + return VFD_NG; + } + + if (--argc > Commands[cmd].max_args) { + + // too many parameters for the command + + PrintMessage(MSG_TOO_MANY_ARGS); + PrintMessage(Commands[cmd].hint); + return VFD_NG; + } + + // Get the current driver state + + ret = VfdGetDriverState(&driver_state); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_GET_STAT_NG); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + // Perform the requested operation + + return (*Commands[cmd].func)(args); +} + +// +// Install the Virtual Floppy Driver +// Command Line Parameters: +// (optional) driver file path - default to executive's dir +// (optional) auto start switch - default to demand start +// +int Install(const char **args) +{ + const char *install_path = NULL; + DWORD start_type = SERVICE_DEMAND_START; + + DWORD ret; + + // process parameters + + while (args && *args) { + + if (!_stricmp(*args, "/a") || + !_stricmp(*args, "/auto")) { + + if (start_type != SERVICE_DEMAND_START) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } +/* + if (IS_WINDOWS_NT()) { + + // On Windows NT, SYSTEM start drivers must be placed + // under the winnt\system32 directory. Since I don't + // care to handle driver file copying, I use the AUTO + // start method for Windows NT. + + start_type = SERVICE_AUTO_START; + } + else { + + // On Windows XP, the VFD driver must be running when + // the shell starts -- otherwise the shell doesn't + // recognize the VFD drives. Since Windows XP allows + // SYSTEM start drivers to be placed in any local + // directories, I use the SYSTEM start method here. + // + // This is not an issue when the driver is started + // manually because in that case VFD.EXE and VFDWIN.EXE + // notify the shell of the VFD drives. + // + // On Windows 2000 both SYSTEM and AUTO work fine. + + start_type = SERVICE_SYSTEM_START; + } +*/ + // On second thought -- Win2K / XP mount manager assigns + // arbitrary drive letters to all drives it finds during + // the system start up. There is no way to prevent it + // until the driver is fully PnP compatible, so I'd settle + // for AUTO start for the time being. + + start_type = SERVICE_AUTO_START; + } + else if (**args == '/') { + PrintMessage(MSG_UNKNOWN_OPTION, *args); + PrintMessage(MSG_HINT_INSTALL, help_progname); + return VFD_NG; + } + else { + if (install_path) { + PrintMessage(MSG_DUPLICATE_ARGS, "path"); + return VFD_NG; + } + + install_path = *args; + } + + args++; + } + + // already installed? + + if (driver_state != VFD_NOT_INSTALLED) { + PrintMessage(MSG_DRIVER_EXISTS); + return VFD_NG; + } + + // install the driver + + ret = VfdInstallDriver( + install_path, + start_type); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_INSTALL_NG); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + // Get the latest driver state + + ret = VfdGetDriverState(&driver_state); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_GET_STAT_NG); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + // operation successfull + + PrintMessage(MSG_INSTALL_OK); + + return VFD_OK; +} + +// +// Remove Virtual Floppy Driver from system +// Command Line Parameters: +// [/F | /FORCE | /Q | /QUIT] +// /F forces remove operation if the driver cannot be stopped +// /Q quits remove operation if the driver cannot be stopped +// +int Remove(const char **args) +{ + int mode = OPERATION_ASK; + const char *stop_params[] = { NULL, NULL }; + DWORD ret; + int idx; + + // parse parameters + + while (args && *args) { + + if (!_stricmp(*args, "/f") || + !_stricmp(*args, "/force")) { + + if (mode != OPERATION_ASK) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + mode = OPERATION_FORCE; + stop_params[0] = *args; + } + else if (!_stricmp(*args, "/q") || + !_stricmp(*args, "/quit")) { + + if (mode != OPERATION_ASK) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + mode = OPERATION_QUIT; + stop_params[0] = *args; + } + else { + PrintMessage(MSG_UNKNOWN_OPTION, *args); + PrintMessage(MSG_HINT_REMOVE, help_progname); + return VFD_NG; + } + + args++; + } + + // ensure the driver is installed + + if (driver_state == VFD_NOT_INSTALLED) { + PrintMessage(MSG_NOT_INSTALLED); + return VFD_NG; + } + + // ensure the driver is stopped + + if (driver_state == SERVICE_RUNNING) { + + // Try to stop with the same command line option (/F or /Q) + + while (Stop(stop_params) != VFD_OK) { + + // stop failed + + if (mode == OPERATION_FORCE) { + PrintMessage(MSG_REMOVE_FORCE); + break; + } + else if (mode == OPERATION_QUIT) { + PrintMessage(MSG_REMOVE_QUIT); + return VFD_NG; + } + else { + int c; + + PrintMessage(MSG_REMOVE_WARN); + + c = InputChar(MSG_RETRY_FORCE_CANCEL, "rfc"); + + if (c == 'f') { // force + break; + } + else if (c == 'c') { // cancel + return VFD_NG; + } + } + } + } + + // remove the driver + + ret = VfdRemoveDriver(); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_REMOVE_NG); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + // Wait for the driver to be actually removed for 3 secs Max. + + for (idx = 0; idx < 10; idx++) { + + ret = VfdGetDriverState(&driver_state); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_GET_STAT_NG); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + if (driver_state == VFD_NOT_INSTALLED) { + break; + } + + Sleep(300); + } + + if (driver_state != VFD_NOT_INSTALLED) { + PrintMessage(MSG_REMOVE_PENDING); + return VFD_NG; + } + + // operation successful + + PrintMessage(MSG_REMOVE_OK); + + return VFD_OK; +} + +// +// Configure the Virtual Floppy Driver +// Command Line Parameters: +// /auto, /manual +// +int Config(const char **args) +{ + DWORD start_type = SERVICE_DISABLED; + DWORD ret; + + while (args && *args) { + if (!_stricmp(*args, "/a") || + !_stricmp(*args, "/auto")) { + + if (start_type != SERVICE_DISABLED) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + start_type = SERVICE_AUTO_START; + } + else if (!_stricmp(*args, "/m") || + !_stricmp(*args, "/manual")) { + + if (start_type != SERVICE_DISABLED) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + start_type = SERVICE_DEMAND_START; + } + else { + PrintMessage(MSG_UNKNOWN_OPTION, *args); + PrintMessage(MSG_HINT_CONFIG, help_progname); + return VFD_NG; + } + + args++; + } + + if (start_type == SERVICE_DISABLED) { + // no parameter is specified + PrintMessage(MSG_HINT_CONFIG, help_progname); + return VFD_NG; + } + + // ensure that the driver is installed + + if (driver_state == VFD_NOT_INSTALLED) { + PrintMessage(MSG_NOT_INSTALLED); + return VFD_NG; + } + + // ensure that the driver is up to date + + if (CheckDriver() != VFD_OK) { + return VFD_NG; + } + + // configure the driver + + ret = VfdConfigDriver(start_type); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_CONFIG_NG); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + // operation successfull + + PrintMessage(MSG_CONFIG_OK); + + return VFD_OK; +} + +// +// Start the Virtual Floppy Driver +// Command Line Parameters: None +// +int Start(const char **args) +{ + DWORD ret; + + UNREFERENCED_PARAMETER(args); + + // ensure that the driver is installed + + if (driver_state == VFD_NOT_INSTALLED && + Install(NULL) != VFD_OK) { + return VFD_NG; + } + + // ensure that the driver is up to date + + if (CheckDriver() != VFD_OK) { + return VFD_NG; + } + + // ensure that the driver is not running + + if (driver_state == SERVICE_RUNNING) { + PrintMessage(MSG_ALREADY_RUNNING); + return VFD_NG; + } + + // start the driver + + ret = VfdStartDriver(&driver_state); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_START_NG); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + // operation successfull + + PrintMessage(MSG_START_OK); + + return VFD_OK; +} + +// +// Stop the Virtual Floppy Driver +// Command Line Parameters: +// /FORCE | /F Forces the operation on error +// /QUIT | /Q Quits the operation on error +// +int Stop(const char **args) +{ + int mode = OPERATION_ASK; + const char *close_params[] = { "*", NULL, NULL }; + DWORD ret; + + while (args && *args) { + if (!_stricmp(*args, "/f") || + !_stricmp(*args, "/force")) { + + if (mode != OPERATION_ASK) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + mode = OPERATION_FORCE; + + // parameter to pass to the Close() function + close_params[1] = *args; + } + else if (!_stricmp(*args, "/q") || + !_stricmp(*args, "/quit")) { + + if (mode != OPERATION_ASK) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + mode = OPERATION_QUIT; + + // parameter to pass to the Close() function + close_params[1] = *args; + } + else { + PrintMessage(MSG_UNKNOWN_OPTION, *args); + PrintMessage(MSG_HINT_STOP, help_progname); + return VFD_NG; + } + + args++; + } + + // ensure that the driver is installed + + if (driver_state == VFD_NOT_INSTALLED) { + PrintMessage(MSG_NOT_INSTALLED); + return VFD_NG; + } + + // ensure that the driver is running + + if (driver_state == SERVICE_STOPPED) { + PrintMessage(MSG_NOT_STARTED); + return VFD_NG; + } + + // ensure that all drives are empty + + if (driver_state == SERVICE_RUNNING) { + + // Try to close drives with the same operation mode (/F or /Q) + + while (Close(close_params) != VFD_OK) { + + // close failed + + if (mode == OPERATION_FORCE) { + PrintMessage(MSG_STOP_FORCE); + break; + } + else if (mode == OPERATION_QUIT) { + PrintMessage(MSG_STOP_QUIT); + return VFD_NG; + } + else { + int c; + + PrintMessage(MSG_STOP_WARN); + + c = InputChar(MSG_RETRY_FORCE_CANCEL, "rfc"); + + if (c == 'f') { // force + break; + } + else if (c == 'c') { // cancel + return VFD_NG; + } + } + } + } + + // stop the driver + + ret = VfdStopDriver(&driver_state); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_STOP_NG); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + if (driver_state != SERVICE_STOPPED) { + PrintMessage(MSG_STOP_PENDING); + return VFD_NG; + } + + // operation successful + + PrintMessage(MSG_STOP_OK); + + return VFD_OK; +} + +// +// Enable / Disable the shell extension +// Command Line Parameters: +// (optional) /ON or /OFF +// +int Shell(const char **args) +{ + DWORD ret; + + ret = VfdCheckHandlers(); + + if (ret != ERROR_SUCCESS && + ret != ERROR_PATH_NOT_FOUND && + ret != ERROR_FILE_NOT_FOUND) { + PrintMessage(MSG_GET_SHELLEXT_NG); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + if (args && *args) { + if (_stricmp(*args, "/on") == 0) { + if (ret != ERROR_SUCCESS) { + ret = VfdRegisterHandlers(); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_SET_SHELLEXT_NG); + printf("%s", SystemError(ret)); + return VFD_NG; + } + } + } + else if (_stricmp(*args, "/off") == 0) { + if (ret == ERROR_SUCCESS) { + ret = VfdUnregisterHandlers(); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_SET_SHELLEXT_NG); + printf("%s", SystemError(ret)); + return VFD_NG; + } + } + } + else { + PrintMessage(MSG_UNKNOWN_OPTION, *args); + PrintMessage(MSG_HINT_SHELL, help_progname); + return VFD_NG; + } + + ret = VfdCheckHandlers(); + } + + if (ret == ERROR_PATH_NOT_FOUND || + ret == ERROR_FILE_NOT_FOUND) { + PrintMessage(MSG_SHELLEXT_DISABLED); + } + else if (ret == ERROR_SUCCESS) { + PrintMessage(MSG_SHELLEXT_ENABLED); + } + else { + PrintMessage(MSG_GET_SHELLEXT_NG); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + return VFD_OK; +} + +// +// Open an image file to a Virtual Floppy Drive +// Command Line Parameters: +// [drive:] [file] [/NEW] [/RAM] [/P | /W] +// [/size] [/media] [/F | /FORCE | /Q | /QUIT] + +int Open(const char **args) +{ + int mode = OPERATION_ASK; + BOOL create = FALSE; + ULONG target = TARGET_NONE; + PCSTR file_name = NULL; + VFD_DISKTYPE disk_type = VFD_DISKTYPE_FILE; + CHAR protect = '\0'; + VFD_MEDIA media_type = VFD_MEDIA_NONE; + BOOL five_inch = FALSE; + VFD_FLAGS media_flags = 0; + HANDLE hDevice; + CHAR letter; + DWORD ret; + + // process parameters + + while (args && *args) { + + if (!_stricmp(*args, "/f") || + !_stricmp(*args, "/force")) { + + if (mode != OPERATION_ASK) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + mode = OPERATION_FORCE; + } + else if (!_stricmp(*args, "/q") || + !_stricmp(*args, "/quit")) { + + if (mode != OPERATION_ASK) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + mode = OPERATION_QUIT; + } + + else if (!_stricmp(*args, "/new")) { + + if (create) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + create = TRUE; + } + + // Disk type options + + else if (_stricmp(*args, "/ram") == 0) { + + if (disk_type != VFD_DISKTYPE_FILE) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + disk_type = VFD_DISKTYPE_RAM; + } + + // Protect options + else if (_stricmp(*args, "/p") == 0 || + _stricmp(*args, "/w") == 0) { + + if (protect) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + protect = (CHAR)toupper(*(*args + 1)); + } + + // media size options + + else if (strcmp(*args, "/160") == 0) { + if (media_type) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + media_type = VFD_MEDIA_F5_160; + } + else if (strcmp(*args, "/180") == 0) { + if (media_type) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + media_type = VFD_MEDIA_F5_180; + } + else if (strcmp(*args, "/320") == 0) { + if (media_type) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + media_type = VFD_MEDIA_F5_320; + } + else if (strcmp(*args, "/360") == 0) { + if (media_type) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + media_type = VFD_MEDIA_F5_360; + } + else if (strcmp(*args, "/640") == 0) { + if (media_type) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + media_type = VFD_MEDIA_F3_640; + } + else if (strcmp(*args, "/720") == 0) { + if (media_type) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + media_type = VFD_MEDIA_F3_720; + } + else if (strcmp(*args, "/820") == 0) { + if (media_type) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + media_type = VFD_MEDIA_F3_820; + } + else if (strcmp(*args, "/120") == 0 || + strcmp(*args, "/1.20") == 0) { + if (media_type) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + media_type = VFD_MEDIA_F3_1P2; + } + else if (strcmp(*args, "/144") == 0 || + strcmp(*args, "/1.44") == 0) { + if (media_type) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + media_type = VFD_MEDIA_F3_1P4; + } + else if (strcmp(*args, "/168") == 0 || + strcmp(*args, "/1.68") == 0) { + if (media_type) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + media_type = VFD_MEDIA_F3_1P6; + } + else if (strcmp(*args, "/172") == 0 || + strcmp(*args, "/1.72") == 0) { + if (media_type) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + media_type = VFD_MEDIA_F3_1P7; + } + else if (strcmp(*args, "/288") == 0 || + strcmp(*args, "/2.88") == 0) { + if (media_type) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + media_type = VFD_MEDIA_F3_2P8; + } + + // 5.25 inch media + + else if (strcmp(*args, "/5") == 0 || + strcmp(*args, "/525") == 0 || + strcmp(*args, "/5.25") == 0) { + + if (five_inch) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + five_inch = TRUE; + } + + // target option + + else if (isalnum(**args) && + *(*args + 1) == ':' && + *(*args + 2) == '\0') { + + if (target != TARGET_NONE) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + target = toupper(**args); + } + + // filename + + else if (**args != '/') { + if (file_name) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + file_name = *args; + } + else { + PrintMessage(MSG_UNKNOWN_OPTION, *args); + PrintMessage(MSG_HINT_OPEN, help_progname); + return VFD_NG; + } + + args++; + } + + if (target == TARGET_NONE) { + // default target + target = '0'; + PrintMessage(MSG_TARGET_NOTICE, target); + } + + // check target file + + if (file_name) { + DWORD file_attr; + VFD_FILETYPE file_type; + ULONG image_size; + BOOL overwrite = FALSE; + + ret = VfdCheckImageFile( + file_name, &file_attr, &file_type, &image_size); + + if (ret == ERROR_FILE_NOT_FOUND) { + + // the target file does not exist + + if (!create) { // create option not specified + + if (mode == OPERATION_FORCE) { + PrintMessage(MSG_CREATE_NOTICE); + } + else { + printf("%s", SystemError(ret)); + + if (mode == OPERATION_QUIT || + InputChar(MSG_CREATE_CONFIRM, "yn") == 'n') { + return VFD_NG; + } + } + + create = TRUE; + } + } + else if (ret == ERROR_SUCCESS) { + + // the target file exists + + if (create) { // create option is specified + + if (mode == OPERATION_FORCE) { + PrintMessage(MSG_OVERWRITE_NOTICE); + } + else { + printf("%s", SystemError(ERROR_FILE_EXISTS)); + + if (mode == OPERATION_QUIT || + InputChar(MSG_OVERWRITE_CONFIRM, "yn") == 'n') { + return VFD_NG; + } + } + + overwrite = TRUE; + } + } + else { + PrintMessage(MSG_OPEN_NG, file_name); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + // + // create or overwrite the target file + // + + if (create) { + + if (media_type == VFD_MEDIA_NONE) { + + if (mode == OPERATION_FORCE) { + PrintMessage(MSG_CREATE144_NOTICE); + } + else { + PrintMessage(MSG_FILE_MEDIA_UNKNOWN); + + if (mode == OPERATION_QUIT || + InputChar(MSG_CREATE144_CONFIRM, "yn") == 'n') { + return VFD_NG; + } + } + + media_type = VFD_MEDIA_F3_1P4; + } + + ret = VfdCreateImageFile( + file_name, media_type, VFD_FILETYPE_RAW, overwrite); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_CREATE_NG, file_name); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + PrintMessage(MSG_FILE_CREATED); + + ret = VfdCheckImageFile( + file_name, &file_attr, &file_type, &image_size); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_OPEN_NG, file_name); + printf("%s", SystemError(ret)); + return VFD_NG; + } + } + else { + // + // use the existing target file + // check image size and the media type + // + + VFD_MEDIA def_media; // default media for image size + ULONG media_size; // specified media size + + media_size = VfdGetMediaSize(media_type); + + if (media_size > image_size) { + + // specified media is too large for the image + + PrintMessage(MSG_IMAGE_TOO_SMALL); + return VFD_NG; + } + + def_media = VfdLookupMedia(image_size); + + if (def_media == VFD_MEDIA_NONE) { + + // image is too small for the smallest media + + PrintMessage(MSG_IMAGE_TOO_SMALL); + return VFD_NG; + } + + if (media_type == VFD_MEDIA_NONE) { + + // media type is not specified + + ULONG def_size = VfdGetMediaSize(def_media); + + if (def_size != image_size) { + + // image size does not match the largest media size + + PrintMessage(MSG_NO_MATCHING_MEDIA, image_size); + + if (mode == OPERATION_FORCE) { + PrintMessage(MSG_MEDIATYPE_NOTICE, + VfdMediaTypeName(def_media), def_size); + } + else if (mode == OPERATION_QUIT) { + return VFD_NG; + } + else { + PrintMessage(MSG_MEDIATYPE_SUGGEST, + VfdMediaTypeName(def_media), def_size); + + if (InputChar(MSG_MEDIATYPE_CONFIRM, "yn") == 'n') { + return VFD_NG; + } + } + } + + media_type = def_media; + } + } + + // check file attributes against the disk type + + if (file_type == VFD_FILETYPE_ZIP || + (file_attr & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_ENCRYPTED))) { + + if (disk_type != VFD_DISKTYPE_RAM) { + + if (mode == OPERATION_FORCE) { + PrintMessage(MSG_RAM_MODE_NOTICE); + } + else { + PrintMessage(MSG_RAM_MODE_ONLY); + + if (mode == OPERATION_QUIT || + InputChar(MSG_RAM_MODE_CONFIRM, "yn") == 'n') { + return VFD_NG; + } + } + + disk_type = VFD_DISKTYPE_RAM; + } + } + + if (disk_type != VFD_DISKTYPE_FILE) { + if (!protect) { + PrintMessage(MSG_DEFAULT_PROTECT); + protect = 'P'; + } + } + } + else { + // + // pure RAM disk + // + disk_type = VFD_DISKTYPE_RAM; + + if (media_type == VFD_MEDIA_NONE) { + + if (mode == OPERATION_FORCE) { + PrintMessage(MSG_CREATE144_NOTICE); + } + else { + PrintMessage(MSG_RAM_MEDIA_UNKNOWN); + + if (mode == OPERATION_QUIT || + InputChar(MSG_CREATE144_CONFIRM, "yn") == 'n') { + return VFD_NG; + } + } + + media_type = VFD_MEDIA_F3_1P4; + } + } + + if (protect == 'P') { + media_flags |= VFD_FLAG_WRITE_PROTECTED; + } + + if (five_inch && + VfdGetMediaSize(media_type) == + VfdGetMediaSize((VFD_MEDIA)(media_type + 1))) { + media_type = (VFD_MEDIA)(media_type + 1); + } + + // ensure that the driver is installed + + if (driver_state == VFD_NOT_INSTALLED && + Install(NULL) != VFD_OK) { + return VFD_NG; + } + + // ensure that the driver is up to date + + if (CheckDriver() != VFD_OK) { + return VFD_NG; + } + + // ensure that the driver is running + + if (driver_state != SERVICE_RUNNING && + Start(NULL) != VFD_OK) { + return VFD_NG; + } + + // Open the target device + + hDevice = VfdOpenDevice(target); + + if (hDevice == INVALID_HANDLE_VALUE) { + ret = GetLastError(); + PrintMessage(MSG_ACCESS_NG, target); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + // Ensure that the drive is empty + + ret = VfdGetMediaState(hDevice); + + if (ret != ERROR_NOT_READY) { + if (ret == ERROR_SUCCESS || + ret == ERROR_WRITE_PROTECT) { + PrintMessage(MSG_DRIVE_BUSY); + } + else { + PrintMessage(MSG_GET_MEDIA_NG); + printf("%s", SystemError(ret)); + } + + CloseHandle(hDevice); + return VFD_NG; + } + + // Open the image file + + ret = VfdOpenImage(hDevice, file_name, + disk_type, media_type, media_flags); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_OPEN_NG, file_name ? file_name : ""); + printf("%s", SystemError(ret)); + + CloseHandle(hDevice); + return VFD_NG; + } + + // assign a drive letter if the drive has none + + VfdGetGlobalLink(hDevice, &letter); + + if (!isalpha(letter)) { + VfdGetLocalLink(hDevice, &letter); + } + + if (!isalpha(letter)) { + VfdSetLocalLink(hDevice, VfdChooseLetter()); + } + + // Get the actually opened image information. + + PrintImageInfo(hDevice); + + CloseHandle(hDevice); + + return VFD_OK; +} + +// +// Close the current virtual floppy image +// Command Line Parameters: +// drive number or drive letter +// /F | /FORCE | /Q | /QUIT +// +int Close(const char **args) +{ + ULONG mode = OPERATION_ASK; + + ULONG target_min = TARGET_NONE; + ULONG target_max = TARGET_NONE; + HANDLE hDevice; + + VFD_MEDIA media_type; + VFD_FLAGS media_flags; + + DWORD ret; + + // check parameterS + + while (args && *args) { + + if (!_stricmp(*args, "/f") || + !_stricmp(*args, "/force")) { + + if (mode != OPERATION_ASK) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + mode = OPERATION_FORCE; + } + else if (!_stricmp(*args, "/q") || + !_stricmp(*args, "/quit")) { + + if (mode != OPERATION_ASK) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + mode = OPERATION_QUIT; + } + else if ((isalnum(**args) || **args == '*') && + (*(*args + 1) == ':' || *(*args + 1) == '\0')) { + + if (target_min != TARGET_NONE) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + if (**args == '*') { + target_min = '0'; + target_max = '0' + VFD_MAXIMUM_DEVICES; + } + else { + target_min = toupper(**args); + target_max = target_min + 1; + } + } + else { + PrintMessage(MSG_UNKNOWN_OPTION, *args); + PrintMessage(MSG_HINT_CLOSE, help_progname); + return VFD_NG; + } + + args++; + } + + if (target_min == TARGET_NONE) { + // default target = drive 0 + target_min = '0'; + target_max = '1'; + PrintMessage(MSG_TARGET_NOTICE, target_min); + } + + // ensure that the driver is installed + + if (driver_state == VFD_NOT_INSTALLED) { + PrintMessage(MSG_NOT_INSTALLED); + return VFD_NG; + } + + // ensure that the driver is running + + if (driver_state != SERVICE_RUNNING) { + PrintMessage(MSG_NOT_STARTED); + return VFD_NG; + } + + // Close the drive(s) + + while (target_min < target_max) { + + // open the target device + + hDevice = VfdOpenDevice(target_min); + + if (hDevice == INVALID_HANDLE_VALUE) { + ret = GetLastError(); + + PrintMessage(MSG_ACCESS_NG, target_min); + printf("%s", SystemError(ret)); + + if (mode != OPERATION_FORCE) { + return VFD_NG; + } + + target_min++; + continue; + } + + // get the current image information + + ret = VfdGetImageInfo(hDevice, NULL, NULL, + &media_type, &media_flags, NULL, NULL); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_ACCESS_NG, target_min); + printf("%s", SystemError(ret)); + + CloseHandle(hDevice); + + if (mode != OPERATION_FORCE) { + return VFD_NG; + } + + target_min++; + continue; + } + + if (media_type == VFD_MEDIA_NONE) { + + // drive is empty + + CloseHandle(hDevice); + target_min++; + continue; + } + + if (media_flags & VFD_FLAG_DATA_MODIFIED) { + + // RAM disk data is modified + + PrintMessage(MSG_MEDIA_MODIFIED, target_min); + + if (mode == OPERATION_FORCE) { + PrintMessage(MSG_CLOSE_FORCE); + } + else if (mode == OPERATION_QUIT) { + PrintMessage(MSG_CLOSE_QUIT); + CloseHandle(hDevice); + return VFD_NG; + } + else { + if (InputChar(MSG_CLOSE_CONFIRM, "yn") == 'n') { + CloseHandle(hDevice); + return VFD_NG; + } + } + } + +retry: + ret = VfdCloseImage( + hDevice, (mode == OPERATION_FORCE)); + + if (ret == ERROR_ACCESS_DENIED) { + + PrintMessage(MSG_LOCK_NG, target_min); + + if (mode == OPERATION_QUIT) { + CloseHandle(hDevice); + return VFD_NG; + } + else if (mode == OPERATION_ASK) { + + int c; + + if (IS_WINDOWS_NT()) { + c = InputChar(MSG_RETRY_CANCEL, "rc"); + } + else { + c = InputChar(MSG_RETRY_FORCE_CANCEL, "rfc"); + } + + if (c == 'f') { // force + ret = VfdCloseImage(hDevice, TRUE); + } + else if (c == 'c') { // cancel + CloseHandle(hDevice); + return VFD_NG; + } + else { + goto retry; + } + } + } + + CloseHandle(hDevice); + + if (ret == ERROR_SUCCESS) { + PrintMessage(MSG_CLOSE_OK, target_min); + } + else if (ret != ERROR_NOT_READY) { + PrintMessage(MSG_CLOSE_NG, target_min); + printf("%s", SystemError(ret)); + + if (mode != OPERATION_FORCE) { + return VFD_NG; + } + } + + target_min++; + } + + return VFD_OK; +} + +// +// Save the current image into a file +// +int Save(const char **args) +{ + int mode = OPERATION_ASK; + ULONG target = TARGET_NONE; + CHAR file_name[MAX_PATH] = {0}; + BOOL overwrite = FALSE; + BOOL truncate = FALSE; + + HANDLE hDevice; + CHAR current[MAX_PATH] = {0}; + VFD_MEDIA media_type; + VFD_FLAGS media_flags; + VFD_FILETYPE file_type; + DWORD file_attr; + ULONG image_size; + DWORD ret; + + // check parameters + + while (args && *args) { + + if (!_stricmp(*args, "/f") || + !_stricmp(*args, "/force")) { + + if (mode != OPERATION_ASK) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + mode = OPERATION_FORCE; + } + else if (!_stricmp(*args, "/q") || + !_stricmp(*args, "/quit")) { + + if (mode != OPERATION_ASK) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + mode = OPERATION_QUIT; + } + else if (!_stricmp(*args, "/o") || + !_stricmp(*args, "/over")) { + + if (truncate || overwrite) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + overwrite = TRUE; + } + else if (!_stricmp(*args, "/t") || + !_stricmp(*args, "/trunc")) { + + if (truncate || overwrite) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + truncate = TRUE; + } + else if (isalnum(**args) && + *(*args + 1) == ':' && + *(*args + 2) == '\0') { + + if (target != TARGET_NONE) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + target = toupper(**args); + } + else if (**args == '/') { + PrintMessage(MSG_UNKNOWN_OPTION, *args); + PrintMessage(MSG_HINT_SAVE, help_progname); + return VFD_NG; + } + else { + strcpy(file_name, *args); + } + + args++; + } + + if (target == TARGET_NONE) { + target = '0'; + PrintMessage(MSG_TARGET_NOTICE, target); + } + + // ensure that the driver is installed + + if (driver_state == VFD_NOT_INSTALLED) { + PrintMessage(MSG_NOT_INSTALLED); + return VFD_NG; + } + + // ensure that the driver is up to date + + if (CheckDriver() != VFD_OK) { + return VFD_NG; + } + + // ensure that the driver is running + + if (driver_state != SERVICE_RUNNING) { + PrintMessage(MSG_NOT_STARTED); + return VFD_NG; + } + + // Open the target device + + hDevice = VfdOpenDevice(target); + + if (hDevice == INVALID_HANDLE_VALUE) { + ret = GetLastError(); + PrintMessage(MSG_ACCESS_NG, target); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + // Get the current image info + + ret = VfdGetImageInfo(hDevice, current, NULL, + &media_type, &media_flags, NULL, NULL); + + if (ret != ERROR_SUCCESS) { + printf("%s", SystemError(ret)); + CloseHandle(hDevice); + return VFD_NG; + } + + if (media_type == VFD_MEDIA_NONE) { + printf("%s", SystemError(ERROR_NOT_READY)); + CloseHandle(hDevice); + return VFD_NG; + } + + if (file_name[0] == '\0') { + + if (current[0] == '\0') { + + PrintMessage(MSG_TARGET_REQUIRED); + CloseHandle(hDevice); + + return VFD_NG; + } + + strcpy(file_name, current); + } + + if (!_stricmp(file_name, current)) { + + // target is the current image file + + if (!(media_flags & VFD_FLAG_DATA_MODIFIED)) { + + // FILE disk (always up to date) or RAM disk is not modified + + PrintMessage(MSG_TARGET_UP_TO_DATE); + CloseHandle(hDevice); + + return VFD_OK; + } + + overwrite = TRUE; + } + + // check target file + + ret = VfdCheckImageFile(file_name, + &file_attr, &file_type, &image_size); + + if (ret == ERROR_SUCCESS) { + + if (!overwrite && !truncate) { + + if (mode == OPERATION_FORCE) { + PrintMessage(MSG_OVERWRITE_NOTICE); + overwrite = TRUE; + } + else if (mode == OPERATION_QUIT) { + printf("%s", SystemError(ERROR_FILE_EXISTS)); + CloseHandle(hDevice); + + return VFD_NG; + } + else { + int c; + + printf("%s", SystemError(ERROR_FILE_EXISTS)); + + c = InputChar(MSG_OVERWRITE_PROMPT, "otc"); + + if (c == 'o') { + overwrite = TRUE; + } + else if (c == 't') { + truncate = TRUE; + } + else { + CloseHandle(hDevice); + return VFD_NG; + } + } + } + } + else if (ret != ERROR_FILE_NOT_FOUND) { + + printf("%s", SystemError(ret)); + CloseHandle(hDevice); + + return VFD_NG; + } + + if (file_type == VFD_FILETYPE_ZIP) { + + // Cannot update a zip file + + PrintMessage(MSG_TARGET_IS_ZIP); + CloseHandle(hDevice); + + return VFD_NG; + } + +retry: + ret = VfdDismountVolume( + hDevice, (mode == OPERATION_FORCE)); + + if (ret == ERROR_ACCESS_DENIED) { + + PrintMessage(MSG_LOCK_NG, target); + + if (mode == OPERATION_FORCE) { + PrintMessage(MSG_SAVE_FORCE); + } + else if (mode == OPERATION_QUIT) { + PrintMessage(MSG_SAVE_QUIT); + CloseHandle(hDevice); + return VFD_NG; + } + else { + int c = InputChar(MSG_RETRY_FORCE_CANCEL, "rfc"); + + if (c == 'r') { // retry + goto retry; + } + else if (c == 'f') { // force + VfdDismountVolume(hDevice, TRUE); + } + else { // cancel + CloseHandle(hDevice); + return VFD_NG; + } + } + } + else if (ret != ERROR_SUCCESS) { + printf("%s", SystemError(ret)); + CloseHandle(hDevice); + return VFD_NG; + } + + ret = VfdSaveImage(hDevice, file_name, + (overwrite || truncate), truncate); + + CloseHandle(hDevice); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_SAVE_NG, target, file_name); + printf("%s", SystemError(ret)); + + return VFD_NG; + } + + PrintMessage(MSG_SAVE_OK, target, file_name); + + return VFD_OK; +} + +// +// Enable/disable virtual media write protection +// +int Protect(const char **args) +{ +#define PROTECT_NONE 0 +#define PROTECT_ON 1 +#define PROTECT_OFF 2 + ULONG protect = PROTECT_NONE; + ULONG target = TARGET_NONE; + HANDLE hDevice; + DWORD ret; + + // check parameters + + while (args && *args) { + + // Disk type options + + if (_stricmp(*args, "/on") == 0) { + + if (protect) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + protect = PROTECT_ON; + } + else if (_stricmp(*args, "/off") == 0) { + + if (protect) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + protect = PROTECT_OFF; + } + else if (isalnum(**args)) { + + if (target != TARGET_NONE) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + target = toupper(**args); + } + else { + PrintMessage(MSG_UNKNOWN_OPTION, *args); + PrintMessage(MSG_HINT_PROTECT, help_progname); + return VFD_NG; + } + + args++; + } + + if (target == TARGET_NONE) { + target = '0'; + PrintMessage(MSG_TARGET_NOTICE, target); + } + + // ensure that the driver is installed + + if (driver_state == VFD_NOT_INSTALLED) { + PrintMessage(MSG_NOT_INSTALLED); + return VFD_NG; + } + + // ensure that the driver is up to date + + if (CheckDriver() != VFD_OK) { + return VFD_NG; + } + + // ensure that the driver is running + + if (driver_state != SERVICE_RUNNING) { + PrintMessage(MSG_NOT_STARTED); + return VFD_NG; + } + + // open the target drive + + hDevice = VfdOpenDevice(target); + + if (hDevice == INVALID_HANDLE_VALUE) { + ret = GetLastError(); + PrintMessage(MSG_ACCESS_NG, target); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + if (protect) { + // change protect state + + ret = VfdWriteProtect( + hDevice, (protect == PROTECT_ON)); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_PROTECT_NG, target); + printf("%s", SystemError(ret)); + + CloseHandle(hDevice); + return VFD_NG; + } + } + + // get the current protect state + + ret = VfdGetMediaState(hDevice); + + CloseHandle(hDevice); + + if (ret == ERROR_SUCCESS) { + PrintMessage(MSG_MEDIA_WRITABLE); + } + else if (ret == ERROR_WRITE_PROTECT) { + PrintMessage(MSG_MEDIA_PROTECTED); + } + else { + PrintMessage(MSG_GET_MEDIA_NG); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + return VFD_OK; +} + +// +// Format the virtual media with FAT12 +// +int Format(const char **args) +{ + int mode = OPERATION_ASK; + ULONG target = TARGET_NONE; + HANDLE hDevice; + DWORD ret; + + // check parameters + + while (args && *args) { + + if (!_stricmp(*args, "/f") || + !_stricmp(*args, "/force")) { + + if (mode != OPERATION_ASK) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + mode = OPERATION_FORCE; + } + else if (!_stricmp(*args, "/q") || + !_stricmp(*args, "/quit")) { + + if (mode != OPERATION_ASK) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + mode = OPERATION_QUIT; + } + else if (isalnum(**args)) { + if (target != TARGET_NONE) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + target = toupper(**args); + } + else { + PrintMessage(MSG_UNKNOWN_OPTION, *args); + PrintMessage(MSG_HINT_FORMAT, help_progname); + return VFD_NG; + } + + args++; + } + + if (target == TARGET_NONE) { + target = '0'; + PrintMessage(MSG_TARGET_NOTICE, target); + } + + // ensure that the driver is installed + + if (driver_state == VFD_NOT_INSTALLED) { + PrintMessage(MSG_NOT_INSTALLED); + return VFD_NG; + } + + // ensure that the driver is up to date + + if (CheckDriver() != VFD_OK) { + return VFD_NG; + } + + // ensure that the driver is running + + if (driver_state != SERVICE_RUNNING) { + PrintMessage(MSG_NOT_STARTED); + return VFD_NG; + } + + // Open the device + + hDevice = VfdOpenDevice(target); + + if (hDevice == INVALID_HANDLE_VALUE) { + ret = GetLastError(); + PrintMessage(MSG_ACCESS_NG, target); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + // check if the media is writable + + ret = VfdGetMediaState(hDevice); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_FORMAT_NG, target); + printf("%s", SystemError(ret)); + + CloseHandle(hDevice); + return VFD_NG; + } + + // format the media + +retry: + ret = VfdDismountVolume( + hDevice, (mode == OPERATION_FORCE)); + + if (ret == ERROR_ACCESS_DENIED) { + + PrintMessage(MSG_LOCK_NG, target); + + if (mode == OPERATION_FORCE) { + PrintMessage(MSG_FORMAT_FORCE); + } + else if (mode == OPERATION_QUIT) { + PrintMessage(MSG_FORMAT_QUIT); + CloseHandle(hDevice); + return VFD_NG; + } + else { + int c = InputChar(MSG_RETRY_FORCE_CANCEL, "rfc"); + + if (c == 'r') { // retry + goto retry; + } + else if (c == 'f') { // force + VfdDismountVolume(hDevice, TRUE); + } + else { // cancel + CloseHandle(hDevice); + return VFD_NG; + } + } + } + else if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_LOCK_NG, target); + CloseHandle(hDevice); + return VFD_NG; + } + + ret = VfdFormatMedia(hDevice); + + CloseHandle(hDevice); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_FORMAT_NG, target); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + // successful operation + + PrintMessage(MSG_FORMAT_OK); + + return VFD_OK; +} + +// +// Assign a drive letter to a Virtual Floppy Drive +// +int Link(const char **args) +{ + ULONG target_min = TARGET_NONE; + ULONG target_max = TARGET_NONE; + PCSTR letters = NULL; + BOOL global = TRUE; + HANDLE hDevice; + DWORD ret; + + while (args && *args) { + if (!_stricmp(*args, "/g")) { + global = TRUE; + } + else if (!_stricmp(*args, "/l")) { + global = FALSE; + } + else if (isdigit(**args) || **args == '*') { + if (target_min != TARGET_NONE) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + if (**args == '*') { + target_min = '0'; + target_max = '0' + VFD_MAXIMUM_DEVICES; + } + else { + target_min = **args; + target_max = target_min + 1; + } + } + else if (isalpha(**args)) { + if (letters) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + letters = *args; + } + else { + PrintMessage(MSG_UNKNOWN_OPTION, *args); + PrintMessage(MSG_HINT_LINK, help_progname); + return VFD_NG; + } + + args++; + } + + if (target_min == TARGET_NONE) { + // default: drive 0 + target_min = '0'; + target_max = '1'; + PrintMessage(MSG_TARGET_NOTICE, target_min); + } + + // ensure that the driver is installed + + if (driver_state == VFD_NOT_INSTALLED) { + PrintMessage(MSG_NOT_INSTALLED); + return VFD_NG; + } + + // ensure that the driver is up to date + + if (CheckDriver() != VFD_OK) { + return VFD_NG; + } + + // ensure that the driver is running + + if (driver_state != SERVICE_RUNNING) { + PrintMessage(MSG_NOT_STARTED); + return VFD_NG; + } + + while (target_min < target_max) { + ULONG number; + CHAR letter; + + hDevice = VfdOpenDevice(target_min); + + if (hDevice == INVALID_HANDLE_VALUE) { + ret = GetLastError(); + PrintMessage(MSG_ACCESS_NG, target_min); + printf("%s", SystemError(ret)); + target_min++; + continue; + } + + ret = VfdGetDeviceNumber(hDevice, &number); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_ACCESS_NG, target_min); + printf("%s", SystemError(ret)); + CloseHandle(hDevice); + target_min++; + continue; + } + + if (letters && isalpha(*letters)) { + letter = (CHAR)toupper(*(letters++)); + } + else { + letter = VfdChooseLetter(); + } + + if (letter) { + if (global) { + ret = VfdSetGlobalLink(hDevice, letter); + } + else { + ret = VfdSetLocalLink(hDevice, letter); + } + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_LINK_NG, number, letter); + printf("%s", SystemError(ret)); + } + } + else { + PrintMessage(MSG_LINK_FULL); + } + + PrintDriveLetter(hDevice, number); + + CloseHandle(hDevice); + + target_min++; + } + + return VFD_OK; +} + +// +// Remove a drive letter from a Virtual Floppy Drive +// +int Unlink(const char **args) +{ + ULONG target_min = TARGET_NONE; + ULONG target_max = TARGET_NONE; + HANDLE hDevice; + DWORD ret; + + while (args && *args) { + if ((isalnum(**args) || **args == '*') && + (*(*args + 1) == ':' || *(*args + 1) == '\0')) { + + if (target_min != TARGET_NONE) { + PrintMessage(MSG_DUPLICATE_ARGS, *args); + return VFD_NG; + } + + if (**args == '*') { + target_min = '0'; + target_max = '0' + VFD_MAXIMUM_DEVICES; + } + else { + target_min = **args; + target_max = target_min + 1; + } + } + else { + PrintMessage(MSG_UNKNOWN_OPTION, *args); + PrintMessage(MSG_HINT_ULINK, help_progname); + return VFD_NG; + } + + args++; + } + + if (target_min == TARGET_NONE) { + // default: drive 0 + target_min = '0'; + target_max = '1'; + PrintMessage(MSG_TARGET_NOTICE, target_min); + } + + // ensure that the driver is installed + + if (driver_state == VFD_NOT_INSTALLED) { + PrintMessage(MSG_NOT_INSTALLED); + return VFD_NG; + } + + // ensure that the driver is up to date + + if (CheckDriver() != VFD_OK) { + return VFD_NG; + } + + // ensure that the driver is running + + if (driver_state != SERVICE_RUNNING) { + PrintMessage(MSG_NOT_STARTED); + return VFD_NG; + } + + while (target_min < target_max) { + ULONG number; + + hDevice = VfdOpenDevice(target_min); + + if (hDevice == INVALID_HANDLE_VALUE) { + ret = GetLastError(); + PrintMessage(MSG_ACCESS_NG, target_min); + printf("%s", SystemError(ret)); + target_min++; + continue; + } + + ret = VfdGetDeviceNumber(hDevice, &number); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_ACCESS_NG, target_min); + printf("%s", SystemError(ret)); + CloseHandle(hDevice); + target_min++; + continue; + } + + VfdSetGlobalLink(hDevice, 0); + VfdSetLocalLink(hDevice, 0); + + PrintDriveLetter(hDevice, number); + + CloseHandle(hDevice); + + target_min++; + } + + return VFD_OK; +} + +// +// Print current driver state +// Command Line Parameters: None +// +int Status(const char **args) +{ + HANDLE hDevice; + TCHAR path[MAX_PATH]; + DWORD start_type; + DWORD version; + ULONG target; + DWORD ret; + + UNREFERENCED_PARAMETER(args); + + if (driver_state == VFD_NOT_INSTALLED) { + PrintMessage(MSG_NOT_INSTALLED); + } + else { + + // get current driver config + + ret = VfdGetDriverConfig(path, &start_type); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_GET_CONFIG_NG); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + // print driver file path + + PrintMessage(MSG_DRIVER_FILE, path); + + // print driver version + version = 0; + + if (driver_state == SERVICE_RUNNING) { + + hDevice = VfdOpenDevice(0); + + if (hDevice != INVALID_HANDLE_VALUE) { + ret = VfdGetDriverVersion(hDevice, &version); + + CloseHandle(hDevice); + } + + } + + if (version == 0) { + ret = VfdCheckDriverFile(path, &version); + } + + if (ret == ERROR_SUCCESS) { + PrintMessage(MSG_DRIVER_VERSION, + HIWORD(version) & 0x7fff, + LOWORD(version), + (version & 0x80000000) ? "(debug)" : ""); + } + else { + PrintMessage(MSG_GET_VERSION_NG); + printf("%s", SystemError(ret)); + } + + + // print driver start type + + PrintMessage(MSG_START_TYPE); + + switch (start_type) { + case SERVICE_AUTO_START: + PrintMessage(MSG_START_AUTO); + break; + + case SERVICE_BOOT_START: + PrintMessage(MSG_START_BOOT); + break; + + case SERVICE_DEMAND_START: + PrintMessage(MSG_START_DEMAND); + break; + + case SERVICE_DISABLED: + PrintMessage(MSG_START_DISABLED); + break; + + case SERVICE_SYSTEM_START : + PrintMessage(MSG_START_SYSTEM); + break; + + default: + PrintMessage(MSG_UNKNOWN_LONG, start_type); + break; + } + + // print current driver state + + PrintMessage(MSG_DRIVER_STATUS); + + switch (driver_state) { + case SERVICE_STOPPED: + PrintMessage(MSG_STATUS_STOPPED); + break; + + case SERVICE_START_PENDING: + PrintMessage(MSG_STATUS_START_P); + break; + + case SERVICE_STOP_PENDING: + PrintMessage(MSG_STATUS_STOP_P); + break; + + case SERVICE_RUNNING: + PrintMessage(MSG_STATUS_RUNNING); + break; + + case SERVICE_CONTINUE_PENDING: + PrintMessage(MSG_STATUS_CONT_P); + break; + + case SERVICE_PAUSE_PENDING: + PrintMessage(MSG_STATUS_PAUSE_P); + break; + + case SERVICE_PAUSED: + PrintMessage(MSG_STATUS_PAUSED); + break; + + default: + PrintMessage(MSG_UNKNOWN_LONG, driver_state); + break; + } + } + + // print shell extension status + + printf("\n"); + + if (VfdCheckHandlers() == ERROR_SUCCESS) { + PrintMessage(MSG_SHELLEXT_ENABLED); + } + else { + PrintMessage(MSG_SHELLEXT_DISABLED); + } + + // if driver is not running, no more info + + if (driver_state != SERVICE_RUNNING) { + return VFD_OK; + } + + // print image information + + for (target = 0; target < VFD_MAXIMUM_DEVICES; target++) { + HANDLE hDevice = VfdOpenDevice(target); + + if (hDevice == INVALID_HANDLE_VALUE) { + ret = GetLastError(); + PrintMessage(MSG_ACCESS_NG, target + '0'); + printf("%s", SystemError(ret)); + return VFD_NG; + } + + PrintImageInfo(hDevice); + + CloseHandle(hDevice); + } + + return VFD_OK; +} + +// +// Print usage help +// +int Help(const char **args) +{ + DWORD msg = MSG_HELP_GENERAL; + char *buf = NULL; + + if (args && *args) { + int cmd = ParseHelpTopic(*args); + + if (cmd < 0) { + msg = MSG_HELP_HELP; + } + else { + msg = HelpMsg[cmd].help; + } + } + + FormatMessage( + FORMAT_MESSAGE_FROM_HMODULE | + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_ARGUMENT_ARRAY, + NULL, msg, 0, (LPTSTR)&buf, 0, + (va_list *)&help_progname); + + if (buf == NULL) { + printf("%s", SystemError(GetLastError())); + return VFD_NG; + } + + ConsolePager(buf, TRUE); + LocalFree(buf); + + return VFD_OK; +} + +// +// Print version information +// +int Version(const char **args) +{ + UNREFERENCED_PARAMETER(args); + + printf(VFD_PRODUCT_DESC "\n" VFD_COPYRIGHT_STR "\n" + "http://chitchat.at.infoseek.co.jp/vmware/vfd.html\n"); + + return VFD_OK; +} + +// +// Parse command parameter +// +int ParseCommand(const char *cmd) +{ +#define CMD_MATCH_NONE -1 +#define CMD_MATCH_MULTI -2 + + size_t len; + int idx; + int match; + + // skip a leading '/' + + if (*cmd == '/') { + cmd++; + } + + if (*cmd == '\0') { + + // empty command + + return CMD_MATCH_NONE; + } + + // find a match + len = strlen(cmd); + idx = 0; + match = CMD_MATCH_NONE; + + while (Commands[idx].cmd) { + + if (strlen(Commands[idx].cmd) >= len && + !_strnicmp(cmd, Commands[idx].cmd, len)) { + + if (match == CMD_MATCH_NONE) { // first match + match = idx; + } + else { // multiple matches + if (match != CMD_MATCH_MULTI) { // first time + PrintMessage(MSG_AMBIGUOUS_COMMAND, cmd); + printf("> %s ", Commands[match].cmd); + match = CMD_MATCH_MULTI; + } + + printf("%s ", Commands[idx].cmd); + } + } + + idx++; + } + + if (match == CMD_MATCH_NONE) { // match not found + PrintMessage(MSG_UNKNOWN_COMMAND, cmd); + } + else if (match == CMD_MATCH_MULTI) { // multiple matches + printf("\n"); + } + + return match; +} + +int ParseHelpTopic(const char *topic) +{ + size_t len; + int idx; + int match; + + if (*topic == '\0') { + + // empty command + + return CMD_MATCH_NONE; + } + + // find a match + len = strlen(topic); + idx = 0; + match = CMD_MATCH_NONE; + + while (HelpMsg[idx].keyword) { + + if (strlen(HelpMsg[idx].keyword) >= len && + !_strnicmp(topic, HelpMsg[idx].keyword, len)) { + + if (match == CMD_MATCH_NONE) { // first match + match = idx; + } + else { // multiple matches + if (match != CMD_MATCH_MULTI) { // first time + PrintMessage(MSG_AMBIGUOUS_COMMAND, topic); + printf("> %s ", HelpMsg[match].keyword); + match = CMD_MATCH_MULTI; + } + + printf("%s ", HelpMsg[idx].keyword); + } + } + + idx++; + } + + if (match == CMD_MATCH_NONE) { // match not found + PrintMessage(MSG_UNKNOWN_COMMAND, topic); + } + else if (match == CMD_MATCH_MULTI) { // multiple matches + printf("\n"); + } + + return match; +} + +// +// Check driver version and update if necessary +// +int CheckDriver() +{ + char path[MAX_PATH]; + DWORD start; + + // check installed driver file version + + if (VfdGetDriverConfig(path, &start) == ERROR_SUCCESS && + VfdCheckDriverFile(path, NULL) == ERROR_SUCCESS) { + + HANDLE hDevice; + + if (driver_state != SERVICE_RUNNING) { + return VFD_OK; + } + + // check running driver version + + hDevice = VfdOpenDevice(0); + + if (hDevice != INVALID_HANDLE_VALUE) { + CloseHandle(hDevice); + return VFD_OK; + } + } + + PrintMessage(MSG_WRONG_DRIVER); + return VFD_NG; +} + +// +// Print a prompt message and accept the reply input +// +int InputChar(ULONG msg, PCSTR ans) +{ + HANDLE hStdIn; + INPUT_RECORD input; + DWORD result; + int reply; + + PrintMessage(msg); + fflush(NULL); + + hStdIn = GetStdHandle(STD_INPUT_HANDLE); + + FlushConsoleInputBuffer(hStdIn); + + for (;;) { + ReadConsoleInput(hStdIn, &input, sizeof(input), &result); + + if (input.EventType == KEY_EVENT && + input.Event.KeyEvent.bKeyDown) { + + reply = tolower(input.Event.KeyEvent.uChar.AsciiChar); + + if (strchr(ans, reply)) { + break; + } + } + } + + printf("%c\n", reply); + + return reply; +} + +// +// Print image information on a Virtual Floppy Drive +// +void PrintImageInfo( + HANDLE hDevice) +{ + ULONG device_number; + CHAR file_name[MAX_PATH]; + CHAR file_desc[MAX_PATH]; + VFD_DISKTYPE disk_type; + VFD_MEDIA media_type; + VFD_FLAGS media_flags; + VFD_FILETYPE file_type; + ULONG image_size; + DWORD ret; + + printf("\n"); + + // get current device number + + ret = VfdGetDeviceNumber(hDevice, &device_number); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_GET_LINK_NG); + printf("%s", SystemError(ret)); + device_number = (ULONG)-1; + } + + // get current drive letters + + PrintDriveLetter(hDevice, device_number); + + // image file information + + ret = VfdGetImageInfo(hDevice, file_name, &disk_type, + &media_type, &media_flags, &file_type, &image_size); + + if (ret != ERROR_SUCCESS) { + PrintMessage(MSG_GET_FILE_NG); + printf("%s", SystemError(ret)); + return; + } + + // print image file information + if (media_type == VFD_MEDIA_NONE) { + PrintMessage(MSG_IMAGE_NONE); + return; + } + + if (file_name[0]) { + PrintMessage(MSG_IMAGE_NAME, file_name); + + VfdMakeFileDesc(file_desc, sizeof(file_desc), + file_type, image_size, GetFileAttributes(file_name)); + } + else { + PrintMessage(MSG_IMAGE_NAME, ""); + + VfdMakeFileDesc(file_desc, sizeof(file_desc), + VFD_FILETYPE_NONE, image_size, 0); + } + + PrintMessage(MSG_FILE_DESC, file_desc); + + if (disk_type == VFD_DISKTYPE_FILE) { + PrintMessage(MSG_DISKTYPE_FILE); + } + else { + if (media_flags & VFD_FLAG_DATA_MODIFIED) { + PrintMessage(MSG_DISKTYPE_RAM_DIRTY); + } + else { + PrintMessage(MSG_DISKTYPE_RAM_CLEAN); + } + } + + // print other file info + + PrintMessage(MSG_MEDIA_TYPE, VfdMediaTypeName(media_type)); + + if (media_flags & VFD_FLAG_WRITE_PROTECTED) { + PrintMessage(MSG_MEDIA_PROTECTED); + } + else { + PrintMessage(MSG_MEDIA_WRITABLE); + } +} + +// +// Print drive letters on a virtual floppy drive +// +void PrintDriveLetter( + HANDLE hDevice, + ULONG nDrive) +{ + CHAR letter; + + PrintMessage(MSG_DRIVE_LETTER, nDrive); + + VfdGetGlobalLink(hDevice, &letter); + + if (isalpha(letter)) { + PrintMessage(MSG_PERSISTENT, toupper(letter)); + } + + while (VfdGetLocalLink(hDevice, &letter) == ERROR_SUCCESS && + isalpha(letter)) { + PrintMessage(MSG_EPHEMERAL, toupper(letter)); + } + + printf("\n"); +} + +// +// Prints a text on screen a page a time +// +BOOL ConsolePager(char *pBuffer, BOOL bReset) +{ + static int rows = 0; + char prompt[80]; + int prompt_len = 0; + HANDLE hStdOut; + HANDLE hStdIn; + + // + // prepare the console input and output handles + // + hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + hStdIn = GetStdHandle(STD_INPUT_HANDLE); + + for (;;) { + CONSOLE_SCREEN_BUFFER_INFO info; + INPUT_RECORD input; + DWORD result; + DWORD mode; + int cols; + char *cur; + char save; + + // + // Get the current console screen information + // + GetConsoleScreenBufferInfo(hStdOut, &info); + + if (bReset || rows <= 0) { + rows = info.srWindow.Bottom - info.srWindow.Top - 1; + } + + cols = info.dwSize.X; + + // console window is too small for paging + + if (rows <= 0) { + // print all text and exit + printf("%s", pBuffer); + break; + } + + // + // find the tail of the text to be printed this time + // + cur = pBuffer; + save = '\0'; + + while (*cur) { + if (*(cur++) == '\n' || (cols--) == 0) { + // reached the end of a line + if (--rows == 0) { + // reached the end of a page + // insert a terminating NULL char + save = *cur; + *cur = '\0'; + break; + } + + cols = info.dwSize.X; + } + } + + // print the current page + printf("%s", pBuffer); + + // end of the whole text? + if (save == '\0') { + break; + } + + // + // prompt for the next page + // + + // prepare the prompt text + + if (prompt_len == 0) { + + prompt_len = FormatMessage( + FORMAT_MESSAGE_FROM_HMODULE | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, MSG_PAGER_PROMPT, 0, + prompt, sizeof(prompt), NULL); + + if (prompt_len == 0) { + strcpy(prompt, "Press any key to continue..."); + prompt_len = strlen(prompt); + } + } + + // get the current console input mode + + GetConsoleMode(hStdIn, &mode); + + // change the mode to receive Ctrl+C as a regular input + + SetConsoleMode(hStdIn, (mode & ~ENABLE_PROCESSED_INPUT)); + + // get the current cursor position + + GetConsoleScreenBufferInfo(hStdOut, &info); + + // print the prompt text + + WriteConsoleOutputCharacter(hStdOut, prompt, + prompt_len, info.dwCursorPosition, &result); + + // reverse the text color + + FillConsoleOutputAttribute(hStdOut, + (WORD)(info.wAttributes | COMMON_LVB_REVERSE_VIDEO), + prompt_len, info.dwCursorPosition, &result); + + // move cursor to the end of the prompt text + + info.dwCursorPosition.X = + (short)(info.dwCursorPosition.X + prompt_len); + + SetConsoleCursorPosition(hStdOut, info.dwCursorPosition); + + // wait for a key press event + + FlushConsoleInputBuffer(hStdIn); + + do { + ReadConsoleInput(hStdIn, &input, sizeof(input), &result); + } + while (input.EventType != KEY_EVENT || + !input.Event.KeyEvent.bKeyDown || + !input.Event.KeyEvent.uChar.AsciiChar); + + // restore the original cursor position + + info.dwCursorPosition.X = + (short)(info.dwCursorPosition.X - prompt_len); + + SetConsoleCursorPosition(hStdOut, info.dwCursorPosition); + + // delete the prompt text + + FillConsoleOutputCharacter(hStdOut, ' ', + prompt_len, info.dwCursorPosition, &result); + + // restore the text attribute to norml + + FillConsoleOutputAttribute(hStdOut, info.wAttributes, + prompt_len, info.dwCursorPosition, &result); + + // restore the original console mode + + SetConsoleMode(hStdIn, mode); + + // check if the input was 'q', or ? + + if (input.Event.KeyEvent.uChar.AsciiChar == VK_CANCEL || + input.Event.KeyEvent.uChar.AsciiChar == VK_ESCAPE || + tolower(input.Event.KeyEvent.uChar.AsciiChar) == 'q') { + + // cancelled by the user + return FALSE; + } + + // + // process the next page + // + *cur = save; + pBuffer = cur; + } + + return TRUE; +} + +// +// Format and print a message text +// +void PrintMessage(UINT msg, ...) +{ + char *buf = NULL; + va_list list; + + va_start(list, msg); + + if (FormatMessage( + FORMAT_MESSAGE_FROM_HMODULE | + FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, msg, 0, (LPTSTR)&buf, 0, &list)) { + + printf("%s", buf); + } + else { + printf("Unknown Message ID %u\n", msg); + } + + va_end(list); + + if (buf) { + LocalFree(buf); + } +} + +// +// Return a system error message text +// +const char *SystemError(DWORD err) +{ + static char msg[256]; + + if (!FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, 0, msg, sizeof(msg), NULL)) { +#ifndef __REACTOS__ + sprintf(msg, "Unknown system error %lu (0x%08x)\n", err, err); +#else + sprintf(msg, "Unknown system error %lu (0x%08lx)\n", err, err); +#endif + } + + return msg; +} + +// +// Convert a path to match the case of names on the disk +// +void ConvertPathCase(char *src, char *dst) +{ + HANDLE hFind; + WIN32_FIND_DATA find; + char *p; + + p = dst; + + if (*src == '\"') { + src++; + } + + if (*(src + strlen(src) - 1) == '\"') { + *(src + strlen(src) - 1) = '\0'; + } + + // + // handle drive / remote server name + // + if (isalpha(*src) && *(src + 1) == ':') { + + // drive name + + *(p++) = (char)toupper(*src); + strcpy(p++, ":\\"); + + src += 2; + } + else if (*src == '\\' || *src == '/') { + + // absolute path or remote name + + if ((*(src + 1) == '\\' || *(src + 1) == '/') && + *(src + 2) && *(src + 2) != '\\' && *(src + 2) != '/') { + + // remote path + + *(p++) = '\\'; + *(p++) = '\\'; + src += 2; + + while (*src && *src != '\\' && *src != '/') { + *(p++) = *(src++); + } + } + + strcpy(p, "\\"); + } + else { + *p = '\0'; + } + + // skip redundant '\' + + while (*src == '\\' || *src == '/') { + src++; + } + + // process the path + + while (*src) { + + char *q = src; + + // separate the next part + + while (*q && *q != '\\' && *q != '/') { + q++; + } + + if ((q - src) == 2 && !strncmp(src, "..", 2)) { + // parent dir - copy as it is + if (p != dst) { + *p++ = '\\'; + } + + strcpy(p, ".."); + p += 2; + } + else if ((q - src) > 1 || *src != '.') { + // path name other than "." + if (p != dst) { + *(p++) = '\\'; + } + + strncpy(p, src, (q - src)); + *(p + (q - src)) = '\0'; + + hFind = FindFirstFile(dst, &find); + + if (hFind == INVALID_HANDLE_VALUE) { + strcpy(p, src); + break; + } + + FindClose(hFind); + + strcpy(p, find.cFileName); + p += strlen(p); + } + + // skip trailing '\'s + + while (*q == '\\' || *q == '/') { + q++; + } + + src = q; + } +} diff --git a/modules/rosapps/applications/cmdutils/vfdcmd/vfdcmd.rc b/modules/rosapps/applications/cmdutils/vfdcmd/vfdcmd.rc new file mode 100644 index 00000000000..6f4b582bddb --- /dev/null +++ b/modules/rosapps/applications/cmdutils/vfdcmd/vfdcmd.rc @@ -0,0 +1,6 @@ +#define REACTOS_STR_FILE_DESCRIPTION "Virtual Floppy Controler" +#define REACTOS_STR_INTERNAL_NAME "vfdcmd" +#define REACTOS_STR_ORIGINAL_FILENAME "vfdcmd.exe" +#include + +#include diff --git a/modules/rosapps/applications/cmdutils/vfdcmd/vfdcmd.rs b/modules/rosapps/applications/cmdutils/vfdcmd/vfdcmd.rs new file mode 100644 index 00000000000..3956ecc835c --- /dev/null +++ b/modules/rosapps/applications/cmdutils/vfdcmd/vfdcmd.rs @@ -0,0 +1,49 @@ +/* + vfdcmd.rs + + Virtual Floppy Drive for Windows + Driver control program (console version) + Resource script + + The non-standard extension ".rs" is intentional, so that + Microsoft Visual Studio won't try to open this file with + the resource editor + + Copyright (c) 2003-2005 Ken Kato +*/ + +#ifndef APSTUDIO_INVOKED + +// +// version resource +// +#include +#include "vfdver.h" + +#define VFD_FILEOS VOS_NT_WINDOWS32 +#define VFD_FILETYPE VFT_APP +#define VFD_FILESUBTYPE VFT2_UNKNOWN + +#define VFD_DESCRIPTION "Virtual Floppy Drive Console" +#define VFD_INTERNALNAME "vfd.exe" +#define VFD_FILE_MAJOR 2 +#define VFD_FILE_MINOR 1 + +// +// for Japanese version resources +// +#define VFD_VERSIONINFO_ALT "041104B0" +#undef VFD_VERSIONINFO_TRANS +#define VFD_VERSIONINFO_TRANS 0x0409, 0x04B0, 0x0411, 0x04B0 + +#define VFD_DESCRIPTION_ALT "Virtual Floppy Drive コンソール" +#define VFD_PRODUCT_NAME_ALT VFD_PRODUCT_NAME + +#include "vfdver.rc" + +// +// Message resource +// +#include "vfdmsg.rc" + +#endif // not APSTUDIO_INVOKED diff --git a/modules/rosapps/applications/cmdutils/vfdcmd/vfdmsg.mc b/modules/rosapps/applications/cmdutils/vfdcmd/vfdmsg.mc new file mode 100644 index 00000000000..222c04d7610 --- /dev/null +++ b/modules/rosapps/applications/cmdutils/vfdcmd/vfdmsg.mc @@ -0,0 +1,1596 @@ +;/* +; vfdmsg.h +; +; Virtual Floppy Drive for Windows +; Driver control program (console version) +; Message definition +; +; Copyright (C) 2003-2005 Ken Kato +;*/ +; +;#ifndef _VFDMSG_H_ +;#define _VFDMSG_H_ +; + +MessageIdTypedef=DWORD +LanguageNames=(English=0x409:MSG0409) + +;//============================================== +;// Generic error messages +;//============================================== +; + +MessageId= +SymbolicName=MSG_WRONG_PLATFORM +Language=English +Virtual Floppy Drive does not run on Windows 95/98/Me. +. + + +MessageId= +SymbolicName=MSG_TOO_MANY_ARGS +Language=English +Too many command line parameters. +. + + +MessageId= +SymbolicName=MSG_UNKNOWN_COMMAND +Language=English +Command '%1!s!' is unknown. +. + + +MessageId= +SymbolicName=MSG_AMBIGUOUS_COMMAND +Language=English +Command '%1!s!' is ambiguous. +. + + +MessageId= +SymbolicName=MSG_UNKNOWN_OPTION +Language=English +Option '%1!s!' is unknown. +. + + +MessageId= +SymbolicName=MSG_DUPLICATE_ARGS +Language=English +Parameter %1!s! is used more than once. +. + + +;//============================================== +;// Command result message +;//============================================== +; + +MessageId= +SymbolicName=MSG_INSTALL_OK +Language=English +Installed the Virtual Floppy driver. +. + + +MessageId= +SymbolicName=MSG_INSTALL_NG +Language=English +Failed to install the Virtual Floppy driver. +. + + +MessageId= +SymbolicName=MSG_CONFIG_OK +Language=English +Configured the Virtual Floppy driver start method. +. + + +MessageId= +SymbolicName=MSG_CONFIG_NG +Language=English +Failed to configure the Virtual Floppy driver start method. +. + + +MessageId= +SymbolicName=MSG_REMOVE_OK +Language=English +Uninstalled the Virtual Floppy driver. +. + + +MessageId= +SymbolicName=MSG_REMOVE_NG +Language=English +Failed to uninstall the Virtual Floppy driver. +. + + +MessageId= +SymbolicName=MSG_REMOVE_PENDING +Language=English +The Virtual Floppy driver is going to be removed on the next system start up. +You may need to restart the system before installing the driver again. +. + + +MessageId= +SymbolicName=MSG_START_OK +Language=English +Started the Virtual Floppy driver. +. + + +MessageId= +SymbolicName=MSG_START_NG +Language=English +Failed to start the Virtual Floppy driver. +. + + +MessageId= +SymbolicName=MSG_STOP_OK +Language=English +Stopped the Virtual Floppy driver. +. + + +MessageId= +SymbolicName=MSG_STOP_NG +Language=English +Failed to stop the Virtual Floppy driver. +. + + +MessageId= +SymbolicName=MSG_STOP_PENDING +Language=English +Stop operation has succeeded, but something +is preventing the driver from actually stopping. +You may need to reboot the system before restarting the driver. +. + + +MessageId= +SymbolicName=MSG_GET_SHELLEXT_NG +Language=English +Failed to get the shell extension status. +. + + +MessageId= +SymbolicName=MSG_SET_SHELLEXT_NG +Language=English +Failed to set the shell extension status. +. + + +MessageId= +SymbolicName=MSG_SHELLEXT_ENABLED +Language=English +Shell extension is enabled. +. + + +MessageId= +SymbolicName=MSG_SHELLEXT_DISABLED +Language=English +Shell extension is disabled. +. + + +MessageId= +SymbolicName=MSG_OPEN_NG +Language=English +Failed to open the image '%1!s!'. +. + + +MessageId= +SymbolicName=MSG_CLOSE_OK +Language=English +Closed the image on the drive %1!c!. +. + + +MessageId= +SymbolicName=MSG_CLOSE_NG +Language=English +Failed to close the image on the drive %1!c!. +. + + +MessageId= +SymbolicName=MSG_SAVE_OK +Language=English +Saved the image on the drive %1!c! into '%2!s!'. +. + + +MessageId= +SymbolicName=MSG_SAVE_NG +Language=English +Failed to save the image on the drive %1!c! into '%2!s!'. +. + + +MessageId= +SymbolicName=MSG_PROTECT_NG +Language=English +Failed to set write protect state on the drive %1!c!. +. + + +MessageId= +SymbolicName=MSG_FORMAT_OK +Language=English +Format complete. +. + + +MessageId= +SymbolicName=MSG_FORMAT_NG +Language=English +Failed to format the drive %1!c!. +. + + +MessageId= +SymbolicName=MSG_LINK_NG +Language=English +Failed to assign '%2!c!' to the drive %1!lu!. +. + + +MessageId= +SymbolicName=MSG_UNLINK_NG +Language=English +Failed to unlink the letter from the drive %1!lu!. +. + + +;//============================================== +;// Supplemental result message +;//============================================== +; + +MessageId= +SymbolicName=MSG_GET_STAT_NG +Language=English +Failed to get the driver status. +. + + +MessageId= +SymbolicName=MSG_GET_CONFIG_NG +Language=English +Failed to get the driver configuration. +. + + +MessageId= +SymbolicName=MSG_GET_VERSION_NG +Language=English +Failed to get the driver version. +. + + +MessageId= +SymbolicName=MSG_WRONG_DRIVER +Language=English +A wrong driver is installed. +. + + +MessageId= +SymbolicName=MSG_QUERY_UPDATE +Language=English +Update now (y / n) ? %0 +. + + +MessageId= +SymbolicName=MSG_GET_MEDIA_NG +Language=English +Failed to get the current media status. +. + + +MessageId= +SymbolicName=MSG_GET_FILE_NG +Language=English +Failed to get the image information. +. + + +MessageId= +SymbolicName=MSG_GET_LINK_NG +Language=English +Failed to get the current drive letter. +. + + +MessageId= +SymbolicName=MSG_LINK_FULL +Language=English +No drive letter is available. +. + + +MessageId= +SymbolicName=MSG_ACCESS_NG +Language=English +Failed to access the drive %1!c!. +. + + +MessageId= +SymbolicName=MSG_DRIVER_EXISTS +Language=English +The Virtual Floppy driver is already installed. +. + + +MessageId= +SymbolicName=MSG_NOT_INSTALLED +Language=English +The Virtual Floppy driver is not installed. +. + + +MessageId= +SymbolicName=MSG_ALREADY_RUNNING +Language=English +The Virtual Floppy driver is already running. +. + + +MessageId= +SymbolicName=MSG_NOT_STARTED +Language=English +The Virtual Floppy driver is not running. +. + + +MessageId= +SymbolicName=MSG_TARGET_NOTICE +Language=English +Using the default drive (%1!c!). +. + + +MessageId= +SymbolicName=MSG_CREATE_NOTICE +Language=English +Creating a new image file. +. + + +MessageId= +SymbolicName=MSG_CREATE_CONFIRM +Language=English +Create a new image file (Y:yes / N:no) ? %0 +. + + +MessageId= +SymbolicName=MSG_OVERWRITE_NOTICE +Language=English +Overwriting the existing file. +. + + +MessageId= +SymbolicName=MSG_OVERWRITE_CONFIRM +Language=English +Overwrite the existing file (Y:yes / N:no) ? %0 +. + + +MessageId= +SymbolicName=MSG_CREATE_NG +Language=English +Failed to create the new image file '%1!s!'. +. + + +MessageId= +SymbolicName=MSG_FILE_CREATED +Language=English +Created a new image file. +. + + +MessageId= +SymbolicName=MSG_RAM_MEDIA_UNKNOWN +Language=English +A size is not specified for a new RAM image. +. + + +MessageId= +SymbolicName=MSG_FILE_MEDIA_UNKNOWN +Language=English +A size is not specified for a new image file. +. + + +MessageId= +SymbolicName=MSG_CREATE144_NOTICE +Language=English +Creating a 1.44MB image. +. + + +MessageId= +SymbolicName=MSG_CREATE144_CONFIRM +Language=English +Create a 1.44MB image (Y:yes / N:no) ? %0 +. + + +MessageId= +SymbolicName=MSG_IMAGE_TOO_SMALL +Language=English +The image is too small. +. + + +MessageId= +SymbolicName=MSG_NO_MATCHING_MEDIA +Language=English +The image size (%1!lu! bytes) does not match any supported media. +. + + +MessageId= +SymbolicName=MSG_MEDIATYPE_NOTICE +Language=English +Opening as a %1!s! media (%2!lu! bytes). +. + + +MessageId= +SymbolicName=MSG_MEDIATYPE_SUGGEST +Language=English +The largest possible media is %1!s! (%2!lu! bytes). +. + + +MessageId= +SymbolicName=MSG_MEDIATYPE_CONFIRM +Language=English +Open as this media type (Y:yes / N:no) ? %0 +. + + +MessageId= +SymbolicName=MSG_RAM_MODE_NOTICE +Language=English +Opening the image in RAM mode. +. + + +MessageId= +SymbolicName=MSG_RAM_MODE_ONLY +Language=English +This file must be opened in RAM mode. +. + + +MessageId= +SymbolicName=MSG_RAM_MODE_CONFIRM +Language=English +Open in RAM mode (Y:yes / N:no) ? %0 +. + + +MessageId= +SymbolicName=MSG_DEFAULT_PROTECT +Language=English +The media will be write protected by default. +. + + +MessageId= +SymbolicName=MSG_DRIVE_BUSY +Language=English +An image is already opened. +. + + +MessageId= +SymbolicName=MSG_TARGET_REQUIRED +Language=English +Specify a target file to save. +. + + +MessageId= +SymbolicName=MSG_TARGET_UP_TO_DATE +Language=English +The image file is up to date. +. + + +MessageId= +SymbolicName=MSG_OVERWRITE_PROMPT +Language=English +Overwrite the existing file +(O: just overwrite / T: overwrite & truncate / C: cancel) ? %0 +. + + +MessageId= +SymbolicName=MSG_TARGET_IS_ZIP +Language=English +Cannot overwrite a ZIP compressed file. +. + + +MessageId= +SymbolicName=MSG_SAVE_FORCE +Language=English +The save operation is forced to continue. +. + + +MessageId= +SymbolicName=MSG_SAVE_QUIT +Language=English +The save operation is aborted. +. + + +MessageId= +SymbolicName=MSG_FORMAT_FORCE +Language=English +The format operation is forced to continue. +. + + +MessageId= +SymbolicName=MSG_FORMAT_QUIT +Language=English +The format operation is aborted. +. + + +MessageId= +SymbolicName=MSG_MEDIA_MODIFIED +Language=English +RAM disk data on the drive %1!c!: is modified. +. + + +MessageId= +SymbolicName=MSG_CLOSE_FORCE +Language=English +The close operation is forced to continue. +. + + +MessageId= +SymbolicName=MSG_CLOSE_QUIT +Language=English +The close operation is aborted. +. + + +MessageId= +SymbolicName=MSG_CLOSE_CONFIRM +Language=English +Close the image anyway (Y:yes / N:no) ? %0 +. + + +MessageId= +SymbolicName=MSG_RETRY_FORCE_CANCEL +Language=English +R:retry / F:force / C:cancel ? %0 +. + + +MessageId= +SymbolicName=MSG_RETRY_CANCEL +Language=English +R:retry / C:cancel ? %0 +. + + +MessageId= +SymbolicName=MSG_LOCK_NG +Language=English +Failed to lock the drive %1!c!. Some programs may be using the drive. +. + + +MessageId= +SymbolicName=MSG_STOP_FORCE +Language=English +Failed to close the all drives. The operation is forced to continue. +. + + +MessageId= +SymbolicName=MSG_STOP_QUIT +Language=English +Failed to close the all drives. The operation is aborted. +. + + +MessageId= +SymbolicName=MSG_STOP_WARN +Language=English +Failed to close the all drives. The driver may not be able to unload +properly. Continue the stop operation? +. + + +MessageId= +SymbolicName=MSG_REMOVE_FORCE +Language=English +Failed to stop the driver. The operation is forced to continue; +. + + +MessageId= +SymbolicName=MSG_REMOVE_QUIT +Language=English +Failed to stop the driver. The operation is aborted. +. + + +MessageId= +SymbolicName=MSG_REMOVE_WARN +Language=English +Failed to stop the driver. The driver may not be removed completely +until the system is restarted. Continue the operation? +. + + +MessageId= +SymbolicName=MSG_UNKNOWN_LONG +Language=English +Unknown (0x%1!08x!) +. + + +MessageId= +SymbolicName=MSG_DRIVER_FILE +Language=English +Driver : %1!s! +. + + +MessageId= +SymbolicName=MSG_DRIVER_VERSION +Language=English +Version : %1!d!.%2!d! %3!s! +. + + +MessageId= +SymbolicName=MSG_START_TYPE +Language=English +Start Type : %0 +. + + +MessageId= +SymbolicName=MSG_START_AUTO +Language=English +AUTO +. + + +MessageId= +SymbolicName=MSG_START_BOOT +Language=English +BOOT +. + + +MessageId= +SymbolicName=MSG_START_DEMAND +Language=English +DEMAND +. + + +MessageId= +SymbolicName=MSG_START_DISABLED +Language=English +DISABLED +. + + +MessageId= +SymbolicName=MSG_START_SYSTEM +Language=English +SYSTEM +. + + +MessageId= +SymbolicName=MSG_DRIVER_STATUS +Language=English +Status : %0 +. + + +MessageId= +SymbolicName=MSG_STATUS_STOPPED +Language=English +STOPPED +. + + +MessageId= +SymbolicName=MSG_STATUS_START_P +Language=English +START_PENDING +. + + +MessageId= +SymbolicName=MSG_STATUS_STOP_P +Language=English +STOP_PENDING +. + + +MessageId= +SymbolicName=MSG_STATUS_RUNNING +Language=English +RUNNING +. + + +MessageId= +SymbolicName=MSG_STATUS_CONT_P +Language=English +CONTINUE_PENDING +. + + +MessageId= +SymbolicName=MSG_STATUS_PAUSE_P +Language=English +PAUSE_PENDING +. + + +MessageId= +SymbolicName=MSG_STATUS_PAUSED +Language=English +PAUSED +. + + +MessageId= +SymbolicName=MSG_DRIVE_LETTER +Language=English +Drive %1!lu! : %0 +. + + +MessageId= +SymbolicName=MSG_PERSISTENT +Language=English +%1!c! (Persistent) %0 +. + + +MessageId= +SymbolicName=MSG_EPHEMERAL +Language=English +%1!c! (Ephemeral) %0 +. + + +MessageId= +SymbolicName=MSG_IMAGE_NONE +Language=English +Image : +. + + +MessageId= +SymbolicName=MSG_IMAGE_NAME +Language=English +Image : %1!s! +. + + +MessageId= +SymbolicName=MSG_FILE_DESC +Language=English +Description: %1!s! +. + + +MessageId= +SymbolicName=MSG_DISKTYPE_FILE +Language=English +Type : FILE +. + + +MessageId= +SymbolicName=MSG_DISKTYPE_RAM_CLEAN +Language=English +Type : RAM (not modified) +. + + +MessageId= +SymbolicName=MSG_DISKTYPE_RAM_DIRTY +Language=English +Type : RAM (modified) +. + + +MessageId= +SymbolicName=MSG_MEDIA_TYPE +Language=English +Media : %1!s! +. + + +MessageId= +SymbolicName=MSG_MEDIA_WRITABLE +Language=English +Access : Writable +. + + +MessageId= +SymbolicName=MSG_MEDIA_PROTECTED +Language=English +Access : Write Protected +. + + +;// +;// Help message text +;// +MessageId= +SymbolicName=MSG_HINT_INSTALL +Language=English +SYNTAX: %1!s!INSTALL [driver] [/AUTO | /A] +Try '%1!s!HELP INSTALL' for more information. +. + + +MessageId= +SymbolicName=MSG_HINT_REMOVE +Language=English +SYNTAX: %1!s!REMOVE [/FORCE | /F | /QUIT | /Q] +Try '%1!s!HELP REMOVE' for more information. +. + + +MessageId= +SymbolicName=MSG_HINT_CONFIG +Language=English +SYNTAX: %1!s!CONFIG {/AUTO | /A | /MANUAL | /M} +Try '%1!s!HELP CONFIG' for more information. +. + + +MessageId= +SymbolicName=MSG_HINT_START +Language=English +SYNTAX: %1!s!START +Try '%1!s!HELP START' for more information. +. + + +MessageId= +SymbolicName=MSG_HINT_STOP +Language=English +SYNTAX: %1!s!STOP [/FORCE | /F | /QUIT | /Q] +Try '%1!s!HELP STOP' for more information. +. + + +MessageId= +SymbolicName=MSG_HINT_SHELL +Language=English +SYNTAX: %1!s!SHELL [/ON | /OFF] +Try '%1!s!HELP SHELL' for more information. +. + + +MessageId= +SymbolicName=MSG_HINT_OPEN +Language=English +SYNTAX: %1!s!OPEN [drive:] [file] [/NEW] [/RAM] [/P | /W] + [ /160 | /180 | /320 | /360 | /640 | /720 | /820 | /120 | /1.20 + | /144 | /1.44 | /168 | /1.68 | /172 | /1.72 | /288 | /2.88 ] + [ /5 | /525 | /5.25 ] [/F | /FORCE | /Q | QUIT] +Try '%1!s!HELP OPEN' for more information. +. + + +MessageId= +SymbolicName=MSG_HINT_CLOSE +Language=English +SYNTAX: %1!s!CLOSE [drive:] [/FORCE | /F | /QUIT | /Q] +Try '%1!s!HELP CLOSE' for more information. +. + + +MessageId= +SymbolicName=MSG_HINT_SAVE +Language=English +SYNTAX: %1!s!SAVE [drive:] [file] [/OVER | /O | /TRUNC | /T] + [/FORCE | /F | /QUIT | /Q] +Try '%1!s!HELP SAVE' for more information. +. + + +MessageId= +SymbolicName=MSG_HINT_PROTECT +Language=English +SYNTAX: %1!s!PROTECT [drive:] [/ON | /OFF] +Try '%1!s!HELP PROTECT' for more information. +. + + +MessageId= +SymbolicName=MSG_HINT_FORMAT +Language=English +SYNTAX: %1!s!FORMAT [drive:] [/FORCE | /F | /QUIT | /Q] +Try '%1!s!HELP FORMAT' for more information. +. + + +MessageId= +SymbolicName=MSG_HINT_LINK +Language=English +SYNTAX: %1!s!LINK [number] [letter] [/L] +Try '%1!s!HELP LINK' for more information. +. + + +MessageId= +SymbolicName=MSG_HINT_ULINK +Language=English +SYNTAX: %1!s!ULINK [drive] +Try '%1!s!HELP ULINK' for more information. +. + + +MessageId= +SymbolicName=MSG_HINT_STATUS +Language=English +SYNTAX: %1!s!STATUS +Try '%1!s!HELP STATUS' for more information. +. + + +MessageId= +SymbolicName=MSG_HINT_VERSION +Language=English +SYNTAX: %1!s!VERSION +Print version information. +. + + +MessageId= +SymbolicName=MSG_HELP_GENERAL +Language=English +Usage: + %1!s![command [options...]] + +Commands: + INSTALL Install the Virtual Floppy driver. + REMOVE Uninstall the Virtual Floppy driver. + CONFIG Configure the Virtual Floppy driver. + START Start the Virtual Floppy driver. + STOP Stop the Virtual Floppy driver. + SHELL Enable/disable the shell extension. + OPEN Open a Virtual Floppy image. + CLOSE Close a Virtual Floppy image. + SAVE Save the current image into a file. + PROTECT Enable/disable drive write protect. + FORMAT Format the current Virtual Floppy media. + LINK Assign a drive letter to a Virtual Floppy drive. + ULINK Remove a drive letter from a Virtual Floppy drive. + STATUS Print the current status. + HELP | ? Print usage help. + VERSION Print version information + +If a command is not specified, the interactive console is started. +Type '%1!s!HELP CONSOLE' for more information about the interactive +console. + +All commands and options are case insensitive. + +Shorter command name can be used as long as the command can be +distinguished uniquely: I for INSTALL, REM for REMOVE, etc. are +accepted, but ST is invalid because it is ambiguous. You have +to type as much as STAR, STO or STAT in order to distinguish them. + +'%1!s!command {/? | /h}' shows a brief hint about each command. +. + + +MessageId= +SymbolicName=MSG_HELP_INSTALL +Language=English +Install the Virtual Floppy driver. + +SYNTAX: + %1!s!INSTALL [driver] [/AUTO | /A] + +OPTIONS: + driver Specifies the path to the Virtual Floppy driver file. + Default is VFD.SYS in the same directory as the VFD + console program (Note: *NOT* current directory). + + /AUTO Configures the driver to start at the system startup. + /A (Note: *NOT* to start the driver after installation.) + By default the driver has to be started manually. + +Administrator rights are required to install a devide driver. + +Device drivers cannot be installed from network drives. +Make sure to place VFD.SYS on a local drive. + +It is advised to install the driver with the /AUTO option if the +Virtual Floppy drive is going to be used by users other than +Administrators and Power Users, who don't have enough rights to +start device drivers. +. + + +MessageId= +SymbolicName=MSG_HELP_CONFIG +Language=English +Configure the Virtual Floppy driver start method. + +SYNTAX: + %1!s!CONFIG {/AUTO | /A | /MANUAL | /M} + +OPTIONS: + /AUTO Configures the driver to start at the system startup. + /A + + /MANUAL Configures the driver to start on demand. + /M + +The change takes effect the next system start up. +Administrator rights are required to configure a devide driver. +. + + +MessageId= +SymbolicName=MSG_HELP_REMOVE +Language=English +Uninstall the Virtual Floppy driver. + +SYNTAX: + %1!s!REMOVE [/FORCE | /F | /QUIT | /Q] + +OPTIONS: + /FORCE Suppress prompting and forces the remove operation when + /F the driver cannot be stopped. + + /QUIT Suppress prompting and quits the remove operation when + /Q the driver cannot be stopped. + +Closes all images and stops the driver if necessary, then removes the +Virtual Floppy driver entries from the system registry. +This command does not delete the driver file from the local disk. + +There are cases, due to the condition of the system, when +uninstallation does not complete immediately and restarting of the +system is required. In such cases you may not be able to install the +Virtual Floppy driver again until the system is restarted and +uninstallation process is complete. + +Administrator rights are required to uninstall a device driver. +. + + +MessageId= +SymbolicName=MSG_HELP_START +Language=English +Start the Virtual Floppy driver. + +SYNTAX: + %1!s!START + +OPTIONS: + NONE + +If the driver is not installed, this command attempts to install it +with thedefault options. + +At least Power User rights are required to start a device driver. +. + + +MessageId= +SymbolicName=MSG_HELP_STOP +Language=English +Stop the Virtual Floppy driver + +SYNTAX: + %1!s!STOP [/FORCE | /F | /QUIT | /Q] + +OPTIONS: + /FORCE Suppress prompting and forces the stop operation when any + /F of the drives are in use and cannot be closed. + + /QUIT Suppress prompting and quits the stop operation when any + /Q of the drives are in use and cannot be closed. + +This command closes all images before stopping the driver. +An image cannot be closed if the virtual drive is used by any other +programs. Forcing the stop operation with a drive in use may leave +the driver in stop pending state. In such cases the driver cannot be +restarted until all programs stop using the drive and the driver is +properly unloaded. + +At least Power User rights are required to stop a device driver. +. + + +MessageId= +SymbolicName=MSG_HELP_SHELL +Language=English +Enable / disable the Virtual Floppy drive shell extension. + +SYNTAX: + %1!s!SHELL [/ON | /OFF] + +OPTIONS: + /ON Enables the shell extension. + + /OFF Disables the shell extension. + +If an option is not specified, this command prints the current state +of the shell extension. +. + + +MessageId= +SymbolicName=MSG_HELP_OPEN +Language=English +Open a Virtual Floppy image. + +SYNTAX: + %1!s!OPEN [drive:] [file] [/NEW] [/RAM] [/P | /W] + [/size] [/media] [/F | /FORCE | /Q | /QUIT] + +OPTIONS: + drive: Specifies a target Virtual Floppy drive, either by a drive + number or a drive letter, such as "0:", "1:", "B:", "X:". + The trailing ':' is required. + The drive 0 is assumed if not specified. + + file Specifies a Virtual Floppy image file to open. + An empty RAM disk is created if not specified. + + /NEW Creates a new image file. + Ignored if a file is not specified. + + /RAM RAM mode - mounts an on-memory copy of the image, instead + of directly mounting the image file. + Changes made to the virtual media are lost when the image + is closed, unless the image is explicitly saved to a file + with the 'SAVE' command. + Ignored if a file is not specified. + + /P Opens the image as a write protected media. + Write protection state can be chenged later with the + 'PROTECT' command. + + /W Opens the image as a writable media. + Write protection state can be chenged later with the + 'PROTECT' command. + + /size Specifies a media size. Acceptable options are: + + /160 (160KB) /820 (820KB) + /180 (180KB) /120 or /1.20 (1.20MB) + /320 (320KB) /144 or /1.44 (1.44MB) + /360 (360KB) /168 or /1.68 (1.68MB DMF) + /640 (640KB) /172 or /1.72 (1.72MB DMF) + /720 (720KB) /288 or /2.88 (2.88MB) + + /5 Specifies a 5.25 inch media. Takes effect only with + /525 640KB, 720KB and 1.2MB media and otherwise ignored. + /5.25 160KB, 180KB, 320KB and 360KB media are always 5.25". + 820KB, 1.44MB, 1.68MB, 1.72MB and 2.88MB media are always + 3.5". + + /FORCE Suppress prompring on minor conflicts and/or omission of + /F necessary parameters and continues the operation as best + as possible, employing default values if necessary. + See below for details. + + /QUIT Suppress prompring on minor conflicts and/or omission of + /Q necessary parameters and quits the operation on the first + such occasion. + See below for details. + +If the target drive does not have a drive letter, this command also +assigns a local drive letter (see '%1!s!HELP LINK') using the first +available letter. + +Read only files, NTFS encrypted/compressed files and ZIP compressed +image files (such as WinImage IMZ file) cannot be mounted directly +and must be opened in RAM mode. + +Without a size option, size of a virtual media is decided from the +actual image size. With an explicit size option you can mount a +file as a smaller media, in such cases surplus data at the end of +the image is ignored. +A virtual media size cannot exceed the actual image size. + +The /F and /Q options affect the behavior of the OPEN command in +many ways: + + When the target file does not exist and the /NEW option + is not present + + (none) ask user whether to create the target + /F create the target without asking + /Q abort the operation without asking + + The target file exists and the /NEW option is present + + (none) ask user whether to overwrite the existing file + /F overwrite the file without asking + /Q abort the operation without asking + + The target file cannot be mounted directly and the /RAM + option is not present + + (none) ask user whether to open in RAM mode + /F open in RAM mode without asking + /Q abort the operation without asking + + A size option is not present for creating a new image + + (none) ask user whether to create a 1.44MB (default) image + /F create a 1.44MB image without asking + /Q abort the operation without asking + + A size option is not present and the target file size is + not an exact match for any of supported media + + (none) ask user whether to mount as a largest media to fit + in the actual image + /F mount as a largest media to fit in the actual image + without asking + /Q abort the operation without asking +. + + +MessageId= +SymbolicName=MSG_HELP_CLOSE +Language=English +Close a Virtual Floppy image. + +SYNTAX: + %1!s!CLOSE [drive:] [/FORCE | /F | /QUIT | /Q] + +OPTIONS: + drive: Specifies a target Virtual Floppy drive, either by a drive + number or a drive letter, such as "0:", "1:", "B:", "X:". + The trailing ':' is optional. + "*" stands for both drives. + The drive 0 is used if not specified. + + /FORCE Suppress prompting and forces the close operation when RAM + /F disk data is modified or the drive is in use. + Forcing with the drive in use will work only on Windows + 2000 and later (not on NT). + + /QUIT Suppress prompting and quits the close operation when RAM + /Q disk data is modified or the drive is in use. + +If neither /Q nor /F is specified, the user has to choose whether to +retry, force, or quit. + +Unlike the previous versions of the VFD, this command does *NOT* +remove the drive letter of the target drive. +. + + +MessageId= +SymbolicName=MSG_HELP_SAVE +Language=English +Save the current image data into a file. + +SYNTAX: + %1!s!SAVE [drive:] [file] [/O | /OVER | /T | /TRUNC] + [/FORCE | /F | /QUIT | /Q] + +OPTIONS: + drive: Specifies a target Virtual Floppy drive, either by a drive + number or a drive letter, such as "0:", "1:", "B:", "X:". + The trailing ':' is required. + The drive 0 is used if not specified. + + file Specifies a file name to save data. + If not specified, the current image file name is used. + Required if the current image is a pure RAM disk. + + /OVER Overwrite the file if the target file exists. + /O If the existing file is larger than the current image, + file size is not changed and the surplus data at the end + of the file is left unchanged. + If the target is the current image file, this is the + default behavior of this command. + Ignored if the target does not exist. + + /TRUNC Overwrite the file if the target file exists. + /T If the existing file is larger than the current image, + the file is truncated to the image size and the surplus + data at the end of the file is discarded. + Ignored if the target does not exist. + + /FORCE Suppress prompting when the target volume can not be + /F locked and forces the operation without locking. + + /QUIT Suppress prompting when the target volume can not be + /Q locked and quits the operation. + +If the target is the current image file, the file is always +overwritten without a question and the /O option is not necessary. +Otherwise this command fails if the target file exists and neither +/O or /T is present. + +If the existing file is smaller than the current image, the file +is always expanded to the current image size either with /O or /T. + +This program NEVER overwrites a ZIP compressed file regardless of /O +or /T option, or even if it is the current image file. +The SAVE command always fails if the target is a ZIP compressed file. +. + + +MessageId= +SymbolicName=MSG_HELP_PROTECT +Language=English +Enable / disable drive write protect. + +SYNTAX: + %1!s!PROTECT [drive:] [/ON | /OFF] + +OPTIONS: + drive: Specifies a target Virtual Floppy drive, either by a drive + number or a drive letter, such as "0:", "1:", "B:", "X:". + The trailing ':' is optional. + The drive 0 is used if not specified. + + /ON Enables the drive write protect - the drive becomes read only. + + /OFF Disables the drive write protect - the drive becomes writable. + +If an option is not specified, this command prints the current write +protect state of the drive. + +After write protection is disabled with this command, Windows may not +notice the change immediately and claim that the media is still write +protected. Refreshing the Explorer or retrying the faild operation +will fix that. +. + + +MessageId= +SymbolicName=MSG_HELP_FORMAT +Language=English +Format a Virtual Floppy media with FAT. + +SYNTAX: + %1!s!FORMAT [drive:] [/FORCE | /F | /QUIT | /Q] + +OPTIONS: + drive: Specifies a target Virtual Floppy drive, either by a drive + number or a drive letter, such as "0:", "1:", "B:", "X:". + The trailing ':' is optional. + The drive 0 is used if not specified. + + /FORCE Suppress prompting when the target volume can not be + /F locked and forces the operation without locking. + + /QUIT Suppress prompting when the target volume can not be + /Q locked and quits the operation. +. + + +MessageId= +SymbolicName=MSG_HELP_LINK +Language=English +Assign a drive letter to a Virtual Floppy drive. + +SYNTAX: + %1!s!LINK [number] [letter] [/L] + +OPTIONS: + number Specifies a target drive number. + If not specified, drive 0 is used. + "*" stands for both drives. + + letter Spesifies a drive letter to assign. + If not specified, the first available letter is used. + If the target is both drives, letters for each drives can + be specified like "BF" (B for 0, F for 1). + + /L Assign an ephemeral / local drive letter. + The default (without this option) is persistent / global. + +Persistent / global drive letters are reclaimed each time the driver +starts. +On Windows 2000 SP2 and later they are not deleted on user logoff. +On Terminal Servers they are globaly visible to all users on the +system. + +Ephemeral / local drive letters are not reclaimed on driver start up. +On Windows 2000 SP2 and later they are deleted on user logoff. +On Terminal Servers, they are visible only to the current user and +each user can assign different drive letter to the same drive. +. + + +MessageId= +SymbolicName=MSG_HELP_ULINK +Language=English +Remove a drive letter from a Virtual Floppy drive. + +SYNTAX: + %1!s!ULINK [drive] + +OPTIONS: + drive Specifies a target Virtual Floppy drive, either by a drive + number or a drive letter. + If not specified, drive 0 is used. + "*" stands for both drives. + +Drive letters can be removed even if the drive is being used. +Some applications such as Windows Explorer detects it and acts +accordingly, for example closes folder windows for the drive. +. + + +MessageId= +SymbolicName=MSG_HELP_STATUS +Language=English +Print the current status. + +SYNTAX: + %1!s!STATUS + +OPTIONS: + NONE + +This command prints the following information: + + Driver file path + Driver version + Driver start type + Driver running state + + Shell extension status + + Drive letter + Image name + Image description (file type, size, file attributes, etc.) + Disk type (RAM or FILE) + Write protection +. + + +MessageId= +SymbolicName=MSG_HELP_HELP +Language=English +Print the VFD console help. + +SYNTAX: + %1!s!HELP [command | topic] + +OPTIONS: + command Specifies one of the following commands + + INSTALL REMOVE CONFIG START STOP + SHELL OPEN CLOSE SAVE PROTECT + FORMAT LINK ULINK STATUS HELP + VERSION + + topic Specifies one of the following topics + + CONSOLE + +If an option is not specified, the general help is printed. +. + + +MessageId= +SymbolicName=MSG_CONSOLE_HINT +Language=English + + ********** the VFD interactive console ********** + +you can use the following commands in addition to regular VFD commands: + + ATTRIB CD CHDIR : + DIR EXIT QUIT BYE + .(period) + Windows command + +Type '? CONSOLE' or 'HELP CONSOLE' for more information + +. + + +MessageId= +SymbolicName=MSG_HELP_CONSOLE +Language=English +In the interactive console, you can use the following commands in +addition to regular VFD commands: + + CD | CHDIR + Displays the name of or changes the current directory. + Similar to the Windows CD/CHDIR command. + + : Change the current directory to the root of the specified + drive. Similar to the Windows drive change command. + + DIR Executes the Windows DIR command. + All options for the Windows DIR command are available. + + ATTRIB Executes the Windows ATTRIB command. + All options for the Windows ATTRIB command are available. + + EXIT | QUIT | BYE | + Quits the VFD interactive console. + +A command typed with a leading '.'(period) is executed by the Windows +command processor (cmd.exe). + + e.g.) .FORMAT [options ...] + Executes the Windows format.exe. All options are passed to + the format.exe. + + FORMAT [options ...] + Executes the VFD 'FORMAT' command. + +To execute an external command with spaces in its name, put the +'.' (period) outside the quoteation. + + e.g.) ."C:\Program Files\My App\My Program.exe" [options ...] + +DIR and ATTRIB Windows commands are recognized without a period, +for they are used very frequently. + +Commands to affect current directory and environment variable have +effects only inside the Windows command processor. You can execute +them but they have no effect on the VFD console. + + .CD .CHDIR .: to change the current directory + .PUSHD .POPD + .PATH to change the search path + .PROMPT + .SET to change the value of an environment variable +. + + +MessageId= +SymbolicName=MSG_PAGER_PROMPT +Language=English +Press any key to continue ('Q' or to quit) ...%0 +. + + +; +;#endif // _VFDMSG_H_ diff --git a/modules/rosapps/drivers/CMakeLists.txt b/modules/rosapps/drivers/CMakeLists.txt index 61a8e43fcfd..18def36ba27 100644 --- a/modules/rosapps/drivers/CMakeLists.txt +++ b/modules/rosapps/drivers/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(green) add_subdirectory(vcdrom) +add_subdirectory(vfd) diff --git a/modules/rosapps/drivers/vfd/CMakeLists.txt b/modules/rosapps/drivers/vfd/CMakeLists.txt new file mode 100644 index 00000000000..1c234239b06 --- /dev/null +++ b/modules/rosapps/drivers/vfd/CMakeLists.txt @@ -0,0 +1,19 @@ +list(APPEND SOURCE + vfddbg.c + vfddev.c + vfddrv.c + vfdfmt.c + vfdimg.c + vfdioctl.c + vfdlink.c + vfdmnt.c + vfdpnp.c + vfdrdwr.c) + +include_directories(${REACTOS_SOURCE_DIR}/modules/rosapps/include/vfd) +add_library(vfddrv SHARED ${SOURCE} vfddrv.rc) +set_module_type(vfddrv kernelmodedriver) +add_importlibs(vfddrv ntoskrnl hal) +set_target_properties(vfddrv PROPERTIES OUTPUT_NAME "vfd") +add_cd_file(TARGET vfddrv DESTINATION reactos/system32/drivers FOR all) +add_registry_inf(vfd_reg.inf) diff --git a/modules/rosapps/drivers/vfd/imports.h b/modules/rosapps/drivers/vfd/imports.h new file mode 100644 index 00000000000..8a9ca901be7 --- /dev/null +++ b/modules/rosapps/drivers/vfd/imports.h @@ -0,0 +1,357 @@ +/* + imports.h + + Virtual Floppy Drive for Windows NT platform + Kernel mode driver: imported elements from various sources + + Copyright (C) 2003-2005 Ken Kato + + This file contains: + + a) #include directive for system headers + + b) Stuff imported from newer DDKs so that the driver built with older + DDKs can run on newer Windows. + + c) Stuff imported from ntifs.h (http://www.acc.umu.se/~bosse/) so that + the driver can be compiled without it. + + d) Prototypes of standard functions which are exported from ntoskrnl.exe + but not declared in regular DDK header files. +*/ + +#ifndef _IMPORTS_H_ +#define _IMPORTS_H_ + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#ifdef _MSC_VER +#pragma warning(push,3) +#endif +#include +#include +#include +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#ifdef _MSC_VER +// disable unwanted (and trivial) warnings : +// 4054 - type cast from a function pointer to a data pointer +// 4201 - anonymous structure +// 4514 - unreferenced inline function +#pragma warning(disable: 4054 4201 4514) +#endif + +#if (VER_PRODUCTBUILD >= 2195) +#include +#else // (VER_PRODUCTBUILD < 2195) +// +// Imports from Windows 2000 DDK +// +typedef enum _MM_PAGE_PRIORITY { + LowPagePriority = 0, + NormalPagePriority = 16, + HighPagePriority = 32 +} MM_PAGE_PRIORITY; + +#define FILE_ATTRIBUTE_ENCRYPTED 0x00004000 + +#define FILE_DEVICE_MASS_STORAGE 0x0000002d + +// +// Imports from Windows 2000 DDK +// +#define IOCTL_STORAGE_CHECK_VERIFY2 CTL_CODE( \ + IOCTL_STORAGE_BASE, \ + 0x0200, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) + +// +// Imports from Windows 2000 DDK , +// +#define MOUNTMGR_DEVICE_NAME L"\\Device\\MountPointManager" +#define MOUNTMGRCONTROLTYPE ((ULONG) 'm') +#define MOUNTDEVCONTROLTYPE ((ULONG) 'M') + +#define IOCTL_MOUNTDEV_QUERY_UNIQUE_ID CTL_CODE( \ + MOUNTDEVCONTROLTYPE,\ + 0, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) + +#define IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY \ + CTL_CODE( \ + MOUNTDEVCONTROLTYPE,\ + 1, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) + +#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME CTL_CODE( \ + MOUNTDEVCONTROLTYPE,\ + 2, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) + +#define IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME \ + CTL_CODE( \ + MOUNTDEVCONTROLTYPE,\ + 3, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) + +#define IOCTL_MOUNTDEV_LINK_CREATED CTL_CODE( \ + MOUNTDEVCONTROLTYPE,\ + 4, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) + +#define IOCTL_MOUNTDEV_LINK_DELETED CTL_CODE( \ + MOUNTDEVCONTROLTYPE,\ + 5, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) + +#define IOCTL_MOUNTMGR_CREATE_POINT CTL_CODE( \ + MOUNTMGRCONTROLTYPE,\ + 0, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +#define IOCTL_MOUNTMGR_DELETE_POINTS CTL_CODE( \ + MOUNTMGRCONTROLTYPE,\ + 1, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +#define IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION \ + CTL_CODE( \ + MOUNTMGRCONTROLTYPE,\ + 11, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +typedef struct _MOUNTDEV_UNIQUE_ID { + USHORT UniqueIdLength; + UCHAR UniqueId[1]; +} MOUNTDEV_UNIQUE_ID, *PMOUNTDEV_UNIQUE_ID; + +typedef struct _MOUNTDEV_NAME { + USHORT NameLength; + WCHAR Name[1]; +} MOUNTDEV_NAME, *PMOUNTDEV_NAME; + +typedef struct _MOUNTDEV_SUGGESTED_LINK_NAME { + BOOLEAN UseOnlyIfThereAreNoOtherLinks; + USHORT NameLength; + WCHAR Name[1]; +} MOUNTDEV_SUGGESTED_LINK_NAME, *PMOUNTDEV_SUGGESTED_LINK_NAME; + +typedef struct _MOUNTMGR_TARGET_NAME { + USHORT DeviceNameLength; + WCHAR DeviceName[1]; +} MOUNTMGR_TARGET_NAME, *PMOUNTMGR_TARGET_NAME; + +typedef struct _MOUNTMGR_CREATE_POINT_INPUT { + USHORT SymbolicLinkNameOffset; + USHORT SymbolicLinkNameLength; + USHORT DeviceNameOffset; + USHORT DeviceNameLength; +} MOUNTMGR_CREATE_POINT_INPUT, *PMOUNTMGR_CREATE_POINT_INPUT; + +typedef struct _MOUNTMGR_MOUNT_POINT { + ULONG SymbolicLinkNameOffset; + USHORT SymbolicLinkNameLength; + ULONG UniqueIdOffset; + USHORT UniqueIdLength; + ULONG DeviceNameOffset; + USHORT DeviceNameLength; +} MOUNTMGR_MOUNT_POINT, *PMOUNTMGR_MOUNT_POINT; + +typedef struct _MOUNTMGR_MOUNT_POINTS { + ULONG Size; + ULONG NumberOfMountPoints; + MOUNTMGR_MOUNT_POINT MountPoints[1]; +} MOUNTMGR_MOUNT_POINTS, *PMOUNTMGR_MOUNT_POINTS; + +#endif // (VER_PRODUCTBUILD < 2195) + +#if (VER_PRODUCTBUILD < 2600) +// +// Imports from Windows XP DDK +// +#define IOCTL_DISK_GET_PARTITION_INFO_EX CTL_CODE( \ + IOCTL_DISK_BASE, \ + 0x0012, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) + +#define IOCTL_DISK_GET_LENGTH_INFO CTL_CODE( \ + IOCTL_DISK_BASE, \ + 0x0017, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +typedef unsigned __int64 ULONG64, *PULONG64; + +typedef enum _PARTITION_STYLE { + PARTITION_STYLE_MBR, + PARTITION_STYLE_GPT +} PARTITION_STYLE; + +typedef struct _PARTITION_INFORMATION_MBR { + UCHAR PartitionType; + BOOLEAN BootIndicator; + BOOLEAN RecognizedPartition; + ULONG HiddenSectors; +} PARTITION_INFORMATION_MBR, *PPARTITION_INFORMATION_MBR; + +typedef struct _PARTITION_INFORMATION_GPT { + GUID PartitionType; + GUID PartitionId; + ULONG64 Attributes; + WCHAR Name[36]; +} PARTITION_INFORMATION_GPT, *PPARTITION_INFORMATION_GPT; + +typedef struct _PARTITION_INFORMATION_EX { + PARTITION_STYLE PartitionStyle; + LARGE_INTEGER StartingOffset; + LARGE_INTEGER PartitionLength; + ULONG PartitionNumber; + BOOLEAN RewritePartition; + union { + PARTITION_INFORMATION_MBR Mbr; + PARTITION_INFORMATION_GPT Gpt; + }; +} PARTITION_INFORMATION_EX, *PPARTITION_INFORMATION_EX; + +typedef struct _GET_LENGTH_INFORMATION { + LARGE_INTEGER Length; +} GET_LENGTH_INFORMATION, *PGET_LENGTH_INFORMATION; + +// +// Imports from Windows XP DDK +// +#define IOCTL_STORAGE_GET_HOTPLUG_INFO CTL_CODE( \ + IOCTL_STORAGE_BASE, \ + 0x0305, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) + +typedef struct _STORAGE_HOTPLUG_INFO { + ULONG Size; + BOOLEAN MediaRemovable; + BOOLEAN MediaHotplug; + BOOLEAN DeviceHotplug; + BOOLEAN WriteCacheEnableOverride; +} STORAGE_HOTPLUG_INFO, *PSTORAGE_HOTPLUG_INFO; + +// +// Imports from Windows XP DDK +// +#define IOCTL_MOUNTDEV_QUERY_STABLE_GUID CTL_CODE( \ + MOUNTDEVCONTROLTYPE,\ + 6, \ + METHOD_BUFFERED, \ + FILE_ANY_ACCESS) + +typedef struct _MOUNTDEV_STABLE_GUID { + GUID StableGuid; +} MOUNTDEV_STABLE_GUID, *PMOUNTDEV_STABLE_GUID; + +#endif // (VER_PRODUCTBUILD < 2600) + +// +// Imports from ntifs.h +// +#define TOKEN_SOURCE_LENGTH 8 + +typedef enum _TOKEN_TYPE { + TokenPrimary = 1, + TokenImpersonation +} TOKEN_TYPE; + +typedef struct _TOKEN_SOURCE { + CCHAR SourceName[TOKEN_SOURCE_LENGTH]; + LUID SourceIdentifier; +} TOKEN_SOURCE, *PTOKEN_SOURCE; + +typedef struct _TOKEN_CONTROL { + LUID TokenId; + LUID AuthenticationId; + LUID ModifiedId; + TOKEN_SOURCE TokenSource; +} TOKEN_CONTROL, *PTOKEN_CONTROL; + +typedef struct _SECURITY_CLIENT_CONTEXT { + SECURITY_QUALITY_OF_SERVICE SecurityQos; + PACCESS_TOKEN ClientToken; + BOOLEAN DirectlyAccessClientToken; + BOOLEAN DirectAccessEffectiveOnly; + BOOLEAN ServerIsRemote; + TOKEN_CONTROL ClientTokenControl; +} SECURITY_CLIENT_CONTEXT, *PSECURITY_CLIENT_CONTEXT; + +#define PsDereferenceImpersonationToken(T) \ + if (ARGUMENT_PRESENT(T)) (ObDereferenceObject((T))) + +#define PsDereferencePrimaryToken(T) (ObDereferenceObject((T))) + +NTKERNELAPI +VOID +NTAPI +PsRevertToSelf ( + VOID +); + +NTKERNELAPI +NTSTATUS +NTAPI +SeCreateClientSecurity ( + IN PETHREAD Thread, + IN PSECURITY_QUALITY_OF_SERVICE QualityOfService, + IN BOOLEAN RemoteClient, + OUT PSECURITY_CLIENT_CONTEXT ClientContext +); + +#define SeDeleteClientSecurity(C) \ +{ \ + if (SeTokenType((C)->ClientToken) == TokenPrimary) { \ + PsDereferencePrimaryToken((C)->ClientToken); \ + } \ + else { \ + PsDereferenceImpersonationToken((C)->ClientToken); \ + } \ +} + +NTKERNELAPI +VOID +NTAPI +SeImpersonateClient ( + IN PSECURITY_CLIENT_CONTEXT ClientContext, + IN PETHREAD ServerThread OPTIONAL +); + +NTKERNELAPI +TOKEN_TYPE +NTAPI +SeTokenType ( + IN PACCESS_TOKEN Token +); + +// +// Functions exported by ntoskrnl.exe, but not declared in DDK headers +// +int _snprintf(char *buffer, size_t count, const char *format, ...); +int _snwprintf(wchar_t *buffer, size_t count, const wchar_t *format, ...); +int sprintf(char *buffer, const char *format, ...); +int _swprintf(wchar_t *buffer, const wchar_t *format, ...); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // _IMPORTS_H_ diff --git a/modules/rosapps/drivers/vfd/vfd_reg.inf b/modules/rosapps/drivers/vfd/vfd_reg.inf new file mode 100644 index 00000000000..110bfed91e0 --- /dev/null +++ b/modules/rosapps/drivers/vfd/vfd_reg.inf @@ -0,0 +1,7 @@ +; Virtual floppy class driver +[AddReg] +HKLM,"SYSTEM\CurrentControlSet\Services\VirtualFD","ErrorControl",0x00010001,0x00000000 +HKLM,"SYSTEM\CurrentControlSet\Services\VirtualFD","Group",0x00000000,"SCSI Class" +HKLM,"SYSTEM\CurrentControlSet\Services\VirtualFD","ImagePath",0x00020000,"system32\drivers\vfd.sys" +HKLM,"SYSTEM\CurrentControlSet\Services\VirtualFD","Start",0x00010001,0x00000003 +HKLM,"SYSTEM\CurrentControlSet\Services\VirtualFD","Type",0x00010001,0x00000001 diff --git a/modules/rosapps/drivers/vfd/vfddbg.c b/modules/rosapps/drivers/vfd/vfddbg.c new file mode 100644 index 00000000000..829f25b07a4 --- /dev/null +++ b/modules/rosapps/drivers/vfd/vfddbg.c @@ -0,0 +1,1799 @@ +/* + vfddbg.c + + Virtual Floppy Drive for Windows NT platform + Kernel mode driver debug functions + + Copyright (C) 2003-2005 Ken Kato +*/ + +#if !DBG + +// suppress empty compile unit warning +#pragma warning (disable: 4206) +#pragma message ("Debug feature is disabled.") + +#else // DBG + +#include "imports.h" +#include "vfddrv.h" +#include "vfddbg.h" + +#define CASE_RETURN_STR(str) case str: return #str; + +// +// Return IRP Major Function name +// +#ifndef IRP_MJ_POWER +#define IRP_MJ_POWER 0x16 +#endif +#ifndef IRP_MJ_SYSTEM_CONTROL +#define IRP_MJ_SYSTEM_CONTROL 0x17 +#endif +#ifndef IRP_MJ_PNP +#define IRP_MJ_PNP 0x1b +#endif + +PCSTR +GetMajorFuncName( + UCHAR major_code) +{ + static char functionName[80]; + + switch (major_code) { + CASE_RETURN_STR(IRP_MJ_CREATE); // 0x00 + CASE_RETURN_STR(IRP_MJ_CREATE_NAMED_PIPE); // 0x01 + CASE_RETURN_STR(IRP_MJ_CLOSE); // 0x02 + CASE_RETURN_STR(IRP_MJ_READ); // 0x03 + CASE_RETURN_STR(IRP_MJ_WRITE); // 0x04 + CASE_RETURN_STR(IRP_MJ_QUERY_INFORMATION); // 0x05 + CASE_RETURN_STR(IRP_MJ_SET_INFORMATION); // 0x06 + CASE_RETURN_STR(IRP_MJ_QUERY_EA); // 0x07 + CASE_RETURN_STR(IRP_MJ_SET_EA); // 0x08 + CASE_RETURN_STR(IRP_MJ_FLUSH_BUFFERS); // 0x09 + CASE_RETURN_STR(IRP_MJ_QUERY_VOLUME_INFORMATION); // 0x0a + CASE_RETURN_STR(IRP_MJ_SET_VOLUME_INFORMATION); // 0x0b + CASE_RETURN_STR(IRP_MJ_DIRECTORY_CONTROL); // 0x0c + CASE_RETURN_STR(IRP_MJ_FILE_SYSTEM_CONTROL); // 0x0d + CASE_RETURN_STR(IRP_MJ_DEVICE_CONTROL); // 0x0e + CASE_RETURN_STR(IRP_MJ_INTERNAL_DEVICE_CONTROL); // 0x0f + CASE_RETURN_STR(IRP_MJ_SHUTDOWN); // 0x10 + CASE_RETURN_STR(IRP_MJ_LOCK_CONTROL); // 0x11 + CASE_RETURN_STR(IRP_MJ_CLEANUP); // 0x12 + CASE_RETURN_STR(IRP_MJ_CREATE_MAILSLOT); // 0x13 + CASE_RETURN_STR(IRP_MJ_QUERY_SECURITY); // 0x14 + CASE_RETURN_STR(IRP_MJ_SET_SECURITY); // 0x15 + CASE_RETURN_STR(IRP_MJ_POWER); // 0x16 + CASE_RETURN_STR(IRP_MJ_SYSTEM_CONTROL); // 0x17 + CASE_RETURN_STR(IRP_MJ_DEVICE_CHANGE); // 0x18 + CASE_RETURN_STR(IRP_MJ_QUERY_QUOTA); // 0x19 + CASE_RETURN_STR(IRP_MJ_SET_QUOTA); // 0x1a + CASE_RETURN_STR(IRP_MJ_PNP); // 0x1b + default: + functionName[sizeof(functionName) - 1] = '\0'; + _snprintf(functionName, sizeof(functionName) - 1, + // sprintf(functionName, + "Unknown Major Function (0x%x)", major_code); + return functionName; + } +} + +#ifdef VFD_PNP + +// +// Return PnP IRP Minor Function Name +// +PCSTR +GetPnpIrpName(ULONG minor_code) +{ + static char functionName[80]; + + switch (minor_code) { + CASE_RETURN_STR(IRP_MN_START_DEVICE); // 0x00 + CASE_RETURN_STR(IRP_MN_QUERY_REMOVE_DEVICE); // 0x01 + CASE_RETURN_STR(IRP_MN_REMOVE_DEVICE); // 0x02 + CASE_RETURN_STR(IRP_MN_CANCEL_REMOVE_DEVICE); // 0x03 + CASE_RETURN_STR(IRP_MN_STOP_DEVICE); // 0x04 + CASE_RETURN_STR(IRP_MN_QUERY_STOP_DEVICE); // 0x05 + CASE_RETURN_STR(IRP_MN_CANCEL_STOP_DEVICE); // 0x06 + CASE_RETURN_STR(IRP_MN_QUERY_DEVICE_RELATIONS); // 0x07 + CASE_RETURN_STR(IRP_MN_QUERY_INTERFACE); // 0x08 + CASE_RETURN_STR(IRP_MN_QUERY_CAPABILITIES); // 0x09 + CASE_RETURN_STR(IRP_MN_QUERY_RESOURCES); // 0x0A + CASE_RETURN_STR(IRP_MN_QUERY_RESOURCE_REQUIREMENTS); // 0x0B + CASE_RETURN_STR(IRP_MN_QUERY_DEVICE_TEXT); // 0x0C + CASE_RETURN_STR(IRP_MN_FILTER_RESOURCE_REQUIREMENTS); // 0x0D + CASE_RETURN_STR(IRP_MN_READ_CONFIG); // 0x0F + CASE_RETURN_STR(IRP_MN_WRITE_CONFIG); // 0x10 + CASE_RETURN_STR(IRP_MN_EJECT); // 0x11 + CASE_RETURN_STR(IRP_MN_SET_LOCK); // 0x12 + CASE_RETURN_STR(IRP_MN_QUERY_ID); // 0x13 + CASE_RETURN_STR(IRP_MN_QUERY_PNP_DEVICE_STATE); // 0x14 + CASE_RETURN_STR(IRP_MN_QUERY_BUS_INFORMATION); // 0x15 + CASE_RETURN_STR(IRP_MN_DEVICE_USAGE_NOTIFICATION); // 0x16 + CASE_RETURN_STR(IRP_MN_SURPRISE_REMOVAL); // 0x17 + CASE_RETURN_STR(IRP_MN_QUERY_LEGACY_BUS_INFORMATION); // 0x18 + default: + functionName[sizeof(functionName) - 1] = '\0'; + _snprintf(functionName, sizeof(functionName) - 1, + // sprintf(functionName, + "Unknown PNP IRP (0x%x)", minor_code); + return functionName; + } +} + +// +// Return Power IRP Minor Function Name +// +PCSTR +GetPowerIrpName(ULONG minor_code) +{ + static char functionName[80]; + + switch (minor_code) { + CASE_RETURN_STR(IRP_MN_SET_POWER); + CASE_RETURN_STR(IRP_MN_QUERY_POWER); + CASE_RETURN_STR(IRP_MN_WAIT_WAKE); + CASE_RETURN_STR(IRP_MN_POWER_SEQUENCE); + default: + functionName[sizeof(functionName) - 1] = '\0'; + _snprintf(functionName, sizeof(functionName) - 1, + // sprintf(functionName, + "Unknown Power IRP (0x%x)", minor_code); + return functionName; + } +} + +// +// Return System IRP Minor Function Name +// +PCSTR +GetSystemIrpName(ULONG minor_code) +{ + static char functionName[80]; + + switch (minor_code) { + CASE_RETURN_STR(IRP_MN_QUERY_ALL_DATA); // 0x00 + CASE_RETURN_STR(IRP_MN_QUERY_SINGLE_INSTANCE); // 0x01 + CASE_RETURN_STR(IRP_MN_CHANGE_SINGLE_INSTANCE); // 0x02 + CASE_RETURN_STR(IRP_MN_CHANGE_SINGLE_ITEM); // 0x03 + CASE_RETURN_STR(IRP_MN_ENABLE_EVENTS); // 0x04 + CASE_RETURN_STR(IRP_MN_DISABLE_EVENTS); // 0x05 + CASE_RETURN_STR(IRP_MN_ENABLE_COLLECTION); // 0x06 + CASE_RETURN_STR(IRP_MN_DISABLE_COLLECTION); // 0x07 + CASE_RETURN_STR(IRP_MN_REGINFO); // 0x08 + CASE_RETURN_STR(IRP_MN_EXECUTE_METHOD); // 0x09 + default: + functionName[sizeof(functionName) - 1] = '\0'; + _snprintf(functionName, sizeof(functionName) - 1, + // sprintf(functionName, + "Unknown System IRP (0x%x)", minor_code); + return functionName; + } +} + +#endif // VFD_PNP + + +#include +#ifndef __REACTOS__ +#include +#endif +#include + +#if (VER_PRODUCTBUILD < 2195) +// +// imports from Win2K DDK +// + +// mountmgr.h + +#define MOUNTMGRCONTROLTYPE ((ULONG) 'm') +#define MOUNTDEVCONTROLTYPE ((ULONG) 'M') +/* +#define IOCTL_MOUNTMGR_CREATE_POINT \ + CTL_CODE(MOUNTMGRCONTROLTYPE, 0, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_MOUNTMGR_DELETE_POINTS \ + CTL_CODE(MOUNTMGRCONTROLTYPE, 1, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +*/ +#define IOCTL_MOUNTMGR_QUERY_POINTS \ + CTL_CODE(MOUNTMGRCONTROLTYPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_MOUNTMGR_DELETE_POINTS_DBONLY \ + CTL_CODE(MOUNTMGRCONTROLTYPE, 3, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER \ + CTL_CODE(MOUNTMGRCONTROLTYPE, 4, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_MOUNTMGR_AUTO_DL_ASSIGNMENTS \ + CTL_CODE(MOUNTMGRCONTROLTYPE, 5, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED \ + CTL_CODE(MOUNTMGRCONTROLTYPE, 6, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED \ + CTL_CODE(MOUNTMGRCONTROLTYPE, 7, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_MOUNTMGR_CHANGE_NOTIFY \ + CTL_CODE(MOUNTMGRCONTROLTYPE, 8, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_MOUNTMGR_KEEP_LINKS_WHEN_OFFLINE \ + CTL_CODE(MOUNTMGRCONTROLTYPE, 9, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_MOUNTMGR_CHECK_UNPROCESSED_VOLUMES \ + CTL_CODE(MOUNTMGRCONTROLTYPE, 10, METHOD_BUFFERED, FILE_READ_ACCESS) +/* +#define IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION \ + CTL_CODE(MOUNTMGRCONTROLTYPE, 11, METHOD_BUFFERED, FILE_READ_ACCESS) +*/ + +// mountdev.h +/* +#define IOCTL_MOUNTDEV_QUERY_UNIQUE_ID \ + CTL_CODE(MOUNTDEVCONTROLTYPE, 0, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY \ + CTL_CODE(MOUNTDEVCONTROLTYPE, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME \ + CTL_CODE(MOUNTDEVCONTROLTYPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME \ + CTL_CODE(MOUNTDEVCONTROLTYPE, 3, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_MOUNTDEV_LINK_CREATED \ + CTL_CODE(MOUNTDEVCONTROLTYPE, 4, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_MOUNTDEV_LINK_DELETED \ + CTL_CODE(MOUNTDEVCONTROLTYPE, 5, METHOD_BUFFERED, FILE_ANY_ACCESS) +*/ + +// ntdddisk.h +#define IOCTL_DISK_UPDATE_DRIVE_SIZE \ + CTL_CODE(IOCTL_DISK_BASE, 0x0032, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_DISK_GROW_PARTITION \ + CTL_CODE(IOCTL_DISK_BASE, 0x0034, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_DISK_GET_CACHE_INFORMATION \ + CTL_CODE(IOCTL_DISK_BASE, 0x0035, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_DISK_SET_CACHE_INFORMATION \ + CTL_CODE(IOCTL_DISK_BASE, 0x0036, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_DISK_DELETE_DRIVE_LAYOUT \ + CTL_CODE(IOCTL_DISK_BASE, 0x0040, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_DISK_FORMAT_DRIVE \ + CTL_CODE(IOCTL_DISK_BASE, 0x00f3, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_DISK_SENSE_DEVICE \ + CTL_CODE(IOCTL_DISK_BASE, 0x00f8, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_DISK_INTERNAL_SET_NOTIFY \ + CTL_CODE(IOCTL_DISK_BASE, 0x0102, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// ntddft.h +#define FT_SECONDARY_READ_ALT \ + CTL_CODE(FTTYPE, 4, METHOD_OUT_DIRECT, FILE_READ_ACCESS) +#define FT_PRIMARY_READ_ALT \ + CTL_CODE(FTTYPE, 5, METHOD_OUT_DIRECT, FILE_READ_ACCESS) +#define FT_CLUSTER_SET_MEMBER_STATE \ + CTL_CODE(FTTYPE,11, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FT_CLUSTER_GET_MEMBER_STATE \ + CTL_CODE(FTTYPE,12, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// ntddstor.h +#define IOCTL_STORAGE_LOAD_MEDIA2 \ + CTL_CODE(IOCTL_STORAGE_BASE, 0x0203, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_EJECTION_CONTROL \ + CTL_CODE(IOCTL_STORAGE_BASE, 0x0250, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_MCN_CONTROL \ + CTL_CODE(IOCTL_STORAGE_BASE, 0x0251, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_GET_MEDIA_TYPES_EX \ + CTL_CODE(IOCTL_STORAGE_BASE, 0x0301, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_RESET_BUS \ + CTL_CODE(IOCTL_STORAGE_BASE, 0x0400, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_RESET_DEVICE \ + CTL_CODE(IOCTL_STORAGE_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_STORAGE_GET_DEVICE_NUMBER \ + CTL_CODE(IOCTL_STORAGE_BASE, 0x0420, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_PREDICT_FAILURE \ + CTL_CODE(IOCTL_STORAGE_BASE, 0x0440, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_STORAGE_QUERY_PROPERTY \ + CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define OBSOLETE_IOCTL_STORAGE_RESET_BUS \ + CTL_CODE(IOCTL_STORAGE_BASE, 0x0400, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define OBSOLETE_IOCTL_STORAGE_RESET_DEVICE \ + CTL_CODE(IOCTL_STORAGE_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +// ntddft2.h +#define FTCONTROLTYPE ((ULONG) 'g') +#define FT_CREATE_LOGICAL_DISK \ + CTL_CODE(FTCONTROLTYPE, 0, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define FT_BREAK_LOGICAL_DISK \ + CTL_CODE(FTCONTROLTYPE, 1, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define FT_ENUMERATE_LOGICAL_DISKS \ + CTL_CODE(FTCONTROLTYPE, 2, METHOD_BUFFERED, FILE_READ_ACCESS) +#define FT_QUERY_LOGICAL_DISK_INFORMATION \ + CTL_CODE(FTCONTROLTYPE, 3, METHOD_BUFFERED, FILE_READ_ACCESS) +#define FT_ORPHAN_LOGICAL_DISK_MEMBER \ + CTL_CODE(FTCONTROLTYPE, 4, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define FT_REPLACE_LOGICAL_DISK_MEMBER \ + CTL_CODE(FTCONTROLTYPE, 5, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define FT_QUERY_NT_DEVICE_NAME_FOR_LOGICAL_DISK \ + CTL_CODE(FTCONTROLTYPE, 6, METHOD_BUFFERED, FILE_READ_ACCESS) +#define FT_INITIALIZE_LOGICAL_DISK \ + CTL_CODE(FTCONTROLTYPE, 7, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define FT_QUERY_DRIVE_LETTER_FOR_LOGICAL_DISK \ + CTL_CODE(FTCONTROLTYPE, 8, METHOD_BUFFERED, FILE_READ_ACCESS) +#define FT_CHECK_IO \ + CTL_CODE(FTCONTROLTYPE, 9, METHOD_BUFFERED, FILE_READ_ACCESS) +#define FT_SET_DRIVE_LETTER_FOR_LOGICAL_DISK \ + CTL_CODE(FTCONTROLTYPE, 10, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define FT_QUERY_NT_DEVICE_NAME_FOR_PARTITION \ + CTL_CODE(FTCONTROLTYPE, 12, METHOD_BUFFERED, FILE_READ_ACCESS) +#define FT_CHANGE_NOTIFY \ + CTL_CODE(FTCONTROLTYPE, 13, METHOD_BUFFERED, FILE_READ_ACCESS) +#define FT_STOP_SYNC_OPERATIONS \ + CTL_CODE(FTCONTROLTYPE, 14, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define FT_QUERY_LOGICAL_DISK_ID \ + CTL_CODE(FTCONTROLTYPE, 100, METHOD_BUFFERED, FILE_READ_ACCESS) +#define FT_CREATE_PARTITION_LOGICAL_DISK \ + CTL_CODE(FTCONTROLTYPE, 101, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +// ntddvol.h +#define IOCTL_VOLUME_BASE ((ULONG) 'V') +#define IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS \ + CTL_CODE(IOCTL_VOLUME_BASE, 0, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VOLUME_SUPPORTS_ONLINE_OFFLINE \ + CTL_CODE(IOCTL_VOLUME_BASE, 1, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VOLUME_ONLINE \ + CTL_CODE(IOCTL_VOLUME_BASE, 2, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_VOLUME_OFFLINE \ + CTL_CODE(IOCTL_VOLUME_BASE, 3, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_VOLUME_IS_OFFLINE \ + CTL_CODE(IOCTL_VOLUME_BASE, 4, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VOLUME_IS_IO_CAPABLE \ + CTL_CODE(IOCTL_VOLUME_BASE, 5, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VOLUME_QUERY_FAILOVER_SET \ + CTL_CODE(IOCTL_VOLUME_BASE, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VOLUME_QUERY_VOLUME_NUMBER \ + CTL_CODE(IOCTL_VOLUME_BASE, 7, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VOLUME_LOGICAL_TO_PHYSICAL \ + CTL_CODE(IOCTL_VOLUME_BASE, 8, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VOLUME_PHYSICAL_TO_LOGICAL \ + CTL_CODE(IOCTL_VOLUME_BASE, 9, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#else // (VER_PRODUCTBUILD < 2195) + +#include +#include +#ifndef __REACTOS__ +#include +#endif +#include + +#define FT_SECONDARY_READ_ALT \ + CTL_CODE(FTTYPE, 4, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) +#define FT_PRIMARY_READ_ALT \ + CTL_CODE(FTTYPE, 5, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) + +#endif // (VER_PRODUCTBUILD < 2195) + +#if (VER_PRODUCTBUILD < 2600) +// +// imports from WinXP DDK +// + +// mountmgr.h +#define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH \ + CTL_CODE(MOUNTMGRCONTROLTYPE, 12, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATHS \ + CTL_CODE(MOUNTMGRCONTROLTYPE, 13, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// mountdev.h +/* +#define IOCTL_MOUNTDEV_QUERY_STABLE_GUID \ + CTL_CODE(MOUNTDEVCONTROLTYPE, 6, METHOD_BUFFERED, FILE_ANY_ACCESS) +*/ + +// ntdddisk.h +#define IOCTL_DISK_PERFORMANCE_OFF \ + CTL_CODE(IOCTL_DISK_BASE, 0x0018, METHOD_BUFFERED, FILE_ANY_ACCESS) +/* +#define IOCTL_DISK_GET_PARTITION_INFO_EX \ + CTL_CODE(IOCTL_DISK_BASE, 0x0012, METHOD_BUFFERED, FILE_ANY_ACCESS) +*/ +#define IOCTL_DISK_SET_PARTITION_INFO_EX \ + CTL_CODE(IOCTL_DISK_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_DISK_GET_DRIVE_LAYOUT_EX \ + CTL_CODE(IOCTL_DISK_BASE, 0x0014, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_DISK_SET_DRIVE_LAYOUT_EX \ + CTL_CODE(IOCTL_DISK_BASE, 0x0015, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_DISK_CREATE_DISK \ + CTL_CODE(IOCTL_DISK_BASE, 0x0016, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +/* +#define IOCTL_DISK_GET_LENGTH_INFO \ + CTL_CODE(IOCTL_DISK_BASE, 0x0017, METHOD_BUFFERED, FILE_READ_ACCESS) +*/ +#define IOCTL_DISK_GET_DRIVE_GEOMETRY_EX \ + CTL_CODE(IOCTL_DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_DISK_GET_WRITE_CACHE_STATE \ + CTL_CODE(IOCTL_DISK_BASE, 0x0037, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_DISK_UPDATE_PROPERTIES \ + CTL_CODE(IOCTL_DISK_BASE, 0x0050, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// ntddstor.h +#define IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER \ + CTL_CODE(IOCTL_STORAGE_BASE, 0x0304, METHOD_BUFFERED, FILE_ANY_ACCESS) +/* +#define IOCTL_STORAGE_GET_HOTPLUG_INFO \ + CTL_CODE(IOCTL_STORAGE_BASE, 0x0305, METHOD_BUFFERED, FILE_ANY_ACCESS) +*/ +#define IOCTL_STORAGE_SET_HOTPLUG_INFO \ + CTL_CODE(IOCTL_STORAGE_BASE, 0x0306, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_STORAGE_BREAK_RESERVATION \ + CTL_CODE(IOCTL_STORAGE_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS) + +// ntddvol.h +#define IOCTL_VOLUME_IS_PARTITION \ + CTL_CODE(IOCTL_VOLUME_BASE, 10, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VOLUME_READ_PLEX \ + CTL_CODE(IOCTL_VOLUME_BASE, 11, METHOD_OUT_DIRECT, FILE_READ_ACCESS) +#define IOCTL_VOLUME_IS_CLUSTERED \ + CTL_CODE(IOCTL_VOLUME_BASE, 12, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VOLUME_SET_GPT_ATTRIBUTES \ + CTL_CODE(IOCTL_VOLUME_BASE, 13, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_VOLUME_GET_GPT_ATTRIBUTES \ + CTL_CODE(IOCTL_VOLUME_BASE, 14, METHOD_BUFFERED, FILE_ANY_ACCESS) + +#endif // (VER_PRODUCTBUILD < 2600) + +PCSTR +GetIoControlName( + ULONG ctrl_code) +{ + static CHAR buf[20]; + + switch (ctrl_code) { + // + // VFD control codes + // + CASE_RETURN_STR(IOCTL_VFD_OPEN_IMAGE); + CASE_RETURN_STR(IOCTL_VFD_CLOSE_IMAGE); + CASE_RETURN_STR(IOCTL_VFD_QUERY_IMAGE); + CASE_RETURN_STR(IOCTL_VFD_SET_LINK); + CASE_RETURN_STR(IOCTL_VFD_QUERY_LINK); + CASE_RETURN_STR(IOCTL_VFD_SET_PROTECT); + CASE_RETURN_STR(IOCTL_VFD_CLEAR_PROTECT); + CASE_RETURN_STR(IOCTL_VFD_RESET_MODIFY); + CASE_RETURN_STR(IOCTL_VFD_QUERY_NUMBER); + CASE_RETURN_STR(IOCTL_VFD_QUERY_NAME); + CASE_RETURN_STR(IOCTL_VFD_QUERY_VERSION); + + // + // Standard control codes + // + // mountmgr.h + CASE_RETURN_STR(IOCTL_MOUNTMGR_CREATE_POINT); + CASE_RETURN_STR(IOCTL_MOUNTMGR_DELETE_POINTS); + CASE_RETURN_STR(IOCTL_MOUNTMGR_QUERY_POINTS); + CASE_RETURN_STR(IOCTL_MOUNTMGR_DELETE_POINTS_DBONLY); + CASE_RETURN_STR(IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER); + CASE_RETURN_STR(IOCTL_MOUNTMGR_AUTO_DL_ASSIGNMENTS); + CASE_RETURN_STR(IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED); + CASE_RETURN_STR(IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED); + CASE_RETURN_STR(IOCTL_MOUNTMGR_CHANGE_NOTIFY); + CASE_RETURN_STR(IOCTL_MOUNTMGR_KEEP_LINKS_WHEN_OFFLINE); + CASE_RETURN_STR(IOCTL_MOUNTMGR_CHECK_UNPROCESSED_VOLUMES); + CASE_RETURN_STR(IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION); + CASE_RETURN_STR(IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH); + CASE_RETURN_STR(IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATHS); + CASE_RETURN_STR(IOCTL_MOUNTDEV_QUERY_DEVICE_NAME); + + // mountdev.h + CASE_RETURN_STR(IOCTL_MOUNTDEV_QUERY_UNIQUE_ID); + CASE_RETURN_STR(IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY); + CASE_RETURN_STR(IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME); + CASE_RETURN_STR(IOCTL_MOUNTDEV_LINK_CREATED); + CASE_RETURN_STR(IOCTL_MOUNTDEV_LINK_DELETED); + CASE_RETURN_STR(IOCTL_MOUNTDEV_QUERY_STABLE_GUID); + + // ntdddisk.h + CASE_RETURN_STR(IOCTL_DISK_GET_DRIVE_GEOMETRY); + CASE_RETURN_STR(IOCTL_DISK_GET_PARTITION_INFO); + CASE_RETURN_STR(IOCTL_DISK_SET_PARTITION_INFO); + CASE_RETURN_STR(IOCTL_DISK_GET_DRIVE_LAYOUT); + CASE_RETURN_STR(IOCTL_DISK_SET_DRIVE_LAYOUT); + CASE_RETURN_STR(IOCTL_DISK_VERIFY); + CASE_RETURN_STR(IOCTL_DISK_FORMAT_TRACKS); + CASE_RETURN_STR(IOCTL_DISK_REASSIGN_BLOCKS); + CASE_RETURN_STR(IOCTL_DISK_PERFORMANCE); + CASE_RETURN_STR(IOCTL_DISK_IS_WRITABLE); + CASE_RETURN_STR(IOCTL_DISK_LOGGING); + CASE_RETURN_STR(IOCTL_DISK_FORMAT_TRACKS_EX); + CASE_RETURN_STR(IOCTL_DISK_HISTOGRAM_STRUCTURE); + CASE_RETURN_STR(IOCTL_DISK_HISTOGRAM_DATA); + CASE_RETURN_STR(IOCTL_DISK_HISTOGRAM_RESET); + CASE_RETURN_STR(IOCTL_DISK_REQUEST_STRUCTURE); + CASE_RETURN_STR(IOCTL_DISK_REQUEST_DATA); + CASE_RETURN_STR(IOCTL_DISK_PERFORMANCE_OFF); + CASE_RETURN_STR(IOCTL_DISK_CONTROLLER_NUMBER); + CASE_RETURN_STR(SMART_GET_VERSION); + CASE_RETURN_STR(SMART_SEND_DRIVE_COMMAND); + CASE_RETURN_STR(SMART_RCV_DRIVE_DATA); + CASE_RETURN_STR(IOCTL_DISK_GET_PARTITION_INFO_EX); + CASE_RETURN_STR(IOCTL_DISK_SET_PARTITION_INFO_EX); + CASE_RETURN_STR(IOCTL_DISK_GET_DRIVE_LAYOUT_EX); + CASE_RETURN_STR(IOCTL_DISK_SET_DRIVE_LAYOUT_EX); + CASE_RETURN_STR(IOCTL_DISK_CREATE_DISK); + CASE_RETURN_STR(IOCTL_DISK_GET_LENGTH_INFO); + CASE_RETURN_STR(IOCTL_DISK_GET_DRIVE_GEOMETRY_EX); + CASE_RETURN_STR(IOCTL_DISK_UPDATE_DRIVE_SIZE); + CASE_RETURN_STR(IOCTL_DISK_GROW_PARTITION); + CASE_RETURN_STR(IOCTL_DISK_GET_CACHE_INFORMATION); + CASE_RETURN_STR(IOCTL_DISK_SET_CACHE_INFORMATION); +#if (NTDDI_VERSION < NTDDI_WS03) + CASE_RETURN_STR(IOCTL_DISK_GET_WRITE_CACHE_STATE); +#else + CASE_RETURN_STR(OBSOLETE_DISK_GET_WRITE_CACHE_STATE); +#endif + CASE_RETURN_STR(IOCTL_DISK_DELETE_DRIVE_LAYOUT); + CASE_RETURN_STR(IOCTL_DISK_UPDATE_PROPERTIES); + CASE_RETURN_STR(IOCTL_DISK_FORMAT_DRIVE); + CASE_RETURN_STR(IOCTL_DISK_SENSE_DEVICE); + CASE_RETURN_STR(IOCTL_DISK_INTERNAL_SET_VERIFY); + CASE_RETURN_STR(IOCTL_DISK_INTERNAL_CLEAR_VERIFY); + CASE_RETURN_STR(IOCTL_DISK_INTERNAL_SET_NOTIFY); + CASE_RETURN_STR(IOCTL_DISK_CHECK_VERIFY); + CASE_RETURN_STR(IOCTL_DISK_MEDIA_REMOVAL); + CASE_RETURN_STR(IOCTL_DISK_EJECT_MEDIA); + CASE_RETURN_STR(IOCTL_DISK_LOAD_MEDIA); + CASE_RETURN_STR(IOCTL_DISK_RESERVE); + CASE_RETURN_STR(IOCTL_DISK_RELEASE); + CASE_RETURN_STR(IOCTL_DISK_FIND_NEW_DEVICES); + CASE_RETURN_STR(IOCTL_DISK_GET_MEDIA_TYPES); + CASE_RETURN_STR(IOCTL_DISK_SIMBAD); + +#ifndef __REACTOS__ + // ntddft.h + CASE_RETURN_STR(FT_INITIALIZE_SET); + CASE_RETURN_STR(FT_REGENERATE); + CASE_RETURN_STR(FT_CONFIGURE); + CASE_RETURN_STR(FT_VERIFY); + CASE_RETURN_STR(FT_SECONDARY_READ); + CASE_RETURN_STR(FT_PRIMARY_READ); + CASE_RETURN_STR(FT_BALANCED_READ_MODE); + CASE_RETURN_STR(FT_SYNC_REDUNDANT_COPY); + CASE_RETURN_STR(FT_SEQUENTIAL_WRITE_MODE); + CASE_RETURN_STR(FT_PARALLEL_WRITE_MODE); + CASE_RETURN_STR(FT_QUERY_SET_STATE); + CASE_RETURN_STR(FT_CLUSTER_SET_MEMBER_STATE); + CASE_RETURN_STR(FT_CLUSTER_GET_MEMBER_STATE); + + // ntddft2.h + CASE_RETURN_STR(FT_CREATE_LOGICAL_DISK); + CASE_RETURN_STR(FT_BREAK_LOGICAL_DISK); + CASE_RETURN_STR(FT_ENUMERATE_LOGICAL_DISKS); + CASE_RETURN_STR(FT_QUERY_LOGICAL_DISK_INFORMATION); + CASE_RETURN_STR(FT_ORPHAN_LOGICAL_DISK_MEMBER); + CASE_RETURN_STR(FT_REPLACE_LOGICAL_DISK_MEMBER); + CASE_RETURN_STR(FT_QUERY_NT_DEVICE_NAME_FOR_LOGICAL_DISK); + CASE_RETURN_STR(FT_INITIALIZE_LOGICAL_DISK); + CASE_RETURN_STR(FT_QUERY_DRIVE_LETTER_FOR_LOGICAL_DISK); + CASE_RETURN_STR(FT_CHECK_IO); + CASE_RETURN_STR(FT_SET_DRIVE_LETTER_FOR_LOGICAL_DISK); + CASE_RETURN_STR(FT_QUERY_NT_DEVICE_NAME_FOR_PARTITION); + CASE_RETURN_STR(FT_CHANGE_NOTIFY); + CASE_RETURN_STR(FT_STOP_SYNC_OPERATIONS); + CASE_RETURN_STR(FT_QUERY_LOGICAL_DISK_ID); + CASE_RETURN_STR(FT_CREATE_PARTITION_LOGICAL_DISK); +#endif + + // ntddstor.h + CASE_RETURN_STR(IOCTL_STORAGE_CHECK_VERIFY); + CASE_RETURN_STR(IOCTL_STORAGE_CHECK_VERIFY2); + CASE_RETURN_STR(IOCTL_STORAGE_MEDIA_REMOVAL); + CASE_RETURN_STR(IOCTL_STORAGE_EJECT_MEDIA); + CASE_RETURN_STR(IOCTL_STORAGE_LOAD_MEDIA); + CASE_RETURN_STR(IOCTL_STORAGE_LOAD_MEDIA2); + CASE_RETURN_STR(IOCTL_STORAGE_RESERVE); + CASE_RETURN_STR(IOCTL_STORAGE_RELEASE); + CASE_RETURN_STR(IOCTL_STORAGE_FIND_NEW_DEVICES); + CASE_RETURN_STR(IOCTL_STORAGE_EJECTION_CONTROL); + CASE_RETURN_STR(IOCTL_STORAGE_MCN_CONTROL); + CASE_RETURN_STR(IOCTL_STORAGE_GET_MEDIA_TYPES); + CASE_RETURN_STR(IOCTL_STORAGE_GET_MEDIA_TYPES_EX); + CASE_RETURN_STR(IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER); + CASE_RETURN_STR(IOCTL_STORAGE_GET_HOTPLUG_INFO); + CASE_RETURN_STR(IOCTL_STORAGE_SET_HOTPLUG_INFO); + CASE_RETURN_STR(IOCTL_STORAGE_RESET_BUS); + CASE_RETURN_STR(IOCTL_STORAGE_RESET_DEVICE); + CASE_RETURN_STR(IOCTL_STORAGE_BREAK_RESERVATION); + CASE_RETURN_STR(IOCTL_STORAGE_GET_DEVICE_NUMBER); + CASE_RETURN_STR(IOCTL_STORAGE_PREDICT_FAILURE); + CASE_RETURN_STR(IOCTL_STORAGE_QUERY_PROPERTY); + CASE_RETURN_STR(OBSOLETE_IOCTL_STORAGE_RESET_BUS); + CASE_RETURN_STR(OBSOLETE_IOCTL_STORAGE_RESET_DEVICE); + + // ntddvol.h + CASE_RETURN_STR(IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS); + CASE_RETURN_STR(IOCTL_VOLUME_IS_CLUSTERED); + CASE_RETURN_STR(IOCTL_VOLUME_SUPPORTS_ONLINE_OFFLINE); + CASE_RETURN_STR(IOCTL_VOLUME_ONLINE); + CASE_RETURN_STR(IOCTL_VOLUME_OFFLINE); + CASE_RETURN_STR(IOCTL_VOLUME_IS_OFFLINE); + CASE_RETURN_STR(IOCTL_VOLUME_IS_IO_CAPABLE); + CASE_RETURN_STR(IOCTL_VOLUME_QUERY_FAILOVER_SET); + CASE_RETURN_STR(IOCTL_VOLUME_QUERY_VOLUME_NUMBER); + CASE_RETURN_STR(IOCTL_VOLUME_LOGICAL_TO_PHYSICAL); + CASE_RETURN_STR(IOCTL_VOLUME_PHYSICAL_TO_LOGICAL); + CASE_RETURN_STR(IOCTL_VOLUME_IS_PARTITION); + CASE_RETURN_STR(IOCTL_VOLUME_READ_PLEX); + CASE_RETURN_STR(IOCTL_VOLUME_SET_GPT_ATTRIBUTES); + CASE_RETURN_STR(IOCTL_VOLUME_GET_GPT_ATTRIBUTES); + + default: + buf[sizeof(buf) - 1] = '\0'; + _snprintf(buf, sizeof(buf) - 1, + // sprintf(buf, + "Unknown IOCTL: 0x%08x", ctrl_code); + return buf; + } +} + +#if (VER_PRODUCTBUILD < 2195) +// +// from new +// +#define FACILITY_USB_ERROR_CODE 0x10 +#define FACILITY_TERMINAL_SERVER 0xA +#define FACILITY_HID_ERROR_CODE 0x11 +#define FACILITY_FIREWIRE_ERROR_CODE 0x12 +#define FACILITY_DEBUGGER 0x1 +#define FACILITY_CLUSTER_ERROR_CODE 0x13 +#define FACILITY_ACPI_ERROR_CODE 0x14 +#define STATUS_RESOURCE_REQUIREMENTS_CHANGED ((NTSTATUS)0x00000119L) +#define STATUS_TRANSLATION_COMPLETE ((NTSTATUS)0x00000120L) +#define STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY ((NTSTATUS)0x00000121L) +#define DBG_EXCEPTION_HANDLED ((NTSTATUS)0x00010001L) +#define DBG_CONTINUE ((NTSTATUS)0x00010002L) +#define STATUS_ARBITRATION_UNHANDLED ((NTSTATUS)0x40000026L) +#define STATUS_CARDBUS_NOT_SUPPORTED ((NTSTATUS)0x40000027L) +#define STATUS_WX86_CREATEWX86TIB ((NTSTATUS)0x40000028L) +#define STATUS_MP_PROCESSOR_MISMATCH ((NTSTATUS)0x40000029L) +#define DBG_REPLY_LATER ((NTSTATUS)0x40010001L) +#define DBG_UNABLE_TO_PROVIDE_HANDLE ((NTSTATUS)0x40010002L) +#define DBG_TERMINATE_THREAD ((NTSTATUS)0x40010003L) +#define DBG_TERMINATE_PROCESS ((NTSTATUS)0x40010004L) +#define DBG_CONTROL_C ((NTSTATUS)0x40010005L) +#define DBG_PRINTEXCEPTION_C ((NTSTATUS)0x40010006L) +#define DBG_RIPEXCEPTION ((NTSTATUS)0x40010007L) +#define DBG_CONTROL_BREAK ((NTSTATUS)0x40010008L) +#define DBG_EXCEPTION_NOT_HANDLED ((NTSTATUS)0x80010001L) +#define STATUS_VALIDATE_CONTINUE ((NTSTATUS)0xC0000271L) +#define STATUS_NO_MATCH ((NTSTATUS)0xC0000272L) +#define STATUS_NO_MORE_MATCHES ((NTSTATUS)0xC0000273L) +#define STATUS_NOT_A_REPARSE_POINT ((NTSTATUS)0xC0000275L) +#define STATUS_IO_REPARSE_TAG_INVALID ((NTSTATUS)0xC0000276L) +#define STATUS_IO_REPARSE_TAG_MISMATCH ((NTSTATUS)0xC0000277L) +#define STATUS_IO_REPARSE_DATA_INVALID ((NTSTATUS)0xC0000278L) +#define STATUS_IO_REPARSE_TAG_NOT_HANDLED ((NTSTATUS)0xC0000279L) +#define STATUS_REPARSE_POINT_NOT_RESOLVED ((NTSTATUS)0xC0000280L) +#define STATUS_DIRECTORY_IS_A_REPARSE_POINT ((NTSTATUS)0xC0000281L) +#define STATUS_RANGE_LIST_CONFLICT ((NTSTATUS)0xC0000282L) +#define STATUS_SOURCE_ELEMENT_EMPTY ((NTSTATUS)0xC0000283L) +#define STATUS_DESTINATION_ELEMENT_FULL ((NTSTATUS)0xC0000284L) +#define STATUS_ILLEGAL_ELEMENT_ADDRESS ((NTSTATUS)0xC0000285L) +#define STATUS_MAGAZINE_NOT_PRESENT ((NTSTATUS)0xC0000286L) +#define STATUS_REINITIALIZATION_NEEDED ((NTSTATUS)0xC0000287L) +#define STATUS_DEVICE_REQUIRES_CLEANING ((NTSTATUS)0x80000288L) +#define STATUS_DEVICE_DOOR_OPEN ((NTSTATUS)0x80000289L) +#define STATUS_ENCRYPTION_FAILED ((NTSTATUS)0xC000028AL) +#define STATUS_DECRYPTION_FAILED ((NTSTATUS)0xC000028BL) +#define STATUS_RANGE_NOT_FOUND ((NTSTATUS)0xC000028CL) +#define STATUS_NO_RECOVERY_POLICY ((NTSTATUS)0xC000028DL) +#define STATUS_NO_EFS ((NTSTATUS)0xC000028EL) +#define STATUS_WRONG_EFS ((NTSTATUS)0xC000028FL) +#define STATUS_NO_USER_KEYS ((NTSTATUS)0xC0000290L) +#define STATUS_FILE_NOT_ENCRYPTED ((NTSTATUS)0xC0000291L) +#define STATUS_NOT_EXPORT_FORMAT ((NTSTATUS)0xC0000292L) +#define STATUS_FILE_ENCRYPTED ((NTSTATUS)0xC0000293L) +#define STATUS_WAKE_SYSTEM ((NTSTATUS)0x40000294L) +#define STATUS_WMI_GUID_NOT_FOUND ((NTSTATUS)0xC0000295L) +#define STATUS_WMI_INSTANCE_NOT_FOUND ((NTSTATUS)0xC0000296L) +#define STATUS_WMI_ITEMID_NOT_FOUND ((NTSTATUS)0xC0000297L) +#define STATUS_WMI_TRY_AGAIN ((NTSTATUS)0xC0000298L) +#define STATUS_SHARED_POLICY ((NTSTATUS)0xC0000299L) +#define STATUS_POLICY_OBJECT_NOT_FOUND ((NTSTATUS)0xC000029AL) +#define STATUS_POLICY_ONLY_IN_DS ((NTSTATUS)0xC000029BL) +#define STATUS_VOLUME_NOT_UPGRADED ((NTSTATUS)0xC000029CL) +#define STATUS_REMOTE_STORAGE_NOT_ACTIVE ((NTSTATUS)0xC000029DL) +#define STATUS_REMOTE_STORAGE_MEDIA_ERROR ((NTSTATUS)0xC000029EL) +#define STATUS_NO_TRACKING_SERVICE ((NTSTATUS)0xC000029FL) +#define STATUS_SERVER_SID_MISMATCH ((NTSTATUS)0xC00002A0L) +#define STATUS_DS_NO_ATTRIBUTE_OR_VALUE ((NTSTATUS)0xC00002A1L) +#define STATUS_DS_INVALID_ATTRIBUTE_SYNTAX ((NTSTATUS)0xC00002A2L) +#define STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED ((NTSTATUS)0xC00002A3L) +#define STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS ((NTSTATUS)0xC00002A4L) +#define STATUS_DS_BUSY ((NTSTATUS)0xC00002A5L) +#define STATUS_DS_UNAVAILABLE ((NTSTATUS)0xC00002A6L) +#define STATUS_DS_NO_RIDS_ALLOCATED ((NTSTATUS)0xC00002A7L) +#define STATUS_DS_NO_MORE_RIDS ((NTSTATUS)0xC00002A8L) +#define STATUS_DS_INCORRECT_ROLE_OWNER ((NTSTATUS)0xC00002A9L) +#define STATUS_DS_RIDMGR_INIT_ERROR ((NTSTATUS)0xC00002AAL) +#define STATUS_DS_OBJ_CLASS_VIOLATION ((NTSTATUS)0xC00002ABL) +#define STATUS_DS_CANT_ON_NON_LEAF ((NTSTATUS)0xC00002ACL) +#define STATUS_DS_CANT_ON_RDN ((NTSTATUS)0xC00002ADL) +#define STATUS_DS_CANT_MOD_OBJ_CLASS ((NTSTATUS)0xC00002AEL) +#define STATUS_DS_CROSS_DOM_MOVE_FAILED ((NTSTATUS)0xC00002AFL) +#define STATUS_DS_GC_NOT_AVAILABLE ((NTSTATUS)0xC00002B0L) +#define STATUS_DIRECTORY_SERVICE_REQUIRED ((NTSTATUS)0xC00002B1L) +#define STATUS_REPARSE_ATTRIBUTE_CONFLICT ((NTSTATUS)0xC00002B2L) +#define STATUS_CANT_ENABLE_DENY_ONLY ((NTSTATUS)0xC00002B3L) +#define STATUS_FLOAT_MULTIPLE_FAULTS ((NTSTATUS)0xC00002B4L) +#define STATUS_FLOAT_MULTIPLE_TRAPS ((NTSTATUS)0xC00002B5L) +#define STATUS_DEVICE_REMOVED ((NTSTATUS)0xC00002B6L) +#define STATUS_JOURNAL_DELETE_IN_PROGRESS ((NTSTATUS)0xC00002B7L) +#define STATUS_JOURNAL_NOT_ACTIVE ((NTSTATUS)0xC00002B8L) +#define STATUS_NOINTERFACE ((NTSTATUS)0xC00002B9L) +#define STATUS_DS_ADMIN_LIMIT_EXCEEDED ((NTSTATUS)0xC00002C1L) +#define STATUS_DRIVER_FAILED_SLEEP ((NTSTATUS)0xC00002C2L) +#define STATUS_MUTUAL_AUTHENTICATION_FAILED ((NTSTATUS)0xC00002C3L) +#define STATUS_CORRUPT_SYSTEM_FILE ((NTSTATUS)0xC00002C4L) +#define STATUS_DATATYPE_MISALIGNMENT_ERROR ((NTSTATUS)0xC00002C5L) +#define STATUS_WMI_READ_ONLY ((NTSTATUS)0xC00002C6L) +#define STATUS_WMI_SET_FAILURE ((NTSTATUS)0xC00002C7L) +#define STATUS_COMMITMENT_MINIMUM ((NTSTATUS)0xC00002C8L) +#define STATUS_REG_NAT_CONSUMPTION ((NTSTATUS)0xC00002C9L) +#define STATUS_TRANSPORT_FULL ((NTSTATUS)0xC00002CAL) +#define STATUS_DS_SAM_INIT_FAILURE ((NTSTATUS)0xC00002CBL) +#define STATUS_ONLY_IF_CONNECTED ((NTSTATUS)0xC00002CCL) +#define STATUS_DS_SENSITIVE_GROUP_VIOLATION ((NTSTATUS)0xC00002CDL) +#define STATUS_PNP_RESTART_ENUMERATION ((NTSTATUS)0xC00002CEL) +#define STATUS_JOURNAL_ENTRY_DELETED ((NTSTATUS)0xC00002CFL) +#define STATUS_DS_CANT_MOD_PRIMARYGROUPID ((NTSTATUS)0xC00002D0L) +#define STATUS_SYSTEM_IMAGE_BAD_SIGNATURE ((NTSTATUS)0xC00002D1L) +#define STATUS_PNP_REBOOT_REQUIRED ((NTSTATUS)0xC00002D2L) +#define STATUS_POWER_STATE_INVALID ((NTSTATUS)0xC00002D3L) +#define STATUS_DS_INVALID_GROUP_TYPE ((NTSTATUS)0xC00002D4L) +#define STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN ((NTSTATUS)0xC00002D5L) +#define STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN ((NTSTATUS)0xC00002D6L) +#define STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER ((NTSTATUS)0xC00002D7L) +#define STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER ((NTSTATUS)0xC00002D8L) +#define STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER ((NTSTATUS)0xC00002D9L) +#define STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER ((NTSTATUS)0xC00002DAL) +#define STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER ((NTSTATUS)0xC00002DBL) +#define STATUS_DS_HAVE_PRIMARY_MEMBERS ((NTSTATUS)0xC00002DCL) +#define STATUS_WMI_NOT_SUPPORTED ((NTSTATUS)0xC00002DDL) +#define STATUS_INSUFFICIENT_POWER ((NTSTATUS)0xC00002DEL) +#define STATUS_SAM_NEED_BOOTKEY_PASSWORD ((NTSTATUS)0xC00002DFL) +#define STATUS_SAM_NEED_BOOTKEY_FLOPPY ((NTSTATUS)0xC00002E0L) +#define STATUS_DS_CANT_START ((NTSTATUS)0xC00002E1L) +#define STATUS_DS_INIT_FAILURE ((NTSTATUS)0xC00002E2L) +#define STATUS_SAM_INIT_FAILURE ((NTSTATUS)0xC00002E3L) +#define STATUS_DS_GC_REQUIRED ((NTSTATUS)0xC00002E4L) +#define STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY ((NTSTATUS)0xC00002E5L) +#define STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS ((NTSTATUS)0xC00002E6L) +#define STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED ((NTSTATUS)0xC00002E7L) +#define STATUS_MULTIPLE_FAULT_VIOLATION ((NTSTATUS)0xC00002E8L) +#define STATUS_NOT_SUPPORTED_ON_SBS ((NTSTATUS)0xC0000300L) +#define DBG_NO_STATE_CHANGE ((NTSTATUS)0xC0010001L) +#define DBG_APP_NOT_IDLE ((NTSTATUS)0xC0010002L) +#define RPC_NT_PIPE_CLOSED ((NTSTATUS)0xC003005FL) +#define RPC_NT_PIPE_DISCIPLINE_ERROR ((NTSTATUS)0xC0030060L) +#define RPC_NT_PIPE_EMPTY ((NTSTATUS)0xC0030061L) +#define RPC_NT_INVALID_ASYNC_HANDLE ((NTSTATUS)0xC0020062L) +#define RPC_NT_INVALID_ASYNC_CALL ((NTSTATUS)0xC0020063L) +#define STATUS_ACPI_INVALID_OPCODE ((NTSTATUS)0xC0140001L) +#define STATUS_ACPI_STACK_OVERFLOW ((NTSTATUS)0xC0140002L) +#define STATUS_ACPI_ASSERT_FAILED ((NTSTATUS)0xC0140003L) +#define STATUS_ACPI_INVALID_INDEX ((NTSTATUS)0xC0140004L) +#define STATUS_ACPI_INVALID_ARGUMENT ((NTSTATUS)0xC0140005L) +#define STATUS_ACPI_FATAL ((NTSTATUS)0xC0140006L) +#define STATUS_ACPI_INVALID_SUPERNAME ((NTSTATUS)0xC0140007L) +#define STATUS_ACPI_INVALID_ARGTYPE ((NTSTATUS)0xC0140008L) +#define STATUS_ACPI_INVALID_OBJTYPE ((NTSTATUS)0xC0140009L) +#define STATUS_ACPI_INVALID_TARGETTYPE ((NTSTATUS)0xC014000AL) +#define STATUS_ACPI_INCORRECT_ARGUMENT_COUNT ((NTSTATUS)0xC014000BL) +#define STATUS_ACPI_ADDRESS_NOT_MAPPED ((NTSTATUS)0xC014000CL) +#define STATUS_ACPI_INVALID_EVENTTYPE ((NTSTATUS)0xC014000DL) +#define STATUS_ACPI_HANDLER_COLLISION ((NTSTATUS)0xC014000EL) +#define STATUS_ACPI_INVALID_DATA ((NTSTATUS)0xC014000FL) +#define STATUS_ACPI_INVALID_REGION ((NTSTATUS)0xC0140010L) +#define STATUS_ACPI_INVALID_ACCESS_SIZE ((NTSTATUS)0xC0140011L) +#define STATUS_ACPI_ACQUIRE_GLOBAL_LOCK ((NTSTATUS)0xC0140012L) +#define STATUS_ACPI_ALREADY_INITIALIZED ((NTSTATUS)0xC0140013L) +#define STATUS_ACPI_NOT_INITIALIZED ((NTSTATUS)0xC0140014L) +#define STATUS_ACPI_INVALID_MUTEX_LEVEL ((NTSTATUS)0xC0140015L) +#define STATUS_ACPI_MUTEX_NOT_OWNED ((NTSTATUS)0xC0140016L) +#define STATUS_ACPI_MUTEX_NOT_OWNER ((NTSTATUS)0xC0140017L) +#define STATUS_ACPI_RS_ACCESS ((NTSTATUS)0xC0140018L) +#define STATUS_ACPI_INVALID_TABLE ((NTSTATUS)0xC0140019L) +#define STATUS_ACPI_REG_HANDLER_FAILED ((NTSTATUS)0xC0140020L) +#define STATUS_ACPI_POWER_REQUEST_FAILED ((NTSTATUS)0xC0140021L) +#define STATUS_CTX_WINSTATION_NAME_INVALID ((NTSTATUS)0xC00A0001L) +#define STATUS_CTX_INVALID_PD ((NTSTATUS)0xC00A0002L) +#define STATUS_CTX_PD_NOT_FOUND ((NTSTATUS)0xC00A0003L) +#define STATUS_CTX_CDM_CONNECT ((NTSTATUS)0x400A0004L) +#define STATUS_CTX_CDM_DISCONNECT ((NTSTATUS)0x400A0005L) +#define STATUS_CTX_CLOSE_PENDING ((NTSTATUS)0xC00A0006L) +#define STATUS_CTX_NO_OUTBUF ((NTSTATUS)0xC00A0007L) +#define STATUS_CTX_MODEM_INF_NOT_FOUND ((NTSTATUS)0xC00A0008L) +#define STATUS_CTX_INVALID_MODEMNAME ((NTSTATUS)0xC00A0009L) +#define STATUS_CTX_RESPONSE_ERROR ((NTSTATUS)0xC00A000AL) +#define STATUS_CTX_MODEM_RESPONSE_TIMEOUT ((NTSTATUS)0xC00A000BL) +#define STATUS_CTX_MODEM_RESPONSE_NO_CARRIER ((NTSTATUS)0xC00A000CL) +#define STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE ((NTSTATUS)0xC00A000DL) +#define STATUS_CTX_MODEM_RESPONSE_BUSY ((NTSTATUS)0xC00A000EL) +#define STATUS_CTX_MODEM_RESPONSE_VOICE ((NTSTATUS)0xC00A000FL) +#define STATUS_CTX_TD_ERROR ((NTSTATUS)0xC00A0010L) +#define STATUS_CTX_LICENSE_CLIENT_INVALID ((NTSTATUS)0xC00A0012L) +#define STATUS_CTX_LICENSE_NOT_AVAILABLE ((NTSTATUS)0xC00A0013L) +#define STATUS_CTX_LICENSE_EXPIRED ((NTSTATUS)0xC00A0014L) +#define STATUS_CTX_WINSTATION_NOT_FOUND ((NTSTATUS)0xC00A0015L) +#define STATUS_CTX_WINSTATION_NAME_COLLISION ((NTSTATUS)0xC00A0016L) +#define STATUS_CTX_WINSTATION_BUSY ((NTSTATUS)0xC00A0017L) +#define STATUS_CTX_BAD_VIDEO_MODE ((NTSTATUS)0xC00A0018L) +#define STATUS_CTX_GRAPHICS_INVALID ((NTSTATUS)0xC00A0022L) +#define STATUS_CTX_NOT_CONSOLE ((NTSTATUS)0xC00A0024L) +#define STATUS_CTX_CLIENT_QUERY_TIMEOUT ((NTSTATUS)0xC00A0026L) +#define STATUS_CTX_CONSOLE_DISCONNECT ((NTSTATUS)0xC00A0027L) +#define STATUS_CTX_CONSOLE_CONNECT ((NTSTATUS)0xC00A0028L) +#define STATUS_CTX_SHADOW_DENIED ((NTSTATUS)0xC00A002AL) +#define STATUS_CTX_WINSTATION_ACCESS_DENIED ((NTSTATUS)0xC00A002BL) +#define STATUS_CTX_INVALID_WD ((NTSTATUS)0xC00A002EL) +#define STATUS_CTX_WD_NOT_FOUND ((NTSTATUS)0xC00A002FL) +#define STATUS_CTX_SHADOW_INVALID ((NTSTATUS)0xC00A0030L) +#define STATUS_CTX_SHADOW_DISABLED ((NTSTATUS)0xC00A0031L) +#define STATUS_RDP_PROTOCOL_ERROR ((NTSTATUS)0xC00A0032L) +#define STATUS_CTX_CLIENT_LICENSE_NOT_SET ((NTSTATUS)0xC00A0033L) +#define STATUS_CTX_CLIENT_LICENSE_IN_USE ((NTSTATUS)0xC00A0034L) +#define STATUS_PNP_BAD_MPS_TABLE ((NTSTATUS)0xC0040035L) +#define STATUS_PNP_TRANSLATION_FAILED ((NTSTATUS)0xC0040036L) +#define STATUS_PNP_IRQ_TRANSLATION_FAILED ((NTSTATUS)0xC0040037L) +#endif // VER_PRODUCTBUILD < 2195 + +static PCSTR +NtStatusToStr( + NTSTATUS status); + +PCSTR +GetStatusName( + NTSTATUS status) +{ + static CHAR statusName[80]; + CHAR severity; + + switch (status & 0xf0000000) { + case 0x00000000: severity = 'S'; break; + case 0x40000000: severity = 'I'; break; + case 0x80000000: severity = 'W'; break; + case 0xC0000000: severity = 'E'; break; + default: severity = '?'; + } + + statusName[sizeof(statusName) - 1] = '\0'; + _snprintf(statusName, sizeof(statusName) - 1, + // sprintf(statusName, + "(%c)%s", severity, NtStatusToStr(status)); + + return statusName; +} + +PCSTR +NtStatusToStr( + NTSTATUS status) +{ + switch (status) { + CASE_RETURN_STR(STATUS_SUCCESS); +/* + CASE_RETURN_STR(STATUS_WAIT_0); +*/ + CASE_RETURN_STR(STATUS_WAIT_1); + CASE_RETURN_STR(STATUS_WAIT_2); + CASE_RETURN_STR(STATUS_WAIT_3); + CASE_RETURN_STR(STATUS_WAIT_63); + CASE_RETURN_STR(STATUS_ABANDONED); +/* + CASE_RETURN_STR(STATUS_ABANDONED_WAIT_0); +*/ + CASE_RETURN_STR(STATUS_ABANDONED_WAIT_63); + CASE_RETURN_STR(STATUS_USER_APC); + CASE_RETURN_STR(STATUS_KERNEL_APC); + CASE_RETURN_STR(STATUS_ALERTED); + CASE_RETURN_STR(STATUS_TIMEOUT); + CASE_RETURN_STR(STATUS_PENDING); + CASE_RETURN_STR(STATUS_REPARSE); + CASE_RETURN_STR(STATUS_MORE_ENTRIES); + CASE_RETURN_STR(STATUS_NOT_ALL_ASSIGNED); + CASE_RETURN_STR(STATUS_SOME_NOT_MAPPED); + CASE_RETURN_STR(STATUS_OPLOCK_BREAK_IN_PROGRESS); + CASE_RETURN_STR(STATUS_VOLUME_MOUNTED); + CASE_RETURN_STR(STATUS_RXACT_COMMITTED); + CASE_RETURN_STR(STATUS_NOTIFY_CLEANUP); + CASE_RETURN_STR(STATUS_NOTIFY_ENUM_DIR); + CASE_RETURN_STR(STATUS_NO_QUOTAS_FOR_ACCOUNT); + CASE_RETURN_STR(STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED); + CASE_RETURN_STR(STATUS_PAGE_FAULT_TRANSITION); + CASE_RETURN_STR(STATUS_PAGE_FAULT_DEMAND_ZERO); + CASE_RETURN_STR(STATUS_PAGE_FAULT_COPY_ON_WRITE); + CASE_RETURN_STR(STATUS_PAGE_FAULT_GUARD_PAGE); + CASE_RETURN_STR(STATUS_PAGE_FAULT_PAGING_FILE); + CASE_RETURN_STR(STATUS_CACHE_PAGE_LOCKED); + CASE_RETURN_STR(STATUS_CRASH_DUMP); + CASE_RETURN_STR(STATUS_BUFFER_ALL_ZEROS); + CASE_RETURN_STR(STATUS_REPARSE_OBJECT); + CASE_RETURN_STR(STATUS_RESOURCE_REQUIREMENTS_CHANGED); + CASE_RETURN_STR(STATUS_TRANSLATION_COMPLETE); + CASE_RETURN_STR(STATUS_DS_MEMBERSHIP_EVALUATED_LOCALLY); + CASE_RETURN_STR(DBG_EXCEPTION_HANDLED); + CASE_RETURN_STR(DBG_CONTINUE); + CASE_RETURN_STR(STATUS_OBJECT_NAME_EXISTS); + CASE_RETURN_STR(STATUS_THREAD_WAS_SUSPENDED); + CASE_RETURN_STR(STATUS_WORKING_SET_LIMIT_RANGE); + CASE_RETURN_STR(STATUS_IMAGE_NOT_AT_BASE); + CASE_RETURN_STR(STATUS_RXACT_STATE_CREATED); + CASE_RETURN_STR(STATUS_SEGMENT_NOTIFICATION); + CASE_RETURN_STR(STATUS_LOCAL_USER_SESSION_KEY); + CASE_RETURN_STR(STATUS_BAD_CURRENT_DIRECTORY); + CASE_RETURN_STR(STATUS_SERIAL_MORE_WRITES); + CASE_RETURN_STR(STATUS_REGISTRY_RECOVERED); + CASE_RETURN_STR(STATUS_FT_READ_RECOVERY_FROM_BACKUP); + CASE_RETURN_STR(STATUS_FT_WRITE_RECOVERY); + CASE_RETURN_STR(STATUS_SERIAL_COUNTER_TIMEOUT); + CASE_RETURN_STR(STATUS_NULL_LM_PASSWORD); + CASE_RETURN_STR(STATUS_IMAGE_MACHINE_TYPE_MISMATCH); + CASE_RETURN_STR(STATUS_RECEIVE_PARTIAL); + CASE_RETURN_STR(STATUS_RECEIVE_EXPEDITED); + CASE_RETURN_STR(STATUS_RECEIVE_PARTIAL_EXPEDITED); + CASE_RETURN_STR(STATUS_EVENT_DONE); + CASE_RETURN_STR(STATUS_EVENT_PENDING); + CASE_RETURN_STR(STATUS_CHECKING_FILE_SYSTEM); + CASE_RETURN_STR(STATUS_FATAL_APP_EXIT); + CASE_RETURN_STR(STATUS_PREDEFINED_HANDLE); + CASE_RETURN_STR(STATUS_WAS_UNLOCKED); + CASE_RETURN_STR(STATUS_SERVICE_NOTIFICATION); + CASE_RETURN_STR(STATUS_WAS_LOCKED); + CASE_RETURN_STR(STATUS_LOG_HARD_ERROR); + CASE_RETURN_STR(STATUS_ALREADY_WIN32); + CASE_RETURN_STR(STATUS_WX86_UNSIMULATE); + CASE_RETURN_STR(STATUS_WX86_CONTINUE); + CASE_RETURN_STR(STATUS_WX86_SINGLE_STEP); + CASE_RETURN_STR(STATUS_WX86_BREAKPOINT); + CASE_RETURN_STR(STATUS_WX86_EXCEPTION_CONTINUE); + CASE_RETURN_STR(STATUS_WX86_EXCEPTION_LASTCHANCE); + CASE_RETURN_STR(STATUS_WX86_EXCEPTION_CHAIN); + CASE_RETURN_STR(STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE); + CASE_RETURN_STR(STATUS_NO_YIELD_PERFORMED); + CASE_RETURN_STR(STATUS_TIMER_RESUME_IGNORED); + CASE_RETURN_STR(STATUS_ARBITRATION_UNHANDLED); + CASE_RETURN_STR(STATUS_CARDBUS_NOT_SUPPORTED); + CASE_RETURN_STR(STATUS_WX86_CREATEWX86TIB); + CASE_RETURN_STR(STATUS_MP_PROCESSOR_MISMATCH); + CASE_RETURN_STR(DBG_REPLY_LATER); + CASE_RETURN_STR(DBG_UNABLE_TO_PROVIDE_HANDLE); + CASE_RETURN_STR(DBG_TERMINATE_THREAD); + CASE_RETURN_STR(DBG_TERMINATE_PROCESS); + CASE_RETURN_STR(DBG_CONTROL_C); + CASE_RETURN_STR(DBG_PRINTEXCEPTION_C); + CASE_RETURN_STR(DBG_RIPEXCEPTION); + CASE_RETURN_STR(DBG_CONTROL_BREAK); + CASE_RETURN_STR(STATUS_GUARD_PAGE_VIOLATION); + CASE_RETURN_STR(STATUS_DATATYPE_MISALIGNMENT); + CASE_RETURN_STR(STATUS_BREAKPOINT); + CASE_RETURN_STR(STATUS_SINGLE_STEP); + CASE_RETURN_STR(STATUS_BUFFER_OVERFLOW); + CASE_RETURN_STR(STATUS_NO_MORE_FILES); + CASE_RETURN_STR(STATUS_WAKE_SYSTEM_DEBUGGER); + CASE_RETURN_STR(STATUS_HANDLES_CLOSED); + CASE_RETURN_STR(STATUS_NO_INHERITANCE); + CASE_RETURN_STR(STATUS_GUID_SUBSTITUTION_MADE); + CASE_RETURN_STR(STATUS_PARTIAL_COPY); + CASE_RETURN_STR(STATUS_DEVICE_PAPER_EMPTY); + CASE_RETURN_STR(STATUS_DEVICE_POWERED_OFF); + CASE_RETURN_STR(STATUS_DEVICE_OFF_LINE); + CASE_RETURN_STR(STATUS_DEVICE_BUSY); + CASE_RETURN_STR(STATUS_NO_MORE_EAS); + CASE_RETURN_STR(STATUS_INVALID_EA_NAME); + CASE_RETURN_STR(STATUS_EA_LIST_INCONSISTENT); + CASE_RETURN_STR(STATUS_INVALID_EA_FLAG); + CASE_RETURN_STR(STATUS_VERIFY_REQUIRED); + CASE_RETURN_STR(STATUS_EXTRANEOUS_INFORMATION); + CASE_RETURN_STR(STATUS_RXACT_COMMIT_NECESSARY); + CASE_RETURN_STR(STATUS_NO_MORE_ENTRIES); + CASE_RETURN_STR(STATUS_FILEMARK_DETECTED); + CASE_RETURN_STR(STATUS_MEDIA_CHANGED); + CASE_RETURN_STR(STATUS_BUS_RESET); + CASE_RETURN_STR(STATUS_END_OF_MEDIA); + CASE_RETURN_STR(STATUS_BEGINNING_OF_MEDIA); + CASE_RETURN_STR(STATUS_MEDIA_CHECK); + CASE_RETURN_STR(STATUS_SETMARK_DETECTED); + CASE_RETURN_STR(STATUS_NO_DATA_DETECTED); + CASE_RETURN_STR(STATUS_REDIRECTOR_HAS_OPEN_HANDLES); + CASE_RETURN_STR(STATUS_SERVER_HAS_OPEN_HANDLES); + CASE_RETURN_STR(STATUS_ALREADY_DISCONNECTED); + CASE_RETURN_STR(STATUS_LONGJUMP); + CASE_RETURN_STR(DBG_EXCEPTION_NOT_HANDLED); + CASE_RETURN_STR(STATUS_UNSUCCESSFUL); + CASE_RETURN_STR(STATUS_NOT_IMPLEMENTED); + CASE_RETURN_STR(STATUS_INVALID_INFO_CLASS); + CASE_RETURN_STR(STATUS_INFO_LENGTH_MISMATCH); + CASE_RETURN_STR(STATUS_ACCESS_VIOLATION); + CASE_RETURN_STR(STATUS_IN_PAGE_ERROR); + CASE_RETURN_STR(STATUS_PAGEFILE_QUOTA); + CASE_RETURN_STR(STATUS_INVALID_HANDLE); + CASE_RETURN_STR(STATUS_BAD_INITIAL_STACK); + CASE_RETURN_STR(STATUS_BAD_INITIAL_PC); + CASE_RETURN_STR(STATUS_INVALID_CID); + CASE_RETURN_STR(STATUS_TIMER_NOT_CANCELED); + CASE_RETURN_STR(STATUS_INVALID_PARAMETER); + CASE_RETURN_STR(STATUS_NO_SUCH_DEVICE); + CASE_RETURN_STR(STATUS_NO_SUCH_FILE); + CASE_RETURN_STR(STATUS_INVALID_DEVICE_REQUEST); + CASE_RETURN_STR(STATUS_END_OF_FILE); + CASE_RETURN_STR(STATUS_WRONG_VOLUME); + CASE_RETURN_STR(STATUS_NO_MEDIA_IN_DEVICE); + CASE_RETURN_STR(STATUS_UNRECOGNIZED_MEDIA); + CASE_RETURN_STR(STATUS_NONEXISTENT_SECTOR); + CASE_RETURN_STR(STATUS_MORE_PROCESSING_REQUIRED); + CASE_RETURN_STR(STATUS_NO_MEMORY); + CASE_RETURN_STR(STATUS_CONFLICTING_ADDRESSES); + CASE_RETURN_STR(STATUS_NOT_MAPPED_VIEW); + CASE_RETURN_STR(STATUS_UNABLE_TO_FREE_VM); + CASE_RETURN_STR(STATUS_UNABLE_TO_DELETE_SECTION); + CASE_RETURN_STR(STATUS_INVALID_SYSTEM_SERVICE); + CASE_RETURN_STR(STATUS_ILLEGAL_INSTRUCTION); + CASE_RETURN_STR(STATUS_INVALID_LOCK_SEQUENCE); + CASE_RETURN_STR(STATUS_INVALID_VIEW_SIZE); + CASE_RETURN_STR(STATUS_INVALID_FILE_FOR_SECTION); + CASE_RETURN_STR(STATUS_ALREADY_COMMITTED); + CASE_RETURN_STR(STATUS_ACCESS_DENIED); + CASE_RETURN_STR(STATUS_BUFFER_TOO_SMALL); + CASE_RETURN_STR(STATUS_OBJECT_TYPE_MISMATCH); + CASE_RETURN_STR(STATUS_NONCONTINUABLE_EXCEPTION); + CASE_RETURN_STR(STATUS_INVALID_DISPOSITION); + CASE_RETURN_STR(STATUS_UNWIND); + CASE_RETURN_STR(STATUS_BAD_STACK); + CASE_RETURN_STR(STATUS_INVALID_UNWIND_TARGET); + CASE_RETURN_STR(STATUS_NOT_LOCKED); + CASE_RETURN_STR(STATUS_PARITY_ERROR); + CASE_RETURN_STR(STATUS_UNABLE_TO_DECOMMIT_VM); + CASE_RETURN_STR(STATUS_NOT_COMMITTED); + CASE_RETURN_STR(STATUS_INVALID_PORT_ATTRIBUTES); + CASE_RETURN_STR(STATUS_PORT_MESSAGE_TOO_LONG); + CASE_RETURN_STR(STATUS_INVALID_PARAMETER_MIX); + CASE_RETURN_STR(STATUS_INVALID_QUOTA_LOWER); + CASE_RETURN_STR(STATUS_DISK_CORRUPT_ERROR); + CASE_RETURN_STR(STATUS_OBJECT_NAME_INVALID); + CASE_RETURN_STR(STATUS_OBJECT_NAME_NOT_FOUND); + CASE_RETURN_STR(STATUS_OBJECT_NAME_COLLISION); + CASE_RETURN_STR(STATUS_PORT_DISCONNECTED); + CASE_RETURN_STR(STATUS_DEVICE_ALREADY_ATTACHED); + CASE_RETURN_STR(STATUS_OBJECT_PATH_INVALID); + CASE_RETURN_STR(STATUS_OBJECT_PATH_NOT_FOUND); + CASE_RETURN_STR(STATUS_OBJECT_PATH_SYNTAX_BAD); + CASE_RETURN_STR(STATUS_DATA_OVERRUN); + CASE_RETURN_STR(STATUS_DATA_LATE_ERROR); + CASE_RETURN_STR(STATUS_DATA_ERROR); + CASE_RETURN_STR(STATUS_CRC_ERROR); + CASE_RETURN_STR(STATUS_SECTION_TOO_BIG); + CASE_RETURN_STR(STATUS_PORT_CONNECTION_REFUSED); + CASE_RETURN_STR(STATUS_INVALID_PORT_HANDLE); + CASE_RETURN_STR(STATUS_SHARING_VIOLATION); + CASE_RETURN_STR(STATUS_QUOTA_EXCEEDED); + CASE_RETURN_STR(STATUS_INVALID_PAGE_PROTECTION); + CASE_RETURN_STR(STATUS_MUTANT_NOT_OWNED); + CASE_RETURN_STR(STATUS_SEMAPHORE_LIMIT_EXCEEDED); + CASE_RETURN_STR(STATUS_PORT_ALREADY_SET); + CASE_RETURN_STR(STATUS_SECTION_NOT_IMAGE); + CASE_RETURN_STR(STATUS_SUSPEND_COUNT_EXCEEDED); + CASE_RETURN_STR(STATUS_THREAD_IS_TERMINATING); + CASE_RETURN_STR(STATUS_BAD_WORKING_SET_LIMIT); + CASE_RETURN_STR(STATUS_INCOMPATIBLE_FILE_MAP); + CASE_RETURN_STR(STATUS_SECTION_PROTECTION); + CASE_RETURN_STR(STATUS_EAS_NOT_SUPPORTED); + CASE_RETURN_STR(STATUS_EA_TOO_LARGE); + CASE_RETURN_STR(STATUS_NONEXISTENT_EA_ENTRY); + CASE_RETURN_STR(STATUS_NO_EAS_ON_FILE); + CASE_RETURN_STR(STATUS_EA_CORRUPT_ERROR); + CASE_RETURN_STR(STATUS_FILE_LOCK_CONFLICT); + CASE_RETURN_STR(STATUS_LOCK_NOT_GRANTED); + CASE_RETURN_STR(STATUS_DELETE_PENDING); + CASE_RETURN_STR(STATUS_CTL_FILE_NOT_SUPPORTED); + CASE_RETURN_STR(STATUS_UNKNOWN_REVISION); + CASE_RETURN_STR(STATUS_REVISION_MISMATCH); + CASE_RETURN_STR(STATUS_INVALID_OWNER); + CASE_RETURN_STR(STATUS_INVALID_PRIMARY_GROUP); + CASE_RETURN_STR(STATUS_NO_IMPERSONATION_TOKEN); + CASE_RETURN_STR(STATUS_CANT_DISABLE_MANDATORY); + CASE_RETURN_STR(STATUS_NO_LOGON_SERVERS); + CASE_RETURN_STR(STATUS_NO_SUCH_LOGON_SESSION); + CASE_RETURN_STR(STATUS_NO_SUCH_PRIVILEGE); + CASE_RETURN_STR(STATUS_PRIVILEGE_NOT_HELD); + CASE_RETURN_STR(STATUS_INVALID_ACCOUNT_NAME); + CASE_RETURN_STR(STATUS_USER_EXISTS); + CASE_RETURN_STR(STATUS_NO_SUCH_USER); + CASE_RETURN_STR(STATUS_GROUP_EXISTS); + CASE_RETURN_STR(STATUS_NO_SUCH_GROUP); + CASE_RETURN_STR(STATUS_MEMBER_IN_GROUP); + CASE_RETURN_STR(STATUS_MEMBER_NOT_IN_GROUP); + CASE_RETURN_STR(STATUS_LAST_ADMIN); + CASE_RETURN_STR(STATUS_WRONG_PASSWORD); + CASE_RETURN_STR(STATUS_ILL_FORMED_PASSWORD); + CASE_RETURN_STR(STATUS_PASSWORD_RESTRICTION); + CASE_RETURN_STR(STATUS_LOGON_FAILURE); + CASE_RETURN_STR(STATUS_ACCOUNT_RESTRICTION); + CASE_RETURN_STR(STATUS_INVALID_LOGON_HOURS); + CASE_RETURN_STR(STATUS_INVALID_WORKSTATION); + CASE_RETURN_STR(STATUS_PASSWORD_EXPIRED); + CASE_RETURN_STR(STATUS_ACCOUNT_DISABLED); + CASE_RETURN_STR(STATUS_NONE_MAPPED); + CASE_RETURN_STR(STATUS_TOO_MANY_LUIDS_REQUESTED); + CASE_RETURN_STR(STATUS_LUIDS_EXHAUSTED); + CASE_RETURN_STR(STATUS_INVALID_SUB_AUTHORITY); + CASE_RETURN_STR(STATUS_INVALID_ACL); + CASE_RETURN_STR(STATUS_INVALID_SID); + CASE_RETURN_STR(STATUS_INVALID_SECURITY_DESCR); + CASE_RETURN_STR(STATUS_PROCEDURE_NOT_FOUND); + CASE_RETURN_STR(STATUS_INVALID_IMAGE_FORMAT); + CASE_RETURN_STR(STATUS_NO_TOKEN); + CASE_RETURN_STR(STATUS_BAD_INHERITANCE_ACL); + CASE_RETURN_STR(STATUS_RANGE_NOT_LOCKED); + CASE_RETURN_STR(STATUS_DISK_FULL); + CASE_RETURN_STR(STATUS_SERVER_DISABLED); + CASE_RETURN_STR(STATUS_SERVER_NOT_DISABLED); + CASE_RETURN_STR(STATUS_TOO_MANY_GUIDS_REQUESTED); + CASE_RETURN_STR(STATUS_GUIDS_EXHAUSTED); + CASE_RETURN_STR(STATUS_INVALID_ID_AUTHORITY); + CASE_RETURN_STR(STATUS_AGENTS_EXHAUSTED); + CASE_RETURN_STR(STATUS_INVALID_VOLUME_LABEL); + CASE_RETURN_STR(STATUS_SECTION_NOT_EXTENDED); + CASE_RETURN_STR(STATUS_NOT_MAPPED_DATA); + CASE_RETURN_STR(STATUS_RESOURCE_DATA_NOT_FOUND); + CASE_RETURN_STR(STATUS_RESOURCE_TYPE_NOT_FOUND); + CASE_RETURN_STR(STATUS_RESOURCE_NAME_NOT_FOUND); + CASE_RETURN_STR(STATUS_ARRAY_BOUNDS_EXCEEDED); + CASE_RETURN_STR(STATUS_FLOAT_DENORMAL_OPERAND); + CASE_RETURN_STR(STATUS_FLOAT_DIVIDE_BY_ZERO); + CASE_RETURN_STR(STATUS_FLOAT_INEXACT_RESULT); + CASE_RETURN_STR(STATUS_FLOAT_INVALID_OPERATION); + CASE_RETURN_STR(STATUS_FLOAT_OVERFLOW); + CASE_RETURN_STR(STATUS_FLOAT_STACK_CHECK); + CASE_RETURN_STR(STATUS_FLOAT_UNDERFLOW); + CASE_RETURN_STR(STATUS_INTEGER_DIVIDE_BY_ZERO); + CASE_RETURN_STR(STATUS_INTEGER_OVERFLOW); + CASE_RETURN_STR(STATUS_PRIVILEGED_INSTRUCTION); + CASE_RETURN_STR(STATUS_TOO_MANY_PAGING_FILES); + CASE_RETURN_STR(STATUS_FILE_INVALID); + CASE_RETURN_STR(STATUS_ALLOTTED_SPACE_EXCEEDED); + CASE_RETURN_STR(STATUS_INSUFFICIENT_RESOURCES); + CASE_RETURN_STR(STATUS_DFS_EXIT_PATH_FOUND); + CASE_RETURN_STR(STATUS_DEVICE_DATA_ERROR); + CASE_RETURN_STR(STATUS_DEVICE_NOT_CONNECTED); + CASE_RETURN_STR(STATUS_DEVICE_POWER_FAILURE); + CASE_RETURN_STR(STATUS_FREE_VM_NOT_AT_BASE); + CASE_RETURN_STR(STATUS_MEMORY_NOT_ALLOCATED); + CASE_RETURN_STR(STATUS_WORKING_SET_QUOTA); + CASE_RETURN_STR(STATUS_MEDIA_WRITE_PROTECTED); + CASE_RETURN_STR(STATUS_DEVICE_NOT_READY); + CASE_RETURN_STR(STATUS_INVALID_GROUP_ATTRIBUTES); + CASE_RETURN_STR(STATUS_BAD_IMPERSONATION_LEVEL); + CASE_RETURN_STR(STATUS_CANT_OPEN_ANONYMOUS); + CASE_RETURN_STR(STATUS_BAD_VALIDATION_CLASS); + CASE_RETURN_STR(STATUS_BAD_TOKEN_TYPE); + CASE_RETURN_STR(STATUS_BAD_MASTER_BOOT_RECORD); + CASE_RETURN_STR(STATUS_INSTRUCTION_MISALIGNMENT); + CASE_RETURN_STR(STATUS_INSTANCE_NOT_AVAILABLE); + CASE_RETURN_STR(STATUS_PIPE_NOT_AVAILABLE); + CASE_RETURN_STR(STATUS_INVALID_PIPE_STATE); + CASE_RETURN_STR(STATUS_PIPE_BUSY); + CASE_RETURN_STR(STATUS_ILLEGAL_FUNCTION); + CASE_RETURN_STR(STATUS_PIPE_DISCONNECTED); + CASE_RETURN_STR(STATUS_PIPE_CLOSING); + CASE_RETURN_STR(STATUS_PIPE_CONNECTED); + CASE_RETURN_STR(STATUS_PIPE_LISTENING); + CASE_RETURN_STR(STATUS_INVALID_READ_MODE); + CASE_RETURN_STR(STATUS_IO_TIMEOUT); + CASE_RETURN_STR(STATUS_FILE_FORCED_CLOSED); + CASE_RETURN_STR(STATUS_PROFILING_NOT_STARTED); + CASE_RETURN_STR(STATUS_PROFILING_NOT_STOPPED); + CASE_RETURN_STR(STATUS_COULD_NOT_INTERPRET); + CASE_RETURN_STR(STATUS_FILE_IS_A_DIRECTORY); + CASE_RETURN_STR(STATUS_NOT_SUPPORTED); + CASE_RETURN_STR(STATUS_REMOTE_NOT_LISTENING); + CASE_RETURN_STR(STATUS_DUPLICATE_NAME); + CASE_RETURN_STR(STATUS_BAD_NETWORK_PATH); + CASE_RETURN_STR(STATUS_NETWORK_BUSY); + CASE_RETURN_STR(STATUS_DEVICE_DOES_NOT_EXIST); + CASE_RETURN_STR(STATUS_TOO_MANY_COMMANDS); + CASE_RETURN_STR(STATUS_ADAPTER_HARDWARE_ERROR); + CASE_RETURN_STR(STATUS_INVALID_NETWORK_RESPONSE); + CASE_RETURN_STR(STATUS_UNEXPECTED_NETWORK_ERROR); + CASE_RETURN_STR(STATUS_BAD_REMOTE_ADAPTER); + CASE_RETURN_STR(STATUS_PRINT_QUEUE_FULL); + CASE_RETURN_STR(STATUS_NO_SPOOL_SPACE); + CASE_RETURN_STR(STATUS_PRINT_CANCELLED); + CASE_RETURN_STR(STATUS_NETWORK_NAME_DELETED); + CASE_RETURN_STR(STATUS_NETWORK_ACCESS_DENIED); + CASE_RETURN_STR(STATUS_BAD_DEVICE_TYPE); + CASE_RETURN_STR(STATUS_BAD_NETWORK_NAME); + CASE_RETURN_STR(STATUS_TOO_MANY_NAMES); + CASE_RETURN_STR(STATUS_TOO_MANY_SESSIONS); + CASE_RETURN_STR(STATUS_SHARING_PAUSED); + CASE_RETURN_STR(STATUS_REQUEST_NOT_ACCEPTED); + CASE_RETURN_STR(STATUS_REDIRECTOR_PAUSED); + CASE_RETURN_STR(STATUS_NET_WRITE_FAULT); + CASE_RETURN_STR(STATUS_PROFILING_AT_LIMIT); + CASE_RETURN_STR(STATUS_NOT_SAME_DEVICE); + CASE_RETURN_STR(STATUS_FILE_RENAMED); + CASE_RETURN_STR(STATUS_VIRTUAL_CIRCUIT_CLOSED); + CASE_RETURN_STR(STATUS_NO_SECURITY_ON_OBJECT); + CASE_RETURN_STR(STATUS_CANT_WAIT); + CASE_RETURN_STR(STATUS_PIPE_EMPTY); + CASE_RETURN_STR(STATUS_CANT_ACCESS_DOMAIN_INFO); + CASE_RETURN_STR(STATUS_CANT_TERMINATE_SELF); + CASE_RETURN_STR(STATUS_INVALID_SERVER_STATE); + CASE_RETURN_STR(STATUS_INVALID_DOMAIN_STATE); + CASE_RETURN_STR(STATUS_INVALID_DOMAIN_ROLE); + CASE_RETURN_STR(STATUS_NO_SUCH_DOMAIN); + CASE_RETURN_STR(STATUS_DOMAIN_EXISTS); + CASE_RETURN_STR(STATUS_DOMAIN_LIMIT_EXCEEDED); + CASE_RETURN_STR(STATUS_OPLOCK_NOT_GRANTED); + CASE_RETURN_STR(STATUS_INVALID_OPLOCK_PROTOCOL); + CASE_RETURN_STR(STATUS_INTERNAL_DB_CORRUPTION); + CASE_RETURN_STR(STATUS_INTERNAL_ERROR); + CASE_RETURN_STR(STATUS_GENERIC_NOT_MAPPED); + CASE_RETURN_STR(STATUS_BAD_DESCRIPTOR_FORMAT); + CASE_RETURN_STR(STATUS_INVALID_USER_BUFFER); + CASE_RETURN_STR(STATUS_UNEXPECTED_IO_ERROR); + CASE_RETURN_STR(STATUS_UNEXPECTED_MM_CREATE_ERR); + CASE_RETURN_STR(STATUS_UNEXPECTED_MM_MAP_ERROR); + CASE_RETURN_STR(STATUS_UNEXPECTED_MM_EXTEND_ERR); + CASE_RETURN_STR(STATUS_NOT_LOGON_PROCESS); + CASE_RETURN_STR(STATUS_LOGON_SESSION_EXISTS); + CASE_RETURN_STR(STATUS_INVALID_PARAMETER_1); + CASE_RETURN_STR(STATUS_INVALID_PARAMETER_2); + CASE_RETURN_STR(STATUS_INVALID_PARAMETER_3); + CASE_RETURN_STR(STATUS_INVALID_PARAMETER_4); + CASE_RETURN_STR(STATUS_INVALID_PARAMETER_5); + CASE_RETURN_STR(STATUS_INVALID_PARAMETER_6); + CASE_RETURN_STR(STATUS_INVALID_PARAMETER_7); + CASE_RETURN_STR(STATUS_INVALID_PARAMETER_8); + CASE_RETURN_STR(STATUS_INVALID_PARAMETER_9); + CASE_RETURN_STR(STATUS_INVALID_PARAMETER_10); + CASE_RETURN_STR(STATUS_INVALID_PARAMETER_11); + CASE_RETURN_STR(STATUS_INVALID_PARAMETER_12); + CASE_RETURN_STR(STATUS_REDIRECTOR_NOT_STARTED); + CASE_RETURN_STR(STATUS_REDIRECTOR_STARTED); + CASE_RETURN_STR(STATUS_STACK_OVERFLOW); + CASE_RETURN_STR(STATUS_NO_SUCH_PACKAGE); + CASE_RETURN_STR(STATUS_BAD_FUNCTION_TABLE); + CASE_RETURN_STR(STATUS_VARIABLE_NOT_FOUND); + CASE_RETURN_STR(STATUS_DIRECTORY_NOT_EMPTY); + CASE_RETURN_STR(STATUS_FILE_CORRUPT_ERROR); + CASE_RETURN_STR(STATUS_NOT_A_DIRECTORY); + CASE_RETURN_STR(STATUS_BAD_LOGON_SESSION_STATE); + CASE_RETURN_STR(STATUS_LOGON_SESSION_COLLISION); + CASE_RETURN_STR(STATUS_NAME_TOO_LONG); + CASE_RETURN_STR(STATUS_FILES_OPEN); + CASE_RETURN_STR(STATUS_CONNECTION_IN_USE); + CASE_RETURN_STR(STATUS_MESSAGE_NOT_FOUND); + CASE_RETURN_STR(STATUS_PROCESS_IS_TERMINATING); + CASE_RETURN_STR(STATUS_INVALID_LOGON_TYPE); + CASE_RETURN_STR(STATUS_NO_GUID_TRANSLATION); + CASE_RETURN_STR(STATUS_CANNOT_IMPERSONATE); + CASE_RETURN_STR(STATUS_IMAGE_ALREADY_LOADED); + CASE_RETURN_STR(STATUS_ABIOS_NOT_PRESENT); + CASE_RETURN_STR(STATUS_ABIOS_LID_NOT_EXIST); + CASE_RETURN_STR(STATUS_ABIOS_LID_ALREADY_OWNED); + CASE_RETURN_STR(STATUS_ABIOS_NOT_LID_OWNER); + CASE_RETURN_STR(STATUS_ABIOS_INVALID_COMMAND); + CASE_RETURN_STR(STATUS_ABIOS_INVALID_LID); + CASE_RETURN_STR(STATUS_ABIOS_SELECTOR_NOT_AVAILABLE); + CASE_RETURN_STR(STATUS_ABIOS_INVALID_SELECTOR); + CASE_RETURN_STR(STATUS_NO_LDT); + CASE_RETURN_STR(STATUS_INVALID_LDT_SIZE); + CASE_RETURN_STR(STATUS_INVALID_LDT_OFFSET); + CASE_RETURN_STR(STATUS_INVALID_LDT_DESCRIPTOR); + CASE_RETURN_STR(STATUS_INVALID_IMAGE_NE_FORMAT); + CASE_RETURN_STR(STATUS_RXACT_INVALID_STATE); + CASE_RETURN_STR(STATUS_RXACT_COMMIT_FAILURE); + CASE_RETURN_STR(STATUS_MAPPED_FILE_SIZE_ZERO); + CASE_RETURN_STR(STATUS_TOO_MANY_OPENED_FILES); + CASE_RETURN_STR(STATUS_CANCELLED); + CASE_RETURN_STR(STATUS_CANNOT_DELETE); + CASE_RETURN_STR(STATUS_INVALID_COMPUTER_NAME); + CASE_RETURN_STR(STATUS_FILE_DELETED); + CASE_RETURN_STR(STATUS_SPECIAL_ACCOUNT); + CASE_RETURN_STR(STATUS_SPECIAL_GROUP); + CASE_RETURN_STR(STATUS_SPECIAL_USER); + CASE_RETURN_STR(STATUS_MEMBERS_PRIMARY_GROUP); + CASE_RETURN_STR(STATUS_FILE_CLOSED); + CASE_RETURN_STR(STATUS_TOO_MANY_THREADS); + CASE_RETURN_STR(STATUS_THREAD_NOT_IN_PROCESS); + CASE_RETURN_STR(STATUS_TOKEN_ALREADY_IN_USE); + CASE_RETURN_STR(STATUS_PAGEFILE_QUOTA_EXCEEDED); + CASE_RETURN_STR(STATUS_COMMITMENT_LIMIT); + CASE_RETURN_STR(STATUS_INVALID_IMAGE_LE_FORMAT); + CASE_RETURN_STR(STATUS_INVALID_IMAGE_NOT_MZ); + CASE_RETURN_STR(STATUS_INVALID_IMAGE_PROTECT); + CASE_RETURN_STR(STATUS_INVALID_IMAGE_WIN_16); + CASE_RETURN_STR(STATUS_LOGON_SERVER_CONFLICT); + CASE_RETURN_STR(STATUS_TIME_DIFFERENCE_AT_DC); + CASE_RETURN_STR(STATUS_SYNCHRONIZATION_REQUIRED); + CASE_RETURN_STR(STATUS_DLL_NOT_FOUND); + CASE_RETURN_STR(STATUS_OPEN_FAILED); + CASE_RETURN_STR(STATUS_IO_PRIVILEGE_FAILED); + CASE_RETURN_STR(STATUS_ORDINAL_NOT_FOUND); + CASE_RETURN_STR(STATUS_ENTRYPOINT_NOT_FOUND); + CASE_RETURN_STR(STATUS_CONTROL_C_EXIT); + CASE_RETURN_STR(STATUS_LOCAL_DISCONNECT); + CASE_RETURN_STR(STATUS_REMOTE_DISCONNECT); + CASE_RETURN_STR(STATUS_REMOTE_RESOURCES); + CASE_RETURN_STR(STATUS_LINK_FAILED); + CASE_RETURN_STR(STATUS_LINK_TIMEOUT); + CASE_RETURN_STR(STATUS_INVALID_CONNECTION); + CASE_RETURN_STR(STATUS_INVALID_ADDRESS); + CASE_RETURN_STR(STATUS_DLL_INIT_FAILED); + CASE_RETURN_STR(STATUS_MISSING_SYSTEMFILE); + CASE_RETURN_STR(STATUS_UNHANDLED_EXCEPTION); + CASE_RETURN_STR(STATUS_APP_INIT_FAILURE); + CASE_RETURN_STR(STATUS_PAGEFILE_CREATE_FAILED); + CASE_RETURN_STR(STATUS_NO_PAGEFILE); + CASE_RETURN_STR(STATUS_INVALID_LEVEL); + CASE_RETURN_STR(STATUS_WRONG_PASSWORD_CORE); + CASE_RETURN_STR(STATUS_ILLEGAL_FLOAT_CONTEXT); + CASE_RETURN_STR(STATUS_PIPE_BROKEN); + CASE_RETURN_STR(STATUS_REGISTRY_CORRUPT); + CASE_RETURN_STR(STATUS_REGISTRY_IO_FAILED); + CASE_RETURN_STR(STATUS_NO_EVENT_PAIR); + CASE_RETURN_STR(STATUS_UNRECOGNIZED_VOLUME); + CASE_RETURN_STR(STATUS_SERIAL_NO_DEVICE_INITED); + CASE_RETURN_STR(STATUS_NO_SUCH_ALIAS); + CASE_RETURN_STR(STATUS_MEMBER_NOT_IN_ALIAS); + CASE_RETURN_STR(STATUS_MEMBER_IN_ALIAS); + CASE_RETURN_STR(STATUS_ALIAS_EXISTS); + CASE_RETURN_STR(STATUS_LOGON_NOT_GRANTED); + CASE_RETURN_STR(STATUS_TOO_MANY_SECRETS); + CASE_RETURN_STR(STATUS_SECRET_TOO_LONG); + CASE_RETURN_STR(STATUS_INTERNAL_DB_ERROR); + CASE_RETURN_STR(STATUS_FULLSCREEN_MODE); + CASE_RETURN_STR(STATUS_TOO_MANY_CONTEXT_IDS); + CASE_RETURN_STR(STATUS_LOGON_TYPE_NOT_GRANTED); + CASE_RETURN_STR(STATUS_NOT_REGISTRY_FILE); + CASE_RETURN_STR(STATUS_NT_CROSS_ENCRYPTION_REQUIRED); + CASE_RETURN_STR(STATUS_DOMAIN_CTRLR_CONFIG_ERROR); + CASE_RETURN_STR(STATUS_FT_MISSING_MEMBER); + CASE_RETURN_STR(STATUS_ILL_FORMED_SERVICE_ENTRY); + CASE_RETURN_STR(STATUS_ILLEGAL_CHARACTER); + CASE_RETURN_STR(STATUS_UNMAPPABLE_CHARACTER); + CASE_RETURN_STR(STATUS_UNDEFINED_CHARACTER); + CASE_RETURN_STR(STATUS_FLOPPY_VOLUME); + CASE_RETURN_STR(STATUS_FLOPPY_ID_MARK_NOT_FOUND); + CASE_RETURN_STR(STATUS_FLOPPY_WRONG_CYLINDER); + CASE_RETURN_STR(STATUS_FLOPPY_UNKNOWN_ERROR); + CASE_RETURN_STR(STATUS_FLOPPY_BAD_REGISTERS); + CASE_RETURN_STR(STATUS_DISK_RECALIBRATE_FAILED); + CASE_RETURN_STR(STATUS_DISK_OPERATION_FAILED); + CASE_RETURN_STR(STATUS_DISK_RESET_FAILED); + CASE_RETURN_STR(STATUS_SHARED_IRQ_BUSY); + CASE_RETURN_STR(STATUS_FT_ORPHANING); + CASE_RETURN_STR(STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT); + CASE_RETURN_STR(STATUS_PARTITION_FAILURE); + CASE_RETURN_STR(STATUS_INVALID_BLOCK_LENGTH); + CASE_RETURN_STR(STATUS_DEVICE_NOT_PARTITIONED); + CASE_RETURN_STR(STATUS_UNABLE_TO_LOCK_MEDIA); + CASE_RETURN_STR(STATUS_UNABLE_TO_UNLOAD_MEDIA); + CASE_RETURN_STR(STATUS_EOM_OVERFLOW); + CASE_RETURN_STR(STATUS_NO_MEDIA); + CASE_RETURN_STR(STATUS_NO_SUCH_MEMBER); + CASE_RETURN_STR(STATUS_INVALID_MEMBER); + CASE_RETURN_STR(STATUS_KEY_DELETED); + CASE_RETURN_STR(STATUS_NO_LOG_SPACE); + CASE_RETURN_STR(STATUS_TOO_MANY_SIDS); + CASE_RETURN_STR(STATUS_LM_CROSS_ENCRYPTION_REQUIRED); + CASE_RETURN_STR(STATUS_KEY_HAS_CHILDREN); + CASE_RETURN_STR(STATUS_CHILD_MUST_BE_VOLATILE); + CASE_RETURN_STR(STATUS_DEVICE_CONFIGURATION_ERROR); + CASE_RETURN_STR(STATUS_DRIVER_INTERNAL_ERROR); + CASE_RETURN_STR(STATUS_INVALID_DEVICE_STATE); + CASE_RETURN_STR(STATUS_IO_DEVICE_ERROR); + CASE_RETURN_STR(STATUS_DEVICE_PROTOCOL_ERROR); + CASE_RETURN_STR(STATUS_BACKUP_CONTROLLER); + CASE_RETURN_STR(STATUS_LOG_FILE_FULL); + CASE_RETURN_STR(STATUS_TOO_LATE); + CASE_RETURN_STR(STATUS_NO_TRUST_LSA_SECRET); + CASE_RETURN_STR(STATUS_NO_TRUST_SAM_ACCOUNT); + CASE_RETURN_STR(STATUS_TRUSTED_DOMAIN_FAILURE); + CASE_RETURN_STR(STATUS_TRUSTED_RELATIONSHIP_FAILURE); + CASE_RETURN_STR(STATUS_EVENTLOG_FILE_CORRUPT); + CASE_RETURN_STR(STATUS_EVENTLOG_CANT_START); + CASE_RETURN_STR(STATUS_TRUST_FAILURE); + CASE_RETURN_STR(STATUS_MUTANT_LIMIT_EXCEEDED); + CASE_RETURN_STR(STATUS_NETLOGON_NOT_STARTED); + CASE_RETURN_STR(STATUS_ACCOUNT_EXPIRED); + CASE_RETURN_STR(STATUS_POSSIBLE_DEADLOCK); + CASE_RETURN_STR(STATUS_NETWORK_CREDENTIAL_CONFLICT); + CASE_RETURN_STR(STATUS_REMOTE_SESSION_LIMIT); + CASE_RETURN_STR(STATUS_EVENTLOG_FILE_CHANGED); + CASE_RETURN_STR(STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT); + CASE_RETURN_STR(STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT); + CASE_RETURN_STR(STATUS_NOLOGON_SERVER_TRUST_ACCOUNT); + CASE_RETURN_STR(STATUS_DOMAIN_TRUST_INCONSISTENT); + CASE_RETURN_STR(STATUS_FS_DRIVER_REQUIRED); + CASE_RETURN_STR(STATUS_NO_USER_SESSION_KEY); + CASE_RETURN_STR(STATUS_USER_SESSION_DELETED); + CASE_RETURN_STR(STATUS_RESOURCE_LANG_NOT_FOUND); + CASE_RETURN_STR(STATUS_INSUFF_SERVER_RESOURCES); + CASE_RETURN_STR(STATUS_INVALID_BUFFER_SIZE); + CASE_RETURN_STR(STATUS_INVALID_ADDRESS_COMPONENT); + CASE_RETURN_STR(STATUS_INVALID_ADDRESS_WILDCARD); + CASE_RETURN_STR(STATUS_TOO_MANY_ADDRESSES); + CASE_RETURN_STR(STATUS_ADDRESS_ALREADY_EXISTS); + CASE_RETURN_STR(STATUS_ADDRESS_CLOSED); + CASE_RETURN_STR(STATUS_CONNECTION_DISCONNECTED); + CASE_RETURN_STR(STATUS_CONNECTION_RESET); + CASE_RETURN_STR(STATUS_TOO_MANY_NODES); + CASE_RETURN_STR(STATUS_TRANSACTION_ABORTED); + CASE_RETURN_STR(STATUS_TRANSACTION_TIMED_OUT); + CASE_RETURN_STR(STATUS_TRANSACTION_NO_RELEASE); + CASE_RETURN_STR(STATUS_TRANSACTION_NO_MATCH); + CASE_RETURN_STR(STATUS_TRANSACTION_RESPONDED); + CASE_RETURN_STR(STATUS_TRANSACTION_INVALID_ID); + CASE_RETURN_STR(STATUS_TRANSACTION_INVALID_TYPE); + CASE_RETURN_STR(STATUS_NOT_SERVER_SESSION); + CASE_RETURN_STR(STATUS_NOT_CLIENT_SESSION); + CASE_RETURN_STR(STATUS_CANNOT_LOAD_REGISTRY_FILE); + CASE_RETURN_STR(STATUS_DEBUG_ATTACH_FAILED); + CASE_RETURN_STR(STATUS_SYSTEM_PROCESS_TERMINATED); + CASE_RETURN_STR(STATUS_DATA_NOT_ACCEPTED); + CASE_RETURN_STR(STATUS_NO_BROWSER_SERVERS_FOUND); + CASE_RETURN_STR(STATUS_VDM_HARD_ERROR); + CASE_RETURN_STR(STATUS_DRIVER_CANCEL_TIMEOUT); + CASE_RETURN_STR(STATUS_REPLY_MESSAGE_MISMATCH); + CASE_RETURN_STR(STATUS_MAPPED_ALIGNMENT); + CASE_RETURN_STR(STATUS_IMAGE_CHECKSUM_MISMATCH); + CASE_RETURN_STR(STATUS_LOST_WRITEBEHIND_DATA); + CASE_RETURN_STR(STATUS_CLIENT_SERVER_PARAMETERS_INVALID); + CASE_RETURN_STR(STATUS_PASSWORD_MUST_CHANGE); + CASE_RETURN_STR(STATUS_NOT_FOUND); + CASE_RETURN_STR(STATUS_NOT_TINY_STREAM); + CASE_RETURN_STR(STATUS_RECOVERY_FAILURE); + CASE_RETURN_STR(STATUS_STACK_OVERFLOW_READ); + CASE_RETURN_STR(STATUS_FAIL_CHECK); + CASE_RETURN_STR(STATUS_DUPLICATE_OBJECTID); + CASE_RETURN_STR(STATUS_OBJECTID_EXISTS); + CASE_RETURN_STR(STATUS_CONVERT_TO_LARGE); + CASE_RETURN_STR(STATUS_RETRY); + CASE_RETURN_STR(STATUS_FOUND_OUT_OF_SCOPE); + CASE_RETURN_STR(STATUS_ALLOCATE_BUCKET); + CASE_RETURN_STR(STATUS_PROPSET_NOT_FOUND); + CASE_RETURN_STR(STATUS_MARSHALL_OVERFLOW); + CASE_RETURN_STR(STATUS_INVALID_VARIANT); + CASE_RETURN_STR(STATUS_DOMAIN_CONTROLLER_NOT_FOUND); + CASE_RETURN_STR(STATUS_ACCOUNT_LOCKED_OUT); + CASE_RETURN_STR(STATUS_HANDLE_NOT_CLOSABLE); + CASE_RETURN_STR(STATUS_CONNECTION_REFUSED); + CASE_RETURN_STR(STATUS_GRACEFUL_DISCONNECT); + CASE_RETURN_STR(STATUS_ADDRESS_ALREADY_ASSOCIATED); + CASE_RETURN_STR(STATUS_ADDRESS_NOT_ASSOCIATED); + CASE_RETURN_STR(STATUS_CONNECTION_INVALID); + CASE_RETURN_STR(STATUS_CONNECTION_ACTIVE); + CASE_RETURN_STR(STATUS_NETWORK_UNREACHABLE); + CASE_RETURN_STR(STATUS_HOST_UNREACHABLE); + CASE_RETURN_STR(STATUS_PROTOCOL_UNREACHABLE); + CASE_RETURN_STR(STATUS_PORT_UNREACHABLE); + CASE_RETURN_STR(STATUS_REQUEST_ABORTED); + CASE_RETURN_STR(STATUS_CONNECTION_ABORTED); + CASE_RETURN_STR(STATUS_BAD_COMPRESSION_BUFFER); + CASE_RETURN_STR(STATUS_USER_MAPPED_FILE); + CASE_RETURN_STR(STATUS_AUDIT_FAILED); + CASE_RETURN_STR(STATUS_TIMER_RESOLUTION_NOT_SET); + CASE_RETURN_STR(STATUS_CONNECTION_COUNT_LIMIT); + CASE_RETURN_STR(STATUS_LOGIN_TIME_RESTRICTION); + CASE_RETURN_STR(STATUS_LOGIN_WKSTA_RESTRICTION); + CASE_RETURN_STR(STATUS_IMAGE_MP_UP_MISMATCH); + CASE_RETURN_STR(STATUS_INSUFFICIENT_LOGON_INFO); + CASE_RETURN_STR(STATUS_BAD_DLL_ENTRYPOINT); + CASE_RETURN_STR(STATUS_BAD_SERVICE_ENTRYPOINT); + CASE_RETURN_STR(STATUS_LPC_REPLY_LOST); + CASE_RETURN_STR(STATUS_IP_ADDRESS_CONFLICT1); + CASE_RETURN_STR(STATUS_IP_ADDRESS_CONFLICT2); + CASE_RETURN_STR(STATUS_REGISTRY_QUOTA_LIMIT); + CASE_RETURN_STR(STATUS_PATH_NOT_COVERED); + CASE_RETURN_STR(STATUS_NO_CALLBACK_ACTIVE); + CASE_RETURN_STR(STATUS_LICENSE_QUOTA_EXCEEDED); + CASE_RETURN_STR(STATUS_PWD_TOO_SHORT); + CASE_RETURN_STR(STATUS_PWD_TOO_RECENT); + CASE_RETURN_STR(STATUS_PWD_HISTORY_CONFLICT); + CASE_RETURN_STR(STATUS_PLUGPLAY_NO_DEVICE); + CASE_RETURN_STR(STATUS_UNSUPPORTED_COMPRESSION); + CASE_RETURN_STR(STATUS_INVALID_HW_PROFILE); + CASE_RETURN_STR(STATUS_INVALID_PLUGPLAY_DEVICE_PATH); + CASE_RETURN_STR(STATUS_DRIVER_ORDINAL_NOT_FOUND); + CASE_RETURN_STR(STATUS_DRIVER_ENTRYPOINT_NOT_FOUND); + CASE_RETURN_STR(STATUS_RESOURCE_NOT_OWNED); + CASE_RETURN_STR(STATUS_TOO_MANY_LINKS); + CASE_RETURN_STR(STATUS_QUOTA_LIST_INCONSISTENT); + CASE_RETURN_STR(STATUS_FILE_IS_OFFLINE); + CASE_RETURN_STR(STATUS_EVALUATION_EXPIRATION); + CASE_RETURN_STR(STATUS_ILLEGAL_DLL_RELOCATION); + CASE_RETURN_STR(STATUS_LICENSE_VIOLATION); + CASE_RETURN_STR(STATUS_DLL_INIT_FAILED_LOGOFF); + CASE_RETURN_STR(STATUS_DRIVER_UNABLE_TO_LOAD); + CASE_RETURN_STR(STATUS_DFS_UNAVAILABLE); + CASE_RETURN_STR(STATUS_VOLUME_DISMOUNTED); + CASE_RETURN_STR(STATUS_WX86_INTERNAL_ERROR); + CASE_RETURN_STR(STATUS_WX86_FLOAT_STACK_CHECK); + CASE_RETURN_STR(STATUS_VALIDATE_CONTINUE); + CASE_RETURN_STR(STATUS_NO_MATCH); + CASE_RETURN_STR(STATUS_NO_MORE_MATCHES); + CASE_RETURN_STR(STATUS_NOT_A_REPARSE_POINT); + CASE_RETURN_STR(STATUS_IO_REPARSE_TAG_INVALID); + CASE_RETURN_STR(STATUS_IO_REPARSE_TAG_MISMATCH); + CASE_RETURN_STR(STATUS_IO_REPARSE_DATA_INVALID); + CASE_RETURN_STR(STATUS_IO_REPARSE_TAG_NOT_HANDLED); + CASE_RETURN_STR(STATUS_REPARSE_POINT_NOT_RESOLVED); + CASE_RETURN_STR(STATUS_DIRECTORY_IS_A_REPARSE_POINT); + CASE_RETURN_STR(STATUS_RANGE_LIST_CONFLICT); + CASE_RETURN_STR(STATUS_SOURCE_ELEMENT_EMPTY); + CASE_RETURN_STR(STATUS_DESTINATION_ELEMENT_FULL); + CASE_RETURN_STR(STATUS_ILLEGAL_ELEMENT_ADDRESS); + CASE_RETURN_STR(STATUS_MAGAZINE_NOT_PRESENT); + CASE_RETURN_STR(STATUS_REINITIALIZATION_NEEDED); + CASE_RETURN_STR(STATUS_DEVICE_REQUIRES_CLEANING); + CASE_RETURN_STR(STATUS_DEVICE_DOOR_OPEN); + CASE_RETURN_STR(STATUS_ENCRYPTION_FAILED); + CASE_RETURN_STR(STATUS_DECRYPTION_FAILED); + CASE_RETURN_STR(STATUS_RANGE_NOT_FOUND); + CASE_RETURN_STR(STATUS_NO_RECOVERY_POLICY); + CASE_RETURN_STR(STATUS_NO_EFS); + CASE_RETURN_STR(STATUS_WRONG_EFS); + CASE_RETURN_STR(STATUS_NO_USER_KEYS); + CASE_RETURN_STR(STATUS_FILE_NOT_ENCRYPTED); + CASE_RETURN_STR(STATUS_NOT_EXPORT_FORMAT); + CASE_RETURN_STR(STATUS_FILE_ENCRYPTED); + CASE_RETURN_STR(STATUS_WAKE_SYSTEM); + CASE_RETURN_STR(STATUS_WMI_GUID_NOT_FOUND); + CASE_RETURN_STR(STATUS_WMI_INSTANCE_NOT_FOUND); + CASE_RETURN_STR(STATUS_WMI_ITEMID_NOT_FOUND); + CASE_RETURN_STR(STATUS_WMI_TRY_AGAIN); + CASE_RETURN_STR(STATUS_SHARED_POLICY); + CASE_RETURN_STR(STATUS_POLICY_OBJECT_NOT_FOUND); + CASE_RETURN_STR(STATUS_POLICY_ONLY_IN_DS); + CASE_RETURN_STR(STATUS_VOLUME_NOT_UPGRADED); + CASE_RETURN_STR(STATUS_REMOTE_STORAGE_NOT_ACTIVE); + CASE_RETURN_STR(STATUS_REMOTE_STORAGE_MEDIA_ERROR); + CASE_RETURN_STR(STATUS_NO_TRACKING_SERVICE); + CASE_RETURN_STR(STATUS_SERVER_SID_MISMATCH); + CASE_RETURN_STR(STATUS_DS_NO_ATTRIBUTE_OR_VALUE); + CASE_RETURN_STR(STATUS_DS_INVALID_ATTRIBUTE_SYNTAX); + CASE_RETURN_STR(STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED); + CASE_RETURN_STR(STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS); + CASE_RETURN_STR(STATUS_DS_BUSY); + CASE_RETURN_STR(STATUS_DS_UNAVAILABLE); + CASE_RETURN_STR(STATUS_DS_NO_RIDS_ALLOCATED); + CASE_RETURN_STR(STATUS_DS_NO_MORE_RIDS); + CASE_RETURN_STR(STATUS_DS_INCORRECT_ROLE_OWNER); + CASE_RETURN_STR(STATUS_DS_RIDMGR_INIT_ERROR); + CASE_RETURN_STR(STATUS_DS_OBJ_CLASS_VIOLATION); + CASE_RETURN_STR(STATUS_DS_CANT_ON_NON_LEAF); + CASE_RETURN_STR(STATUS_DS_CANT_ON_RDN); + CASE_RETURN_STR(STATUS_DS_CANT_MOD_OBJ_CLASS); + CASE_RETURN_STR(STATUS_DS_CROSS_DOM_MOVE_FAILED); + CASE_RETURN_STR(STATUS_DS_GC_NOT_AVAILABLE); + CASE_RETURN_STR(STATUS_DIRECTORY_SERVICE_REQUIRED); + CASE_RETURN_STR(STATUS_REPARSE_ATTRIBUTE_CONFLICT); + CASE_RETURN_STR(STATUS_CANT_ENABLE_DENY_ONLY); + CASE_RETURN_STR(STATUS_FLOAT_MULTIPLE_FAULTS); + CASE_RETURN_STR(STATUS_FLOAT_MULTIPLE_TRAPS); + CASE_RETURN_STR(STATUS_DEVICE_REMOVED); + CASE_RETURN_STR(STATUS_JOURNAL_DELETE_IN_PROGRESS); + CASE_RETURN_STR(STATUS_JOURNAL_NOT_ACTIVE); + CASE_RETURN_STR(STATUS_NOINTERFACE); + CASE_RETURN_STR(STATUS_DS_ADMIN_LIMIT_EXCEEDED); + CASE_RETURN_STR(STATUS_DRIVER_FAILED_SLEEP); + CASE_RETURN_STR(STATUS_MUTUAL_AUTHENTICATION_FAILED); + CASE_RETURN_STR(STATUS_CORRUPT_SYSTEM_FILE); + CASE_RETURN_STR(STATUS_DATATYPE_MISALIGNMENT_ERROR); + CASE_RETURN_STR(STATUS_WMI_READ_ONLY); + CASE_RETURN_STR(STATUS_WMI_SET_FAILURE); + CASE_RETURN_STR(STATUS_COMMITMENT_MINIMUM); + CASE_RETURN_STR(STATUS_REG_NAT_CONSUMPTION); + CASE_RETURN_STR(STATUS_TRANSPORT_FULL); + CASE_RETURN_STR(STATUS_DS_SAM_INIT_FAILURE); + CASE_RETURN_STR(STATUS_ONLY_IF_CONNECTED); + CASE_RETURN_STR(STATUS_DS_SENSITIVE_GROUP_VIOLATION); + CASE_RETURN_STR(STATUS_PNP_RESTART_ENUMERATION); + CASE_RETURN_STR(STATUS_JOURNAL_ENTRY_DELETED); + CASE_RETURN_STR(STATUS_DS_CANT_MOD_PRIMARYGROUPID); + CASE_RETURN_STR(STATUS_SYSTEM_IMAGE_BAD_SIGNATURE); + CASE_RETURN_STR(STATUS_PNP_REBOOT_REQUIRED); + CASE_RETURN_STR(STATUS_POWER_STATE_INVALID); + CASE_RETURN_STR(STATUS_DS_INVALID_GROUP_TYPE); + CASE_RETURN_STR(STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN); + CASE_RETURN_STR(STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN); + CASE_RETURN_STR(STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER); + CASE_RETURN_STR(STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER); + CASE_RETURN_STR(STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER); + CASE_RETURN_STR(STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER); + CASE_RETURN_STR(STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER); + CASE_RETURN_STR(STATUS_DS_HAVE_PRIMARY_MEMBERS); + CASE_RETURN_STR(STATUS_WMI_NOT_SUPPORTED); + CASE_RETURN_STR(STATUS_INSUFFICIENT_POWER); + CASE_RETURN_STR(STATUS_SAM_NEED_BOOTKEY_PASSWORD); + CASE_RETURN_STR(STATUS_SAM_NEED_BOOTKEY_FLOPPY); + CASE_RETURN_STR(STATUS_DS_CANT_START); + CASE_RETURN_STR(STATUS_DS_INIT_FAILURE); + CASE_RETURN_STR(STATUS_SAM_INIT_FAILURE); + CASE_RETURN_STR(STATUS_DS_GC_REQUIRED); + CASE_RETURN_STR(STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY); + CASE_RETURN_STR(STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS); + CASE_RETURN_STR(STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED); + CASE_RETURN_STR(STATUS_MULTIPLE_FAULT_VIOLATION); + CASE_RETURN_STR(STATUS_NOT_SUPPORTED_ON_SBS); + CASE_RETURN_STR(STATUS_WOW_ASSERTION); + CASE_RETURN_STR(DBG_NO_STATE_CHANGE); + CASE_RETURN_STR(DBG_APP_NOT_IDLE); + CASE_RETURN_STR(RPC_NT_INVALID_STRING_BINDING); + CASE_RETURN_STR(RPC_NT_WRONG_KIND_OF_BINDING); + CASE_RETURN_STR(RPC_NT_INVALID_BINDING); + CASE_RETURN_STR(RPC_NT_PROTSEQ_NOT_SUPPORTED); + CASE_RETURN_STR(RPC_NT_INVALID_RPC_PROTSEQ); + CASE_RETURN_STR(RPC_NT_INVALID_STRING_UUID); + CASE_RETURN_STR(RPC_NT_INVALID_ENDPOINT_FORMAT); + CASE_RETURN_STR(RPC_NT_INVALID_NET_ADDR); + CASE_RETURN_STR(RPC_NT_NO_ENDPOINT_FOUND); + CASE_RETURN_STR(RPC_NT_INVALID_TIMEOUT); + CASE_RETURN_STR(RPC_NT_OBJECT_NOT_FOUND); + CASE_RETURN_STR(RPC_NT_ALREADY_REGISTERED); + CASE_RETURN_STR(RPC_NT_TYPE_ALREADY_REGISTERED); + CASE_RETURN_STR(RPC_NT_ALREADY_LISTENING); + CASE_RETURN_STR(RPC_NT_NO_PROTSEQS_REGISTERED); + CASE_RETURN_STR(RPC_NT_NOT_LISTENING); + CASE_RETURN_STR(RPC_NT_UNKNOWN_MGR_TYPE); + CASE_RETURN_STR(RPC_NT_UNKNOWN_IF); + CASE_RETURN_STR(RPC_NT_NO_BINDINGS); + CASE_RETURN_STR(RPC_NT_NO_PROTSEQS); + CASE_RETURN_STR(RPC_NT_CANT_CREATE_ENDPOINT); + CASE_RETURN_STR(RPC_NT_OUT_OF_RESOURCES); + CASE_RETURN_STR(RPC_NT_SERVER_UNAVAILABLE); + CASE_RETURN_STR(RPC_NT_SERVER_TOO_BUSY); + CASE_RETURN_STR(RPC_NT_INVALID_NETWORK_OPTIONS); + CASE_RETURN_STR(RPC_NT_NO_CALL_ACTIVE); + CASE_RETURN_STR(RPC_NT_CALL_FAILED); + CASE_RETURN_STR(RPC_NT_CALL_FAILED_DNE); + CASE_RETURN_STR(RPC_NT_PROTOCOL_ERROR); + CASE_RETURN_STR(RPC_NT_UNSUPPORTED_TRANS_SYN); + CASE_RETURN_STR(RPC_NT_UNSUPPORTED_TYPE); + CASE_RETURN_STR(RPC_NT_INVALID_TAG); + CASE_RETURN_STR(RPC_NT_INVALID_BOUND); + CASE_RETURN_STR(RPC_NT_NO_ENTRY_NAME); + CASE_RETURN_STR(RPC_NT_INVALID_NAME_SYNTAX); + CASE_RETURN_STR(RPC_NT_UNSUPPORTED_NAME_SYNTAX); + CASE_RETURN_STR(RPC_NT_UUID_NO_ADDRESS); + CASE_RETURN_STR(RPC_NT_DUPLICATE_ENDPOINT); + CASE_RETURN_STR(RPC_NT_UNKNOWN_AUTHN_TYPE); + CASE_RETURN_STR(RPC_NT_MAX_CALLS_TOO_SMALL); + CASE_RETURN_STR(RPC_NT_STRING_TOO_LONG); + CASE_RETURN_STR(RPC_NT_PROTSEQ_NOT_FOUND); + CASE_RETURN_STR(RPC_NT_PROCNUM_OUT_OF_RANGE); + CASE_RETURN_STR(RPC_NT_BINDING_HAS_NO_AUTH); + CASE_RETURN_STR(RPC_NT_UNKNOWN_AUTHN_SERVICE); + CASE_RETURN_STR(RPC_NT_UNKNOWN_AUTHN_LEVEL); + CASE_RETURN_STR(RPC_NT_INVALID_AUTH_IDENTITY); + CASE_RETURN_STR(RPC_NT_UNKNOWN_AUTHZ_SERVICE); + CASE_RETURN_STR(EPT_NT_INVALID_ENTRY); + CASE_RETURN_STR(EPT_NT_CANT_PERFORM_OP); + CASE_RETURN_STR(EPT_NT_NOT_REGISTERED); + CASE_RETURN_STR(RPC_NT_NOTHING_TO_EXPORT); + CASE_RETURN_STR(RPC_NT_INCOMPLETE_NAME); + CASE_RETURN_STR(RPC_NT_INVALID_VERS_OPTION); + CASE_RETURN_STR(RPC_NT_NO_MORE_MEMBERS); + CASE_RETURN_STR(RPC_NT_NOT_ALL_OBJS_UNEXPORTED); + CASE_RETURN_STR(RPC_NT_INTERFACE_NOT_FOUND); + CASE_RETURN_STR(RPC_NT_ENTRY_ALREADY_EXISTS); + CASE_RETURN_STR(RPC_NT_ENTRY_NOT_FOUND); + CASE_RETURN_STR(RPC_NT_NAME_SERVICE_UNAVAILABLE); + CASE_RETURN_STR(RPC_NT_INVALID_NAF_ID); + CASE_RETURN_STR(RPC_NT_CANNOT_SUPPORT); + CASE_RETURN_STR(RPC_NT_NO_CONTEXT_AVAILABLE); + CASE_RETURN_STR(RPC_NT_INTERNAL_ERROR); + CASE_RETURN_STR(RPC_NT_ZERO_DIVIDE); + CASE_RETURN_STR(RPC_NT_ADDRESS_ERROR); + CASE_RETURN_STR(RPC_NT_FP_DIV_ZERO); + CASE_RETURN_STR(RPC_NT_FP_UNDERFLOW); + CASE_RETURN_STR(RPC_NT_FP_OVERFLOW); + CASE_RETURN_STR(RPC_NT_NO_MORE_ENTRIES); + CASE_RETURN_STR(RPC_NT_SS_CHAR_TRANS_OPEN_FAIL); + CASE_RETURN_STR(RPC_NT_SS_CHAR_TRANS_SHORT_FILE); + CASE_RETURN_STR(RPC_NT_SS_IN_NULL_CONTEXT); + CASE_RETURN_STR(RPC_NT_SS_CONTEXT_MISMATCH); + CASE_RETURN_STR(RPC_NT_SS_CONTEXT_DAMAGED); + CASE_RETURN_STR(RPC_NT_SS_HANDLES_MISMATCH); + CASE_RETURN_STR(RPC_NT_SS_CANNOT_GET_CALL_HANDLE); + CASE_RETURN_STR(RPC_NT_NULL_REF_POINTER); + CASE_RETURN_STR(RPC_NT_ENUM_VALUE_OUT_OF_RANGE); + CASE_RETURN_STR(RPC_NT_BYTE_COUNT_TOO_SMALL); + CASE_RETURN_STR(RPC_NT_BAD_STUB_DATA); + CASE_RETURN_STR(RPC_NT_CALL_IN_PROGRESS); + CASE_RETURN_STR(RPC_NT_NO_MORE_BINDINGS); + CASE_RETURN_STR(RPC_NT_GROUP_MEMBER_NOT_FOUND); + CASE_RETURN_STR(EPT_NT_CANT_CREATE); + CASE_RETURN_STR(RPC_NT_INVALID_OBJECT); + CASE_RETURN_STR(RPC_NT_NO_INTERFACES); + CASE_RETURN_STR(RPC_NT_CALL_CANCELLED); + CASE_RETURN_STR(RPC_NT_BINDING_INCOMPLETE); + CASE_RETURN_STR(RPC_NT_COMM_FAILURE); + CASE_RETURN_STR(RPC_NT_UNSUPPORTED_AUTHN_LEVEL); + CASE_RETURN_STR(RPC_NT_NO_PRINC_NAME); + CASE_RETURN_STR(RPC_NT_NOT_RPC_ERROR); + CASE_RETURN_STR(RPC_NT_UUID_LOCAL_ONLY); + CASE_RETURN_STR(RPC_NT_SEC_PKG_ERROR); + CASE_RETURN_STR(RPC_NT_NOT_CANCELLED); + CASE_RETURN_STR(RPC_NT_INVALID_ES_ACTION); + CASE_RETURN_STR(RPC_NT_WRONG_ES_VERSION); + CASE_RETURN_STR(RPC_NT_WRONG_STUB_VERSION); + CASE_RETURN_STR(RPC_NT_INVALID_PIPE_OBJECT); + CASE_RETURN_STR(RPC_NT_INVALID_PIPE_OPERATION); + CASE_RETURN_STR(RPC_NT_WRONG_PIPE_VERSION); + CASE_RETURN_STR(RPC_NT_PIPE_CLOSED); + CASE_RETURN_STR(RPC_NT_PIPE_DISCIPLINE_ERROR); + CASE_RETURN_STR(RPC_NT_PIPE_EMPTY); + CASE_RETURN_STR(RPC_NT_INVALID_ASYNC_HANDLE); + CASE_RETURN_STR(RPC_NT_INVALID_ASYNC_CALL); + CASE_RETURN_STR(RPC_NT_SEND_INCOMPLETE); + CASE_RETURN_STR(STATUS_ACPI_INVALID_OPCODE); + CASE_RETURN_STR(STATUS_ACPI_STACK_OVERFLOW); + CASE_RETURN_STR(STATUS_ACPI_ASSERT_FAILED); + CASE_RETURN_STR(STATUS_ACPI_INVALID_INDEX); + CASE_RETURN_STR(STATUS_ACPI_INVALID_ARGUMENT); + CASE_RETURN_STR(STATUS_ACPI_FATAL); + CASE_RETURN_STR(STATUS_ACPI_INVALID_SUPERNAME); + CASE_RETURN_STR(STATUS_ACPI_INVALID_ARGTYPE); + CASE_RETURN_STR(STATUS_ACPI_INVALID_OBJTYPE); + CASE_RETURN_STR(STATUS_ACPI_INVALID_TARGETTYPE); + CASE_RETURN_STR(STATUS_ACPI_INCORRECT_ARGUMENT_COUNT); + CASE_RETURN_STR(STATUS_ACPI_ADDRESS_NOT_MAPPED); + CASE_RETURN_STR(STATUS_ACPI_INVALID_EVENTTYPE); + CASE_RETURN_STR(STATUS_ACPI_HANDLER_COLLISION); + CASE_RETURN_STR(STATUS_ACPI_INVALID_DATA); + CASE_RETURN_STR(STATUS_ACPI_INVALID_REGION); + CASE_RETURN_STR(STATUS_ACPI_INVALID_ACCESS_SIZE); + CASE_RETURN_STR(STATUS_ACPI_ACQUIRE_GLOBAL_LOCK); + CASE_RETURN_STR(STATUS_ACPI_ALREADY_INITIALIZED); + CASE_RETURN_STR(STATUS_ACPI_NOT_INITIALIZED); + CASE_RETURN_STR(STATUS_ACPI_INVALID_MUTEX_LEVEL); + CASE_RETURN_STR(STATUS_ACPI_MUTEX_NOT_OWNED); + CASE_RETURN_STR(STATUS_ACPI_MUTEX_NOT_OWNER); + CASE_RETURN_STR(STATUS_ACPI_RS_ACCESS); + CASE_RETURN_STR(STATUS_ACPI_INVALID_TABLE); + CASE_RETURN_STR(STATUS_ACPI_REG_HANDLER_FAILED); + CASE_RETURN_STR(STATUS_ACPI_POWER_REQUEST_FAILED); + CASE_RETURN_STR(STATUS_CTX_WINSTATION_NAME_INVALID); + CASE_RETURN_STR(STATUS_CTX_INVALID_PD); + CASE_RETURN_STR(STATUS_CTX_PD_NOT_FOUND); + CASE_RETURN_STR(STATUS_CTX_CDM_CONNECT); + CASE_RETURN_STR(STATUS_CTX_CDM_DISCONNECT); + CASE_RETURN_STR(STATUS_CTX_CLOSE_PENDING); + CASE_RETURN_STR(STATUS_CTX_NO_OUTBUF); + CASE_RETURN_STR(STATUS_CTX_MODEM_INF_NOT_FOUND); + CASE_RETURN_STR(STATUS_CTX_INVALID_MODEMNAME); + CASE_RETURN_STR(STATUS_CTX_RESPONSE_ERROR); + CASE_RETURN_STR(STATUS_CTX_MODEM_RESPONSE_TIMEOUT); + CASE_RETURN_STR(STATUS_CTX_MODEM_RESPONSE_NO_CARRIER); + CASE_RETURN_STR(STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE); + CASE_RETURN_STR(STATUS_CTX_MODEM_RESPONSE_BUSY); + CASE_RETURN_STR(STATUS_CTX_MODEM_RESPONSE_VOICE); + CASE_RETURN_STR(STATUS_CTX_TD_ERROR); + CASE_RETURN_STR(STATUS_CTX_LICENSE_CLIENT_INVALID); + CASE_RETURN_STR(STATUS_CTX_LICENSE_NOT_AVAILABLE); + CASE_RETURN_STR(STATUS_CTX_LICENSE_EXPIRED); + CASE_RETURN_STR(STATUS_CTX_WINSTATION_NOT_FOUND); + CASE_RETURN_STR(STATUS_CTX_WINSTATION_NAME_COLLISION); + CASE_RETURN_STR(STATUS_CTX_WINSTATION_BUSY); + CASE_RETURN_STR(STATUS_CTX_BAD_VIDEO_MODE); + CASE_RETURN_STR(STATUS_CTX_GRAPHICS_INVALID); + CASE_RETURN_STR(STATUS_CTX_NOT_CONSOLE); + CASE_RETURN_STR(STATUS_CTX_CLIENT_QUERY_TIMEOUT); + CASE_RETURN_STR(STATUS_CTX_CONSOLE_DISCONNECT); + CASE_RETURN_STR(STATUS_CTX_CONSOLE_CONNECT); + CASE_RETURN_STR(STATUS_CTX_SHADOW_DENIED); + CASE_RETURN_STR(STATUS_CTX_WINSTATION_ACCESS_DENIED); + CASE_RETURN_STR(STATUS_CTX_INVALID_WD); + CASE_RETURN_STR(STATUS_CTX_WD_NOT_FOUND); + CASE_RETURN_STR(STATUS_CTX_SHADOW_INVALID); + CASE_RETURN_STR(STATUS_CTX_SHADOW_DISABLED); + CASE_RETURN_STR(STATUS_RDP_PROTOCOL_ERROR); + CASE_RETURN_STR(STATUS_CTX_CLIENT_LICENSE_NOT_SET); + CASE_RETURN_STR(STATUS_CTX_CLIENT_LICENSE_IN_USE); + CASE_RETURN_STR(STATUS_PNP_BAD_MPS_TABLE); + CASE_RETURN_STR(STATUS_PNP_TRANSLATION_FAILED); + CASE_RETURN_STR(STATUS_PNP_IRQ_TRANSLATION_FAILED); + default: + return "Unknown"; + } +} +#endif // DBG diff --git a/modules/rosapps/drivers/vfd/vfddbg.h b/modules/rosapps/drivers/vfd/vfddbg.h new file mode 100644 index 00000000000..08bf8c51809 --- /dev/null +++ b/modules/rosapps/drivers/vfd/vfddbg.h @@ -0,0 +1,79 @@ +/* + vfddbg.h + + Virtual Floppy Drive for Windows NT platform + Kernel mode driver: debug functions header + + Copyright (C) 2003-2005 Ken Kato +*/ + +#ifndef _VFDDBG_H_ +#define _VFDDBG_H_ + +#if DBG + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +PCSTR +GetStatusName( + NTSTATUS status); + +PCSTR +GetMajorFuncName( + UCHAR major_code); + +PCSTR +GetIoControlName( + ULONG ctrl_code); + +#ifdef VFD_PNP + +PCSTR +GetPnpIrpName( + ULONG minor_code); + +PCSTR +GetPowerIrpName( + ULONG minor_code); + +PCSTR +GetSystemIrpName( + ULONG minor_code); + +#endif // VFD_PNP + +// +// Debug Trace Level Flags +// +#define VFDERR 0x00000000 +#define VFDWARN 0x00000001 +#define VFDINFO 0x00000003 + +#define VFDDEV 0x00000004 +#define VFDDRV 0x00000008 +#define VFDRDWR 0x00000010 +#define VFDIMG 0x00000020 +#define VFDLINK 0x00000040 +#define VFDFMT 0x00000080 +#define VFDCTL 0x00000100 +#define VFDMNT 0x00000200 +#define VFDPNP 0x00000400 + +#define VFDTRACE(LEVEL,STRING) \ + if ((TraceFlags & (LEVEL)) == (LEVEL)) { \ + DbgPrint STRING; \ + } + +extern ULONG TraceFlags; + +#else // DBG +#define VFDTRACE(LEVEL,STRING) +#endif // DBG + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // _VFDDBG_H_ diff --git a/modules/rosapps/drivers/vfd/vfddev.c b/modules/rosapps/drivers/vfd/vfddev.c new file mode 100644 index 00000000000..6aee0bcd8a2 --- /dev/null +++ b/modules/rosapps/drivers/vfd/vfddev.c @@ -0,0 +1,407 @@ +/* + vfddev.c + + Virtual Floppy Drive for Windows NT platform + Kernel mode driver: device create/delete functions + + Copyright (C) 2003-2005 Ken Kato +*/ + +#include "imports.h" +#include "vfddrv.h" +#include "vfddbg.h" + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, VfdCreateDevice) +#pragma alloc_text(PAGE, VfdDeleteDevice) +#endif // ALLOC_PRAGMA + +// +// Create a VFD device object +// +NTSTATUS +VfdCreateDevice( + IN PDRIVER_OBJECT DriverObject, + OUT PVOID Parameter) +{ + NTSTATUS status; + ULONG physical_num; + + UNICODE_STRING unicode_name; + WCHAR name_buffer[40]; + + PVFD_DRIVER_EXTENSION driver_extension = NULL; + PDEVICE_OBJECT device_object = NULL; + PDEVICE_EXTENSION device_extension = NULL; + HANDLE thread_handle = NULL; + + VFDTRACE(VFDINFO | VFDDEV, ("[VFD] VfdCreateDevice - IN\n")); + +#ifdef VFD_PNP + + // Get the driver device_extension for the driver object + driver_extension = IoGetDriverObjectExtension( + DriverObject, VFD_DRIVER_EXTENSION_ID); + +#else // VFD_PNP + + // The driver device_extension is passed as the Parameter + driver_extension = (PVFD_DRIVER_EXTENSION)Parameter; + +#endif // VFD_PNP + + if (driver_extension == NULL) { + VFDTRACE(VFDERR, ("[VFD] Failed to get the driver extension\n")); + return STATUS_DRIVER_INTERNAL_ERROR; + } + + // + // Create a device object + // \Device\Floppy + // + physical_num = 0; + + do { + name_buffer[sizeof(name_buffer) - 1] = UNICODE_NULL; + + _snwprintf(name_buffer, sizeof(name_buffer) - 1, + L"\\Device\\Floppy%lu", physical_num); + + RtlInitUnicodeString(&unicode_name, name_buffer); + + status = IoCreateDevice( + DriverObject, + sizeof(DEVICE_EXTENSION), + &unicode_name, + FILE_DEVICE_DISK, + FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE | FILE_DEVICE_SECURE_OPEN, + FALSE, + &device_object); + + if (status != STATUS_OBJECT_NAME_EXISTS && + status != STATUS_OBJECT_NAME_COLLISION) { + break; + } + } + while (++physical_num < 100); + + if (!NT_SUCCESS(status)) { + VFDTRACE(VFDERR, + ("[VFD] IoCreateDevice() %s\n", + GetStatusName(status))); + return status; + } + + IoGetConfigurationInformation()->FloppyCount++; + + VFDTRACE(VFDINFO | VFDDEV, + ("[VFD] Created a device object %ws\n", name_buffer)); + + // + // Initialize the device object / device extension + // + + device_object->Flags |= DO_DIRECT_IO; + + device_extension = (PDEVICE_EXTENSION)device_object->DeviceExtension; + + RtlZeroMemory(device_extension, sizeof(DEVICE_EXTENSION)); + + // Store the back pointer to the device object + + device_extension->DeviceObject = device_object; + + // Store the logical device number + + device_extension->DeviceNumber = driver_extension->NumberOfDevices; + + // Store the device name + + if (!VfdCopyUnicode(&(device_extension->DeviceName), &unicode_name)) { + VFDTRACE(VFDERR, + ("[VFD] Failed to allocate device name buffer\n")); + status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + // set the default disk geometry (3.5" 1.44M) + + device_extension->Geometry = &geom_tbl[0]; + + // Create the interface link (\??\VirtualFD) + + name_buffer[sizeof(name_buffer) - 1] = UNICODE_NULL; + + _snwprintf(name_buffer, sizeof(name_buffer) - 1, + L"\\??\\" VFD_DEVICE_BASENAME L"%lu", + device_extension->DeviceNumber); + + RtlInitUnicodeString(&unicode_name, name_buffer); + + status = IoCreateSymbolicLink( + &unicode_name, &device_extension->DeviceName); + + if (!NT_SUCCESS(status)) { + VFDTRACE(VFDERR, + ("[VFD] IoCreateSymbolicLink(%ws) %s\n", + name_buffer, GetStatusName(status))); + goto cleanup; + } + + VFDTRACE(VFDINFO|VFDDEV, + ("[VFD] Created a symbolic link %ws\n", name_buffer)); + + // Prepare the IRP queue list for the device thread + + InitializeListHead(&device_extension->ListHead); + + KeInitializeSpinLock(&device_extension->ListLock); + + KeInitializeEvent( + &device_extension->RequestEvent, + SynchronizationEvent, + FALSE); + + // Create the device thread + + device_extension->TerminateThread = FALSE; + + status = PsCreateSystemThread( + &thread_handle, + (ACCESS_MASK) 0L, + NULL, + NULL, + NULL, + VfdDeviceThread, + device_object); + + if (!NT_SUCCESS(status)) { + VFDTRACE(VFDERR, + ("[VFD] PsCreateSystemThread() %s\n", + GetStatusName(status))); + goto cleanup; + } + + // get a reference pointer to the thread + + status = ObReferenceObjectByHandle( + thread_handle, + THREAD_ALL_ACCESS, + NULL, + KernelMode, + &device_extension->ThreadPointer, + NULL); + + ZwClose(thread_handle); + + if (!NT_SUCCESS(status)) { + VFDTRACE(VFDERR, + ("[VFD] ObReferenceObjectByHandle() %s\n", + GetStatusName(status))); + goto cleanup; + } + + // + // Load the persistent drive letter from the registry + // + if (driver_extension->RegistryPath.Buffer) { + VfdLoadLink(device_extension, + driver_extension->RegistryPath.Buffer); + // error is not fatal here + } + + // increment the number of devices in the driver extension + + driver_extension->NumberOfDevices++; + + if (DriverObject->DriverUnload) { + // not called from the DriverEntry routine + device_object->Flags &= ~DO_DEVICE_INITIALIZING; + } + +#ifdef VFD_PNP + if (Parameter) { + // return the device object pointer + *(PDEVICE_OBJECT *)Parameter = device_object; + } +#else // VFD_PNP + device_extension->DriverExtension = driver_extension; +#endif // VFD_PNP + + VFDTRACE(VFDINFO | VFDDEV, ("[VFD] VfdCreateDevice - OK\n")); + + return STATUS_SUCCESS; + +cleanup: + // + // Something went wrong at one point + // Delete all resources that might be created in this function + // + if (thread_handle) { + + // terminate the device thread + device_extension->TerminateThread = TRUE; + + KeSetEvent( + &device_extension->RequestEvent, + (KPRIORITY) 0, + FALSE); + + if (device_extension->ThreadPointer) { + ObDereferenceObject(device_extension->ThreadPointer); + } + } + + VFDTRACE(VFDINFO|VFDDEV, + ("[VFD] Deleting symbolic link %ws\n", name_buffer)); + + IoDeleteSymbolicLink(&unicode_name); + + if (device_extension->DeviceName.Buffer) { + VFDTRACE(VFDINFO|VFDDEV, ("[VFD] Deleting device %ws\n", + device_extension->DeviceName.Buffer)); + + ExFreePool(device_extension->DeviceName.Buffer); + } + + IoDeleteDevice(device_object); + IoGetConfigurationInformation()->FloppyCount--; + + VFDTRACE(VFDINFO|VFDDEV, + ("[VFD] VfdCreateDevice - %s\n", + GetStatusName(status))); + + return status; +} + +// +// delete a VFD device object +// +VOID +VfdDeleteDevice( + IN PDEVICE_OBJECT DeviceObject) +{ + PDEVICE_EXTENSION device_extension; + PVFD_DRIVER_EXTENSION driver_extension; + UNICODE_STRING unicode_name; + WCHAR name_buffer[40]; + + VFDTRACE(VFDINFO|VFDDEV, ("[VFD] VfdDeleteDevice - IN\n")); + + device_extension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; + + // + // decrement the number of device in the driver extension + // +#ifdef VFD_PNP + driver_extension = IoGetDriverObjectExtension( + DeviceObject->DriverObject, VFD_DRIVER_EXTENSION_ID); +#else // VFD_PNP + driver_extension = device_extension->DriverExtension; +#endif // VFD_PNP + + if (driver_extension) { + driver_extension->NumberOfDevices--; + } + + // + // cleanup the device object + // + + // Terminate the device thread + + device_extension->TerminateThread = TRUE; + + KeSetEvent( + &device_extension->RequestEvent, + (KPRIORITY) 0, + FALSE); + + KeWaitForSingleObject( + device_extension->ThreadPointer, + Executive, + KernelMode, + FALSE, + NULL); + + ObDereferenceObject( + device_extension->ThreadPointer); + + // Delete security context object + + if (device_extension->SecurityContext) { + SeDeleteClientSecurity(device_extension->SecurityContext); + ExFreePool(device_extension->SecurityContext); + } + + // Close the image file or free the image buffer + + if (device_extension->FileHandle) { + ZwClose(device_extension->FileHandle); + } + + if (device_extension->FileBuffer) { + ExFreePool(device_extension->FileBuffer); + } + + // Release the image path buffer + + if (device_extension->FileName.Buffer) { + ExFreePool(device_extension->FileName.Buffer); + } + + // Remove the interface symbolic link + + name_buffer[sizeof(name_buffer) - 1] = UNICODE_NULL; + + _snwprintf(name_buffer, sizeof(name_buffer) - 1, + L"\\??\\" VFD_DEVICE_BASENAME L"%lu", + device_extension->DeviceNumber); + + RtlInitUnicodeString(&unicode_name, name_buffer); + + VFDTRACE(VFDINFO|VFDDEV, + ("[VFD] Deleting link %ws\n", name_buffer)); + + IoDeleteSymbolicLink(&unicode_name); + + // Remove the persistent drive letter + + if (device_extension->DriveLetter) { +#ifdef VFD_MOUNT_MANAGER + if (OsMajorVersion >= 5) { + // Request the mount manager to remove the drive letter. + // This will cause the mount manager to update its database + // and it won't arbitrarily assign the drive letter the next + // time the driver starts. + VfdMountMgrMountPoint(device_extension, 0); + } + else +#endif // VFD_MOUNT_MANAGER + { + // Windows NT style drive letter handling + // Simply remove the symbolic link + VfdSetLink(device_extension, 0); + } + } + + // Release the device name buffer + + if (device_extension->DeviceName.Buffer) { + VFDTRACE(VFDINFO|VFDDEV, + ("[VFD] Deleting device %ws\n", + device_extension->DeviceName.Buffer)); + + ExFreePool(device_extension->DeviceName.Buffer); + } + + // Delete the device object + + IoDeleteDevice(DeviceObject); + IoGetConfigurationInformation()->FloppyCount--; + + VFDTRACE(VFDINFO|VFDDEV, + ("[VFD] VfdDeleteDevice - OUT\n")); + + return; +} diff --git a/modules/rosapps/drivers/vfd/vfddrv.c b/modules/rosapps/drivers/vfd/vfddrv.c new file mode 100644 index 00000000000..feefafff959 --- /dev/null +++ b/modules/rosapps/drivers/vfd/vfddrv.c @@ -0,0 +1,523 @@ +/* + vfddrv.c + + Virtual Floppy Drive for Windows NT platform + Kernel mode driver: miscellaneous driver functions + + Copyright (C) 2003-2005 Ken Kato +*/ + +#include "imports.h" +#include "vfddrv.h" +#include "vfddbg.h" + +// +// driver reinitialize routine +// -- create a drive letter for each device +// +#ifdef __cplusplus +extern "C" +#endif // __cplusplus +static VOID +NTAPI +VfdReinitialize( + IN PDRIVER_OBJECT DriverObject, + IN PVOID Context, + IN ULONG Count); + +// +// specify code segment +// +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT, DriverEntry) +#pragma alloc_text(PAGE, VfdReinitialize) +#pragma alloc_text(PAGE, VfdUnloadDriver) +#pragma alloc_text(PAGE, VfdCreateClose) +#pragma alloc_text(PAGE, VfdCopyUnicode) +#pragma alloc_text(PAGE, VfdFreeUnicode) +#endif // ALLOC_PRAGMA + +// +// operating system version +// +#ifndef __REACTOS__ +extern ULONG OsMajorVersion = 0; +extern ULONG OsMinorVersion = 0; +extern ULONG OsBuildNumber = 0; +#else +ULONG OsMajorVersion = 0; +ULONG OsMinorVersion = 0; +ULONG OsBuildNumber = 0; +#endif + +// +// Trace level flag +// +#if DBG +#ifndef __REACTOS__ +extern ULONG TraceFlags = (ULONG)-1; +#else +ULONG TraceFlags = (ULONG)-1; +#endif +#endif // DBG + +// +// Driver Entry routine +// +NTSTATUS +NTAPI +DriverEntry ( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + NTSTATUS status; + PVFD_DRIVER_EXTENSION driver_extension; + ULONG number_of_devices = VFD_DEFAULT_DEVICES; + + ASSERT(DriverObject); + + // Get operating system version + + PsGetVersion(&OsMajorVersion, &OsMinorVersion, &OsBuildNumber, NULL); + +#ifdef VFD_PNP +#define VFD_PNP_TAG "(Plug & Play version)" +#else +#define VFD_PNP_TAG +#endif + + VFDTRACE(0, ("[VFD] %s %s" VFD_PNP_TAG "\n", + VFD_PRODUCT_NAME, VFD_DRIVER_VERSION_STR)); + + VFDTRACE(0, + ("[VFD] Running on Windows NT %lu.%lu build %lu\n", + OsMajorVersion, OsMinorVersion, OsBuildNumber)); + + VFDTRACE(0, + ("[VFD] Build Target Environment: %d\n", VER_PRODUCTBUILD)); + +#ifdef VFD_PNP + + // Create device_extension for the driver object to store driver specific + // information. Device specific information are stored in device extension + // for each device object. + + status = IoAllocateDriverObjectExtension( + DriverObject, + VFD_DRIVER_EXTENSION_ID, + sizeof(VFD_DRIVER_EXTENSION), + &driver_extension); + + if(!NT_SUCCESS(status)) { + VFDTRACE(0, ("[VFD] IoAllocateDriverObjectExtension - %s\n", + GetStatusName(status))); + return status; + } + +#else // VFD_PNP + + // Windows NT doesn't have the IoAllocateDriverObjectExtension + // function and I think there's little point in making a non-PnP + // driver incompatible with Windows NT. + + driver_extension = (PVFD_DRIVER_EXTENSION)ExAllocatePoolWithTag( + PagedPool, sizeof(VFD_DRIVER_EXTENSION), VFD_POOL_TAG); + + if (!driver_extension) { + VFDTRACE(0, ("[VFD] failed to allocate the driver extension.\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + +#endif // VFD_PNP + + RtlZeroMemory(driver_extension, sizeof(VFD_DRIVER_EXTENSION)); + + // + // Copy the registry path into the driver extension so we can use it later + // + if (VfdCopyUnicode(&(driver_extension->RegistryPath), RegistryPath)) { + + // + // Read config values from the registry + // + RTL_QUERY_REGISTRY_TABLE params[3]; + ULONG default_devs = VFD_DEFAULT_DEVICES; +#if DBG + ULONG default_trace = (ULONG)-1; +#endif + + RtlZeroMemory(params, sizeof(params)); + + VFDTRACE(0, ("[VFD] Registry Path: %ws\n", + driver_extension->RegistryPath.Buffer)); + + params[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + params[0].Name = VFD_REG_DEVICE_NUMBER; + params[0].EntryContext = &number_of_devices; + params[0].DefaultType = REG_DWORD; + params[0].DefaultData = &default_devs; + params[0].DefaultLength = sizeof(ULONG); + +#if DBG + params[1].Flags = RTL_QUERY_REGISTRY_DIRECT; + params[1].Name = VFD_REG_TRACE_FLAGS; + params[1].EntryContext = &TraceFlags; + params[1].DefaultType = REG_DWORD; + params[1].DefaultData = &default_trace; + params[1].DefaultLength = sizeof(ULONG); +#endif // DBG + + status = RtlQueryRegistryValues( + RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, + driver_extension->RegistryPath.Buffer, + params, NULL, NULL); + + if (!NT_SUCCESS(status) || + number_of_devices == 0 || + number_of_devices > VFD_MAXIMUM_DEVICES) { + number_of_devices = VFD_DEFAULT_DEVICES; + } + + VFDTRACE(0,("[VFD] NumberOfDevices = %lu\n", number_of_devices)); + VFDTRACE(0,("[VFD] TraceFlags = 0x%08x\n", TraceFlags)); + } + else { + VFDTRACE(0, ("[VFD] failed to allocate the registry path buffer.\n")); + // this error is not fatal + } + + // + // Create VFD device objects + // + do { +#ifdef VFD_PNP + status = VfdCreateDevice(DriverObject, NULL); +#else // VFD_PNP + status = VfdCreateDevice(DriverObject, driver_extension); +#endif // VFD_PNP + + if (!NT_SUCCESS(status)) { + break; + } + } + while (driver_extension->NumberOfDevices < number_of_devices); + + if (!driver_extension->NumberOfDevices) { + + // Failed to create even one device + + VfdFreeUnicode(&(driver_extension->RegistryPath)); + + return status; + } + + // Setup dispatch table + + DriverObject->MajorFunction[IRP_MJ_CREATE] = VfdCreateClose; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = VfdCreateClose; + DriverObject->MajorFunction[IRP_MJ_READ] = VfdReadWrite; + DriverObject->MajorFunction[IRP_MJ_WRITE] = VfdReadWrite; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VfdDeviceControl; + +#ifdef VFD_PNP + DriverObject->MajorFunction[IRP_MJ_PNP] = VfdPlugAndPlay; + DriverObject->MajorFunction[IRP_MJ_POWER] = VfdPowerControl; + DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = VfdSystemControl; + DriverObject->DriverExtension->AddDevice = VfdAddDevice; +#endif // VFDPNP + + DriverObject->DriverUnload = VfdUnloadDriver; + + // Register the driver reinitialize routine to be called + // *after* the DriverEntry routine returns + + IoRegisterDriverReinitialization( + DriverObject, VfdReinitialize, NULL); + + VFDTRACE(VFDINFO, + ("[VFD] driver initialized with %lu devices.\n", + driver_extension->NumberOfDevices)); + + return STATUS_SUCCESS; +} + +// +// Driver unload routine +// Cleans up the device objects and other resources +// +VOID +NTAPI +VfdUnloadDriver ( + IN PDRIVER_OBJECT DriverObject) +{ + PDEVICE_OBJECT device_object; + PVFD_DRIVER_EXTENSION driver_extension; + + VFDTRACE(VFDINFO, ("[VFD] VfdUnloadDriver - IN\n")); + + device_object = DriverObject->DeviceObject; + +#ifdef VFD_PNP + driver_extension = IoGetDriverObjectExtension( + DriverObject, VFD_DRIVER_EXTENSION_ID); +#else + if (device_object && device_object->DeviceExtension) { + driver_extension = + ((PDEVICE_EXTENSION)(device_object->DeviceExtension))->DriverExtension; + } + else { + driver_extension = NULL; + } +#endif // VFD_PNP + + // + // Delete all remaining device objects + // + while (device_object) { + + PDEVICE_OBJECT next_device = device_object->NextDevice; + + VfdDeleteDevice(device_object); + + device_object = next_device; + } + + // + // Release the driver extension and the registry path buffer + // + if (driver_extension) { + + if (driver_extension->RegistryPath.Buffer) { + VFDTRACE(0, ("[VFD] Releasing the registry path buffer\n")); + ExFreePool(driver_extension->RegistryPath.Buffer); + } + +#ifndef VFD_PNP + // The system takes care of freeing the driver extension + // allocated with IoAllocateDriverObjectExtension in a PnP driver. + VFDTRACE(0, ("[VFD] Releasing the driver extension\n")); + ExFreePool(driver_extension); +#endif // VFD_PNP + } + + VFDTRACE(VFDINFO, ("[VFD] VfdUnloadDriver - OUT\n")); +} + +// +// IRP_MJ_CREATE and IRP_MJ_CLOSE handler +// Really nothing to do here... +// +NTSTATUS +NTAPI +VfdCreateClose ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ +#if DBG + if (DeviceObject && DeviceObject->DeviceExtension && + ((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->DeviceName.Buffer) { + + VFDTRACE(VFDINFO, ("[VFD] %-40s %ws\n", + GetMajorFuncName(IoGetCurrentIrpStackLocation(Irp)->MajorFunction), + ((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->DeviceName.Buffer)); + } + else { + VFDTRACE(VFDINFO, ("[VFD] %-40s %p\n", + GetMajorFuncName(IoGetCurrentIrpStackLocation(Irp)->MajorFunction), + DeviceObject)); + } +#endif // DBG + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = FILE_OPENED; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} + +// +// Called after the DriverEntry routine has returned +// (Re)Create a persistent drive letter for each device +// +VOID +NTAPI +VfdReinitialize( + IN PDRIVER_OBJECT DriverObject, + IN PVOID Context, + IN ULONG Count) +{ + PDEVICE_OBJECT device_object; + PDEVICE_EXTENSION device_extension; + + UNREFERENCED_PARAMETER(Context); + UNREFERENCED_PARAMETER(Count); + + VFDTRACE(VFDINFO, ("[VFD] VfdReinitialize - IN\n")); + + device_object = DriverObject->DeviceObject; + + while (device_object) { + device_extension = (PDEVICE_EXTENSION)device_object->DeviceExtension; + +#ifdef VFD_MOUNT_MANAGER + if (OsMajorVersion >= 5) { + // Windows 2000 / XP + // Notify the mount manager of a VFD volume arrival + VfdMountMgrNotifyVolume(device_extension); + + if (device_extension->DriveLetter) { + // Create a drive letter via the mount manager. + // The mount manager may have created a drive letter + // in response to the volume arrival notification above. + // In that case, the following call just fails. + VfdMountMgrMountPoint( + device_extension, device_extension->DriveLetter); + // ignoring the error for it is not fatal here + } + } + else +#endif // VFD_MOUNT_MANAGER + { + // Windows NT style drive letter assignment + // Simply create a symbolic link here + if (device_extension->DriveLetter) { + VfdSetLink( + device_extension, device_extension->DriveLetter); + // ignoring the error for it is not fatal here + } + } + + device_object = device_object->NextDevice; + } + + VFDTRACE(VFDINFO, ("[VFD] VfdReinitialize - OUT\n")); +} + +// +// Device dedicated thread routine +// Dispatch read, write and device I/O request +// redirected from the driver dispatch routines +// +VOID +NTAPI +VfdDeviceThread ( + IN PVOID ThreadContext) +{ + PDEVICE_OBJECT device_object; + PDEVICE_EXTENSION device_extension; + PLIST_ENTRY request; + PIRP irp; + PIO_STACK_LOCATION io_stack; + + ASSERT(ThreadContext != NULL); + + device_object = (PDEVICE_OBJECT)ThreadContext; + + device_extension = (PDEVICE_EXTENSION)device_object->DeviceExtension; + + KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY); + + for (;;) { + // wait for the request event to be signalled + KeWaitForSingleObject( + &device_extension->RequestEvent, + Executive, + KernelMode, + FALSE, + NULL); + + // terminate request ? + if (device_extension->TerminateThread) { + VFDTRACE(0, ("[VFD] Exitting the I/O thread\n")); + PsTerminateSystemThread(STATUS_SUCCESS); + } + + // perform requested tasks + + while ((request = ExInterlockedRemoveHeadList( + &device_extension->ListHead, + &device_extension->ListLock)) != NULL) + { + irp = CONTAINING_RECORD(request, IRP, Tail.Overlay.ListEntry); + + io_stack = IoGetCurrentIrpStackLocation(irp); + + irp->IoStatus.Information = 0; + + switch (io_stack->MajorFunction) { + case IRP_MJ_READ: + VfdReadData(device_extension, irp, + io_stack->Parameters.Read.Length, + &io_stack->Parameters.Read.ByteOffset); + break; + + case IRP_MJ_WRITE: + VfdWriteData(device_extension, irp, + io_stack->Parameters.Write.Length, + &io_stack->Parameters.Write.ByteOffset); + break; + + case IRP_MJ_DEVICE_CONTROL: + VfdIoCtlThread(device_extension, irp, + io_stack->Parameters.DeviceIoControl.IoControlCode); + break; + + default: + // This shouldn't happen... + VFDTRACE(0, + ("[VFD] %s passed to the I/O thread\n", + GetMajorFuncName(io_stack->MajorFunction))); + + irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR; + } + + IoCompleteRequest(irp, + (CCHAR)(NT_SUCCESS(irp->IoStatus.Status) ? + IO_DISK_INCREMENT : IO_NO_INCREMENT)); + +#ifdef VFD_PNP + IoReleaseRemoveLock(&device_extension->RemoveLock, irp); +#endif // VFD_PNP + } // while + } // for (;;) +} + +// +// Copy a UNICODE_STRING adding a trailing NULL characer +// +PWSTR VfdCopyUnicode( + PUNICODE_STRING dst, + PUNICODE_STRING src) +{ + RtlZeroMemory(dst, sizeof(UNICODE_STRING)); + + dst->MaximumLength = + (USHORT)(src->MaximumLength + sizeof(UNICODE_NULL)); + + dst->Buffer = (PWSTR)ExAllocatePoolWithTag( + PagedPool, dst->MaximumLength, VFD_POOL_TAG); + + if(dst->Buffer) { + dst->Length = src->Length; + RtlZeroMemory(dst->Buffer, dst->MaximumLength); + + if (src->Length) { + RtlCopyMemory(dst->Buffer, src->Buffer, src->Length); + } + } + + return dst->Buffer; +} + +// +// Free a UNICODE_STRING buffer +// +VOID VfdFreeUnicode( + PUNICODE_STRING str) +{ + if (str->Buffer) { + ExFreePool(str->Buffer); + } + RtlZeroMemory(str, sizeof(UNICODE_STRING)); +} diff --git a/modules/rosapps/drivers/vfd/vfddrv.h b/modules/rosapps/drivers/vfd/vfddrv.h new file mode 100644 index 00000000000..589ca894cc1 --- /dev/null +++ b/modules/rosapps/drivers/vfd/vfddrv.h @@ -0,0 +1,357 @@ +/* + vfddrv.h + + Virtual Floppy Drive for Windows NT platform + Kernel mode driver: local header + + Copyright(C) 2003-2005 Ken Kato +*/ + +#ifndef _VFDDRV_H_ +#define _VFDDRV_H_ + +#ifdef __cplusplus +extern "C" { +#pragma message("Compiled as C++ for testing purpose.") +#endif // __cplusplus + +#include "vfdtypes.h" +#include "vfdio.h" +#include "vfdver.h" + +// +// Tag used for ExAllocatePoolWithTag +// +#define VFD_POOL_TAG 'DFVx' + +// +// PnP driver specific stuff +// +#ifdef VFD_PNP + +#if (VER_PRODUCTBUILD < 2195) +#error Cannot build a PnP version with the Windows NT DDK +#endif // (VER_PRODUCTBUILD < 2195) + +// +// device state enumeration +// +typedef enum _DEVICE_STATE +{ + VFD_STOPPED, // Dvice stopped + VFD_WORKING, // Started and working + VFD_PENDINGSTOP, // Stop pending + VFD_PENDINGREMOVE, // Remove pending + VFD_SURPRISEREMOVED, // Surprise removed + VFD_REMOVED, // Removed + VFD_MAX_STATE // Unknown state -Some error +} +DEVICE_STATE, *PDEVICE_STATE; + +// +// use the address of the DriverEntry functions as the +// driver extension identifier +// +#define VFD_DRIVER_EXTENSION_ID ((PVOID)DriverEntry) + +#endif // VFD_PNP + +// +// driver extension for the VFD driver +// +typedef struct _VFD_DRIVER_EXTENSION +{ + UNICODE_STRING RegistryPath; + ULONG NumberOfDevices; +} +VFD_DRIVER_EXTENSION, *PVFD_DRIVER_EXTENSION; + +// +// device extension for Virtual FD device +// +typedef struct _DEVICE_EXTENSION +{ + // back pointer to the device object + PDEVICE_OBJECT DeviceObject; + + // device information + UNICODE_STRING DeviceName; // \Device\Floppy + ULONG DeviceNumber; // \??\VirtualFD + CHAR DriveLetter; // \DosDevices\: + + // Security context to access files on network drive + PSECURITY_CLIENT_CONTEXT SecurityContext; + + // IRP queue list + LIST_ENTRY ListHead; + KSPIN_LOCK ListLock; + + // device thread + KEVENT RequestEvent; + PVOID ThreadPointer; + BOOLEAN TerminateThread; + + // drive information + ULONG MediaChangeCount; + + // media information + VFD_MEDIA MediaType; + VFD_FLAGS MediaFlags; + VFD_FILETYPE FileType; + ULONG ImageSize; + ANSI_STRING FileName; + + const DISK_GEOMETRY *Geometry; + ULONG Sectors; + + HANDLE FileHandle; + PUCHAR FileBuffer; + +#ifdef VFD_PNP + DEVICE_STATE DeviceState; // Current device state + IO_REMOVE_LOCK RemoveLock; // avoid abnormal removal + PDEVICE_OBJECT PhysicalDevice; + PDEVICE_OBJECT TargetDevice; + UNICODE_STRING InterfaceName; +#else // VFD_PNP + PVFD_DRIVER_EXTENSION DriverExtension; +#endif // VFD_PNP +} +DEVICE_EXTENSION, *PDEVICE_EXTENSION; + +// +// Stanard driver routines +// +NTSTATUS +NTAPI +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath); + +VOID +NTAPI +VfdUnloadDriver( + IN PDRIVER_OBJECT DriverObject); + +NTSTATUS +NTAPI +VfdCreateClose( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +NTAPI +VfdReadWrite( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +NTAPI +VfdDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +#ifdef VFD_PNP + +NTSTATUS +NTAPI +VfdPlugAndPlay( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +NTAPI +VfdPowerControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +NTAPI +VfdSystemControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + +NTSTATUS +NTAPI +VfdAddDevice( + IN PDRIVER_OBJECT DriverObject, + IN OUT PDEVICE_OBJECT PhysicalDevice); + +#endif // VFD_PNP + +// +// Prototypes for private routines +// + +// +// vfddrv.c +// +extern ULONG OsMajorVersion; +extern ULONG OsMinorVersion; +extern ULONG OsBuildNumber; + +VOID +NTAPI +VfdDeviceThread( + IN PVOID ThreadContext); + +PWSTR +VfdCopyUnicode( + OUT PUNICODE_STRING dst, + IN PUNICODE_STRING src); + +VOID +VfdFreeUnicode( + IN OUT PUNICODE_STRING str); + +// +// vfddev.c +// +NTSTATUS +VfdCreateDevice( + IN PDRIVER_OBJECT DriverObject, + OUT PVOID Parameter); + +VOID +VfdDeleteDevice( + IN PDEVICE_OBJECT DeviceObject); + +// +// vfdioctl.c +// +VOID +VfdIoCtlThread( + IN PDEVICE_EXTENSION DeviceExtension, + IN PIRP Irp, + IN ULONG ControlCode); + +// +// vfdimg.c +// +NTSTATUS +VfdOpenCheck( + IN PDEVICE_EXTENSION DeviceExtension, + IN PVFD_IMAGE_INFO ImageInfo, + IN ULONG InputLength); + +NTSTATUS +VfdOpenImage( + IN PDEVICE_EXTENSION DeviceExtension, + IN PVFD_IMAGE_INFO ImageInfo); + +VOID +VfdCloseImage( + IN PDEVICE_EXTENSION DeviceExtension); + +NTSTATUS +VfdQueryImage( + IN PDEVICE_EXTENSION DeviceExtension, + OUT PVFD_IMAGE_INFO ImageInfo, + IN ULONG BufferLength, + OUT PULONG ReturnLength); + +// +// vfdrdwr.c +// +VOID +VfdReadData( + IN PDEVICE_EXTENSION DeviceExtension, + IN OUT PIRP Irp, + IN ULONG Length, + IN PLARGE_INTEGER Offset); + +VOID +VfdWriteData( + IN PDEVICE_EXTENSION DeviceExtension, + IN OUT PIRP Irp, + IN ULONG Length, + IN PLARGE_INTEGER Offset); + +// +// vfdlink.c +// +NTSTATUS +VfdSetLink( + IN PDEVICE_EXTENSION DeviceExtension, + IN CHAR DriveLetter); + +NTSTATUS +VfdStoreLink( + IN PDEVICE_EXTENSION DeviceExtension); + +NTSTATUS +VfdLoadLink( + IN PDEVICE_EXTENSION DeviceExtension, + IN PWSTR RegistryPath); + +// +// vfdfmt.c +// +extern const DISK_GEOMETRY geom_tbl[VFD_MEDIA_MAX]; + +NTSTATUS +VfdFormatCheck( + IN PDEVICE_EXTENSION DeviceExtension, + IN PFORMAT_PARAMETERS FormatParams, + IN ULONG InputLength, + IN ULONG ControlCode); + +NTSTATUS +VfdFormatTrack( + IN PDEVICE_EXTENSION DeviceExtension, + IN PFORMAT_PARAMETERS FormatParams); + +// +// vfdmnt.c +// +#ifdef VFD_MOUNT_MANAGER +/* +NTSTATUS +VfdRegisterMountManager( + IN PDEVICE_EXTENSION DeviceExtension); +*/ + +NTSTATUS +VfdMountMgrNotifyVolume( + IN PDEVICE_EXTENSION DeviceExtension); + +NTSTATUS +VfdMountMgrMountPoint( + IN PDEVICE_EXTENSION DeviceExtension, + IN CHAR DriveLetter); + +NTSTATUS +VfdMountDevUniqueId( + IN PDEVICE_EXTENSION DeviceExtension, + OUT PMOUNTDEV_UNIQUE_ID UniqueId, + IN ULONG OutputLength, + OUT PIO_STATUS_BLOCK IoStatus); + +NTSTATUS +VfdMountDevDeviceName( + IN PDEVICE_EXTENSION DeviceExtension, + OUT PMOUNTDEV_NAME DeviceName, + IN ULONG OutputLength, + OUT PIO_STATUS_BLOCK IoStatus); + +NTSTATUS +VfdMountDevSuggestedLink( + IN PDEVICE_EXTENSION DeviceExtension, + OUT PMOUNTDEV_SUGGESTED_LINK_NAME LinkName, + IN ULONG OutputLength, + OUT PIO_STATUS_BLOCK IoStatus); + +NTSTATUS +VfdMountDevLinkModified( + IN PDEVICE_EXTENSION DeviceExtension, + IN PMOUNTDEV_NAME LinkName, + IN ULONG InputLength, + IN ULONG ControlCode); + +#endif // VFD_MOUNT_MANAGER + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // _VFDDRV_H_ diff --git a/modules/rosapps/drivers/vfd/vfddrv.rc b/modules/rosapps/drivers/vfd/vfddrv.rc new file mode 100644 index 00000000000..4d800596557 --- /dev/null +++ b/modules/rosapps/drivers/vfd/vfddrv.rc @@ -0,0 +1,30 @@ +/* + vfddrv.rc + + Virtual Floppy Drive for Windows NT platform + Kernel mode driver: version resource script + + Copyright (C) 2003-2005 Ken Kato +*/ + +// !!! NOTE !!! +// Editing this file with Microsoft Visual Studio will almost +// certainly mess things up... + +#ifndef APSTUDIO_INVOKED + +#include +#include "vfdver.h" + +#define VFD_FILEOS VOS_NT_WINDOWS32 +#define VFD_FILETYPE VFT_DRV +#define VFD_FILESUBTYPE VFT2_DRV_SYSTEM + +#define VFD_DESCRIPTION "Virtual Floppy Drive Kernel Mode Driver" +#define VFD_INTERNALNAME VFD_DRIVER_FILENAME +#define VFD_FILE_MAJOR VFD_DRIVER_MAJOR +#define VFD_FILE_MINOR VFD_DRIVER_MINOR + +#include "vfdver.rc" + +#endif // APSTUDIO_INVOKED diff --git a/modules/rosapps/drivers/vfd/vfdfmt.c b/modules/rosapps/drivers/vfd/vfdfmt.c new file mode 100644 index 00000000000..680dcbc7d31 --- /dev/null +++ b/modules/rosapps/drivers/vfd/vfdfmt.c @@ -0,0 +1,234 @@ +/* + vfdfmt.c + + Virtual Floppy Drive for Windows NT platform + Kernel mode driver: disk format functions + + Copyright (C) 2003-2005 Ken Kato +*/ + +#include "imports.h" +#include "vfddrv.h" +#include "vfddbg.h" + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, VfdFormatCheck) +#pragma alloc_text(PAGE, VfdFormatTrack) +#endif // ALLOC_PRAGMA + +// +// Media geometry constant table +// +// MediaTypes values added since Win NT DDK +#ifndef F3_640_512 +#define F3_640_512 (MEDIA_TYPE)14 +#endif +#ifndef F3_1Pt2_512 +#define F3_1Pt2_512 (MEDIA_TYPE)17 +#endif + +#ifndef __REACTOS__ +extern DISK_GEOMETRY const geom_tbl[VFD_MEDIA_MAX] = { +DISK_GEOMETRY const geom_tbl[VFD_MEDIA_MAX] = { + {{ 80 }, F3_1Pt44_512, 2, 18, VFD_BYTES_PER_SECTOR }, // default + {{ 40 }, F5_160_512, 1, 8, VFD_BYTES_PER_SECTOR }, // 160K + {{ 40 }, F5_180_512, 1, 9, VFD_BYTES_PER_SECTOR }, // 180K + {{ 40 }, F5_320_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 320K + {{ 40 }, F5_360_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 360K + {{ 80 }, F3_640_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 640k + {{ 80 }, F5_640_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 640k + {{ 80 }, F3_720_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 720K + {{ 80 }, F5_720_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 720K + {{ 82 }, RemovableMedia, 2, 10, VFD_BYTES_PER_SECTOR }, // 820K + {{ 80 }, F3_1Pt2_512, 2, 15, VFD_BYTES_PER_SECTOR }, // 1200K + {{ 80 }, F5_1Pt2_512, 2, 15, VFD_BYTES_PER_SECTOR }, // 1200K + {{ 80 }, F3_1Pt44_512, 2, 18, VFD_BYTES_PER_SECTOR }, // 1440K + {{ 80 }, RemovableMedia, 2, 21, VFD_BYTES_PER_SECTOR }, // 1680K DMF + {{ 82 }, RemovableMedia, 2, 21, VFD_BYTES_PER_SECTOR }, // 1720K DMF + {{ 80 }, F3_2Pt88_512, 2, 36, VFD_BYTES_PER_SECTOR }, // 2880K +#else +DISK_GEOMETRY const geom_tbl[VFD_MEDIA_MAX] = { + {{ .QuadPart = 80 }, F3_1Pt44_512, 2, 18, VFD_BYTES_PER_SECTOR }, // default + {{ .QuadPart = 40 }, F5_160_512, 1, 8, VFD_BYTES_PER_SECTOR }, // 160K + {{ .QuadPart = 40 }, F5_180_512, 1, 9, VFD_BYTES_PER_SECTOR }, // 180K + {{ .QuadPart = 40 }, F5_320_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 320K + {{ .QuadPart = 40 }, F5_360_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 360K + {{ .QuadPart = 80 }, F3_640_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 640k + {{ .QuadPart = 80 }, F5_640_512, 2, 8, VFD_BYTES_PER_SECTOR }, // 640k + {{ .QuadPart = 80 }, F3_720_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 720K + {{ .QuadPart = 80 }, F5_720_512, 2, 9, VFD_BYTES_PER_SECTOR }, // 720K + {{ .QuadPart = 82 }, RemovableMedia, 2, 10, VFD_BYTES_PER_SECTOR }, // 820K + {{ .QuadPart = 80 }, F3_1Pt2_512, 2, 15, VFD_BYTES_PER_SECTOR }, // 1200K + {{ .QuadPart = 80 }, F5_1Pt2_512, 2, 15, VFD_BYTES_PER_SECTOR }, // 1200K + {{ .QuadPart = 80 }, F3_1Pt44_512, 2, 18, VFD_BYTES_PER_SECTOR }, // 1440K + {{ .QuadPart = 80 }, RemovableMedia, 2, 21, VFD_BYTES_PER_SECTOR }, // 1680K DMF + {{ .QuadPart = 82 }, RemovableMedia, 2, 21, VFD_BYTES_PER_SECTOR }, // 1720K DMF + {{ .QuadPart = 80 }, F3_2Pt88_512, 2, 36, VFD_BYTES_PER_SECTOR }, // 2880K +#endif +}; + +// +// Parameter check for IOCTL_DISK_FORMAT_TRACK and IOCTL_DISK_FORMAT_TRACK_EX +// +NTSTATUS +VfdFormatCheck( + PDEVICE_EXTENSION DeviceExtension, + PFORMAT_PARAMETERS FormatParams, + ULONG InputLength, + ULONG ControlCode) +{ + const DISK_GEOMETRY *geometry; + + // Check media status + + if (!DeviceExtension->FileHandle && + !DeviceExtension->FileBuffer) { + return STATUS_NO_MEDIA_IN_DEVICE; + } + + // Media is writable? + + if (DeviceExtension->MediaFlags & VFD_FLAG_WRITE_PROTECTED) { + return STATUS_MEDIA_WRITE_PROTECTED; + } + + // Check input parameter size + + if (InputLength < sizeof(FORMAT_PARAMETERS)) { + return STATUS_INVALID_PARAMETER; + } + + // Choose appropriate DISK_GEOMETRY for current image size + + geometry = DeviceExtension->Geometry; + + if (!geometry) { + return STATUS_DRIVER_INTERNAL_ERROR; + } + + // Input parameter sanity check + + if ((FormatParams->StartHeadNumber > geometry->TracksPerCylinder - 1) || + (FormatParams->EndHeadNumber > geometry->TracksPerCylinder - 1) || + (FormatParams->StartCylinderNumber > geometry->Cylinders.LowPart) || + (FormatParams->EndCylinderNumber > geometry->Cylinders.LowPart) || + (FormatParams->EndCylinderNumber < FormatParams->StartCylinderNumber)) + { + return STATUS_INVALID_PARAMETER; + } + + // If this is an EX request then make a couple of extra checks + + if (ControlCode == IOCTL_DISK_FORMAT_TRACKS_EX) { + + PFORMAT_EX_PARAMETERS exparams; + + if (InputLength < sizeof(FORMAT_EX_PARAMETERS)) { + return STATUS_INVALID_PARAMETER; + } + + exparams = (PFORMAT_EX_PARAMETERS)FormatParams; + + if (InputLength < + FIELD_OFFSET(FORMAT_EX_PARAMETERS, SectorNumber) + + exparams->SectorsPerTrack * sizeof(USHORT)) + { + return STATUS_INVALID_PARAMETER; + } + + if (exparams->FormatGapLength > geometry->SectorsPerTrack || + exparams->SectorsPerTrack != geometry->SectorsPerTrack) + { + return STATUS_INVALID_PARAMETER; + } + } + + return STATUS_SUCCESS; +} + +// +// Format tracks +// Actually, just fills specified range of tracks with fill characters +// +NTSTATUS +VfdFormatTrack( + IN PDEVICE_EXTENSION DeviceExtension, + IN PFORMAT_PARAMETERS FormatParams) +{ + const DISK_GEOMETRY *geometry; + ULONG track_length; + PUCHAR format_buffer; + LARGE_INTEGER start_offset; + LARGE_INTEGER end_offset; + NTSTATUS status; + + VFDTRACE(0, ("[VFD] VfdFormatTrack - IN\n")); + + ASSERT(DeviceExtension != NULL); + + geometry = DeviceExtension->Geometry; + + if (!geometry) { + return STATUS_DRIVER_INTERNAL_ERROR; + } + + track_length = geometry->BytesPerSector * geometry->SectorsPerTrack; + + format_buffer = (PUCHAR)ExAllocatePoolWithTag( + PagedPool, track_length, VFD_POOL_TAG); + + if (format_buffer == NULL) { + VFDTRACE(0, ("[VFD] cannot allocate a format buffer\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlFillMemory(format_buffer, track_length, VFD_FORMAT_FILL_DATA); + + start_offset.QuadPart = + FormatParams->StartCylinderNumber * geometry->TracksPerCylinder * track_length + + FormatParams->StartHeadNumber * track_length; + + end_offset.QuadPart = + FormatParams->EndCylinderNumber * geometry->TracksPerCylinder * track_length + + FormatParams->EndHeadNumber * track_length; + + do { + if (DeviceExtension->FileHandle) { + IO_STATUS_BLOCK io_status; + + status = ZwWriteFile( + DeviceExtension->FileHandle, + NULL, + NULL, + NULL, + &io_status, + format_buffer, + track_length, + &start_offset, + NULL); + + if (!NT_SUCCESS(status)) { + VFDTRACE(0, ("[VFD] ZwWriteFile - %s\n", + GetStatusName(status))); + break; + } + } + else { + RtlMoveMemory( + DeviceExtension->FileBuffer + start_offset.QuadPart, + format_buffer, + track_length); + + status = STATUS_SUCCESS; + } + + start_offset.QuadPart += track_length; + } + while (start_offset.QuadPart <= end_offset.QuadPart); + + ExFreePool(format_buffer); + + VFDTRACE(0, ("[VFD] VfdFormatTrack - OUT\n")); + + return status; +} diff --git a/modules/rosapps/drivers/vfd/vfdimg.c b/modules/rosapps/drivers/vfd/vfdimg.c new file mode 100644 index 00000000000..b6cabe04ab1 --- /dev/null +++ b/modules/rosapps/drivers/vfd/vfdimg.c @@ -0,0 +1,527 @@ +/* + vfdimg.c + + Virtual Floppy Drive for Windows NT platform + Kernel mode driver: Image handling functions + + Copyright (C) 2003-2005 Ken Kato +*/ + +#include "imports.h" +#include "vfddrv.h" +#include "vfddbg.h" + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, VfdOpenCheck) +#pragma alloc_text(PAGE, VfdOpenImage) +#pragma alloc_text(PAGE, VfdCloseImage) +#pragma alloc_text(PAGE, VfdQueryImage) +#endif // ALLOC_PRAGMA + +// +// Check IOCTL_VFD_OPEN_IMAGE input parameters +// +NTSTATUS +VfdOpenCheck( + PDEVICE_EXTENSION DeviceExtension, + PVFD_IMAGE_INFO ImageInfo, + ULONG InputLength) +{ + // Check media status + + if (DeviceExtension->FileHandle || + DeviceExtension->FileBuffer) { + + VFDTRACE(VFDWARN, ("[VFD] image already opened.\n")); + + return STATUS_DEVICE_BUSY; + } + + // Check input parameter length + + if (InputLength < sizeof(VFD_IMAGE_INFO) || + InputLength < sizeof(VFD_IMAGE_INFO) + ImageInfo->NameLength) + { + return STATUS_INVALID_PARAMETER; + } + + // Check input parameters + + if (ImageInfo->MediaType == VFD_MEDIA_NONE || + ImageInfo->MediaType >= VFD_MEDIA_MAX) { + + VFDTRACE(VFDWARN, ("[VFD] invalid MediaType - %u.\n", + ImageInfo->MediaType)); + + return STATUS_INVALID_PARAMETER; + } + + if (ImageInfo->DiskType == VFD_DISKTYPE_FILE && + ImageInfo->NameLength == 0) { + + VFDTRACE(VFDWARN, + ("[VFD] File name required for VFD_DISKTYPE_FILE.\n")); + + return STATUS_INVALID_PARAMETER; + } + + // create a security context to match the calling process' context + // the driver thread uses this context to impersonate the client + // to open the specified image file + +// if (ImageInfo->DiskType == VFD_DISKTYPE_FILE) + { + SECURITY_QUALITY_OF_SERVICE sqos; + + if (DeviceExtension->SecurityContext != NULL) { + SeDeleteClientSecurity(DeviceExtension->SecurityContext); + } + else { + DeviceExtension->SecurityContext = + (PSECURITY_CLIENT_CONTEXT)ExAllocatePoolWithTag( + NonPagedPool, sizeof(SECURITY_CLIENT_CONTEXT), VFD_POOL_TAG); + } + + RtlZeroMemory(&sqos, sizeof(SECURITY_QUALITY_OF_SERVICE)); + + sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); + sqos.ImpersonationLevel = SecurityImpersonation; + sqos.ContextTrackingMode = SECURITY_STATIC_TRACKING; + sqos.EffectiveOnly = FALSE; + + SeCreateClientSecurity( + PsGetCurrentThread(), &sqos, FALSE, + DeviceExtension->SecurityContext); + } + + return STATUS_SUCCESS; +} + +// +// Open a virtual floppy image file or create an empty ram disk +// +NTSTATUS +VfdOpenImage ( + IN PDEVICE_EXTENSION DeviceExtension, + IN PVFD_IMAGE_INFO ImageInfo) +{ + IO_STATUS_BLOCK io_status; + NTSTATUS status = STATUS_SUCCESS; + const DISK_GEOMETRY *geometry; + ULONG sectors; + ULONG alignment; + + VFDTRACE(0, ("[VFD] VfdOpenImage - IN\n")); + + // + // Store file name in the device extension + // + if (ImageInfo->NameLength) { + + if (ImageInfo->NameLength + 1 > + DeviceExtension->FileName.MaximumLength) { + + // expand the filename buffer + + if (DeviceExtension->FileName.Buffer) { + ExFreePool(DeviceExtension->FileName.Buffer); + RtlZeroMemory( + &DeviceExtension->FileName, + sizeof(ANSI_STRING)); + } + + DeviceExtension->FileName.Buffer = (PCHAR)ExAllocatePoolWithTag( + NonPagedPool, ImageInfo->NameLength + 1, VFD_POOL_TAG); + + if (!DeviceExtension->FileName.Buffer) { + VFDTRACE(0, ("[VFD] Can't allocate memory for image path\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + DeviceExtension->FileName.MaximumLength + = (USHORT)(ImageInfo->NameLength + 1); + + RtlZeroMemory( + DeviceExtension->FileName.Buffer, + DeviceExtension->FileName.MaximumLength); + } + + if (DeviceExtension->FileName.Buffer) { + RtlCopyMemory( + DeviceExtension->FileName.Buffer, + ImageInfo->FileName, + ImageInfo->NameLength); + + DeviceExtension->FileName.Buffer[ImageInfo->NameLength] = '\0'; + } + } + + DeviceExtension->FileName.Length = ImageInfo->NameLength; + + // + // Get DISK_GEOMETRY and calculate the media capacity + // -- validity of the ImageInfo->MediaType value is assured in + // the VfdOpenCheck function + // + geometry = &geom_tbl[ImageInfo->MediaType]; + + sectors = + geometry->Cylinders.LowPart * + geometry->TracksPerCylinder * + geometry->SectorsPerTrack; + + if (ImageInfo->ImageSize != 0 && + ImageInfo->ImageSize < VFD_SECTOR_TO_BYTE(sectors)) { + + VFDTRACE(0, ("[VFD] Image is smaller than the media\n")); + return STATUS_INVALID_PARAMETER; + } + + // + // Prepare a virtual media according to the ImageInfo + // + if (ImageInfo->DiskType == VFD_DISKTYPE_FILE) { + // + // open an existing image file + // + HANDLE file_handle; + OBJECT_ATTRIBUTES attributes; + UNICODE_STRING unicode_name; + FILE_STANDARD_INFORMATION file_standard; + FILE_BASIC_INFORMATION file_basic; + FILE_ALIGNMENT_INFORMATION file_alignment; + PFILE_OBJECT file_object; + BOOLEAN network_drive; + + // convert the filename into a unicode string + + status = RtlAnsiStringToUnicodeString( + &unicode_name, &DeviceExtension->FileName, TRUE); + + if (!NT_SUCCESS(status)) { + VFDTRACE(0, ("[VFD] Failed to convert filename to UNICODE\n")); + return status; + } + + VFDTRACE(VFDINFO, + ("[VFD] Opening %s\n", DeviceExtension->FileName.Buffer)); + + // prepare an object attribute to open + + InitializeObjectAttributes( + &attributes, + &unicode_name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + // open the target file + + status = ZwCreateFile( + &file_handle, + GENERIC_READ | GENERIC_WRITE, + &attributes, + &io_status, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_OPEN, + FILE_NON_DIRECTORY_FILE | + FILE_RANDOM_ACCESS | + FILE_NO_INTERMEDIATE_BUFFERING | + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + RtlFreeUnicodeString(&unicode_name); + + if (!NT_SUCCESS(status)) { + VFDTRACE(0, ("[VFD] ZwCreateFile - %s\n", + GetStatusName(status))); + return status; + } + + // Check the file size + + status = ZwQueryInformationFile( + file_handle, + &io_status, + &file_standard, + sizeof(FILE_STANDARD_INFORMATION), + FileStandardInformation); + + if (!NT_SUCCESS(status)) { + VFDTRACE(0, + ("[VFD] ZwQueryInformationFile - FILE_STANDARD_INFORMATION\n")); + + ZwClose(file_handle); + goto exit_func; + } + + // Actual file size can be larger than the media capacity + + if (file_standard.EndOfFile.QuadPart < VFD_SECTOR_TO_BYTE(sectors)) { + + VFDTRACE(0, ("[VFD] file is smaller than the media.\n")); + + status = STATUS_INVALID_PARAMETER; + + ZwClose(file_handle); + goto exit_func; + } + + DeviceExtension->ImageSize = file_standard.EndOfFile.LowPart; + + // Find out whether the file is on a local disk or a network drive + + network_drive = FALSE; + + status = ObReferenceObjectByHandle( + file_handle, + GENERIC_READ, + NULL, + KernelMode, +#ifndef __REACTOS__ + &file_object, +#else + (PVOID *)&file_object, +#endif + NULL); + + if (NT_SUCCESS(status)) { + if (file_object && file_object->DeviceObject) { + VFDTRACE(VFDINFO, ("[VFD] Device type is 0x%08x\n", + file_object->DeviceObject->DeviceType)); + + if (file_object->DeviceObject->DeviceType + == FILE_DEVICE_NETWORK_FILE_SYSTEM) { + network_drive = TRUE; + } + + // how about these types ? + // FILE_DEVICE_NETWORK + // FILE_DEVICE_NETWORK_BROWSER + // FILE_DEVICE_NETWORK_REDIRECTOR + } + else { + VFDTRACE(VFDWARN, ("[VFD Cannot decide the device type\n")); + } + ObDereferenceObject(file_object); + } + else { + VFDTRACE(0, ("[VFD] ObReferenceObjectByHandle - %s\n", + GetStatusName(status))); + } + + if (!network_drive) { + // The NT cache manager can deadlock if a filesystem that is using + // the cache manager is used in a virtual disk that stores its file + // on a file systemthat is also using the cache manager, this is + // why we open the file with FILE_NO_INTERMEDIATE_BUFFERING above, + // however if the file is compressed or encrypted NT will not honor + // this request and cache it anyway since it need to store the + // decompressed/unencrypted data somewhere, therefor we put an + // extra check here and don't alow disk images to be compressed/ + // encrypted. + + status = ZwQueryInformationFile( + file_handle, + &io_status, + &file_basic, + sizeof(FILE_BASIC_INFORMATION), + FileBasicInformation); + + if (!NT_SUCCESS(status)) { + VFDTRACE(0, + ("[VFD] ZwQueryInformationFile - FILE_BASIC_INFORMATION\n")); + + ZwClose(file_handle); + goto exit_func; + } + + if (file_basic.FileAttributes + & (FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_ENCRYPTED)) + { + VFDTRACE(0, + ("[VFD] Image file is compressed and/or encrypted\n")); + + status = STATUS_ACCESS_DENIED; + + ZwClose(file_handle); + goto exit_func; + } + } + + // Retrieve the file alignment requirement + + status = ZwQueryInformationFile( + file_handle, + &io_status, + &file_alignment, + sizeof(FILE_ALIGNMENT_INFORMATION), + FileAlignmentInformation); + + if (!NT_SUCCESS(status)) { + VFDTRACE(0, + ("[VFD] ZwQueryInformationFile - FILE_ALIGNMENT_INFORMATION\n")); + + ZwClose(file_handle); + goto exit_func; + } + + DeviceExtension->FileHandle = file_handle; + + alignment = file_alignment.AlignmentRequirement; + + VFDTRACE(0, ("[VFD] Opened an image file\n")); + } + else { + // + // Create an empty RAM disk + // + DeviceExtension->FileBuffer = (PUCHAR)ExAllocatePoolWithTag( + NonPagedPool, + VFD_SECTOR_TO_BYTE(sectors), + VFD_POOL_TAG); + + if (!DeviceExtension->FileBuffer) { + VFDTRACE(0, ("[VFD] Can't allocate memory for RAM disk\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory( + DeviceExtension->FileBuffer, + VFD_SECTOR_TO_BYTE(sectors)); + + if (ImageInfo->ImageSize) { + DeviceExtension->ImageSize = ImageInfo->ImageSize; + } + else { + DeviceExtension->ImageSize = VFD_SECTOR_TO_BYTE(sectors); + } + + alignment = FILE_WORD_ALIGNMENT; + + VFDTRACE(0, ("[VFD] Created an empty RAM disk\n")); + } + + DeviceExtension->MediaChangeCount++; + + DeviceExtension->MediaType = ImageInfo->MediaType; + DeviceExtension->MediaFlags = ImageInfo->MediaFlags; + DeviceExtension->FileType = ImageInfo->FileType; + DeviceExtension->Geometry = geometry; + DeviceExtension->Sectors = sectors; + + VFDTRACE(0, ("[VFD] Media:%d Flag:0x%02x Size:%lu Capacity:%lu\n", + DeviceExtension->MediaType, + DeviceExtension->MediaFlags, + DeviceExtension->ImageSize, + DeviceExtension->Sectors)); + + DeviceExtension->DeviceObject->AlignmentRequirement + = alignment; + +exit_func: + VFDTRACE(0, ("[VFD] VfdOpenImage - %s\n", GetStatusName(status))); + + return status; +} + +// +// Close the current image +// +VOID +VfdCloseImage ( + IN PDEVICE_EXTENSION DeviceExtension) +{ + VFDTRACE(0, ("[VFD] VfdCloseImage - IN\n")); + + ASSERT(DeviceExtension); + + DeviceExtension->MediaType = VFD_MEDIA_NONE; + DeviceExtension->MediaFlags = 0; + DeviceExtension->FileType = 0; + DeviceExtension->ImageSize = 0; + DeviceExtension->FileName.Length = 0; + DeviceExtension->Sectors = 0; + + if (DeviceExtension->FileHandle) { + ZwClose(DeviceExtension->FileHandle); + DeviceExtension->FileHandle = NULL; + } + + if (DeviceExtension->FileBuffer) { + ExFreePool(DeviceExtension->FileBuffer); + DeviceExtension->FileBuffer = NULL; + } + + VFDTRACE(0, ("[VFD] VfdCloseImage - OUT\n")); +} + +// +// Return information about the current image +// +NTSTATUS +VfdQueryImage( + IN PDEVICE_EXTENSION DeviceExtension, + OUT PVFD_IMAGE_INFO ImageInfo, + IN ULONG BufferLength, + OUT PULONG ReturnLength) +{ + // Check output buffer length + + if (BufferLength < sizeof(VFD_IMAGE_INFO)) { + return STATUS_BUFFER_TOO_SMALL; + } + + RtlZeroMemory(ImageInfo, BufferLength); + + // Store fixed length image information + + ImageInfo->MediaType = DeviceExtension->MediaType; + + if (DeviceExtension->MediaType == VFD_MEDIA_NONE) { + *ReturnLength = sizeof(VFD_IMAGE_INFO); + return STATUS_SUCCESS; + } + + if (DeviceExtension->FileBuffer) { + ImageInfo->DiskType = VFD_DISKTYPE_RAM; + } + else { + ImageInfo->DiskType = VFD_DISKTYPE_FILE; + } + + ImageInfo->MediaFlags = DeviceExtension->MediaFlags; + ImageInfo->FileType = DeviceExtension->FileType; + ImageInfo->ImageSize = DeviceExtension->ImageSize; + + ImageInfo->NameLength = DeviceExtension->FileName.Length; + + // output buffer is large enough to hold the file name? + + if (BufferLength < sizeof(VFD_IMAGE_INFO) + + DeviceExtension->FileName.Length) + { + *ReturnLength = sizeof(VFD_IMAGE_INFO); + return STATUS_BUFFER_OVERFLOW; + } + + // copy file name + + if (DeviceExtension->FileName.Length && + DeviceExtension->FileName.Buffer) { + + RtlCopyMemory(ImageInfo->FileName, + DeviceExtension->FileName.Buffer, + DeviceExtension->FileName.Length); + } + + // store the actually returned data length + + *ReturnLength = sizeof(VFD_IMAGE_INFO) + + DeviceExtension->FileName.Length; + + return STATUS_SUCCESS; +} diff --git a/modules/rosapps/drivers/vfd/vfdioctl.c b/modules/rosapps/drivers/vfd/vfdioctl.c new file mode 100644 index 00000000000..db4ec798797 --- /dev/null +++ b/modules/rosapps/drivers/vfd/vfdioctl.c @@ -0,0 +1,591 @@ +/* + vfdioctl.c + + Virtual Floppy Drive for Windows NT platform + Kernel mode driver: I/O control request handling + + Copyright (C) 2003-2005 Ken Kato +*/ + +#include "imports.h" +#include "vfddrv.h" +#include "vfddbg.h" + +/* +#include +DEFINE_GUID(VFD_GUID, 0x4563b3d8L, 0x936a, 0x4692, + 0xb6, 0x0c, 0x16, 0xd3, 0xb2, 0x57, 0xbb, 0xf2); +*/ + +#define IO_INPUTLEN(p) (p)->Parameters.DeviceIoControl.InputBufferLength +#define IO_OUTPUTLEN(p) (p)->Parameters.DeviceIoControl.OutputBufferLength +#define IO_CTRLCODE(p) (p)->Parameters.DeviceIoControl.IoControlCode + +// +// IOCTL commands handler +// +NTSTATUS +NTAPI +VfdDeviceControl ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PDEVICE_EXTENSION device_extension; + PIO_STACK_LOCATION io_stack; + NTSTATUS status; + + device_extension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; + io_stack = IoGetCurrentIrpStackLocation(Irp); + + Irp->IoStatus.Information = 0; + + VFDTRACE(VFDINFO, ("[VFD] %-40s %ws\n", + GetIoControlName(IO_CTRLCODE(io_stack)), + device_extension->DeviceName.Buffer)); + +#ifdef VFD_PNP + status = IoAcquireRemoveLock(&device_extension->RemoveLock, Irp); + + if (!NT_SUCCESS(status)) { + VFDTRACE(0, + ("Acquire RemoveLock failed %s\n", NtStatusToStr(status))); + + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return status; + } +#endif // VFD_PNP + +/* + // Check if volume verification is required + + if ((DeviceObject->Flags & DO_VERIFY_VOLUME) && + !(io_stack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) { + + VFDTRACE(VFDWARN, + ("[VFD] %-40s - %s\n", + GetIoControlName(IO_CTRLCODE(io_stack)), + GetStatusName(STATUS_VERIFY_REQUIRED))); + + Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_VERIFY_REQUIRED; + } +*/ + + switch (IO_CTRLCODE(io_stack)) { + case IOCTL_VFD_OPEN_IMAGE: + // Open an image file or create an empty RAM disk. + // Only a few checks are done here. + // Actual operation is done in device thread + + status = VfdOpenCheck( + device_extension, + (PVFD_IMAGE_INFO)Irp->AssociatedIrp.SystemBuffer, + IO_INPUTLEN(io_stack)); + + if (!NT_SUCCESS(status)) { + break; + } + + // Pass the task to the device thread + status = STATUS_PENDING; + break; + + case IOCTL_VFD_CLOSE_IMAGE: + case IOCTL_DISK_EJECT_MEDIA: + case IOCTL_STORAGE_EJECT_MEDIA: + // Close the current image file or delete the RAM disk + // Only status check is done here. + // Actual operation is done in device thread. + + if (!device_extension->FileHandle && + !device_extension->FileBuffer) { + status = STATUS_NO_MEDIA_IN_DEVICE; + break; + } + + // Pass the task to the device thread + status = STATUS_PENDING; + break; + + case IOCTL_VFD_QUERY_IMAGE: + // Returns current image file information + + status = VfdQueryImage( + device_extension, + (PVFD_IMAGE_INFO)Irp->AssociatedIrp.SystemBuffer, + IO_OUTPUTLEN(io_stack), + &Irp->IoStatus.Information); + + break; + + case IOCTL_VFD_SET_LINK: + // Create / remove a persistent drive letter + // and store it in the registry + + if (IO_INPUTLEN(io_stack) < sizeof(CHAR)) { + status = STATUS_INVALID_PARAMETER; + break; + } + +#ifdef VFD_MOUNT_MANAGER + if (OsMajorVersion >= 5) { + // Windows 2000/XP + // Create a drive letter via the mount manager + + status = VfdMountMgrMountPoint(device_extension, + *(PCHAR)Irp->AssociatedIrp.SystemBuffer); + + // The new drive letter will be stored in the device extension + // and the registry when IOCTL_MOUNTDEV_LINK_CREATED or + // IOCTL_MOUNTDEV_LINK_DELETED is issued from the mount manager. + } + else +#else // VFD_MOUNT_MANAGER + { + // Windows NT style drive letter assignment + // Simply create a symbolic link and store the new value + + status = VfdSetLink(device_extension, + *(PCHAR)Irp->AssociatedIrp.SystemBuffer); + + if (NT_SUCCESS(status)) { + // Store the new drive letter into the registry + status = VfdStoreLink(device_extension); + } + } +#endif // VFD_MOUNT_MANAGER + break; + + case IOCTL_VFD_QUERY_LINK: + // Return the current persistent drive letter + + if (IO_OUTPUTLEN(io_stack) < sizeof(CHAR)) { + status = STATUS_BUFFER_TOO_SMALL; + break; + } + + *(PCHAR)Irp->AssociatedIrp.SystemBuffer = + device_extension->DriveLetter; + + Irp->IoStatus.Information = sizeof(CHAR); + status = STATUS_SUCCESS; + break; + + case IOCTL_VFD_SET_PROTECT: + // Set media protect flag + + if (!device_extension->FileHandle && + !device_extension->FileBuffer) { + status = STATUS_NO_MEDIA_IN_DEVICE; + break; + } + + device_extension->MediaFlags |= VFD_FLAG_WRITE_PROTECTED; + status = STATUS_SUCCESS; + break; + + case IOCTL_VFD_CLEAR_PROTECT: + // Clear media protect flag + + if (!device_extension->FileHandle && + !device_extension->FileBuffer) { + status = STATUS_NO_MEDIA_IN_DEVICE; + break; + } + + device_extension->MediaFlags &= ~VFD_FLAG_WRITE_PROTECTED; + status = STATUS_SUCCESS; + break; + + case IOCTL_VFD_RESET_MODIFY: + // Reset the data modify flag + + if (!device_extension->FileHandle && + !device_extension->FileBuffer) { + status = STATUS_NO_MEDIA_IN_DEVICE; + break; + } + + device_extension->MediaFlags &= ~VFD_FLAG_DATA_MODIFIED; + status = STATUS_SUCCESS; + break; + + case IOCTL_VFD_QUERY_NUMBER: + // Return VFD device number (\??\VirtualFD) + + if (IO_OUTPUTLEN(io_stack) < sizeof(ULONG)) { + status = STATUS_BUFFER_TOO_SMALL; + break; + } + + *(PULONG)Irp->AssociatedIrp.SystemBuffer= + device_extension->DeviceNumber; + + Irp->IoStatus.Information = sizeof(ULONG); + status = STATUS_SUCCESS; + break; + + case IOCTL_VFD_QUERY_NAME: + // Return VFD device name (\Device\Floppy) + // counted unicode string (not null terminated) + + if (IO_OUTPUTLEN(io_stack) < sizeof(USHORT)) { + status = STATUS_BUFFER_TOO_SMALL; + break; + } + + { + PUSHORT p = (PUSHORT)Irp->AssociatedIrp.SystemBuffer; + + *p = device_extension->DeviceName.Length; + + if (IO_OUTPUTLEN(io_stack) < sizeof(USHORT) + *p) { + + Irp->IoStatus.Information = sizeof(USHORT); + status = STATUS_BUFFER_OVERFLOW; + break; + } + + RtlCopyMemory(p + 1, device_extension->DeviceName.Buffer, *p); + + Irp->IoStatus.Information = sizeof(USHORT) + *p; + } + + status = STATUS_SUCCESS; + break; + + case IOCTL_VFD_QUERY_VERSION: + // Return the VFD driver version + + if (IO_OUTPUTLEN(io_stack) < sizeof(ULONG)) { + status = STATUS_BUFFER_TOO_SMALL; + break; + } + + *(PULONG)Irp->AssociatedIrp.SystemBuffer = + (VFD_DRIVER_MAJOR << 16) | VFD_DRIVER_MINOR | VFD_DEBUG_FLAG; + + Irp->IoStatus.Information = sizeof(ULONG); + status = STATUS_SUCCESS; + break; + + // + // standard disk and storage I/O control requests + // + + case IOCTL_DISK_CHECK_VERIFY: + case IOCTL_STORAGE_CHECK_VERIFY: + case IOCTL_STORAGE_CHECK_VERIFY2: + + if (IO_OUTPUTLEN(io_stack) >= sizeof(ULONG)) { + + *(PULONG)Irp->AssociatedIrp.SystemBuffer = + device_extension->MediaChangeCount; + + Irp->IoStatus.Information = sizeof(ULONG); + } + + status = STATUS_SUCCESS; + break; + + case IOCTL_DISK_FORMAT_TRACKS: + case IOCTL_DISK_FORMAT_TRACKS_EX: + // Only parameter checks are performed here + // Actual operation is done by the device thread + + status = VfdFormatCheck( + device_extension, + (PFORMAT_PARAMETERS)Irp->AssociatedIrp.SystemBuffer, + IO_INPUTLEN(io_stack), + IO_CTRLCODE(io_stack)); + + if (!NT_SUCCESS(status)) { + break; + } + + // Pass the task to the device thread + status = STATUS_PENDING; + break; + + case IOCTL_DISK_GET_DRIVE_GEOMETRY: + // Returns the geometry of current media + + if (!device_extension->FileHandle && + !device_extension->FileBuffer) { + status = STATUS_NO_MEDIA_IN_DEVICE; + break; + } + // fall through + + case IOCTL_DISK_GET_MEDIA_TYPES: + case IOCTL_STORAGE_GET_MEDIA_TYPES: + // Return *the last mounted* disk geometry, although xxx_GET_MEDIA_TYPES + // commands are supposed to return all supported media types. + // This makes the matter much simpler...;-) + // If no image has been mounted yet, 1.44MB media is assumed. + + if (IO_OUTPUTLEN(io_stack) < sizeof(DISK_GEOMETRY)) { + return STATUS_BUFFER_TOO_SMALL; + } + + // Copy appropriate DISK_GEOMETRY into the output buffer + + if (device_extension->Geometry) { + RtlCopyMemory( + Irp->AssociatedIrp.SystemBuffer, + device_extension->Geometry, + sizeof(DISK_GEOMETRY)); + } + else { + // default = 3.5" 1.44 MB media + RtlCopyMemory( + Irp->AssociatedIrp.SystemBuffer, + &geom_tbl[VFD_MEDIA_F3_1P4], + sizeof(DISK_GEOMETRY)); + } + Irp->IoStatus.Information = sizeof(DISK_GEOMETRY); + + status = STATUS_SUCCESS; + break; + + case IOCTL_DISK_GET_LENGTH_INFO: + // Return disk length information + // (Windows XP requires this request to be handled) + + if (!device_extension->FileHandle && + !device_extension->FileBuffer) { + status = STATUS_NO_MEDIA_IN_DEVICE; + break; + } + + if (IO_OUTPUTLEN(io_stack) < sizeof(GET_LENGTH_INFORMATION)) { + status = STATUS_BUFFER_TOO_SMALL; + break; + } + + ((PGET_LENGTH_INFORMATION)Irp->AssociatedIrp.SystemBuffer)->Length.QuadPart = + VFD_SECTOR_TO_BYTE(device_extension->Sectors); + + Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION); + + status = STATUS_SUCCESS; + break; + + case IOCTL_DISK_IS_WRITABLE: + // Checks if current media is writable + + if (!device_extension->FileHandle && + !device_extension->FileBuffer) { + status = STATUS_NO_MEDIA_IN_DEVICE; + } + else if (device_extension->MediaFlags & VFD_FLAG_WRITE_PROTECTED) { + status = STATUS_MEDIA_WRITE_PROTECTED; + } + else { + status = STATUS_SUCCESS; + } + break; + +/* + case IOCTL_DISK_MEDIA_REMOVAL: + case IOCTL_STORAGE_MEDIA_REMOVAL: + // Since removal lock is irrelevant for virtual disks, + // there's really nothing to do here... + + status = STATUS_SUCCESS; + break; + + case IOCTL_STORAGE_GET_HOTPLUG_INFO: + { + PSTORAGE_HOTPLUG_INFO hotplug; + + if (IO_OUTPUTLEN(io_stack) < sizeof(STORAGE_HOTPLUG_INFO)) { + status = STATUS_BUFFER_TOO_SMALL; + break; + } + + hotplug = (PSTORAGE_HOTPLUG_INFO)Irp->AssociatedIrp.SystemBuffer; + + RtlZeroMemory(hotplug, sizeof(STORAGE_HOTPLUG_INFO)); + + hotplug->Size = sizeof(STORAGE_HOTPLUG_INFO); + hotplug->MediaRemovable = 1; + + Irp->IoStatus.Information = sizeof(STORAGE_HOTPLUG_INFO); + status = STATUS_SUCCESS; + } + break; +*/ + +#ifdef VFD_MOUNT_MANAGER + // + // IO control requests received from the mount manager + // (on Windows 2000 / XP) + // + + case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID: + // Returns a unique ID for the target device + status = VfdMountDevUniqueId( + device_extension, + Irp->AssociatedIrp.SystemBuffer, + IO_OUTPUTLEN(io_stack), + &Irp->IoStatus); + break; + +// case IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY: + + case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME: + // Returns the device name of the target device + status = VfdMountDevDeviceName( + device_extension, + Irp->AssociatedIrp.SystemBuffer, + IO_OUTPUTLEN(io_stack), + &Irp->IoStatus); + break; + + case IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME: + // Returns the drive letter link which we want the mount manager + // to create. This request is issued in response to the volume + // arrival notification, and the mount manager will create the + // symbolic link. + status = VfdMountDevSuggestedLink( + device_extension, + Irp->AssociatedIrp.SystemBuffer, + IO_OUTPUTLEN(io_stack), + &Irp->IoStatus); + break; + + case IOCTL_MOUNTDEV_LINK_CREATED: + case IOCTL_MOUNTDEV_LINK_DELETED: + // Issued after the mount manager created/deleted a symbolic link + status = VfdMountDevLinkModified( + device_extension, + Irp->AssociatedIrp.SystemBuffer, + IO_INPUTLEN(io_stack), + IO_CTRLCODE(io_stack)); + break; + +/* + case IOCTL_MOUNTDEV_QUERY_STABLE_GUID: + { + PMOUNTDEV_STABLE_GUID guid; + + if (IO_OUTPUTLEN(io_stack) < sizeof(MOUNTDEV_STABLE_GUID)) { + status = STATUS_INVALID_PARAMETER; + break; + } + + guid = Irp->AssociatedIrp.SystemBuffer; + + RtlCopyMemory( + &guid->StableGuid, &VFD_GUID, sizeof(GUID)); + + Irp->IoStatus.Information = sizeof(guid); + status = STATUS_SUCCESS; + } + break; +*/ +#endif // VFD_MOUNT_MANAGER + + default: + // Unknown IOCTL request + status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + +#if DBG + if ((NT_SUCCESS(status) && (TraceFlags & VFDINFO) == VFDINFO) || + (TraceFlags & VFDWARN) == VFDWARN) { + VFDTRACE(0,("[VFD] %-40s - %s\n", + GetIoControlName(IO_CTRLCODE(io_stack)), + GetStatusName(status))); + } +#endif + + if (status == STATUS_PENDING) { + // Let the device thread perform the operation + + IoMarkIrpPending(Irp); + + ExInterlockedInsertTailList( + &device_extension->ListHead, + &Irp->Tail.Overlay.ListEntry, + &device_extension->ListLock); + + KeSetEvent( + &device_extension->RequestEvent, + (KPRIORITY) 0, + FALSE); + } + else { + // complete the operation + + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + +#ifdef VFD_PNP + IoReleaseRemoveLock(&device_extension->RemoveLock, Irp); +#endif // VFD_PNP + } + + return status; +} + +// +// Handle IO control requests in the device thread +// +VOID +VfdIoCtlThread( + IN PDEVICE_EXTENSION DeviceExtension, + IN PIRP Irp, + IN ULONG ControlCode) +{ + switch (ControlCode) { + case IOCTL_VFD_OPEN_IMAGE: + // open the file from the caller's security context + // -- this allows this driver to open network files + if (DeviceExtension->SecurityContext) { + SeImpersonateClient(DeviceExtension->SecurityContext, NULL); + } + + Irp->IoStatus.Status = VfdOpenImage(DeviceExtension, + (PVFD_IMAGE_INFO)Irp->AssociatedIrp.SystemBuffer); + + PsRevertToSelf(); + break; + + case IOCTL_VFD_CLOSE_IMAGE: + case IOCTL_DISK_EJECT_MEDIA: + case IOCTL_STORAGE_EJECT_MEDIA: + VfdCloseImage(DeviceExtension); + Irp->IoStatus.Status = STATUS_SUCCESS; + break; + + case IOCTL_DISK_FORMAT_TRACKS: + case IOCTL_DISK_FORMAT_TRACKS_EX: + Irp->IoStatus.Status = VfdFormatTrack(DeviceExtension, + (PFORMAT_PARAMETERS)Irp->AssociatedIrp.SystemBuffer); + break; + + default: + // This shouldn't happen... + VFDTRACE(0, + ("[VFD] %s passed to the device thread\n", + GetIoControlName(ControlCode))); + + Irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR; + } + +#if DBG + if ((NT_SUCCESS(Irp->IoStatus.Status) && (TraceFlags & VFDINFO) == VFDINFO) || + (TraceFlags & VFDWARN) == VFDWARN) { + VFDTRACE(0,("[VFD] %-40s - %s\n", + GetIoControlName(ControlCode), + GetStatusName(Irp->IoStatus.Status))); + } +#endif +} diff --git a/modules/rosapps/drivers/vfd/vfdlink.c b/modules/rosapps/drivers/vfd/vfdlink.c new file mode 100644 index 00000000000..0d32cd2bd0e --- /dev/null +++ b/modules/rosapps/drivers/vfd/vfdlink.c @@ -0,0 +1,226 @@ +/* + vfdlink.c + + Virtual Floppy Drive for Windows NT platform + Kernel mode driver: persistent drive letter functions + + Copyright (C) 2003-2005 Ken Kato +*/ + +#include "imports.h" +#include "vfddrv.h" +#include "vfddbg.h" + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, VfdSetLink) +#pragma alloc_text(PAGE, VfdLoadLink) +#pragma alloc_text(PAGE, VfdStoreLink) +#endif // ALLOC_PRAGMA + +// +// create or remove the persistent drive letter (Windows NT) +// +NTSTATUS +VfdSetLink( + IN PDEVICE_EXTENSION DeviceExtension, + IN CHAR DriveLetter) +{ + UNICODE_STRING unicode_name; + WCHAR name_buf[15]; + NTSTATUS status = STATUS_SUCCESS; + + VFDTRACE(VFDINFO, ("[VFD] VfdSetLink - IN\n")); + + // convert lower case into upper case + + if (DriveLetter >= 'a' && DriveLetter <= 'z') { + DriveLetter -= ('a' - 'A'); + } + + // check the drive letter range + + if (DriveLetter != 0 && + (DriveLetter < 'A' || DriveLetter > 'Z')) { + return STATUS_INVALID_PARAMETER; + } + + if (DeviceExtension->DriveLetter && + DeviceExtension->DriveLetter != DriveLetter) { + // + // Delete the old drive letter + // + name_buf[sizeof(name_buf) - 1] = UNICODE_NULL; + + _snwprintf(name_buf, sizeof(name_buf) - 1, + L"\\??\\%wc:", DeviceExtension->DriveLetter); + + RtlInitUnicodeString(&unicode_name, name_buf); + + status = IoDeleteSymbolicLink(&unicode_name); + + if (NT_SUCCESS(status)) { + VFDTRACE(VFDINFO, + ("[VFD] Link %ws deleted\n", name_buf)); + + DeviceExtension->DriveLetter = 0; + } + else if (status != STATUS_OBJECT_NAME_NOT_FOUND) { + // the driver letter did not exist in the first place + + VFDTRACE(VFDINFO, + ("[VFD] Link %ws not found\n", name_buf)); + + DeviceExtension->DriveLetter = 0; + status = STATUS_SUCCESS; + } + else { + VFDTRACE(VFDWARN, + ("[VFD] IoDeleteSymbolicLink %ws - %s\n", + name_buf, GetStatusName(status))); + } + } + + if (NT_SUCCESS(status) && DriveLetter) { + // + // Create a new drive letter + // + + name_buf[sizeof(name_buf) - 1] = UNICODE_NULL; + + _snwprintf(name_buf, sizeof(name_buf) - 1, + (OsMajorVersion >= 5) ? + L"\\??\\Global\\%wc:" : L"\\??\\%wc:", + DriveLetter); + + RtlInitUnicodeString(&unicode_name, name_buf); + + status = IoCreateSymbolicLink( + &unicode_name, &(DeviceExtension->DeviceName)); + + if (NT_SUCCESS(status)) { + VFDTRACE(VFDINFO, ("[VFD] Link %ws created\n", name_buf)); + + DeviceExtension->DriveLetter = DriveLetter; + } + else { + VFDTRACE(VFDWARN, + ("[VFD] IoCreateSymbolicLink %ws - %s\n", + name_buf, GetStatusName(status))); + } + } + + VFDTRACE(VFDINFO, + ("[VFD] VfdSetLink - %s\n", GetStatusName(status))); + + return status; +} + +// +// load the persistent drive letter from the registry +// +NTSTATUS +VfdLoadLink( + IN PDEVICE_EXTENSION DeviceExtension, + IN PWSTR RegistryPath) +{ + RTL_QUERY_REGISTRY_TABLE params[2]; + WCHAR name_buf[20]; + ULONG letter; + ULONG zero = 0; + NTSTATUS status; + + VFDTRACE(VFDINFO, ("[VFD] VfdLoadLink - IN\n")); + + RtlZeroMemory(params, sizeof(params)); + + name_buf[sizeof(name_buf) - 1] = UNICODE_NULL; + + _snwprintf(name_buf, sizeof(name_buf) - 1, + VFD_REG_DRIVE_LETTER L"%lu", + DeviceExtension->DeviceNumber); + + params[0].Flags = RTL_QUERY_REGISTRY_DIRECT; + params[0].Name = name_buf; + params[0].EntryContext = &letter; + params[0].DefaultType = REG_DWORD; + params[0].DefaultData = &zero; + params[0].DefaultLength = sizeof(ULONG); + + status = RtlQueryRegistryValues( + RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, + RegistryPath, ¶ms[0], NULL, NULL); + + VFDTRACE(VFDINFO, + ("[VFD] Drive letter '%wc' loaded from the registry\n", + letter ? letter : ' ')); + + DeviceExtension->DriveLetter = (CHAR)letter; + + VFDTRACE(VFDINFO, + ("[VFD] VfdLoadLink - %s\n", GetStatusName(status))); + + return status; +} + +// +// store the persistent drive letter into the registry +// +NTSTATUS +VfdStoreLink( + IN PDEVICE_EXTENSION DeviceExtension) +{ + PVFD_DRIVER_EXTENSION driver_extension; + WCHAR name_buf[20]; + ULONG letter; + NTSTATUS status; + + VFDTRACE(VFDINFO, ("[VFD] VfdStoreLink - IN\n")); + +#ifdef VFD_PNP + driver_extension = IoGetDriverObjectExtension( + DeviceExtension->device_object->DriverObject, + VFD_DRIVER_EXTENSION_ID); +#else // VFD_PNP + driver_extension = DeviceExtension->DriverExtension; +#endif // VFD_PNP + + if (!driver_extension || + !driver_extension->RegistryPath.Buffer) { + + VFDTRACE(VFDWARN, ("[VFD] Registry Path not present.\n")); + VFDTRACE(VFDINFO, ("[VFD] VfdStoreLinks - OUT\n")); + return STATUS_DRIVER_INTERNAL_ERROR; + } + + name_buf[sizeof(name_buf) - 1] = UNICODE_NULL; + + _snwprintf(name_buf, sizeof(name_buf) - 1, + VFD_REG_DRIVE_LETTER L"%lu", + DeviceExtension->DeviceNumber); + + letter = DeviceExtension->DriveLetter; + + status = RtlWriteRegistryValue( + RTL_REGISTRY_ABSOLUTE, + driver_extension->RegistryPath.Buffer, + name_buf, + REG_DWORD, + &letter, + sizeof(ULONG)); + + if (!NT_SUCCESS(status)) { + VFDTRACE(VFDWARN, + ("[VFD] RtlWriteRegistryValue - %s\n", + GetStatusName(status))); + } + else { + VFDTRACE(VFDINFO, + ("[VFD] Drive letter '%wc' stored into the registry\n", + letter ? letter : L' ')); + } + + VFDTRACE(VFDINFO, + ("[VFD] VfdStoreLink - %s\n", GetStatusName(status))); + + return status; +} diff --git a/modules/rosapps/drivers/vfd/vfdmnt.c b/modules/rosapps/drivers/vfd/vfdmnt.c new file mode 100644 index 00000000000..7d84180adac --- /dev/null +++ b/modules/rosapps/drivers/vfd/vfdmnt.c @@ -0,0 +1,665 @@ +/* + vfdmnt.c + + Virtual Floppy Drive for Windows NT platform + Kernel mode driver mount manager functions + + Copyright (C) 2003-2005 Ken Kato +*/ + +#ifndef VFD_MOUNT_MANAGER +/* + Not in working order for the time being + so DO NOT define VFD_MOUNT_MANAGER macro + unless you know exactly what you are doing... +*/ +#ifdef _MSC_VER +// suppress empty compile unit warning +#pragma warning (disable: 4206) +#pragma message ("Mount Manager support feature is disabled.") +#endif + +#else // VFD_MOUNT_MANAGER +/* + The flow of the drive letter assignment via the Mount Manager + during the VFD driver start up + + 1) IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION VFD -> MM + notifies the mount manager of VFD devices. + + 2) IOCTL_MOUNTDEV_QUERY_DEVICE_NAME VFD <- MM + device name (\Device\Floppy) VFD -> MM + + 3) IOCTL_MOUNTDEV_QUERY_UNIQUE_ID VFD <- MM + device unique ID (\??\VirtualFD) VFD -> MM + + 4) IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME VFD <- MM + drive letter link (\DosDevices\:) VFD -> MM + + 5) The mount manager creates the drive letter link + + 6) IOCTL_MOUNTDEV_LINK_CREATED VFD <- MM + The driver stores the created drive letter + + The flow of the drive letter operation with IOCTL_VFD_SET_LINK + + 1) IOCTL_MOUNTMGR_CREATE_POINT or + IOCTL_MOUNTMGR_DELETE_POINTS VFD -> MM + + 2) The mount manager creates/deletes the drive letter link + + 3) IOCTL_MOUNTDEV_LINK_CREATED or + IOCTL_MOUNTDEV_LINK_DELETED VFD <- MM + The driver stores the created/deleted drive letter +*/ + +#include "imports.h" +#include "vfddrv.h" +#include "vfddbg.h" + +// +// Call the mount manager with an IO control IRP +// +static NTSTATUS +VfdMountMgrSendRequest( + ULONG ControlCode, + PVOID InputBuffer, + ULONG InputLength, + PVOID OutputBuffer, + ULONG OutputLength); + +#ifdef ALLOC_PRAGMA +//#pragma alloc_text(PAGE, VfdRegisterMountManager) +#pragma alloc_text(PAGE, VfdMountMgrNotifyVolume) +#pragma alloc_text(PAGE, VfdMountMgrMountPoint) +#pragma alloc_text(PAGE, VfdMountMgrSendRequest) +#pragma alloc_text(PAGE, VfdMountDevUniqueId) +#pragma alloc_text(PAGE, VfdMountDevDeviceName) +#pragma alloc_text(PAGE, VfdMountDevSuggestedLink) +#pragma alloc_text(PAGE, VfdMountDevLinkModified) +#endif // ALLOC_PRAGMA + +/* +#include +#include +// +// register a device to the mount manager interface +// does not work... +// +NTSTATUS +VfdRegisterMountManager( + PDEVICE_EXTENSION DeviceExtension) +{ + NTSTATUS status = STATUS_SUCCESS; + UNICODE_STRING interface; + UNICODE_STRING interface2; + + VFDTRACE(VFDINFO, + ("[VFD] Registering %ws to the Mount Manager Interface\n", + DeviceExtension->DeviceName.Buffer)); + + RtlInitUnicodeString(&interface, NULL); + + status = IoRegisterDeviceInterface( + DeviceExtension->DeviceObject, + (LPGUID)&MOUNTDEV_MOUNTED_DEVICE_GUID, + NULL, + &interface); + + if (!NT_SUCCESS(status)) { + VFDTRACE(0, + ("[VFD] IoRegisterDeviceInterface - %s\n", + GetStatusName(status))); + return status; + } + + status = IoSetDeviceInterfaceState(&interface, TRUE); + + if (NT_SUCCESS(status)) { + if (VfdCopyUnicode(&interface2, &interface)) { + VFDTRACE(VFDINFO, + ("[VFD] Interface: %ws\n", interface2.Buffer)); + } + else { + VFDTRACE(0, + ("[VFD] Failed to allocate an interface name buffer\n")); + status = STATUS_INSUFFICIENT_RESOURCES; + } + } + else { + VFDTRACE(0, + ("[VFD] IoSetDeviceInterfaceState - %s\n", + GetStatusName(status))); + } + + RtlFreeUnicodeString(&interface); + VfdFreeUnicode(&interface2); + + return status; +} +*/ + +// +// informs the Mount Manager of a new VFD device +// +NTSTATUS +VfdMountMgrNotifyVolume( + PDEVICE_EXTENSION DeviceExtension) +{ + PMOUNTMGR_TARGET_NAME target_name; + USHORT target_name_buf[MAXIMUM_FILENAME_LENGTH]; + NTSTATUS status; + + VFDTRACE(VFDINFO, + ("[VFD] VfdMountMgrNotifyVolume - %ws\n", + DeviceExtension->DeviceName.Buffer)); + + target_name = (PMOUNTMGR_TARGET_NAME)target_name_buf; + + target_name->DeviceNameLength = + DeviceExtension->DeviceName.Length; + + RtlCopyMemory( + target_name->DeviceName, + DeviceExtension->DeviceName.Buffer, + DeviceExtension->DeviceName.Length); + + status = VfdMountMgrSendRequest( + IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION, + target_name, + sizeof(target_name->DeviceNameLength) + target_name->DeviceNameLength, + NULL, + 0); + + VFDTRACE(VFDINFO, + ("[VFD] VfdMountMgrNotifyVolume - %s\n", + GetStatusName(status))); + + return status; +} + +// +// Create / remove a drive letter via the Mount Manager +// +NTSTATUS +VfdMountMgrMountPoint( + PDEVICE_EXTENSION DeviceExtension, + CHAR DriveLetter) +{ + ULONG alloc_size; + UNICODE_STRING link_name; + WCHAR link_buf[20]; + NTSTATUS status; + + VFDTRACE(VFDINFO, ("[VFD] VfdMountMgrMountPoint - IN\n")); + + // convert lower case into upper case + + if (DriveLetter >= 'a' && DriveLetter <= 'z') { + DriveLetter -= ('a' - 'A'); + } + + if (DriveLetter >= 'A' && DriveLetter <= 'Z') { + + // Create a new drive letter + + PMOUNTMGR_CREATE_POINT_INPUT create; + + swprintf(link_buf, L"\\DosDevices\\%wc:", DriveLetter); + + RtlInitUnicodeString(&link_name, link_buf); + + VFDTRACE(VFDINFO, + ("[VFD] Creating a link: %ws => %ws\n", + link_buf, DeviceExtension->DeviceName.Buffer)); + + // allocate buffer for MOUNTMGR_CREATE_POINT_INPUT + + alloc_size = sizeof(MOUNTMGR_CREATE_POINT_INPUT) + + link_name.Length + DeviceExtension->DeviceName.Length; + + create = (PMOUNTMGR_CREATE_POINT_INPUT)ExAllocatePoolWithTag( + NonPagedPool, alloc_size, VFD_POOL_TAG); + + if (!create) { + VFDTRACE(0, ("[VFD] Failed to allocate mount point input\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // set the symbolic link name + + create->SymbolicLinkNameOffset = sizeof(MOUNTMGR_CREATE_POINT_INPUT); + create->SymbolicLinkNameLength = link_name.Length; + + RtlCopyMemory( + (PCHAR)create + create->SymbolicLinkNameOffset, + link_name.Buffer, + link_name.Length); + + // set the target device name + + create->DeviceNameOffset = (USHORT) + (create->SymbolicLinkNameOffset + create->SymbolicLinkNameLength); + create->DeviceNameLength = DeviceExtension->DeviceName.Length; + + RtlCopyMemory( + (PCHAR)create + create->DeviceNameOffset, + DeviceExtension->DeviceName.Buffer, + DeviceExtension->DeviceName.Length); + + // call the mount manager with the IO control request + + status = VfdMountMgrSendRequest( + IOCTL_MOUNTMGR_CREATE_POINT, + create, alloc_size, NULL, 0); + + ExFreePool(create); + + // no need to set the new drive letter into the + // DeviceExtension because the mount manager will issue an + // IOCTL_MOUNTDEV_LINK_CREATED and it will be processed then + } + else if (DriveLetter == 0) { + + // Delete the existing drive letter + + PMOUNTMGR_MOUNT_POINT mount; + PMOUNTMGR_MOUNT_POINTS points; + UNICODE_STRING unique_id; + WCHAR unique_buf[20]; + + swprintf(link_buf, L"\\DosDevices\\%wc:", + DeviceExtension->DriveLetter); + + VFDTRACE(VFDINFO, + ("[VFD] Deleting link: %ws\n", link_buf)); + + RtlInitUnicodeString(&link_name, link_buf); + + swprintf(unique_buf, L"\\??\\" VFD_DEVICE_BASENAME L"%lu", + DeviceExtension->DeviceNumber); + + RtlInitUnicodeString(&unique_id, unique_buf); + + // allocate buffer for MOUNTMGR_MOUNT_POINT + + alloc_size = sizeof(MOUNTMGR_MOUNT_POINT) + + link_name.Length + + unique_id.Length + + DeviceExtension->DeviceName.Length; + + mount = (PMOUNTMGR_MOUNT_POINT)ExAllocatePoolWithTag( + NonPagedPool, alloc_size, VFD_POOL_TAG); + + if (!mount) { + VFDTRACE(0, ("[VFD] Failed to allocate mount point input\n")); + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory(mount, alloc_size + sizeof(WCHAR)); + + // set the symbolic link name + + mount->SymbolicLinkNameOffset = sizeof(MOUNTMGR_MOUNT_POINT); + mount->SymbolicLinkNameLength = link_name.Length; + + RtlCopyMemory( + (PCHAR)mount + mount->SymbolicLinkNameOffset, + link_name.Buffer, link_name.Length); + + // set the unique id + + mount->UniqueIdOffset = + mount->SymbolicLinkNameOffset + + mount->SymbolicLinkNameLength; + mount->UniqueIdLength = unique_id.Length; + + RtlCopyMemory( + (PCHAR)mount + mount->UniqueIdOffset, + unique_id.Buffer, unique_id.Length); + + // set the target device name + + mount->DeviceNameOffset = + mount->UniqueIdOffset + + mount->UniqueIdLength; + mount->DeviceNameLength = + DeviceExtension->DeviceName.Length; + + RtlCopyMemory( + (PCHAR)mount + mount->DeviceNameOffset, + DeviceExtension->DeviceName.Buffer, + DeviceExtension->DeviceName.Length); + + // prepare the output buffer + + points = (PMOUNTMGR_MOUNT_POINTS)ExAllocatePoolWithTag( + NonPagedPool, alloc_size * 2, VFD_POOL_TAG); + + status = VfdMountMgrSendRequest( + IOCTL_MOUNTMGR_DELETE_POINTS, + mount, alloc_size, points, alloc_size * 2); + + ExFreePool(mount); + ExFreePool(points); + + if (status == STATUS_OBJECT_NAME_NOT_FOUND) { + // the drive letter did not exist in the first place + DeviceExtension->DriveLetter = 0; + } + + // no need to clear the drive letter in the + // DeviceExtension because the mount manager will issue an + // IOCTL_MOUNTDEV_LINK_DELETED and it will be processed then + } + else { + return STATUS_INVALID_PARAMETER; + } + + VFDTRACE(VFDINFO, ("[VFD] VfdMountMgrMountPoint - %s\n", + GetStatusName(status))); + + return status; +} + +// +// send a request to the Mount Manager +// +NTSTATUS +VfdMountMgrSendRequest( + ULONG ControlCode, + PVOID InputBuffer, + ULONG InputLength, + PVOID OutputBuffer, + ULONG OutputLength) +{ + NTSTATUS status = STATUS_SUCCESS; + UNICODE_STRING mntmgr_name; + PDEVICE_OBJECT mntmgr_dev; + PFILE_OBJECT mntmgr_file; + IO_STATUS_BLOCK io_status; + KEVENT event; + PIRP irp; + + // Obtain a pointer to the Mount Manager device object + + RtlInitUnicodeString( + &mntmgr_name, + MOUNTMGR_DEVICE_NAME); + + status = IoGetDeviceObjectPointer( + &mntmgr_name, + FILE_READ_ATTRIBUTES, + &mntmgr_file, + &mntmgr_dev); + + if (!NT_SUCCESS(status)) { + VFDTRACE(VFDWARN, + ("[VFD] IoGetDeviceObjectPointer - %s\n", GetStatusName(status))); + return status; + } + + KeInitializeEvent(&event, NotificationEvent, FALSE); + + // Create an IRP request block + + irp = IoBuildDeviceIoControlRequest( + ControlCode, + mntmgr_dev, + InputBuffer, + InputLength, + OutputBuffer, + OutputLength, + FALSE, + &event, + &io_status); + + if (!irp) { + VFDTRACE(VFDWARN, + ("[VFD] IoBuildDeviceIoControlRequest\n")); + ObDereferenceObject(mntmgr_file); + return STATUS_DRIVER_INTERNAL_ERROR; + } + + // Call the mount manager + + status = IoCallDriver(mntmgr_dev, irp); + + if (!NT_SUCCESS(status)) { + VFDTRACE(VFDWARN, + ("[VFD] IoCallDriver - %s\n", GetStatusName(status))); + } + + if (status == STATUS_PENDING) { + + // Wait for the operation to complete + + KeWaitForSingleObject( + &event, Executive, KernelMode, FALSE, NULL); + + status = io_status.Status; + + if (!NT_SUCCESS(status)) { + VFDTRACE(VFDWARN, + ("[VFD] IoCallDriver - %s\n", GetStatusName(status))); + } + } + + ObDereferenceObject(mntmgr_file); + + return status; +} + +// +// IOCTL_MOUNTDEV_QUERY_UNIQUE_ID +// -- use the device interface link (\??\VirtualFD) as the unique ID +// +NTSTATUS +VfdMountDevUniqueId( + PDEVICE_EXTENSION DeviceExtension, + PMOUNTDEV_UNIQUE_ID UniqueId, + ULONG OutputLength, + PIO_STATUS_BLOCK IoStatus) +{ + WCHAR buf[20]; + UNICODE_STRING unicode; + + if (OutputLength < sizeof(MOUNTDEV_UNIQUE_ID)) { + return STATUS_INVALID_PARAMETER; + } + + swprintf(buf, + L"\\??\\" VFD_DEVICE_BASENAME L"%lu", + DeviceExtension->DeviceNumber); + + RtlInitUnicodeString(&unicode, buf); + + UniqueId->UniqueIdLength = unicode.Length; + + if (OutputLength < + sizeof(UniqueId->UniqueIdLength) + UniqueId->UniqueIdLength) { + + IoStatus->Information = sizeof(MOUNTDEV_UNIQUE_ID); + return STATUS_BUFFER_OVERFLOW; + } + + RtlCopyMemory( + UniqueId->UniqueId, buf, unicode.Length); + + IoStatus->Information = + sizeof(UniqueId->UniqueIdLength) + UniqueId->UniqueIdLength; + + return STATUS_SUCCESS; +} + +// +// IOCTL_MOUNTDEV_QUERY_DEVICE_NAME +// Returns the device name of the target device (\Device\Floppy) +// +NTSTATUS +VfdMountDevDeviceName( + PDEVICE_EXTENSION DeviceExtension, + PMOUNTDEV_NAME DeviceName, + ULONG OutputLength, + PIO_STATUS_BLOCK IoStatus) +{ + if (OutputLength < sizeof(MOUNTDEV_NAME)) { + return STATUS_INVALID_PARAMETER; + } + + DeviceName->NameLength = DeviceExtension->DeviceName.Length; + + if (OutputLength < + sizeof(DeviceName->NameLength) + DeviceName->NameLength) { + + IoStatus->Information = sizeof(MOUNTDEV_NAME); + return STATUS_BUFFER_OVERFLOW; + } + + RtlCopyMemory( + DeviceName->Name, + DeviceExtension->DeviceName.Buffer, + DeviceName->NameLength); + + IoStatus->Information = + sizeof(DeviceName->NameLength) + DeviceName->NameLength; + + return STATUS_SUCCESS; +} + +// +// IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME +// Returns the drive letter link which we want the mount manager +// to create. This request is issued in response to the volume +// arrival notification, and the mount manager will create the +// symbolic link. +// +NTSTATUS +VfdMountDevSuggestedLink( + PDEVICE_EXTENSION DeviceExtension, + PMOUNTDEV_SUGGESTED_LINK_NAME LinkName, + ULONG OutputLength, + PIO_STATUS_BLOCK IoStatus) +{ + WCHAR buf[20]; + UNICODE_STRING unicode; + + if (OutputLength < sizeof(MOUNTDEV_SUGGESTED_LINK_NAME)) { + return STATUS_INVALID_PARAMETER; + } + + LinkName->UseOnlyIfThereAreNoOtherLinks = TRUE; + + if (!DeviceExtension->DriveLetter) { + + // No persistent drive letter stored in the registry + VFDTRACE(VFDINFO, ("[VFD] suggested link : none\n")); + + LinkName->NameLength = 0; + + IoStatus->Information = sizeof(MOUNTDEV_SUGGESTED_LINK_NAME); + return STATUS_SUCCESS; + } + + // A persistent drive letter exists + + swprintf(buf, L"\\DosDevices\\%wc:", + DeviceExtension->DriveLetter); + + VFDTRACE(VFDINFO, ("[VFD] suggested link : %ws\n", buf)); + + RtlInitUnicodeString(&unicode, buf); + + LinkName->NameLength = unicode.Length; + + if (OutputLength < + sizeof(MOUNTDEV_SUGGESTED_LINK_NAME) + + LinkName->NameLength - sizeof(WCHAR)) { + + IoStatus->Information = sizeof(MOUNTDEV_SUGGESTED_LINK_NAME); + return STATUS_BUFFER_OVERFLOW; + } + + RtlCopyMemory(LinkName->Name, buf, unicode.Length); + + IoStatus->Information = + sizeof(MOUNTDEV_SUGGESTED_LINK_NAME) + + LinkName->NameLength - sizeof(WCHAR); + + return STATUS_SUCCESS; +} + +// +// IOCTL_MOUNTDEV_LINK_CREATED / IOCTL_MOUNTDEV_LINK_DELETED +// Issued after the mount manager created/deleted a symbolic link +// If the link is a drive letter, store the new value into the +// registry as the new drive letter +// +NTSTATUS +VfdMountDevLinkModified( + PDEVICE_EXTENSION DeviceExtension, + PMOUNTDEV_NAME LinkName, + ULONG InputLength, + ULONG ControlCode) +{ + if (InputLength < sizeof(MOUNTDEV_NAME)) { + return STATUS_INVALID_PARAMETER; + } + + if (InputLength < sizeof(MOUNTDEV_NAME) + + LinkName->NameLength - sizeof(WCHAR)) { + + return STATUS_INVALID_PARAMETER; + } + +#if DBG + { // Print the reported link name + PWSTR buf = ExAllocatePoolWithTag( + PagedPool, LinkName->NameLength + sizeof(WCHAR), VFD_POOL_TAG); + + if (buf) { + RtlZeroMemory(buf, LinkName->NameLength + sizeof(WCHAR)); + RtlCopyMemory(buf, LinkName->Name, LinkName->NameLength); + VFDTRACE(VFDINFO, ("[VFD] %ws\n", buf)); + ExFreePool(buf); + } + } +#endif // DBG + + if (LinkName->NameLength == 28 && + LinkName->Name[0] == L'\\' && + LinkName->Name[1] == L'D' && + LinkName->Name[2] == L'o' && + LinkName->Name[3] == L's' && + LinkName->Name[4] == L'D' && + LinkName->Name[5] == L'e' && + LinkName->Name[6] == L'v' && + LinkName->Name[7] == L'i' && + LinkName->Name[8] == L'c' && + LinkName->Name[9] == L'e' && + LinkName->Name[10] == L's' && + LinkName->Name[11] == L'\\' && + LinkName->Name[12] >= L'A' && + LinkName->Name[12] <= L'Z' && + LinkName->Name[13] == L':') { + + // The link is a drive letter + + if (ControlCode == IOCTL_MOUNTDEV_LINK_CREATED) { + // link is created - store the new drive letter + DeviceExtension->DriveLetter = (CHAR)LinkName->Name[12]; + } + else { + // link is deleted - clear the drive letter + DeviceExtension->DriveLetter = 0; + } + + // Store the value into the registry + + VfdStoreLink(DeviceExtension); + } + + return STATUS_SUCCESS; +} + +#endif // VFD_MOUNT_MANAGER diff --git a/modules/rosapps/drivers/vfd/vfdpnp.c b/modules/rosapps/drivers/vfd/vfdpnp.c new file mode 100644 index 00000000000..e0885e7ada0 --- /dev/null +++ b/modules/rosapps/drivers/vfd/vfdpnp.c @@ -0,0 +1,474 @@ +/* + vfdpnp.c + + Virtual Floppy Drive for Windows NT platform + Kernel mode driver: Plug & Play functions + + Copyright (C) 2003-2005 Ken Kato +*/ + +#ifndef VFD_PNP +/* + Not in working order for the time being + so DO NOT define VFD_PNP macro + unless you know exactly what you are doing... +*/ +// suppress empty compile unit warning +#ifdef _MSC_VER +#pragma warning (disable: 4206) +#pragma message ("Plug and play support feature is disabled.") +#endif + +#else // VFD_PNP + +#include "imports.h" +#include "vfddrv.h" +#include "vfddbg.h" + +static NTSTATUS +VfdReportDevice( + PDEVICE_EXTENSION device_extension); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, VfdPlugAndPlay) +#pragma alloc_text(PAGE, VfdPowerControl) +#pragma alloc_text(PAGE, VfdSystemControl) +#pragma alloc_text(PAGE, VfdAddDevice) +#pragma alloc_text(PAGE, VfdReportDevice) +#endif // ALLOC_PRAGMA + +#define REMLOCK_TAG 'LdfV' // "VfdL" +#define REMLOCK_MAXIMUM 1 // Max minutes system allows lock to be held +#define REMLOCK_HIGHWATER 10 // Max number of irps holding lock at one time + +#if DBG +static PCSTR StateTable[] ={ + { "STOPPED" }, + { "WORKING" }, + { "PENDINGSTOP" }, + { "PENDINGREMOVE" }, + { "SURPRISEREMOVED" }, + { "REMOVED" }, + { "UNKNOWN" } +}; +#endif // DBG + +// +// PnP I/O request dispatch +// +NTSTATUS +VfdPlugAndPlay( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION io_stack; + PDEVICE_EXTENSION device_extension; + NTSTATUS status = STATUS_SUCCESS; + BOOLEAN lockHeld = TRUE; + + // + // setup necessary pointers + // + io_stack = IoGetCurrentIrpStackLocation( Irp ); + device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; + + ASSERT(device_extension->DeviceState < VFD_MAX_STATE); + + VFDTRACE(VFDINFO, ("[VFD] VfdPlugAndPlay - IN. %ws %s Device State=%s\n", + device_extension->device_name.Buffer, + GetPnpIrpName(io_stack->MinorFunction), + StateTable[device_extension->DeviceState])); + + // + // Acquire remove lock + // + status = IoAcquireRemoveLock(&device_extension->RemoveLock, Irp); + + if (!NT_SUCCESS(status)) { + VFDTRACE(0, ("Acquire RemoveLock failed - %s\n", NtStatusToStr(status))); + + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return status; + } + + // + // Process the PnP I/O request + // + switch (io_stack->MinorFunction) { + case IRP_MN_START_DEVICE: // 0x00 + // + // Start the device + // + device_extension->DeviceState = VFD_WORKING; + status = STATUS_SUCCESS; + + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + break; + + case IRP_MN_QUERY_REMOVE_DEVICE: // 0x01 + // + // Prepare device removal + // + device_extension->DeviceState = VFD_PENDINGREMOVE; + status = STATUS_SUCCESS; + + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + break; + + case IRP_MN_REMOVE_DEVICE: // 0x02 + // + // Remove the device + // + status = STATUS_SUCCESS; + + // complete the current request + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + // + // Set the device status to REMOVED and wait for other drivers + // to release the lock, then delete the device object + // + device_extension->DeviceState = VFD_REMOVED; + IoReleaseRemoveLockAndWait(&device_extension->RemoveLock, Irp); + lockHeld = FALSE; + + VfdRemoveDevice(DeviceObject); + break; + + case IRP_MN_CANCEL_REMOVE_DEVICE: // 0x03 + // + // Before sending the IRP down make sure we have received + // a IRP_MN_QUERY_REMOVE_DEVICE. We may get Cancel Remove + // without receiving a Query Remove earlier, if the + // driver on top fails a Query Remove and passes down the + // Cancel Remove. + // + + if (device_extension->DeviceState == VFD_PENDINGREMOVE) { + device_extension->DeviceState = VFD_WORKING; + } + + status = STATUS_SUCCESS; + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + break; + + case IRP_MN_STOP_DEVICE: // 0x04 + device_extension->DeviceState = VFD_STOPPED; + + status = STATUS_SUCCESS; + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + break; + + case IRP_MN_QUERY_STOP_DEVICE: // 0x05 + device_extension->DeviceState = VFD_PENDINGSTOP; + + status = STATUS_SUCCESS; + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + break; + + case IRP_MN_CANCEL_STOP_DEVICE: // 0x06 + // + // Before sending the IRP down make sure we have received + // a IRP_MN_QUERY_STOP_DEVICE. We may get Cancel Stop + // without receiving a Query Stop earlier, if the + // driver on top fails a Query Stop and passes down the + // Cancel Stop. + // + + if (device_extension->DeviceState == VFD_PENDINGSTOP ) { + device_extension->DeviceState = VFD_WORKING; + } + + status = STATUS_SUCCESS; + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + break; + + case IRP_MN_QUERY_DEVICE_RELATIONS: // 0x07 + status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + + switch (io_stack->Parameters.QueryDeviceRelations.Type) { + case BusRelations: + VFDTRACE(VFDINFO, ("------- BusRelations Query\n")); + break; + + case EjectionRelations: + VFDTRACE(VFDINFO, ("------- EjectionRelations Query\n")); + break; + + case PowerRelations: + VFDTRACE(VFDINFO, ("------- PowerRelations Query\n")); + break; + + case RemovalRelations: + VFDTRACE(VFDINFO, ("------- RemovalRelations Query\n")); + break; + + case TargetDeviceRelation: + VFDTRACE(VFDINFO, ("------- TargetDeviceRelation Query\n")); + + Irp->IoStatus.Information = (LONG)ExAllocatePoolWithTag( + PagedPool, sizeof(DEVICE_RELATIONS), VFD_POOL_TAG); + + if (Irp->IoStatus.Information) { + PDEVICE_RELATIONS rel = (PDEVICE_RELATIONS)Irp->IoStatus.Information; + + rel->Count = 1; + rel->Objects[0] = device_extension->device_object; + + status = STATUS_SUCCESS; + } + else { + status = STATUS_INSUFFICIENT_RESOURCES; + } + break; + + default: + VFDTRACE(VFDINFO, ("------- Unknown Query\n")); + break; + } + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + break; + +// case IRP_MN_QUERY_INTERFACE: // 0x08 +// case IRP_MN_QUERY_CAPABILITIES: // 0x09 +// case IRP_MN_QUERY_RESOURCES: // 0x0A +// case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: // 0x0B +// case IRP_MN_QUERY_DEVICE_TEXT: // 0x0C +// case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: // 0x0D +// case IRP_MN_READ_CONFIG: // 0x0F +// case IRP_MN_WRITE_CONFIG: // 0x10 +// case IRP_MN_EJECT: // 0x11 +// case IRP_MN_SET_LOCK: // 0x12 +// case IRP_MN_QUERY_ID: // 0x13 +// case IRP_MN_QUERY_PNP_DEVICE_STATE: // 0x14 +// case IRP_MN_QUERY_BUS_INFORMATION: // 0x15 +// case IRP_MN_DEVICE_USAGE_NOTIFICATION: // 0x16 + + case IRP_MN_SURPRISE_REMOVAL: // 0x17 + device_extension->DeviceState = VFD_SURPRISEREMOVED; + + status = STATUS_SUCCESS; + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + break; + +// case IRP_MN_QUERY_LEGACY_BUS_INFORMATION: // 0x18 + + default: + // + // unknown request -- simply pass it to the lower device + // + status = STATUS_INVALID_DEVICE_REQUEST; + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + break; + } + + // + // Device Extenion is gone if the current IRP is IRP_MN_REMOVE_DEVICE + // + if (lockHeld == TRUE) { + IoReleaseRemoveLock(&device_extension->RemoveLock, Irp); + } + + VFDTRACE(VFDINFO, ("[VFD] VfdPlugAndPlay - %s\n", NtStatusToStr(status))); + + return status; +} + +// +// Power management I/O request dispatch +// +NTSTATUS +VfdPowerControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION io_stack; + PDEVICE_EXTENSION device_extension; + NTSTATUS status; + + io_stack = IoGetCurrentIrpStackLocation( Irp ); + device_extension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; + + VFDTRACE(VFDINFO, ("[VFD] VfdPowerControl - IN. %ws %s Device State=%s\n", + device_extension->device_name.Buffer, + GetPnpIrpName(io_stack->MinorFunction), + StateTable[device_extension->DeviceState])); + + PoStartNextPowerIrp(Irp); + + // + // If the device has been removed, the driver should not pass + // the IRP down to the next lower driver. + // + + if (device_extension->DeviceState == VFD_REMOVED) { + status = STATUS_DELETE_PENDING; + } + else { + status = STATUS_SUCCESS; + } + + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + VFDTRACE(VFDINFO, ("[VFD] VfdPowerControl - %s\n", NtStatusToStr(status))); + + return status; +} + +// +// WMI I/O request dispatch +// +NTSTATUS +VfdSystemControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION io_stack; + PDEVICE_EXTENSION device_extension; + NTSTATUS status; + + io_stack = IoGetCurrentIrpStackLocation(Irp); + device_extension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; + + VFDTRACE(VFDINFO, ("[VFD] VfdSystemControl - IN. %ws %s Device State=%s\n", + device_extension->device_name.Buffer, + GetPnpIrpName(io_stack->MinorFunction), + StateTable[device_extension->DeviceState])); + + status = STATUS_SUCCESS; + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + VFDTRACE(VFDINFO, ("[VFD] VfdSystemControl - %s\n", NtStatusToStr(status))); + + return status; +} + +// +// PnP AddDevice function +// +NTSTATUS +VfdAddDevice( + IN PDRIVER_OBJECT DriverObject, + IN OUT PDEVICE_OBJECT PhysicalDevice) +{ + PDEVICE_OBJECT device_object; + PDEVICE_EXTENSION device_extension; + NTSTATUS status; + + VFDTRACE(VFDINFO, ("[VFD] VfdAddDevice - IN\n")); + + status = VfdCreateDevice(DriverObject, &device_object); + + if (NT_SUCCESS(status)) { + + device_object->Flags |= DO_POWER_PAGABLE; + + device_extension = + (PDEVICE_EXTENSION)device_object->DeviceExtension; + + // Device starts in Stopped state + device_extension->DeviceState = VFD_STOPPED; + + VFDTRACE(VFDINFO, ("[VFD] Initializing the remove lock\n")); + + IoInitializeRemoveLock( + &device_extension->RemoveLock, + REMLOCK_TAG, + REMLOCK_MAXIMUM, + REMLOCK_HIGHWATER); + + if (PhysicalDevice) { + device_extension->PhysicalDevice = PhysicalDevice; + } + else { + VfdReportDevice(device_extension); + } + VfdRegisterInterface(device_extension); + VfdMountMgrNotifyVolume(device_extension); + } + + return status; +} + +// +// Report a VFD device to the PnP manager +// +NTSTATUS +VfdReportDevice( + PDEVICE_EXTENSION device_extension) +{ + NTSTATUS status = STATUS_SUCCESS; + CM_RESOURCE_LIST list = {0}; + PCM_FULL_RESOURCE_DESCRIPTOR full = &(list.List[0]); + PCM_PARTIAL_RESOURCE_LIST part = &(full->PartialResourceList); + PCM_PARTIAL_RESOURCE_DESCRIPTOR desc = &(part->PartialDescriptors[0]);; + + list.Count = 1; + + full->InterfaceType = Internal; + full->BusNumber = device_extension->device_number; + + part->Version = 1; + part->Revision = 1; + part->Count = 1; + + desc->Type = CmResourceTypeDeviceSpecific; + desc->ShareDisposition = CmResourceShareShared; + desc->Flags = 0; + + VFDTRACE(VFDINFO,("[VFD] Reporting device %lu to the PnP manager\n", + device_extension->device_number)); + + status = IoReportDetectedDevice( + device_extension->device_object->DriverObject, // IN PDRIVER_OBJECT DriverObject, + Internal, // IN INTERFACE_TYPE LegacyBusType, + (ULONG)-1, // IN ULONG BusNumber, + (ULONG)-1, // IN ULONG SlotNumber, + &list, // IN PCM_RESOURCE_LIST ResourceList, + NULL, // IN PIO_RESOURCE_REQUIREMENTS_LIST OPTIONAL, + TRUE, // IN BOOLEAN ResourceAssigned, + &(device_extension->PhysicalDevice) // IN OUT PDEVICE_OBJECT *DeviceObject + ); + + if (!NT_SUCCESS(status)) { + VFDTRACE(0, + ("[VFD] IoReportDetectedDevice - %s\n", + NtStatusToStr(status))); + } + + device_extension->TargetDevice = IoAttachDeviceToDeviceStack( + device_extension->device_object, + device_extension->PhysicalDevice); + + return status; +} + +#endif // VFD_PNP diff --git a/modules/rosapps/drivers/vfd/vfdrdwr.c b/modules/rosapps/drivers/vfd/vfdrdwr.c new file mode 100644 index 00000000000..564fb68eef0 --- /dev/null +++ b/modules/rosapps/drivers/vfd/vfdrdwr.c @@ -0,0 +1,357 @@ +/* + vfdrdwr.c + + Virtual Floppy Drive for Windows NT platform + Kernel mode driver: Read and Write functions + + Copyright (C) 2003-2005 Ken Kato +*/ + +#include "imports.h" +#include "vfddrv.h" +#include "vfddbg.h" + +// +// IRP_MJ_READ and IRP_MJ_WRITE dispatcher +// Insert the IRP into the IRP queue list. +// Actual operation is performed by the device thread +// +#define IO_READ_OFF(p) (p)->Parameters.Read.ByteOffset.QuadPart +#define IO_READ_LEN(p) (p)->Parameters.Read.Length + +NTSTATUS +NTAPI +VfdReadWrite ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PDEVICE_EXTENSION device_extension; + PIO_STACK_LOCATION io_stack; + NTSTATUS status; + + device_extension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; + + io_stack = IoGetCurrentIrpStackLocation(Irp); + +#if DBG + if (DeviceObject && DeviceObject->DeviceExtension && + ((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->DeviceName.Buffer) { + + VFDTRACE(VFDINFO, ("[VFD] %-40s %ws\n", + GetMajorFuncName(io_stack->MajorFunction), + ((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->DeviceName.Buffer)); + } + else { + VFDTRACE(VFDINFO, ("[VFD] %-40s %p\n", + GetMajorFuncName(io_stack->MajorFunction), + DeviceObject)); + } +#endif // DBG + +#ifdef VFD_PNP + + if (device_extension->DeviceState != VFD_WORKING) { + + // Device is not yet started or being removed, reject any IO request + // TODO: Queue the IRPs + + VFDTRACE(VFDWARN, ("[VFD] Device not ready\n")); + + status = STATUS_INVALID_DEVICE_STATE; + goto complete_request; + } + else { + status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp); + + if (!NT_SUCCESS(status)) { + VFDTRACE(0, ("[VFD] Acquire RemoveLock failed: %s\n", GetStatusName(status))); + + goto complete_request; + } + } +#endif // VFD_PNP + +/* + // Check if volume verification is required + + if ((DeviceObject->Flags & DO_VERIFY_VOLUME) && + !(io_stack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) { + + status = STATUS_VERIFY_REQUIRED; + goto complete_request; + } +*/ + + // Check if an image is opened + + if (!device_extension->FileHandle && + !device_extension->FileBuffer) { + + status = STATUS_NO_MEDIA_IN_DEVICE; + goto complete_request; + } + + + // Check if write operation is allowed + + if (io_stack->MajorFunction == IRP_MJ_WRITE && + (device_extension->MediaFlags & VFD_FLAG_WRITE_PROTECTED)) { + + status = STATUS_MEDIA_WRITE_PROTECTED; + goto complete_request; + } + + + // Check for invalid parameters. It is an error for the starting offset + // + length to go past the end of the partition, or for the length or + // offset to not be a proper multiple of the sector size. + // + // Others are possible, but we don't check them since we trust the + // file system and they aren't deadly. + + if ((IO_READ_OFF(io_stack) + IO_READ_LEN(io_stack)) > + VFD_SECTOR_TO_BYTE(device_extension->Sectors)) { + + VFDTRACE(VFDWARN, + ("[VFD] Offset:%I64u + Length:%u goes past the media size %lu\n", + IO_READ_OFF(io_stack), IO_READ_LEN(io_stack), + VFD_SECTOR_TO_BYTE(device_extension->Sectors))); + + status = STATUS_INVALID_PARAMETER; + goto complete_request; + } + + if (!VFD_SECTOR_ALIGNED((IO_READ_LEN(io_stack))) || + !VFD_SECTOR_ALIGNED((IO_READ_OFF(io_stack)))) { + + VFDTRACE(VFDWARN, + ("[VFD] Invalid Alignment Offset:%I64u Length:%u\n", + IO_READ_OFF(io_stack), IO_READ_LEN(io_stack))); + + status = STATUS_INVALID_PARAMETER; + goto complete_request; + } + + // If read/write data length is 0, we are done + + if (IO_READ_LEN(io_stack) == 0) { + status = STATUS_SUCCESS; + goto complete_request; + } + + // It seems that actual read/write operation is going to take place + // so mark the IRP as pending, insert the IRP into queue list + // then signal the device thread to perform the operation + + IoMarkIrpPending(Irp); + + ExInterlockedInsertTailList( + &device_extension->ListHead, + &Irp->Tail.Overlay.ListEntry, + &device_extension->ListLock); + + KeSetEvent( + &device_extension->RequestEvent, + (KPRIORITY) 0, + FALSE); + + VFDTRACE(VFDINFO,("[VFD] %-40s - STATUS_PENDING\n", + GetMajorFuncName(io_stack->MajorFunction))); + + return STATUS_PENDING; + +complete_request: + + // complete the request immediately + + Irp->IoStatus.Status = status; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + VFDTRACE(VFDWARN,("[VFD] %-40s - %s\n", + GetMajorFuncName(io_stack->MajorFunction), + GetStatusName(status))); + + return status; +} + +// +// Substitute for MmGetSystemAddressForMdlSafe +// for NT 4.0 DDK does not provide its equivqlent +// originally written by Bruce Engle for filedisk +// +static PVOID +MmGetSystemAddressForMdlPrettySafe( + IN PMDL Mdl, + IN MM_PAGE_PRIORITY Priority) +{ +#if (VER_PRODUCTBUILD >= 2195) + if (OsMajorVersion >= 5) { + return MmGetSystemAddressForMdlSafe(Mdl, Priority); + } + else { +#endif // (VER_PRODUCTBUILD >= 2195) + CSHORT MdlMappingCanFail; + PVOID MappedSystemVa; + + MdlMappingCanFail = (CSHORT)(Mdl->MdlFlags & MDL_MAPPING_CAN_FAIL); + + Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL; + + MappedSystemVa = MmGetSystemAddressForMdl(Mdl); + + if (!MdlMappingCanFail) { + Mdl->MdlFlags &= ~MDL_MAPPING_CAN_FAIL; + } + + return MappedSystemVa; +#if (VER_PRODUCTBUILD >= 2195) + } +#endif // (VER_PRODUCTBUILD >= 2195) +} + +// +// Read sectors from image file or RAM disk buffer into read buffer +// +VOID +VfdReadData( + IN PDEVICE_EXTENSION DeviceExtension, + IN OUT PIRP Irp, + IN ULONG Length, + IN PLARGE_INTEGER Offset) +{ + PVOID buf; + + VFDTRACE(VFDINFO,("[VFD] VfdReadData - IN\n")); + + buf = MmGetSystemAddressForMdlPrettySafe( + Irp->MdlAddress, NormalPagePriority); + + if (!buf) { + VFDTRACE(0, + ("[VFD] MmGetSystemAddressForMdlPrettySafe\n")); + + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + return; + } + + if (DeviceExtension->FileHandle) { + + // Read from image file + Irp->IoStatus.Status = ZwReadFile( + DeviceExtension->FileHandle, + NULL, + NULL, + NULL, + &Irp->IoStatus, + buf, + Length, + Offset, + NULL); + + if (NT_SUCCESS(Irp->IoStatus.Status)) { + Irp->IoStatus.Information = Length; + } + else { + VFDTRACE(0, + ("[VFD] ZwReadFile - %s\n", + GetStatusName(Irp->IoStatus.Status))); + } + } + else if (DeviceExtension->FileBuffer) { + + // Copy from RAM disk buffer + RtlMoveMemory( + buf, + DeviceExtension->FileBuffer + Offset->QuadPart, + Length); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = Length; + } + else { + // no image opened + Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE; + } + + VFDTRACE(VFDINFO,("[VFD] VfdReadData - %s\n", + GetStatusName(Irp->IoStatus.Status))); + + return; +} + +// +// Write sectors from write buffer into image file or RAM image buffer +// +VOID +VfdWriteData( + IN PDEVICE_EXTENSION DeviceExtension, + IN OUT PIRP Irp, + IN ULONG Length, + IN PLARGE_INTEGER Offset) +{ + PVOID buf; + + VFDTRACE(VFDINFO,("[VFD] VfdWriteData - IN\n")); + + buf = MmGetSystemAddressForMdlPrettySafe( + Irp->MdlAddress, NormalPagePriority); + + if (!buf) { + VFDTRACE(0, + ("[VFD] MmGetSystemAddressForMdlPrettySafe\n")); + + Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; + return; + } + + if (DeviceExtension->FileHandle) { + + // Write into image file + Irp->IoStatus.Status = ZwWriteFile( + DeviceExtension->FileHandle, + NULL, + NULL, + NULL, + &Irp->IoStatus, + buf, + Length, + Offset, + NULL); + + if (NT_SUCCESS(Irp->IoStatus.Status)) { + Irp->IoStatus.Information = Length; + } + else { + VFDTRACE(0, + ("[VFD] ZwWriteFile - %s\n", + GetStatusName(Irp->IoStatus.Status))); + } + } + else if (DeviceExtension->FileBuffer) { + + // Deal with the modify flag + if (RtlCompareMemory( + DeviceExtension->FileBuffer + Offset->QuadPart, + buf, Length) != Length) { + DeviceExtension->MediaFlags |= VFD_FLAG_DATA_MODIFIED; + } + + // Copy into RAM image buffer + RtlMoveMemory( + DeviceExtension->FileBuffer + Offset->QuadPart, + buf, Length); + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = Length; + } + else { + // no image opened + Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE; + } + + VFDTRACE(VFDINFO,("[VFD] VfdWriteData - %s\n", + GetStatusName(Irp->IoStatus.Status))); + + return; +} diff --git a/modules/rosapps/include/CMakeLists.txt b/modules/rosapps/include/CMakeLists.txt new file mode 100644 index 00000000000..2c82e7c2ed5 --- /dev/null +++ b/modules/rosapps/include/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(vfd) diff --git a/modules/rosapps/include/vfd/CMakeLists.txt b/modules/rosapps/include/vfd/CMakeLists.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/modules/rosapps/include/vfd/vfdapi.h b/modules/rosapps/include/vfd/vfdapi.h new file mode 100644 index 00000000000..15af5a9c403 --- /dev/null +++ b/modules/rosapps/include/vfd/vfdapi.h @@ -0,0 +1,324 @@ +/* + vfdapi.h + + Virtual Floppy Drive for Windows + Driver control library API header + + Copyright (C) 2003-2008 Ken Kato +*/ + +#ifndef _VFDAPI_H_ +#define _VFDAPI_H_ + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// +// custom SERVICE STATE value returned by VfdGetDriverState +// +#define VFD_NOT_INSTALLED 0xffffffff + +// +// VFD operation code for VFD notification message +// +typedef enum _VFD_OPERATION { + VFD_OPERATION_NONE, // No operation + VFD_OPERATION_INSTALL, // The driver was installed + VFD_OPERATION_CONFIG, // The driver config was changed + VFD_OPERATION_REMOVE, // The driver was removed + VFD_OPERATION_START, // The driver was started + VFD_OPERATION_STOP, // The driver was stopped + VFD_OPERATION_OPEN, // An image was opened + VFD_OPERATION_SAVE, // An image was saved + VFD_OPERATION_CLOSE, // An image was closed + VFD_OPERATION_SETLINK, // A drive letter was created + VFD_OPERATION_DELLINK, // A drive letter was removed + VFD_OPERATION_PROTECT, // Write protect state was changed + VFD_OPERATION_SHELL, // Shell extension was installed/removed + VFD_OPERATION_MAX // Maximum value place holder +} VFD_OPERATION, *PVFD_OPERATION; + +//============================== +// Driver management functions +//============================== + +// Install the driver + +DWORD WINAPI VfdInstallDriver( + PCSTR sFileName, + DWORD nStart); + +// Uninstall the driver + +DWORD WINAPI VfdRemoveDriver(); + +// Configure the driver + +DWORD WINAPI VfdConfigDriver( + DWORD nStart); + +// Start the driver + +DWORD WINAPI VfdStartDriver( + PDWORD pState); + +// Stop the driver + +DWORD WINAPI VfdStopDriver( + PDWORD pState); + +// Get current driver config information + +DWORD WINAPI VfdGetDriverConfig( + PSTR sFileName, + PDWORD pStart); + +// Get current driver state + +DWORD WINAPI VfdGetDriverState( + PDWORD pState); + +//============================== +// Device control functions +//============================== + +// Open a VFD device + +HANDLE WINAPI VfdOpenDevice( + ULONG nTarget); + +// Get the device number + +DWORD WINAPI VfdGetDeviceNumber( + HANDLE hDevice, + PULONG pNumber); + +// Get the device name + +DWORD WINAPI VfdGetDeviceName( + HANDLE hDevice, + PCHAR pName, + ULONG nLength); + +// Get the driver version + +DWORD WINAPI VfdGetDriverVersion( + HANDLE hDevice, + PULONG pVersion); + +//============================== +// image functions +//============================== + +// Open a virtual floppy image + +DWORD WINAPI VfdOpenImage( + HANDLE hDevice, + PCSTR sFileName, + VFD_DISKTYPE nDiskType, + VFD_MEDIA nMediaType, + VFD_FLAGS nMediaFlags); + +// Close the current virtual floppy image + +DWORD WINAPI VfdCloseImage( + HANDLE hDevice, + BOOL bForce); + +// Get the current image information + +DWORD WINAPI VfdGetImageInfo( + HANDLE hDevice, + PSTR sFileName, + PVFD_DISKTYPE pDiskType, + PVFD_MEDIA pMediaType, + PVFD_FLAGS pMediaFlags, + PVFD_FILETYPE pFileType, + PULONG pImageSize); + +// Save the current image into a file + +DWORD WINAPI VfdSaveImage( + HANDLE hDevice, + PCSTR sFileName, + BOOL bOverWrite, + BOOL bTruncate); + +// Format the current virtual media + +DWORD WINAPI VfdFormatMedia( + HANDLE hDevice); + +// Get the current media state (opened / write protected) + +DWORD WINAPI VfdGetMediaState( + HANDLE hDevice); + +// Set write protect state + +DWORD WINAPI VfdWriteProtect( + HANDLE hDevice, + BOOL bProtect); + +// Dismount the volume (should be called before Save, Format) + +DWORD WINAPI VfdDismountVolume( + HANDLE hDevice, + BOOL bForce); + +//============================== +// Drive letter functions +//============================== + +// Assign or remove a persistent drive letter + +DWORD WINAPI VfdSetGlobalLink( + HANDLE hDevice, + CHAR cLetter); + +// Get the current persistent drive letter + +DWORD WINAPI VfdGetGlobalLink( + HANDLE hDevice, + PCHAR pLetter); + +// Assign or remove an ephemeral drive letter + +DWORD WINAPI VfdSetLocalLink( + HANDLE hDevice, + CHAR cLetter); + +// Get the first ephemeral drive letter + +DWORD WINAPI VfdGetLocalLink( + HANDLE hDevice, + PCHAR pLetter); + +// Choose the first available drive letter + +CHAR WINAPI VfdChooseLetter(); + +//============================== +// utility functions +//============================== + +// Check running platform + +BOOL WINAPI VfdIsValidPlatform(); + +// Get VFD notification message value + +UINT WINAPI VfdGetNotifyMessage(); + +// Check if specified file is a valid VFD driver + +DWORD WINAPI VfdCheckDriverFile( + PCSTR sFileName, + PULONG pFileVersion); + +// Check if specified path is a valid image file + +DWORD WINAPI VfdCheckImageFile( + PCSTR sFileName, + PDWORD pAttributes, + PVFD_FILETYPE pFileType, + PULONG pImageSize); + +// Create a formatted new image file + +DWORD WINAPI VfdCreateImageFile( + PCSTR sFileName, + VFD_MEDIA nMediaType, + VFD_FILETYPE nFileType, + BOOL bOverWrite); + +// Lookup the largest media to fit in a size + +VFD_MEDIA WINAPI VfdLookupMedia( + ULONG nSize); + +// Get media size (in bytes) of a media type + +ULONG WINAPI VfdGetMediaSize( + VFD_MEDIA nMediaType); + +// Get media type name + +PCSTR WINAPI VfdMediaTypeName( + VFD_MEDIA nMediaType); + +// Make a file description text + +void WINAPI VfdMakeFileDesc( + PSTR pBuffer, + ULONG nBufSize, + VFD_FILETYPE nFileType, + ULONG nFileSize, + DWORD nFileAttr); + +//============================== +// Shell Extension functions +//============================== + +// install the shell extension + +DWORD WINAPI VfdRegisterHandlers(); + +// uninstall the shell extension + +DWORD WINAPI VfdUnregisterHandlers(); + +// check if the shell extension is installed + +DWORD WINAPI VfdCheckHandlers(); + +//============================== +// GUI utility functions +//============================== + +// open an existing image file + +DWORD WINAPI VfdGuiOpen( + HWND hParent, // parent window + ULONG nDevice); // device number + +// Save the current image + +DWORD WINAPI VfdGuiSave( + HWND hParent, // parent window + ULONG nDevice); // device number + +// close the current image + +DWORD WINAPI VfdGuiClose( + HWND hParent, // parent window + ULONG nDevice); // device number + +// format the current media + +DWORD WINAPI VfdGuiFormat( + HWND hParent, // parent window + ULONG nDevice); // device number + +// display a tooltip window + +void WINAPI VfdToolTip( + HWND hParent, // parent window + PCSTR sText, // tooltip text + int pos_x, // position x + int pos_y, // position y + BOOL stick); // stick (remain until losing the focus) or + // non-stick (remain until the mouse leaves) + +// Show image information tooltip + +void WINAPI VfdImageTip( + HWND hParent, + ULONG nDevice); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // _VFDAPI_H_ diff --git a/modules/rosapps/include/vfd/vfdio.h b/modules/rosapps/include/vfd/vfdio.h new file mode 100644 index 00000000000..b3f4a56e4a9 --- /dev/null +++ b/modules/rosapps/include/vfd/vfdio.h @@ -0,0 +1,393 @@ +/* + vfdio.h + + Virtual Floppy Drive for Windows + Kernel mode driver / user mode program interface header + + Copyright (C) 2003-2005 Ken Kato +*/ + +#ifndef _VFDIO_H_ +#define _VFDIO_H_ + +#ifndef __T +#ifdef _NTDDK_ +#define __T(x) L ## x +#else +#define __T(x) x +#endif +#endif + +#ifndef _T +#define _T(x) __T(x) +#endif + +// +// Device/driver setting registry value names +// +#define VFD_REG_DEVICE_NUMBER _T("NumberOfDisks") +#define VFD_REG_TRACE_FLAGS _T("TraceFlags") +#define VFD_REG_DRIVE_LETTER _T("DriveLetter") + +// +// Device object interface base name +// +#define VFD_DEVICE_BASENAME _T("VirtualFD") + +// +// sector size constants and macros +// +#define VFD_BYTES_PER_SECTOR 512 +#define VFD_SECTOR_ALIGN_MASK (VFD_BYTES_PER_SECTOR - 1) +#define VFD_BYTE_SHIFT_COUNT 9 + +#define VFD_BYTE_TO_SECTOR(b) ((b) >> VFD_BYTE_SHIFT_COUNT) +#define VFD_SECTOR_TO_BYTE(s) ((s) << VFD_BYTE_SHIFT_COUNT) +#define VFD_SECTOR_ALIGNED(b) (((b) & VFD_SECTOR_ALIGN_MASK) == 0) + +// +// Fill character for formatting media +// +#define VFD_FORMAT_FILL_DATA (UCHAR)0xf6 + +// +// Image information structure +// Used for IOCTL_VFD_OPEN_IMAGE and IOCTL_VFD_QUERY_IMAGE +// +#pragma pack (push,2) +#ifdef _MSC_VER +#pragma warning (push) +#pragma warning (disable: 4200) // Zero sized struct member warning +#endif + +typedef struct _VFD_IMAGE_INFO { + VFD_DISKTYPE DiskType; // VFD_DISKTYPE_xxx value in vfdtypes.h + VFD_MEDIA MediaType; // VFD_MEDIA_xxx value in vfdtypes.h + VFD_FLAGS MediaFlags; // VFD_FLAG_xxx value in vfdtypes.h + VFD_FILETYPE FileType; // VFD_FILETYE_xxx value in vfdtypes.h + ULONG ImageSize; // actual image size in bytes + USHORT NameLength; // length in bytes of the file name + CHAR FileName[0]; // variable length file name string +} VFD_IMAGE_INFO, *PVFD_IMAGE_INFO; + +#ifdef _MSC_VER +#pragma warning (pop) +#endif +#pragma pack (pop) + +// +// Device IO control codes +// + +/* + IOCTL_VFD_OPEN_IMAGE + + Open an existing floppy image file or create an empty RAM disk + + Input: + buffer containing a VFD_IMAGE_INFO structure followed by + an image file name + + InputLength: + sizeof(VFD_IMAGE_INFO) plus length of the image file name + + Output: + Not used with this operation; set to NULL. + + Output Length: + Not used with this operation; set to zero. + + Return: + STATUS_INVALID_PARAMETER input buffer size < sizeof(VFD_IMAGE_INFO) + or any other parameter errors + STATUS_DEVICE_BUSY an image is already opened + STATUS_ACCESS_DENIED file access error. returned also when the + file is compressed / encrypted +*/ +#define IOCTL_VFD_OPEN_IMAGE CTL_CODE( \ + IOCTL_DISK_BASE, \ + 0x800, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + IOCTL_VFD_CLOSE_IMAGE + + Close the current virtual floppy image + + Input: + Not used with this operation; set to NULL. + + Input Length: + Not used with this operation; set to zero. + + Output: + Not used with this operation; set to NULL. + + Output Length: + Not used with this operation; set to zero. + + Return: + STATUS_NO_MEDIA_IN_DEVICE image is not opened +*/ +#define IOCTL_VFD_CLOSE_IMAGE CTL_CODE( \ + IOCTL_DISK_BASE, \ + 0x801, \ + METHOD_NEITHER, \ + FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + IOCTL_VFD_QUERY_IMAGE + + Get the current image information + + Input: + Not used with this operation; set to NULL. + + Input Length: + Not used with this operation; set to zero. + + Output: + Buffer to receive a VFD_IMAGE_INFO data structure + + Output Length: + must be long enough to hold a VFD_IMAGE_INFO with the image file name + + Return: + STATUS_BUFFER_TOO_SMALL buffer length < sizeof(VFD_IMAGE_INFO) + STATUS_BUFFER_OVERFLOW buffer cannot hold the image file name. + NameLength member contains the file name + length (number of bytes). See this value + to decide necessary buffer length. +*/ +#define IOCTL_VFD_QUERY_IMAGE CTL_CODE( \ + IOCTL_DISK_BASE, \ + 0x802, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +/* + IOCTL_VFD_SET_LINK + + Create or delete a persistent drive letter + On Windows NT, this command simply creates a symbolic link. + On Windows 2000/XP, the driver calls the Mount Manager to manipulate + a drive letter. + + Input: + buffer containing a drive letter 'A' - 'Z' to create a drive letter, + or 0 to delete the current drive letter. + + Input Length: + sizeof(CHAR) or larger + + Output: + Not used with this operation; set to NULL. + + Output Length: + Not used with this operation; set to zero. + + Return: + STATUS_INVALID_PARAMETER input length == 0 or + any other parameter errors +*/ +#define IOCTL_VFD_SET_LINK CTL_CODE( \ + IOCTL_DISK_BASE, \ + 0x803, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + IOCTL_VFD_QUERY_LINK + + Get the current persistent drive letter + + Input: + Not used with this operation; set to NULL. + + Input Length: + Not used with this operation; set to zero. + + Output: + buffer to receive the current drive letter. + 0 is returned if there is none. + + Output Length: + sizeof(CHAR) or larger + + Return: + STATUS_BUFFER_TOO_SMALL buffer length < sizeof(CHAR) +*/ +#define IOCTL_VFD_QUERY_LINK CTL_CODE( \ + IOCTL_DISK_BASE, \ + 0x804, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +/* + IOCTL_VFD_SET_PROTECT + + Enable the virtual media write protection + + Input: + Not used with this operation; set to NULL. + + Input Length: + Not used with this operation; set to zero. + + Output: + Not used with this operation; set to NULL. + + Output Length: + Not used with this operation; set to zero. + + Return: + STATUS_NO_MEDIA_IN_DEVICE image is not opened +*/ +#define IOCTL_VFD_SET_PROTECT CTL_CODE( \ + IOCTL_DISK_BASE, \ + 0x805, \ + METHOD_NEITHER, \ + FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + IOCTL_VFD_CLEAR_PROTECT + + Disable the virtual media write protection + + Input: + Not used with this operation; set to NULL. + + Input Length: + Not used with this operation; set to zero. + + Output: + Not used with this operation; set to NULL. + + Output Length: + Not used with this operation; set to zero. + + Return: + STATUS_NO_MEDIA_IN_DEVICE image is not opened +*/ +#define IOCTL_VFD_CLEAR_PROTECT CTL_CODE( \ + IOCTL_DISK_BASE, \ + 0x806, \ + METHOD_NEITHER, \ + FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + IOCTL_VFD_RESET_MODIFY + + Reset the data modify flag + + Input: + Not used with this operation; set to NULL. + + Input Length: + Not used with this operation; set to zero. + + Output: + Not used with this operation; set to NULL. + + Output Length: + Not used with this operation; set to zero. + + Return: + STATUS_NO_MEDIA_IN_DEVICE image is not opened +*/ +#define IOCTL_VFD_RESET_MODIFY CTL_CODE( \ + IOCTL_DISK_BASE, \ + 0x807, \ + METHOD_NEITHER, \ + FILE_READ_ACCESS | FILE_WRITE_ACCESS) + +/* + IOCTL_VFD_QUERY_NUMBER + + Get the current device's VFD device number ( in "\??\VirtualFD") + + Input: + Not used with this operation; set to NULL. + + Input Length: + Not used with this operation; set to zero. + + Output: + buffer to receive the VFD device number + + Output Length: + sizeof(ULONG) or larger + + Return: + STATUS_BUFFER_TOO_SMALL buffer length < sizeof(ULONG) +*/ +#define IOCTL_VFD_QUERY_NUMBER CTL_CODE( \ + IOCTL_DISK_BASE, \ + 0x80d, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +/* + IOCTL_VFD_QUERY_NAME + + Get the current device's name (\Device\Floppy) + The name is returned in a counted UNICODE string (not NULL terminated) + + Input: + Not used with this operation; set to NULL. + + Input Length: + Not used with this operation; set to zero. + + Output: + buffer to receive the length (USHORT value, number of bytes) followed + by the UNICODE device name. + + Output Length: + enough to receive the length and the name + + Return: + STATUS_BUFFER_TOO_SMALL buffer length < sizeof(USHORT) + STATUS_BUFFER_OVERFLOW buffer cannot hold the device name. + The first sizeof(USHORT) bytes of the + buffer contains the device name length. + See this value to decide the necessary + buffer length. +*/ +#define IOCTL_VFD_QUERY_NAME CTL_CODE( \ + IOCTL_DISK_BASE, \ + 0x80e, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +/* + IOCTL_VFD_QUERY_VERSION + + Get the running VFD driver version + + Input: + Not used with this operation; set to NULL. + + Input Length: + Not used with this operation; set to zero. + + Output: + buffer to receive the VFD version (ULONG value) + High word: major version + Low word: minor version + MSB: debug version flag (1:debug 0:release) + + Output Length: + sizeof(ULONG) or larger + + Return: + STATUS_BUFFER_TOO_SMALL buffer length < sizeof(ULONG) +*/ +#define IOCTL_VFD_QUERY_VERSION CTL_CODE( \ + IOCTL_DISK_BASE, \ + 0x80f, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +#endif // _VFDIO_H_ diff --git a/modules/rosapps/include/vfd/vfdtypes.h b/modules/rosapps/include/vfd/vfdtypes.h new file mode 100644 index 00000000000..1019f38d8c5 --- /dev/null +++ b/modules/rosapps/include/vfd/vfdtypes.h @@ -0,0 +1,77 @@ +/* + vfdtypes.h + + Virtual Floppy Drive for Windows + kernel mode / user mode common data types / constants + + Copyright (C) 2003-2005 Ken Kato +*/ + +#ifndef _VFDTYPES_H_ +#define _VFDTYPES_H_ + +// +// Supported disk type enumeration +// +enum _VFD_DISKTYPE +{ + VFD_DISKTYPE_FILE = 0, // file disk (direct file access) + VFD_DISKTYPE_RAM // ram disk (on memory image) +}; + +// +// Supported media type enumeration +// +enum _VFD_MEDIA +{ + VFD_MEDIA_NONE = 0, // no media / unknown + VFD_MEDIA_F5_160, // 5.25" 160KB + VFD_MEDIA_F5_180, // 5.25" 180KB + VFD_MEDIA_F5_320, // 5.25" 320KB + VFD_MEDIA_F5_360, // 5.25" 360KB + VFD_MEDIA_F3_640, // 3.5" 640KB + VFD_MEDIA_F5_640, // 5.25" 640KB + VFD_MEDIA_F3_720, // 3.5" 720KB + VFD_MEDIA_F5_720, // 5.25" 720KB + VFD_MEDIA_F3_820, // 3.5" 820KB + VFD_MEDIA_F3_1P2, // 3.5" 1.2MB + VFD_MEDIA_F5_1P2, // 5.25" 1.2MB + VFD_MEDIA_F3_1P4, // 3.5" 1.44MB + VFD_MEDIA_F3_1P6, // 3.5" 1.68MB DMF + VFD_MEDIA_F3_1P7, // 3.5" 1.72MB DMF + VFD_MEDIA_F3_2P8, // 3.5" 2.88MB + VFD_MEDIA_MAX // max value placeholder +}; + +// +// Supported file type enumeration +// +enum _VFD_FILETYPE +{ + VFD_FILETYPE_NONE = 0, // no file + VFD_FILETYPE_RAW, // RAW image file + VFD_FILETYPE_ZIP, // ZIP compressed image + VFD_FILETYPE_MAX // max value place holder +}; + +// +// Type definition +// +typedef UCHAR VFD_DISKTYPE, *PVFD_DISKTYPE; +typedef UCHAR VFD_MEDIA, *PVFD_MEDIA; +typedef UCHAR VFD_FILETYPE, *PVFD_FILETYPE; +typedef UCHAR VFD_FLAGS, *PVFD_FLAGS; + +// +// Image flag values +// +#define VFD_FLAG_WRITE_PROTECTED (VFD_FLAGS)0x01 +#define VFD_FLAG_DATA_MODIFIED (VFD_FLAGS)0x02 + +// +// Default and max number of virtual floppy devices +// +#define VFD_DEFAULT_DEVICES 2 +#define VFD_MAXIMUM_DEVICES 2 + +#endif // _VFDTYPES_H_ diff --git a/modules/rosapps/include/vfd/vfdver.h b/modules/rosapps/include/vfd/vfdver.h new file mode 100644 index 00000000000..8868e5a82df --- /dev/null +++ b/modules/rosapps/include/vfd/vfdver.h @@ -0,0 +1,72 @@ +/* + vfdver.h + + Virtual Floppy Drive for Windows + common version definition + + Copyright (c) 2003-2008 Ken Kato +*/ + +#ifndef _VFDVER_H_ +#define _VFDVER_H_ + +// product version information +#define VFD_PRODUCT_NAME "Virtual Floppy Drive for Windows" +#define VFD_PRODUCT_MAJOR 2 +#define VFD_PRODUCT_MINOR 1 + +// driver file version information +#define VFD_DRIVER_FILENAME "vfd.sys" +#define VFD_DRIVER_MAJOR 2 +#define VFD_DRIVER_MINOR 1 + +// build year and month/date +#define VFD_BUILD_YEAR 2008 +#define VFD_BUILD_MDAY 0206 + +// copyright information +#define VFD_COMPANY_NAME "Ken Kato" +#define VFD_COPYRIGHT_YEARS "2003-2008" + +// version information language and code page +// LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP +#define VFD_VERSIONINFO_LANG "040904B0" +#define VFD_VERSIONINFO_TRANS 0x0409, 0x04B0 + +#if ((DBG) || defined(_DEBUG)) +#define VFD_DEBUG_FLAG 0x80000000 +#define VFD_DEBUG_TAG " (debug)" +#else +#define VFD_DEBUG_FLAG 0 +#define VFD_DEBUG_TAG +#endif + +// +// Version manipulation macros +// +#define VFD_PRODUCT_VERSION_VAL \ + ((ULONG)((USHORT)VFD_PRODUCT_MAJOR<<16)|((USHORT)VFD_PRODUCT_MINOR)) + +#define VFD_DRIVER_VERSION_VAL \ + ((ULONG)((USHORT)VFD_DRIVER_MAJOR<<16)|((USHORT)VFD_DRIVER_MINOR)) + +#define VFD_FILE_VERSION_VAL \ + ((ULONG)((USHORT)VFD_FILE_MAJOR<<16)|((USHORT)VFD_FILE_MINOR)) + +#define VFD_VERSION_STR2(a,b) #a "." #b +#define VFD_VERSION_STR(a,b) VFD_VERSION_STR2(a,b) +#define VFD_PRODUCT_VERSION_STR VFD_VERSION_STR(VFD_PRODUCT_MAJOR,VFD_PRODUCT_MINOR) +#define VFD_DRIVER_VERSION_STR VFD_VERSION_STR(VFD_DRIVER_MAJOR,VFD_DRIVER_MINOR) +#define VFD_FILE_VERSION_STR VFD_VERSION_STR(VFD_FILE_MAJOR,VFD_FILE_MINOR) +#define VFD_BUILD_DATE_STR VFD_VERSION_STR(VFD_BUILD_YEAR,VFD_BUILD_MDAY) + +// +// Product description +// +#define VFD_PRODUCT_DESC \ + VFD_PRODUCT_NAME " " VFD_PRODUCT_VERSION_STR "." VFD_BUILD_DATE_STR VFD_DEBUG_TAG + +#define VFD_COPYRIGHT_STR \ + "Copyright (c) " VFD_COPYRIGHT_YEARS " " VFD_COMPANY_NAME + +#endif // _VFDVER_H_ diff --git a/modules/rosapps/include/vfd/vfdver.rc b/modules/rosapps/include/vfd/vfdver.rc new file mode 100644 index 00000000000..4d5a5ca0a9c --- /dev/null +++ b/modules/rosapps/include/vfd/vfdver.rc @@ -0,0 +1,79 @@ +/* + vfdver.rc + + Virtual Floppy Drive for Windows + common version resource script + + Copyright (C) 2003-2005 Ken Kato +*/ + +// !!! NOTE !!! +// Editing this file with Microsoft Visual Studio will almost +// certainly mess things up... + +#ifndef APSTUDIO_INVOKED + +// Language neutral +LANGUAGE 0, 0 + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VFD_FILE_MAJOR,VFD_FILE_MINOR,VFD_BUILD_YEAR,VFD_BUILD_MDAY +PRODUCTVERSION VFD_PRODUCT_MAJOR,VFD_PRODUCT_MINOR,VFD_BUILD_YEAR,VFD_BUILD_MDAY + +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + +#ifndef VFD_SPECIAL_FLAG +#define VFD_SPECIAL_FLAG 0 +#endif + +#if ((DBG) || defined(_DEBUG)) +FILEFLAGS VS_FF_DEBUG | VFD_SPECIAL_FLAG +#else +FILEFLAGS 0 | VFD_SPECIAL_FLAG +#endif + +FILEOS VFD_FILEOS +FILETYPE VFD_FILETYPE +FILESUBTYPE VFD_FILESUBTYPE +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK VFD_VERSIONINFO_LANG + BEGIN + VALUE "CompanyName", VFD_COMPANY_NAME + VALUE "FileDescription", VFD_DESCRIPTION VFD_DEBUG_TAG + VALUE "FileVersion", VFD_FILE_VERSION_STR + VALUE "InternalName", VFD_INTERNALNAME + VALUE "LegalCopyright", VFD_COPYRIGHT_STR + VALUE "OriginalFilename", VFD_INTERNALNAME + VALUE "ProductName", VFD_PRODUCT_NAME + VALUE "ProductVersion", VFD_PRODUCT_VERSION_STR +#if VFD_SPECIAL_FLAG + Value "SpecialBuild", VFD_SPECIAL_DESC +#endif + END +#ifdef VFD_VERSIONINFO_ALT + BLOCK VFD_VERSIONINFO_ALT + BEGIN + VALUE "CompanyName", VFD_COMPANY_NAME + VALUE "FileDescription", VFD_DESCRIPTION_ALT VFD_DEBUG_TAG + VALUE "FileVersion", VFD_FILE_VERSION_STR + VALUE "InternalName", VFD_INTERNALNAME + VALUE "LegalCopyright", VFD_COPYRIGHT_STR + VALUE "OriginalFilename", VFD_INTERNALNAME + VALUE "ProductName", VFD_PRODUCT_NAME_ALT + VALUE "ProductVersion", VFD_PRODUCT_VERSION_STR +#if VFD_SPECIAL_FLAG + Value "SpecialBuild", VFD_SPECIAL_DESC_ALT +#endif + END +#endif // VFD_VERSIONINFO_ALT + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", VFD_VERSIONINFO_TRANS + END +END + +#endif // APSTUDIO_INVOKED diff --git a/modules/rosapps/lib/CMakeLists.txt b/modules/rosapps/lib/CMakeLists.txt index 0df7b79d950..d3cfcf2a8fa 100644 --- a/modules/rosapps/lib/CMakeLists.txt +++ b/modules/rosapps/lib/CMakeLists.txt @@ -1 +1,2 @@ +add_subdirectory(vfdlib) add_subdirectory(win32err) diff --git a/modules/rosapps/lib/vfdlib/CMakeLists.txt b/modules/rosapps/lib/vfdlib/CMakeLists.txt new file mode 100644 index 00000000000..2ceeb8f41fa --- /dev/null +++ b/modules/rosapps/lib/vfdlib/CMakeLists.txt @@ -0,0 +1,33 @@ +set_cpp(WITH_RUNTIME WITH_EXCEPTIONS WITH_STL) + +spec2def(vfd.dll vfdlib.spec ADD_IMPORTLIB) + +add_message_headers(ANSI vfdmsg_lib.mc) + +list(APPEND SOURCE + vfdctl.c + vfdfat.c + vfdguiopen.c + vfdguisave.c + vfdguitip.c + vfdguiut.c + vfdlib.c + vfdshcfact.cpp + vfdshext.cpp + vfdshmenu.cpp + vfdshprop.cpp + vfdshutil.cpp + vfdzip.c) + +add_library(vfd SHARED + ${SOURCE} + vfdlib.rc + ${CMAKE_CURRENT_BINARY_DIR}/vfdlib.def) + +include_directories(${REACTOS_SOURCE_DIR}/modules/rosapps/include/vfd + ${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/zlib) +set_module_type(vfd win32dll ENTRYPOINT DllMain 12) +target_link_libraries(vfd zlib_solo uuid) +add_importlibs(vfd advapi32 user32 gdi32 shell32 comdlg32 comctl32 ole32 version psapi msvcrt kernel32 ntdll) +add_dependencies(vfd vfdmsg_lib) +add_cd_file(TARGET vfd DESTINATION reactos/system32 FOR all) diff --git a/modules/rosapps/lib/vfdlib/res/config.ico b/modules/rosapps/lib/vfdlib/res/config.ico new file mode 100644 index 00000000000..6a842f1d42a Binary files /dev/null and b/modules/rosapps/lib/vfdlib/res/config.ico differ diff --git a/modules/rosapps/lib/vfdlib/res/image.ico b/modules/rosapps/lib/vfdlib/res/image.ico new file mode 100644 index 00000000000..6e969b47886 Binary files /dev/null and b/modules/rosapps/lib/vfdlib/res/image.ico differ diff --git a/modules/rosapps/lib/vfdlib/res/vfd.ico b/modules/rosapps/lib/vfdlib/res/vfd.ico new file mode 100644 index 00000000000..451ccd3d1d0 Binary files /dev/null and b/modules/rosapps/lib/vfdlib/res/vfd.ico differ diff --git a/modules/rosapps/lib/vfdlib/vfdctl.c b/modules/rosapps/lib/vfdlib/vfdctl.c new file mode 100644 index 00000000000..54c3320e390 --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdctl.c @@ -0,0 +1,3272 @@ +/* + vfdctl.c + + Virtual Floppy Drive for Windows + Driver control library + Driver and image control functions + + Copyright (C) 2003-2005 Ken Kato +*/ + +#ifdef __cplusplus +#pragma message(__FILE__": Compiled as C++ for testing purpose.") +#endif // __cplusplus + +#define WIN32_LEAN_AND_MEAN +#include +#include +#ifdef _MSC_VER +#pragma warning (push, 3) +#endif +#include +#include +#ifdef _MSC_VER +#pragma warning (pop) +#endif +#include + +#include "vfdtypes.h" +#include "vfdio.h" +#include "vfdapi.h" +#include "vfdlib.h" +#include "vfdver.h" + +#ifndef IOCTL_DISK_GET_LENGTH_INFO +// Old winioctl.h header doesn't define the following + +#define IOCTL_DISK_GET_LENGTH_INFO CTL_CODE(\ +IOCTL_DISK_BASE, 0x0017, METHOD_BUFFERED, FILE_READ_ACCESS) + +typedef struct _GET_LENGTH_INFORMATION { + LARGE_INTEGER Length; +} GET_LENGTH_INFORMATION, *PGET_LENGTH_INFORMATION; + +#endif // IOCTL_DISK_GET_LENGTH_INFO + +// +// DOS device name (\\.\VirtualFD) +// +#ifndef __REACTOS__ +#define VFD_DEVICE_TEMPLATE "\\\\.\\" VFD_DEVICE_BASENAME "%u" +#else +#define VFD_DEVICE_TEMPLATE "\\\\.\\" VFD_DEVICE_BASENAME "%lu" +#endif +#define VFD_VOLUME_TEMPLATE "\\\\.\\%c:" + +#define VFD_INSTALL_DIRECTORY "\\system32\\drivers\\" + +#ifdef _DEBUG +#ifndef __REACTOS__ +extern ULONG TraceFlags = (ULONG)-1;//0; +extern CHAR *TraceFile = NULL; +extern ULONG TraceLine = 0; +#else +ULONG TraceFlags = (ULONG)-1;//0; +CHAR const * TraceFile = NULL; +ULONG TraceLine = 0; +#endif +#endif + +// +// broadcast a WM_DEVICECHANGE system message to inform +// a drive letter creation / removal +// +#define VFD_LINK_CREATED 0 +#define VFD_LINK_REMOVED 1 + +static void VfdBroadcastLink( + CHAR cLetter, + BOOL bRemoved) +{ + DWORD receipients; + DWORD device_event; + DEV_BROADCAST_VOLUME params; + + if (!isalpha(cLetter)) { + VFDTRACE(0, + ("VfdBroadcastLink: invalid parameter")) + return; + } + + receipients = BSM_APPLICATIONS; + + device_event = bRemoved ? + DBT_DEVICEREMOVECOMPLETE : DBT_DEVICEARRIVAL; + + ZeroMemory(¶ms, sizeof(params)); + + params.dbcv_size = sizeof(params); + params.dbcv_devicetype = DBT_DEVTYP_VOLUME; + params.dbcv_reserved = 0; + params.dbcv_unitmask = (1 << (toupper(cLetter) - 'A')); + params.dbcv_flags = 0; + + if (BroadcastSystemMessage( + BSF_NOHANG | BSF_FORCEIFHUNG | BSF_NOTIMEOUTIFNOTHUNG, + &receipients, + WM_DEVICECHANGE, + device_event, + (LPARAM)¶ms) <= 0) { + + VFDTRACE(0, + ("VfdBroadcastLink: BroadcastSystemMessage - %s", + SystemMessage(GetLastError()))); + } +} + +// +// Broadcast a VFD notify message +// +static __inline void VfdNotify( + WPARAM wParam, + LPARAM lParam) +{ + // SendNotifyMessage causes volume locking conflict (I think) + // on Windows XP while closing an image with VfdWin +// SendNotifyMessage(HWND_BROADCAST, uVfdMsg, wParam, lParam); + PostMessage(HWND_BROADCAST, g_nNotifyMsg, wParam, lParam); +} + +#ifdef VFD_EMBED_DRIVER +// +// Restore the VFD driver file in the system directory +// + +static DWORD VfdRestoreDriver( + PCSTR sPath) +{ +#define FUNC "VfdRestoreDriver" + HRSRC hRes; + DWORD size; + HGLOBAL hDrv; + PVOID pData; + DWORD result; + HANDLE hFile; + DWORD ret; + + // + // Prepare driver binary + // + + // use embedded driver binary + +#define S(s) #s + hRes = FindResource(g_hDllModule, + S(VFD_DRIVER_NAME_ID), S(VFD_DRIVER_TYPE_ID)); +#undef S + + if (hRes == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": FindResource - %s", + SystemMessage(ret))); + + return ret; + } + + size = SizeofResource(g_hDllModule, hRes); + + if (size == 0) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": SizeofResource - %s", + SystemMessage(ret))); + + return ret; + } + + hDrv = LoadResource(g_hDllModule, hRes); + + if (hDrv == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": LoadResource - %s", + SystemMessage(ret))); + + return ret; + } + + pData = LockResource(hDrv); + + if (pData == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": LockResource - %s", + SystemMessage(ret))); + + return ret; + } + + // create the driver file + + hFile = CreateFile(sPath, GENERIC_WRITE, + 0, NULL, OPEN_ALWAYS, 0, NULL); + + if (hFile == INVALID_HANDLE_VALUE) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": CreateFile(%s) - %s", + sPath, SystemMessage(ret))); + + return ret; + } + + if (!WriteFile(hFile, pData, size, &result, NULL) || + size != result) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": CreateFile - %s", + SystemMessage(ret))); + + CloseHandle(hFile); + return ret; + } + + SetEndOfFile(hFile); + CloseHandle(hFile); + + return ERROR_SUCCESS; +} +#endif // VFD_EMBED_DRIVER + +// +// Install the Virtual Floppy Driver +// +DWORD WINAPI VfdInstallDriver( + PCSTR sFileName, + DWORD nStart) +{ +#undef FUNC +#define FUNC "VfdInstallDriver" + SC_HANDLE hScManager; // Service Control Manager + SC_HANDLE hService = NULL; // Service (= Driver) +#ifndef VFD_EMBED_DRIVER + CHAR file_path[MAX_PATH]; + PSTR file_name; +#endif // VFD_EMBED_DRIVER + CHAR system_dir[MAX_PATH]; + PSTR inst_path; + DWORD len; + DWORD ret = ERROR_SUCCESS; + + // get SystemRoot directory path + +// len = GetEnvironmentVariable( +// "SystemRoot", system_dir, sizeof(system_dir)); + len = GetWindowsDirectory(system_dir, sizeof(system_dir)); + + if (len == 0 || len > sizeof(system_dir)) { + VFDTRACE(0, + (FUNC ": %%SystemRoot%% is empty or too long.\n")); + + return ERROR_BAD_ENVIRONMENT; + } + + inst_path = &system_dir[len]; + +#ifdef VFD_EMBED_DRIVER + // + // use embedded driver file + // + strcpy(inst_path++, VFD_INSTALL_DIRECTORY VFD_DRIVER_FILENAME); + + ret = VfdRestoreDriver(system_dir); + + if (ret != ERROR_SUCCESS) { + return ret; + } + +#else // VFD_EMBED_DRIVER + // Prepare driver binary's full path + + if (sFileName == NULL || *sFileName == '\0') { + + // default driver file is vfd.sys in the same directory as executable + + len = GetModuleFileName( + NULL, file_path, sizeof(file_path)); + + if (len == 0) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": GetModuleFileName - %s", + SystemMessage(ret))); + + return ret; + } + + // search the last '\' character + + while (len > 0 && file_path[len - 1] != '\\') { + len --; + } + + // supply the file name (vfd.sys) + + file_name = &file_path[len]; + strcpy(file_name, VFD_DRIVER_FILENAME); + } + else { + + // ensure that tha path is an absolute full path + + len = GetFullPathName( + sFileName, + sizeof(file_path), + file_path, + &file_name); + + if (len == 0) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": GetFullPathName(%s) - %s\n", + sFileName, SystemMessage(ret))); + + return ret; + } + + if (GetFileAttributes(file_path) & FILE_ATTRIBUTE_DIRECTORY) { + // if the specified path is a directory, + // supply the file name (vfd.sys) + + file_name = &file_path[len]; + strcpy(file_name++, "\\" VFD_DRIVER_FILENAME); + } + } + + // Check if the file is a valid Virtual Floppy driver + + ret = VfdCheckDriverFile(file_path, NULL); + + if (ret != ERROR_SUCCESS) { + VFDTRACE(0, + (FUNC ": VfdCheckDriverFile(%s)\n", file_path)); + + return ret; + } + + // if the path is under the system directory, make it relative + // to the system directory + + len = strlen(system_dir); + + if (!_strnicmp(file_path, system_dir, len)) { + inst_path = &file_path[len]; + + while (*inst_path == '\\') { + inst_path++; + } + } + else { + inst_path = &file_path[0]; + } +#endif // VFD_EMBED_DRIVER + + // 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(); + + VFDTRACE(0, + (FUNC ": OpenSCManager() - %s", + SystemMessage(ret))); + + goto cleanup; + } + + // 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 + nStart, // service start type + SERVICE_ERROR_NORMAL, // start error sevirity + inst_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(); + + VFDTRACE(0, + (FUNC ": CreateService() - %s", + SystemMessage(ret))); + + goto cleanup; + } + +cleanup: + // Close the service object handle + + if (hService) { + CloseServiceHandle(hService); + } + + // Close handle to the service control manager. + + if (hScManager) { + CloseServiceHandle(hScManager); + } + + if (ret == ERROR_SUCCESS) { + // Broadcast the successful operation + VfdNotify(VFD_OPERATION_INSTALL, 0); + } +#ifdef VFD_EMBED_DRIVER + else { + // Delete the restored driver file + DeleteFile(system_dir); + } +#endif // VFD_EMBED_DRIVER + + return ret; +} + +// +// Configure the Virtual Floppy Driver (change the start method) +// + +DWORD WINAPI VfdConfigDriver( + DWORD nStart) +{ +#undef FUNC +#define FUNC "VfdConfigDriver" + 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(); + + VFDTRACE(0, + (FUNC ": OpenSCManager() - %s", + SystemMessage(ret))); + + return ret; + } + + // Open the VFD driver entry in the service database + + hService = OpenService( + hScManager, // Service control manager + VFD_DEVICE_BASENAME, // service name + SERVICE_CHANGE_CONFIG); // service access mode + + if (hService == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": OpenService(SERVICE_CHANGE_CONFIG) - %s", + SystemMessage(ret))); + + goto cleanup; + } + + // Change the start method of the VFD driver + + if (!ChangeServiceConfig( + hService, + SERVICE_NO_CHANGE, + nStart, + SERVICE_NO_CHANGE, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL)) { + + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": ChangeServiceConfig() - %s", + SystemMessage(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_CONFIG, 0); + } + + return ret; +} + +// +// Remove the Virtual Floppy Driver entry from the service database +// +DWORD WINAPI VfdRemoveDriver() +{ +#undef FUNC +#define FUNC "VfdRemoveDriver" + SC_HANDLE hScManager; // Service Control Manager + SC_HANDLE hService; // Service (= Driver) + CHAR file_path[MAX_PATH]; + DWORD ret = ERROR_SUCCESS; + + // Get the current driver path + + ret = VfdGetDriverConfig(file_path, NULL); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + // Connect to the Service Control Manager + + hScManager = OpenSCManager(NULL, NULL, 0); + + if (hScManager == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": OpenSCManager() - %s", + SystemMessage(ret))); + + return ret; + } + + // Open the VFD driver entry in the service database + + hService = OpenService( + hScManager, // Service control manager + VFD_DEVICE_BASENAME, // service name + DELETE); // service access mode + + if (hService == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": OpenService(DELETE) - %s", + SystemMessage(ret))); + + goto cleanup; + } + + // Remove driver entry from registry + + if (!DeleteService(hService)) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": DeleteService() - %s", + SystemMessage(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); + +#ifdef VFD_EMBED_DRIVER + // Remove the driver file + DeleteFile(file_path); +#endif // VFD_EMBED_DRIVER + } + + return ret; +} + +// +// Start the Virtual Floppy Driver +// +DWORD WINAPI VfdStartDriver( + PDWORD pState) +{ +#undef FUNC +#define FUNC "VfdStartDriver" + SC_HANDLE hScManager; // Service Control Manager + SC_HANDLE hService; // Service (= Driver) + SERVICE_STATUS stat; + DWORD ret = ERROR_SUCCESS; + HCURSOR original; + int i; + + if (pState) { + *pState = 0; + } + + // Connect to the Service Control Manager + + hScManager = OpenSCManager(NULL, NULL, 0); + + if (hScManager == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": OpenSCManager() - %s", + SystemMessage(ret))); + + return ret; + } + + // show an hourglass cursor + + original = SetCursor(LoadCursor(NULL, IDC_WAIT)); + + // Open the VFD driver entry in the service database + + hService = OpenService( + hScManager, // Service control manager + VFD_DEVICE_BASENAME, // service name + SERVICE_START + | SERVICE_QUERY_STATUS); // service access mode + + if (hService == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": OpenService(SERVICE_START) - %s", + SystemMessage(ret))); + + goto cleanup; + } + + // Start the driver + + if (!StartService(hService, 0, NULL)) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": StartService() - %s", + SystemMessage(ret))); + + goto cleanup; + } + + // Wait until the driver is properly running + + i = 0; + + for (;;) { + if (!QueryServiceStatus(hService, &stat)) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": QueryServiceStatus() - %s", + SystemMessage(ret))); + + break; + } + + if (stat.dwCurrentState == SERVICE_RUNNING || ++i == 5) { + break; + } + + Sleep(1000); + } + + if (stat.dwCurrentState == SERVICE_RUNNING) { + + // Broadcast the successful operation + + if (ret == ERROR_SUCCESS) { + VfdNotify(VFD_OPERATION_START, 0); + } + + // broadcast the arrival of VFD drives + // otherwise WinXP explorer doesn't recognize the VFD drives + + for (i = 0; i < VFD_MAXIMUM_DEVICES; i++) { + HANDLE hDevice; + CHAR letter = 0; + + hDevice = VfdOpenDevice(i); + + if (hDevice != INVALID_HANDLE_VALUE) { + + VfdGetGlobalLink(hDevice, &letter); + + CloseHandle(hDevice); + + if (isalpha(letter)) { + VfdBroadcastLink(letter, VFD_LINK_CREATED); + VfdNotify(VFD_OPERATION_SETLINK, i); + } + } + else { + VFDTRACE(0, + (FUNC ": VfdOpenDevice(%d) - %s", + i, SystemMessage(GetLastError()))); + } + } + } + else { + // somehow failed to start the driver + + ret = ERROR_SERVICE_NOT_ACTIVE; + } + + if (pState) { + *pState = stat.dwCurrentState; + } + +cleanup: + // Close the service object handle + + if (hService) { + CloseServiceHandle(hService); + } + + // Close handle to the service control manager. + + if (hScManager) { + CloseServiceHandle(hScManager); + } + + // revert to the original cursor + + SetCursor(original); + + return ret; +} + +// +// Stop the Virtual Floppy Driver +// +DWORD WINAPI VfdStopDriver( + PDWORD pState) +{ +#undef FUNC +#define FUNC "VfdStopDriver" + SC_HANDLE hScManager; // Service Control Manager + SC_HANDLE hService; // Service (= Driver) + SERVICE_STATUS stat; + CHAR drive_letters[VFD_MAXIMUM_DEVICES]; + DWORD ret = ERROR_SUCCESS; + int i; + HCURSOR original; + + if (pState) { + *pState = 0; + } + + // Connect to the Service Control Manager + + hScManager = OpenSCManager(NULL, NULL, 0); + + if (hScManager == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": OpenSCManager() - %s", + SystemMessage(ret))); + + return ret; + } + + // Show the hourglass cursor + + original = SetCursor(LoadCursor(NULL, IDC_WAIT)); + + // Open the VFD driver entry in the service database + + hService = OpenService( + hScManager, // Service control manager + VFD_DEVICE_BASENAME, // service name + SERVICE_STOP + | SERVICE_QUERY_STATUS); // service access mode + + if (hService == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": OpenService(SERVICE_STOP) - %s", + SystemMessage(ret))); + + goto cleanup; + } + + // Get assigned drive letters + + for (i = 0; i < VFD_MAXIMUM_DEVICES; i++) { + HANDLE hDevice; + CHAR letter; + + hDevice = VfdOpenDevice(i); + + if (hDevice != INVALID_HANDLE_VALUE) { + + // remove all session local drive letters + + while (VfdGetLocalLink(hDevice, &letter) == ERROR_SUCCESS && + isalpha(letter)) { + VfdSetLocalLink(hDevice, 0); + } + + // store existing persistent drive letters + + VfdGetGlobalLink(hDevice, &drive_letters[i]); + + CloseHandle(hDevice); + } + else { + VFDTRACE(0, + (FUNC ": VfdOpenDevice(%d) - %s", + i, SystemMessage(GetLastError()))); + } + } + + // Stop the driver + + if (!ControlService(hService, SERVICE_CONTROL_STOP, &stat)) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": ControlService(SERVICE_CONTROL_STOP) - %s", + SystemMessage(ret))); + + goto cleanup; + } + + // Wait until the driver is stopped + + i = 0; + + while (stat.dwCurrentState != SERVICE_STOPPED && ++i < 5) { + Sleep(1000); + + if (!QueryServiceStatus(hService, &stat)) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": QueryServiceStatus() - %s", + SystemMessage(ret))); + + break; + } + } + + if (stat.dwCurrentState != SERVICE_RUNNING) { + + // broadcast the removal of persistent drive letters + + for (i = 0; i < VFD_MAXIMUM_DEVICES; i++) { + if (isalpha(drive_letters[i])) { + VfdBroadcastLink(drive_letters[i], VFD_LINK_REMOVED); + VfdNotify(VFD_OPERATION_DELLINK, i); + } + } + } + + if (pState) { + *pState = 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); + } + + // revert to the original cursor + + SetCursor(original); + + return ret; +} + +// +// Get the Virtual Floppy Driver configuration +// +DWORD WINAPI VfdGetDriverConfig( + PSTR sFileName, + PDWORD pStart) +{ +#undef FUNC +#define FUNC "VfdGetDriverConfig" + SC_HANDLE hScManager; // Service Control Manager + SC_HANDLE hService; // Service (= Driver) + LPQUERY_SERVICE_CONFIG config = NULL; + DWORD result; + DWORD ret = ERROR_SUCCESS; + + if (sFileName) { + ZeroMemory(sFileName, MAX_PATH); + } + + if (pStart) { + *pStart = 0; + } + + // Connect to the Service Control Manager + + hScManager = OpenSCManager(NULL, NULL, 0); + + if (hScManager == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": OpenSCManager() - %s", SystemMessage(ret))); + + return ret; + } + + // Open the VFD driver entry in the service database + + hService = OpenService( + hScManager, // Service control manager + VFD_DEVICE_BASENAME, // service name + SERVICE_QUERY_CONFIG); // service access mode + + if (hService == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": OpenService(SERVICE_QUERY_CONFIG) - %s", + SystemMessage(ret))); + + goto cleanup; + } + + // Get the length of config information + + if (!QueryServiceConfig(hService, NULL, 0, &result)) { + ret = GetLastError(); + + if (ret == ERROR_INSUFFICIENT_BUFFER) { + ret = ERROR_SUCCESS; + } + else { + VFDTRACE(0, + (FUNC ": QueryServiceConfig() - %s", + SystemMessage(ret))); + + goto cleanup; + } + } + + // allocate a required buffer + + config = (LPQUERY_SERVICE_CONFIG)LocalAlloc(LPTR, result); + + if (config == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": LocalAlloc(%lu) - %s\n", + result, SystemMessage(ret))); + + goto cleanup; + } + + // get the config information + + if (!QueryServiceConfig(hService, config, result, &result)) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": QueryServiceConfig() - %s", + SystemMessage(ret))); + + goto cleanup; + } + + // copy information to output buffer + + if (sFileName) { + if (strncmp(config->lpBinaryPathName, "\\??\\", 4) == 0) { + + // driver path is an absolute UNC path + strncpy( + sFileName, + config->lpBinaryPathName + 4, + MAX_PATH); + } + else if (config->lpBinaryPathName[0] == '\\' || + (isalpha(config->lpBinaryPathName[0]) && + config->lpBinaryPathName[1] == ':')) { + + // driver path is an absolute path + strncpy(sFileName, + config->lpBinaryPathName, + MAX_PATH); + } + else { + // driver path is relative to the SystemRoot +// DWORD len = GetEnvironmentVariable( +// "SystemRoot", sFileName, MAX_PATH); + + DWORD len = GetWindowsDirectory(sFileName, MAX_PATH); + + if (len == 0 || len > MAX_PATH) { + VFDTRACE(0, + (FUNC ": %%SystemRoot%% is empty or too long.\n")); + + ret = ERROR_BAD_ENVIRONMENT; + goto cleanup; + } + + sprintf((sFileName + len), "\\%s", + config->lpBinaryPathName); + } + } + + if (pStart) { + *pStart = config->dwStartType; + } + +cleanup: + // Free service config buffer + + if (config) { + LocalFree(config); + } + + // Close the service object handle + + if (hService) { + CloseServiceHandle(hService); + } + + // Close handle to the service control manager. + + if (hScManager) { + CloseServiceHandle(hScManager); + } + + return ret; +} + +// +// Get the Virtual Floppy Driver running state +// +DWORD WINAPI VfdGetDriverState( + PDWORD pState) +{ +#undef FUNC +#define FUNC "VfdGetDriverState" + SC_HANDLE hScManager = NULL; // Service Control Manager + SC_HANDLE hService = NULL; // Service (= Driver) + SERVICE_STATUS status; + DWORD ret = ERROR_SUCCESS; + + if (pState) { + *pState = 0; + } + + // Connect to the Service Control Manager + + hScManager = OpenSCManager(NULL, NULL, 0); + + if (hScManager == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": OpenSCManager() - %s", + SystemMessage(ret))); + + return ret; + } + + // Open the VFD driver entry in the service database + + hService = OpenService( + hScManager, // Service control manager + VFD_DEVICE_BASENAME, // service name + SERVICE_QUERY_STATUS); // service access mode + + if (hService == NULL) { + + ret = GetLastError(); + + if (ret == ERROR_SERVICE_DOES_NOT_EXIST) { + + if (pState) { + *pState = VFD_NOT_INSTALLED; + } + + ret = ERROR_SUCCESS; + } + else { + VFDTRACE(0, + (FUNC ": OpenService(SERVICE_QUERY_STATUS) - %s", + SystemMessage(ret))); + } + + goto cleanup; + } + + // Get current driver status + + ZeroMemory(&status, sizeof(status)); + + if (!QueryServiceStatus(hService, &status)) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": QueryServiceStatus() - %s", + SystemMessage(ret))); + + goto cleanup; + } + + if (pState) { + *pState = 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; +} + +// +// open a Virtual Floppy drive without showing the "Insert Floppy" +// dialog when the drive is empty. +// +HANDLE WINAPI VfdOpenDevice( + ULONG nTarget) // either a drive letter or a device number +{ +#undef FUNC +#define FUNC "VfdOpenDevice" + CHAR dev_name[20]; + UINT err_mode; + HANDLE hDevice; + + // format a device name string + + if (isalpha(nTarget)) { + // nTarget is a drive letter + // \\.\: +#ifndef __REACTOS__ + sprintf(dev_name, VFD_VOLUME_TEMPLATE, nTarget); +#else + sprintf(dev_name, VFD_VOLUME_TEMPLATE, (CHAR)nTarget); +#endif + } + else if (isdigit(nTarget)) { + // nTarget is a device number in character + // \\.\VirtualFD + sprintf(dev_name, VFD_DEVICE_TEMPLATE, nTarget - '0'); + } + else { + // nTarget is a device number value + // \\.\VirtualFD + sprintf(dev_name, VFD_DEVICE_TEMPLATE, nTarget); + } + + // change error mode in order to avoid "Insert Floppy" dialog + + err_mode = SetErrorMode(SEM_FAILCRITICALERRORS); + + // open the target drive + + hDevice = CreateFile( + dev_name, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_NO_BUFFERING, + NULL); + + // revert to the original error mode + + SetErrorMode(err_mode); + + if (hDevice != INVALID_HANDLE_VALUE) { + + // check if the target is a valid VFD drive + + ULONG version; + + if (VfdGetDriverVersion(hDevice, &version) != ERROR_SUCCESS) { + + // Failed to get the driver version + + CloseHandle(hDevice); + hDevice = INVALID_HANDLE_VALUE; + } + else if ((version & ~0x80000000) != + MAKELONG(VFD_DRIVER_MINOR, VFD_DRIVER_MAJOR)) { + + // the driver version mismatch + +// CloseHandle(hDevice); +// hDevice = INVALID_HANDLE_VALUE; + + SetLastError(ERROR_REVISION_MISMATCH); + } + } + else { + VFDTRACE(0,( + "CreateFile(%s) - %s", dev_name, + SystemMessage(GetLastError())));; + } + + return hDevice; +} + +// +// Open a Virtual Floppy Image +// +DWORD WINAPI VfdOpenImage( + HANDLE hDevice, + PCSTR sFileName, + VFD_DISKTYPE nDiskType, + VFD_MEDIA nMediaType, + VFD_FLAGS nMediaFlags) +{ +#undef FUNC +#define FUNC "VfdOpenImage" + PCSTR prefix; + CHAR abspath[MAX_PATH]; + DWORD name_len; + DWORD result; + DWORD ret = ERROR_SUCCESS; + + PVFD_IMAGE_INFO image_info = NULL; + PUCHAR image_buf = NULL; + ULONG image_size; + VFD_FILETYPE file_type; + + // + // Check parameters + // + + if (hDevice == NULL || + hDevice == INVALID_HANDLE_VALUE) { + return ERROR_INVALID_HANDLE; + } + + if (nMediaType == VFD_MEDIA_NONE || + nMediaType >= VFD_MEDIA_MAX) { + + VFDTRACE(0, + (FUNC ": Invalid MediaType - %u\n", nMediaType)); + + return ERROR_INVALID_PARAMETER; + } + + + if (sFileName && *sFileName) { + + // check file contents and attributes + + HANDLE hFile = CreateFile(sFileName, GENERIC_READ, + FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + + if (hFile == INVALID_HANDLE_VALUE) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": CreateFile(%s) - %s", + sFileName, SystemMessage(ret))); + + return ret; + } + + // try extracting image data from zip compressed file + + ExtractZipImage(hFile, &image_buf, &image_size); + + if (image_buf) { + + file_type = VFD_FILETYPE_ZIP; + + // imz file must be opened in RAM mode + + if (nDiskType == VFD_DISKTYPE_FILE) { + + VFDTRACE(0, + (FUNC ": %s is a zip compressed file", + sFileName)); + + CloseHandle(hFile); + ret = ERROR_INVALID_PARAMETER; + + goto exit_func; + } + } + else { + + file_type = VFD_FILETYPE_RAW; + + if (nDiskType == VFD_DISKTYPE_FILE) { + + // direct image file must not be compressed or encrypted + + BY_HANDLE_FILE_INFORMATION info; + + if (!GetFileInformationByHandle(hFile, &info)) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": GetFileInformationByHandle - %s", + SystemMessage(ret))); + + CloseHandle(hFile); + + return ret; + } + + if (info.dwFileAttributes & + (FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_ENCRYPTED)) { + + VFDTRACE(0, + (FUNC ": file is compressed/encrypted")); + + CloseHandle(hFile); + + return ERROR_FILE_ENCRYPTED; + } + + image_size = info.nFileSizeLow; + } + else { + + // prepare image data for a file based RAM disk + + image_size = GetFileSize(hFile, NULL); + + if (image_size == 0 || image_size == INVALID_FILE_SIZE) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": GetFileSize - %s", + SystemMessage(ret))); + + CloseHandle(hFile); + + return ret; + } + + image_buf = (PUCHAR)LocalAlloc(LPTR, image_size); + + if (image_buf == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": LocalAlloc - %s", + SystemMessage(ret))); + + CloseHandle(hFile); + + return ret; + } + + if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) != 0) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": SetFilePointer - %s", + SystemMessage(ret))); + + CloseHandle(hFile); + + goto exit_func; + } + + if (!ReadFile(hFile, image_buf, image_size, &result, NULL) || + image_size != result) { + + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": ReadFile - %s", + SystemMessage(ret))); + + CloseHandle(hFile); + + goto exit_func; + } + } + } + + CloseHandle(hFile); + + // Prepare absolute path in the kernel namespace + + if (*sFileName == '\\' && *(sFileName + 1) == '\\') { + + // \\server\share\path\floppy.img + + prefix = "\\??\\UNC"; + sFileName++; // drip the first '\' + } + else { + + // local path + + PSTR file_part; + + if (GetFullPathName(sFileName, + sizeof(abspath), abspath, &file_part) == 0) { + + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": GetFullPathName(%s) - %s\n", + sFileName, SystemMessage(ret))); + + goto exit_func; + } + + prefix = "\\??\\"; + sFileName = abspath; + } + + name_len = strlen(prefix) + strlen(sFileName); + } + else { + + // filename is not specified -- pure RAM disk + + nDiskType = VFD_DISKTYPE_RAM; + file_type = VFD_FILETYPE_NONE; + + prefix = NULL; + name_len = 0; + + // prepare a FAT formatted RAM image + + image_size = VfdGetMediaSize(nMediaType); + + image_buf = (PUCHAR)LocalAlloc(LPTR, image_size); + + if (image_buf == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": LocalAlloc - %s", + SystemMessage(ret))); + + return ret; + } + + FormatBufferFat(image_buf, VFD_BYTE_TO_SECTOR(image_size)); + } + + if (image_size < VfdGetMediaSize(nMediaType)) { + + // image is too small for the specified media type + + VFDTRACE(0, + (FUNC ": Image is too small for the specified media type\n")); + + ret = ERROR_INVALID_PARAMETER; + goto exit_func; + } + + // prepare VFD_IMAGE_INFO structure + + image_info = (PVFD_IMAGE_INFO)LocalAlloc(LPTR, + sizeof(VFD_IMAGE_INFO) + name_len + 1); + + if (image_info == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": LocalAlloc(%lu) - %s\n", + sizeof(VFD_IMAGE_INFO) + name_len + 1, + SystemMessage(ret))); + + goto exit_func; + } + + ZeroMemory(image_info, + sizeof(VFD_IMAGE_INFO) + name_len + 1); + + if (name_len) { + sprintf(image_info->FileName, + "%s%s", prefix, sFileName); + } + + image_info->NameLength = (USHORT)name_len; + + image_info->DiskType = nDiskType; + image_info->MediaType = nMediaType; + image_info->MediaFlags = nMediaFlags; + image_info->FileType = file_type; + image_info->ImageSize = image_size; + + if (nDiskType != VFD_DISKTYPE_FILE) { + // protect flag for a RAM disk is set after + // initializing the image buffer + image_info->MediaFlags &= ~VFD_FLAG_WRITE_PROTECTED; + } + + VFDTRACE(0, + (FUNC ": Opening file \"%s\" (%lu bytes) %s %s %s %s\n", + name_len ? image_info->FileName : "", + image_info->ImageSize, + (file_type == VFD_FILETYPE_ZIP) ? "ZIP image" : "RAW image", + VfdMediaTypeName(nMediaType), + (nDiskType == VFD_DISKTYPE_FILE) ? "FILE disk" : "RAM disk", + (nMediaFlags & VFD_FLAG_WRITE_PROTECTED) ? "Protected" : "Writable")); + + // Open the image file / create a ram disk + + if (!DeviceIoControl( + hDevice, + IOCTL_VFD_OPEN_IMAGE, + image_info, + sizeof(VFD_IMAGE_INFO) + name_len, + NULL, + 0, + &result, + NULL)) + { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": DeviceIoControl(IOCTL_VFD_OPEN_FILE) - %s", + SystemMessage(ret))); + + goto exit_func; + } + + // initialize the RAM disk image + + if (nDiskType != VFD_DISKTYPE_FILE) { + + image_size &= ~VFD_SECTOR_ALIGN_MASK; + + if (SetFilePointer(hDevice, 0, NULL, FILE_BEGIN) != 0) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": SetFilePointer - %s", + SystemMessage(ret))); + + goto exit_func; + } + + if (!WriteFile(hDevice, image_buf, image_size, &result, NULL) || + image_size != result) { + + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": WriteFile - %s", + SystemMessage(ret))); + + goto exit_func; + } + + if (nMediaFlags & VFD_FLAG_WRITE_PROTECTED) { + VfdWriteProtect(hDevice, TRUE); + } + + if (!DeviceIoControl( + hDevice, + IOCTL_VFD_RESET_MODIFY, + NULL, + 0, + NULL, + 0, + &result, + NULL)) + { + VFDTRACE(0, + (FUNC ": DeviceIoControl(IOCTL_VFD_RESET_MODIFY) - %s", + SystemMessage(GetLastError()))); + } + } + + // Broadcast the successful operation + + if (ret == ERROR_SUCCESS) { + ULONG number; + CHAR root[] = "A:\\"; + + if (VfdGetDeviceNumber(hDevice, &number) == ERROR_SUCCESS) { + VfdNotify(VFD_OPERATION_OPEN, number); + } + + VfdGetGlobalLink(hDevice, &root[0]); + + if (isalpha(root[0])) { + SHChangeNotify(SHCNE_MEDIAINSERTED, SHCNF_PATH, root, NULL); + } + + while (VfdGetLocalLink(hDevice, &root[0]) == ERROR_SUCCESS && + isalpha(root[0])) { + SHChangeNotify(SHCNE_MEDIAINSERTED, SHCNF_PATH, root, NULL); + } + } + +exit_func: + if (image_info) { + LocalFree(image_info); + } + + if (image_buf) { + LocalFree(image_buf); + } + + return ret; +} + +// +// Close the virtual floppy Image +// +DWORD WINAPI VfdCloseImage( + HANDLE hDevice, + BOOL bForce) +{ +#undef FUNC +#define FUNC "VfdCloseImage" + DWORD result; + DWORD ret = ERROR_SUCCESS; + int retry = 0; + +lock_retry: + if (!DeviceIoControl( + hDevice, + FSCTL_LOCK_VOLUME, + NULL, + 0, + NULL, + 0, + &result, + NULL)) + { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": DeviceIoControl(FSCTL_LOCK_VOLUME) - %s", + SystemMessage(ret))); + + if (ret != ERROR_ACCESS_DENIED || retry == 5) { + // error other than access denied or + // operation kept failing for 5 seconds + return ret; + } + + if (!bForce) { + // error is access denied and + // the force flag is not set + + if (retry == 0) { + + // send the MEDIAREMOVED notification to the shell and + // see if the shell releases the target drive + + CHAR root[] = "A:\\"; + + VfdGetGlobalLink(hDevice, &root[0]); + + if (isalpha(root[0])) { + SHChangeNotify(SHCNE_MEDIAREMOVED, SHCNF_PATH, root, NULL); + } + + while (VfdGetLocalLink(hDevice, &root[0]) == ERROR_SUCCESS && + isalpha(root[0])) { + SHChangeNotify(SHCNE_MEDIAREMOVED, SHCNF_PATH, root, NULL); + } + } + + Sleep(1000); + retry++; + + goto lock_retry; + } + } + + ret = ERROR_SUCCESS; + + if (!DeviceIoControl( + hDevice, + FSCTL_DISMOUNT_VOLUME, + NULL, + 0, + NULL, + 0, + &result, + NULL)) + { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": DeviceIoControl(FSCTL_DISMOUNT_VOLUME) - %s", + SystemMessage(ret))); + + return ret; + } + + if (!DeviceIoControl( + hDevice, + IOCTL_VFD_CLOSE_IMAGE, + NULL, + 0, + NULL, + 0, + &result, + NULL)) + { + ret = GetLastError(); + + if (ret != ERROR_NOT_READY) { + VFDTRACE(0, + (FUNC ": DeviceIoControl(IOCTL_VFD_CLOSE_FILE) - %s", + SystemMessage(ret))); + } + + return ret; + } + + if (!DeviceIoControl( + hDevice, + FSCTL_UNLOCK_VOLUME, + NULL, + 0, + NULL, + 0, + &result, + NULL)) + { + // This should not be fatal because the volume is unlocked + // when the handle is closed anyway + VFDTRACE(0, + (FUNC ": DeviceIoControl(FSCTL_UNLOCK_VOLUME) - %s", + SystemMessage(GetLastError()))); + } + + // Broadcast the successful operation + if (ret == ERROR_SUCCESS) { + ULONG number; + + if (VfdGetDeviceNumber(hDevice, &number) == ERROR_SUCCESS) { + VfdNotify(VFD_OPERATION_CLOSE, number); + } + } + + return ret; +} + +// +// Get Virtual Floppy image info +// +DWORD WINAPI VfdGetImageInfo( + HANDLE hDevice, + PSTR sFileName, + PVFD_DISKTYPE pDiskType, + PVFD_MEDIA pMediaType, + PVFD_FLAGS pMediaFlags, + PVFD_FILETYPE pFileType, + PULONG pImageSize) +{ +#undef FUNC +#define FUNC "VfdGetImageInfo" + PVFD_IMAGE_INFO image_info; + DWORD result; + DWORD ret = ERROR_SUCCESS; + + image_info = (PVFD_IMAGE_INFO)LocalAlloc( + LPTR, sizeof(VFD_IMAGE_INFO) + MAX_PATH); + + if (image_info == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": LocalAlloc(%lu) - %s\n", + sizeof(VFD_IMAGE_INFO) + MAX_PATH, SystemMessage(ret))); + + return ret; + } + + ZeroMemory(image_info, sizeof(VFD_IMAGE_INFO) + MAX_PATH); + + // Query file information + + if (!DeviceIoControl( + hDevice, + IOCTL_VFD_QUERY_IMAGE, + NULL, + 0, + image_info, + sizeof(VFD_IMAGE_INFO) + MAX_PATH, + &result, + NULL)) + { + ret = GetLastError(); + + if (ret != ERROR_MORE_DATA) { + VFDTRACE(0, + (FUNC ": DeviceIoControl(IOCTL_VFD_QUERY_FILE) - %s", + SystemMessage(ret))); + + goto cleanup; + } + } + + // copy obtained information to output buffer + + if (sFileName) { + + // if filename is too long, clip it + + if (image_info->NameLength >= MAX_PATH) { + image_info->NameLength = MAX_PATH - 1; + } + + // ensure the name is properly terminated + + image_info->FileName[image_info->NameLength] = '\0'; + + if (strncmp(image_info->FileName, "\\??\\UNC", 7) == 0) { + *sFileName = '\\'; + strcpy(sFileName + 1, image_info->FileName + 7); + } + else if (strncmp(image_info->FileName, "\\??\\", 4) == 0) { + strcpy(sFileName, image_info->FileName + 4); + } + else { + strcpy(sFileName, image_info->FileName); + } + } + + if (pDiskType) { + *pDiskType = image_info->DiskType; + } + + if (pMediaType) { + *pMediaType = image_info->MediaType; + } + + if (pMediaFlags) { + *pMediaFlags = image_info->MediaFlags; + } + + if (pFileType) { + *pFileType = image_info->FileType; + } + + if (pImageSize) { + *pImageSize = image_info->ImageSize; + } + +cleanup: + if (image_info) { + LocalFree(image_info); + } + + return ret; +} + +// +// Get current media state (opened / write protected) +// +DWORD WINAPI VfdGetMediaState( + HANDLE hDevice) +{ +#undef FUNC +#define FUNC "VfdGetMediaState" + DWORD result; + DWORD ret = ERROR_SUCCESS; + + // Query file information + + if (!DeviceIoControl( + hDevice, + IOCTL_DISK_IS_WRITABLE, + NULL, + 0, + NULL, + 0, + &result, + NULL)) + { + ret = GetLastError(); + + if (ret != ERROR_NOT_READY) { + VFDTRACE(0, + (FUNC ": DeviceIoControl(IOCTL_DISK_IS_WRITABLE) - %s", + SystemMessage(ret))); + } + } + + return ret; +} + +// +// Set or Delete a global drive letter +// +DWORD WINAPI VfdSetGlobalLink( + HANDLE hDevice, + CHAR cLetter) +{ +#undef FUNC +#define FUNC "VfdSetGlobalLink" + CHAR letter; + ULONG number; + DWORD result; + DWORD ret; + + if (isalpha(cLetter)) { + + // make sure the drive does not have a drive letter + + letter = 0; + + VfdGetGlobalLink(hDevice, &letter); + + if (isalpha(letter)) { + VFDTRACE(0, + (FUNC ": Drive already has a drive letter %c\n", letter)); + return ERROR_ALREADY_ASSIGNED; + } + + VfdGetLocalLink(hDevice, &letter); + + if (isalpha(letter)) { + VFDTRACE(0, + (FUNC ": Drive already has a drive letter %c\n", letter)); + return ERROR_ALREADY_ASSIGNED; + } + + // make sure drive letter is not in use + + cLetter = (CHAR)toupper(cLetter); + + if (GetLogicalDrives() & (1 << (cLetter - 'A'))) { + VFDTRACE(0, + (FUNC ": Drive letter %c already used\n", cLetter)); + return ERROR_ALREADY_ASSIGNED; + } + + // Assign a new drive letter + + if (!DeviceIoControl( + hDevice, + IOCTL_VFD_SET_LINK, + &cLetter, + sizeof(cLetter), + NULL, + 0, + &result, + NULL)) + { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": DeviceIoControl(IOCTL_VFD_SET_LINK) - %s", + SystemMessage(ret))); + + return ret; + } + + // broadcast system message + + VfdBroadcastLink(cLetter, VFD_LINK_CREATED); + + // broadcast VFD message + + if (VfdGetDeviceNumber(hDevice, &number) == ERROR_SUCCESS) { + VfdNotify(VFD_OPERATION_SETLINK, number); + } + + return ERROR_SUCCESS; + } + else if (!cLetter) { + + // make sure the drive has a global drive letter + + letter = 0; + + VfdGetGlobalLink(hDevice, &letter); + + if (!isalpha(letter)) { + VFDTRACE(0, + (FUNC ": Drive does not have a drive letter\n")); + return ERROR_INVALID_FUNCTION; + } + + // Remove drive letters + + if (!DeviceIoControl( + hDevice, + IOCTL_VFD_SET_LINK, + &cLetter, + sizeof(cLetter), + NULL, + 0, + &result, + NULL)) + { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": DeviceIoControl(IOCTL_VFD_SET_LINK) - %s", + SystemMessage(ret))); + + return ret; + } + + // broadcast system message + + VfdBroadcastLink(letter, VFD_LINK_REMOVED); + + // broadcast VFD message + if (VfdGetDeviceNumber(hDevice, &number) == ERROR_SUCCESS) { + VfdNotify(VFD_OPERATION_DELLINK, number); + } + + return ERROR_SUCCESS; + } + else { + return ERROR_INVALID_PARAMETER; + } +} + +// +// Get a global drive letter +// +DWORD WINAPI VfdGetGlobalLink( + HANDLE hDevice, + PCHAR pLetter) +{ +#undef FUNC +#define FUNC "VfdGetGlobalLinks" + DWORD result; + DWORD ret; + + if (!pLetter) { + return ERROR_INVALID_PARAMETER; + } + + *pLetter = 0; + + if (!DeviceIoControl( + hDevice, + IOCTL_VFD_QUERY_LINK, + NULL, + 0, + pLetter, + sizeof(*pLetter), + &result, + NULL)) + { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": DeviceIoControl(IOCTL_VFD_QUERY_LINK) - %s", + SystemMessage(ret))); + + return ret; + } + + return ERROR_SUCCESS; +} + +// +// Set or remove a local drive letter +// +DWORD WINAPI VfdSetLocalLink( + HANDLE hDevice, + CHAR cLetter) +{ +#undef FUNC +#define FUNC "VfdSetLocalLink" + CHAR letter; + CHAR dos_name[] = "A:"; + CHAR dev_name[MAX_PATH]; + ULONG number; + DWORD ret; + + if (isalpha(cLetter)) { + + // make sure the drive does not have a drive letter + + letter = 0; + + VfdGetGlobalLink(hDevice, &letter); + + if (isalpha(letter)) { + VFDTRACE(0, + (FUNC ": Drive already has a drive letter %c\n", letter)); + return ERROR_ALREADY_ASSIGNED; + } + + VfdGetLocalLink(hDevice, &letter); + + if (isalpha(letter)) { + VFDTRACE(0, + (FUNC ": Drive already has a drive letter %c\n", letter)); + return ERROR_ALREADY_ASSIGNED; + } + + // make sure drive letters are not in use + + cLetter = (CHAR)toupper(cLetter); + + if (GetLogicalDrives() & (1 << (cLetter - 'A'))) { + VFDTRACE(0, + (FUNC ": Drive letter already used\n")); + + return ERROR_ALREADY_ASSIGNED; + } + + // get VFD device name + + ret = VfdGetDeviceName(hDevice, dev_name, sizeof(dev_name)); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + // assign a drive letter + + dos_name[0] = cLetter; + + if (!DefineDosDevice(DDD_RAW_TARGET_PATH, dos_name, dev_name)) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": DefineDosDevice(%s,%s) - %s", + dos_name, dev_name, SystemMessage(ret))); + } + + if (ret == ERROR_SUCCESS) { + // broadcast VFD message + + if (VfdGetDeviceNumber(hDevice, &number) == ERROR_SUCCESS) { + VfdNotify(VFD_OPERATION_SETLINK, number); + } + } + + return ret; + } + else if (!cLetter) { + + // make sure the drive has a local drive letter + + letter = 0; + + VfdGetLocalLink(hDevice, &letter); + + if (!isalpha(letter)) { + VFDTRACE(0, + (FUNC ": Drive letter is not assigned to this drive\n")); + return ERROR_INVALID_FUNCTION; + } + + // get VFD device name + + ret = VfdGetDeviceName(hDevice, dev_name, sizeof(dev_name)); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + // remove drive letters +#define DDD_FLAGS (DDD_REMOVE_DEFINITION | DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE) + + dos_name[0] = (CHAR)toupper(letter); + + if (!DefineDosDevice(DDD_FLAGS, dos_name, dev_name)) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": DefineDosDevice(%s,%s) - %s", + dos_name, dev_name, SystemMessage(ret))); + } + + if (ret == ERROR_SUCCESS) { + // broadcast VFD message + if (VfdGetDeviceNumber(hDevice, &number) == ERROR_SUCCESS) { + VfdNotify(VFD_OPERATION_DELLINK, number); + } + } + + return ret; + } + else { + return ERROR_INVALID_PARAMETER; + } +} + +// +// Get local drive letters +// +DWORD WINAPI VfdGetLocalLink( + HANDLE hDevice, + PCHAR pLetter) +{ +#undef FUNC +#define FUNC "VfdGetLocalLinks" + CHAR global; + ULONG logical; + CHAR dos_name[] = "A:"; + CHAR dev_name[MAX_PATH]; + CHAR dos_target[MAX_PATH * 2]; + DWORD ret; + + if (!pLetter) { + return ERROR_INVALID_PARAMETER; + } + + // Get the VFD device name + + ret = VfdGetDeviceName(hDevice, dev_name, sizeof(dev_name)); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + // Get global drive letter + + ret = VfdGetGlobalLink(hDevice, &global); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + // Get logical drives + + logical = GetLogicalDrives(); + + // exclude the global drive letter + + if (isalpha(global)) { + logical &= ~(1 << (toupper(global) - 'A')); + } + + // start searching from the next drive letter + + if (isalpha(*pLetter)) { + dos_name[0] = (CHAR)(toupper(*pLetter) + 1); + logical >>= (dos_name[0] - 'A'); + } + + // Check dos device targets + + *pLetter = '\0'; + + while (logical) { + if (logical & 0x01) { + if (QueryDosDevice(dos_name, dos_target, sizeof(dos_target))) { + if (_stricmp(dos_target, dev_name) == 0) { + *pLetter = dos_name[0]; + break; + } + } + else { + VFDTRACE(0, + (FUNC ": QueryDosDevice(%s) - %s", + dos_name, SystemMessage(GetLastError()))); + } + } + logical >>= 1; + dos_name[0]++; + } + + return ERROR_SUCCESS; +} + +// +// Get the Virtual Floppy device number +// +DWORD WINAPI VfdGetDeviceNumber( + HANDLE hDevice, + PULONG pNumber) +{ +#undef FUNC +#define FUNC "VfdGetDeviceNumber" + DWORD result; + DWORD ret = ERROR_SUCCESS; + + if (!pNumber) { + return ERROR_INVALID_PARAMETER; + } + + *pNumber = 0; + + if (!DeviceIoControl( + hDevice, + IOCTL_VFD_QUERY_NUMBER, + NULL, + 0, + pNumber, + sizeof(ULONG), + &result, + NULL)) + { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": DeviceIoControl(IOCTL_VFD_QUERY_NUMBER) - %s", + SystemMessage(ret))); + } + + return ret; +} + +// Get the Virtual Floppy device name + +DWORD WINAPI VfdGetDeviceName( + HANDLE hDevice, + PCHAR pName, + ULONG nLength) +{ +#undef FUNC +#define FUNC "VfdGetDeviceName" + DWORD result; + WCHAR wname[MAX_PATH]; + DWORD ret = ERROR_SUCCESS; + + if (!pName || !nLength) { + return ERROR_INVALID_PARAMETER; + } + + ZeroMemory(pName, nLength); + + if (!DeviceIoControl( + hDevice, + IOCTL_VFD_QUERY_NAME, + NULL, + 0, + wname, + sizeof(wname), + &result, + NULL)) + { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": DeviceIoControl(IOCTL_VFD_QUERY_NUMBER) - %s", + SystemMessage(ret))); + } + + if (!WideCharToMultiByte(CP_OEMCP, 0, &wname[1], + wname[0] / sizeof(WCHAR), pName, nLength, NULL, NULL)) { + + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": WideCharToMultiByte - %s", + SystemMessage(ret))); + } + + return ret; +} + +// +// Get Virtual Floppy driver version +// +DWORD WINAPI VfdGetDriverVersion( + HANDLE hDevice, + PULONG pVersion) +{ +#undef FUNC +#define FUNC "VfdGetDriverVersion" + DWORD result; + DWORD ret = ERROR_SUCCESS; + + if (!pVersion) { + return ERROR_INVALID_PARAMETER; + } + + *pVersion = '\0'; + + if (!DeviceIoControl( + hDevice, + IOCTL_VFD_QUERY_VERSION, + NULL, + 0, + pVersion, + sizeof(ULONG), + &result, + NULL)) + { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": DeviceIoControl(IOCTL_VFD_QUERY_VERSION) - %s", + SystemMessage(ret))); + } + + return ret; +} + +// +// Change the write protect state of the media +// +DWORD WINAPI VfdWriteProtect( + HANDLE hDevice, + BOOL bProtect) +{ +#undef FUNC +#define FUNC "VfdWriteProtect" + DWORD result; + DWORD ret = ERROR_SUCCESS; + + if (!DeviceIoControl( + hDevice, + bProtect ? IOCTL_VFD_SET_PROTECT : IOCTL_VFD_CLEAR_PROTECT, + NULL, + 0, + NULL, + 0, + &result, + NULL)) + { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": DeviceIoControl(IOCTL_VFD_SET_PROTECT) - %s", + SystemMessage(ret))); + } + + if (ret == ERROR_SUCCESS) { + ULONG number; + + if (VfdGetDeviceNumber(hDevice, &number) == ERROR_SUCCESS) { + VfdNotify(VFD_OPERATION_PROTECT, number); + } + } + + return ret; +} + +// Format the current media with FAT12 + +DWORD WINAPI VfdFormatMedia( + HANDLE hDevice) +{ +#undef FUNC +#define FUNC "VfdFormatMedia" + DWORD result; + DWORD ret = ERROR_SUCCESS; + PUCHAR buf = NULL; + GET_LENGTH_INFORMATION length; + + // Get the media size + + if (!DeviceIoControl( + hDevice, + IOCTL_DISK_GET_LENGTH_INFO, + NULL, + 0, + &length, + sizeof(length), + &result, + NULL)) + { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": DeviceIoControl(IOCTL_DISK_GET_LENGTH_INFO) - %s", + SystemMessage(ret))); + + goto exit_func; + } + + // Prepare a formatted image buffer + + buf = (PUCHAR)LocalAlloc(LPTR, length.Length.LowPart); + + if (buf == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": LocalAlloc - %s", + SystemMessage(ret))); + + goto exit_func; + } + + // format the buffer + + ret = FormatBufferFat(buf, + VFD_BYTE_TO_SECTOR(length.Length.LowPart)); + + if (ret != ERROR_SUCCESS) { + goto exit_func; + } + + // seek the top of the media + + if (SetFilePointer(hDevice, 0, NULL, FILE_BEGIN) != 0) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": SetFilePointer - %s", + SystemMessage(ret))); + + goto exit_func; + } + + // write the image into the media + + if (!WriteFile(hDevice, buf, length.Length.LowPart, &result, NULL) || + result != length.Length.LowPart) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": WriteFile - %s", + SystemMessage(ret))); + + goto exit_func; + } + +exit_func: + // unlock the target volume + if (!DeviceIoControl( + hDevice, + FSCTL_UNLOCK_VOLUME, + NULL, + 0, + NULL, + 0, + &result, + NULL)) + { + VFDTRACE(0, + (FUNC ": DeviceIoControl(FSCTL_UNLOCK_VOLUME) - %s", + SystemMessage(GetLastError()))); + } + + // release the format image buffer + if (buf) { + LocalFree(buf); + } + + return ret; +} + +// Dismount the volume (should be called before Save, Format) + +DWORD WINAPI VfdDismountVolume( + HANDLE hDevice, + BOOL bForce) +{ +#undef FUNC +#define FUNC "VfdDismountVolume" + DWORD result; + DWORD ret = ERROR_SUCCESS; + + // Lock the target volume + + if (!DeviceIoControl( + hDevice, + FSCTL_LOCK_VOLUME, + NULL, + 0, + NULL, + 0, + &result, + NULL)) + { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": DeviceIoControl(FSCTL_LOCK_VOLUME) - %s", + SystemMessage(ret))); + + if (ret != ERROR_ACCESS_DENIED || !bForce) { + return ret; + } + } + + // Dismount the target volume + + if (!DeviceIoControl( + hDevice, + FSCTL_DISMOUNT_VOLUME, + NULL, + 0, + NULL, + 0, + &result, + NULL)) + { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": DeviceIoControl(FSCTL_DISMOUNT_VOLUME) - %s", + SystemMessage(ret))); + } + + return ret; +} + +// Save the current image into a file + +DWORD WINAPI VfdSaveImage( + HANDLE hDevice, + PCSTR sFileName, + BOOL bOverWrite, + BOOL bTruncate) +{ +#undef FUNC +#define FUNC "VfdSaveImage" + HANDLE hFile = INVALID_HANDLE_VALUE; + DWORD result; + DWORD ret = ERROR_SUCCESS; + PUCHAR buf = NULL; + GET_LENGTH_INFORMATION length; + + + ret = ERROR_SUCCESS; + + // Get the media size + + if (!DeviceIoControl( + hDevice, + IOCTL_DISK_GET_LENGTH_INFO, + NULL, + 0, + &length, + sizeof(length), + &result, + NULL)) + { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": DeviceIoControl(IOCTL_DISK_GET_LENGTH_INFO) - %s", + SystemMessage(ret))); + + goto exit_func; + } + + // Prepare an intermediate image buffer + + buf = (PUCHAR)LocalAlloc(LPTR, length.Length.LowPart); + + if (buf == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": LocalAlloc - %s", + SystemMessage(ret))); + + goto exit_func; + } + + // seek the top of the media + + if (SetFilePointer(hDevice, 0, NULL, FILE_BEGIN) != 0) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": SetFilePointer - %s", + SystemMessage(ret))); + + goto exit_func; + } + + // read the image data + + if (!ReadFile(hDevice, buf, length.Length.LowPart, &result, NULL) || + result != length.Length.LowPart) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": ReadFile - %s", + SystemMessage(ret))); + + goto exit_func; + } + + // open the destination file + + hFile = CreateFile(sFileName, GENERIC_WRITE, 0, NULL, + bOverWrite ? OPEN_ALWAYS : CREATE_NEW, 0, NULL); + + if (hFile == INVALID_HANDLE_VALUE) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": CreateFile - %s", + SystemMessage(ret))); + + goto exit_func; + } + + // seek the top of the file + + if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) != 0) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": SetFilePointer - %s", + SystemMessage(ret))); + + goto exit_func; + } + + // write the image data + + if (!WriteFile(hFile, buf, length.Length.LowPart, &result, NULL) || + result != length.Length.LowPart) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": WriteFile - %s", + SystemMessage(ret))); + + goto exit_func; + } + + // truncate the target file + + if (bTruncate && !SetEndOfFile(hFile)) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": SetEndOfFile - %s", + SystemMessage(ret))); + + goto exit_func; + } + + // reset the media modified flag + + if (!DeviceIoControl( + hDevice, + IOCTL_VFD_RESET_MODIFY, + NULL, + 0, + NULL, + 0, + &result, + NULL)) + { + VFDTRACE(0, + (FUNC ": DeviceIoControl(IOCTL_VFD_RESET_MODIFY) - %s", + SystemMessage(GetLastError()))); + } + +exit_func: + // unlock the target volume + + if (!DeviceIoControl( + hDevice, + FSCTL_UNLOCK_VOLUME, + NULL, + 0, + NULL, + 0, + &result, + NULL)) + { + VFDTRACE(0, + (FUNC ": DeviceIoControl(FSCTL_UNLOCK_VOLUME) - %s", + SystemMessage(GetLastError()))); + } + + // release the format image buffer + + if (buf) { + LocalFree(buf); + } + + // close the image file + + if (hFile != INVALID_HANDLE_VALUE) { + CloseHandle(hFile); + } + + return ret; +} + +// +// Check if specified file is valid VFD driver +// +DWORD WINAPI VfdCheckDriverFile( + PCSTR sFileName, + PULONG pFileVersion) +{ +#undef FUNC +#define FUNC "VfdCheckDriverFile" + DWORD result; + DWORD dummy; + PVOID info; + VS_FIXEDFILEINFO *fixedinfo; + DWORD ret = ERROR_SUCCESS; + PSTR str; + + // Check parameter + + if (!sFileName || !*sFileName) { + return ERROR_INVALID_PARAMETER; + } + + if (pFileVersion) { + *pFileVersion = 0; + } + + // check file existence + + if (GetFileAttributes(sFileName) == INVALID_FILE_ATTRIBUTES) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": GetFileAttributes - %s\n", + SystemMessage(ret))); + + return ret; + } + + // check file version + + result = GetFileVersionInfoSize((PSTR)sFileName, &dummy); + + if (result == 0) { + VFDTRACE(0, + (FUNC ": GetFileVersionInfoSize == 0\n")); + + return ERROR_BAD_DRIVER; + } + + info = LocalAlloc(LPTR, result); + + if (info == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": LocalAlloc(%lu) - %s\n", + result, SystemMessage(ret))); + + return ret; + } + + if (!GetFileVersionInfo((PSTR)sFileName, 0, result, info)) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": GetFileVersionInfo - %s", SystemMessage(ret))); + + goto cleanup; + } + + result = sizeof(fixedinfo); + + if (!VerQueryValue(info, "\\", (PVOID *)&fixedinfo, (PUINT)&result)) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": VerQueryValue(\"\\\") - %s", SystemMessage(ret))); + + goto cleanup; + } + + if (fixedinfo->dwFileOS != VOS_NT_WINDOWS32 || + fixedinfo->dwFileType != VFT_DRV || + fixedinfo->dwFileSubtype != VFT2_DRV_SYSTEM) { + + VFDTRACE(0, +#ifndef __REACTOS__ + (FUNC ": Invalid file type flags\n")); +#else + (FUNC ": Invalid file type flags. os: %x (%x), type: %x (%x), subtype: %x (%x)\n", + fixedinfo->dwFileOS, VOS_NT_WINDOWS32, fixedinfo->dwFileType, VFT_DRV, + fixedinfo->dwFileSubtype, VFT2_DRV_SYSTEM)); +#endif + + ret = ERROR_BAD_DRIVER; + + goto cleanup; + } + + if (pFileVersion) { + *pFileVersion = fixedinfo->dwFileVersionMS; + + if (fixedinfo->dwFileFlags & VS_FF_DEBUG) { + *pFileVersion |= 0x80000000; + } + } + + if (!VerQueryValue(info, + "\\StringFileInfo\\" VFD_VERSIONINFO_LANG "\\OriginalFileName", + (PVOID *)&str, (PUINT)&result)) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": VerQueryValue(\"OriginalFileName\") - %s", + SystemMessage(ret))); + + goto cleanup; + } + + if (strcmp(str, VFD_DRIVER_FILENAME)) { + VFDTRACE(0, + (FUNC ": Invalid original file name\n")); + + ret = ERROR_BAD_DRIVER; + + goto cleanup; + } + + if (fixedinfo->dwFileVersionMS != MAKELONG(VFD_DRIVER_MINOR, VFD_DRIVER_MAJOR) || + fixedinfo->dwProductVersionMS != MAKELONG(VFD_PRODUCT_MINOR, VFD_PRODUCT_MAJOR)) { + + VFDTRACE(0, + (FUNC ": Invalid version values - file:%08x, prod: %08x\n", + fixedinfo->dwFileVersionMS, fixedinfo->dwProductVersionMS)); + + ret = ERROR_BAD_DRIVER; + + goto cleanup; + } + + // Ensure that the driver binary is located on a local drive + // because device driver cannot be started on network drives. + + if (*sFileName == '\\' && *(sFileName + 1) == '\\') { + // full path is a UNC path -- \\server\dir\... + + VFDTRACE(0, + (FUNC ": Driver is located on a network drive\n")); + + return ERROR_NETWORK_ACCESS_DENIED; + } + else { + // ensure that the drive letter is not a network drive + + CHAR root[] = " :\\"; + + root[0] = *sFileName; + + if (GetDriveType(root) == DRIVE_REMOTE) { + // the drive is a network drive + + VFDTRACE(0, + (FUNC ": Driver is located on a network drive\n")); + + return ERROR_NETWORK_ACCESS_DENIED; + } + } + +cleanup: + LocalFree(info); + + return ret; +} + +// +// check an image file +// +DWORD WINAPI VfdCheckImageFile( + PCSTR sFileName, + PDWORD pAttributes, + PVFD_FILETYPE pFileType, + PULONG pImageSize) +{ +#undef FUNC +#define FUNC "VfdCheckImageFile" + HANDLE hFile; + DWORD ret = ERROR_SUCCESS; + + if (!sFileName || !*sFileName || !pAttributes || !pImageSize || !pFileType) { + return ERROR_INVALID_PARAMETER; + } + + // get file attributes + + *pAttributes = GetFileAttributes(sFileName); + + if (*pAttributes == INVALID_FILE_ATTRIBUTES) { + ret = GetLastError(); + + if (ret != ERROR_FILE_NOT_FOUND) { + VFDTRACE(0, + (FUNC ": GetFileAttributes(%s) - %s\n", + sFileName, SystemMessage(ret))); + } + + return ret; + } + + // Open the target file + + hFile = CreateFile(sFileName, GENERIC_READ | GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, 0, NULL); + + if (hFile == INVALID_HANDLE_VALUE) { + + // failed to open + + ret = GetLastError(); + + if (ret != ERROR_ACCESS_DENIED) { + VFDTRACE(0, + (FUNC ": CreateFile(%s) - %s\n", + sFileName, SystemMessage(ret))); + + return ret; + } + + // try opening it read-only + + hFile = CreateFile(sFileName, GENERIC_READ, + FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + + if (hFile == INVALID_HANDLE_VALUE) { + + // cannot open even read-only + + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": CreateFile(%s) - %s\n", + sFileName, SystemMessage(ret))); + + return ret; + } + + // file can be opened read-only + *pAttributes |= FILE_ATTRIBUTE_READONLY; + ret = ERROR_SUCCESS; + } + + // check if the image is an IMZ file + + if (ExtractZipInfo(hFile, pImageSize) == ERROR_SUCCESS) { + *pFileType = VFD_FILETYPE_ZIP; + } + else { + *pImageSize = GetFileSize(hFile, NULL); + *pFileType = VFD_FILETYPE_RAW; + } + + CloseHandle(hFile); + + return ret; +} + +// +// Create a formatted new image file +// +DWORD WINAPI VfdCreateImageFile( + PCSTR sFileName, + VFD_MEDIA nMediaType, + VFD_FILETYPE nFileType, + BOOL bOverWrite) +{ +#undef FUNC +#define FUNC "VfdCreateImageFile" + HANDLE hFile; + ULONG file_size; + PUCHAR image_buf = NULL; + DWORD result; + DWORD ret = ERROR_SUCCESS; + + if (nFileType != VFD_FILETYPE_RAW) { + return ERROR_INVALID_PARAMETER; + } + + file_size = VfdGetMediaSize(nMediaType); + + if (file_size == 0) { + return ERROR_INVALID_PARAMETER; + } + + hFile = CreateFile(sFileName, GENERIC_WRITE, 0, NULL, + bOverWrite ? CREATE_ALWAYS : CREATE_NEW, 0, NULL); + + if (hFile == INVALID_HANDLE_VALUE) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": CreateFile - %s", + SystemMessage(ret))); + + return ret; + } + + image_buf = (PUCHAR)LocalAlloc(LPTR, file_size); + + if (image_buf == NULL) { + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": LocalAlloc - %s", + SystemMessage(ret))); + + goto exit_func; + } + + FormatBufferFat(image_buf, VFD_BYTE_TO_SECTOR(file_size)); + + if (!WriteFile(hFile, image_buf, file_size, &result, NULL) || + file_size != result) { + + ret = GetLastError(); + + VFDTRACE(0, + (FUNC ": WriteFile - %s", + SystemMessage(ret))); + + goto exit_func; + } + + SetEndOfFile(hFile); + +exit_func: + CloseHandle(hFile); + + if (image_buf) { + LocalFree(image_buf); + } + + return ret; +} + + +// +// choose first available drive letter +// +CHAR WINAPI VfdChooseLetter() +{ + DWORD logical_drives = GetLogicalDrives(); + CHAR drive_letter = 'A'; + + if (logical_drives == 0) { + return '\0'; + } + + while (logical_drives & 0x1) { + logical_drives >>= 1; + drive_letter++; + } + + if (drive_letter > 'Z') { + return '\0'; + } + + return drive_letter; +} + +// +// media type functions +// +static const struct +{ + ULONG Size; + PCSTR Name; +} +media_tbl[VFD_MEDIA_MAX] = +{ + { 0, "" }, // VFD_MEDIA_NONE, + { VFD_SECTOR_TO_BYTE(320), "5.25\" 160KB" }, // VFD_MEDIA_F5_160 + { VFD_SECTOR_TO_BYTE(360), "5.25\" 180KB" }, // VFD_MEDIA_F5_180 + { VFD_SECTOR_TO_BYTE(640), "5.25\" 320KB" }, // VFD_MEDIA_F5_320 + { VFD_SECTOR_TO_BYTE(720), "5.25\" 360KB" }, // VFD_MEDIA_F5_360 + { VFD_SECTOR_TO_BYTE(1280), "3.5\" 640KB" }, // VFD_MEDIA_F3_640 + { VFD_SECTOR_TO_BYTE(1280), "5.25\" 640KB" }, // VFD_MEDIA_F5_640 + { VFD_SECTOR_TO_BYTE(1440), "3.5\" 720KB" }, // VFD_MEDIA_F3_720 + { VFD_SECTOR_TO_BYTE(1440), "5.25\" 720KB" }, // VFD_MEDIA_F5_720 + { VFD_SECTOR_TO_BYTE(1640), "3.5\" 820KB" }, // VFD_MEDIA_F3_820 + { VFD_SECTOR_TO_BYTE(2400), "3.5\" 1.2MB" }, // VFD_MEDIA_F3_1P2 + { VFD_SECTOR_TO_BYTE(2400), "5.25\" 1.2MB" }, // VFD_MEDIA_F5_1P2 + { VFD_SECTOR_TO_BYTE(2880), "3.5\" 1.44MB" }, // VFD_MEDIA_F3_1P4 + { VFD_SECTOR_TO_BYTE(3360), "3.5\" 1.68MB DMF" }, // VFD_MEDIA_F3_1P6 + { VFD_SECTOR_TO_BYTE(3444), "3.5\" 1.72MB DMF" }, // VFD_MEDIA_F3_1P7 + { VFD_SECTOR_TO_BYTE(5760), "3.5\" 2.88MB"} // VFD_MEDIA_F3_2P8 +}; + +// Lookup the largest media to fit in a size + +VFD_MEDIA WINAPI VfdLookupMedia( + ULONG nSize) +{ + VFD_MEDIA i; + + for (i = 1; i < VFD_MEDIA_MAX; i++) { + if (nSize < media_tbl[i].Size) { + break; + } + } + + return (--i); +} + +// Get media size (in bytes) of a media type + +ULONG WINAPI VfdGetMediaSize( + VFD_MEDIA nMediaType) +{ + return nMediaType < VFD_MEDIA_MAX ? media_tbl[nMediaType].Size : 0; +} + +// Get media type name + +PCSTR WINAPI VfdMediaTypeName( + VFD_MEDIA nMediaType) +{ + return nMediaType < VFD_MEDIA_MAX ? media_tbl[nMediaType].Name : NULL; +} diff --git a/modules/rosapps/lib/vfdlib/vfdfat.c b/modules/rosapps/lib/vfdlib/vfdfat.c new file mode 100644 index 00000000000..369c7e3b0b7 --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdfat.c @@ -0,0 +1,205 @@ +/* + vfdfat.c + + Virtual Floppy Drive for Windows + Driver control library + Formats the image with FAT12 + + Copyright (C) 2003-2005 Ken Kato +*/ + +#ifdef __cplusplus +#pragma message(__FILE__": Compiled as C++ for testing purpose.") +#endif // __cplusplus + +#define WIN32_LEAN_AND_MEAN +#include + +#include "vfdtypes.h" +#include "vfdio.h" +#include "vfdlib.h" +#include "vfdver.h" + +#pragma pack(1) +// +// BIOS parameter block +// +typedef struct _DOS_BPB +{ + USHORT BytesPerSector; + UCHAR SectorsPerCluster; + USHORT ReservedSectors; + UCHAR NumberOfFATs; + USHORT RootEntries; + USHORT SmallSectors; + UCHAR MediaDescriptor; + USHORT SectorsPerFAT; + USHORT SectorsPerTrack; + USHORT NumberOfHeads; + ULONG HiddenSectors; + ULONG LargeSectors; +} +DOS_BPB, *PDOS_BPB; + +// +// Extended BIOS parameter block for FAT12/16/HUGE +// +typedef struct _EXBPB +{ + UCHAR PhysicalDriveNumber; + UCHAR Reserved; + UCHAR BootSignature; + ULONG VolumeSerialNumber; + CHAR VolumeLabel[11]; + CHAR FileSystemType[8]; +} +EXBPB, *PEXBPB; + +// +// Partition Boot Record +// +typedef struct _DOS_PBR { // Partition Boot Record + UCHAR jump[3]; // Jump Instruction (E9 or EB, xx, 90) + CHAR oemid[8]; // OEM ID (OS type) + DOS_BPB bpb; // BIOS parameter block + EXBPB exbpb; // Extended BIOS parameter block +} +DOS_PBR, *PDOS_PBR; + +#pragma pack() + +#define FAT_DIR_ENTRY_SIZE 32 + +// We need to have the 0xeb and 0x90 in the jump code +// because the file system recognizer checks these values +#define VFD_JUMP_CODE "\xeb\x3c\x90" +#define VFD_OEM_NAME "VFD" VFD_DRIVER_VERSION_STR " " +#define VFD_VOLUME_LABEL "NO NAME " +#define VFD_FILESYSTEM "FAT12 " + +// +// Select DOS BPB parameters from media size +// +static const DOS_BPB *SelectDosBpb( + USHORT nSectors) +{ + static const DOS_BPB bpb_tbl[] = { + // b/s s/c r fat root sec desc s/f s/t h + {VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 320, 0xFE, 1, 8, 1, 0, 0}, // 160KB 5.25" + {VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 360, 0xFC, 1, 9, 1, 0, 0}, // 180KB 5.25" + {VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 640, 0xFF, 1, 8, 2, 0, 0}, // 320KB 5.25" + {VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 720, 0xFD, 2, 9, 2, 0, 0}, // 360KB 5.25" + {VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 1280, 0xFB, 2, 8, 2, 0, 0}, // 640KB 5.25" / 3.5" + {VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 1440, 0xF9, 3, 9, 2, 0, 0}, // 720KB 5.25" / 3.5" + {VFD_BYTES_PER_SECTOR, 2, 1, 2, 112, 1640, 0xF9, 3, 10, 2, 0, 0}, // 820KB 3.5" + {VFD_BYTES_PER_SECTOR, 1, 1, 2, 224, 2400, 0xF9, 7, 15, 2, 0, 0}, // 1.20MB 5.25" / 3.5" + {VFD_BYTES_PER_SECTOR, 1, 1, 2, 224, 2880, 0xF0, 9, 18, 2, 0, 0}, // 1.44MB 3.5" + {VFD_BYTES_PER_SECTOR, 1, 1, 2, 224, 3360, 0xF0, 10, 21, 2, 0, 0}, // 1.68MB 3.5" + {VFD_BYTES_PER_SECTOR, 1, 1, 2, 224, 3444, 0xF0, 10, 21, 2, 0, 0}, // 1.72MB 3.5" + {VFD_BYTES_PER_SECTOR, 2, 1, 2, 240, 5760, 0xF0, 9, 36, 2, 0, 0}, // 2.88MB 3.5" + }; + + int i; + + for (i = 0; i < sizeof(bpb_tbl) / sizeof(bpb_tbl[0]); i++) { + if (nSectors == bpb_tbl[i].SmallSectors) { + return &bpb_tbl[i]; + } + } + + return NULL; +} + +// +// Format the buffer with FAT12 +// +DWORD FormatBufferFat( + PUCHAR pBuffer, + ULONG nSectors) +{ + const DOS_BPB *bpb; // BIOS Parameter Block + PDOS_PBR pbr; // Partition Boot Record + PUCHAR fat; // File Allocation Table + USHORT idx; + + VFDTRACE(0, + ("[VFD] VfdFormatImage - IN\n")); + + // + // Select DOS BPB parameters from media size + // + bpb = SelectDosBpb((USHORT)nSectors); + + if (!bpb) { + VFDTRACE(0, + ("[VFD] Unsupported media size %lu\n", + nSectors)); + return ERROR_INVALID_PARAMETER; + } + + // + // Initialize the whole area with the fill data + // + FillMemory(pBuffer, + VFD_SECTOR_TO_BYTE(nSectors), + VFD_FORMAT_FILL_DATA); + + // + // Make up the FAT boot record + // + ZeroMemory(pBuffer, VFD_BYTES_PER_SECTOR); + + pbr = (PDOS_PBR)pBuffer; + + CopyMemory(pbr->jump, VFD_JUMP_CODE, sizeof(pbr->jump)); + CopyMemory(pbr->oemid, VFD_OEM_NAME, sizeof(pbr->oemid)); + CopyMemory(&pbr->bpb, bpb, sizeof(pbr->bpb)); + + // Make up the extended BPB + + pbr->exbpb.BootSignature = 0x29; + + // use the tick count as the volume serial number + pbr->exbpb.VolumeSerialNumber = GetTickCount(); + + CopyMemory(pbr->exbpb.VolumeLabel, + VFD_VOLUME_LABEL, sizeof(pbr->exbpb.VolumeLabel)); + + CopyMemory(pbr->exbpb.FileSystemType, + VFD_FILESYSTEM, sizeof(pbr->exbpb.FileSystemType)); + + // Set the boot record signature + + *(pBuffer + VFD_BYTES_PER_SECTOR - 2) = 0x55; + *(pBuffer + VFD_BYTES_PER_SECTOR - 1) = 0xaa; + + // + // Clear FAT areas + // + fat = pBuffer + VFD_SECTOR_TO_BYTE(bpb->ReservedSectors); + + ZeroMemory( + fat, + VFD_SECTOR_TO_BYTE(bpb->SectorsPerFAT * bpb->NumberOfFATs)); + + // + // Make up FAT entries for the root directory + // + for (idx = 0; idx < bpb->NumberOfFATs; idx++) { + *fat = bpb->MediaDescriptor; + *(fat + 1) = 0xff; + *(fat + 2) = 0xff; + + fat += VFD_SECTOR_TO_BYTE(bpb->SectorsPerFAT); + } + + // + // Clear root directory entries + // + ZeroMemory(fat, bpb->RootEntries * FAT_DIR_ENTRY_SIZE); + + VFDTRACE(0, + ("[VFD] VfdFormatImage - OUT\n")); + + return ERROR_SUCCESS; +} diff --git a/modules/rosapps/lib/vfdlib/vfdguiopen.c b/modules/rosapps/lib/vfdlib/vfdguiopen.c new file mode 100644 index 00000000000..d67281c2f46 --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdguiopen.c @@ -0,0 +1,562 @@ +/* + vfdguiopen.c + + Virtual Floppy Drive for Windows + Driver control library + Open image GUI utility function + + Copyright (c) 2003-2005 Ken Kato +*/ + +#ifdef __cplusplus +#pragma message(__FILE__": Compiled as C++ for testing purpose.") +#endif // __cplusplus + +#define WIN32_LEAN_AND_MEAN +#include +#ifdef _MSC_VER +#pragma warning(push,3) +#endif +#include +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include "vfdtypes.h" +#include "vfdapi.h" +#include "vfdlib.h" +#ifndef __REACTOS__ +#include "vfdmsg.h" +#else +#include "vfdmsg_lib.h" +#endif +#include "vfdguirc.h" + +// +// String constants +// + +#define FALLBACK_IMAGE_FILTER \ + "Common image files (bin,dat,fdd,flp,ima,img,vfd)\0" \ + "*.bin;*.dat;*.fdd;*.flp;*.ima;*.img;*.vfd\0" \ + "Zip compressed image (imz,zip)\0*.imz;*.zip\0" \ + "All files (*.*)\0*.*\0" + +#define FALLBACK_IMAGE_TITLE "Open Virtual Floppy Image" + +// +// local functions +// +static INT CALLBACK OpenDialogProc( + HWND hDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +static void OnInit(HWND hDlg, ULONG nDevice); +static void OnImage(HWND hDlg, HWND hEdit); +static void OnBrowse(HWND hDlg); +static void OnDiskType(HWND hDlg, HWND hRadio); +static void OnMediaType(HWND hDlg, HWND hCombo); +static void OnProtect(HWND hDlg, HWND hCheck); +static DWORD OnOK(HWND hDlg); + +// +// Show Open Image dialog box +// +DWORD WINAPI VfdGuiOpen( + HWND hParent, + ULONG nDevice) +{ + switch (DialogBoxParam( + g_hDllModule, + MAKEINTRESOURCE(IDD_OPENDIALOG), + hParent, + OpenDialogProc, + nDevice)) + { + case IDOK: + return ERROR_SUCCESS; + + case IDCANCEL: + return ERROR_CANCELLED; + + default: + return GetLastError(); + } +} + +// +// Open image dialog procedure +// +INT CALLBACK OpenDialogProc( + HWND hDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch (uMsg) { + case WM_INITDIALOG: + OnInit(hDlg, lParam); + return TRUE; + + case WM_COMMAND: + switch (wParam) { + case MAKELONG(IDC_IMAGEFILE, EN_CHANGE): + OnImage(hDlg, (HWND)lParam); + return TRUE; + + case IDC_BROWSE: + OnBrowse(hDlg); + return TRUE; + + case IDC_DISKTYPE_FILE: + case IDC_DISKTYPE_RAM: + OnDiskType(hDlg, (HWND)lParam); + return TRUE; + + case MAKELONG(IDC_MEDIATYPE, CBN_SELCHANGE): + OnMediaType(hDlg, (HWND)lParam); + return TRUE; + + case IDC_OPEN_PROTECTED: + OnProtect(hDlg, (HWND)lParam); + return TRUE; + + case IDOK: + if (OnOK(hDlg) == ERROR_SUCCESS) { + EndDialog(hDlg, IDOK); + } + return TRUE; + + case IDCANCEL: + EndDialog(hDlg, IDCANCEL); + return TRUE; + } + break; + + case WM_CONTEXTMENU: + ShowContextMenu(hDlg, (HWND)wParam, lParam); + break; + + case WM_HELP: + { + LPHELPINFO info = (LPHELPINFO)lParam; + + if (info->iContextType == HELPINFO_WINDOW) { + ShowHelpWindow(hDlg, info->iCtrlId); + } + } + return TRUE; + } + + return FALSE; +} + +// +// Initialize the Open Image dialog +// +void OnInit( + HWND hDlg, + ULONG nDevice) +{ + VFD_MEDIA i; + + // Store the device number + + SetWindowLong(hDlg, GWL_USERDATA, nDevice); + + // Store default file size + + SetWindowLong(hDlg, DWL_USER, INVALID_FILE_SIZE); + + // Set dialog window title + + SetControlText(hDlg, 0, MSG_OPEN_TITLE); + + // Set control captions + + SetControlText(hDlg, IDC_IMAGEFILE_LABEL, MSG_IMAGEFILE_ACCEL); + SetControlText(hDlg, IDC_IMAGEDESC_LABEL, MSG_DESCRIPTION_LABEL); + SetControlText(hDlg, IDC_BROWSE, MSG_BROWSE_BUTTON); + SetControlText(hDlg, IDC_DISKTYPE_LABEL, MSG_DISKTYPE_LABEL); + SetControlText(hDlg, IDC_MEDIATYPE_LABEL, MSG_MEDIATYPE_ACCEL); + SetControlText(hDlg, IDC_OPEN_PROTECTED, MSG_MENU_PROTECT); + SetControlText(hDlg, IDOK, MSG_CREATE_BUTTON); + SetControlText(hDlg, IDCANCEL, MSG_CANCEL_BUTTON); + + // select RAM disk as default + + CheckRadioButton(hDlg, IDC_DISKTYPE_FILE, + IDC_DISKTYPE_RAM, IDC_DISKTYPE_RAM); + + // setup media type combo list + + for (i = 1; i < VFD_MEDIA_MAX; i++) { + SendDlgItemMessage(hDlg, IDC_MEDIATYPE, + CB_ADDSTRING, 0, (LPARAM)VfdMediaTypeName(i)); + } + + // select 1.44MB as the default + + SendDlgItemMessage(hDlg, IDC_MEDIATYPE, CB_SELECTSTRING, + (WPARAM)-1, (LPARAM)VfdMediaTypeName(VFD_MEDIA_F3_1P4)); + + // set up other controls + + OnImage(hDlg, GetDlgItem(hDlg, IDC_IMAGEFILE)); +} + +// +// Path is changed -- check if the file exists +// +void OnImage( + HWND hDlg, + HWND hEdit) +{ + CHAR buf[MAX_PATH]; + DWORD file_attr; + ULONG image_size; + VFD_FILETYPE file_type; + VFD_MEDIA media_type; + + DWORD ret = ERROR_SUCCESS; + + // Store default file size + + SetWindowLong(hDlg, DWL_USER, INVALID_FILE_SIZE); + + // get currently selected media type + + media_type = (VFD_MEDIA)(SendDlgItemMessage( + hDlg, IDC_MEDIATYPE, CB_GETCURSEL, 0, 0) + 1); + + // clear hint and description text + + SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, NULL); + SetDlgItemText(hDlg, IDC_IMAGEFILE_HINT, NULL); + + // get file name and file information + + if (GetWindowText(hEdit, buf, sizeof(buf))) { + + ret = VfdCheckImageFile( + buf, &file_attr, &file_type, &image_size); + + if (ret == ERROR_SUCCESS) { + + // use media type from image size + + media_type = VfdLookupMedia(image_size); + } + else if (ret == ERROR_FILE_NOT_FOUND) { + + // new file + // use the parent directory attributes + + PSTR p; + + if ((p = strrchr(buf, '\\')) != NULL) { + *p = '\0'; + } + + file_attr = GetFileAttributes(buf); + + if (file_attr == INVALID_FILE_ATTRIBUTES) { + // directory access error + EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); + SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, SystemMessage(ret)); + return; + } + + file_attr &= ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY); + image_size = INVALID_FILE_SIZE; + file_type = VFD_FILETYPE_RAW; + } + else { + // file access error + EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); + SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, SystemMessage(ret)); + return; + } + + // make file description text + + VfdMakeFileDesc(buf, sizeof(buf), + file_type, image_size, file_attr); + + // set file description + + SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, buf); + } + else { + + // filename is empty - RAM disk + + file_attr = 0; + image_size = INVALID_FILE_SIZE; + file_type = VFD_FILETYPE_NONE; + + SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, "RAM"); + } + + // store the image size + + SetWindowLong(hDlg, DWL_USER, image_size); + + // setup disktype controls + + if (file_type != VFD_FILETYPE_RAW || + (file_attr & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_ENCRYPTED))) { + + // file cannot be opened directly -- RAM mode is forced + + CheckRadioButton(hDlg, IDC_DISKTYPE_FILE, + IDC_DISKTYPE_RAM, IDC_DISKTYPE_RAM); + + EnableWindow(GetDlgItem(hDlg, IDC_DISKTYPE_FILE), FALSE); + } + else { + EnableWindow(GetDlgItem(hDlg, IDC_DISKTYPE_FILE), TRUE); + } + + // set OK button text + + if (image_size == INVALID_FILE_SIZE) { + // file does not exist - OK button is "Create" + + SetControlText(hDlg, IDOK, MSG_CREATE_BUTTON); + } + else { + // file exists - OK button is "Open" + + SetControlText(hDlg, IDOK, MSG_OPEN_BUTTON); + } + + // select media type + + SendDlgItemMessage(hDlg, IDC_MEDIATYPE, + CB_SETCURSEL, media_type - 1, 0); + + OnMediaType(hDlg, GetDlgItem(hDlg, IDC_MEDIATYPE)); +} + +// +// Show open file dialog box +// +void OnBrowse( + HWND hDlg) +{ + OPENFILENAME ofn; + PSTR title; + PSTR filter; + CHAR file[MAX_PATH]; + CHAR dir[MAX_PATH]; + DWORD len; + + // prepare title and filter text + + title = ModuleMessage(MSG_OPEN_TITLE); + + filter = ModuleMessage(MSG_OPEN_FILTER); + + if (filter) { + PSTR p = filter; + + do { + if (*p == '|') { + *p = '\0'; + } + } + while (*(++p)); + } + + // get current file name from the control + + ZeroMemory(file, sizeof(file)); + ZeroMemory(dir, sizeof(dir)); + + len = GetDlgItemText(hDlg, IDC_IMAGEFILE, file, sizeof(file)); + + if (len && file[len - 1] == '\\') { + strcpy(dir, file); + ZeroMemory(file, sizeof(file)); + } + + // prepare OPENFILENAME structure + + ZeroMemory(&ofn, sizeof(ofn)); + + ofn.lStructSize = IS_WINDOWS_NT() ? + OPENFILENAME_SIZE_VERSION_400 : sizeof(ofn); + + ofn.hwndOwner = hDlg; + ofn.lpstrFilter = filter ? filter : FALLBACK_IMAGE_FILTER; + ofn.lpstrFile = file; + ofn.nMaxFile = sizeof(file); + ofn.lpstrInitialDir = dir; + ofn.lpstrTitle = title ? title : FALLBACK_IMAGE_TITLE; + ofn.Flags = OFN_ENABLESIZING | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST; + + // show the open file dialog box + + if (GetOpenFileName(&ofn)) { + SetDlgItemText(hDlg, IDC_IMAGEFILE, file); + SetFocus(GetDlgItem(hDlg, IDC_IMAGEFILE)); + } + + // release text buffers + + if (filter) { + LocalFree(filter); + } + + if (title) { + LocalFree(title); + } +} + +// +// Disk type is changed +// +void OnDiskType( + HWND hDlg, + HWND hRadio) +{ + UNREFERENCED_PARAMETER(hDlg); + UNREFERENCED_PARAMETER(hRadio); +} + +// +// Media type is changed +// +void OnMediaType( + HWND hDlg, + HWND hCombo) +{ + VFD_MEDIA media_type; + ULONG media_size; + ULONG image_size; + + image_size = GetWindowLong(hDlg, DWL_USER); + + if (image_size == INVALID_FILE_SIZE) { + return; + } + + media_type = (VFD_MEDIA)(SendMessage( + hCombo, CB_GETCURSEL, 0, 0) + 1); + + if (media_type == 0) { + return; + } + + media_size = VfdGetMediaSize(media_type); + + if (media_size > image_size) { + // selected media is too large + SetControlText(hDlg, IDC_IMAGEFILE_HINT, MSG_FILE_TOO_SMALL); + EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); + return; + } + else if (media_size < image_size) { + SetControlText(hDlg, IDC_IMAGEFILE_HINT, MSG_SIZE_MISMATCH); + } + else { + SetDlgItemText(hDlg, IDC_IMAGEFILE_HINT, NULL); + } + + EnableWindow(GetDlgItem(hDlg, IDOK), TRUE); +} + +// +// Write Protect check box is clicked +// +void OnProtect( + HWND hDlg, + HWND hCheck) +{ + UNREFERENCED_PARAMETER(hDlg); + UNREFERENCED_PARAMETER(hCheck); +} + +// +// Create / open an image +// +DWORD OnOK( + HWND hDlg) +{ + CHAR file_name[MAX_PATH]; + VFD_DISKTYPE disk_type; + VFD_MEDIA media_type; + VFD_FLAGS image_flags; + HANDLE hDevice; + DWORD ret; + + // get the disk type + + if (IsDlgButtonChecked(hDlg, IDC_DISKTYPE_FILE) == BST_CHECKED) { + disk_type = VFD_DISKTYPE_FILE; + } + else { + disk_type = VFD_DISKTYPE_RAM; + } + + // get the media type + + media_type = (VFD_MEDIA)(SendDlgItemMessage( + hDlg, IDC_MEDIATYPE, CB_GETCURSEL, 0, 0) + 1); + + // get the protect flag + + if (IsDlgButtonChecked(hDlg, IDC_OPEN_PROTECTED) == BST_CHECKED) { + image_flags = VFD_FLAG_WRITE_PROTECTED; + } + else { + image_flags = 0; + } + + // get the image name to create + + if (GetDlgItemText(hDlg, IDC_IMAGEFILE, file_name, sizeof(file_name))) { + + // file is specified + + if (GetWindowLong(hDlg, DWL_USER) == INVALID_FILE_SIZE) { + + // create a new image + + ret = VfdCreateImageFile( + file_name, media_type, VFD_FILETYPE_RAW, FALSE); + + if (ret != ERROR_SUCCESS) { + goto exit_func; + } + } + } + + // open the image + + hDevice = VfdOpenDevice(GetWindowLong(hDlg, GWL_USERDATA)); + + if (hDevice == INVALID_HANDLE_VALUE) { + ret = GetLastError(); + goto exit_func; + } + + ret = VfdOpenImage( + hDevice, file_name, disk_type, media_type, image_flags); + + CloseHandle(hDevice); + +exit_func: + if (ret != ERROR_SUCCESS) { + + // show error message + + MessageBox(hDlg, SystemMessage(ret), + VFD_MSGBOX_TITLE, MB_ICONSTOP); + } + + return ret; +} diff --git a/modules/rosapps/lib/vfdlib/vfdguirc.h b/modules/rosapps/lib/vfdlib/vfdguirc.h new file mode 100644 index 00000000000..10bd1218311 --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdguirc.h @@ -0,0 +1,47 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by vfdlib.rc +// +#define IDD_PROPDIALOG 101 +#define IDD_OPENDIALOG 102 +#define IDD_SAVEDIALOG 103 +#define IDI_VFD_ICON 104 +#define IDI_IMAGE_ICON 105 +#define IDI_CONFIG_ICON 106 +#define IDC_PROPERTY_TITLE 1001 +#define IDC_COPYRIGHT_STR 1002 +#define IDC_IMAGEFILE_LABEL 1003 +#define IDC_IMAGEFILE 1004 +#define IDC_IMAGEDESC_LABEL 1005 +#define IDC_IMAGEFILE_DESC 1006 +#define IDC_IMAGEFILE_HINT 1007 +#define IDC_TARGETFILE_LABEL 1008 +#define IDC_TARGETFILE 1009 +#define IDC_DISKTYPE_LABEL 1010 +#define IDC_DISKTYPE 1011 +#define IDC_DISKTYPE_FILE 1012 +#define IDC_DISKTYPE_RAM 1013 +#define IDC_MEDIATYPE_LABEL 1014 +#define IDC_MEDIATYPE 1015 +#define IDC_WRITE_PROTECTED 1016 +#define IDC_OPEN_PROTECTED 1017 +#define IDC_BROWSE 1018 +#define IDC_OPEN 1019 +#define IDC_SAVE 1020 +#define IDC_CLOSE 1021 +#define IDC_FORMAT 1022 +#define IDC_CONTROL 1023 +#define IDC_OVERWRITE 1024 +#define IDC_TRUNCATE 1025 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 107 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1025 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/modules/rosapps/lib/vfdlib/vfdguisave.c b/modules/rosapps/lib/vfdlib/vfdguisave.c new file mode 100644 index 00000000000..ffaf4e329fe --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdguisave.c @@ -0,0 +1,529 @@ +/* + vfdguisave.c + + Virtual Floppy Drive for Windows + Driver control library + Save image GUI utility function + + Copyright (c) 2003-2005 Ken Kato +*/ + +#ifdef __cplusplus +#pragma message(__FILE__": Compiled as C++ for testing purpose.") +#endif // __cplusplus + +#define WIN32_LEAN_AND_MEAN +#include +#ifdef _MSC_VER +#pragma warning(push,3) +#endif +#include +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include "vfdtypes.h" +#include "vfdapi.h" +#include "vfdlib.h" +#ifndef __REACTOS__ +#include "vfdmsg.h" +#else +#include "vfdmsg_lib.h" +#endif +#include "vfdguirc.h" + +// +// local functions +// +static INT CALLBACK SaveDialogProc( + HWND hDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam); + +static void OnInit(HWND hDlg, PCSAVE_PARAM pParam); +static void OnTarget(HWND hDlg, HWND hEdit); +static void OnBrowse(HWND hDlg); +static void OnOverwrite(HWND hDlg, HWND hCheck); +static void OnTruncate(HWND hDlg, HWND hCheck); +static DWORD OnOK(HWND hDlg); + +// +// Show Save Image dialog box +// +DWORD WINAPI VfdGuiSave( + HWND hParent, + ULONG nDevice) +{ + SAVE_PARAM param; + CHAR path[MAX_PATH]; + DWORD ret; + + // open the source device + + param.hDevice = VfdOpenDevice(nDevice); + + if (param.hDevice == INVALID_HANDLE_VALUE) { + return GetLastError(); + } + + // get current image information + + param.ImageName = path; + + ret = VfdGetImageInfo( + param.hDevice, + param.ImageName, + ¶m.DiskType, + ¶m.MediaType, + ¶m.MediaFlags, + ¶m.FileType, + ¶m.ImageSize); + + if (ret == ERROR_SUCCESS) { + + // show dialog box + + ret = GuiSaveParam(hParent, ¶m); + } + + // close the source device + + CloseHandle(param.hDevice); + + return ret; +} + +DWORD GuiSaveParam( + HWND hParent, + PCSAVE_PARAM pParam) +{ + switch (DialogBoxParam( + g_hDllModule, + MAKEINTRESOURCE(IDD_SAVEDIALOG), + hParent, + SaveDialogProc, + (LPARAM)pParam)) + { + case IDOK: + return ERROR_SUCCESS; + + case IDCANCEL: + return ERROR_CANCELLED; + + default: + return GetLastError(); + } +} + +// +// The dialog procedure +// +INT CALLBACK SaveDialogProc( + HWND hDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch (uMsg) { + case WM_INITDIALOG: + OnInit(hDlg, (PCSAVE_PARAM)lParam); + return TRUE; + + case WM_COMMAND: + switch (wParam) { + case MAKELONG(IDC_TARGETFILE, EN_CHANGE): + OnTarget(hDlg, (HWND)lParam); + return TRUE; + + case IDC_BROWSE: + OnBrowse(hDlg); + return TRUE; + + case IDC_OVERWRITE: + OnOverwrite(hDlg, (HWND)lParam); + return TRUE; + + case IDC_TRUNCATE: + OnTruncate(hDlg, (HWND)lParam); + return TRUE; + + case IDOK: + if (OnOK(hDlg) == ERROR_SUCCESS) { + EndDialog(hDlg, IDOK); + } + return TRUE; + + case IDCANCEL: + EndDialog(hDlg, IDCANCEL); + return TRUE; + } + break; + + case WM_CONTEXTMENU: + ShowContextMenu(hDlg, (HWND)wParam, lParam); + break; + + case WM_HELP: + { + LPHELPINFO info = (LPHELPINFO)lParam; + + if (info->iContextType == HELPINFO_WINDOW) { + ShowHelpWindow(hDlg, info->iCtrlId); + } + } + return TRUE; + } + + return FALSE; +} + +// +// Initialize the dialog +// +void OnInit( + HWND hDlg, + PCSAVE_PARAM pParam) +{ + // Store parameters + + SetWindowLong(hDlg, GWL_USERDATA, (ULONG)pParam); + + // clear the target existence flag + + SetWindowLong(hDlg, DWL_USER, 0); + + // Set dialog window title + + SetControlText(hDlg, 0, MSG_SAVE_TITLE); + + // Set control captions + + SetControlText(hDlg, IDC_IMAGEFILE_LABEL, MSG_IMAGEFILE_LABEL); + SetControlText(hDlg, IDC_DISKTYPE_LABEL, MSG_DISKTYPE_LABEL); + SetControlText(hDlg, IDC_MEDIATYPE_LABEL, MSG_MEDIATYPE_LABEL); + SetControlText(hDlg, IDC_TARGETFILE_LABEL, MSG_TARGETFILE_LABEL); + SetControlText(hDlg, IDC_IMAGEDESC_LABEL, MSG_DESCRIPTION_LABEL); + SetControlText(hDlg, IDC_BROWSE, MSG_BROWSE_BUTTON); + SetControlText(hDlg, IDC_OVERWRITE, MSG_OVERWRITE_CHECK); + SetControlText(hDlg, IDC_TRUNCATE, MSG_TRUNCATE_CHECK); + SetControlText(hDlg, IDOK, MSG_SAVE_BUTTON); + SetControlText(hDlg, IDCANCEL, MSG_CANCEL_BUTTON); + + // set disk type + + if (pParam->DiskType == VFD_DISKTYPE_FILE) { + SetDlgItemText(hDlg, IDC_DISKTYPE, "FILE"); + } + else { + SetDlgItemText(hDlg, IDC_DISKTYPE, "RAM"); + } + + // display media type + + SetDlgItemText(hDlg, IDC_MEDIATYPE, + VfdMediaTypeName(pParam->MediaType)); + + // set current image and initial target + + if (pParam->ImageName[0]) { + SetDlgItemText(hDlg, IDC_IMAGEFILE, pParam->ImageName); + SetDlgItemText(hDlg, IDC_TARGETFILE, pParam->ImageName); + } + else if (pParam->DiskType != VFD_DISKTYPE_FILE) { + SetDlgItemText(hDlg, IDC_IMAGEFILE, ""); + OnTarget(hDlg, GetDlgItem(hDlg, IDC_TARGETFILE)); + } +} + +// +// Path is changed -- check specified target file +// +void OnTarget( + HWND hDlg, + HWND hEdit) +{ + PCSAVE_PARAM param; + CHAR buf[MAX_PATH]; + ULONG file_size; + VFD_FILETYPE file_type; + DWORD file_attr; + DWORD ret; + + // clear the target existence flag + + SetWindowLong(hDlg, DWL_USER, 0); + + // clear the description and hint text + + SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, NULL); + SetDlgItemText(hDlg, IDC_IMAGEFILE_HINT, NULL); + + // get the target file name + + if (GetWindowText(hEdit, buf, sizeof(buf)) == 0) { + + // target file is blank + + EnableWindow(GetDlgItem(hDlg, IDC_OVERWRITE), FALSE); + EnableWindow(GetDlgItem(hDlg, IDC_TRUNCATE), FALSE); + EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); + + return; + } + else { + CHAR full[MAX_PATH]; + PSTR file; + + // convert into a full path + + if (GetFullPathName(buf, sizeof(full), full, &file)) { + strcpy(buf, full); + } + } + + // + // get the current image info + // + param = (PCSAVE_PARAM)GetWindowLong(hDlg, GWL_USERDATA); + + if (_stricmp(param->ImageName, buf) == 0) { + + // target is the current file + + char desc[MAX_PATH]; + + VfdMakeFileDesc(desc, sizeof(desc), + param->FileType, param->ImageSize, + GetFileAttributes(param->ImageName)); + + SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, desc); + SetControlText(hDlg, IDC_IMAGEFILE_HINT, MSG_CURRENT_FILE); + + if (param->DiskType == VFD_DISKTYPE_FILE) { + + // cannot overwrite the current FILE disk image + + EnableWindow(GetDlgItem(hDlg, IDC_OVERWRITE), FALSE); + EnableWindow(GetDlgItem(hDlg, IDC_TRUNCATE), FALSE); + EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); + return; + } + } + + // + // check target image file + // + ret = VfdCheckImageFile( + buf, &file_attr, &file_type, &file_size); + + if (ret == ERROR_FILE_NOT_FOUND) { + // file does not exist + SetControlText(hDlg, IDC_IMAGEFILE_DESC, MSG_DESC_NEW_FILE); + EnableWindow(GetDlgItem(hDlg, IDC_OVERWRITE), FALSE); + EnableWindow(GetDlgItem(hDlg, IDC_TRUNCATE), FALSE); + EnableWindow(GetDlgItem(hDlg, IDOK), TRUE); + return; + } + else if (ret != ERROR_SUCCESS) { + SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, SystemMessage(ret)); + EnableWindow(GetDlgItem(hDlg, IDC_OVERWRITE), FALSE); + EnableWindow(GetDlgItem(hDlg, IDC_TRUNCATE), FALSE); + EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); + return; + } + + // set target file description + + VfdMakeFileDesc(buf, sizeof(buf), + file_type, file_size, file_attr); + + SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, buf); + + // check target file type + + if (file_type == VFD_FILETYPE_ZIP) { + SetControlText(hDlg, IDC_IMAGEFILE_HINT, MSG_TARGET_IS_ZIP); + EnableWindow(GetDlgItem(hDlg, IDC_OVERWRITE), FALSE); + EnableWindow(GetDlgItem(hDlg, IDC_TRUNCATE), FALSE); + EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); + return; + } + + // the target is an existing raw file + + EnableWindow(GetDlgItem(hDlg, IDC_OVERWRITE), TRUE); + + // set truncate box + + if (file_size > VfdGetMediaSize(param->MediaType)) { + EnableWindow(GetDlgItem(hDlg, IDC_TRUNCATE), TRUE); + SetControlText(hDlg, IDC_IMAGEFILE_HINT, MSG_SIZE_MISMATCH); + } + else { + EnableWindow(GetDlgItem(hDlg, IDC_TRUNCATE), FALSE); + } + + // check overwrite setting + + if (IsDlgButtonChecked(hDlg, IDC_OVERWRITE) != BST_CHECKED) { + EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); + } + else { + EnableWindow(GetDlgItem(hDlg, IDOK), TRUE); + } + + // target file exists and overwritable + + SetWindowLong(hDlg, DWL_USER, 1); +} + + +// +// Show save file dialog box +// +void OnBrowse( + HWND hDlg) +{ + OPENFILENAME ofn; + PSTR title; + CHAR file[MAX_PATH]; + CHAR dir[MAX_PATH]; + DWORD len; + + title = ModuleMessage(MSG_SAVE_TITLE); + + ZeroMemory(&ofn, sizeof(ofn)); + ZeroMemory(file, sizeof(file)); + ZeroMemory(dir, sizeof(dir)); + + len = GetDlgItemText(hDlg, IDC_TARGETFILE, file, sizeof(file)); + + if (len && file[len - 1] == '\\') { + strcpy(dir, file); + ZeroMemory(file, sizeof(file)); + } + + // Different structure sizes must be used for NT and 2K/XP + ofn.lStructSize = IS_WINDOWS_NT() ? + OPENFILENAME_SIZE_VERSION_400 : sizeof(ofn); + + ofn.hwndOwner = hDlg; + ofn.lpstrFile = file; + ofn.nMaxFile = sizeof(file); + ofn.lpstrInitialDir = dir; + ofn.lpstrTitle = title ? title : "Save Image"; + ofn.lpstrFilter = "*.*\0*.*\0"; + ofn.Flags = OFN_ENABLESIZING | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST; + + if (GetSaveFileName(&ofn)) { + SetDlgItemText(hDlg, IDC_TARGETFILE, file); + SetFocus(GetDlgItem(hDlg, IDC_TARGETFILE)); + } + + if (title) { + LocalFree(title); + } +} + +void OnOverwrite( + HWND hDlg, + HWND hCheck) +{ + if (GetWindowLong(hDlg, DWL_USER)) { + // the target file exists and overwritable + if (SendMessage(hCheck, BM_GETCHECK, 0, 0) != BST_CHECKED) { + EnableWindow(GetDlgItem(hDlg, IDOK), FALSE); + } + else { + EnableWindow(GetDlgItem(hDlg, IDOK), TRUE); + } + } +} + +void OnTruncate( + HWND hDlg, + HWND hCheck) +{ + UNREFERENCED_PARAMETER(hDlg); + UNREFERENCED_PARAMETER(hCheck); +} + +// +// Save image +// +DWORD OnOK( + HWND hDlg) +{ + PCSAVE_PARAM param; + CHAR path[MAX_PATH]; + BOOL overwrite; + BOOL truncate; + DWORD ret; + + param = (PCSAVE_PARAM)GetWindowLong(hDlg, GWL_USERDATA); + + if (!param) { + return ERROR_INVALID_FUNCTION; + } + + // get the target image name + + if (GetDlgItemText(hDlg, IDC_TARGETFILE, path, sizeof(path)) == 0) { + return ERROR_INVALID_FUNCTION; + } + + if (GetWindowLong(hDlg, DWL_USER)) { + // the target file exists and overwritable + overwrite = (IsDlgButtonChecked(hDlg, IDC_OVERWRITE) == BST_CHECKED); + truncate = (IsDlgButtonChecked(hDlg, IDC_TRUNCATE) == BST_CHECKED); + } + else { + overwrite = FALSE; + truncate = TRUE; + } + +retry: + ret = VfdDismountVolume(param->hDevice, FALSE); + + if (ret == ERROR_ACCESS_DENIED) { + PSTR msg = ModuleMessage(MSG_UNMOUNT_CONFIRM); + + int reply = MessageBox( + hDlg, msg ? msg : "retry", VFD_MSGBOX_TITLE, + MB_ICONEXCLAMATION | MB_CANCELTRYCONTINUE); + + if (msg) { + LocalFree(msg); + } + + if (reply == IDRETRY) { + goto retry; + } + else if (reply == IDCANCEL) { + return ERROR_CANCELLED; + } + else { + VfdDismountVolume(param->hDevice, TRUE); + } + } + else if (ret != ERROR_SUCCESS) { + + MessageBox(hDlg, SystemMessage(ret), + VFD_MSGBOX_TITLE, MB_ICONSTOP); + + return ret; + } + + ret = VfdSaveImage(param->hDevice, path, overwrite, truncate); + + if (ret != ERROR_SUCCESS) { + + // show error message + + MessageBox(hDlg, SystemMessage(ret), + VFD_MSGBOX_TITLE, MB_ICONSTOP); + } + + return ret; +} diff --git a/modules/rosapps/lib/vfdlib/vfdguitip.c b/modules/rosapps/lib/vfdlib/vfdguitip.c new file mode 100644 index 00000000000..a8bbb8586e5 --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdguitip.c @@ -0,0 +1,354 @@ +/* + vfdguitip.c + + Virtual Floppy Drive for Windows + Driver control library + tooltip information GUI utility functions + + Copyright (c) 2003-2005 Ken Kato +*/ + +#ifdef __cplusplus +#pragma message(__FILE__": Compiled as C++ for testing purpose.") +#endif // __cplusplus + +#define WIN32_LEAN_AND_MEAN +#include + +#include "vfdtypes.h" +#include "vfdapi.h" +#include "vfdlib.h" +#ifndef __REACTOS__ +#include "vfdmsg.h" +#else +#include "vfdmsg_lib.h" +#endif + +// +// tooltip window class name +// +#define VFD_INFOTIP_WNDCLASS "VfdInfoTip" + +// +// the window procedure +// +static LRESULT CALLBACK ToolTipProc( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam) +{ + switch (uMsg) { + case WM_CREATE: + // Store Font handle + SetWindowLong(hWnd, GWL_USERDATA, + (LONG)((LPCREATESTRUCT)lParam)->lpCreateParams); + return 0; + + case WM_PAINT: + { + PAINTSTRUCT paint; + HDC hDC = BeginPaint(hWnd, &paint); + + if (hDC) { + char text[MAX_PATH]; + int len; + RECT rc; + + + SelectObject(hDC, (HFONT)GetWindowLong(hWnd, GWL_USERDATA)); + + SetTextColor(hDC, GetSysColor(COLOR_INFOTEXT)); + SetBkMode(hDC, TRANSPARENT); + + len = GetWindowText(hWnd, text, sizeof(text)); + + rc.top = 8; + rc.left = 8; + rc.right = paint.rcPaint.right; + rc.bottom = paint.rcPaint.bottom; + + DrawText(hDC, text, len, &rc, DT_LEFT | DT_TOP); + + EndPaint(hWnd, &paint); + } + } + return 0; + + case WM_KILLFOCUS: + if (!(GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_TOPMOST)) { + // Stick tool tip - Closed on kill focus + DestroyWindow(hWnd); + } + return 0; + + case WM_SETCURSOR: + if (GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_TOPMOST) { + // Non-stick tool tip - Closed when cursor leaves + TRACKMOUSEEVENT track; + + track.cbSize = sizeof(track); + track.dwFlags = TME_LEAVE; + track.hwndTrack = hWnd; + track.dwHoverTime = 0; + + TrackMouseEvent(&track); + } + return 0; + + case WM_MOUSELEAVE: + // Non-stick tool tip - Closed when cursor leaves + DestroyWindow(hWnd); + return 0; + + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + // Both stick and non-stick tool tip + // Closed when clicked + SetCapture(hWnd); + return 0; + + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + // Both stick and non-stick tool tip + // Closed when clicked + if (GetCapture() == hWnd) { + DestroyWindow(hWnd); + } + return 0; + + case WM_DESTROY: + // delete font + DeleteObject((HFONT)GetWindowLong(hWnd, GWL_USERDATA)); + return 0; + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + +// +// Create and show tooltip window +// +void WINAPI VfdToolTip( + HWND hParent, + PCSTR sText, + int pos_x, + int pos_y, + BOOL stick) +{ +#ifndef __REACTOS__ + HWND hWnd; +#endif + WNDCLASS wc = {0}; + LOGFONT lf; + HFONT font; + HDC dc; + int len; + SIZE sz; + RECT rc; + int scr_x; + int scr_y; + + // + // Register Window Class + // + + wc.lpfnWndProc = ToolTipProc; + wc.hInstance = g_hDllModule; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_INFOBK + 1); + wc.lpszClassName = VFD_INFOTIP_WNDCLASS; + + RegisterClass(&wc); + + // + // Create Tool Tip Font (== Icon title font) + // + + SystemParametersInfo( + SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, 0); + + font = CreateFontIndirect(&lf); + + // + // Calculate Tool Tip Window size + // + + dc = GetDC(hParent); + + SelectObject(dc, font); + + len = strlen(sText); + + GetTextExtentPoint32(dc, sText, len, &sz); + + rc.left = 0; + rc.top = 0; + rc.right = sz.cx; + rc.bottom = sz.cy; + + DrawText(dc, sText, len, &rc, DT_CALCRECT | DT_LEFT | DT_TOP); + + ReleaseDC(hParent, dc); + + sz.cx = rc.right - rc.left + 16; + sz.cy = rc.bottom - rc.top + 16; + + // + // Decide the window position + // + if (pos_x == -1 || pos_y == -1) { + // + // Use current cursor position + // + POINT pt; + + GetCursorPos(&pt); + + pos_x = pt.x - (sz.cx / 2); + pos_y = pt.y - (sz.cy / 2); + } + else { + pos_x = pos_x - (sz.cx / 2); + } + + // + // make sure the tip window fits in visible area + // + scr_x = GetSystemMetrics(SM_CXSCREEN); + scr_y = GetSystemMetrics(SM_CYSCREEN); + + if (pos_x < 0) { + pos_x = 0; + } + if (pos_x + sz.cx > scr_x) { + pos_x = scr_x - sz.cx; + } + if (pos_y < 0) { + pos_y = 0; + } + if (pos_y + sz.cy > scr_y) { + pos_y = scr_y - sz.cy; + } + + // + // Create the tool tip window + // +#ifndef __REACTOS__ + hWnd = CreateWindowEx( +#else + CreateWindowEx( +#endif + stick ? 0 : WS_EX_TOPMOST, + VFD_INFOTIP_WNDCLASS, + sText, + WS_BORDER | WS_POPUP | WS_VISIBLE, + pos_x, pos_y, + sz.cx, sz.cy, + hParent, + NULL, + NULL, + (PVOID)font); + + // + // Give focus if it is not a stick tool-tip + // + if (!stick) { + SetFocus(hParent); + } +} + +// +// Show an image information tooltip +// +void WINAPI VfdImageTip( + HWND hParent, + ULONG nDevice) +{ + HANDLE hDevice; + PSTR info_str = NULL; + PSTR type_str = NULL; + PSTR prot_str = NULL; + PCSTR media_str = NULL; + CHAR path[MAX_PATH]; + CHAR desc[MAX_PATH]; + VFD_DISKTYPE disk_type; + VFD_MEDIA media_type; + VFD_FLAGS media_flags; + VFD_FILETYPE file_type; + ULONG image_size; + DWORD file_attr; + ULONG ret; + + hDevice = VfdOpenDevice(nDevice); + + if (hDevice == INVALID_HANDLE_VALUE) { + VfdToolTip(hParent, + SystemMessage(GetLastError()), -1, -1, FALSE); + return; + } + + ret = VfdGetImageInfo( + hDevice, + path, + &disk_type, + &media_type, + &media_flags, + &file_type, + &image_size); + + CloseHandle(hDevice); + + if (ret != ERROR_SUCCESS) { + VfdToolTip(hParent, SystemMessage(ret), -1, -1, FALSE); + return; + } + + if (path[0]) { + file_attr = GetFileAttributes(path); + } + else { + if (disk_type != VFD_DISKTYPE_FILE) { + strcpy(path, ""); + } + file_attr = 0; + } + + VfdMakeFileDesc(desc, sizeof(desc), + file_type, image_size, file_attr); + + if (disk_type == VFD_DISKTYPE_FILE) { + type_str = "FILE"; + } + else { + type_str = "RAM"; + } + + media_str = VfdMediaTypeName(media_type); + + if (media_flags & VFD_FLAG_WRITE_PROTECTED) { + prot_str = ModuleMessage(MSG_WRITE_PROTECTED); + } + else { + prot_str = ModuleMessage(MSG_WRITE_ALLOWED); + } + + info_str = ModuleMessage( + MSG_IMAGE_INFOTIP, + path, + desc, + type_str ? type_str : "", + media_str ? media_str : "", + prot_str ? prot_str : ""); + + if (info_str) { + VfdToolTip(hParent, info_str, -1, -1, FALSE); + LocalFree(info_str); + } + + if (prot_str) { + LocalFree(prot_str); + } +} diff --git a/modules/rosapps/lib/vfdlib/vfdguiut.c b/modules/rosapps/lib/vfdlib/vfdguiut.c new file mode 100644 index 00000000000..12c9c11da7f --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdguiut.c @@ -0,0 +1,581 @@ +/* + vfdguiut.c + + Virtual Floppy Drive for Windows + Driver control library + open / close / format GUI utility functions + + Copyright (c) 2003-2005 Ken Kato +*/ + +#ifdef __cplusplus +#pragma message(__FILE__": Compiled as C++ for testing purpose.") +#endif // __cplusplus + +#define WIN32_LEAN_AND_MEAN +#include +#include + +#include "vfdtypes.h" +#include "vfdapi.h" +#include "vfdlib.h" +#ifndef __REACTOS__ +#include "vfdmsg.h" +#else +#include "vfdmsg_lib.h" +#endif +#include "vfdguirc.h" + +// +// message box constants added since Win2K +// + +#ifndef MB_CANCELTRYCONTINUE +#define MB_CANCELTRYCONTINUE 0x00000006L +#endif + +#ifndef IDTRYAGAIN +#define IDTRYAGAIN 10 +#endif + +#ifndef IDCONTINUE +#define IDCONTINUE 11 +#endif + +// +// local funcitons +// +static PSTR FormatSizeBytes(ULONG size, PSTR buf) +{ + ULONG comma = 1; + int len; + + while ((comma * 1000) < size) { + comma *= 1000; + } + + len = sprintf(buf, "%lu", size / comma); + + while (comma > 1) { + size %= comma; + comma /= 1000; + len += sprintf(buf + len, ",%03lu", size / comma); + } + + return buf; +} + +static PSTR FormatSizeUnits(ULONG size, PSTR buf) +{ + static const char *name[3] = { + " KB", " MB", " GB" + }; + int unit; + double dsize; + + if (size < 1000) { +#ifndef __REACTOS__ + sprintf(buf, "%u", size); +#else + sprintf(buf, "%lu", size); +#endif + return buf; + } + + dsize = size; + dsize /= 1024; + unit = 0; + + while (unit < 2 && dsize >= 1000) { + dsize /= 1000; + unit++; + } + + if (dsize < 10) { + sprintf(buf, "%3.2f%s", dsize, name[unit]); + } + else if (dsize < 100) { + sprintf(buf, "%3.1f%s", dsize, name[unit]); + } + else if (dsize < 1000) { + sprintf(buf, "%3.0f%s", dsize, name[unit]); + } + else { + FormatSizeBytes((ULONG)dsize, buf); + strcat(buf, name[unit]); + } + + return buf; +} + +// +// Close the current image +// +DWORD WINAPI VfdGuiClose( + HWND hParent, // parent window + ULONG nDevice) // device number +{ + HANDLE hDevice; + SAVE_PARAM param; + CHAR path[MAX_PATH]; + HCURSOR hourglass; + DWORD ret; + int reply; + + VFDTRACE(0, ("VfdGuiClose()\n")); + + hDevice = VfdOpenDevice(nDevice); + + if (hDevice == INVALID_HANDLE_VALUE) { + return GetLastError(); + } + + // get current image information + + ret = VfdGetImageInfo( + hDevice, + path, + ¶m.DiskType, + ¶m.MediaType, + ¶m.MediaFlags, + ¶m.FileType, + ¶m.ImageSize); + + if (ret != ERROR_SUCCESS) { + CloseHandle(hDevice); + return ret; + } + + param.hDevice = hDevice; + param.ImageName = path; + + // check if RAM image is modified + + if (param.MediaFlags & VFD_FLAG_DATA_MODIFIED) { + PSTR msg = ModuleMessage(MSG_MEDIA_MODIFIED); + + for (;;) { + reply = MessageBox(hParent, msg ? msg : "save?", + VFD_MSGBOX_TITLE, MB_ICONQUESTION | MB_YESNOCANCEL); + + if (reply != IDYES) { + break; + } + + if (GuiSaveParam(hParent, ¶m) == ERROR_SUCCESS) { + break; + } + } + + if (msg) { + LocalFree(msg); + } + + if (reply == IDCANCEL) { + CloseHandle(hDevice); + return ERROR_CANCELLED; + } + } + + // close the image + + hourglass = LoadCursor(NULL, IDC_WAIT); + + for (;;) { + + // show the hourglass cursor + + HCURSOR original = SetCursor(hourglass); + + // close the current image + + ret = VfdCloseImage(hDevice, FALSE); + + // restore the original cursor + + SetCursor(original); + + if (ret != ERROR_ACCESS_DENIED) { + // success or errors other than access denied + break; + } + + if (IS_WINDOWS_NT()) { + + // Windows NT -- cannot force close + // show retry / cancel message box + + PSTR msg = ModuleMessage(MSG_UNMOUNT_FAILED); + + reply = MessageBox( + hParent, msg ? msg : "retry", VFD_MSGBOX_TITLE, + MB_ICONEXCLAMATION | MB_RETRYCANCEL); + + if (msg) { + LocalFree(msg); + } + } + else { + + // Windows 2000 and later -- possible to force + // show cancel / retry / continue message box + + PSTR msg = ModuleMessage(MSG_UNMOUNT_CONFIRM); + + reply = MessageBox( + hParent, msg ? msg : "retry", VFD_MSGBOX_TITLE, + MB_ICONEXCLAMATION | MB_CANCELTRYCONTINUE); + + if (msg) { + LocalFree(msg); + } + + if (reply == IDCONTINUE) { + + // try forced close + + ret = VfdCloseImage(hDevice, TRUE); + } + } + + if (reply == IDCANCEL) { + ret = ERROR_CANCELLED; + break; + } + else if (reply == IDCONTINUE) { + + // try forced close + + ret = VfdCloseImage(hDevice, TRUE); + break; + } + } + + CloseHandle(hDevice); + + return ret; +} + +// +// Format the current media +// +DWORD WINAPI VfdGuiFormat( + HWND hParent, // parent window + ULONG nDevice) // device number +{ + HANDLE hDevice; + ULONG ret; + PSTR msg; + + msg = ModuleMessage(MSG_FORMAT_WARNING); + + ret = MessageBox(hParent, + msg ? msg : "Format?", + VFD_MSGBOX_TITLE, + MB_ICONEXCLAMATION | MB_OKCANCEL); + + if (msg) { + LocalFree(msg); + } + + if (ret == IDCANCEL) { + MessageBox(hParent, + SystemMessage(ERROR_CANCELLED), + VFD_MSGBOX_TITLE, MB_ICONSTOP); + + return ERROR_CANCELLED; + } + + hDevice = VfdOpenDevice(nDevice); + + if (hDevice == INVALID_HANDLE_VALUE) { + ret = GetLastError(); + } + else { + HCURSOR original; + +retry: + original = SetCursor(LoadCursor(NULL, IDC_WAIT)); + + ret = VfdDismountVolume(hDevice, FALSE); + + if (ret == ERROR_ACCESS_DENIED) { + PSTR msg; + int reply; + + SetCursor(original); + + msg = ModuleMessage(MSG_UNMOUNT_CONFIRM); + + reply = MessageBox( + hParent, msg ? msg : "retry", VFD_MSGBOX_TITLE, + MB_ICONEXCLAMATION | MB_CANCELTRYCONTINUE); + + if (msg) { + LocalFree(msg); + } + + if (reply == IDRETRY) { + goto retry; + } + else if (reply == IDCANCEL) { + ret = ERROR_CANCELLED; + } + else { + VfdDismountVolume(hDevice, TRUE); + ret = ERROR_SUCCESS; + } + } + + if (ret == ERROR_SUCCESS) { + ret = VfdFormatMedia(hDevice); + } + + SetCursor(original); + + CloseHandle(hDevice); + } + + MessageBox(hParent, + SystemMessage(ret), + VFD_MSGBOX_TITLE, + ret == ERROR_SUCCESS ? MB_ICONINFORMATION : MB_ICONSTOP); + + return ret; +} + +// +// Set a text to a dialog control +// +void SetControlText( + HWND hWnd, + UINT nCtrl, + DWORD nMsg) +{ + PSTR p = NULL; + + if (nMsg) { + p = ModuleMessage(nMsg); + } + + if (nCtrl) { + SetDlgItemText(hWnd, nCtrl, p); + } + else { + SetWindowText(hWnd, p); + } + + if (p) { + LocalFree(p); + } +} + +// +// Make file description text +// +void WINAPI VfdMakeFileDesc( + PSTR pBuffer, + ULONG nBufSize, + VFD_FILETYPE nFileType, + ULONG nFileSize, + DWORD nFileAttr) +{ + PSTR type_str; + PSTR size_str; + PSTR attr_ro; + PSTR attr_enc; + PSTR attr_cmp; + + ZeroMemory(pBuffer, nBufSize); + + switch (nFileType) { + case VFD_FILETYPE_RAW: + type_str = ModuleMessage(MSG_FILETYPE_RAW); + break; + + case VFD_FILETYPE_ZIP: + type_str = ModuleMessage(MSG_FILETYPE_ZIP); + break; + + default: + type_str = NULL; + } + + if (nFileSize == INVALID_FILE_SIZE) { + size_str = ModuleMessage(MSG_DESC_NEW_FILE); + } + else { + CHAR buf[20], buf2[20]; + size_str = ModuleMessage(MSG_DESC_FILESIZE, + FormatSizeBytes(nFileSize, buf), + FormatSizeUnits(nFileSize, buf2)); + } + + attr_ro = NULL; + attr_cmp = NULL; + attr_enc = NULL; + + if (nFileAttr != INVALID_FILE_ATTRIBUTES) { + if (nFileAttr & FILE_ATTRIBUTE_READONLY) { + attr_ro = ModuleMessage(MSG_ATTR_READONLY); + } + + if (nFileAttr & FILE_ATTRIBUTE_COMPRESSED) { + attr_cmp = ModuleMessage(MSG_ATTR_COMPRESSED); + } + + if (nFileAttr & FILE_ATTRIBUTE_ENCRYPTED) { + attr_enc = ModuleMessage(MSG_ATTR_ENCRYPTED); + } + } + + _snprintf(pBuffer, nBufSize - 1, "%s %s %s %s %s", + type_str ? type_str : "", + size_str ? size_str : "", + attr_ro ? attr_ro : "", + attr_cmp ? attr_cmp : "", + attr_enc ? attr_enc : ""); + + if (type_str) { + LocalFree(type_str); + } + if (size_str) { + LocalFree(size_str); + } + if (attr_ro) { + LocalFree(attr_ro); + } + if (attr_cmp) { + LocalFree(attr_cmp); + } + if (attr_enc) { + LocalFree(attr_enc); + } +} + +void ShowContextMenu( + HWND hDlg, + HWND hCtl, + LPARAM lParam) +{ + POINT pt; + UINT id; + HMENU hMenu; + + pt.x = ((int)(short)LOWORD(lParam)); + pt.y = ((int)(short)HIWORD(lParam)); + + if (pt.x == -1 || pt.y == -1) { + RECT rc; + + GetWindowRect(hCtl, &rc); + pt.x = (rc.left + rc.right) / 2; + pt.y = (rc.top + rc.bottom) / 2; + + id = GetDlgCtrlID(hCtl); + } + else { + POINT pt2 = pt; + + ScreenToClient(hDlg, &pt2); + + id = GetDlgCtrlID( + ChildWindowFromPoint(hDlg, pt2)); + } + + if (id < IDC_IMAGEFILE_LABEL || + id > IDC_TRUNCATE) { + return; + } + + hMenu = CreatePopupMenu(); + + AppendMenu(hMenu, MF_STRING, 1, "&What's This"); + + if (TrackPopupMenu(hMenu, TPM_RETURNCMD, + pt.x, pt.y, 0, hDlg, NULL)) + { + ShowHelpWindow(hDlg, id); + } + + DestroyMenu(hMenu); +} + +// +// Show tool tip help +// +void ShowHelpWindow( + HWND hDlg, + UINT nCtl) +{ + UINT msg; + RECT rc; + PSTR help; + + switch (nCtl) { + case IDC_IMAGEFILE_LABEL: + case IDC_IMAGEFILE: + msg = MSG_HELP_IMAGEFILE; + break; + case IDC_IMAGEDESC_LABEL: + case IDC_IMAGEFILE_DESC: + msg = MSG_HELP_IMAGEDESC; + break; + case IDC_TARGETFILE_LABEL: + case IDC_TARGETFILE: + msg = MSG_HELP_TARGETFILE; + break; + case IDC_DISKTYPE_LABEL: + case IDC_DISKTYPE: + case IDC_DISKTYPE_FILE: + case IDC_DISKTYPE_RAM: + msg = MSG_HELP_DISKTYPE; + break; + case IDC_MEDIATYPE_LABEL: + case IDC_MEDIATYPE: + msg = MSG_HELP_MEDIATYPE; + break; + case IDC_WRITE_PROTECTED: + msg = MSG_HELP_PROTECT_NOW; + break; + case IDC_OPEN_PROTECTED: + msg = MSG_HELP_PROTECT_OPEN; + break; + case IDC_BROWSE: + msg = MSG_HELP_BROWSE; + break; + case IDC_OPEN: + msg = MSG_HELP_OPEN; + break; + case IDC_SAVE: + msg = MSG_HELP_SAVE; + break; + case IDC_CLOSE: + msg = MSG_HELP_CLOSE; + break; + case IDC_FORMAT: + msg = MSG_HELP_FORMAT; + break; + case IDC_CONTROL: + msg = MSG_HELP_CONTROL; + break; + case IDC_OVERWRITE: + msg = MSG_HELP_OVERWRITE; + break; + case IDC_TRUNCATE: + msg = MSG_HELP_TRUNCATE; + break; + default: + return; + } + + GetWindowRect(GetDlgItem(hDlg, nCtl), &rc); + + help = ModuleMessage(msg); + + if (help) { + VfdToolTip(hDlg, help, rc.left, (rc.top + rc.bottom) / 2, TRUE); + LocalFree(help); + } +} + diff --git a/modules/rosapps/lib/vfdlib/vfdlib.c b/modules/rosapps/lib/vfdlib/vfdlib.c new file mode 100644 index 00000000000..8529653e026 --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdlib.c @@ -0,0 +1,184 @@ +/* + vfdlib.c + + Virtual Floppy Drive for Windows + Driver control library + Miscellaneous functions + + Copyright (C) 2003-2008 Ken Kato +*/ + +#ifdef __cplusplus +#pragma message(__FILE__": Compiled as C++ for testing purpose.") +#endif // __cplusplus + +#define WIN32_LEAN_AND_MEAN +#include +#include + +#ifdef _DEBUG +#include +#endif // _DEBUG + +#include "vfdtypes.h" +#include "vfdapi.h" +#include "vfdlib.h" + +// +// DLL Global variables +// + +#ifndef __REACTOS__ +extern HINSTANCE g_hDllModule = NULL; // Handle to this DLL itself +extern UINT g_cDllRefCnt = 0; // Reference count of this DLL +extern UINT g_nNotifyMsg = 0; // VFD notification message +#else +HINSTANCE g_hDllModule = NULL; // Handle to this DLL itself +UINT g_cDllRefCnt = 0; // Reference count of this DLL +UINT g_nNotifyMsg = 0; // VFD notification message +#endif + +// +// DllMain +// +BOOL WINAPI DllMain( + HINSTANCE hInstance, + DWORD dwReason, + LPVOID lpReserved) +{ +#ifdef _DEBUG + char name[MAX_PATH]; + HMODULE hMod; + DWORD size; + + if (EnumProcessModules(GetCurrentProcess(), &hMod, sizeof(hMod), &size)) { + GetModuleBaseName(GetCurrentProcess(), hMod, name, sizeof(name)); + } + else { + strcpy(name, "unknown"); + } +#endif // _DEBUG + + UNREFERENCED_PARAMETER(lpReserved); + + if (dwReason == DLL_PROCESS_ATTACH) { + VFDTRACE(0, ("DLL_PROCESS_ATTACH - %s\n", name)); + + // this DLL doesn't need DLL_THREAD_ATTACH and DLL_THREAD_DETACH + DisableThreadLibraryCalls(hInstance); + + // store the DLL instance handle + g_hDllModule = hInstance; + + // register the VFD notification message + g_nNotifyMsg = RegisterWindowMessage(VFD_NOTIFY_MESSAGE); + + } + else if (dwReason == DLL_PROCESS_DETACH) { + VFDTRACE(0, ("DLL_PROCESS_DETACH - %s\n", name)); + } + + return TRUE; +} + +// +// Check running platform +// +BOOL WINAPI VfdIsValidPlatform() +{ + BOOL (WINAPI *pfnIsWow64Process)(HANDLE, PBOOL); + BOOL wow64; + + if (GetVersion() & 0x80000000) { + return FALSE; // doesn't work on Win9x + } + + pfnIsWow64Process = (BOOL (WINAPI *)(HANDLE, PBOOL)) + GetProcAddress(GetModuleHandle("kernel32.dll"), "IsWow64Process"); + + if (pfnIsWow64Process == NULL) { + return TRUE; // NT4 or 2000 -- assured to be 32 bit + } + + wow64 = FALSE; + + if (!pfnIsWow64Process(GetCurrentProcess(), &wow64)) { + return FALSE; + } + + return !wow64; +} + +// +// Get VFD notification message value +// +UINT WINAPI VfdGetNotifyMessage() +{ + return g_nNotifyMsg; +} + + +// +// Get message text from this DLL module +// +PSTR ModuleMessage( + DWORD nFormat, ...) +{ + PSTR p; + va_list args; + + va_start(args, nFormat); + + if (!FormatMessage( + FORMAT_MESSAGE_FROM_HMODULE | + FORMAT_MESSAGE_ALLOCATE_BUFFER, + g_hDllModule, nFormat, 0, (LPTSTR)&p, 0, &args)) { + p = NULL; + } + + va_end(args); + + return p; +} + +// +// Get system error message string +// +PCSTR SystemMessage( + DWORD nError) +{ + static CHAR msg[256]; + + if (!FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, nError, 0, msg, sizeof(msg), NULL)) { + + _snprintf(msg, sizeof(msg), + "Unknown system error %lu (0x%08x)\n", nError, nError); + } + + return msg; +} + +#ifdef _DEBUG +// +// Format and output debug string +// +void DebugTrace( + PCSTR sFormat, ...) +{ + CHAR buf[512]; + int len; + va_list args; + + len = _snprintf(buf, sizeof(buf), + "%s(%lu) : ", TraceFile, TraceLine); + + va_start(args, sFormat); + + _vsnprintf(buf + len, sizeof(buf) - len, sFormat, args); + + OutputDebugString(buf); +} +#endif // _DEBUG diff --git a/modules/rosapps/lib/vfdlib/vfdlib.h b/modules/rosapps/lib/vfdlib/vfdlib.h new file mode 100644 index 00000000000..22b59584b8a --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdlib.h @@ -0,0 +1,185 @@ +/* + vfdlib.h + + Virtual Floppy Drive for Windows + Driver control library local header + + Copyright (C) 2003-2005 Ken Kato +*/ + +#ifndef _VFDLIB_H_ +#define _VFDLIB_H_ + +#define VFD_LIBRARY_FILENAME "vfd.dll" + +#ifdef VFD_EMBED_DRIVER +#define VFD_DRIVER_NAME_ID VFD_DRIVER +#define VFD_DRIVER_TYPE_ID BINARY +#endif + +#ifndef RC_INVOKED + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// +// DLL instance handle +// +extern HINSTANCE g_hDllModule; + +// +// Reference count for the DLL +// +extern UINT g_cDllRefCnt; + +// +// VFD notification message value +// +extern UINT g_nNotifyMsg; + +// +// VFD notification message register string +// +#define VFD_NOTIFY_MESSAGE "VfdNotifyMessage" + +// +// Message box title string +// +#define VFD_MSGBOX_TITLE "Virtual Floppy Drive" + +// +// shell extention string constants +// +#define VFDEXT_DESCRIPTION "VFD shell extension" +#define VFDEXT_MENU_REGKEY "Drive\\shellex\\ContextMenuHandlers\\VFD" +#define VFDEXT_DND_REGKEY "Drive\\shellex\\DragDropHandlers\\VFD" +#define VFDEXT_PROP_REGKEY "Drive\\shellex\\PropertySheetHandlers\\VFD" +#define VFDEXT_INFO_REGKEY "Drive\\shellex\\{00021500-0000-0000-C000-000000000046}" + +//===================================== +// Image handling functions +//===================================== + +// Format a buffer with FAT12 + +DWORD FormatBufferFat( + PUCHAR pBuffer, + ULONG nSectors); + +// Extract image information from a zip compressed file + +DWORD ExtractZipInfo( + HANDLE hFile, + ULONG *pSize); + +// Extract original image from a zip compressed file + +DWORD ExtractZipImage( + HANDLE hFile, + PUCHAR *pBuffer, + PULONG pLength); + +//===================================== +// GUI utility functions +//===================================== + +typedef struct _SAVE_PARAM { + HANDLE hDevice; + VFD_DISKTYPE DiskType; + VFD_MEDIA MediaType; + VFD_FLAGS MediaFlags; + VFD_FILETYPE FileType; + ULONG ImageSize; + PSTR ImageName; +} SAVE_PARAM, PSAVE_PARAM; + +typedef const SAVE_PARAM CSAVE_PARAM, *PCSAVE_PARAM; + +DWORD GuiSaveParam( + HWND hParent, + PCSAVE_PARAM pParam); + +void ShowContextMenu( + HWND hDlg, + HWND hCtl, + LPARAM lParam); + +void ShowHelpWindow( + HWND hDlg, + UINT nCtl); + +// +// Set a message to a control window +// +void SetControlText( + HWND hWnd, + UINT nCtrl, + DWORD nMsg); + +//============================== +// Message extract functions +//============================== + +// Return a system error message + +PCSTR SystemMessage( + DWORD nError); + +// Return a message from this DLL module + +PSTR ModuleMessage( + DWORD nFormat, ...); + +//============================== +// utility macros +//============================== + +#define IS_WINDOWS_NT() ((GetVersion() & 0xff) < 5) + +//============================== +// Debug functions +//============================== + +#ifdef _DEBUG +extern ULONG TraceFlags; +#ifndef __REACTOS__ +extern PCHAR TraceFile; +#else +extern CHAR const * TraceFile; +#endif +extern ULONG TraceLine; + +#define VFDTRACE(LEVEL,STRING) \ + if ((TraceFlags & (LEVEL)) == (LEVEL)) { \ + TraceFile = __FILE__; \ + TraceLine = __LINE__; \ + DebugTrace STRING; \ + } + +void DebugTrace(PCSTR sFormat, ...); + +#else // _DEBUG +#define VFDTRACE(LEVEL,STRING) +#endif // _DEBUG + +// +// supplement old system headers +// +#ifndef INVALID_FILE_ATTRIBUTES +#define INVALID_FILE_ATTRIBUTES ((DWORD)-1) +#endif // INVALID_FILE_ATTRIBUTES + +#if defined(_INC_COMMDLG) && !defined(OPENFILENAME_SIZE_VERSION_400) +// Pre Win2K system header is used +// OPENFILENAME is defined without extra fields. +#define OPENFILENAME_SIZE_VERSION_400 sizeof(OPENFILENAME) +#endif // __INC_COMMDLG && !OPENFILENAME_SIZE_VERSION_400 + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // RC_INVOKED + +#endif // _VFDLIB_H_ diff --git a/modules/rosapps/lib/vfdlib/vfdlib.rc b/modules/rosapps/lib/vfdlib/vfdlib.rc new file mode 100644 index 00000000000..561407e5e81 --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdlib.rc @@ -0,0 +1,219 @@ +//Microsoft Developer Studio generated resource script. +// +#include "vfdguirc.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// ニュートラル resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(932) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "vfdguirc.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_OPENDIALOG DIALOGEX 0, 0, 250, 150 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CONTEXTHELP +CAPTION "Open Virtual Floppy Image" +FONT 9, "MS Shell Dlg" +BEGIN + LTEXT "&Image File:",IDC_IMAGEFILE_LABEL,7,7,52,12, + SS_CENTERIMAGE + EDITTEXT IDC_IMAGEFILE,60,7,130,12,ES_AUTOHSCROLL + PUSHBUTTON "&Browse...",IDC_BROWSE,193,7,50,14 + LTEXT "Description:",IDC_IMAGEDESC_LABEL,7,27,52,8 + EDITTEXT IDC_IMAGEFILE_DESC,60,27,183,12,ES_AUTOHSCROLL | + ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + LTEXT "additional information",IDC_IMAGEFILE_HINT,60,43,183,8 + LTEXT "Disk Type:",IDC_DISKTYPE_LABEL,7,59,52,10 + CONTROL "&FILE",IDC_DISKTYPE_FILE,"Button",BS_AUTORADIOBUTTON | + WS_GROUP | WS_TABSTOP,60,59,38,10 + CONTROL "&RAM",IDC_DISKTYPE_RAM,"Button",BS_AUTORADIOBUTTON,99, + 59,38,10 + LTEXT "&Media Type:",IDC_MEDIATYPE_LABEL,7,75,52,12, + SS_CENTERIMAGE + COMBOBOX IDC_MEDIATYPE,59,75,80,84,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + DEFPUSHBUTTON "&Open",IDOK,72,129,50,14,WS_GROUP + PUSHBUTTON "Cancel",IDCANCEL,127,129,50,14 + CONTROL "&Write Protect",IDC_OPEN_PROTECTED,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,59,95,184,10 +END + +IDD_PROPDIALOG DIALOGEX 0, 0, 226, 215 +STYLE WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTEXTHELP +FONT 9, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + ICON IDI_VFD_ICON,IDC_STATIC,7,7,20,20 + CTEXT "Virtual Floppy Drive for Windows",IDC_PROPERTY_TITLE,29, + 10,168,8,SS_CENTERIMAGE + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,32,212,1 + LTEXT "Image File:",IDC_IMAGEFILE_LABEL,7,40,50,8 + EDITTEXT IDC_IMAGEFILE,58,40,161,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_BORDER | NOT WS_TABSTOP + LTEXT "Description:",IDC_IMAGEDESC_LABEL,7,58,50,8 + EDITTEXT IDC_IMAGEFILE_DESC,58,58,161,12,ES_AUTOHSCROLL | + ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + LTEXT "Disk Type:",IDC_DISKTYPE_LABEL,7,76,50,8 + EDITTEXT IDC_DISKTYPE,58,76,161,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_BORDER | NOT WS_TABSTOP + LTEXT "Media Type:",IDC_MEDIATYPE_LABEL,7,94,50,8 + EDITTEXT IDC_MEDIATYPE,58,94,161,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_BORDER | NOT WS_TABSTOP + CONTROL "&Write Protect",IDC_WRITE_PROTECTED,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,58,112,161,8 + PUSHBUTTON "&Open",IDC_OPEN,7,127,50,14 + PUSHBUTTON "&Save",IDC_SAVE,61,127,50,14 + PUSHBUTTON "&Close",IDC_CLOSE,115,127,50,14 + PUSHBUTTON "&Format",IDC_FORMAT,169,127,50,14 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,7,148,212,1 + PUSHBUTTON "&VFD Control Panel",IDC_CONTROL,139,192,80,14 + CTEXT "Copyright (c) 2003-2008 Ken Kato",IDC_COPYRIGHT_STR,29, + 20,168,8,SS_CENTERIMAGE +END + +IDD_SAVEDIALOG DIALOGEX 0, 0, 250, 150 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CONTEXTHELP +CAPTION "Save Virtual Floppy Image" +FONT 9, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + LTEXT "Image File:",IDC_IMAGEFILE_LABEL,7,7,52,12 + EDITTEXT IDC_IMAGEFILE,60,7,183,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_BORDER | NOT WS_TABSTOP + LTEXT "Disk Type:",IDC_DISKTYPE_LABEL,7,25,52,8,SS_NOPREFIX + EDITTEXT IDC_DISKTYPE,60,25,58,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_BORDER | NOT WS_TABSTOP + LTEXT "Media Type:",IDC_MEDIATYPE_LABEL,120,25,52,8, + SS_NOPREFIX + EDITTEXT IDC_MEDIATYPE,173,25,70,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_BORDER | NOT WS_TABSTOP + LTEXT "Target &File:",IDC_TARGETFILE_LABEL,7,43,52,12, + SS_CENTERIMAGE + EDITTEXT IDC_TARGETFILE,60,43,131,12,ES_AUTOHSCROLL + PUSHBUTTON "&Browse...",IDC_BROWSE,193,43,50,14 + LTEXT "Description:",IDC_IMAGEDESC_LABEL,7,64,52,8,SS_NOPREFIX + EDITTEXT IDC_IMAGEFILE_DESC,60,64,183,12,ES_AUTOHSCROLL | + ES_READONLY | NOT WS_BORDER | NOT WS_TABSTOP + CONTROL "&Overwrite an existing file",IDC_OVERWRITE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,60,95,183,10 + CONTROL "&Truncate an existing file",IDC_TRUNCATE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,60,111,183,10 + DEFPUSHBUTTON "&Save",IDOK,72,129,50,14,WS_DISABLED + PUSHBUTTON "Cancel",IDCANCEL,127,129,50,14 + LTEXT "additional information",IDC_IMAGEFILE_HINT,60,80,183,8, + SS_NOPREFIX +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_OPENDIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 243 + TOPMARGIN, 7 + BOTTOMMARGIN, 143 + END + + IDD_PROPDIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 219 + TOPMARGIN, 7 + BOTTOMMARGIN, 206 + END + + IDD_SAVEDIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 243 + TOPMARGIN, 7 + BOTTOMMARGIN, 143 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +#ifndef __REACTOS__ +IDI_VFD_ICON ICON DISCARDABLE "res\\vfd.ico" +IDI_IMAGE_ICON ICON DISCARDABLE "res\\image.ico" +IDI_CONFIG_ICON ICON DISCARDABLE "res\\config.ico" +#else +IDI_VFD_ICON ICON DISCARDABLE "res/vfd.ico" +IDI_IMAGE_ICON ICON DISCARDABLE "res/image.ico" +IDI_CONFIG_ICON ICON DISCARDABLE "res/config.ico" +#endif +#endif // ニュートラル resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + +#ifdef __REACTOS__ +#include +#endif diff --git a/modules/rosapps/lib/vfdlib/vfdlib.rs b/modules/rosapps/lib/vfdlib/vfdlib.rs new file mode 100644 index 00000000000..d06414a0911 --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdlib.rs @@ -0,0 +1,83 @@ +/* + vfdlib.rc + + Virtual Floppy Drive for Windows + Driver control library + Resource Script + + The non-standard extension ".rs" is intentional, so that + Microsoft Visual Studio won't try to open this file with + the resource editor + + Copyright (c) 2003-2005 Ken Kato +*/ + +#ifndef APSTUDIO_INVOKED + +// +// version resource constants +// +#include + +// +// VFD common version constants +// +#include "vfdver.h" + +// +// Library specific version constants +// +#include "vfdlib.h" + +#define VFD_FILEOS VOS_NT_WINDOWS32 +#define VFD_FILETYPE VFT_DLL +#define VFD_FILESUBTYPE VFT2_UNKNOWN + +#define VFD_DESCRIPTION "Virtual Floppy Drive Library" +#define VFD_INTERNALNAME VFD_LIBRARY_FILENAME +#define VFD_FILE_MAJOR 2 +#define VFD_FILE_MINOR 1 + +// +// embedded VFD driver binary +// +#ifdef VFD_EMBED_DRIVER + +#define VFD_SPECIAL_FLAG VS_FF_SPECIALBUILD +#define VFD_SPECIAL_DESC "Driver binary embedded version" +#define VFD_SPECIAL_DESC_ALT "ドライババイナリ埋め込み版" + +#ifdef _DEBUG +VFD_DRIVER_NAME_ID VFD_DRIVER_TYPE_ID "..\..\sys\objchk\i386\vfd.sys" +#else // _DEBUG +VFD_DRIVER_NAME_ID VFD_DRIVER_TYPE_ID "..\..\sys\objfre\i386\vfd.sys" +#endif // _DEBUG + +#endif // VFD_EMBED_DRIVER + +// +// Japanese version resource constants +// +#define VFD_VERSIONINFO_ALT "041104B0" +#undef VFD_VERSIONINFO_TRANS +#define VFD_VERSIONINFO_TRANS 0x0409, 0x04B0, 0x0411, 0x04B0 + +#define VFD_DESCRIPTION_ALT "Virtual Floppy Drive ライブラリ" +#define VFD_PRODUCT_NAME_ALT VFD_PRODUCT_NAME + +// +// VFD common version resource +// +#include "vfdver.rc" + +// +// GUI resource +// +#include "vfdlib.rc" + +// +// Module message resource +// +#include "vfdmsg.rc" + +#endif // !APSTUDIO_INVOKED diff --git a/modules/rosapps/lib/vfdlib/vfdlib.spec b/modules/rosapps/lib/vfdlib/vfdlib.spec new file mode 100644 index 00000000000..dcc79340f59 --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdlib.spec @@ -0,0 +1,55 @@ +@ stdcall -private DllCanUnloadNow() +@ stdcall -private DllGetClassObject(ptr ptr ptr) + +@ stdcall VfdRegisterHandlers() +@ stdcall VfdUnregisterHandlers() +@ stdcall VfdCheckHandlers() + +@ stdcall VfdInstallDriver(str long) +@ stdcall VfdConfigDriver(long) +@ stdcall VfdRemoveDriver() +@ stdcall VfdStartDriver(ptr) +@ stdcall VfdStopDriver(ptr) +@ stdcall VfdGetDriverConfig(str ptr) +@ stdcall VfdGetDriverState(ptr) + +@ stdcall VfdOpenDevice(long) +@ stdcall VfdGetDeviceNumber(ptr ptr) +@ stdcall VfdGetDeviceName(ptr str long) +@ stdcall VfdGetDriverVersion(ptr ptr) + +@ stdcall VfdOpenImage(ptr str long long long) +@ stdcall VfdCloseImage(ptr long) +@ stdcall VfdGetImageInfo(ptr str ptr ptr ptr ptr ptr) +@ stdcall VfdSaveImage(ptr str long long) +@ stdcall VfdFormatMedia(ptr) +@ stdcall VfdGetMediaState(ptr) +@ stdcall VfdWriteProtect(ptr long) +@ stdcall VfdDismountVolume(ptr long) + +@ stdcall VfdSetGlobalLink(ptr long) +@ stdcall VfdGetGlobalLink(ptr str) +@ stdcall VfdSetLocalLink(ptr long) +@ stdcall VfdGetLocalLink(ptr str) + +@ stdcall VfdGetNotifyMessage() + +@ stdcall VfdChooseLetter() +@ stdcall VfdCheckDriverFile(str ptr) +@ stdcall VfdCheckImageFile(str ptr ptr ptr) +@ stdcall VfdCreateImageFile(str long long long) + +@ stdcall VfdLookupMedia(long) +@ stdcall VfdGetMediaSize(long) +@ stdcall VfdMediaTypeName(long) + +@ stdcall VfdMakeFileDesc(str long long long long) + +@ stdcall VfdGuiOpen(ptr long) +@ stdcall VfdGuiSave(ptr long) +@ stdcall VfdGuiClose(ptr long) +@ stdcall VfdGuiFormat(ptr long) +@ stdcall VfdToolTip(ptr str long long long) +@ stdcall VfdImageTip(ptr long) + +@ stdcall VfdIsValidPlatform() diff --git a/modules/rosapps/lib/vfdlib/vfdmsg_lib.mc b/modules/rosapps/lib/vfdlib/vfdmsg_lib.mc new file mode 100644 index 00000000000..cffa15b93d3 --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdmsg_lib.mc @@ -0,0 +1,523 @@ +;/* +; vfdmsg.h +; +; Virtual Floppy Drive for Windows +; Driver control library +; Message definition +; +; Copyright (c) 2003-2005 Ken Kato +;*/ +; +;#ifndef _VFDMSG_H_ +;#define _VFDMSG_H_ +; + +MessageIdTypedef=DWORD +LanguageNames=(English=0x409:msg0409) + +; +;// +;// Context menu text +;// +; +MessageId= +SymbolicName=MSG_MENU_OPEN +Language=English +&Open VFD image...%0 +. + + +MessageId= +SymbolicName=MSG_HELP_OPEN +Language=English +Open a virtual floppy image.%0 +. + + +MessageId= +SymbolicName=MSG_MENU_CLOSE +Language=English +&Close VFD image%0 +. + + +MessageId= +SymbolicName=MSG_HELP_CLOSE +Language=English +Close the current virtual floppy image.%0 +. + + +MessageId= +SymbolicName=MSG_MENU_SAVE +Language=English +&Save VFD image...%0 +. + + +MessageId= +SymbolicName=MSG_HELP_SAVE +Language=English +Save the current image into a file.%0 +. + + +MessageId= +SymbolicName=MSG_MENU_PROTECT +Language=English +&Write Protect%0 +. + + +MessageId= +SymbolicName=MSG_HELP_PROTECT +Language=English +Enable/disable the media write protection.%0 +. + + +MessageId= +SymbolicName=MSG_MENU_PROP +Language=English +VFD &Property%0 +. + + +MessageId= +SymbolicName=MSG_HELP_PROP +Language=English +Display the VFD property page.%0 +. + + +MessageId= +SymbolicName=MSG_MENU_DROP +Language=English +&Open with VFD%0 +. + + +MessageId= +SymbolicName=MSG_HELP_DROP +Language=English +Open the file with VFD.%0 +. + + +; +;// +;// Dialog title text +;// +; + +MessageId= +SymbolicName=MSG_OPEN_TITLE +Language=English +Open Virtual Floppy Image%0 +. + + +MessageId= +SymbolicName=MSG_SAVE_TITLE +Language=English +Save Virtual Floppy Image%0 +. + + +; +;// +;// Dialog label text +;// +; + +MessageId= +SymbolicName=MSG_IMAGEFILE_LABEL +Language=English +Image File:%0 +. + + +MessageId= +SymbolicName=MSG_IMAGEFILE_ACCEL +Language=English +&Image File:%0 +. + + +MessageId= +SymbolicName=MSG_DESCRIPTION_LABEL +Language=English +Description:%0 +. + + +MessageId= +SymbolicName=MSG_DISKTYPE_LABEL +Language=English +Disk Type:%0 +. + + +MessageId= +SymbolicName=MSG_MEDIATYPE_LABEL +Language=English +Media Type:%0 +. + + +MessageId= +SymbolicName=MSG_MEDIATYPE_ACCEL +Language=English +&Media Type:%0 +. + + +MessageId= +SymbolicName=MSG_TARGETFILE_LABEL +Language=English +&Target File:%0 +. + + +; +;// +;// button text +;// +; + +MessageId= +SymbolicName=MSG_OPEN_BUTTON +Language=English +&Open%0 +. + + +MessageId= +SymbolicName=MSG_CREATE_BUTTON +Language=English +&Create%0 +. + + +MessageId= +SymbolicName=MSG_SAVE_BUTTON +Language=English +&Save%0 +. + + +MessageId= +SymbolicName=MSG_CLOSE_BUTTON +Language=English +&Close%0 +. + + +MessageId= +SymbolicName=MSG_FORMAT_BUTTON +Language=English +&Format%0 +. + + +MessageId= +SymbolicName=MSG_CONTROL_BUTTON +Language=English +&VFD Control Panel%0 +. + + +MessageId= +SymbolicName=MSG_BROWSE_BUTTON +Language=English +&Browse...%0 +. + + +MessageId= +SymbolicName=MSG_CANCEL_BUTTON +Language=English +Cancel%0 +. + + +MessageId= +SymbolicName=MSG_OVERWRITE_CHECK +Language=English +Overwrite an existing file.%0 +. + + +MessageId= +SymbolicName=MSG_TRUNCATE_CHECK +Language=English +Truncate an existing file.%0 +. + + +; +;// +;// file description text +;// +; +MessageId= +SymbolicName=MSG_FILETYPE_RAW +Language=English +RAW image%0 +. + + +MessageId= +SymbolicName=MSG_FILETYPE_ZIP +Language=English +ZIP image%0 +. + + +MessageId= +SymbolicName=MSG_DESC_NEW_FILE +Language=English +New file%0 +. + + +MessageId= +SymbolicName=MSG_DESC_FILESIZE +Language=English +%1!s! bytes (%2!s!)%0 +. + + +MessageId= +SymbolicName=MSG_ATTR_READONLY +Language=English +ReadOnly%0 +. + + +MessageId= +SymbolicName=MSG_ATTR_COMPRESSED +Language=English +Compressed%0 +. + + +MessageId= +SymbolicName=MSG_ATTR_ENCRYPTED +Language=English +Encrypted%0 +. + + +; +;// +;// ToolTip +;// +; +MessageId= +SymbolicName=MSG_WRITE_PROTECTED +Language=English +&Write Protected%0 +. + + +MessageId= +SymbolicName=MSG_WRITE_ALLOWED +Language=English +Write Allowed%0 +. + + +MessageId= +SymbolicName=MSG_IMAGE_INFOTIP +Language=English +%1!s! +%2!s! +Type: %3!s! disk +Media: %4!s! +%5!s!%0 +. + + +; +;// +;// Context help text +;// +; + +MessageId= +SymbolicName=MSG_HELP_IMAGEFILE +Language=English +Image file name.%0 +. + + +MessageId= +SymbolicName=MSG_HELP_IMAGEDESC +Language=English +Information about the image file.%0 +. + + +MessageId= +SymbolicName=MSG_HELP_TARGETFILE +Language=English +Save target file name.%0 +. + + +MessageId= +SymbolicName=MSG_HELP_DISKTYPE +Language=English +Virtual disk type.%0 +. + + +MessageId= +SymbolicName=MSG_HELP_MEDIATYPE +Language=English +Virtual floppy media type.%0 +. + + +MessageId= +SymbolicName=MSG_HELP_FORMAT +Language=English +Click to format the +current image with FAT.%0 +. + + +MessageId= +SymbolicName=MSG_HELP_CONTROL +Language=English +Start the VFD Control Panel.%0 +. + + +MessageId= +SymbolicName=MSG_HELP_PROTECT_NOW +Language=English +Enable/disable the media write protection. +The change takes effect immediately.%0 +. + + +MessageId= +SymbolicName=MSG_HELP_PROTECT_OPEN +Language=English +Open the image as a +write protected media.%0 +. + + +MessageId= +SymbolicName=MSG_HELP_BROWSE +Language=English +Browse for folders to +find the target file.%0 +. + + +MessageId= +SymbolicName=MSG_HELP_OVERWRITE +Language=English +Overwrite the existing file +to save the current image.%0 +. + + +MessageId= +SymbolicName=MSG_HELP_TRUNCATE +Language=English +Truncate the target file after +saving the current image.%0 +. + + +; +;// +;// Hint text +;// +; +MessageId= +SymbolicName=MSG_CURRENT_FILE +Language=English +Current image file.%0 +. + + +MessageId= +SymbolicName=MSG_FILE_TOO_SMALL +Language=English +The file is too small for the selected media type.%0 +. + + +MessageId= +SymbolicName=MSG_SIZE_MISMATCH +Language=English +The file size does not match the selected media size.%0 +. + + +MessageId= +SymbolicName=MSG_FILE_ACCESS_ERROR +Language=English +Cannot access the file.%0 +. + + +MessageId= +SymbolicName=MSG_TARGET_IS_ZIP +Language=English +Cannot overwrite a ZIP compressed file.%0 +. + + +; +;// +;// Other text +;// +; +MessageId= +SymbolicName=MSG_OPEN_FILTER +Language=English +Common image files (bin,dat,fdd,flp,ima,img,vfd)|*.bin;*.dat;*.fdd;*.flp;*.ima;*.img;*.vfd|ZIP Compressed Image (imz,zip)|*.imz;*.zip|All files (*.*)|*.*|%0 +. + + +MessageId= +SymbolicName=MSG_FORMAT_WARNING +Language=English +Warning: Formatting will erase all data on this disk. +Click [OK] to format the disk, [Cancel] to quit.%0 +. + + +MessageId= +SymbolicName=MSG_MEDIA_MODIFIED +Language=English +Data on the RAM disk is modified. +Save to a file before closing ?%0 +. + + +MessageId= +SymbolicName=MSG_UNMOUNT_CONFIRM +Language=English +Failed to lock the volume. +Make sure that any files are not in use. +Continuing forces all files to be closed.%0 +. + + +MessageId= +SymbolicName=MSG_UNMOUNT_FAILED +Language=English +Failed to unmount the volume. +Make sure that any files are not in use.%0 +. + +; +;#endif // _VFDMSG_H_ diff --git a/modules/rosapps/lib/vfdlib/vfdshcfact.cpp b/modules/rosapps/lib/vfdlib/vfdshcfact.cpp new file mode 100644 index 00000000000..9a3065c6ec1 --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdshcfact.cpp @@ -0,0 +1,126 @@ +/* + vfdshcfact.cpp + + Virtual Floppy Drive for Windows + Driver control library + shell extension COM class factory class + + Copyright (c) 2003-2005 Ken Kato +*/ + +#define WIN32_LEAN_AND_MEAN +#include +#include + +#include "vfdtypes.h" +#include "vfdlib.h" +#include "vfdshext.h" + +// class header +#include "vfdshcfact.h" + +// +// constructor +// +CVfdFactory::CVfdFactory() +{ + VFDTRACE(0, ("CVfdFactory::CVfdFactory()\n")); + + m_cRefCnt = 0L; + + g_cDllRefCnt++; +} + +// +// destructor +// +CVfdFactory::~CVfdFactory() +{ + VFDTRACE(0, ("CVfdFactory::~CVfdFactory()\n")); + + g_cDllRefCnt--; +} + +// +// IUnknown methods +// +STDMETHODIMP CVfdFactory::QueryInterface( + REFIID riid, + LPVOID *ppv) +{ + VFDTRACE(0, ("CVfdFactory::QueryInterface()\n")); + + *ppv = NULL; + + if (IsEqualIID(riid, IID_IUnknown) || + IsEqualIID(riid, IID_IClassFactory)) { + *ppv = (LPCLASSFACTORY)this; + + AddRef(); + + return NOERROR; + } + + return E_NOINTERFACE; +} + +STDMETHODIMP_(ULONG) CVfdFactory::AddRef() +{ + VFDTRACE(0, ("CVfdFactory::AddRef()\n")); + + return ++m_cRefCnt; +} + +STDMETHODIMP_(ULONG) CVfdFactory::Release() +{ + VFDTRACE(0, ("CVfdFactory::Release()\n")); + + if (--m_cRefCnt) { + return m_cRefCnt; + } + +#ifndef __REACTOS__ + delete this; +#endif + + return 0L; +} + +// +// IClassFactory methods +// +STDMETHODIMP CVfdFactory::CreateInstance( + LPUNKNOWN pUnkOuter, + REFIID riid, + LPVOID *ppvObj) +{ + VFDTRACE(0, ("CVfdFactory::CreateInstance()\n")); + + *ppvObj = NULL; + + // Shell extensions typically don't support + // aggregation (inheritance) + + if (pUnkOuter) { + return CLASS_E_NOAGGREGATION; + } + + // Create the main shell extension object. + // The shell will then call QueryInterface with IID_IShellExtInit + // -- this is how shell extensions are initialized. + + LPCVFDSHEXT pVfdShExt = new CVfdShExt; + + if (!pVfdShExt) { + return E_OUTOFMEMORY; + } + + return pVfdShExt->QueryInterface(riid, ppvObj); +} + +STDMETHODIMP CVfdFactory::LockServer(BOOL fLock) +{ + VFDTRACE(0, ("CVfdFactory::LockServer()\n")); + UNREFERENCED_PARAMETER(fLock); + return NOERROR; +} diff --git a/modules/rosapps/lib/vfdlib/vfdshcfact.h b/modules/rosapps/lib/vfdlib/vfdshcfact.h new file mode 100644 index 00000000000..767b22d7a02 --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdshcfact.h @@ -0,0 +1,42 @@ +/* + vfdshcfact.h + + Virtual Floppy Drive for Windows + Driver control library + shell extension COM class-factory class header + + Copyright (c) 2003-2005 Ken Kato +*/ + +#ifndef _VFDSHCFACT_H_ +#define _VFDSHCFACT_H_ + +// +// CVfdFactory +// class factory class to create the COM shell extension object +// +class CVfdFactory : public IClassFactory +{ +protected: + ULONG m_cRefCnt; // Reference count to the object + +public: + // Constructor + CVfdFactory(); + + // Destructor + ~CVfdFactory(); + + // IUnknown inheritance + STDMETHODIMP QueryInterface(REFIID, LPVOID *); + STDMETHODIMP_(ULONG) AddRef(); + STDMETHODIMP_(ULONG) Release(); + + // IClassFactory inheritance + STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID *); + STDMETHODIMP LockServer(BOOL); +}; + +typedef CVfdFactory *LPCVFDFACTORY; + +#endif // _VFDSHCFACT_H_ diff --git a/modules/rosapps/lib/vfdlib/vfdshext.cpp b/modules/rosapps/lib/vfdlib/vfdshext.cpp new file mode 100644 index 00000000000..73f249da645 --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdshext.cpp @@ -0,0 +1,235 @@ +/* + vfdshext.cpp + + Virtual Floppy Drive for Windows + Driver control library + shell extension COM shell extension class + + Copyright (c) 2003-2005 Ken Kato +*/ + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +#include "vfdtypes.h" +#include "vfdapi.h" +#include "vfdlib.h" + +// class header +#include "vfdshext.h" + +// +// Constructor +// +CVfdShExt::CVfdShExt() +{ + VFDTRACE(0, ("CVfdShExt::CVfdShExt()\n")); + + m_cRefCnt = 0L; + m_pDataObj = NULL; + m_nDevice = (ULONG)-1; + m_sTarget[0] = '\0'; + m_bDragDrop = FALSE; + + g_cDllRefCnt++; +} + +// +// Destructor +// +CVfdShExt::~CVfdShExt() +{ + VFDTRACE(0, ("CVfdShExt::~CVfdShExt()\n")); + + if (m_pDataObj) { + m_pDataObj->Release(); + } + + g_cDllRefCnt--; +} + +// IUnknown members + +STDMETHODIMP CVfdShExt::QueryInterface( + REFIID riid, + LPVOID *ppv) +{ + *ppv = NULL; + + if (IsEqualIID(riid, IID_IShellExtInit) || + IsEqualIID(riid, IID_IUnknown)) { + VFDTRACE(0, + ("CVfdShExt::QueryInterface()==>IID_IShellExtInit\n")); + + *ppv = (LPSHELLEXTINIT)this; + } + else if (IsEqualIID(riid, IID_IContextMenu)) { + VFDTRACE(0, + ("CVfdShExt::QueryInterface()==>IID_IContextMenu\n")); + + *ppv = (LPCONTEXTMENU)this; + } + else if (IsEqualIID(riid, IID_IShellPropSheetExt)) { + VFDTRACE(0, + ("CVfdShExt::QueryInterface()==>IID_IShellPropSheetExt\n")); + + *ppv = (LPSHELLPROPSHEETEXT)this; + } + + if (*ppv) { + AddRef(); + + return NOERROR; + } + + VFDTRACE(0, + ("CVfdShExt::QueryInterface()==>Unknown Interface!\n")); + + return E_NOINTERFACE; +} + +STDMETHODIMP_(ULONG) CVfdShExt::AddRef() +{ + VFDTRACE(0, ("CVfdShExt::AddRef()\n")); + + return ++m_cRefCnt; +} + +STDMETHODIMP_(ULONG) CVfdShExt::Release() +{ + VFDTRACE(0, ("CVfdShExt::Release()\n")); + + if (--m_cRefCnt) { + return m_cRefCnt; + } + +#ifndef __REACTOS__ + delete this; +#endif + + return 0L; +} + +// IShellExtInit members + +// +// Initialize +// Called by the shell to initialize the shell extension object +// +STDMETHODIMP CVfdShExt::Initialize( + LPCITEMIDLIST pIDFolder, + LPDATAOBJECT pDataObj, + HKEY hRegKey) +{ + CHAR drive = '\0'; + + VFDTRACE(0, ("CVfdShExt::Initialize()\n")); + + UNREFERENCED_PARAMETER(hRegKey); + + // Initialize can be called more than once + + if (m_pDataObj) { + m_pDataObj->Release(); + m_pDataObj = NULL; + } + + m_nDevice = (ULONG)-1; + m_sTarget[0] = '\0'; + + // Get the folder name + if (SHGetPathFromIDList(pIDFolder, m_sTarget)) { + + // act as a Drag-and-Drop Handler + + VFDTRACE(0, ("Drag-Drop: %s\n", m_sTarget)); + + if (GetDriveType(m_sTarget) != DRIVE_REMOVABLE) { + VFDTRACE(0, ("Not a VFD drive\n")); + return NOERROR; + } + + drive = m_sTarget[0]; + m_bDragDrop = TRUE; + } + else { + + // act as a context menu handler + + VFDTRACE(0, ("Context menu:\n")); + m_bDragDrop = FALSE; + } + + // Extract the target object name + + if (pDataObj) { + + STGMEDIUM medium; + FORMATETC fmt = { + CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL + }; + + if (SUCCEEDED(pDataObj->GetData(&fmt, &medium))) { + if (DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, NULL, 0)) { + + DragQueryFile((HDROP)medium.hGlobal, + 0, m_sTarget, sizeof(m_sTarget)); + } + + ReleaseStgMedium(&medium); + } + } + + VFDTRACE(0, ("Target %s\n", m_sTarget)); + + if (!drive) { + // Contect menu handler + // -- Data object is the target drive + drive = m_sTarget[0]; + } + + HANDLE hDevice = VfdOpenDevice(drive); + + if (hDevice == INVALID_HANDLE_VALUE) { + VFDTRACE(0, ("Not a VFD drive\n")); + return NOERROR; + } + + ULONG ret = VfdGetDeviceNumber(hDevice, &m_nDevice); + + CloseHandle(hDevice); + + if (ret != ERROR_SUCCESS) { + m_nDevice = (ULONG)-1; + return NOERROR; + } + + VFDTRACE(0, ("VFD device %d\n", m_nDevice)); + // Store the data object + + m_pDataObj = pDataObj; + m_pDataObj->AddRef(); + + return NOERROR; +} + +/* +STDMETHODIMP CVfdShExt::GetInfoFlags( + DWORD *pdwFlags) +{ + VFDTRACE(0, ("CVfdShExt::GetInfoFlags\n")); + *pdwFlags = 0; + return NOERROR; +} + +STDMETHODIMP CVfdShExt::GetInfoTip( + DWORD dwFlags, + LPWSTR *ppwszTip) +{ + VFDTRACE(0, ("CVfdShExt::GetInfoTip\n")); + *ppwszTip = NULL; + return NOERROR; +} +*/ diff --git a/modules/rosapps/lib/vfdlib/vfdshext.h b/modules/rosapps/lib/vfdlib/vfdshext.h new file mode 100644 index 00000000000..7379cb50cdb --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdshext.h @@ -0,0 +1,99 @@ +/* + vfdshext.h + + Virtual Floppy Drive for Windows + Driver control library + shell extension COM class header + + Copyright (c) 2003-2005 Ken Kato +*/ + +#ifndef _VFDSHEXT_H_ +#define _VFDSHEXT_H_ + +// +// CVfdShExt +// COM Shell extension class +// +class CVfdShExt : public IContextMenu, + IShellExtInit, + IShellPropSheetExt +// IQueryInfo +{ +protected: + ULONG m_cRefCnt; // reference count + LPDATAOBJECT m_pDataObj; // IDataObject pointer + ULONG m_nDevice; // VFD device number + CHAR m_sTarget[MAX_PATH]; // target path + BOOL m_bDragDrop; + +public: + // constructor / destructor + CVfdShExt(); + ~CVfdShExt(); + + // perform VFD operations + DWORD DoVfdOpen(HWND hParent); + DWORD DoVfdNew(HWND hParent); + DWORD DoVfdClose(HWND hParent); + DWORD DoVfdSave(HWND hParent); + DWORD DoVfdProtect(HWND hParent); + DWORD DoVfdDrop(HWND hParent); + + // get current attributes + ULONG GetDevice() { return m_nDevice; } + PCSTR GetTarget() { return m_sTarget; } + + // IUnknown inheritance + STDMETHODIMP QueryInterface(REFIID, LPVOID *); + STDMETHODIMP_(ULONG) AddRef(); + STDMETHODIMP_(ULONG) Release(); + + // IShellExtInit inheritance + STDMETHODIMP Initialize( + LPCITEMIDLIST pIDFolder, + LPDATAOBJECT pDataObj, + HKEY hKeyID); + + // IContextMenu inheritance + STDMETHODIMP QueryContextMenu( + HMENU hMenu, + UINT indexMenu, + UINT idCmdFirst, + UINT idCmdLast, + UINT uFlags); + + STDMETHODIMP InvokeCommand( + LPCMINVOKECOMMANDINFO lpcmi); + + STDMETHODIMP GetCommandString( + UINT idCmd, + UINT uFlags, + UINT *reserved, + LPSTR pszName, + UINT cchMax); + + // IShellPropSheetExt inheritance + STDMETHODIMP AddPages( + LPFNADDPROPSHEETPAGE lpfnAddPage, + LPARAM lParam); + + STDMETHODIMP ReplacePage( + UINT uPageID, + LPFNADDPROPSHEETPAGE lpfnReplaceWith, + LPARAM lParam); +/* + // IQueryInfo inheritance + + STDMETHODIMP GetInfoFlags( + DWORD *pdwFlags); + + STDMETHODIMP GetInfoTip( + DWORD dwFlags, + LPWSTR *ppwszTip); +*/ +}; + +typedef CVfdShExt *LPCVFDSHEXT; + +#endif // _VFDSHEXT_H_ diff --git a/modules/rosapps/lib/vfdlib/vfdshguid.h b/modules/rosapps/lib/vfdlib/vfdshguid.h new file mode 100644 index 00000000000..e5988f5b957 --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdshguid.h @@ -0,0 +1,17 @@ +/* + vfdshguid.h + + Virtual Floppy Drive for Windows + Driver control library + shell extension GUID header + + Copyright (c) 2003-2005 Ken Kato +*/ + +#ifndef _VFDSHGUID_H_ +#define _VFDSHGUID_H_ + +DEFINE_GUID(CLSID_VfdShellExt, 0x296c1585L, 0x678f, 0x4584, + 0x8f, 0x02, 0x10, 0x39, 0xc1, 0xd1, 0x86, 0x4c); + +#endif // _VFDSHGUID_H_ diff --git a/modules/rosapps/lib/vfdlib/vfdshmenu.cpp b/modules/rosapps/lib/vfdlib/vfdshmenu.cpp new file mode 100644 index 00000000000..3bce66a9072 --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdshmenu.cpp @@ -0,0 +1,597 @@ +/* + vfdshmenu.cpp + + Virtual Floppy Drive for Windows + Driver control library + COM shell extension class context menu functions + + Copyright (c) 2003-2005 Ken Kato +*/ + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +#include "vfdtypes.h" +#include "vfdapi.h" +#include "vfdlib.h" +#ifndef __REACTOS__ +#include "vfdmsg.h" +#else +#include "vfdmsg_lib.h" +#endif + +// class header +#include "vfdshext.h" + +// +// Undocumented windows API to handle shell property sheets +// + +typedef BOOL (WINAPI *SHOBJECTPROPERTIES)( + HWND hwnd, DWORD dwType, LPCWSTR lpObject, LPCWSTR lpPage); + +#ifndef SHOP_FILEPATH +#define SHOP_FILEPATH 0x00000002 +#endif + +#define SHOP_EXPORT_ORDINAL 178 + +// +// Context Menu Items +// +enum { + VFD_CMD_OPEN = 0, + VFD_CMD_SAVE, + VFD_CMD_CLOSE, + VFD_CMD_PROTECT, + VFD_CMD_DROP, + VFD_CMD_PROP, + VFD_CMD_MAX +}; + +static struct _vfd_menu { + UINT textid; // menu item text id + UINT helpid; // menu item help id +#ifndef __REACTOS__ + PCHAR verbA; // ansi verb text + PWCHAR verbW; // unicode verb text +#else + LPCSTR verbA; // ansi verb text + LPCWSTR verbW; // unicode verb text +#endif +} +g_VfdMenu[VFD_CMD_MAX] = { + { MSG_MENU_OPEN, MSG_HELP_OPEN, "vfdopen", L"vfdopen" }, + { MSG_MENU_SAVE, MSG_HELP_SAVE, "vfdsave", L"vfdsave" }, + { MSG_MENU_CLOSE, MSG_HELP_CLOSE, "vfdclose", L"vfdclose" }, + { MSG_MENU_PROTECT, MSG_HELP_PROTECT, "protect", L"protect" }, + { MSG_MENU_DROP, MSG_HELP_DROP, "vfddrop", L"vfddrop" }, + { MSG_MENU_PROP, MSG_HELP_PROP, "vfdprop", L"vfdprop" }, +}; + +// +// local functions +// +static void AddMenuItem( + HMENU hMenu, + UINT uPos, + UINT uFlags, + UINT uCmd, + UINT uText) +{ + PSTR text = ModuleMessage(uText); + + if (text) { + InsertMenu(hMenu, uPos, uFlags, uCmd, text); + LocalFree(text); + } +} + + +// +// FUNCTION: CVfdShExt::QueryContextMenu(HMENU, UINT, UINT, UINT, UINT) +// +// PURPOSE: Called by the shell just before the context menu is displayed. +// This is where you add your specific menu items. +// +// PARAMETERS: +// hMenu - Handle to the context menu +// indexMenu - Index of where to begin inserting menu items +// idCmdFirst - Lowest value for new menu ID's +// idCmtLast - Highest value for new menu ID's +// uFlags - Specifies the context of the menu event +// +STDMETHODIMP CVfdShExt::QueryContextMenu( + HMENU hMenu, + UINT indexMenu, + UINT idCmdFirst, + UINT idCmdLast, + UINT uFlags) +{ + UNREFERENCED_PARAMETER(idCmdLast); + VFDTRACE(0, ("CVfdShExt::QueryContextMenu()\n")); + + // + // Check if menu items should be added + // + if ((CMF_DEFAULTONLY & uFlags) || + !m_pDataObj || m_nDevice == (ULONG)-1) { + + VFDTRACE(0, ("Don't add any items.\n")); + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0); + } + + // + // Drag & Drop handler? + // + if (m_bDragDrop) { + + VFDTRACE(0, ("Invoked as the Drop handler.\n")); + + if (GetFileAttributes(m_sTarget) & FILE_ATTRIBUTE_DIRECTORY) { + + // if the dropped item is a directory, nothing to do here + VFDTRACE(0, ("Dropped object is a directory.\n")); + + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0); + } + + // Add a drop context menu item + AddMenuItem( + hMenu, + indexMenu, + MF_BYPOSITION | MF_STRING, + idCmdFirst + VFD_CMD_DROP, + g_VfdMenu[VFD_CMD_DROP].textid); + + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, VFD_CMD_DROP + 1); + } + + // + // Context menu handler + // + VFDTRACE(0, ("Invoked as the context menu handler.\n")); + + // + // Get the VFD media state + // + HANDLE hDevice = VfdOpenDevice(m_nDevice); + + if (hDevice == INVALID_HANDLE_VALUE) { + VFDTRACE(0, ("device open failed.\n")); + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0); + } + + DWORD status = VfdGetMediaState(hDevice); + + CloseHandle(hDevice); + + // + // Add context menu items + // + + InsertMenu(hMenu, indexMenu++, + MF_BYPOSITION | MF_SEPARATOR, 0, NULL); + + if (status == ERROR_SUCCESS || + status == ERROR_WRITE_PROTECT) { + + // An image is opened + + // insert the "save" menu item + + AddMenuItem( + hMenu, + indexMenu++, + MF_BYPOSITION | MF_STRING, + idCmdFirst + VFD_CMD_SAVE, + g_VfdMenu[VFD_CMD_SAVE].textid); + + // insert the "close" menu item + + AddMenuItem( + hMenu, + indexMenu++, + MF_BYPOSITION | MF_STRING, + idCmdFirst + VFD_CMD_CLOSE, + g_VfdMenu[VFD_CMD_CLOSE].textid); + + // insert the "protect" menu item + + AddMenuItem( + hMenu, + indexMenu++, + MF_BYPOSITION | MF_STRING, + idCmdFirst + VFD_CMD_PROTECT, + g_VfdMenu[VFD_CMD_PROTECT].textid); + + // check "protect" menu item + + if (status == ERROR_WRITE_PROTECT) { + CheckMenuItem(hMenu, indexMenu - 1, + MF_BYPOSITION | MF_CHECKED); + } + } + else { + // The drive is empty + + // insert the "open" menu item + + AddMenuItem( + hMenu, + indexMenu++, + MF_BYPOSITION | MF_STRING, + idCmdFirst + VFD_CMD_OPEN, + g_VfdMenu[VFD_CMD_OPEN].textid); + } + + // Insert the "proterty" menu item + + AddMenuItem( + hMenu, + indexMenu++, + MF_BYPOSITION | MF_STRING, + idCmdFirst + VFD_CMD_PROP, + g_VfdMenu[VFD_CMD_PROP].textid); + + // Insert a separator + + InsertMenu(hMenu, indexMenu, + MF_BYPOSITION | MF_SEPARATOR, 0, NULL); + + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, VFD_CMD_PROP + 1); +} + +// +// FUNCTION: CVfdShExt::GetCommandString(LPCMINVOKECOMMANDINFO) +// +// PURPOSE: Retrieves information about a shortcut menu command, +// including the Help string and the language-independent, +// or canonical, name for the command. +// +// PARAMETERS: +// idCmd - Menu command identifier offset. +// uFlags - Flags specifying the information to return. +// This parameter can have one of the following values. +// GCS_HELPTEXTA Sets pszName to an ANSI string containing the Help text for the command. +// GCS_HELPTEXTW Sets pszName to a Unicode string containing the Help text for the command. +// GCS_VALIDATEA Returns S_OK if the menu item exists, or S_FALSE otherwise. +// GCS_VALIDATEW Returns S_OK if the menu item exists, or S_FALSE otherwise. +// GCS_VERBA Sets pszName to an ANSI string containing the language-independent command name for the menu item. +// GCS_VERBW Sets pszName to a Unicode string containing the language-independent command name for the menu item. +// pwReserved - Reserved. Applications must specify NULL when calling this method, and handlers must ignore this parameter when called. +// pszName - Address of the buffer to receive the null-terminated string being retrieved. +// cchMax - Size of the buffer to receive the null-terminated string. +// + +STDMETHODIMP CVfdShExt::GetCommandString( + UINT idCmd, + UINT uFlags, + UINT *reserved, + LPSTR pszName, + UINT cchMax) +{ + VFDTRACE(0, + ("CVfdShExt::GetCommandString(%u,...)\n", idCmd)); + + UNREFERENCED_PARAMETER(reserved); + + if (idCmd >= sizeof(g_VfdMenu) / sizeof(g_VfdMenu[0])) { + return S_FALSE; + } + + switch (uFlags) { + case GCS_HELPTEXTA: + FormatMessageA( + FORMAT_MESSAGE_FROM_HMODULE | + FORMAT_MESSAGE_IGNORE_INSERTS, + g_hDllModule, g_VfdMenu[idCmd].helpid, + 0, pszName, cchMax, NULL); + + VFDTRACE(0, ("HELPTEXTA: %s\n", pszName)); + break; + + case GCS_HELPTEXTW: + FormatMessageW( + FORMAT_MESSAGE_FROM_HMODULE | + FORMAT_MESSAGE_IGNORE_INSERTS, + g_hDllModule, g_VfdMenu[idCmd].helpid, + 0, (LPWSTR)pszName, cchMax, NULL); + + VFDTRACE(0, ("HELPTEXTW: %ws\n", pszName)); + break; + + case GCS_VERBA: + lstrcpynA(pszName, g_VfdMenu[idCmd].verbA, cchMax); + break; + + case GCS_VERBW: + lstrcpynW((LPWSTR)pszName, g_VfdMenu[idCmd].verbW, cchMax); + break; + } + + return NOERROR; +} + +// +// FUNCTION: CVfdShExt::InvokeCommand(LPCMINVOKECOMMANDINFO) +// +// PURPOSE: Called by the shell after the user has selected on of the +// menu items that was added in QueryContextMenu(). +// +// PARAMETERS: +// lpcmi - Pointer to an CMINVOKECOMMANDINFO structure +// + +STDMETHODIMP CVfdShExt::InvokeCommand( + LPCMINVOKECOMMANDINFO lpcmi) +{ + VFDTRACE(0, ("CVfdShExt::InvokeCommand()\n")); + + BOOL unicode = FALSE; + UINT id; + DWORD ret; + CMINVOKECOMMANDINFOEX *excmi = (CMINVOKECOMMANDINFOEX *)lpcmi; + + if (lpcmi->cbSize >= sizeof(CMINVOKECOMMANDINFOEX) && + (lpcmi->fMask & CMIC_MASK_UNICODE)) { + + unicode = TRUE; + } + + + if (!unicode && HIWORD(lpcmi->lpVerb)) { + + VFDTRACE(0, ("ANSI: %s\n", lpcmi->lpVerb)); + + // ANSI verb + for (id = 0; id < sizeof(g_VfdMenu) / sizeof(g_VfdMenu[0]); id++) { + if (!lstrcmpi(lpcmi->lpVerb, g_VfdMenu[id].verbA)) { + break; + } + } + } + else if (unicode && HIWORD(excmi->lpVerbW)) { + + VFDTRACE(0, ("UNICODE: %ws\n", excmi->lpVerbW)); + + // UNICODE verb + for (id = 0; id < sizeof(g_VfdMenu) / sizeof(g_VfdMenu[0]); id++) { + if (!lstrcmpiW(excmi->lpVerbW, g_VfdMenu[id].verbW)) { + break; + } + } + } + else { + + VFDTRACE(0, ("Command: %u\n", LOWORD(lpcmi->lpVerb))); + + // Command ID + id = LOWORD(lpcmi->lpVerb); + } + + VFDTRACE(0, ("MenuItem: %u\n", id)); + + switch (id) { + case VFD_CMD_OPEN: + ret = DoVfdOpen(lpcmi->hwnd); + + if (ret == ERROR_SUCCESS) { + VfdImageTip(lpcmi->hwnd, m_nDevice); + } + break; + + case VFD_CMD_SAVE: + ret = DoVfdSave(lpcmi->hwnd); + break; + + case VFD_CMD_CLOSE: + ret = DoVfdClose(lpcmi->hwnd); + break; + + case VFD_CMD_PROTECT: + ret = DoVfdProtect(lpcmi->hwnd); + + if (ret == ERROR_SUCCESS) { + VfdImageTip(lpcmi->hwnd, m_nDevice); + } + else if (ret == ERROR_WRITE_PROTECT) { + VfdImageTip(lpcmi->hwnd, m_nDevice); + ret = ERROR_SUCCESS; + } + break; + + case VFD_CMD_DROP: + ret = DoVfdDrop(lpcmi->hwnd); + + if (ret == ERROR_SUCCESS) { + VfdImageTip(lpcmi->hwnd, m_nDevice); + } + break; + + case VFD_CMD_PROP: + { + SHOBJECTPROPERTIES pSHObjectProperties; + WCHAR path[4] = L" :\\"; + + pSHObjectProperties = (SHOBJECTPROPERTIES)GetProcAddress( + LoadLibrary("shell32"), "SHObjectProperties"); + + if (!pSHObjectProperties) { + pSHObjectProperties = (SHOBJECTPROPERTIES)GetProcAddress( + LoadLibrary("shell32"), (LPCSTR)SHOP_EXPORT_ORDINAL); + } + + if (pSHObjectProperties) { + path[0] = m_sTarget[0]; + + pSHObjectProperties(lpcmi->hwnd, + SHOP_FILEPATH, path, L"VFD"); + } + } + ret = ERROR_SUCCESS; + break; + + default: + return E_INVALIDARG; + } + + if (ret != ERROR_SUCCESS && + ret != ERROR_CANCELLED) { + + MessageBox(lpcmi->hwnd, + SystemMessage(ret), VFD_MSGBOX_TITLE, MB_ICONSTOP); + } + + return NOERROR; +} + +//===================================== +// perform VFD menu operation +//===================================== + +DWORD CVfdShExt::DoVfdOpen( + HWND hParent) +{ + DWORD ret = VfdGuiOpen(hParent, m_nDevice); + + if (ret != ERROR_SUCCESS && ret != ERROR_CANCELLED) { + MessageBox(hParent, SystemMessage(ret), + VFD_MSGBOX_TITLE, MB_ICONSTOP); + } + + return ret; +} + +// +// Save the VFD image +// +DWORD CVfdShExt::DoVfdSave( + HWND hParent) +{ + return VfdGuiSave(hParent, m_nDevice); +} + +// +// Close current VFD image +// +DWORD CVfdShExt::DoVfdClose( + HWND hParent) +{ + return VfdGuiClose(hParent, m_nDevice); +} + +// +// Enable/disable media write protection +// +DWORD CVfdShExt::DoVfdProtect( + HWND hParent) +{ + HANDLE hDevice; + DWORD ret; + + UNREFERENCED_PARAMETER(hParent); + VFDTRACE(0, ("CVfdShExt::DoVfdProtect()\n")); + + hDevice = VfdOpenDevice(m_nDevice); + + if (hDevice == INVALID_HANDLE_VALUE) { + return GetLastError(); + } + + ret = VfdGetMediaState(hDevice); + + if (ret == ERROR_SUCCESS) { + ret = VfdWriteProtect(hDevice, TRUE); + } + else if (ret == ERROR_WRITE_PROTECT) { + ret = VfdWriteProtect(hDevice, FALSE); + } + + if (ret == ERROR_SUCCESS) { + ret = VfdGetMediaState(hDevice); + } + + CloseHandle(hDevice); + + return ret; +} + +// +// Open dropped file with VFD +// +DWORD CVfdShExt::DoVfdDrop( + HWND hParent) +{ + HANDLE hDevice; + DWORD file_attr; + ULONG file_size; + VFD_FILETYPE file_type; + + VFD_DISKTYPE disk_type; + VFD_MEDIA media_type; + + DWORD ret; + + VFDTRACE(0, ("CVfdShExt::DoVfdDropOpen()\n")); + + // check if dropped file is a valid image + + ret = VfdCheckImageFile( + m_sTarget, &file_attr, &file_type, &file_size); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + // check file size + media_type = VfdLookupMedia(file_size); + + if (!media_type) { + PSTR msg = ModuleMessage(MSG_FILE_TOO_SMALL); + + MessageBox(hParent, msg ? msg : "Bad size", + VFD_MSGBOX_TITLE, MB_ICONSTOP); + + if (msg) { + LocalFree(msg); + } + + return ERROR_CANCELLED; + } + + if ((file_type == VFD_FILETYPE_ZIP) || + (file_attr & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_ENCRYPTED))) { + + disk_type = VFD_DISKTYPE_RAM; + } + else { + disk_type = VFD_DISKTYPE_FILE; + } + + // close current image (if opened) + + ret = DoVfdClose(hParent); + + if (ret != ERROR_SUCCESS && + ret != ERROR_NOT_READY) { + return ret; + } + + // open dropped file + + hDevice = VfdOpenDevice(m_nDevice); + + if (hDevice == INVALID_HANDLE_VALUE) { + return GetLastError(); + } + + ret = VfdOpenImage( + hDevice, m_sTarget, disk_type, media_type, FALSE); + + CloseHandle(hDevice); + + return ret; +} diff --git a/modules/rosapps/lib/vfdlib/vfdshprop.cpp b/modules/rosapps/lib/vfdlib/vfdshprop.cpp new file mode 100644 index 00000000000..54cd37f95ef --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdshprop.cpp @@ -0,0 +1,434 @@ +/* + vfdshprop.cpp + + Virtual Floppy Drive for Windows + Driver control library + COM shell extension class property sheet functions + + Copyright (c) 2003-2005 Ken Kato +*/ + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include + +#include "vfdtypes.h" +#include "vfdapi.h" +#include "vfdlib.h" +#include "vfdver.h" +#ifndef __REACTOS__ +#include "vfdmsg.h" +#else +#include "vfdmsg_lib.h" +#endif +#include "vfdguirc.h" + +// class header +#include "vfdshext.h" + +// property sheet property ID + +#define VFD_PROPERTY_ID "VFD" + +// +// local functions +// +static BOOL CALLBACK VfdPageDlgProc( + HWND hDlg, + UINT uMessage, + WPARAM wParam, + LPARAM lParam); + +static UINT CALLBACK VfdPageCallback( + HWND hWnd, + UINT uMessage, + LPPROPSHEETPAGE ppsp); + +static void OnPropInit(HWND hDlg); +static void OnControl(HWND hDlg); +static void UpdateImageInfo(HWND hDlg, ULONG nDevice); + +// +// property sheet callback function +// +UINT CALLBACK VfdPageCallback( + HWND hWnd, + UINT uMessage, + LPPROPSHEETPAGE ppsp) +{ + UNREFERENCED_PARAMETER(hWnd); + + switch(uMessage) { + case PSPCB_CREATE: + return TRUE; + + case PSPCB_RELEASE: + if (ppsp->lParam) { + ((LPCVFDSHEXT)(ppsp->lParam))->Release(); + } + return TRUE; + } + return TRUE; +} + +// +// property page dialog procedure +// +BOOL CALLBACK VfdPageDlgProc( + HWND hDlg, + UINT uMessage, + WPARAM wParam, + LPARAM lParam) +{ + LPPROPSHEETPAGE psp; + LPCVFDSHEXT lpcs; + + switch (uMessage) { + case WM_INITDIALOG: + SetWindowLong(hDlg, DWL_USER, lParam); + + if (lParam) { + lpcs = (LPCVFDSHEXT)((LPPROPSHEETPAGE)lParam)->lParam; + + OnPropInit(hDlg); + UpdateImageInfo(hDlg, lpcs->GetDevice()); + } + return TRUE; + + case WM_COMMAND: + psp = (LPPROPSHEETPAGE)GetWindowLong(hDlg, DWL_USER); + + if (!psp) { + break; + } + + lpcs = (LPCVFDSHEXT)psp->lParam; + + if (!lpcs) { + break; + } + + switch (wParam) { + case IDC_OPEN: + if (lpcs->DoVfdOpen(hDlg) == ERROR_SUCCESS) { + SendMessage((HWND)lParam, + BM_SETSTYLE, BS_PUSHBUTTON, TRUE); + } + UpdateImageInfo(hDlg, lpcs->GetDevice()); + break; + + case IDC_SAVE: + if (lpcs->DoVfdSave(hDlg) == ERROR_SUCCESS) { + SendMessage((HWND)lParam, + BM_SETSTYLE, BS_PUSHBUTTON, TRUE); + } + UpdateImageInfo(hDlg, lpcs->GetDevice()); + break; + + case IDC_CLOSE: + if (lpcs->DoVfdClose(hDlg) == ERROR_SUCCESS) { + SendMessage((HWND)lParam, + BM_SETSTYLE, BS_PUSHBUTTON, TRUE); + } + UpdateImageInfo(hDlg, lpcs->GetDevice()); + break; + + case IDC_WRITE_PROTECTED: + lpcs->DoVfdProtect(hDlg); + break; + + case IDC_FORMAT: + VfdGuiFormat(hDlg, lpcs->GetDevice()); + break; + + case IDC_CONTROL: + OnControl(hDlg); + break; + } + break; + + case WM_CONTEXTMENU: + ShowContextMenu(hDlg, (HWND)wParam, lParam); + break; + + case WM_HELP: + { + LPHELPINFO info = (LPHELPINFO)lParam; + + if (info->iContextType == HELPINFO_WINDOW) { + ShowHelpWindow(hDlg, info->iCtrlId); + } + } + return TRUE; + + default: + if (uMessage == g_nNotifyMsg) { + psp = (LPPROPSHEETPAGE)GetWindowLong(hDlg, DWL_USER); + + if (!psp) { + break; + } + + lpcs = (LPCVFDSHEXT)psp->lParam; + + if (!lpcs) { + break; + } + + UpdateImageInfo(hDlg, lpcs->GetDevice()); + } + break; + } + + return FALSE; +} + +// +// initialize the property page +// +void OnPropInit( + HWND hDlg) +{ + // set up control text + + SetDlgItemText(hDlg, IDC_PROPERTY_TITLE, VFD_PRODUCT_DESC); + SetDlgItemText(hDlg, IDC_COPYRIGHT_STR, VFD_COPYRIGHT_STR); + + SetControlText(hDlg, IDC_IMAGEFILE_LABEL, MSG_IMAGEFILE_LABEL); + SetControlText(hDlg, IDC_IMAGEDESC_LABEL, MSG_DESCRIPTION_LABEL); + SetControlText(hDlg, IDC_DISKTYPE_LABEL, MSG_DISKTYPE_LABEL); + SetControlText(hDlg, IDC_MEDIATYPE_LABEL, MSG_MEDIATYPE_LABEL); + SetControlText(hDlg, IDC_WRITE_PROTECTED, MSG_MENU_PROTECT); + SetControlText(hDlg, IDC_OPEN, MSG_OPEN_BUTTON); + SetControlText(hDlg, IDC_SAVE, MSG_SAVE_BUTTON); + SetControlText(hDlg, IDC_CLOSE, MSG_CLOSE_BUTTON); + SetControlText(hDlg, IDC_FORMAT, MSG_FORMAT_BUTTON); + SetControlText(hDlg, IDC_CONTROL, MSG_CONTROL_BUTTON); +} + +// +// Control Panel button is clicked +// +void OnControl( + HWND hDlg) +{ + CHAR module_path[MAX_PATH]; + CHAR full_path[MAX_PATH]; + PSTR file_name; + DWORD ret; + + ret = GetModuleFileName( + g_hDllModule, module_path, sizeof(module_path)); + + if (ret == 0 || ret >= sizeof(module_path)) { + file_name = full_path; + } + else { + ret = GetFullPathName( + module_path, sizeof(full_path), full_path, &file_name); + + if (ret == 0 || ret >= sizeof(full_path)) { + file_name = full_path; + } + } + + strcpy(file_name, "vfdwin.exe"); + + VFDTRACE(0, ("Starting %s\n", full_path)); + + ret = (DWORD)ShellExecute( + hDlg, NULL, full_path, NULL, NULL, SW_SHOW); + + if (ret > 32) { + PropSheet_PressButton(GetParent(hDlg), PSBTN_CANCEL); + } + else { + MessageBox(hDlg, SystemMessage(ret), + VFD_MSGBOX_TITLE, MB_ICONSTOP); + } +} + +// +// Update image information on the property page +// +void UpdateImageInfo( + HWND hDlg, + ULONG nDevice) +{ + HANDLE hDevice; + CHAR buf[MAX_PATH]; + VFD_DISKTYPE disk_type; + VFD_MEDIA media_type; + VFD_FLAGS media_flags; + VFD_FILETYPE file_type; + ULONG image_size; + DWORD attrib; + ULONG ret; + + hDevice = VfdOpenDevice(nDevice); + + if (hDevice == INVALID_HANDLE_VALUE) { + MessageBox(hDlg, + SystemMessage(GetLastError()), + VFD_MSGBOX_TITLE, MB_ICONSTOP); + return; + } + + // get current image information + + ret = VfdGetImageInfo( + hDevice, + buf, + &disk_type, + &media_type, + &media_flags, + &file_type, + &image_size); + + CloseHandle(hDevice); + + if (ret != ERROR_SUCCESS) { + MessageBox(hDlg, + SystemMessage(ret), + VFD_MSGBOX_TITLE, MB_ICONSTOP); + return; + } + + if (media_type == VFD_MEDIA_NONE) { + + // drive is empty + + SetDlgItemText(hDlg, IDC_IMAGEFILE, NULL); + SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, NULL); + SetDlgItemText(hDlg, IDC_DISKTYPE, NULL); + SetDlgItemText(hDlg, IDC_MEDIATYPE, NULL); + + EnableWindow(GetDlgItem(hDlg, IDC_WRITE_PROTECTED), FALSE); + EnableWindow(GetDlgItem(hDlg, IDC_OPEN), TRUE); + EnableWindow(GetDlgItem(hDlg, IDC_SAVE), FALSE); + EnableWindow(GetDlgItem(hDlg, IDC_CLOSE), FALSE); + EnableWindow(GetDlgItem(hDlg, IDC_FORMAT), FALSE); + + SendMessage(GetDlgItem(hDlg, IDC_OPEN), + BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); + + SetFocus(GetDlgItem(hDlg, IDC_OPEN)); + + return; + } + + // display image file name + + if (buf[0]) { + attrib = GetFileAttributes(buf); + + if (attrib == INVALID_FILE_ATTRIBUTES) { + attrib = 0; + } + } + else { + if (disk_type != VFD_DISKTYPE_FILE) { + strcpy(buf, ""); + } + attrib = 0; + } + + SetDlgItemText(hDlg, IDC_IMAGEFILE, buf); + + // display image description + + VfdMakeFileDesc(buf, sizeof(buf), + file_type, image_size, attrib); + + SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, buf); + + // display disk type + + if (disk_type == VFD_DISKTYPE_FILE) { + SetDlgItemText(hDlg, IDC_DISKTYPE, "FILE"); + } + else { + SetDlgItemText(hDlg, IDC_DISKTYPE, "RAM"); + } + + // display media type + + SetDlgItemText(hDlg, IDC_MEDIATYPE, + VfdMediaTypeName(media_type)); + + // set write protect check box + + if (media_flags & VFD_FLAG_WRITE_PROTECTED) { + CheckDlgButton(hDlg, IDC_WRITE_PROTECTED, BST_CHECKED); + } + else { + CheckDlgButton(hDlg, IDC_WRITE_PROTECTED, BST_UNCHECKED); + } + + EnableWindow(GetDlgItem(hDlg, IDC_WRITE_PROTECTED), TRUE); + EnableWindow(GetDlgItem(hDlg, IDC_OPEN), FALSE); + EnableWindow(GetDlgItem(hDlg, IDC_SAVE), TRUE); + EnableWindow(GetDlgItem(hDlg, IDC_CLOSE), TRUE); + EnableWindow(GetDlgItem(hDlg, IDC_FORMAT), TRUE); + + SendMessage(GetDlgItem(hDlg, IDC_CLOSE), + BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE); + + SetFocus(GetDlgItem(hDlg, IDC_CLOSE)); +} + +// +// CVfdShExt class members inherited from IShellPropSheetExt +// + +// Add property page +STDMETHODIMP CVfdShExt::AddPages( + LPFNADDPROPSHEETPAGE lpfnAddPage, + LPARAM lParam) +{ + PROPSHEETPAGE psp; + HPROPSHEETPAGE hpage; + + if (!m_pDataObj || m_nDevice == (ULONG)-1) { + // not a VFD drive + VFDTRACE(0, ("PropPage: Not a VFD drive\n")); + + return NOERROR; + } + + psp.dwSize = sizeof(psp); // no extra data. + psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE | PSP_USECALLBACK; + psp.hInstance = g_hDllModule; + psp.pszTemplate = MAKEINTRESOURCE(IDD_PROPDIALOG); + psp.hIcon = 0; + psp.pszTitle = "VFD"; + psp.pfnDlgProc = VfdPageDlgProc; + psp.pcRefParent = &g_cDllRefCnt; + psp.pfnCallback = VfdPageCallback; + psp.lParam = (LPARAM)this; + + AddRef(); + hpage = CreatePropertySheetPage(&psp); + + if (hpage) { + if (!lpfnAddPage(hpage, lParam)) { + DestroyPropertySheetPage(hpage); + Release(); + } + } + + return NOERROR; +} + +STDMETHODIMP CVfdShExt::ReplacePage( + UINT uPageID, + LPFNADDPROPSHEETPAGE lpfnReplaceWith, + LPARAM lParam) +{ + UNREFERENCED_PARAMETER(uPageID); + UNREFERENCED_PARAMETER(lpfnReplaceWith); + UNREFERENCED_PARAMETER(lParam); + return E_FAIL; +} diff --git a/modules/rosapps/lib/vfdlib/vfdshutil.cpp b/modules/rosapps/lib/vfdlib/vfdshutil.cpp new file mode 100644 index 00000000000..be9b8f47c83 --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdshutil.cpp @@ -0,0 +1,419 @@ +/* + vfdshutil.cpp + + Virtual Floppy Drive for Windows + Driver control library + shell extension utility functions + + Copyright (c) 2003-2005 Ken Kato +*/ + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +#include "vfdtypes.h" +#include "vfdapi.h" +#include "vfdlib.h" +#include "vfdshcfact.h" + +//===================================== +// Initialize the GUID instance +//===================================== + +#ifdef _MSC_VER +#pragma data_seg(".text") +#endif +#define INITGUID +#include +#include +#include "vfdshguid.h" +#ifdef _MSC_VER +#pragma data_seg() +#endif + +// +// Registry path to the approved shell extensions key +// +#define REGKEY_APPROVED \ + "Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved" + + +//===================================== +// Shell extension library requirements +//===================================== + +// +// Creates a class factory instance +// +STDAPI DllGetClassObject( + REFCLSID rclsid, + REFIID riid, + LPVOID *ppvOut) +{ + VFDTRACE(0, + ("DllGetClassObject\n")); + + *ppvOut = NULL; + + if (IsEqualIID(rclsid, CLSID_VfdShellExt)) { + CVfdFactory *pFactory = new CVfdFactory; + + if (!pFactory) { + return E_OUTOFMEMORY; + } + + return pFactory->QueryInterface(riid, ppvOut); + } + + return CLASS_E_CLASSNOTAVAILABLE; +} + +// +// DllCanUnloadNow +// +STDAPI DllCanUnloadNow(void) +{ + VFDTRACE(0, + ("DllCanUnloadNow - %s\n", (g_cDllRefCnt ? "No" : "Yes"))); + + return (g_cDllRefCnt ? S_FALSE : S_OK); +} + +//===================================== +// Shell extension register functions +//===================================== + +static inline void MakeGuidString(LPTSTR str, const GUID &guid) +{ + sprintf(str, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + guid.Data1, guid.Data2, guid.Data3, + guid.Data4[0], guid.Data4[1], + guid.Data4[2], guid.Data4[3], guid.Data4[4], + guid.Data4[5], guid.Data4[6], guid.Data4[7]); +} + +// +// Regster this dll as shell extention handlers +// +DWORD WINAPI VfdRegisterHandlers() +{ + TCHAR buf[MAX_PATH]; + TCHAR guid_str[40]; + HKEY hKey; + DWORD temp; + DWORD ret; + + MakeGuidString(guid_str, CLSID_VfdShellExt); + + // + // Register the GUID in the CLSID subtree + // + sprintf(buf, "CLSID\\%s", guid_str); + + VFDTRACE(0, ("HKCR\\%s\n", buf)); + + ret = RegCreateKeyEx( + HKEY_CLASSES_ROOT, buf, 0, NULL, + 0, KEY_ALL_ACCESS, NULL, &hKey, &temp); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + if (temp == REG_OPENED_EXISTING_KEY) { + temp = sizeof(buf); + + ret = RegQueryValueEx( + hKey, NULL, NULL, NULL, (PBYTE)buf, &temp); + + if (ret != ERROR_SUCCESS) { + RegCloseKey(hKey); + return ret; + } + + if (_stricmp(buf, VFDEXT_DESCRIPTION)) { + RegCloseKey(hKey); + return ERROR_FILE_EXISTS; + } + } + else { + + VFDTRACE(0, ("@=" VFDEXT_DESCRIPTION "\n")); + + ret = RegSetValueEx(hKey, NULL, NULL, REG_SZ, + (PBYTE)VFDEXT_DESCRIPTION, sizeof(VFDEXT_DESCRIPTION)); + + RegCloseKey(hKey); + + if (ret != ERROR_SUCCESS) { + return ret; + } + } + + // + // Register the executable path + // + sprintf(buf, "CLSID\\%s\\InProcServer32", guid_str); + + VFDTRACE(0, ("HKCR\\%s\n", buf)); + + ret = RegCreateKeyEx( + HKEY_CLASSES_ROOT, buf, 0, NULL, + 0, KEY_ALL_ACCESS, NULL, &hKey, NULL); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + temp = GetModuleFileName(g_hDllModule, buf, sizeof(buf)); + + VFDTRACE(0, ("@=%s\n", buf)); + + ret = RegSetValueEx( + hKey, NULL, NULL, REG_SZ, (PBYTE)buf, temp + 1); + + if (ret != ERROR_SUCCESS) { + RegCloseKey(hKey); + return ret; + } + + VFDTRACE(0, ("ThreadingModel=Apartment\n")); + + ret = RegSetValueEx(hKey, "ThreadingModel", NULL, REG_SZ, + (PBYTE)"Apartment", sizeof("Apartment")); + + RegCloseKey(hKey); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + // + // Register context menu handler + // + VFDTRACE(0, ("HKCR\\" VFDEXT_MENU_REGKEY "\n")); + + ret = RegCreateKeyEx( + HKEY_CLASSES_ROOT, VFDEXT_MENU_REGKEY, 0, NULL, + 0, KEY_ALL_ACCESS, NULL, &hKey, NULL); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + VFDTRACE(0, ("@=%s\n", guid_str)); + + ret = RegSetValueEx(hKey, NULL, NULL, REG_SZ, + (PBYTE)guid_str, strlen(guid_str) + 1); + + RegCloseKey(hKey); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + // + // Register Drag&Drop handler + // + if (!IS_WINDOWS_NT()) { + // + // Windows NT does not support Drag&Drop handlers ??? + // + VFDTRACE(0, ("HKCR\\" VFDEXT_DND_REGKEY "\n")); + + ret = RegCreateKeyEx( + HKEY_CLASSES_ROOT, VFDEXT_DND_REGKEY, 0, NULL, + 0, KEY_ALL_ACCESS, NULL, &hKey, NULL); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + VFDTRACE(0, ("@=%s\n", guid_str)); + + ret = RegSetValueEx(hKey, NULL, NULL, REG_SZ, + (PBYTE)guid_str, strlen(guid_str) + 1); + + RegCloseKey(hKey); + + if (ret != ERROR_SUCCESS) { + return ret; + } + } + + // + // Register property sheet handler + // + VFDTRACE(0, ("HKCR\\" VFDEXT_PROP_REGKEY "\n")); + + ret = RegCreateKeyEx( + HKEY_CLASSES_ROOT, VFDEXT_PROP_REGKEY, 0, NULL, + 0, KEY_ALL_ACCESS, NULL, &hKey, NULL); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + VFDTRACE(0, ("@=%s\n", guid_str)); + + ret = RegSetValueEx(hKey, NULL, NULL, REG_SZ, + (PBYTE)guid_str, strlen(guid_str) + 1); + + RegCloseKey(hKey); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + // + // Register approved extensions entry + // + VFDTRACE(0, ("HKLM\\" REGKEY_APPROVED "\n")); + + ret = RegCreateKeyEx( + HKEY_LOCAL_MACHINE, REGKEY_APPROVED, + 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, NULL); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + VFDTRACE(0, + ("%s=" VFDEXT_DESCRIPTION "\n", guid_str)); + + ret = RegSetValueEx(hKey, guid_str, NULL, REG_SZ, + (PBYTE)VFDEXT_DESCRIPTION, sizeof(VFDEXT_DESCRIPTION)); + + RegCloseKey(hKey); + + return ret; +} + +// +// Unregister context menu handler +// +DWORD WINAPI VfdUnregisterHandlers() +{ + TCHAR buf[MAX_PATH]; + TCHAR guid_str[40]; + HKEY hKey; + DWORD temp; + DWORD ret; + + MakeGuidString(guid_str, CLSID_VfdShellExt); + + sprintf(buf, "CLSID\\%s", guid_str); + + VFDTRACE(0, ("HKCR\\%s\n", buf)); + + temp = sizeof(buf); + + ret = RegQueryValue(HKEY_CLASSES_ROOT, buf, buf, (PLONG)&temp); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + if (_stricmp(buf, VFDEXT_DESCRIPTION)) { + return ERROR_PATH_NOT_FOUND; + } + + sprintf(buf, "CLSID\\%s\\InProcServer32", guid_str); + + VFDTRACE(0, ("HKCR\\%s\n", buf)); + + ret = RegDeleteKey(HKEY_CLASSES_ROOT, buf); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + sprintf(buf, "CLSID\\%s", guid_str); + + VFDTRACE(0, ("HKCR\\%s\n", buf)); + + ret = RegDeleteKey(HKEY_CLASSES_ROOT, buf); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + VFDTRACE(0, ("HKCR\\" VFDEXT_MENU_REGKEY "\n")); + + ret = RegDeleteKey(HKEY_CLASSES_ROOT, VFDEXT_MENU_REGKEY); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + if (!IS_WINDOWS_NT()) { + + // Windows NT doesn't support Drag & Drop handlers ??? + + VFDTRACE(0, ("HKCR\\" VFDEXT_DND_REGKEY "\n")); + + ret = RegDeleteKey(HKEY_CLASSES_ROOT, VFDEXT_DND_REGKEY); + + if (ret != ERROR_SUCCESS) { + return ret; + } + } + + VFDTRACE(0, ("HKCR\\" VFDEXT_PROP_REGKEY "\n")); + + ret = RegDeleteKey(HKEY_CLASSES_ROOT, VFDEXT_PROP_REGKEY); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + VFDTRACE(0, ("HKLM\\" REGKEY_APPROVED "\n")); + + ret = RegCreateKeyEx( + HKEY_LOCAL_MACHINE, + REGKEY_APPROVED, + 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, NULL); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + ret = RegDeleteValue(hKey, guid_str); + + RegCloseKey(hKey); + + return ret; +} + +// +// Check if context menu handler is registered +// +DWORD WINAPI VfdCheckHandlers() +{ + TCHAR buf[MAX_PATH]; + TCHAR guid_str[40]; + DWORD temp; + DWORD ret; + + MakeGuidString(guid_str, CLSID_VfdShellExt); + + sprintf(buf, "CLSID\\%s", guid_str); + + VFDTRACE(0, ("HKCR\\%s\n", buf)); + + temp = sizeof(buf); + + ret = RegQueryValue(HKEY_CLASSES_ROOT, buf, buf, (PLONG)&temp); + + if (ret != ERROR_SUCCESS) { + return ret; + } + + if (_stricmp(buf, VFDEXT_DESCRIPTION)) { + return ERROR_PATH_NOT_FOUND; + } + + return ERROR_SUCCESS; +} diff --git a/modules/rosapps/lib/vfdlib/vfdzip.c b/modules/rosapps/lib/vfdlib/vfdzip.c new file mode 100644 index 00000000000..710428fa858 --- /dev/null +++ b/modules/rosapps/lib/vfdlib/vfdzip.c @@ -0,0 +1,422 @@ +/* + vfdzip.c + + Virtual Floppy Drive for Windows + Driver control library + Zip compressed floppy image handling + + Copyright (C) 2003-2005 Ken Kato +*/ + +#ifdef __cplusplus +#pragma message(__FILE__": Compiled as C++ for testing purpose.") +#endif // __cplusplus + +#define WIN32_LEAN_AND_MEAN +#include + +#include "vfdtypes.h" +#include "vfdio.h" +#include "vfdlib.h" + +#ifndef __REACTOS__ +#define ZLIB_WINAPI +#else +#define Z_SOLO +#define ZLIB_INTERNAL +#endif +#include "zlib.h" + +#ifdef VFD_NO_ZLIB +#pragma message("ZIP image support is disabled.") + +DWORD ExtractZipInfo( + HANDLE hFile, + ULONG *pSize) +{ + UNREFERENCED_PARAMETER(hFile); + UNREFERENCED_PARAMETER(pSize); + return ERROR_NOT_SUPPORTED; +} + +DWORD ExtractZipImage( + HANDLE hFile, + PUCHAR *pBuffer, + PULONG pLength) +{ + UNREFERENCED_PARAMETER(hFile); + UNREFERENCED_PARAMETER(pBuffer); + UNREFERENCED_PARAMETER(pLength); + return ERROR_NOT_SUPPORTED; +} + +#else // VFD_NO_ZLIB + +#ifdef _DEBUG +static const char *ZLIB_ERROR(int err) +{ + switch (err) { + case Z_OK : return "Z_OK"; + case Z_STREAM_END : return "Z_STREAM_END"; + case Z_NEED_DICT : return "Z_NEED_DICT"; + case Z_ERRNO : return "Z_ERRNO"; + case Z_STREAM_ERROR : return "Z_STREAM_ERROR"; + case Z_DATA_ERROR : return "Z_DATA_ERROR"; + case Z_MEM_ERROR : return "Z_MEM_ERROR"; + case Z_BUF_ERROR : return "Z_BUF_ERROR"; + case Z_VERSION_ERROR: return "Z_VERSION_ERROR"; + default : return "unknown"; + } +} +#endif // _DEBUG + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)) +{ + UNREFERENCED_PARAMETER(opaque); + return LocalAlloc(LPTR, items * size); +} + +void zcfree OF((voidpf opaque, voidpf ptr)) +{ + UNREFERENCED_PARAMETER(opaque); + LocalFree(ptr); +} + +#define ZIP_LOCAL_SIGNATURE 0x04034b50 + +#define ZIP_FLAG_ENCRYPTED 0x01 + +#define ZIP_FLAG_DEFLATE_NORMAL 0x00 +#define ZIP_FLAG_DEFLATE_MAX 0x02 +#define ZIP_FLAG_DEFLATE_FAST 0x04 +#define ZIP_FLAG_DEFLATE_SUPER 0x06 +#define ZIP_FLAG_DEFLATE_MASK 0x06 + +#define ZIP_FLAG_SIZE_IN_DESC 0x08 + +#define ZIP_METHOD_STORED 0 +#define ZIP_METHOD_SHRUNK 1 +#define ZIP_METHOD_REDUCED1 2 +#define ZIP_METHOD_REDUCED2 3 +#define ZIP_METHOD_REDUCED3 4 +#define ZIP_METHOD_REDUCED4 5 +#define ZIP_METHOD_IMPLODED 6 +#define ZIP_METHOD_TOKENIZED 7 +#define ZIP_METHOD_DEFLATED 8 +#define ZIP_METHOD_DEFLATE64 9 +#define ZIP_METHOD_PKWARE_IMP 10 +#define ZIP_METHOD_RESERVED 11 +#define ZIP_METHOD_BZIP2 12 + +#pragma pack(1) + +typedef struct _zip_local_file_header { + ULONG header_signature; + USHORT required_version; + USHORT general_flags; + USHORT compression_method; + USHORT last_mod_time; + USHORT last_mod_date; + ULONG crc32; + ULONG compressed_size; + ULONG uncompressed_size; + USHORT file_name_length; + USHORT extra_field_length; + CHAR file_name[1]; + // followed by extra field data, then compressed data +} +ZIP_HEADER, *PZIP_HEADER; + +// +// Check if the file is ZIP compressed +// +DWORD ExtractZipInfo( + HANDLE hFile, + ULONG *pSize) +{ + ZIP_HEADER zip_hdr; + DWORD result; + DWORD ret; + + if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) != 0) { + ret = GetLastError(); + + VFDTRACE(0, + ("SetFilePointer() - %s\n", + SystemMessage(ret))); + + return ret; + } + + if (!ReadFile(hFile, &zip_hdr, sizeof(zip_hdr), &result, NULL)) { + ret = GetLastError(); + + VFDTRACE(0, + ("ReadFile() - %s\n", + SystemMessage(ret))); + + return ret; + } + + if (result != sizeof(zip_hdr) || + zip_hdr.header_signature != ZIP_LOCAL_SIGNATURE || + zip_hdr.compression_method != ZIP_METHOD_DEFLATED || + (zip_hdr.general_flags & ZIP_FLAG_ENCRYPTED)) { + + VFDTRACE(0, + ("[VFD] Invalid ZIP file\n")); + + return ERROR_INVALID_DATA; + } + + // correct (and supported) ZIP header detected + + *pSize = zip_hdr.uncompressed_size; + + return ERROR_SUCCESS; +} + +// +// Extract original data from IMZ file +// +DWORD ExtractZipImage( + HANDLE hFile, + PUCHAR *pBuffer, + PULONG pLength) +{ + UCHAR buf[VFD_BYTES_PER_SECTOR]; + DWORD result; + DWORD ret; + + PZIP_HEADER zip_hdr; + ULONG compressed; + ULONG uncompressed; + PUCHAR file_cache; + z_stream stream; + int zlib_ret; + + VFDTRACE(0, + ("[VFD] VfdExtractImz - IN\n")); + + *pBuffer = NULL; + *pLength = 0; + + // + // Read PKZIP local file header of the first file in the file + // -- An IMZ file actually is just a ZIP file with a different + // extension, which contains a single floppy image file + // + if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) != 0) { + ret = GetLastError(); + + VFDTRACE(0,( + "SetFilePointer - %s", SystemMessage(ret)));; + + return ret; + } + + if (!ReadFile(hFile, buf, VFD_BYTES_PER_SECTOR, &result, NULL) || + result < VFD_BYTES_PER_SECTOR) { + + ret = GetLastError(); + + VFDTRACE(0,( + "ReadFile - %s", SystemMessage(ret)));; + + return ret; + } + + zip_hdr = (PZIP_HEADER)buf; + + // check local file header signature + + if (zip_hdr->header_signature != ZIP_LOCAL_SIGNATURE) { + + VFDTRACE(0, + ("[VFD] PKZIP header signature not found.\n")); + + return ERROR_INVALID_DATA; + } + + // check compression method + + if (zip_hdr->compression_method != Z_DEFLATED) { + + VFDTRACE(0, + ("[VFD] Bad PKZIP compression method.\n")); + + return ERROR_NOT_SUPPORTED; + } + + if (zip_hdr->general_flags & 0x01) { + // encrypted zip not supported + + VFDTRACE(0, + ("[VFD] PKZIP encrypted.\n")); + + return ERROR_NOT_SUPPORTED; + } + + // check uncompressed image size + + compressed = zip_hdr->compressed_size; + uncompressed = zip_hdr->uncompressed_size; + + switch (uncompressed) { + case VFD_SECTOR_TO_BYTE(320): + case VFD_SECTOR_TO_BYTE(360): + case VFD_SECTOR_TO_BYTE(640): + case VFD_SECTOR_TO_BYTE(720): + case VFD_SECTOR_TO_BYTE(1280): + case VFD_SECTOR_TO_BYTE(1440): + case VFD_SECTOR_TO_BYTE(1640): + case VFD_SECTOR_TO_BYTE(2400): + case VFD_SECTOR_TO_BYTE(2880): + case VFD_SECTOR_TO_BYTE(3360): + case VFD_SECTOR_TO_BYTE(3444): + case VFD_SECTOR_TO_BYTE(5760): + break; + + default: + VFDTRACE(0, + ("[VFD] Unsupported image size %lu.\n", + uncompressed)); + + return ERROR_NOT_SUPPORTED; + } + + // check local file header length + // -- Just for simplicity, the compressed data must start in the + // first sector in the file: this is not a problem in most cases. + + if (FIELD_OFFSET(ZIP_HEADER, file_name) + + zip_hdr->file_name_length + + zip_hdr->extra_field_length >= VFD_BYTES_PER_SECTOR) { + + VFDTRACE(0, + ("[VFD] PKZIP header too long.\n")); + + return ERROR_NOT_SUPPORTED; + } + + // allocate memory to store uncompressed data + + file_cache = (PUCHAR)LocalAlloc(LPTR, uncompressed); + + if (!file_cache) { + + VFDTRACE(0, + ("[VFD] Failed to allocate file cache.\n")); + + return ERROR_OUTOFMEMORY; + } + + // initialize the zlib stream + + ZeroMemory(&stream, sizeof(stream)); + + // set initial input data information + + stream.next_in = (PUCHAR)zip_hdr->file_name + + zip_hdr->file_name_length + zip_hdr->extra_field_length; + + stream.avail_in = VFD_BYTES_PER_SECTOR - + FIELD_OFFSET(ZIP_HEADER, file_name) - + zip_hdr->file_name_length - zip_hdr->extra_field_length; + + // set output buffer information + + stream.next_out = file_cache; + stream.avail_out = uncompressed; + + zlib_ret = inflateInit2(&stream, -MAX_WBITS); + + // negative MAX_WBITS value passed to the inflateInit2() function + // indicates that there is no zlib header. + // In this case inflate() function requires an extra "dummy" byte + // after the compressed stream in order to complete decompression + // and return Z_STREAM_END. However, both compressed and uncompressed + // data size are already known from the pkzip header, Z_STREAM_END + // is not absolutely necessary to know the completion of the operation. + + if (zlib_ret != Z_OK) { + LocalFree(file_cache); + + VFDTRACE(0, + ("[VFD] inflateInit2() failed - %s.\n", + ZLIB_ERROR(zlib_ret))); + + return ERROR_INVALID_FUNCTION; + } + + for (;;) { + + // uncompress current block + + zlib_ret = inflate(&stream, Z_NO_FLUSH); + + if (zlib_ret != Z_OK) { + if (zlib_ret == Z_STREAM_END) { + ret = ERROR_SUCCESS; + } + else { + VFDTRACE(0, + ("[VFD] inflate() failed - %s.\n", + ZLIB_ERROR(zlib_ret))); + + ret = ERROR_INVALID_FUNCTION; + } + break; + } + + if (stream.total_out >= uncompressed) { + // uncompress completed - no need to wait for Z_STREAM_END + // (inflate() would return Z_STREAM_END on the next call) + ret = ERROR_SUCCESS; + break; + } + + if (stream.total_in >= compressed) { + // somehow there is not enought compressed data + ret = ERROR_INVALID_FUNCTION; + break; + } + + // read next block from file + + if (!ReadFile(hFile, buf, VFD_BYTES_PER_SECTOR, &result, NULL) || + result <= 0) { + + ret = GetLastError(); + + VFDTRACE(0, + ("[VFD] Read compressed data - %s.\n", + SystemMessage(ret))); + break; + } + + stream.avail_in = result; + stream.next_in = buf; + } + + // cleanup the zlib stream + + inflateEnd(&stream); + + // set the return information + + if (ret == ERROR_SUCCESS) { + *pBuffer = file_cache; + *pLength = uncompressed; + } + else { + LocalFree(file_cache); + } + + VFDTRACE(0, + ("[VFD] VfdExtractImz - OUT\n")); + + return ret; +} + +#endif // VFD_NO_ZLIB