ReactOS  0.4.12-dev-375-g61fed54
vfdcmd.c
Go to the documentation of this file.
1 /*
2  vfdcmd.c
3 
4  Virtual Floppy Drive for Windows
5  Driver control program (console version)
6 
7  Copyright (C) 2003-2008 Ken Kato
8 */
9 
10 #ifdef __cplusplus
11 #pragma message(__FILE__": Compiled as C++ for testing purpose.")
12 #endif // __cplusplus
13 
14 #define WIN32_LEAN_AND_MEAN
15 #define _CRTDBG_MAP_ALLOC
16 #include <windows.h>
17 #include <stdio.h>
18 #include <stdarg.h>
19 #include <stdlib.h>
20 #include <crtdbg.h>
21 
22 #ifndef INVALID_FILE_ATTRIBUTES
23 #define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
24 #endif // INVALID_FILE_ATTRIBUTES
25 
26 #include "vfdtypes.h"
27 #include "vfdapi.h"
28 #include "vfdver.h"
29 #include "vfdmsg.h"
30 
31 //
32 // current driver state
33 //
35 
36 //
37 // interactive flag
38 //
39 static const char *help_progname = "VFD.EXE ";
40 
41 //
42 // command functions return value
43 //
44 #define VFD_OK 0
45 #define VFD_NG 1
46 
47 //
48 // operation mode
49 //
50 #define OPERATION_ASK 0 // ask user on error
51 #define OPERATION_QUIT 1 // quits on error
52 #define OPERATION_FORCE 2 // force on error
53 
54 //
55 // invalid target number
56 //
57 #define TARGET_NONE (ULONG)-1
58 
59 //
60 // command processing functions
61 //
62 typedef int (*cmdfnc)(const char **args);
63 
64 static int Install(const char **args);
65 static int Remove(const char **args);
66 static int Config(const char **args);
67 static int Start(const char **args);
68 static int Stop(const char **args);
69 static int Shell(const char **args);
70 static int Open(const char **args);
71 static int Close(const char **args);
72 static int Save(const char **args);
73 static int Protect(const char **args);
74 static int Format(const char **args);
75 static int Link(const char **args);
76 static int Unlink(const char **args);
77 static int Status(const char **args);
78 static int Help(const char **args);
79 static int Version(const char **args);
80 
81 //
82 // Command table
83 //
84 static const struct {
85  char *cmd; // command string
86  int max_args; // maximum allowed number of argc
87  cmdfnc func; // command processing function
88  DWORD hint; // command hint message id
89 }
90 Commands[] = {
91  {"INSTALL", 2, Install, MSG_HINT_INSTALL},
92  {"REMOVE", 1, Remove, MSG_HINT_REMOVE },
93  {"CONFIG", 1, Config, MSG_HINT_CONFIG },
94  {"START", 0, Start, MSG_HINT_START },
95  {"STOP", 1, Stop, MSG_HINT_STOP },
96  {"SHELL", 1, Shell, MSG_HINT_SHELL },
97  {"OPEN", 6, Open, MSG_HINT_OPEN },
98  {"CLOSE", 2, Close, MSG_HINT_CLOSE },
99  {"SAVE", 3, Save, MSG_HINT_SAVE, },
100  {"PROTECT", 2, Protect, MSG_HINT_PROTECT},
101  {"FORMAT", 2, Format, MSG_HINT_FORMAT },
102  {"LINK", 3, Link, MSG_HINT_LINK },
103  {"ULINK", 1, Unlink, MSG_HINT_ULINK },
104  {"STATUS", 0, Status, MSG_HINT_STATUS },
105  {"HELP", 1, Help, MSG_HELP_HELP },
106  {"?", 1, Help, MSG_HELP_HELP },
107  {"VERSION", 0, Version, MSG_HINT_VERSION},
108  {0, 0, 0, 0}
109 };
110 
111 //
112 // Help message table
113 //
114 static const struct {
115  char *keyword; // help keyword
116  DWORD help; // help message id
117 }
118 HelpMsg[] = {
119  {"GENERAL", MSG_HELP_GENERAL},
120  {"CONSOLE", MSG_HELP_CONSOLE},
121  {"INSTALL", MSG_HELP_INSTALL},
122  {"REMOVE", MSG_HELP_REMOVE },
123  {"CONFIG", MSG_HELP_CONFIG },
124  {"START", MSG_HELP_START },
125  {"STOP", MSG_HELP_STOP },
126  {"SHELL", MSG_HELP_SHELL },
127  {"OPEN", MSG_HELP_OPEN },
128  {"CLOSE", MSG_HELP_CLOSE },
129  {"SAVE", MSG_HELP_SAVE },
130  {"PROTECT", MSG_HELP_PROTECT},
131  {"FORMAT", MSG_HELP_FORMAT },
132  {"LINK", MSG_HELP_LINK },
133  {"ULINK", MSG_HELP_ULINK },
134  {"STATUS", MSG_HELP_STATUS },
135  {"HELP", MSG_HELP_HELP },
136  {"VERSION", MSG_HINT_VERSION},
137  {0, 0}
138 };
139 
140 //
141 // local functions
142 //
143 static int InteractiveConsole();
144 static int ProcessCommandLine(int argc, const char **args);
145 static int ParseCommand(const char *cmd);
146 static int ParseHelpTopic(const char *topic);
147 static int CheckDriver();
148 static int InputChar(ULONG msg, PCSTR ans);
149 static void PrintImageInfo(HANDLE hDevice);
150 static void PrintDriveLetter(HANDLE hDevice, ULONG nDrive);
151 static void PrintMessage(UINT msg, ...);
152 static BOOL ConsolePager(char *pBuffer, BOOL bReset);
153 static const char *SystemError(DWORD err);
154 static void ConvertPathCase(char *src, char *dst);
155 
156 //
157 // utility macro
158 //
159 #define IS_WINDOWS_NT() ((GetVersion() & 0xff) < 5)
160 
161 //
162 // main
163 //
164 int main(int argc, const char **argv)
165 {
166 #ifdef _DEBUG
167 
168  // output vfd.exe command reference text
169 
170  if (*(argv + 1) && !_stricmp(*(argv + 1), "doc")) {
171  int idx = 0;
172  char *buf = "";
173 
174  printf("\r\n VFD.EXE Command Reference\r\n");
175 
176  while (HelpMsg[idx].keyword) {
177  int len = strlen(HelpMsg[idx].keyword);
178 
179  printf(
180  "\r\n\r\n"
181  "====================\r\n"
182  "%*s\r\n"
183  "====================\r\n"
184  "\r\n",
185  (20 + len) / 2, HelpMsg[idx].keyword);
186 
191  NULL, HelpMsg[idx].help, 0,
192  (LPTSTR)&buf, 0, (va_list *)&help_progname);
193 
194  printf("%s", buf);
195 
196  LocalFree(buf);
197 
198  idx++;
199  }
200 
201  return 0;
202  }
203 #endif
204 
205  // Reports memory leaks at process termination
206 
208 
209  // Check the operating system version
210 
211  if (!VfdIsValidPlatform()) {
212  PrintMessage(MSG_WRONG_PLATFORM);
213  return VFD_NG;
214  }
215 
216  if (argc < 2) {
217  // If no parameter is given, enter the interactive mode
218 
219  return InteractiveConsole();
220  }
221  else {
222  // Perform a single operation
223 
224  return ProcessCommandLine(argc - 1, argv + 1);
225  }
226 }
227 
228 //
229 // VFD interactive console
230 //
232 {
233  char input[1024]; // user input buffer
234 
235  int argc; // number of args in the user input
236  char *args[10]; // args to pass to command functions
237 
238  char sepa; // argument separator
239  char *p; // work pointer
240 
241  // Disable the system default Ctrl+C handler
242 
244 
245  // Set the console title
246 
248 
249  // print version information and the console hint text
250 
251  Version(NULL);
252 
253  PrintMessage(MSG_CONSOLE_HINT);
254 
255  // set interactive flag to exclude "VFD.EXE" from help text
256 
257  help_progname = "";
258 
259  // process user input
260 
261  for (;;) {
262 
263  // print the prompt
264 
265  printf("[VFD] ");
266  fflush(stdout);
267 
268  // read user input
269 
270  fflush(stdin);
271  p = fgets(input, sizeof(input), stdin);
272 
273  if (p == NULL) {
274 
275  // most likely <ctrl+c>
276 
277  printf("exit\n");
278  break;
279  }
280 
281  // skip leading blank characters
282 
283  while (*p == ' ' || *p == '\t' || *p == '\n') {
284  p++;
285  }
286 
287  if (*p == '\0') {
288 
289  // empty input
290 
291  continue;
292  }
293 
294  // handle external commands
295 
296  if (!_strnicmp(p, "dir", 3) ||
297  !_strnicmp(p, "attrib", 6)) {
298 
299  // special cases - frequently used commands
300  // pass these to system() even without '.'
301 
302  system(p);
303  printf("\n");
304  continue;
305  }
306  else if (*p == '.') {
307 
308  // external command
309 
310  system(p + 1);
311  printf("\n");
312  continue;
313  }
314 
315  // split the input line into parameters (10 parameters max)
316 
317  argc = 0;
318  ZeroMemory(args, sizeof(args));
319 
320  do {
321  // top of a parameter
322 
323  args[argc++] = p;
324 
325  // is the parameter quoted?
326 
327  if (*p == '\"' || *p == '\'') {
328  sepa = *(p++);
329  }
330  else {
331  sepa = ' ';
332  }
333 
334  // search the end of the parameter
335 
336  while (*p && *p != '\n') {
337  if (sepa == ' ') {
338  if (*p == '\t' || *p == ' ') {
339  break; // tail of a non-quoted parameter
340  }
341  }
342  else {
343  if (*p == sepa) {
344  sepa = ' '; // close quote
345  }
346  }
347  p++;
348  }
349 
350  // terminate the parameter
351 
352  if (*p) {
353  *(p++) = '\0';
354  }
355 
356  // skip trailing blank characters
357 
358  while (*p == ' ' || *p == '\t' || *p == '\n') {
359  p++;
360  }
361 
362  if (*p == '\0') {
363 
364  // end of the input line - no more args
365 
366  break;
367  }
368  }
369  while (argc < sizeof(args) / sizeof(args[0]));
370 
371  // check the first parameter for special commands
372 
373  if (!_stricmp(args[0], "exit") ||
374  !_stricmp(args[0], "quit") ||
375  !_stricmp(args[0], "bye")) {
376 
377  // exit command
378 
379  break;
380  }
381  else if (!_stricmp(args[0], "cd") ||
382  !_stricmp(args[0], "chdir")) {
383 
384  // internal change directory command
385 
386  if (args[1]) {
387  char path[MAX_PATH];
388  int i;
389 
390  // ignore the /d option (of the standard cd command)
391 
392  if (_stricmp(args[1], "/d")) {
393  i = 1;
394  }
395  else {
396  i = 2;
397  }
398 
399  p = args[i];
400 
401  if (*p == '\"' || *p == '\'') {
402 
403  // the parameter is quoted -- remove quotations
404 
405  p++;
406 
407  while (*p && *p != *args[i]) {
408  p++;
409  }
410 
411  args[i]++; // skip a leading quote
412  *p = '\0'; // remove a trailing quote
413  }
414  else {
415 
416  // the parameter is not quoted
417  // -- concatenate params to allow spaces in unquoted path
418 
419  while (i < argc - 1) {
420  *(args[i] + strlen(args[i])) = ' ';
421  i++;
422  }
423  }
424 
425  // Match the case of the path to the name on the disk
426 
428 
429  if (!SetCurrentDirectory(path)) {
430  DWORD ret = GetLastError();
431 
432  if (ret == ERROR_FILE_NOT_FOUND) {
434  }
435 
436  printf("%s", SystemError(ret));
437  }
438  }
439  else {
440  if (!GetCurrentDirectory(sizeof(input), input)) {
441  printf("%s", SystemError(GetLastError()));
442  }
443  else {
444  printf("%s\n", input);
445  }
446  }
447  }
448  else if (isalpha(*args[0]) &&
449  *(args[0] + 1) == ':' &&
450  *(args[0] + 2) == '\0') {
451 
452  // internal change drive command
453 
454  *args[0] = (char)toupper(*args[0]);
455  *(args[0] + 2) = '\\';
456  *(args[0] + 3) = '\0';
457 
458  if (!SetCurrentDirectory(args[0])) {
459  printf("%s", SystemError(GetLastError()));
460  }
461  }
462  else {
463 
464  // perform the requested VFD command
465 
466  ProcessCommandLine(argc, (const char **)args);
467  }
468 
469  printf("\n");
470  }
471 
472  return VFD_OK;
473 }
474 
475 //
476 // process a single command
477 //
478 int ProcessCommandLine(int argc, const char **args)
479 {
480  int cmd;
481  DWORD ret;
482 
483  //
484  // Decide a command to perform
485  //
486  cmd = ParseCommand(*args);
487 
488  if (cmd < 0) {
489 
490  // no matching command
491 
492  return VFD_NG;
493  }
494 
495  if (*(++args) &&
496  (!strcmp(*args, "/?") ||
497  !_stricmp(*args, "/h"))) {
498 
499  // print a short hint for the command
500 
502  return VFD_NG;
503  }
504 
505  if (--argc > Commands[cmd].max_args) {
506 
507  // too many parameters for the command
508 
509  PrintMessage(MSG_TOO_MANY_ARGS);
511  return VFD_NG;
512  }
513 
514  // Get the current driver state
515 
517 
518  if (ret != ERROR_SUCCESS) {
519  PrintMessage(MSG_GET_STAT_NG);
520  printf("%s", SystemError(ret));
521  return VFD_NG;
522  }
523 
524  // Perform the requested operation
525 
526  return (*Commands[cmd].func)(args);
527 }
528 
529 //
530 // Install the Virtual Floppy Driver
531 // Command Line Parameters:
532 // (optional) driver file path - default to executive's dir
533 // (optional) auto start switch - default to demand start
534 //
535 int Install(const char **args)
536 {
537  const char *install_path = NULL;
538  DWORD start_type = SERVICE_DEMAND_START;
539 
540  DWORD ret;
541 
542  // process parameters
543 
544  while (args && *args) {
545 
546  if (!_stricmp(*args, "/a") ||
547  !_stricmp(*args, "/auto")) {
548 
549  if (start_type != SERVICE_DEMAND_START) {
550  PrintMessage(MSG_DUPLICATE_ARGS, *args);
551  return VFD_NG;
552  }
553 /*
554  if (IS_WINDOWS_NT()) {
555 
556  // On Windows NT, SYSTEM start drivers must be placed
557  // under the winnt\system32 directory. Since I don't
558  // care to handle driver file copying, I use the AUTO
559  // start method for Windows NT.
560 
561  start_type = SERVICE_AUTO_START;
562  }
563  else {
564 
565  // On Windows XP, the VFD driver must be running when
566  // the shell starts -- otherwise the shell doesn't
567  // recognize the VFD drives. Since Windows XP allows
568  // SYSTEM start drivers to be placed in any local
569  // directories, I use the SYSTEM start method here.
570  //
571  // This is not an issue when the driver is started
572  // manually because in that case VFD.EXE and VFDWIN.EXE
573  // notify the shell of the VFD drives.
574  //
575  // On Windows 2000 both SYSTEM and AUTO work fine.
576 
577  start_type = SERVICE_SYSTEM_START;
578  }
579 */
580  // On second thought -- Win2K / XP mount manager assigns
581  // arbitrary drive letters to all drives it finds during
582  // the system start up. There is no way to prevent it
583  // until the driver is fully PnP compatible, so I'd settle
584  // for AUTO start for the time being.
585 
586  start_type = SERVICE_AUTO_START;
587  }
588  else if (**args == '/') {
589  PrintMessage(MSG_UNKNOWN_OPTION, *args);
590  PrintMessage(MSG_HINT_INSTALL, help_progname);
591  return VFD_NG;
592  }
593  else {
594  if (install_path) {
595  PrintMessage(MSG_DUPLICATE_ARGS, "path");
596  return VFD_NG;
597  }
598 
599  install_path = *args;
600  }
601 
602  args++;
603  }
604 
605  // already installed?
606 
608  PrintMessage(MSG_DRIVER_EXISTS);
609  return VFD_NG;
610  }
611 
612  // install the driver
613 
615  install_path,
616  start_type);
617 
618  if (ret != ERROR_SUCCESS) {
619  PrintMessage(MSG_INSTALL_NG);
620  printf("%s", SystemError(ret));
621  return VFD_NG;
622  }
623 
624  // Get the latest driver state
625 
627 
628  if (ret != ERROR_SUCCESS) {
629  PrintMessage(MSG_GET_STAT_NG);
630  printf("%s", SystemError(ret));
631  return VFD_NG;
632  }
633 
634  // operation successfull
635 
636  PrintMessage(MSG_INSTALL_OK);
637 
638  return VFD_OK;
639 }
640 
641 //
642 // Remove Virtual Floppy Driver from system
643 // Command Line Parameters:
644 // [/F | /FORCE | /Q | /QUIT]
645 // /F forces remove operation if the driver cannot be stopped
646 // /Q quits remove operation if the driver cannot be stopped
647 //
648 int Remove(const char **args)
649 {
650  int mode = OPERATION_ASK;
651  const char *stop_params[] = { NULL, NULL };
652  DWORD ret;
653  int idx;
654 
655  // parse parameters
656 
657  while (args && *args) {
658 
659  if (!_stricmp(*args, "/f") ||
660  !_stricmp(*args, "/force")) {
661 
662  if (mode != OPERATION_ASK) {
663  PrintMessage(MSG_DUPLICATE_ARGS, *args);
664  return VFD_NG;
665  }
666 
668  stop_params[0] = *args;
669  }
670  else if (!_stricmp(*args, "/q") ||
671  !_stricmp(*args, "/quit")) {
672 
673  if (mode != OPERATION_ASK) {
674  PrintMessage(MSG_DUPLICATE_ARGS, *args);
675  return VFD_NG;
676  }
677 
679  stop_params[0] = *args;
680  }
681  else {
682  PrintMessage(MSG_UNKNOWN_OPTION, *args);
683  PrintMessage(MSG_HINT_REMOVE, help_progname);
684  return VFD_NG;
685  }
686 
687  args++;
688  }
689 
690  // ensure the driver is installed
691 
693  PrintMessage(MSG_NOT_INSTALLED);
694  return VFD_NG;
695  }
696 
697  // ensure the driver is stopped
698 
699  if (driver_state == SERVICE_RUNNING) {
700 
701  // Try to stop with the same command line option (/F or /Q)
702 
703  while (Stop(stop_params) != VFD_OK) {
704 
705  // stop failed
706 
707  if (mode == OPERATION_FORCE) {
708  PrintMessage(MSG_REMOVE_FORCE);
709  break;
710  }
711  else if (mode == OPERATION_QUIT) {
712  PrintMessage(MSG_REMOVE_QUIT);
713  return VFD_NG;
714  }
715  else {
716  int c;
717 
718  PrintMessage(MSG_REMOVE_WARN);
719 
720  c = InputChar(MSG_RETRY_FORCE_CANCEL, "rfc");
721 
722  if (c == 'f') { // force
723  break;
724  }
725  else if (c == 'c') { // cancel
726  return VFD_NG;
727  }
728  }
729  }
730  }
731 
732  // remove the driver
733 
734  ret = VfdRemoveDriver();
735 
736  if (ret != ERROR_SUCCESS) {
737  PrintMessage(MSG_REMOVE_NG);
738  printf("%s", SystemError(ret));
739  return VFD_NG;
740  }
741 
742  // Wait for the driver to be actually removed for 3 secs Max.
743 
744  for (idx = 0; idx < 10; idx++) {
745 
747 
748  if (ret != ERROR_SUCCESS) {
749  PrintMessage(MSG_GET_STAT_NG);
750  printf("%s", SystemError(ret));
751  return VFD_NG;
752  }
753 
755  break;
756  }
757 
758  Sleep(300);
759  }
760 
762  PrintMessage(MSG_REMOVE_PENDING);
763  return VFD_NG;
764  }
765 
766  // operation successful
767 
768  PrintMessage(MSG_REMOVE_OK);
769 
770  return VFD_OK;
771 }
772 
773 //
774 // Configure the Virtual Floppy Driver
775 // Command Line Parameters:
776 // /auto, /manual
777 //
778 int Config(const char **args)
779 {
780  DWORD start_type = SERVICE_DISABLED;
781  DWORD ret;
782 
783  while (args && *args) {
784  if (!_stricmp(*args, "/a") ||
785  !_stricmp(*args, "/auto")) {
786 
787  if (start_type != SERVICE_DISABLED) {
788  PrintMessage(MSG_DUPLICATE_ARGS, *args);
789  return VFD_NG;
790  }
791 
792  start_type = SERVICE_AUTO_START;
793  }
794  else if (!_stricmp(*args, "/m") ||
795  !_stricmp(*args, "/manual")) {
796 
797  if (start_type != SERVICE_DISABLED) {
798  PrintMessage(MSG_DUPLICATE_ARGS, *args);
799  return VFD_NG;
800  }
801 
802  start_type = SERVICE_DEMAND_START;
803  }
804  else {
805  PrintMessage(MSG_UNKNOWN_OPTION, *args);
806  PrintMessage(MSG_HINT_CONFIG, help_progname);
807  return VFD_NG;
808  }
809 
810  args++;
811  }
812 
813  if (start_type == SERVICE_DISABLED) {
814  // no parameter is specified
815  PrintMessage(MSG_HINT_CONFIG, help_progname);
816  return VFD_NG;
817  }
818 
819  // ensure that the driver is installed
820 
822  PrintMessage(MSG_NOT_INSTALLED);
823  return VFD_NG;
824  }
825 
826  // ensure that the driver is up to date
827 
828  if (CheckDriver() != VFD_OK) {
829  return VFD_NG;
830  }
831 
832  // configure the driver
833 
834  ret = VfdConfigDriver(start_type);
835 
836  if (ret != ERROR_SUCCESS) {
837  PrintMessage(MSG_CONFIG_NG);
838  printf("%s", SystemError(ret));
839  return VFD_NG;
840  }
841 
842  // operation successfull
843 
844  PrintMessage(MSG_CONFIG_OK);
845 
846  return VFD_OK;
847 }
848 
849 //
850 // Start the Virtual Floppy Driver
851 // Command Line Parameters: None
852 //
853 int Start(const char **args)
854 {
855  DWORD ret;
856 
858 
859  // ensure that the driver is installed
860 
862  Install(NULL) != VFD_OK) {
863  return VFD_NG;
864  }
865 
866  // ensure that the driver is up to date
867 
868  if (CheckDriver() != VFD_OK) {
869  return VFD_NG;
870  }
871 
872  // ensure that the driver is not running
873 
874  if (driver_state == SERVICE_RUNNING) {
875  PrintMessage(MSG_ALREADY_RUNNING);
876  return VFD_NG;
877  }
878 
879  // start the driver
880 
882 
883  if (ret != ERROR_SUCCESS) {
884  PrintMessage(MSG_START_NG);
885  printf("%s", SystemError(ret));
886  return VFD_NG;
887  }
888 
889  // operation successfull
890 
891  PrintMessage(MSG_START_OK);
892 
893  return VFD_OK;
894 }
895 
896 //
897 // Stop the Virtual Floppy Driver
898 // Command Line Parameters:
899 // /FORCE | /F Forces the operation on error
900 // /QUIT | /Q Quits the operation on error
901 //
902 int Stop(const char **args)
903 {
904  int mode = OPERATION_ASK;
905  const char *close_params[] = { "*", NULL, NULL };
906  DWORD ret;
907 
908  while (args && *args) {
909  if (!_stricmp(*args, "/f") ||
910  !_stricmp(*args, "/force")) {
911 
912  if (mode != OPERATION_ASK) {
913  PrintMessage(MSG_DUPLICATE_ARGS, *args);
914  return VFD_NG;
915  }
916 
918 
919  // parameter to pass to the Close() function
920  close_params[1] = *args;
921  }
922  else if (!_stricmp(*args, "/q") ||
923  !_stricmp(*args, "/quit")) {
924 
925  if (mode != OPERATION_ASK) {
926  PrintMessage(MSG_DUPLICATE_ARGS, *args);
927  return VFD_NG;
928  }
929 
931 
932  // parameter to pass to the Close() function
933  close_params[1] = *args;
934  }
935  else {
936  PrintMessage(MSG_UNKNOWN_OPTION, *args);
937  PrintMessage(MSG_HINT_STOP, help_progname);
938  return VFD_NG;
939  }
940 
941  args++;
942  }
943 
944  // ensure that the driver is installed
945 
947  PrintMessage(MSG_NOT_INSTALLED);
948  return VFD_NG;
949  }
950 
951  // ensure that the driver is running
952 
953  if (driver_state == SERVICE_STOPPED) {
954  PrintMessage(MSG_NOT_STARTED);
955  return VFD_NG;
956  }
957 
958  // ensure that all drives are empty
959 
960  if (driver_state == SERVICE_RUNNING) {
961 
962  // Try to close drives with the same operation mode (/F or /Q)
963 
964  while (Close(close_params) != VFD_OK) {
965 
966  // close failed
967 
968  if (mode == OPERATION_FORCE) {
969  PrintMessage(MSG_STOP_FORCE);
970  break;
971  }
972  else if (mode == OPERATION_QUIT) {
973  PrintMessage(MSG_STOP_QUIT);
974  return VFD_NG;
975  }
976  else {
977  int c;
978 
979  PrintMessage(MSG_STOP_WARN);
980 
981  c = InputChar(MSG_RETRY_FORCE_CANCEL, "rfc");
982 
983  if (c == 'f') { // force
984  break;
985  }
986  else if (c == 'c') { // cancel
987  return VFD_NG;
988  }
989  }
990  }
991  }
992 
993  // stop the driver
994 
996 
997  if (ret != ERROR_SUCCESS) {
998  PrintMessage(MSG_STOP_NG);
999  printf("%s", SystemError(ret));
1000  return VFD_NG;
1001  }
1002 
1003  if (driver_state != SERVICE_STOPPED) {
1004  PrintMessage(MSG_STOP_PENDING);
1005  return VFD_NG;
1006  }
1007 
1008  // operation successful
1009 
1010  PrintMessage(MSG_STOP_OK);
1011 
1012  return VFD_OK;
1013 }
1014 
1015 //
1016 // Enable / Disable the shell extension
1017 // Command Line Parameters:
1018 // (optional) /ON or /OFF
1019 //
1020 int Shell(const char **args)
1021 {
1022  DWORD ret;
1023 
1024  ret = VfdCheckHandlers();
1025 
1026  if (ret != ERROR_SUCCESS &&
1029  PrintMessage(MSG_GET_SHELLEXT_NG);
1030  printf("%s", SystemError(ret));
1031  return VFD_NG;
1032  }
1033 
1034  if (args && *args) {
1035  if (_stricmp(*args, "/on") == 0) {
1036  if (ret != ERROR_SUCCESS) {
1038 
1039  if (ret != ERROR_SUCCESS) {
1040  PrintMessage(MSG_SET_SHELLEXT_NG);
1041  printf("%s", SystemError(ret));
1042  return VFD_NG;
1043  }
1044  }
1045  }
1046  else if (_stricmp(*args, "/off") == 0) {
1047  if (ret == ERROR_SUCCESS) {
1049 
1050  if (ret != ERROR_SUCCESS) {
1051  PrintMessage(MSG_SET_SHELLEXT_NG);
1052  printf("%s", SystemError(ret));
1053  return VFD_NG;
1054  }
1055  }
1056  }
1057  else {
1058  PrintMessage(MSG_UNKNOWN_OPTION, *args);
1059  PrintMessage(MSG_HINT_SHELL, help_progname);
1060  return VFD_NG;
1061  }
1062 
1063  ret = VfdCheckHandlers();
1064  }
1065 
1066  if (ret == ERROR_PATH_NOT_FOUND ||
1068  PrintMessage(MSG_SHELLEXT_DISABLED);
1069  }
1070  else if (ret == ERROR_SUCCESS) {
1071  PrintMessage(MSG_SHELLEXT_ENABLED);
1072  }
1073  else {
1074  PrintMessage(MSG_GET_SHELLEXT_NG);
1075  printf("%s", SystemError(ret));
1076  return VFD_NG;
1077  }
1078 
1079  return VFD_OK;
1080 }
1081 
1082 //
1083 // Open an image file to a Virtual Floppy Drive
1084 // Command Line Parameters:
1085 // [drive:] [file] [/NEW] [/RAM] [/P | /W]
1086 // [/size] [/media] [/F | /FORCE | /Q | /QUIT]
1087 
1088 int Open(const char **args)
1089 {
1090  int mode = OPERATION_ASK;
1091  BOOL create = FALSE;
1093  PCSTR file_name = NULL;
1094  VFD_DISKTYPE disk_type = VFD_DISKTYPE_FILE;
1095  CHAR protect = '\0';
1096  VFD_MEDIA media_type = VFD_MEDIA_NONE;
1097  BOOL five_inch = FALSE;
1098  VFD_FLAGS media_flags = 0;
1099  HANDLE hDevice;
1100  CHAR letter;
1101  DWORD ret;
1102 
1103  // process parameters
1104 
1105  while (args && *args) {
1106 
1107  if (!_stricmp(*args, "/f") ||
1108  !_stricmp(*args, "/force")) {
1109 
1110  if (mode != OPERATION_ASK) {
1111  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1112  return VFD_NG;
1113  }
1114 
1116  }
1117  else if (!_stricmp(*args, "/q") ||
1118  !_stricmp(*args, "/quit")) {
1119 
1120  if (mode != OPERATION_ASK) {
1121  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1122  return VFD_NG;
1123  }
1124 
1125  mode = OPERATION_QUIT;
1126  }
1127 
1128  else if (!_stricmp(*args, "/new")) {
1129 
1130  if (create) {
1131  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1132  return VFD_NG;
1133  }
1134 
1135  create = TRUE;
1136  }
1137 
1138  // Disk type options
1139 
1140  else if (_stricmp(*args, "/ram") == 0) {
1141 
1142  if (disk_type != VFD_DISKTYPE_FILE) {
1143  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1144  return VFD_NG;
1145  }
1146 
1147  disk_type = VFD_DISKTYPE_RAM;
1148  }
1149 
1150  // Protect options
1151  else if (_stricmp(*args, "/p") == 0 ||
1152  _stricmp(*args, "/w") == 0) {
1153 
1154  if (protect) {
1155  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1156  return VFD_NG;
1157  }
1158 
1159  protect = (CHAR)toupper(*(*args + 1));
1160  }
1161 
1162  // media size options
1163 
1164  else if (strcmp(*args, "/160") == 0) {
1165  if (media_type) {
1166  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1167  return VFD_NG;
1168  }
1169 
1170  media_type = VFD_MEDIA_F5_160;
1171  }
1172  else if (strcmp(*args, "/180") == 0) {
1173  if (media_type) {
1174  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1175  return VFD_NG;
1176  }
1177 
1178  media_type = VFD_MEDIA_F5_180;
1179  }
1180  else if (strcmp(*args, "/320") == 0) {
1181  if (media_type) {
1182  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1183  return VFD_NG;
1184  }
1185 
1186  media_type = VFD_MEDIA_F5_320;
1187  }
1188  else if (strcmp(*args, "/360") == 0) {
1189  if (media_type) {
1190  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1191  return VFD_NG;
1192  }
1193 
1194  media_type = VFD_MEDIA_F5_360;
1195  }
1196  else if (strcmp(*args, "/640") == 0) {
1197  if (media_type) {
1198  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1199  return VFD_NG;
1200  }
1201 
1202  media_type = VFD_MEDIA_F3_640;
1203  }
1204  else if (strcmp(*args, "/720") == 0) {
1205  if (media_type) {
1206  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1207  return VFD_NG;
1208  }
1209 
1210  media_type = VFD_MEDIA_F3_720;
1211  }
1212  else if (strcmp(*args, "/820") == 0) {
1213  if (media_type) {
1214  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1215  return VFD_NG;
1216  }
1217 
1218  media_type = VFD_MEDIA_F3_820;
1219  }
1220  else if (strcmp(*args, "/120") == 0 ||
1221  strcmp(*args, "/1.20") == 0) {
1222  if (media_type) {
1223  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1224  return VFD_NG;
1225  }
1226 
1227  media_type = VFD_MEDIA_F3_1P2;
1228  }
1229  else if (strcmp(*args, "/144") == 0 ||
1230  strcmp(*args, "/1.44") == 0) {
1231  if (media_type) {
1232  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1233  return VFD_NG;
1234  }
1235 
1236  media_type = VFD_MEDIA_F3_1P4;
1237  }
1238  else if (strcmp(*args, "/168") == 0 ||
1239  strcmp(*args, "/1.68") == 0) {
1240  if (media_type) {
1241  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1242  return VFD_NG;
1243  }
1244 
1245  media_type = VFD_MEDIA_F3_1P6;
1246  }
1247  else if (strcmp(*args, "/172") == 0 ||
1248  strcmp(*args, "/1.72") == 0) {
1249  if (media_type) {
1250  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1251  return VFD_NG;
1252  }
1253 
1254  media_type = VFD_MEDIA_F3_1P7;
1255  }
1256  else if (strcmp(*args, "/288") == 0 ||
1257  strcmp(*args, "/2.88") == 0) {
1258  if (media_type) {
1259  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1260  return VFD_NG;
1261  }
1262 
1263  media_type = VFD_MEDIA_F3_2P8;
1264  }
1265 
1266  // 5.25 inch media
1267 
1268  else if (strcmp(*args, "/5") == 0 ||
1269  strcmp(*args, "/525") == 0 ||
1270  strcmp(*args, "/5.25") == 0) {
1271 
1272  if (five_inch) {
1273  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1274  return VFD_NG;
1275  }
1276 
1277  five_inch = TRUE;
1278  }
1279 
1280  // target option
1281 
1282  else if (isalnum(**args) &&
1283  *(*args + 1) == ':' &&
1284  *(*args + 2) == '\0') {
1285 
1286  if (target != TARGET_NONE) {
1287  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1288  return VFD_NG;
1289  }
1290 
1291  target = toupper(**args);
1292  }
1293 
1294  // filename
1295 
1296  else if (**args != '/') {
1297  if (file_name) {
1298  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1299  return VFD_NG;
1300  }
1301 
1302  file_name = *args;
1303  }
1304  else {
1305  PrintMessage(MSG_UNKNOWN_OPTION, *args);
1306  PrintMessage(MSG_HINT_OPEN, help_progname);
1307  return VFD_NG;
1308  }
1309 
1310  args++;
1311  }
1312 
1313  if (target == TARGET_NONE) {
1314  // default target
1315  target = '0';
1316  PrintMessage(MSG_TARGET_NOTICE, target);
1317  }
1318 
1319  // check target file
1320 
1321  if (file_name) {
1322  DWORD file_attr;
1324  ULONG image_size;
1325  BOOL overwrite = FALSE;
1326 
1328  file_name, &file_attr, &file_type, &image_size);
1329 
1330  if (ret == ERROR_FILE_NOT_FOUND) {
1331 
1332  // the target file does not exist
1333 
1334  if (!create) { // create option not specified
1335 
1336  if (mode == OPERATION_FORCE) {
1337  PrintMessage(MSG_CREATE_NOTICE);
1338  }
1339  else {
1340  printf("%s", SystemError(ret));
1341 
1342  if (mode == OPERATION_QUIT ||
1343  InputChar(MSG_CREATE_CONFIRM, "yn") == 'n') {
1344  return VFD_NG;
1345  }
1346  }
1347 
1348  create = TRUE;
1349  }
1350  }
1351  else if (ret == ERROR_SUCCESS) {
1352 
1353  // the target file exists
1354 
1355  if (create) { // create option is specified
1356 
1357  if (mode == OPERATION_FORCE) {
1358  PrintMessage(MSG_OVERWRITE_NOTICE);
1359  }
1360  else {
1362 
1363  if (mode == OPERATION_QUIT ||
1364  InputChar(MSG_OVERWRITE_CONFIRM, "yn") == 'n') {
1365  return VFD_NG;
1366  }
1367  }
1368 
1369  overwrite = TRUE;
1370  }
1371  }
1372  else {
1373  PrintMessage(MSG_OPEN_NG, file_name);
1374  printf("%s", SystemError(ret));
1375  return VFD_NG;
1376  }
1377 
1378  //
1379  // create or overwrite the target file
1380  //
1381 
1382  if (create) {
1383 
1384  if (media_type == VFD_MEDIA_NONE) {
1385 
1386  if (mode == OPERATION_FORCE) {
1387  PrintMessage(MSG_CREATE144_NOTICE);
1388  }
1389  else {
1390  PrintMessage(MSG_FILE_MEDIA_UNKNOWN);
1391 
1392  if (mode == OPERATION_QUIT ||
1393  InputChar(MSG_CREATE144_CONFIRM, "yn") == 'n') {
1394  return VFD_NG;
1395  }
1396  }
1397 
1398  media_type = VFD_MEDIA_F3_1P4;
1399  }
1400 
1402  file_name, media_type, VFD_FILETYPE_RAW, overwrite);
1403 
1404  if (ret != ERROR_SUCCESS) {
1405  PrintMessage(MSG_CREATE_NG, file_name);
1406  printf("%s", SystemError(ret));
1407  return VFD_NG;
1408  }
1409 
1410  PrintMessage(MSG_FILE_CREATED);
1411 
1413  file_name, &file_attr, &file_type, &image_size);
1414 
1415  if (ret != ERROR_SUCCESS) {
1416  PrintMessage(MSG_OPEN_NG, file_name);
1417  printf("%s", SystemError(ret));
1418  return VFD_NG;
1419  }
1420  }
1421  else {
1422  //
1423  // use the existing target file
1424  // check image size and the media type
1425  //
1426 
1427  VFD_MEDIA def_media; // default media for image size
1428  ULONG media_size; // specified media size
1429 
1430  media_size = VfdGetMediaSize(media_type);
1431 
1432  if (media_size > image_size) {
1433 
1434  // specified media is too large for the image
1435 
1436  PrintMessage(MSG_IMAGE_TOO_SMALL);
1437  return VFD_NG;
1438  }
1439 
1440  def_media = VfdLookupMedia(image_size);
1441 
1442  if (def_media == VFD_MEDIA_NONE) {
1443 
1444  // image is too small for the smallest media
1445 
1446  PrintMessage(MSG_IMAGE_TOO_SMALL);
1447  return VFD_NG;
1448  }
1449 
1450  if (media_type == VFD_MEDIA_NONE) {
1451 
1452  // media type is not specified
1453 
1454  ULONG def_size = VfdGetMediaSize(def_media);
1455 
1456  if (def_size != image_size) {
1457 
1458  // image size does not match the largest media size
1459 
1460  PrintMessage(MSG_NO_MATCHING_MEDIA, image_size);
1461 
1462  if (mode == OPERATION_FORCE) {
1463  PrintMessage(MSG_MEDIATYPE_NOTICE,
1464  VfdMediaTypeName(def_media), def_size);
1465  }
1466  else if (mode == OPERATION_QUIT) {
1467  return VFD_NG;
1468  }
1469  else {
1470  PrintMessage(MSG_MEDIATYPE_SUGGEST,
1471  VfdMediaTypeName(def_media), def_size);
1472 
1473  if (InputChar(MSG_MEDIATYPE_CONFIRM, "yn") == 'n') {
1474  return VFD_NG;
1475  }
1476  }
1477  }
1478 
1479  media_type = def_media;
1480  }
1481  }
1482 
1483  // check file attributes against the disk type
1484 
1485  if (file_type == VFD_FILETYPE_ZIP ||
1487 
1488  if (disk_type != VFD_DISKTYPE_RAM) {
1489 
1490  if (mode == OPERATION_FORCE) {
1491  PrintMessage(MSG_RAM_MODE_NOTICE);
1492  }
1493  else {
1494  PrintMessage(MSG_RAM_MODE_ONLY);
1495 
1496  if (mode == OPERATION_QUIT ||
1497  InputChar(MSG_RAM_MODE_CONFIRM, "yn") == 'n') {
1498  return VFD_NG;
1499  }
1500  }
1501 
1502  disk_type = VFD_DISKTYPE_RAM;
1503  }
1504  }
1505 
1506  if (disk_type != VFD_DISKTYPE_FILE) {
1507  if (!protect) {
1508  PrintMessage(MSG_DEFAULT_PROTECT);
1509  protect = 'P';
1510  }
1511  }
1512  }
1513  else {
1514  //
1515  // pure RAM disk
1516  //
1517  disk_type = VFD_DISKTYPE_RAM;
1518 
1519  if (media_type == VFD_MEDIA_NONE) {
1520 
1521  if (mode == OPERATION_FORCE) {
1522  PrintMessage(MSG_CREATE144_NOTICE);
1523  }
1524  else {
1525  PrintMessage(MSG_RAM_MEDIA_UNKNOWN);
1526 
1527  if (mode == OPERATION_QUIT ||
1528  InputChar(MSG_CREATE144_CONFIRM, "yn") == 'n') {
1529  return VFD_NG;
1530  }
1531  }
1532 
1533  media_type = VFD_MEDIA_F3_1P4;
1534  }
1535  }
1536 
1537  if (protect == 'P') {
1538  media_flags |= VFD_FLAG_WRITE_PROTECTED;
1539  }
1540 
1541  if (five_inch &&
1542  VfdGetMediaSize(media_type) ==
1543  VfdGetMediaSize((VFD_MEDIA)(media_type + 1))) {
1544  media_type = (VFD_MEDIA)(media_type + 1);
1545  }
1546 
1547  // ensure that the driver is installed
1548 
1550  Install(NULL) != VFD_OK) {
1551  return VFD_NG;
1552  }
1553 
1554  // ensure that the driver is up to date
1555 
1556  if (CheckDriver() != VFD_OK) {
1557  return VFD_NG;
1558  }
1559 
1560  // ensure that the driver is running
1561 
1562  if (driver_state != SERVICE_RUNNING &&
1563  Start(NULL) != VFD_OK) {
1564  return VFD_NG;
1565  }
1566 
1567  // Open the target device
1568 
1569  hDevice = VfdOpenDevice(target);
1570 
1571  if (hDevice == INVALID_HANDLE_VALUE) {
1572  ret = GetLastError();
1573  PrintMessage(MSG_ACCESS_NG, target);
1574  printf("%s", SystemError(ret));
1575  return VFD_NG;
1576  }
1577 
1578  // Ensure that the drive is empty
1579 
1580  ret = VfdGetMediaState(hDevice);
1581 
1582  if (ret != ERROR_NOT_READY) {
1583  if (ret == ERROR_SUCCESS ||
1584  ret == ERROR_WRITE_PROTECT) {
1585  PrintMessage(MSG_DRIVE_BUSY);
1586  }
1587  else {
1588  PrintMessage(MSG_GET_MEDIA_NG);
1589  printf("%s", SystemError(ret));
1590  }
1591 
1592  CloseHandle(hDevice);
1593  return VFD_NG;
1594  }
1595 
1596  // Open the image file
1597 
1598  ret = VfdOpenImage(hDevice, file_name,
1599  disk_type, media_type, media_flags);
1600 
1601  if (ret != ERROR_SUCCESS) {
1602  PrintMessage(MSG_OPEN_NG, file_name ? file_name : "<RAM>");
1603  printf("%s", SystemError(ret));
1604 
1605  CloseHandle(hDevice);
1606  return VFD_NG;
1607  }
1608 
1609  // assign a drive letter if the drive has none
1610 
1611  VfdGetGlobalLink(hDevice, &letter);
1612 
1613  if (!isalpha(letter)) {
1614  VfdGetLocalLink(hDevice, &letter);
1615  }
1616 
1617  if (!isalpha(letter)) {
1618  VfdSetLocalLink(hDevice, VfdChooseLetter());
1619  }
1620 
1621  // Get the actually opened image information.
1622 
1623  PrintImageInfo(hDevice);
1624 
1625  CloseHandle(hDevice);
1626 
1627  return VFD_OK;
1628 }
1629 
1630 //
1631 // Close the current virtual floppy image
1632 // Command Line Parameters:
1633 // drive number or drive letter
1634 // /F | /FORCE | /Q | /QUIT
1635 //
1636 int Close(const char **args)
1637 {
1639 
1640  ULONG target_min = TARGET_NONE;
1641  ULONG target_max = TARGET_NONE;
1642  HANDLE hDevice;
1643 
1644  VFD_MEDIA media_type;
1645  VFD_FLAGS media_flags;
1646 
1647  DWORD ret;
1648 
1649  // check parameterS
1650 
1651  while (args && *args) {
1652 
1653  if (!_stricmp(*args, "/f") ||
1654  !_stricmp(*args, "/force")) {
1655 
1656  if (mode != OPERATION_ASK) {
1657  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1658  return VFD_NG;
1659  }
1660 
1662  }
1663  else if (!_stricmp(*args, "/q") ||
1664  !_stricmp(*args, "/quit")) {
1665 
1666  if (mode != OPERATION_ASK) {
1667  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1668  return VFD_NG;
1669  }
1670 
1671  mode = OPERATION_QUIT;
1672  }
1673  else if ((isalnum(**args) || **args == '*') &&
1674  (*(*args + 1) == ':' || *(*args + 1) == '\0')) {
1675 
1676  if (target_min != TARGET_NONE) {
1677  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1678  return VFD_NG;
1679  }
1680 
1681  if (**args == '*') {
1682  target_min = '0';
1683  target_max = '0' + VFD_MAXIMUM_DEVICES;
1684  }
1685  else {
1686  target_min = toupper(**args);
1687  target_max = target_min + 1;
1688  }
1689  }
1690  else {
1691  PrintMessage(MSG_UNKNOWN_OPTION, *args);
1692  PrintMessage(MSG_HINT_CLOSE, help_progname);
1693  return VFD_NG;
1694  }
1695 
1696  args++;
1697  }
1698 
1699  if (target_min == TARGET_NONE) {
1700  // default target = drive 0
1701  target_min = '0';
1702  target_max = '1';
1703  PrintMessage(MSG_TARGET_NOTICE, target_min);
1704  }
1705 
1706  // ensure that the driver is installed
1707 
1709  PrintMessage(MSG_NOT_INSTALLED);
1710  return VFD_NG;
1711  }
1712 
1713  // ensure that the driver is running
1714 
1715  if (driver_state != SERVICE_RUNNING) {
1716  PrintMessage(MSG_NOT_STARTED);
1717  return VFD_NG;
1718  }
1719 
1720  // Close the drive(s)
1721 
1722  while (target_min < target_max) {
1723 
1724  // open the target device
1725 
1726  hDevice = VfdOpenDevice(target_min);
1727 
1728  if (hDevice == INVALID_HANDLE_VALUE) {
1729  ret = GetLastError();
1730 
1731  PrintMessage(MSG_ACCESS_NG, target_min);
1732  printf("%s", SystemError(ret));
1733 
1734  if (mode != OPERATION_FORCE) {
1735  return VFD_NG;
1736  }
1737 
1738  target_min++;
1739  continue;
1740  }
1741 
1742  // get the current image information
1743 
1744  ret = VfdGetImageInfo(hDevice, NULL, NULL,
1745  &media_type, &media_flags, NULL, NULL);
1746 
1747  if (ret != ERROR_SUCCESS) {
1748  PrintMessage(MSG_ACCESS_NG, target_min);
1749  printf("%s", SystemError(ret));
1750 
1751  CloseHandle(hDevice);
1752 
1753  if (mode != OPERATION_FORCE) {
1754  return VFD_NG;
1755  }
1756 
1757  target_min++;
1758  continue;
1759  }
1760 
1761  if (media_type == VFD_MEDIA_NONE) {
1762 
1763  // drive is empty
1764 
1765  CloseHandle(hDevice);
1766  target_min++;
1767  continue;
1768  }
1769 
1770  if (media_flags & VFD_FLAG_DATA_MODIFIED) {
1771 
1772  // RAM disk data is modified
1773 
1774  PrintMessage(MSG_MEDIA_MODIFIED, target_min);
1775 
1776  if (mode == OPERATION_FORCE) {
1777  PrintMessage(MSG_CLOSE_FORCE);
1778  }
1779  else if (mode == OPERATION_QUIT) {
1780  PrintMessage(MSG_CLOSE_QUIT);
1781  CloseHandle(hDevice);
1782  return VFD_NG;
1783  }
1784  else {
1785  if (InputChar(MSG_CLOSE_CONFIRM, "yn") == 'n') {
1786  CloseHandle(hDevice);
1787  return VFD_NG;
1788  }
1789  }
1790  }
1791 
1792 retry:
1793  ret = VfdCloseImage(
1794  hDevice, (mode == OPERATION_FORCE));
1795 
1796  if (ret == ERROR_ACCESS_DENIED) {
1797 
1798  PrintMessage(MSG_LOCK_NG, target_min);
1799 
1800  if (mode == OPERATION_QUIT) {
1801  CloseHandle(hDevice);
1802  return VFD_NG;
1803  }
1804  else if (mode == OPERATION_ASK) {
1805 
1806  int c;
1807 
1808  if (IS_WINDOWS_NT()) {
1809  c = InputChar(MSG_RETRY_CANCEL, "rc");
1810  }
1811  else {
1812  c = InputChar(MSG_RETRY_FORCE_CANCEL, "rfc");
1813  }
1814 
1815  if (c == 'f') { // force
1816  ret = VfdCloseImage(hDevice, TRUE);
1817  }
1818  else if (c == 'c') { // cancel
1819  CloseHandle(hDevice);
1820  return VFD_NG;
1821  }
1822  else {
1823  goto retry;
1824  }
1825  }
1826  }
1827 
1828  CloseHandle(hDevice);
1829 
1830  if (ret == ERROR_SUCCESS) {
1831  PrintMessage(MSG_CLOSE_OK, target_min);
1832  }
1833  else if (ret != ERROR_NOT_READY) {
1834  PrintMessage(MSG_CLOSE_NG, target_min);
1835  printf("%s", SystemError(ret));
1836 
1837  if (mode != OPERATION_FORCE) {
1838  return VFD_NG;
1839  }
1840  }
1841 
1842  target_min++;
1843  }
1844 
1845  return VFD_OK;
1846 }
1847 
1848 //
1849 // Save the current image into a file
1850 //
1851 int Save(const char **args)
1852 {
1853  int mode = OPERATION_ASK;
1855  CHAR file_name[MAX_PATH] = {0};
1856  BOOL overwrite = FALSE;
1857  BOOL truncate = FALSE;
1858 
1859  HANDLE hDevice;
1860  CHAR current[MAX_PATH] = {0};
1861  VFD_MEDIA media_type;
1862  VFD_FLAGS media_flags;
1864  DWORD file_attr;
1865  ULONG image_size;
1866  DWORD ret;
1867 
1868  // check parameters
1869 
1870  while (args && *args) {
1871 
1872  if (!_stricmp(*args, "/f") ||
1873  !_stricmp(*args, "/force")) {
1874 
1875  if (mode != OPERATION_ASK) {
1876  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1877  return VFD_NG;
1878  }
1879 
1881  }
1882  else if (!_stricmp(*args, "/q") ||
1883  !_stricmp(*args, "/quit")) {
1884 
1885  if (mode != OPERATION_ASK) {
1886  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1887  return VFD_NG;
1888  }
1889 
1890  mode = OPERATION_QUIT;
1891  }
1892  else if (!_stricmp(*args, "/o") ||
1893  !_stricmp(*args, "/over")) {
1894 
1895  if (truncate || overwrite) {
1896  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1897  return VFD_NG;
1898  }
1899 
1900  overwrite = TRUE;
1901  }
1902  else if (!_stricmp(*args, "/t") ||
1903  !_stricmp(*args, "/trunc")) {
1904 
1905  if (truncate || overwrite) {
1906  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1907  return VFD_NG;
1908  }
1909 
1910  truncate = TRUE;
1911  }
1912  else if (isalnum(**args) &&
1913  *(*args + 1) == ':' &&
1914  *(*args + 2) == '\0') {
1915 
1916  if (target != TARGET_NONE) {
1917  PrintMessage(MSG_DUPLICATE_ARGS, *args);
1918  return VFD_NG;
1919  }
1920 
1921  target = toupper(**args);
1922  }
1923  else if (**args == '/') {
1924  PrintMessage(MSG_UNKNOWN_OPTION, *args);
1925  PrintMessage(MSG_HINT_SAVE, help_progname);
1926  return VFD_NG;
1927  }
1928  else {
1929  strcpy(file_name, *args);
1930  }
1931 
1932  args++;
1933  }
1934 
1935  if (target == TARGET_NONE) {
1936  target = '0';
1937  PrintMessage(MSG_TARGET_NOTICE, target);
1938  }
1939 
1940  // ensure that the driver is installed
1941 
1943  PrintMessage(MSG_NOT_INSTALLED);
1944  return VFD_NG;
1945  }
1946 
1947  // ensure that the driver is up to date
1948 
1949  if (CheckDriver() != VFD_OK) {
1950  return VFD_NG;
1951  }
1952 
1953  // ensure that the driver is running
1954 
1955  if (driver_state != SERVICE_RUNNING) {
1956  PrintMessage(MSG_NOT_STARTED);
1957  return VFD_NG;
1958  }
1959 
1960  // Open the target device
1961 
1962  hDevice = VfdOpenDevice(target);
1963 
1964  if (hDevice == INVALID_HANDLE_VALUE) {
1965  ret = GetLastError();
1966  PrintMessage(MSG_ACCESS_NG, target);
1967  printf("%s", SystemError(ret));
1968  return VFD_NG;
1969  }
1970 
1971  // Get the current image info
1972 
1973  ret = VfdGetImageInfo(hDevice, current, NULL,
1974  &media_type, &media_flags, NULL, NULL);
1975 
1976  if (ret != ERROR_SUCCESS) {
1977  printf("%s", SystemError(ret));
1978  CloseHandle(hDevice);
1979  return VFD_NG;
1980  }
1981 
1982  if (media_type == VFD_MEDIA_NONE) {
1984  CloseHandle(hDevice);
1985  return VFD_NG;
1986  }
1987 
1988  if (file_name[0] == '\0') {
1989 
1990  if (current[0] == '\0') {
1991 
1992  PrintMessage(MSG_TARGET_REQUIRED);
1993  CloseHandle(hDevice);
1994 
1995  return VFD_NG;
1996  }
1997 
1999  }
2000 
2001  if (!_stricmp(file_name, current)) {
2002 
2003  // target is the current image file
2004 
2005  if (!(media_flags & VFD_FLAG_DATA_MODIFIED)) {
2006 
2007  // FILE disk (always up to date) or RAM disk is not modified
2008 
2009  PrintMessage(MSG_TARGET_UP_TO_DATE);
2010  CloseHandle(hDevice);
2011 
2012  return VFD_OK;
2013  }
2014 
2015  overwrite = TRUE;
2016  }
2017 
2018  // check target file
2019 
2021  &file_attr, &file_type, &image_size);
2022 
2023  if (ret == ERROR_SUCCESS) {
2024 
2025  if (!overwrite && !truncate) {
2026 
2027  if (mode == OPERATION_FORCE) {
2028  PrintMessage(MSG_OVERWRITE_NOTICE);
2029  overwrite = TRUE;
2030  }
2031  else if (mode == OPERATION_QUIT) {
2033  CloseHandle(hDevice);
2034 
2035  return VFD_NG;
2036  }
2037  else {
2038  int c;
2039 
2041 
2042  c = InputChar(MSG_OVERWRITE_PROMPT, "otc");
2043 
2044  if (c == 'o') {
2045  overwrite = TRUE;
2046  }
2047  else if (c == 't') {
2048  truncate = TRUE;
2049  }
2050  else {
2051  CloseHandle(hDevice);
2052  return VFD_NG;
2053  }
2054  }
2055  }
2056  }
2057  else if (ret != ERROR_FILE_NOT_FOUND) {
2058 
2059  printf("%s", SystemError(ret));
2060  CloseHandle(hDevice);
2061 
2062  return VFD_NG;
2063  }
2064 
2065  if (file_type == VFD_FILETYPE_ZIP) {
2066 
2067  // Cannot update a zip file
2068 
2069  PrintMessage(MSG_TARGET_IS_ZIP);
2070  CloseHandle(hDevice);
2071 
2072  return VFD_NG;
2073  }
2074 
2075 retry:
2077  hDevice, (mode == OPERATION_FORCE));
2078 
2079  if (ret == ERROR_ACCESS_DENIED) {
2080 
2081  PrintMessage(MSG_LOCK_NG, target);
2082 
2083  if (mode == OPERATION_FORCE) {
2084  PrintMessage(MSG_SAVE_FORCE);
2085  }
2086  else if (mode == OPERATION_QUIT) {
2087  PrintMessage(MSG_SAVE_QUIT);
2088  CloseHandle(hDevice);
2089  return VFD_NG;
2090  }
2091  else {
2092  int c = InputChar(MSG_RETRY_FORCE_CANCEL, "rfc");
2093 
2094  if (c == 'r') { // retry
2095  goto retry;
2096  }
2097  else if (c == 'f') { // force
2098  VfdDismountVolume(hDevice, TRUE);
2099  }
2100  else { // cancel
2101  CloseHandle(hDevice);
2102  return VFD_NG;
2103  }
2104  }
2105  }
2106  else if (ret != ERROR_SUCCESS) {
2107  printf("%s", SystemError(ret));
2108  CloseHandle(hDevice);
2109  return VFD_NG;
2110  }
2111 
2112  ret = VfdSaveImage(hDevice, file_name,
2113  (overwrite || truncate), truncate);
2114 
2115  CloseHandle(hDevice);
2116 
2117  if (ret != ERROR_SUCCESS) {
2118  PrintMessage(MSG_SAVE_NG, target, file_name);
2119  printf("%s", SystemError(ret));
2120 
2121  return VFD_NG;
2122  }
2123 
2124  PrintMessage(MSG_SAVE_OK, target, file_name);
2125 
2126  return VFD_OK;
2127 }
2128 
2129 //
2130 // Enable/disable virtual media write protection
2131 //
2132 int Protect(const char **args)
2133 {
2134 #define PROTECT_NONE 0
2135 #define PROTECT_ON 1
2136 #define PROTECT_OFF 2
2137  ULONG protect = PROTECT_NONE;
2139  HANDLE hDevice;
2140  DWORD ret;
2141 
2142  // check parameters
2143 
2144  while (args && *args) {
2145 
2146  // Disk type options
2147 
2148  if (_stricmp(*args, "/on") == 0) {
2149 
2150  if (protect) {
2151  PrintMessage(MSG_DUPLICATE_ARGS, *args);
2152  return VFD_NG;
2153  }
2154 
2155  protect = PROTECT_ON;
2156  }
2157  else if (_stricmp(*args, "/off") == 0) {
2158 
2159  if (protect) {
2160  PrintMessage(MSG_DUPLICATE_ARGS, *args);
2161  return VFD_NG;
2162  }
2163 
2164  protect = PROTECT_OFF;
2165  }
2166  else if (isalnum(**args)) {
2167 
2168  if (target != TARGET_NONE) {
2169  PrintMessage(MSG_DUPLICATE_ARGS, *args);
2170  return VFD_NG;
2171  }
2172 
2173  target = toupper(**args);
2174  }
2175  else {
2176  PrintMessage(MSG_UNKNOWN_OPTION, *args);
2177  PrintMessage(MSG_HINT_PROTECT, help_progname);
2178  return VFD_NG;
2179  }
2180 
2181  args++;
2182  }
2183 
2184  if (target == TARGET_NONE) {
2185  target = '0';
2186  PrintMessage(MSG_TARGET_NOTICE, target);
2187  }
2188 
2189  // ensure that the driver is installed
2190 
2192  PrintMessage(MSG_NOT_INSTALLED);
2193  return VFD_NG;
2194  }
2195 
2196  // ensure that the driver is up to date
2197 
2198  if (CheckDriver() != VFD_OK) {
2199  return VFD_NG;
2200  }
2201 
2202  // ensure that the driver is running
2203 
2204  if (driver_state != SERVICE_RUNNING) {
2205  PrintMessage(MSG_NOT_STARTED);
2206  return VFD_NG;
2207  }
2208 
2209  // open the target drive
2210 
2211  hDevice = VfdOpenDevice(target);
2212 
2213  if (hDevice == INVALID_HANDLE_VALUE) {
2214  ret = GetLastError();
2215  PrintMessage(MSG_ACCESS_NG, target);
2216  printf("%s", SystemError(ret));
2217  return VFD_NG;
2218  }
2219 
2220  if (protect) {
2221  // change protect state
2222 
2223  ret = VfdWriteProtect(
2224  hDevice, (protect == PROTECT_ON));
2225 
2226  if (ret != ERROR_SUCCESS) {
2227  PrintMessage(MSG_PROTECT_NG, target);
2228  printf("%s", SystemError(ret));
2229 
2230  CloseHandle(hDevice);
2231  return VFD_NG;
2232  }
2233  }
2234 
2235  // get the current protect state
2236 
2237  ret = VfdGetMediaState(hDevice);
2238 
2239  CloseHandle(hDevice);
2240 
2241  if (ret == ERROR_SUCCESS) {
2242  PrintMessage(MSG_MEDIA_WRITABLE);
2243  }
2244  else if (ret == ERROR_WRITE_PROTECT) {
2245  PrintMessage(MSG_MEDIA_PROTECTED);
2246  }
2247  else {
2248  PrintMessage(MSG_GET_MEDIA_NG);
2249  printf("%s", SystemError(ret));
2250  return VFD_NG;
2251  }
2252 
2253  return VFD_OK;
2254 }
2255 
2256 //
2257 // Format the virtual media with FAT12
2258 //
2259 int Format(const char **args)
2260 {
2261  int mode = OPERATION_ASK;
2263  HANDLE hDevice;
2264  DWORD ret;
2265 
2266  // check parameters
2267 
2268  while (args && *args) {
2269 
2270  if (!_stricmp(*args, "/f") ||
2271  !_stricmp(*args, "/force")) {
2272 
2273  if (mode != OPERATION_ASK) {
2274  PrintMessage(MSG_DUPLICATE_ARGS, *args);
2275  return VFD_NG;
2276  }
2277 
2279  }
2280  else if (!_stricmp(*args, "/q") ||
2281  !_stricmp(*args, "/quit")) {
2282 
2283  if (mode != OPERATION_ASK) {
2284  PrintMessage(MSG_DUPLICATE_ARGS, *args);
2285  return VFD_NG;
2286  }
2287 
2288  mode = OPERATION_QUIT;
2289  }
2290  else if (isalnum(**args)) {
2291  if (target != TARGET_NONE) {
2292  PrintMessage(MSG_DUPLICATE_ARGS, *args);
2293  return VFD_NG;
2294  }
2295 
2296  target = toupper(**args);
2297  }
2298  else {
2299  PrintMessage(MSG_UNKNOWN_OPTION, *args);
2300  PrintMessage(MSG_HINT_FORMAT, help_progname);
2301  return VFD_NG;
2302  }
2303 
2304  args++;
2305  }
2306 
2307  if (target == TARGET_NONE) {
2308  target = '0';
2309  PrintMessage(MSG_TARGET_NOTICE, target);
2310  }
2311 
2312  // ensure that the driver is installed
2313 
2315  PrintMessage(MSG_NOT_INSTALLED);
2316  return VFD_NG;
2317  }
2318 
2319  // ensure that the driver is up to date
2320 
2321  if (CheckDriver() != VFD_OK) {
2322  return VFD_NG;
2323  }
2324 
2325  // ensure that the driver is running
2326 
2327  if (driver_state != SERVICE_RUNNING) {
2328  PrintMessage(MSG_NOT_STARTED);
2329  return VFD_NG;
2330  }
2331 
2332  // Open the device
2333 
2334  hDevice = VfdOpenDevice(target);
2335 
2336  if (hDevice == INVALID_HANDLE_VALUE) {
2337  ret = GetLastError();
2338  PrintMessage(MSG_ACCESS_NG, target);
2339  printf("%s", SystemError(ret));
2340  return VFD_NG;
2341  }
2342 
2343  // check if the media is writable
2344 
2345  ret = VfdGetMediaState(hDevice);
2346 
2347  if (ret != ERROR_SUCCESS) {
2348  PrintMessage(MSG_FORMAT_NG, target);
2349  printf("%s", SystemError(ret));
2350 
2351  CloseHandle(hDevice);
2352  return VFD_NG;
2353  }
2354 
2355  // format the media
2356 
2357 retry:
2359  hDevice, (mode == OPERATION_FORCE));
2360 
2361  if (ret == ERROR_ACCESS_DENIED) {
2362 
2363  PrintMessage(MSG_LOCK_NG, target);
2364 
2365  if (mode == OPERATION_FORCE) {
2366  PrintMessage(MSG_FORMAT_FORCE);
2367  }
2368  else if (mode == OPERATION_QUIT) {
2369  PrintMessage(MSG_FORMAT_QUIT);
2370  CloseHandle(hDevice);
2371  return VFD_NG;
2372  }
2373  else {
2374  int c = InputChar(MSG_RETRY_FORCE_CANCEL, "rfc");
2375 
2376  if (c == 'r') { // retry
2377  goto retry;
2378  }
2379  else if (c == 'f') { // force
2380  VfdDismountVolume(hDevice, TRUE);
2381  }
2382  else { // cancel
2383  CloseHandle(hDevice);
2384  return VFD_NG;
2385  }
2386  }
2387  }
2388  else if (ret != ERROR_SUCCESS) {
2389  PrintMessage(MSG_LOCK_NG, target);
2390  CloseHandle(hDevice);
2391  return VFD_NG;
2392  }
2393 
2394  ret = VfdFormatMedia(hDevice);
2395 
2396  CloseHandle(hDevice);
2397 
2398  if (ret != ERROR_SUCCESS) {
2399  PrintMessage(MSG_FORMAT_NG, target);
2400  printf("%s", SystemError(ret));
2401  return VFD_NG;
2402  }
2403 
2404  // successful operation
2405 
2406  PrintMessage(MSG_FORMAT_OK);
2407 
2408  return VFD_OK;
2409 }
2410 
2411 //
2412 // Assign a drive letter to a Virtual Floppy Drive
2413 //
2414 int Link(const char **args)
2415 {
2416  ULONG target_min = TARGET_NONE;
2417  ULONG target_max = TARGET_NONE;
2418  PCSTR letters = NULL;
2419  BOOL global = TRUE;
2420  HANDLE hDevice;
2421  DWORD ret;
2422 
2423  while (args && *args) {
2424  if (!_stricmp(*args, "/g")) {
2425  global = TRUE;
2426  }
2427  else if (!_stricmp(*args, "/l")) {
2428  global = FALSE;
2429  }
2430  else if (isdigit(**args) || **args == '*') {
2431  if (target_min != TARGET_NONE) {
2432  PrintMessage(MSG_DUPLICATE_ARGS, *args);
2433  return VFD_NG;
2434  }
2435 
2436  if (**args == '*') {
2437  target_min = '0';
2438  target_max = '0' + VFD_MAXIMUM_DEVICES;
2439  }
2440  else {
2441  target_min = **args;
2442  target_max = target_min + 1;
2443  }
2444  }
2445  else if (isalpha(**args)) {
2446  if (letters) {
2447  PrintMessage(MSG_DUPLICATE_ARGS, *args);
2448  return VFD_NG;
2449  }
2450  letters = *args;
2451  }
2452  else {
2453  PrintMessage(MSG_UNKNOWN_OPTION, *args);
2454  PrintMessage(MSG_HINT_LINK, help_progname);
2455  return VFD_NG;
2456  }
2457 
2458  args++;
2459  }
2460 
2461  if (target_min == TARGET_NONE) {
2462  // default: drive 0
2463  target_min = '0';
2464  target_max = '1';
2465  PrintMessage(MSG_TARGET_NOTICE, target_min);
2466  }
2467 
2468  // ensure that the driver is installed
2469 
2471  PrintMessage(MSG_NOT_INSTALLED);
2472  return VFD_NG;
2473  }
2474 
2475  // ensure that the driver is up to date
2476 
2477  if (CheckDriver() != VFD_OK) {
2478  return VFD_NG;
2479  }
2480 
2481  // ensure that the driver is running
2482 
2483  if (driver_state != SERVICE_RUNNING) {
2484  PrintMessage(MSG_NOT_STARTED);
2485  return VFD_NG;
2486  }
2487 
2488  while (target_min < target_max) {
2489  ULONG number;
2490  CHAR letter;
2491 
2492  hDevice = VfdOpenDevice(target_min);
2493 
2494  if (hDevice == INVALID_HANDLE_VALUE) {
2495  ret = GetLastError();
2496  PrintMessage(MSG_ACCESS_NG, target_min);
2497  printf("%s", SystemError(ret));
2498  target_min++;
2499  continue;
2500  }
2501 
2502  ret = VfdGetDeviceNumber(hDevice, &number);
2503 
2504  if (ret != ERROR_SUCCESS) {
2505  PrintMessage(MSG_ACCESS_NG, target_min);
2506  printf("%s", SystemError(ret));
2507  CloseHandle(hDevice);
2508  target_min++;
2509  continue;
2510  }
2511 
2512  if (letters && isalpha(*letters)) {
2513  letter = (CHAR)toupper(*(letters++));
2514  }
2515  else {
2516  letter = VfdChooseLetter();
2517  }
2518 
2519  if (letter) {
2520  if (global) {
2521  ret = VfdSetGlobalLink(hDevice, letter);
2522  }
2523  else {
2524  ret = VfdSetLocalLink(hDevice, letter);
2525  }
2526 
2527  if (ret != ERROR_SUCCESS) {
2528  PrintMessage(MSG_LINK_NG, number, letter);
2529  printf("%s", SystemError(ret));
2530  }
2531  }
2532  else {
2533  PrintMessage(MSG_LINK_FULL);
2534  }
2535 
2536  PrintDriveLetter(hDevice, number);
2537 
2538  CloseHandle(hDevice);
2539 
2540  target_min++;
2541  }
2542 
2543  return VFD_OK;
2544 }
2545 
2546 //
2547 // Remove a drive letter from a Virtual Floppy Drive
2548 //
2549 int Unlink(const char **args)
2550 {
2551  ULONG target_min = TARGET_NONE;
2552  ULONG target_max = TARGET_NONE;
2553  HANDLE hDevice;
2554  DWORD ret;
2555 
2556  while (args && *args) {
2557  if ((isalnum(**args) || **args == '*') &&
2558  (*(*args + 1) == ':' || *(*args + 1) == '\0')) {
2559 
2560  if (target_min != TARGET_NONE) {
2561  PrintMessage(MSG_DUPLICATE_ARGS, *args);
2562  return VFD_NG;
2563  }
2564 
2565  if (**args == '*') {
2566  target_min = '0';
2567  target_max = '0' + VFD_MAXIMUM_DEVICES;
2568  }
2569  else {
2570  target_min = **args;
2571  target_max = target_min + 1;
2572  }
2573  }
2574  else {
2575  PrintMessage(MSG_UNKNOWN_OPTION, *args);
2576  PrintMessage(MSG_HINT_ULINK, help_progname);
2577  return VFD_NG;
2578  }
2579 
2580  args++;
2581  }
2582 
2583  if (target_min == TARGET_NONE) {
2584  // default: drive 0
2585  target_min = '0';
2586  target_max = '1';
2587  PrintMessage(MSG_TARGET_NOTICE, target_min);
2588  }
2589 
2590  // ensure that the driver is installed
2591 
2593  PrintMessage(MSG_NOT_INSTALLED);
2594  return VFD_NG;
2595  }
2596 
2597  // ensure that the driver is up to date
2598 
2599  if (CheckDriver() != VFD_OK) {
2600  return VFD_NG;
2601  }
2602 
2603  // ensure that the driver is running
2604 
2605  if (driver_state != SERVICE_RUNNING) {
2606  PrintMessage(MSG_NOT_STARTED);
2607  return VFD_NG;
2608  }
2609 
2610  while (target_min < target_max) {
2611  ULONG number;
2612 
2613  hDevice = VfdOpenDevice(target_min);
2614 
2615  if (hDevice == INVALID_HANDLE_VALUE) {
2616  ret = GetLastError();
2617  PrintMessage(MSG_ACCESS_NG, target_min);
2618  printf("%s", SystemError(ret));
2619  target_min++;
2620  continue;
2621  }
2622 
2623  ret = VfdGetDeviceNumber(hDevice, &number);
2624 
2625  if (ret != ERROR_SUCCESS) {
2626  PrintMessage(MSG_ACCESS_NG, target_min);
2627  printf("%s", SystemError(ret));
2628  CloseHandle(hDevice);
2629  target_min++;
2630  continue;
2631  }
2632 
2633  VfdSetGlobalLink(hDevice, 0);
2634  VfdSetLocalLink(hDevice, 0);
2635 
2636  PrintDriveLetter(hDevice, number);
2637 
2638  CloseHandle(hDevice);
2639 
2640  target_min++;
2641  }
2642 
2643  return VFD_OK;
2644 }
2645 
2646 //
2647 // Print current driver state
2648 // Command Line Parameters: None
2649 //
2650 int Status(const char **args)
2651 {
2652  HANDLE hDevice;
2653  TCHAR path[MAX_PATH];
2654  DWORD start_type;
2655  DWORD version;
2656  ULONG target;
2657  DWORD ret;
2658 
2660 
2662  PrintMessage(MSG_NOT_INSTALLED);
2663  }
2664  else {
2665 
2666  // get current driver config
2667 
2668  ret = VfdGetDriverConfig(path, &start_type);
2669 
2670  if (ret != ERROR_SUCCESS) {
2671  PrintMessage(MSG_GET_CONFIG_NG);
2672  printf("%s", SystemError(ret));
2673  return VFD_NG;
2674  }
2675 
2676  // print driver file path
2677 
2678  PrintMessage(MSG_DRIVER_FILE, path);
2679 
2680  // print driver version
2681  version = 0;
2682 
2683  if (driver_state == SERVICE_RUNNING) {
2684 
2685  hDevice = VfdOpenDevice(0);
2686 
2687  if (hDevice != INVALID_HANDLE_VALUE) {
2688  ret = VfdGetDriverVersion(hDevice, &version);
2689 
2690  CloseHandle(hDevice);
2691  }
2692 
2693  }
2694 
2695  if (version == 0) {
2697  }
2698 
2699  if (ret == ERROR_SUCCESS) {
2700  PrintMessage(MSG_DRIVER_VERSION,
2701  HIWORD(version) & 0x7fff,
2702  LOWORD(version),
2703  (version & 0x80000000) ? "(debug)" : "");
2704  }
2705  else {
2706  PrintMessage(MSG_GET_VERSION_NG);
2707  printf("%s", SystemError(ret));
2708  }
2709 
2710 
2711  // print driver start type
2712 
2713  PrintMessage(MSG_START_TYPE);
2714 
2715  switch (start_type) {
2716  case SERVICE_AUTO_START:
2717  PrintMessage(MSG_START_AUTO);
2718  break;
2719 
2720  case SERVICE_BOOT_START:
2721  PrintMessage(MSG_START_BOOT);
2722  break;
2723 
2724  case SERVICE_DEMAND_START:
2725  PrintMessage(MSG_START_DEMAND);
2726  break;
2727 
2728  case SERVICE_DISABLED:
2729  PrintMessage(MSG_START_DISABLED);
2730  break;
2731 
2732  case SERVICE_SYSTEM_START :
2733  PrintMessage(MSG_START_SYSTEM);
2734  break;
2735 
2736  default:
2737  PrintMessage(MSG_UNKNOWN_LONG, start_type);
2738  break;
2739  }
2740 
2741  // print current driver state
2742 
2743  PrintMessage(MSG_DRIVER_STATUS);
2744 
2745  switch (driver_state) {
2746  case SERVICE_STOPPED:
2747  PrintMessage(MSG_STATUS_STOPPED);
2748  break;
2749 
2750  case SERVICE_START_PENDING:
2751  PrintMessage(MSG_STATUS_START_P);
2752  break;
2753 
2754  case SERVICE_STOP_PENDING:
2755  PrintMessage(MSG_STATUS_STOP_P);
2756  break;
2757 
2758  case SERVICE_RUNNING:
2759  PrintMessage(MSG_STATUS_RUNNING);
2760  break;
2761 
2763  PrintMessage(MSG_STATUS_CONT_P);
2764  break;
2765 
2766  case SERVICE_PAUSE_PENDING:
2767  PrintMessage(MSG_STATUS_PAUSE_P);
2768  break;
2769 
2770  case SERVICE_PAUSED:
2771  PrintMessage(MSG_STATUS_PAUSED);
2772  break;
2773 
2774  default:
2775  PrintMessage(MSG_UNKNOWN_LONG, driver_state);
2776  break;
2777  }
2778  }
2779 
2780  // print shell extension status
2781 
2782  printf("\n");
2783 
2784  if (VfdCheckHandlers() == ERROR_SUCCESS) {
2785  PrintMessage(MSG_SHELLEXT_ENABLED);
2786  }
2787  else {
2788  PrintMessage(MSG_SHELLEXT_DISABLED);
2789  }
2790 
2791  // if driver is not running, no more info
2792 
2793  if (driver_state != SERVICE_RUNNING) {
2794  return VFD_OK;
2795  }
2796 
2797  // print image information
2798 
2799  for (target = 0; target < VFD_MAXIMUM_DEVICES; target++) {
2800  HANDLE hDevice = VfdOpenDevice(target);
2801 
2802  if (hDevice == INVALID_HANDLE_VALUE) {
2803  ret = GetLastError();
2804  PrintMessage(MSG_ACCESS_NG, target + '0');
2805  printf("%s", SystemError(ret));
2806  return VFD_NG;
2807  }
2808 
2809  PrintImageInfo(hDevice);
2810 
2811  CloseHandle(hDevice);
2812  }
2813 
2814  return VFD_OK;
2815 }
2816 
2817 //
2818 // Print usage help
2819 //
2820 int Help(const char **args)
2821 {
2822  DWORD msg = MSG_HELP_GENERAL;
2823  char *buf = NULL;
2824 
2825  if (args && *args) {
2826  int cmd = ParseHelpTopic(*args);
2827 
2828  if (cmd < 0) {
2829  msg = MSG_HELP_HELP;
2830  }
2831  else {
2832  msg = HelpMsg[cmd].help;
2833  }
2834  }
2835 
2836  FormatMessage(
2840  NULL, msg, 0, (LPTSTR)&buf, 0,
2841  (va_list *)&help_progname);
2842 
2843  if (buf == NULL) {
2844  printf("%s", SystemError(GetLastError()));
2845  return VFD_NG;
2846  }
2847 
2848  ConsolePager(buf, TRUE);
2849  LocalFree(buf);
2850 
2851  return VFD_OK;
2852 }
2853 
2854 //
2855 // Print version information
2856 //
2857 int Version(const char **args)
2858 {
2860 
2862  "http://chitchat.at.infoseek.co.jp/vmware/vfd.html\n");
2863 
2864  return VFD_OK;
2865 }
2866 
2867 //
2868 // Parse command parameter
2869 //
2870 int ParseCommand(const char *cmd)
2871 {
2872 #define CMD_MATCH_NONE -1
2873 #define CMD_MATCH_MULTI -2
2874 
2875  size_t len;
2876  int idx;
2877  int match;
2878 
2879  // skip a leading '/'
2880 
2881  if (*cmd == '/') {
2882  cmd++;
2883  }
2884 
2885  if (*cmd == '\0') {
2886 
2887  // empty command
2888 
2889  return CMD_MATCH_NONE;
2890  }
2891 
2892  // find a match
2893  len = strlen(cmd);
2894  idx = 0;
2896 
2897  while (Commands[idx].cmd) {
2898 
2899  if (strlen(Commands[idx].cmd) >= len &&
2900  !_strnicmp(cmd, Commands[idx].cmd, len)) {
2901 
2902  if (match == CMD_MATCH_NONE) { // first match
2903  match = idx;
2904  }
2905  else { // multiple matches
2906  if (match != CMD_MATCH_MULTI) { // first time
2907  PrintMessage(MSG_AMBIGUOUS_COMMAND, cmd);
2908  printf("> %s ", Commands[match].cmd);
2910  }
2911 
2912  printf("%s ", Commands[idx].cmd);
2913  }
2914  }
2915 
2916  idx++;
2917  }
2918 
2919  if (match == CMD_MATCH_NONE) { // match not found
2920  PrintMessage(MSG_UNKNOWN_COMMAND, cmd);
2921  }
2922  else if (match == CMD_MATCH_MULTI) { // multiple matches
2923  printf("\n");
2924  }
2925 
2926  return match;
2927 }
2928 
2929 int ParseHelpTopic(const char *topic)
2930 {
2931  size_t len;
2932  int idx;
2933  int match;
2934 
2935  if (*topic == '\0') {
2936 
2937  // empty command
2938 
2939  return CMD_MATCH_NONE;
2940  }
2941 
2942  // find a match
2943  len = strlen(topic);
2944  idx = 0;
2946 
2947  while (HelpMsg[idx].keyword) {
2948 
2949  if (strlen(HelpMsg[idx].keyword) >= len &&
2951 
2952  if (match == CMD_MATCH_NONE) { // first match
2953  match = idx;
2954  }
2955  else { // multiple matches
2956  if (match != CMD_MATCH_MULTI) { // first time
2957  PrintMessage(MSG_AMBIGUOUS_COMMAND, topic);
2958  printf("> %s ", HelpMsg[match].keyword);
2960  }
2961 
2962  printf("%s ", HelpMsg[idx].keyword);
2963  }
2964  }
2965 
2966  idx++;
2967  }
2968 
2969  if (match == CMD_MATCH_NONE) { // match not found
2970  PrintMessage(MSG_UNKNOWN_COMMAND, topic);
2971  }
2972  else if (match == CMD_MATCH_MULTI) { // multiple matches
2973  printf("\n");
2974  }
2975 
2976  return match;
2977 }
2978 
2979 //
2980 // Check driver version and update if necessary
2981 //
2983 {
2984  char path[MAX_PATH];
2985  DWORD start;
2986 
2987  // check installed driver file version
2988 
2991 
2992  HANDLE hDevice;
2993 
2994  if (driver_state != SERVICE_RUNNING) {
2995  return VFD_OK;
2996  }
2997 
2998  // check running driver version
2999 
3000  hDevice = VfdOpenDevice(0);
3001 
3002  if (hDevice != INVALID_HANDLE_VALUE) {
3003  CloseHandle(hDevice);
3004  return VFD_OK;
3005  }
3006  }
3007 
3008  PrintMessage(MSG_WRONG_DRIVER);
3009  return VFD_NG;
3010 }
3011 
3012 //
3013 // Print a prompt message and accept the reply input
3014 //
3016 {
3017  HANDLE hStdIn;
3019  DWORD result;
3020  int reply;
3021 
3022  PrintMessage(msg);
3023  fflush(NULL);
3024 
3026 
3028 
3029  for (;;) {
3030  ReadConsoleInput(hStdIn, &input, sizeof(input), &result);
3031 
3032  if (input.EventType == KEY_EVENT &&
3033  input.Event.KeyEvent.bKeyDown) {
3034 
3035  reply = tolower(input.Event.KeyEvent.uChar.AsciiChar);
3036 
3037  if (strchr(ans, reply)) {
3038  break;
3039  }
3040  }
3041  }
3042 
3043  printf("%c\n", reply);
3044 
3045  return reply;
3046 }
3047 
3048 //
3049 // Print image information on a Virtual Floppy Drive
3050 //
3052  HANDLE hDevice)
3053 {
3054  ULONG device_number;
3057  VFD_DISKTYPE disk_type;
3058  VFD_MEDIA media_type;
3059  VFD_FLAGS media_flags;
3061  ULONG image_size;
3062  DWORD ret;
3063 
3064  printf("\n");
3065 
3066  // get current device number
3067 
3068  ret = VfdGetDeviceNumber(hDevice, &device_number);
3069 
3070  if (ret != ERROR_SUCCESS) {
3071  PrintMessage(MSG_GET_LINK_NG);
3072  printf("%s", SystemError(ret));
3073  device_number = (ULONG)-1;
3074  }
3075 
3076  // get current drive letters
3077 
3078  PrintDriveLetter(hDevice, device_number);
3079 
3080  // image file information
3081 
3082  ret = VfdGetImageInfo(hDevice, file_name, &disk_type,
3083  &media_type, &media_flags, &file_type, &image_size);
3084 
3085  if (ret != ERROR_SUCCESS) {
3086  PrintMessage(MSG_GET_FILE_NG);
3087  printf("%s", SystemError(ret));
3088  return;
3089  }
3090 
3091  // print image file information
3092  if (media_type == VFD_MEDIA_NONE) {
3093  PrintMessage(MSG_IMAGE_NONE);
3094  return;
3095  }
3096 
3097  if (file_name[0]) {
3098  PrintMessage(MSG_IMAGE_NAME, file_name);
3099 
3102  }
3103  else {
3104  PrintMessage(MSG_IMAGE_NAME, "<RAM>");
3105 
3108  }
3109 
3110  PrintMessage(MSG_FILE_DESC, file_desc);
3111 
3112  if (disk_type == VFD_DISKTYPE_FILE) {
3113  PrintMessage(MSG_DISKTYPE_FILE);
3114  }
3115  else {
3116  if (media_flags & VFD_FLAG_DATA_MODIFIED) {
3117  PrintMessage(MSG_DISKTYPE_RAM_DIRTY);
3118  }
3119  else {
3120  PrintMessage(MSG_DISKTYPE_RAM_CLEAN);
3121  }
3122  }
3123 
3124  // print other file info
3125 
3126  PrintMessage(MSG_MEDIA_TYPE, VfdMediaTypeName(media_type));
3127 
3128  if (media_flags & VFD_FLAG_WRITE_PROTECTED) {
3129  PrintMessage(MSG_MEDIA_PROTECTED);
3130  }
3131  else {
3132  PrintMessage(MSG_MEDIA_WRITABLE);
3133  }
3134 }
3135 
3136 //
3137 // Print drive letters on a virtual floppy drive
3138 //
3140  HANDLE hDevice,
3141  ULONG nDrive)
3142 {
3143  CHAR letter;
3144 
3145  PrintMessage(MSG_DRIVE_LETTER, nDrive);
3146 
3147  VfdGetGlobalLink(hDevice, &letter);
3148 
3149  if (isalpha(letter)) {
3150  PrintMessage(MSG_PERSISTENT, toupper(letter));
3151  }
3152 
3153  while (VfdGetLocalLink(hDevice, &letter) == ERROR_SUCCESS &&
3154  isalpha(letter)) {
3155  PrintMessage(MSG_EPHEMERAL, toupper(letter));
3156  }
3157 
3158  printf("\n");
3159 }
3160 
3161 //
3162 // Prints a text on screen a page a time
3163 //
3165 {
3166  static int rows = 0;
3167  char prompt[80];
3168  int prompt_len = 0;
3169  HANDLE hStdOut;
3170  HANDLE hStdIn;
3171 
3172  //
3173  // prepare the console input and output handles
3174  //
3177 
3178  for (;;) {
3181  DWORD result;
3182  DWORD mode;
3183  int cols;
3184  char *cur;
3185  char save;
3186 
3187  //
3188  // Get the current console screen information
3189  //
3191 
3192  if (bReset || rows <= 0) {
3193  rows = info.srWindow.Bottom - info.srWindow.Top - 1;
3194  }
3195 
3196  cols = info.dwSize.X;
3197 
3198  // console window is too small for paging
3199 
3200  if (rows <= 0) {
3201  // print all text and exit
3202  printf("%s", pBuffer);
3203  break;
3204  }
3205 
3206  //
3207  // find the tail of the text to be printed this time
3208  //
3209  cur = pBuffer;
3210  save = '\0';
3211 
3212  while (*cur) {
3213  if (*(cur++) == '\n' || (cols--) == 0) {
3214  // reached the end of a line
3215  if (--rows == 0) {
3216  // reached the end of a page
3217  // insert a terminating NULL char
3218  save = *cur;
3219  *cur = '\0';
3220  break;
3221  }
3222 
3223  cols = info.dwSize.X;
3224  }
3225  }
3226 
3227  // print the current page
3228  printf("%s", pBuffer);
3229 
3230  // end of the whole text?
3231  if (save == '\0') {
3232  break;
3233  }
3234 
3235  //
3236  // prompt for the next page
3237  //
3238 
3239  // prepare the prompt text
3240 
3241  if (prompt_len == 0) {
3242 
3243  prompt_len = FormatMessage(
3246  NULL, MSG_PAGER_PROMPT, 0,
3247  prompt, sizeof(prompt), NULL);
3248 
3249  if (prompt_len == 0) {
3250  strcpy(prompt, "Press any key to continue...");
3251  prompt_len = strlen(prompt);
3252  }
3253  }
3254 
3255  // get the current console input mode
3256 
3258 
3259  // change the mode to receive Ctrl+C as a regular input
3260 
3262 
3263  // get the current cursor position
3264 
3266 
3267  // print the prompt text
3268 
3270  prompt_len, info.dwCursorPosition, &result);
3271 
3272  // reverse the text color
3273 
3275  (WORD)(info.wAttributes | COMMON_LVB_REVERSE_VIDEO),
3276  prompt_len, info.dwCursorPosition, &result);
3277 
3278  // move cursor to the end of the prompt text
3279 
3280  info.dwCursorPosition.X =
3281  (short)(info.dwCursorPosition.X + prompt_len);
3282 
3283  SetConsoleCursorPosition(hStdOut, info.dwCursorPosition);
3284 
3285  // wait for a key press event
3286 
3288 
3289  do {
3290  ReadConsoleInput(hStdIn, &input, sizeof(input), &result);
3291  }
3292  while (input.EventType != KEY_EVENT ||
3293  !input.Event.KeyEvent.bKeyDown ||
3294  !input.Event.KeyEvent.uChar.AsciiChar);
3295 
3296  // restore the original cursor position
3297 
3298  info.dwCursorPosition.X =
3299  (short)(info.dwCursorPosition.X - prompt_len);
3300 
3301  SetConsoleCursorPosition(hStdOut, info.dwCursorPosition);
3302 
3303  // delete the prompt text
3304 
3306  prompt_len, info.dwCursorPosition, &result);
3307 
3308  // restore the text attribute to norml
3309 
3311  prompt_len, info.dwCursorPosition, &result);
3312 
3313  // restore the original console mode
3314 
3316 
3317  // check if the input was 'q', <esc> or <Ctrl+C> ?
3318 
3319  if (input.Event.KeyEvent.uChar.AsciiChar == VK_CANCEL ||
3320  input.Event.KeyEvent.uChar.AsciiChar == VK_ESCAPE ||
3321  tolower(input.Event.KeyEvent.uChar.AsciiChar) == 'q') {
3322 
3323  // cancelled by the user
3324  return FALSE;
3325  }
3326 
3327  //
3328  // process the next page
3329  //
3330  *cur = save;
3331  pBuffer = cur;
3332  }
3333 
3334  return TRUE;
3335 }
3336 
3337 //
3338 // Format and print a message text
3339 //
3341 {
3342  char *buf = NULL;
3343  va_list list;
3344 
3345  va_start(list, msg);
3346 
3347  if (FormatMessage(
3350  NULL, msg, 0, (LPTSTR)&buf, 0, &list)) {
3351 
3352  printf("%s", buf);
3353  }
3354  else {
3355  printf("Unknown Message ID %u\n", msg);
3356  }
3357 
3358  va_end(list);
3359 
3360  if (buf) {
3361  LocalFree(buf);
3362  }
3363 }
3364 
3365 //
3366 // Return a system error message text
3367 //
3368 const char *SystemError(DWORD err)
3369 {
3370  static char msg[256];
3371 
3372  if (!FormatMessage(
3375  NULL, err, 0, msg, sizeof(msg), NULL)) {
3376 #ifndef __REACTOS__
3377  sprintf(msg, "Unknown system error %lu (0x%08x)\n", err, err);
3378 #else
3379  sprintf(msg, "Unknown system error %lu (0x%08lx)\n", err, err);
3380 #endif
3381  }
3382 
3383  return msg;
3384 }
3385 
3386 //
3387 // Convert a path to match the case of names on the disk
3388 //
3389 void ConvertPathCase(char *src, char *dst)
3390 {
3391  HANDLE hFind;
3393  char *p;
3394 
3395  p = dst;
3396 
3397  if (*src == '\"') {
3398  src++;
3399  }
3400 
3401  if (*(src + strlen(src) - 1) == '\"') {
3402  *(src + strlen(src) - 1) = '\0';
3403  }
3404 
3405  //
3406  // handle drive / remote server name
3407  //
3408  if (isalpha(*src) && *(src + 1) == ':') {
3409 
3410  // drive name
3411 
3412  *(p++) = (char)toupper(*src);
3413  strcpy(p++, ":\\");
3414 
3415  src += 2;
3416  }
3417  else if (*src == '\\' || *src == '/') {
3418 
3419  // absolute path or remote name
3420 
3421  if ((*(src + 1) == '\\' || *(src + 1) == '/') &&
3422  *(src + 2) && *(src + 2) != '\\' && *(src + 2) != '/') {
3423 
3424  // remote path
3425 
3426  *(p++) = '\\';
3427  *(p++) = '\\';
3428  src += 2;
3429 
3430  while (*src && *src != '\\' && *src != '/') {
3431  *(p++) = *(src++);
3432  }
3433  }
3434 
3435  strcpy(p, "\\");
3436  }
3437  else {
3438  *p = '\0';
3439  }
3440 
3441  // skip redundant '\'
3442 
3443  while (*src == '\\' || *src == '/') {
3444  src++;
3445  }
3446 
3447  // process the path
3448 
3449  while (*src) {
3450 
3451  char *q = src;
3452 
3453  // separate the next part
3454 
3455  while (*q && *q != '\\' && *q != '/') {
3456  q++;
3457  }
3458 
3459  if ((q - src) == 2 && !strncmp(src, "..", 2)) {
3460  // parent dir - copy as it is
3461  if (p != dst) {
3462  *p++ = '\\';
3463  }
3464 
3465  strcpy(p, "..");
3466  p += 2;
3467  }
3468  else if ((q - src) > 1 || *src != '.') {
3469  // path name other than "."
3470  if (p != dst) {
3471  *(p++) = '\\';
3472  }
3473 
3474  strncpy(p, src, (q - src));
3475  *(p + (q - src)) = '\0';
3476 
3477  hFind = FindFirstFile(dst, &find);
3478 
3479  if (hFind == INVALID_HANDLE_VALUE) {
3480  strcpy(p, src);
3481  break;
3482  }
3483 
3484  FindClose(hFind);
3485 
3486  strcpy(p, find.cFileName);
3487  p += strlen(p);
3488  }
3489 
3490  // skip trailing '\'s
3491 
3492  while (*q == '\\' || *q == '/') {
3493  q++;
3494  }
3495 
3496  src = q;
3497  }
3498 }
static int ProcessCommandLine(int argc, const char **args)
Definition: vfdcmd.c:478
static int argc
Definition: ServiceArgs.c:12
#define ERROR_FILE_EXISTS
Definition: winerror.h:165
#define SERVICE_SYSTEM_START
Definition: cmtypes.h:974
DWORD WINAPI VfdGetDriverVersion(HANDLE hDevice, PULONG pVersion)
Definition: vfdctl.c:2446
#define TRUE
Definition: types.h:120
#define PROTECT_NONE
static int Start(const char **args)
Definition: vfdcmd.c:853
#define VFD_OK
Definition: vfdcmd.c:44
#define CloseHandle
Definition: compat.h:398
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:736
#define IS_WINDOWS_NT()
Definition: vfdcmd.c:159
int max_args
Definition: vfdcmd.c:86
BOOL WINAPI FillConsoleOutputAttribute(IN HANDLE hConsoleOutput, IN WORD wAttribute, IN DWORD nLength, IN COORD dwWriteCoord, OUT LPDWORD lpNumberOfAttrsWritten)
Definition: console.c:474
#define ERROR_SUCCESS
Definition: deptool.c:10
static int Install(const char **args)
Definition: vfdcmd.c:535
UCHAR VFD_DISKTYPE
Definition: vfdtypes.h:60
#define SERVICE_PAUSE_PENDING
Definition: winsvc.h:26
static void PrintImageInfo(HANDLE hDevice)
Definition: vfdcmd.c:3051
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
Definition: ftp_var.h:139
Definition: match.c:28
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
#define ERROR_WRITE_PROTECT
Definition: winerror.h:122
#define SERVICE_PAUSED
Definition: winsvc.h:27
const char * PCSTR
Definition: typedefs.h:51
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
#define FORMAT_MESSAGE_ARGUMENT_ARRAY
Definition: winbase.h:405
char CHAR
Definition: xmlstorage.h:175
BOOL WINAPI GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode)
Definition: console.c:1571
static int Config(const char **args)
Definition: vfdcmd.c:778
DWORD help
Definition: vfdcmd.c:116
static const struct @1491 HelpMsg[]
DWORD WINAPI VfdCheckHandlers()
Definition: vfdshutil.cpp:393
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
BOOL WINAPI FlushConsoleInputBuffer(IN HANDLE hConsoleInput)
Definition: console.c:169
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1635
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:152
#define SERVICE_START_PENDING
Definition: winsvc.h:22
#define isalpha(c)
Definition: acclib.h:74
char * cmd
Definition: vfdcmd.c:85
FILE * stdin
UCHAR VFD_FLAGS
Definition: vfdtypes.h:63
static void ConvertPathCase(char *src, char *dst)
Definition: vfdcmd.c:3389
ULONG WINAPI VfdGetMediaSize(VFD_MEDIA nMediaType)
Definition: vfdctl.c:3272
static int Unlink(const char **args)
Definition: vfdcmd.c:2549
DWORD WINAPI VfdCreateImageFile(PCSTR sFileName, VFD_MEDIA nMediaType, VFD_FILETYPE nFileType, BOOL bOverWrite)
Definition: vfdctl.c:3126
_Check_return_ _CRTIMP int __cdecl isalnum(_In_ int _C)
#define argv
Definition: mplay32.c:18
#define VK_ESCAPE
Definition: winuser.h:2168
DWORD WINAPI VfdDismountVolume(HANDLE hDevice, BOOL bForce)
Definition: vfdctl.c:2629
Definition: match.c:390
static int Stop(const char **args)
Definition: vfdcmd.c:902
#define _stricmp
Definition: cat.c:22
DWORD WINAPI VfdStartDriver(PDWORD pState)
Definition: vfdctl.c:647
static int Link(const char **args)
Definition: vfdcmd.c:2414
CHAR * LPTSTR
Definition: xmlstorage.h:192
FILE * stdout
DWORD WINAPI VfdGetDeviceNumber(HANDLE hDevice, PULONG pNumber)
Definition: vfdctl.c:2359
struct _test_info info[]
Definition: SetCursorPos.c:19
static int Format(const char **args)
Definition: vfdcmd.c:2259
DWORD WINAPI VfdConfigDriver(DWORD nStart)
Definition: vfdctl.c:468
#define SERVICE_DISABLED
Definition: cmtypes.h:977
#define sprintf(buf, format,...)
Definition: sprintf.c:55
DWORD WINAPI VfdGetDriverConfig(PSTR sFileName, PDWORD pStart)
Definition: vfdctl.c:959
GLuint const GLubyte GLvoid * src
Definition: s_context.h:57
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:91
static void PrintMessage(UINT msg,...)
Definition: vfdcmd.c:3340
int main(int argc, const char **argv)
Definition: vfdcmd.c:164
GLenum GLclampf GLint i
Definition: glfuncs.h:14
#define VFD_MAXIMUM_DEVICES
Definition: vfdtypes.h:75
DWORD WINAPI VfdGetLocalLink(HANDLE hDevice, PCHAR pLetter)
Definition: vfdctl.c:2281
#define SERVICE_STOPPED
Definition: winsvc.h:21
#define va_end(ap)
Definition: acmsvcex.h:90
#define VFD_FLAG_DATA_MODIFIED
Definition: vfdtypes.h:69
#define ERROR_ACCESS_DENIED
Definition: compat.h:87
#define ReadConsoleInput
Definition: wincon.h:766
VFD_MEDIA WINAPI VfdLookupMedia(ULONG nSize)
Definition: vfdctl.c:3256
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleMode(HANDLE hConsoleHandle, DWORD dwMode)
Definition: console.c:1608
static size_t double number
Definition: printf.c:64
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
Definition: console.c:2111
HANDLE hStdOut
Definition: more.c:45
DWORD WINAPI VfdWriteProtect(HANDLE hDevice, BOOL bProtect)
Definition: vfdctl.c:2484
#define SERVICE_RUNNING
Definition: winsvc.h:24
_Check_return_ _CRTIMP int __cdecl _strnicmp(_In_reads_or_z_(_MaxCount) const char *_Str1, _In_reads_or_z_(_MaxCount) const char *_Str2, _In_ size_t _MaxCount)
#define KEY_EVENT
Definition: wincon.h:122
#define FORMAT_MESSAGE_ALLOCATE_BUFFER
Definition: winbase.h:400
#define GetCurrentDirectory
Definition: winbase.h:3619
#define COMMON_LVB_REVERSE_VIDEO
Definition: wincon.h:53
unsigned int idx
Definition: utils.c:41
static int Save(const char **args)
Definition: vfdcmd.c:1851
DWORD WINAPI VfdUnregisterHandlers()
Definition: vfdshutil.cpp:297
UINT msg
Definition: msvc.h:92
smooth NULL
Definition: ftsmooth.c:416
static const WCHAR version[]
Definition: asmname.c:64
PVOID pBuffer
DWORD WINAPI VfdRegisterHandlers()
Definition: vfdshutil.cpp:100
#define ERROR_NOT_READY
Definition: winerror.h:124
unsigned char
Definition: typeof.h:27
BOOL WINAPI SetConsoleCursorPosition(IN HANDLE hConsoleOutput, IN COORD dwCursorPosition)
Definition: console.c:590
#define OPERATION_FORCE
Definition: vfdcmd.c:52
static const struct @1490 Commands[]
static int Help(const char **args)
Definition: vfdcmd.c:2820
char * va_list
Definition: acmsvcex.h:78
#define SERVICE_BOOT_START
Definition: cmtypes.h:973
struct match match
Definition: match.c:33
int __cdecl system(_In_opt_z_ const char *_Command)
#define FindFirstFile
Definition: winbase.h:3596
static int Version(const char **args)
Definition: vfdcmd.c:2857
#define STD_INPUT_HANDLE
Definition: winbase.h:264
#define CMD_MATCH_NONE
#define isdigit(c)
Definition: acclib.h:68
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:404
int(* cmdfnc)(const char **args)
Definition: vfdcmd.c:62
DWORD WINAPI VfdSetLocalLink(HANDLE hDevice, CHAR cLetter)
Definition: vfdctl.c:2154
BOOL WINAPI GetConsoleScreenBufferInfo(IN HANDLE hConsoleOutput, OUT PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo)
Definition: console.c:544
#define FORMAT_MESSAGE_FROM_HMODULE
Definition: winbase.h:403
#define VFD_NOT_INSTALLED
Definition: vfdapi.h:20
#define _CRTDBG_REPORT_FLAG
Definition: crtdbg.h:68
#define _CRTDBG_LEAK_CHECK_DF
Definition: crtdbg.h:60
#define VFD_FLAG_WRITE_PROTECTED
Definition: vfdtypes.h:68
static int InputChar(ULONG msg, PCSTR ans)
Definition: vfdcmd.c:3015
char TCHAR
Definition: xmlstorage.h:189
int toupper(int c)
Definition: utclib.c:881
DWORD WINAPI VfdSetGlobalLink(HANDLE hDevice, CHAR cLetter)
Definition: vfdctl.c:1984
unsigned int BOOL
Definition: ntddk_ex.h:94
static int Open(const char **args)
Definition: vfdcmd.c:1088
#define OPERATION_QUIT
Definition: vfdcmd.c:51
cmdfnc func
Definition: vfdcmd.c:87
char * keyword
Definition: vfdcmd.c:115
#define MAX_PATH
Definition: compat.h:26
DWORD WINAPI VfdGetMediaState(HANDLE hDevice)
Definition: vfdctl.c:1949
DWORD WINAPI VfdFormatMedia(HANDLE hDevice)
Definition: vfdctl.c:2523
const GLubyte * c
Definition: glext.h:8905
unsigned int UINT
Definition: ndis.h:50
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
static const char * SystemError(DWORD err)
Definition: vfdcmd.c:3368
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
FD_TYPE file_type(FDSC **curr, char *fixed)
Definition: file.c:221
PCSTR WINAPI VfdMediaTypeName(VFD_MEDIA nMediaType)
Definition: vfdctl.c:3280
DWORD WINAPI VfdGetGlobalLink(HANDLE hDevice, PCHAR pLetter)
Definition: vfdctl.c:2114
#define TARGET_NONE
Definition: vfdcmd.c:57
DWORD WINAPI VfdGetDriverState(PDWORD pState)
Definition: vfdctl.c:1121
#define FILE_ATTRIBUTE_COMPRESSED
Definition: nt_native.h:711
#define VK_CANCEL
Definition: winuser.h:2146
#define FormatMessage
Definition: winbase.h:3609
int ret
static int Remove(const char **args)
Definition: vfdcmd.c:648
UCHAR VFD_FILETYPE
Definition: vfdtypes.h:62
static int Status(const char **args)
Definition: vfdcmd.c:2650
static int Shell(const char **args)
Definition: vfdcmd.c:1020
VOID VfdCloseImage(IN PDEVICE_EXTENSION DeviceExtension)
Definition: vfdimg.c:435
GLenum GLsizei len
Definition: glext.h:6722
Definition: _list.h:228
#define STD_OUTPUT_HANDLE
Definition: winbase.h:265
#define err(...)
HANDLE WINAPI VfdOpenDevice(ULONG nTarget)
Definition: vfdctl.c:1215
#define FillConsoleOutputCharacter
Definition: wincon.h:776
GLenum mode
Definition: glext.h:6217
#define GetFileAttributes
Definition: winbase.h:3629
DWORD WINAPI VfdGetImageInfo(HANDLE hDevice, PSTR sFileName, PVFD_DISKTYPE pDiskType, PVFD_MEDIA pMediaType, PVFD_FLAGS pMediaFlags, PVFD_FILETYPE pFileType, PULONG pImageSize)
Definition: vfdctl.c:1839
static int CheckDriver()
Definition: vfdcmd.c:2982
static int Protect(const char **args)
Definition: vfdcmd.c:2132
DWORD WINAPI VfdInstallDriver(PCSTR sFileName, DWORD nStart)
Definition: vfdctl.c:241
#define ENABLE_PROCESSED_INPUT
Definition: wincon.h:75
#define FORMAT_MESSAGE_IGNORE_INSERTS
Definition: winbase.h:401
_Check_return_opt_ _CRTIMP char *__cdecl fgets(_Out_writes_z_(_MaxCount) char *_Buf, _In_ int _MaxCount, _Inout_ FILE *_File)
HANDLE hStdIn
Definition: more.c:45
static const char * help_progname
Definition: vfdcmd.c:39
#define SERVICE_CONTINUE_PENDING
Definition: winsvc.h:25
#define FILE_ATTRIBUTE_ENCRYPTED
Definition: ntifs_ex.h:385
static DWORD driver_state
Definition: vfdcmd.c:34
DWORD hint
Definition: vfdcmd.c:88
GLenum GLenum GLenum input
Definition: glext.h:9031
static void PrintDriveLetter(HANDLE hDevice, ULONG nDrive)
Definition: vfdcmd.c:3139
DWORD WINAPI VfdSaveImage(HANDLE hDevice, PCSTR sFileName, BOOL bOverWrite, BOOL bTruncate)
Definition: vfdctl.c:2685
_Check_return_opt_ _CRTIMP int __cdecl fflush(_Inout_opt_ FILE *_File)
#define VFD_PRODUCT_DESC
Definition: vfdver.h:66
#define SetConsoleTitle
Definition: wincon.h:771
DWORD WINAPI VfdCheckDriverFile(PCSTR sFileName, PULONG pFileVersion)
Definition: vfdctl.c:2867
GLuint start
Definition: gl.h:1545
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
Definition: services.c:325
DWORD WINAPI VfdCheckImageFile(PCSTR sFileName, PDWORD pAttributes, PVFD_FILETYPE pFileType, PULONG pImageSize)
Definition: vfdctl.c:3035
static const char topic[]
Definition: propsys.c:43
NTSTATUS VfdOpenImage(IN PDEVICE_EXTENSION DeviceExtension, IN PVFD_IMAGE_INFO ImageInfo)
Definition: vfdimg.c:104
#define va_start(ap, A)
Definition: acmsvcex.h:91
CHAR WINAPI VfdChooseLetter()
Definition: vfdctl.c:3205
GLuint const GLubyte GLvoid const GLvoid * dst
Definition: s_context.h:57
static BOOL ConsolePager(char *pBuffer, BOOL bReset)
Definition: vfdcmd.c:3164
DWORD WINAPI VfdRemoveDriver()
Definition: vfdctl.c:557
char * strchr(const char *String, int ch)
Definition: utclib.c:501
static LPCWSTR file_name
Definition: protocol.c:146
#define SERVICE_AUTO_START
Definition: cmtypes.h:975
static int ParseHelpTopic(const char *topic)
Definition: vfdcmd.c:2929
#define msg(x)
Definition: auth_time.c:54
static TAGID TAGID find
Definition: db.cpp:143
#define PROTECT_OFF
#define OPERATION_ASK
Definition: vfdcmd.c:50
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define c
Definition: ke_i.h:80
#define HIWORD(l)
Definition: typedefs.h:246
unsigned int ULONG
Definition: retypes.h:1
GLenum target
Definition: glext.h:7315
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define CMD_MATCH_MULTI
#define list
Definition: rosglue.h:35
void WINAPI VfdMakeFileDesc(PSTR pBuffer, ULONG nBufSize, VFD_FILETYPE nFileType, ULONG nFileSize, DWORD nFileAttr)
Definition: vfdguiut.c:376
#define VFD_COPYRIGHT_STR
Definition: vfdver.h:69
static int InteractiveConsole()
Definition: vfdcmd.c:231
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
#define VFD_NG
Definition: vfdcmd.c:45
static int Close(const char **args)
Definition: vfdcmd.c:1636
static int ParseCommand(const char *cmd)
Definition: vfdcmd.c:2870
GLfloat GLfloat p
Definition: glext.h:8902
BOOL WINAPI VfdIsValidPlatform()
Definition: vfdlib.c:87
#define WriteConsoleOutputCharacter
Definition: wincon.h:777
#define SERVICE_DEMAND_START
Definition: cmtypes.h:976
GLuint64EXT * result
Definition: glext.h:11304
static const struct access_res create[16]
Definition: package.c:7720
int tolower(int c)
Definition: utclib.c:902
#define CHAR(Char)
#define args
Definition: format.c:66
#define SERVICE_STOP_PENDING
Definition: winsvc.h:23
#define _CrtSetDbgFlag(f)
Definition: crtdbg.h:192
#define LOWORD(l)
Definition: pedump.c:82
UCHAR VFD_MEDIA
Definition: vfdtypes.h:61
#define SetCurrentDirectory
Definition: winbase.h:3717
#define PROTECT_ON
struct task_struct * current
Definition: linux.c:32
_Ret_z_ WCHAR * file_desc(_In_ PFILE_OBJECT FileObject)
Definition: btrfs.c:1332
#define printf
Definition: config.h:203
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:29
static GLint image_size(GLint width, GLint height, GLenum format, GLenum type)
Definition: mipmap.c:4856
DWORD WINAPI VfdStopDriver(PDWORD pState)
Definition: vfdctl.c:801
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502