[VFD] Import the VFD project (Virtual Floppy Drive) which allows creating virtual
authorPierre Schweitzer <pierre@reactos.org>
Sat, 16 Dec 2017 20:48:17 +0000 (21:48 +0100)
committerPierre Schweitzer <pierre@reactos.org>
Sat, 16 Dec 2017 20:48:34 +0000 (21:48 +0100)
floppy drives in ReactOS and mount images on them.
Only the cmd got imported. The GUI interface may come later on.
Note that, as for vcdrom, the driver is left disabled and you need to explicitely
start it through vfd command line interface.

CORE-14090

58 files changed:
modules/rosapps/CMakeLists.txt
modules/rosapps/applications/cmdutils/CMakeLists.txt
modules/rosapps/applications/cmdutils/vfdcmd/CMakeLists.txt [new file with mode: 0644]
modules/rosapps/applications/cmdutils/vfdcmd/vfdcmd.c [new file with mode: 0644]
modules/rosapps/applications/cmdutils/vfdcmd/vfdcmd.rc [new file with mode: 0644]
modules/rosapps/applications/cmdutils/vfdcmd/vfdcmd.rs [new file with mode: 0644]
modules/rosapps/applications/cmdutils/vfdcmd/vfdmsg.mc [new file with mode: 0644]
modules/rosapps/drivers/CMakeLists.txt
modules/rosapps/drivers/vfd/CMakeLists.txt [new file with mode: 0644]
modules/rosapps/drivers/vfd/imports.h [new file with mode: 0644]
modules/rosapps/drivers/vfd/vfd_reg.inf [new file with mode: 0644]
modules/rosapps/drivers/vfd/vfddbg.c [new file with mode: 0644]
modules/rosapps/drivers/vfd/vfddbg.h [new file with mode: 0644]
modules/rosapps/drivers/vfd/vfddev.c [new file with mode: 0644]
modules/rosapps/drivers/vfd/vfddrv.c [new file with mode: 0644]
modules/rosapps/drivers/vfd/vfddrv.h [new file with mode: 0644]
modules/rosapps/drivers/vfd/vfddrv.rc [new file with mode: 0644]
modules/rosapps/drivers/vfd/vfdfmt.c [new file with mode: 0644]
modules/rosapps/drivers/vfd/vfdimg.c [new file with mode: 0644]
modules/rosapps/drivers/vfd/vfdioctl.c [new file with mode: 0644]
modules/rosapps/drivers/vfd/vfdlink.c [new file with mode: 0644]
modules/rosapps/drivers/vfd/vfdmnt.c [new file with mode: 0644]
modules/rosapps/drivers/vfd/vfdpnp.c [new file with mode: 0644]
modules/rosapps/drivers/vfd/vfdrdwr.c [new file with mode: 0644]
modules/rosapps/include/CMakeLists.txt [new file with mode: 0644]
modules/rosapps/include/vfd/CMakeLists.txt [new file with mode: 0644]
modules/rosapps/include/vfd/vfdapi.h [new file with mode: 0644]
modules/rosapps/include/vfd/vfdio.h [new file with mode: 0644]
modules/rosapps/include/vfd/vfdtypes.h [new file with mode: 0644]
modules/rosapps/include/vfd/vfdver.h [new file with mode: 0644]
modules/rosapps/include/vfd/vfdver.rc [new file with mode: 0644]
modules/rosapps/lib/CMakeLists.txt
modules/rosapps/lib/vfdlib/CMakeLists.txt [new file with mode: 0644]
modules/rosapps/lib/vfdlib/res/config.ico [new file with mode: 0644]
modules/rosapps/lib/vfdlib/res/image.ico [new file with mode: 0644]
modules/rosapps/lib/vfdlib/res/vfd.ico [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdctl.c [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdfat.c [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdguiopen.c [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdguirc.h [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdguisave.c [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdguitip.c [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdguiut.c [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdlib.c [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdlib.h [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdlib.rc [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdlib.rs [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdlib.spec [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdmsg_lib.mc [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdshcfact.cpp [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdshcfact.h [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdshext.cpp [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdshext.h [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdshguid.h [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdshmenu.cpp [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdshprop.cpp [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdshutil.cpp [new file with mode: 0644]
modules/rosapps/lib/vfdlib/vfdzip.c [new file with mode: 0644]

index 7ffa0b4..58a32c1 100644 (file)
@@ -1,6 +1,7 @@
 add_subdirectory(applications)
 add_subdirectory(demos)
 add_subdirectory(drivers)
+add_subdirectory(include)
 add_subdirectory(lib)
 add_subdirectory(templates)
 
index 843b2c5..6d5488d 100644 (file)
@@ -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 (file)
index 0000000..fa653f1
--- /dev/null
@@ -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 (file)
index 0000000..8cd40bf
--- /dev/null
@@ -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 <windows.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <crtdbg.h>
+
+#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 <ctrl+c>
+
+                       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 : "<RAM>");
+               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, "<RAM>");
+
+               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', <esc> or <Ctrl+C> ?
+
+               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 (file)
index 0000000..6f4b582
--- /dev/null
@@ -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 <reactos/version.rc>
+
+#include <vfdmsg.rc>
diff --git a/modules/rosapps/applications/cmdutils/vfdcmd/vfdcmd.rs b/modules/rosapps/applications/cmdutils/vfdcmd/vfdcmd.rs
new file mode 100644 (file)
index 0000000..3956ecc
--- /dev/null
@@ -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 <winver.h>
+#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 \83R\83\93\83\\81[\83\8b"
+#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 (file)
index 0000000..222c04d
--- /dev/null
@@ -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      : <none>
+.
+
+
+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   <drive>:
+    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.
+
+  <drive>:  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 | <Ctrl+C>
+            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 .<drive>: 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 <Ctrl+C> to quit) ...%0
+.
+
+
+;
+;#endif // _VFDMSG_H_
index 61a8e43..18def36 100644 (file)
@@ -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 (file)
index 0000000..1c23423
--- /dev/null
@@ -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 (file)
index 0000000..8a9ca90
--- /dev/null
@@ -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 <ntddk.h>
+#include <ntdddisk.h>
+#include <ntverp.h>
+#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 <mountdev.h>
+#else  // (VER_PRODUCTBUILD < 2195)
+//
+// Imports from Windows 2000 DDK <ntddk.h>
+//
+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 <ntddstor.h>
+//
+#define IOCTL_STORAGE_CHECK_VERIFY2                    CTL_CODE(                               \
+                                                                                               IOCTL_STORAGE_BASE, \
+                                                                                               0x0200,                         \
+                                                                                               METHOD_BUFFERED,        \
+                                                                                               FILE_ANY_ACCESS)
+
+//
+//     Imports from Windows 2000 DDK <mountmgr.h>, <mountdev.h>
+//
+#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 <ntdddisk.h>
+//
+#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 <ntddstor.h>
+//
+#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 <mountdev.h>
+//
+#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 (file)
index 0000000..110bfed
--- /dev/null
@@ -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 (file)
index 0000000..829f25b
--- /dev/null
@@ -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 <ntdddisk.h>
+#ifndef __REACTOS__
+#include <ntddft.h>
+#endif
+#include <ntddstor.h>
+
+#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 <mountmgr.h>
+#include <mountdev.h>
+#ifndef __REACTOS__
+#include <ntddft2.h>
+#endif
+#include <ntddvol.h>
+
+#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 <ntstatus.h>
+//
+#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 (file)
index 0000000..08bf8c5
--- /dev/null
@@ -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 (file)
index 0000000..6aee0bc
--- /dev/null
@@ -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<n>
+       //
+       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<n>)
+
+       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 (file)
index 0000000..feefaff
--- /dev/null
@@ -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.Buf