ReactOS  0.4.14-dev-41-g31d7680
vfdctl.c
Go to the documentation of this file.
1 /*
2  vfdctl.c
3 
4  Virtual Floppy Drive for Windows
5  Driver control library
6  Driver and image control functions
7 
8  Copyright (C) 2003-2005 Ken Kato
9 */
10 
11 #ifdef __cplusplus
12 #pragma message(__FILE__": Compiled as C++ for testing purpose.")
13 #endif // __cplusplus
14 
15 #define WIN32_LEAN_AND_MEAN
16 #include <windows.h>
17 #include <dbt.h>
18 #ifdef _MSC_VER
19 #pragma warning (push, 3)
20 #endif
21 #include <shlobj.h>
22 #include <winioctl.h>
23 #ifdef _MSC_VER
24 #pragma warning (pop)
25 #endif
26 #include <stdio.h>
27 
28 #include "vfdtypes.h"
29 #include "vfdio.h"
30 #include "vfdapi.h"
31 #include "vfdlib.h"
32 #include "vfdver.h"
33 
34 #ifndef IOCTL_DISK_GET_LENGTH_INFO
35 // Old winioctl.h header doesn't define the following
36 
37 #define IOCTL_DISK_GET_LENGTH_INFO CTL_CODE(\
38 IOCTL_DISK_BASE, 0x0017, METHOD_BUFFERED, FILE_READ_ACCESS)
39 
40 typedef struct _GET_LENGTH_INFORMATION {
43 
44 #endif // IOCTL_DISK_GET_LENGTH_INFO
45 
46 //
47 // DOS device name (\\.\VirtualFD)
48 //
49 #ifndef __REACTOS__
50 #define VFD_DEVICE_TEMPLATE "\\\\.\\" VFD_DEVICE_BASENAME "%u"
51 #else
52 #define VFD_DEVICE_TEMPLATE "\\\\.\\" VFD_DEVICE_BASENAME "%lu"
53 #endif
54 #define VFD_VOLUME_TEMPLATE "\\\\.\\%c:"
55 
56 #define VFD_INSTALL_DIRECTORY "\\system32\\drivers\\"
57 
58 #ifdef _DEBUG
59 #ifndef __REACTOS__
60 extern ULONG TraceFlags = (ULONG)-1;//0;
61 extern CHAR *TraceFile = NULL;
62 extern ULONG TraceLine = 0;
63 #else
64 ULONG TraceFlags = (ULONG)-1;//0;
65 CHAR const * TraceFile = NULL;
66 ULONG TraceLine = 0;
67 #endif
68 #endif
69 
70 //
71 // broadcast a WM_DEVICECHANGE system message to inform
72 // a drive letter creation / removal
73 //
74 #define VFD_LINK_CREATED 0
75 #define VFD_LINK_REMOVED 1
76 
77 static void VfdBroadcastLink(
78  CHAR cLetter,
79  BOOL bRemoved)
80 {
81  DWORD receipients;
82  DWORD device_event;
84 
85  if (!isalpha(cLetter)) {
86  VFDTRACE(0,
87  ("VfdBroadcastLink: invalid parameter"))
88  return;
89  }
90 
91  receipients = BSM_APPLICATIONS;
92 
93  device_event = bRemoved ?
95 
96  ZeroMemory(&params, sizeof(params));
97 
98  params.dbcv_size = sizeof(params);
99  params.dbcv_devicetype = DBT_DEVTYP_VOLUME;
100  params.dbcv_reserved = 0;
101  params.dbcv_unitmask = (1 << (toupper(cLetter) - 'A'));
102  params.dbcv_flags = 0;
103 
106  &receipients,
108  device_event,
109  (LPARAM)&params) <= 0) {
110 
111  VFDTRACE(0,
112  ("VfdBroadcastLink: BroadcastSystemMessage - %s",
114  }
115 }
116 
117 //
118 // Broadcast a VFD notify message
119 //
120 static __inline void VfdNotify(
121  WPARAM wParam,
122  LPARAM lParam)
123 {
124  // SendNotifyMessage causes volume locking conflict (I think)
125  // on Windows XP while closing an image with VfdWin
126 // SendNotifyMessage(HWND_BROADCAST, uVfdMsg, wParam, lParam);
128 }
129 
130 #ifdef VFD_EMBED_DRIVER
131 //
132 // Restore the VFD driver file in the system directory
133 //
134 
135 static DWORD VfdRestoreDriver(
136  PCSTR sPath)
137 {
138 #define FUNC "VfdRestoreDriver"
139  HRSRC hRes;
140  DWORD size;
141  HGLOBAL hDrv;
142  PVOID pData;
143  DWORD result;
144  HANDLE hFile;
145  DWORD ret;
146 
147  //
148  // Prepare driver binary
149  //
150 
151  // use embedded driver binary
152 
153 #define S(s) #s
154  hRes = FindResource(g_hDllModule,
155  S(VFD_DRIVER_NAME_ID), S(VFD_DRIVER_TYPE_ID));
156 #undef S
157 
158  if (hRes == NULL) {
159  ret = GetLastError();
160 
161  VFDTRACE(0,
162  (FUNC ": FindResource - %s",
163  SystemMessage(ret)));
164 
165  return ret;
166  }
167 
169 
170  if (size == 0) {
171  ret = GetLastError();
172 
173  VFDTRACE(0,
174  (FUNC ": SizeofResource - %s",
175  SystemMessage(ret)));
176 
177  return ret;
178  }
179 
180  hDrv = LoadResource(g_hDllModule, hRes);
181 
182  if (hDrv == NULL) {
183  ret = GetLastError();
184 
185  VFDTRACE(0,
186  (FUNC ": LoadResource - %s",
187  SystemMessage(ret)));
188 
189  return ret;
190  }
191 
192  pData = LockResource(hDrv);
193 
194  if (pData == NULL) {
195  ret = GetLastError();
196 
197  VFDTRACE(0,
198  (FUNC ": LockResource - %s",
199  SystemMessage(ret)));
200 
201  return ret;
202  }
203 
204  // create the driver file
205 
206  hFile = CreateFile(sPath, GENERIC_WRITE,
207  0, NULL, OPEN_ALWAYS, 0, NULL);
208 
209  if (hFile == INVALID_HANDLE_VALUE) {
210  ret = GetLastError();
211 
212  VFDTRACE(0,
213  (FUNC ": CreateFile(%s) - %s",
214  sPath, SystemMessage(ret)));
215 
216  return ret;
217  }
218 
219  if (!WriteFile(hFile, pData, size, &result, NULL) ||
220  size != result) {
221  ret = GetLastError();
222 
223  VFDTRACE(0,
224  (FUNC ": CreateFile - %s",
225  SystemMessage(ret)));
226 
228  return ret;
229  }
230 
233 
234  return ERROR_SUCCESS;
235 }
236 #endif // VFD_EMBED_DRIVER
237 
238 //
239 // Install the Virtual Floppy Driver
240 //
242  PCSTR sFileName,
243  DWORD nStart)
244 {
245 #undef FUNC
246 #define FUNC "VfdInstallDriver"
247  SC_HANDLE hScManager; // Service Control Manager
248  SC_HANDLE hService = NULL; // Service (= Driver)
249 #ifndef VFD_EMBED_DRIVER
251  PSTR file_name;
252 #endif // VFD_EMBED_DRIVER
253  CHAR system_dir[MAX_PATH];
254  PSTR inst_path;
255  DWORD len;
257 
258 #ifdef __REACTOS__
259  CHAR full_file_path[MAX_PATH];
260 #endif
261 
262  // get SystemRoot directory path
263 
264 // len = GetEnvironmentVariable(
265 // "SystemRoot", system_dir, sizeof(system_dir));
266  len = GetWindowsDirectory(system_dir, sizeof(system_dir));
267 
268  if (len == 0 || len > sizeof(system_dir)) {
269  VFDTRACE(0,
270  (FUNC ": %%SystemRoot%% is empty or too long.\n"));
271 
272  return ERROR_BAD_ENVIRONMENT;
273  }
274 
275  inst_path = &system_dir[len];
276 
277 #ifdef __REACTOS__
278  strcpy(full_file_path, system_dir);
279  strcat(full_file_path, VFD_INSTALL_DIRECTORY);
280  strcat(full_file_path, VFD_DRIVER_FILENAME);
281 #endif
282 
283 #ifdef VFD_EMBED_DRIVER
284  //
285  // use embedded driver file
286  //
288 
289  ret = VfdRestoreDriver(system_dir);
290 
291  if (ret != ERROR_SUCCESS) {
292  return ret;
293  }
294 
295 #else // VFD_EMBED_DRIVER
296  // Prepare driver binary's full path
297 
298  if (sFileName == NULL || *sFileName == '\0') {
299 
300  // default driver file is vfd.sys in the same directory as executable
301 
303  NULL, file_path, sizeof(file_path));
304 
305  if (len == 0) {
306  ret = GetLastError();
307 
308  VFDTRACE(0,
309  (FUNC ": GetModuleFileName - %s",
310  SystemMessage(ret)));
311 
312  return ret;
313  }
314 
315  // search the last '\' character
316 
317  while (len > 0 && file_path[len - 1] != '\\') {
318  len --;
319  }
320 
321  // supply the file name (vfd.sys)
322 
323  file_name = &file_path[len];
325  }
326  else {
327 
328  // ensure that tha path is an absolute full path
329 
331  sFileName,
332  sizeof(file_path),
333  file_path,
334  &file_name);
335 
336  if (len == 0) {
337  ret = GetLastError();
338 
339  VFDTRACE(0,
340  (FUNC ": GetFullPathName(%s) - %s\n",
341  sFileName, SystemMessage(ret)));
342 
343  return ret;
344  }
345 
347  // if the specified path is a directory,
348  // supply the file name (vfd.sys)
349 
350  file_name = &file_path[len];
352  }
353  }
354 
355 #ifdef __REACTOS__
356  // Check install directory & file exist or use full_file_path
357 
359  strcpy(file_path, full_file_path);
360  }
361 #endif
362 
363  // Check if the file is a valid Virtual Floppy driver
364 
366 
367  if (ret != ERROR_SUCCESS) {
368  VFDTRACE(0,
369  (FUNC ": VfdCheckDriverFile(%s)\n", file_path));
370 
371  return ret;
372  }
373 
374  // if the path is under the system directory, make it relative
375  // to the system directory
376 
377  len = strlen(system_dir);
378 
379  if (!_strnicmp(file_path, system_dir, len)) {
380  inst_path = &file_path[len];
381 
382  while (*inst_path == '\\') {
383  inst_path++;
384  }
385  }
386  else {
387  inst_path = &file_path[0];
388  }
389 #endif // VFD_EMBED_DRIVER
390 
391  // Connect to the Service Control Manager
392 
393  hScManager = OpenSCManager(
394  NULL, // local machine
395  NULL, // local database
396  SC_MANAGER_CREATE_SERVICE); // access required
397 
398  if (hScManager == NULL) {
399  ret = GetLastError();
400 
401  VFDTRACE(0,
402  (FUNC ": OpenSCManager() - %s",
403  SystemMessage(ret)));
404 
405  goto cleanup;
406  }
407 
408  // Create a new service object
409 
410  hService = CreateService(
411  hScManager, // service control manager
412  VFD_DEVICE_BASENAME, // internal service name
413  VFD_DEVICE_BASENAME, // display name
414  SERVICE_ALL_ACCESS, // access mode
415  SERVICE_KERNEL_DRIVER, // service type
416  nStart, // service start type
417  SERVICE_ERROR_NORMAL, // start error sevirity
418  inst_path, // service image file path
419  NULL, // service group
420  NULL, // service tag
421  NULL, // service dependency
422  NULL, // use LocalSystem account
423  NULL // password for the account
424  );
425 
426  if (!hService) {
427  // Failed to create a service object
428  ret = GetLastError();
429 
430  VFDTRACE(0,
431  (FUNC ": CreateService() - %s",
432  SystemMessage(ret)));
433 
434  goto cleanup;
435  }
436 
437 cleanup:
438  // Close the service object handle
439 
440  if (hService) {
441  CloseServiceHandle(hService);
442  }
443 
444  // Close handle to the service control manager.
445 
446  if (hScManager) {
447  CloseServiceHandle(hScManager);
448  }
449 
450  if (ret == ERROR_SUCCESS) {
451  // Broadcast the successful operation
453  }
454 #ifdef VFD_EMBED_DRIVER
455  else {
456  // Delete the restored driver file
457  DeleteFile(system_dir);
458  }
459 #endif // VFD_EMBED_DRIVER
460 
461  return ret;
462 }
463 
464 //
465 // Configure the Virtual Floppy Driver (change the start method)
466 //
467 
469  DWORD nStart)
470 {
471 #undef FUNC
472 #define FUNC "VfdConfigDriver"
473  SC_HANDLE hScManager; // Service Control Manager
474  SC_HANDLE hService; // Service (= Driver)
476 
477  // Connect to the Service Control Manager
478 
479  hScManager = OpenSCManager(NULL, NULL, 0);
480 
481  if (hScManager == NULL) {
482  ret = GetLastError();
483 
484  VFDTRACE(0,
485  (FUNC ": OpenSCManager() - %s",
486  SystemMessage(ret)));
487 
488  return ret;
489  }
490 
491  // Open the VFD driver entry in the service database
492 
493  hService = OpenService(
494  hScManager, // Service control manager
495  VFD_DEVICE_BASENAME, // service name
496  SERVICE_CHANGE_CONFIG); // service access mode
497 
498  if (hService == NULL) {
499  ret = GetLastError();
500 
501  VFDTRACE(0,
502  (FUNC ": OpenService(SERVICE_CHANGE_CONFIG) - %s",
503  SystemMessage(ret)));
504 
505  goto cleanup;
506  }
507 
508  // Change the start method of the VFD driver
509 
510  if (!ChangeServiceConfig(
511  hService,
513  nStart,
515  NULL,
516  NULL,
517  NULL,
518  NULL,
519  NULL,
520  NULL,
521  NULL)) {
522 
523  ret = GetLastError();
524 
525  VFDTRACE(0,
526  (FUNC ": ChangeServiceConfig() - %s",
527  SystemMessage(ret)));
528 
529  goto cleanup;
530  }
531 
532 cleanup:
533  // Close the service object handle
534 
535  if (hService) {
536  CloseServiceHandle(hService);
537  }
538 
539  // Close handle to the service control manager.
540 
541  if (hScManager) {
542  CloseServiceHandle(hScManager);
543  }
544 
545  // Broadcast the successful operation
546 
547  if (ret == ERROR_SUCCESS) {
549  }
550 
551  return ret;
552 }
553 
554 //
555 // Remove the Virtual Floppy Driver entry from the service database
556 //
558 {
559 #undef FUNC
560 #define FUNC "VfdRemoveDriver"
561  SC_HANDLE hScManager; // Service Control Manager
562  SC_HANDLE hService; // Service (= Driver)
565 
566  // Get the current driver path
567 
569 
570  if (ret != ERROR_SUCCESS) {
571  return ret;
572  }
573 
574  // Connect to the Service Control Manager
575 
576  hScManager = OpenSCManager(NULL, NULL, 0);
577 
578  if (hScManager == NULL) {
579  ret = GetLastError();
580 
581  VFDTRACE(0,
582  (FUNC ": OpenSCManager() - %s",
583  SystemMessage(ret)));
584 
585  return ret;
586  }
587 
588  // Open the VFD driver entry in the service database
589 
590  hService = OpenService(
591  hScManager, // Service control manager
592  VFD_DEVICE_BASENAME, // service name
593  DELETE); // service access mode
594 
595  if (hService == NULL) {
596  ret = GetLastError();
597 
598  VFDTRACE(0,
599  (FUNC ": OpenService(DELETE) - %s",
600  SystemMessage(ret)));
601 
602  goto cleanup;
603  }
604 
605  // Remove driver entry from registry
606 
607  if (!DeleteService(hService)) {
608  ret = GetLastError();
609 
610  VFDTRACE(0,
611  (FUNC ": DeleteService() - %s",
612  SystemMessage(ret)));
613 
614  goto cleanup;
615  }
616 
617 cleanup:
618  // Close the service object handle
619 
620  if (hService) {
621  CloseServiceHandle(hService);
622  }
623 
624  // Close handle to the service control manager.
625 
626  if (hScManager) {
627  CloseServiceHandle(hScManager);
628  }
629 
630  // Broadcast the successful operation
631 
632  if (ret == ERROR_SUCCESS) {
634 
635 #ifdef VFD_EMBED_DRIVER
636  // Remove the driver file
638 #endif // VFD_EMBED_DRIVER
639  }
640 
641  return ret;
642 }
643 
644 //
645 // Start the Virtual Floppy Driver
646 //
648  PDWORD pState)
649 {
650 #undef FUNC
651 #define FUNC "VfdStartDriver"
652  SC_HANDLE hScManager; // Service Control Manager
653  SC_HANDLE hService; // Service (= Driver)
656  HCURSOR original;
657  int i;
658 
659  if (pState) {
660  *pState = 0;
661  }
662 
663  // Connect to the Service Control Manager
664 
665  hScManager = OpenSCManager(NULL, NULL, 0);
666 
667  if (hScManager == NULL) {
668  ret = GetLastError();
669 
670  VFDTRACE(0,
671  (FUNC ": OpenSCManager() - %s",
672  SystemMessage(ret)));
673 
674  return ret;
675  }
676 
677  // show an hourglass cursor
678 
679  original = SetCursor(LoadCursor(NULL, IDC_WAIT));
680 
681  // Open the VFD driver entry in the service database
682 
683  hService = OpenService(
684  hScManager, // Service control manager
685  VFD_DEVICE_BASENAME, // service name
687  | SERVICE_QUERY_STATUS); // service access mode
688 
689  if (hService == NULL) {
690  ret = GetLastError();
691 
692  VFDTRACE(0,
693  (FUNC ": OpenService(SERVICE_START) - %s",
694  SystemMessage(ret)));
695 
696  goto cleanup;
697  }
698 
699  // Start the driver
700 
701  if (!StartService(hService, 0, NULL)) {
702  ret = GetLastError();
703 
704  VFDTRACE(0,
705  (FUNC ": StartService() - %s",
706  SystemMessage(ret)));
707 
708  goto cleanup;
709  }
710 
711  // Wait until the driver is properly running
712 
713  i = 0;
714 
715  for (;;) {
716  if (!QueryServiceStatus(hService, &stat)) {
717  ret = GetLastError();
718 
719  VFDTRACE(0,
720  (FUNC ": QueryServiceStatus() - %s",
721  SystemMessage(ret)));
722 
723  break;
724  }
725 
726  if (stat.dwCurrentState == SERVICE_RUNNING || ++i == 5) {
727  break;
728  }
729 
730  Sleep(1000);
731  }
732 
733  if (stat.dwCurrentState == SERVICE_RUNNING) {
734 
735  // Broadcast the successful operation
736 
737  if (ret == ERROR_SUCCESS) {
739  }
740 
741  // broadcast the arrival of VFD drives
742  // otherwise WinXP explorer doesn't recognize the VFD drives
743 
744  for (i = 0; i < VFD_MAXIMUM_DEVICES; i++) {
745  HANDLE hDevice;
746  CHAR letter = 0;
747 
748  hDevice = VfdOpenDevice(i);
749 
750  if (hDevice != INVALID_HANDLE_VALUE) {
751 
752  VfdGetGlobalLink(hDevice, &letter);
753 
754  CloseHandle(hDevice);
755 
756  if (isalpha(letter)) {
759  }
760  }
761  else {
762  VFDTRACE(0,
763  (FUNC ": VfdOpenDevice(%d) - %s",
765  }
766  }
767  }
768  else {
769  // somehow failed to start the driver
770 
772  }
773 
774  if (pState) {
775  *pState = stat.dwCurrentState;
776  }
777 
778 cleanup:
779  // Close the service object handle
780 
781  if (hService) {
782  CloseServiceHandle(hService);
783  }
784 
785  // Close handle to the service control manager.
786 
787  if (hScManager) {
788  CloseServiceHandle(hScManager);
789  }
790 
791  // revert to the original cursor
792 
793  SetCursor(original);
794 
795  return ret;
796 }
797 
798 //
799 // Stop the Virtual Floppy Driver
800 //
802  PDWORD pState)
803 {
804 #undef FUNC
805 #define FUNC "VfdStopDriver"
806  SC_HANDLE hScManager; // Service Control Manager
807  SC_HANDLE hService; // Service (= Driver)
809  CHAR drive_letters[VFD_MAXIMUM_DEVICES];
811  int i;
812  HCURSOR original;
813 
814  if (pState) {
815  *pState = 0;
816  }
817 
818  // Connect to the Service Control Manager
819 
820  hScManager = OpenSCManager(NULL, NULL, 0);
821 
822  if (hScManager == NULL) {
823  ret = GetLastError();
824 
825  VFDTRACE(0,
826  (FUNC ": OpenSCManager() - %s",
827  SystemMessage(ret)));
828 
829  return ret;
830  }
831 
832  // Show the hourglass cursor
833 
834  original = SetCursor(LoadCursor(NULL, IDC_WAIT));
835 
836  // Open the VFD driver entry in the service database
837 
838  hService = OpenService(
839  hScManager, // Service control manager
840  VFD_DEVICE_BASENAME, // service name
842  | SERVICE_QUERY_STATUS); // service access mode
843 
844  if (hService == NULL) {
845  ret = GetLastError();
846 
847  VFDTRACE(0,
848  (FUNC ": OpenService(SERVICE_STOP) - %s",
849  SystemMessage(ret)));
850 
851  goto cleanup;
852  }
853 
854  // Get assigned drive letters
855 
856  for (i = 0; i < VFD_MAXIMUM_DEVICES; i++) {
857  HANDLE hDevice;
858  CHAR letter;
859 
860  hDevice = VfdOpenDevice(i);
861 
862  if (hDevice != INVALID_HANDLE_VALUE) {
863 
864  // remove all session local drive letters
865 
866  while (VfdGetLocalLink(hDevice, &letter) == ERROR_SUCCESS &&
867  isalpha(letter)) {
868  VfdSetLocalLink(hDevice, 0);
869  }
870 
871  // store existing persistent drive letters
872 
873  VfdGetGlobalLink(hDevice, &drive_letters[i]);
874 
875  CloseHandle(hDevice);
876  }
877  else {
878  VFDTRACE(0,
879  (FUNC ": VfdOpenDevice(%d) - %s",
881  }
882  }
883 
884  // Stop the driver
885 
886  if (!ControlService(hService, SERVICE_CONTROL_STOP, &stat)) {
887  ret = GetLastError();
888 
889  VFDTRACE(0,
890  (FUNC ": ControlService(SERVICE_CONTROL_STOP) - %s",
891  SystemMessage(ret)));
892 
893  goto cleanup;
894  }
895 
896  // Wait until the driver is stopped
897 
898  i = 0;
899 
900  while (stat.dwCurrentState != SERVICE_STOPPED && ++i < 5) {
901  Sleep(1000);
902 
903  if (!QueryServiceStatus(hService, &stat)) {
904  ret = GetLastError();
905 
906  VFDTRACE(0,
907  (FUNC ": QueryServiceStatus() - %s",
908  SystemMessage(ret)));
909 
910  break;
911  }
912  }
913 
914  if (stat.dwCurrentState != SERVICE_RUNNING) {
915 
916  // broadcast the removal of persistent drive letters
917 
918  for (i = 0; i < VFD_MAXIMUM_DEVICES; i++) {
919  if (isalpha(drive_letters[i])) {
920  VfdBroadcastLink(drive_letters[i], VFD_LINK_REMOVED);
922  }
923  }
924  }
925 
926  if (pState) {
927  *pState = stat.dwCurrentState;
928  }
929 
930 cleanup:
931  // Close the service object handle
932 
933  if (hService) {
934  CloseServiceHandle(hService);
935  }
936 
937  // Close handle to the service control manager.
938 
939  if (hScManager) {
940  CloseServiceHandle(hScManager);
941  }
942 
943  // Broadcast the successful operation
944 
945  if (ret == ERROR_SUCCESS) {
947  }
948 
949  // revert to the original cursor
950 
951  SetCursor(original);
952 
953  return ret;
954 }
955 
956 //
957 // Get the Virtual Floppy Driver configuration
958 //
960  PSTR sFileName,
961  PDWORD pStart)
962 {
963 #undef FUNC
964 #define FUNC "VfdGetDriverConfig"
965  SC_HANDLE hScManager; // Service Control Manager
966  SC_HANDLE hService; // Service (= Driver)
968  DWORD result;
970 
971  if (sFileName) {
972  ZeroMemory(sFileName, MAX_PATH);
973  }
974 
975  if (pStart) {
976  *pStart = 0;
977  }
978 
979  // Connect to the Service Control Manager
980 
981  hScManager = OpenSCManager(NULL, NULL, 0);
982 
983  if (hScManager == NULL) {
984  ret = GetLastError();
985 
986  VFDTRACE(0,
987  (FUNC ": OpenSCManager() - %s", SystemMessage(ret)));
988 
989  return ret;
990  }
991 
992  // Open the VFD driver entry in the service database
993 
994  hService = OpenService(
995  hScManager, // Service control manager
996  VFD_DEVICE_BASENAME, // service name
997  SERVICE_QUERY_CONFIG); // service access mode
998 
999  if (hService == NULL) {
1000  ret = GetLastError();
1001 
1002  VFDTRACE(0,
1003  (FUNC ": OpenService(SERVICE_QUERY_CONFIG) - %s",
1004  SystemMessage(ret)));
1005 
1006  goto cleanup;
1007  }
1008 
1009  // Get the length of config information
1010 
1011  if (!QueryServiceConfig(hService, NULL, 0, &result)) {
1012  ret = GetLastError();
1013 
1014  if (ret == ERROR_INSUFFICIENT_BUFFER) {
1015  ret = ERROR_SUCCESS;
1016  }
1017  else {
1018  VFDTRACE(0,
1019  (FUNC ": QueryServiceConfig() - %s",
1020  SystemMessage(ret)));
1021 
1022  goto cleanup;
1023  }
1024  }
1025 
1026  // allocate a required buffer
1027 
1029 
1030  if (config == NULL) {
1031  ret = GetLastError();
1032 
1033  VFDTRACE(0,
1034  (FUNC ": LocalAlloc(%lu) - %s\n",
1035  result, SystemMessage(ret)));
1036 
1037  goto cleanup;
1038  }
1039 
1040  // get the config information
1041 
1042  if (!QueryServiceConfig(hService, config, result, &result)) {
1043  ret = GetLastError();
1044 
1045  VFDTRACE(0,
1046  (FUNC ": QueryServiceConfig() - %s",
1047  SystemMessage(ret)));
1048 
1049  goto cleanup;
1050  }
1051 
1052  // copy information to output buffer
1053 
1054  if (sFileName) {
1055  if (strncmp(config->lpBinaryPathName, "\\??\\", 4) == 0) {
1056 
1057  // driver path is an absolute UNC path
1058  strncpy(
1059  sFileName,
1060  config->lpBinaryPathName + 4,
1061  MAX_PATH);
1062  }
1063  else if (config->lpBinaryPathName[0] == '\\' ||
1064  (isalpha(config->lpBinaryPathName[0]) &&
1065  config->lpBinaryPathName[1] == ':')) {
1066 
1067  // driver path is an absolute path
1068  strncpy(sFileName,
1069  config->lpBinaryPathName,
1070  MAX_PATH);
1071  }
1072  else {
1073  // driver path is relative to the SystemRoot
1074 // DWORD len = GetEnvironmentVariable(
1075 // "SystemRoot", sFileName, MAX_PATH);
1076 
1077  DWORD len = GetWindowsDirectory(sFileName, MAX_PATH);
1078 
1079  if (len == 0 || len > MAX_PATH) {
1080  VFDTRACE(0,
1081  (FUNC ": %%SystemRoot%% is empty or too long.\n"));
1082 
1084  goto cleanup;
1085  }
1086 
1087  sprintf((sFileName + len), "\\%s",
1088  config->lpBinaryPathName);
1089  }
1090  }
1091 
1092  if (pStart) {
1093  *pStart = config->dwStartType;
1094  }
1095 
1096 cleanup:
1097  // Free service config buffer
1098 
1099  if (config) {
1100  LocalFree(config);
1101  }
1102 
1103  // Close the service object handle
1104 
1105  if (hService) {
1106  CloseServiceHandle(hService);
1107  }
1108 
1109  // Close handle to the service control manager.
1110 
1111  if (hScManager) {
1112  CloseServiceHandle(hScManager);
1113  }
1114 
1115  return ret;
1116 }
1117 
1118 //
1119 // Get the Virtual Floppy Driver running state
1120 //
1122  PDWORD pState)
1123 {
1124 #undef FUNC
1125 #define FUNC "VfdGetDriverState"
1126  SC_HANDLE hScManager = NULL; // Service Control Manager
1127  SC_HANDLE hService = NULL; // Service (= Driver)
1130 
1131  if (pState) {
1132  *pState = 0;
1133  }
1134 
1135  // Connect to the Service Control Manager
1136 
1137  hScManager = OpenSCManager(NULL, NULL, 0);
1138 
1139  if (hScManager == NULL) {
1140  ret = GetLastError();
1141 
1142  VFDTRACE(0,
1143  (FUNC ": OpenSCManager() - %s",
1144  SystemMessage(ret)));
1145 
1146  return ret;
1147  }
1148 
1149  // Open the VFD driver entry in the service database
1150 
1151  hService = OpenService(
1152  hScManager, // Service control manager
1153  VFD_DEVICE_BASENAME, // service name
1154  SERVICE_QUERY_STATUS); // service access mode
1155 
1156  if (hService == NULL) {
1157 
1158  ret = GetLastError();
1159 
1161 
1162  if (pState) {
1163  *pState = VFD_NOT_INSTALLED;
1164  }
1165 
1166  ret = ERROR_SUCCESS;
1167  }
1168  else {
1169  VFDTRACE(0,
1170  (FUNC ": OpenService(SERVICE_QUERY_STATUS) - %s",
1171  SystemMessage(ret)));
1172  }
1173 
1174  goto cleanup;
1175  }
1176 
1177  // Get current driver status
1178 
1179  ZeroMemory(&status, sizeof(status));
1180 
1181  if (!QueryServiceStatus(hService, &status)) {
1182  ret = GetLastError();
1183 
1184  VFDTRACE(0,
1185  (FUNC ": QueryServiceStatus() - %s",
1186  SystemMessage(ret)));
1187 
1188  goto cleanup;
1189  }
1190 
1191  if (pState) {
1192  *pState = status.dwCurrentState;
1193  }
1194 
1195 cleanup:
1196  // Close the service object handle
1197 
1198  if (hService) {
1199  CloseServiceHandle(hService);
1200  }
1201 
1202  // Close handle to the service control manager.
1203 
1204  if (hScManager) {
1205  CloseServiceHandle(hScManager);
1206  }
1207 
1208  return ret;
1209 }
1210 
1211 //
1212 // open a Virtual Floppy drive without showing the "Insert Floppy"
1213 // dialog when the drive is empty.
1214 //
1216  ULONG nTarget) // either a drive letter or a device number
1217 {
1218 #undef FUNC
1219 #define FUNC "VfdOpenDevice"
1220  CHAR dev_name[20];
1221  UINT err_mode;
1222  HANDLE hDevice;
1223 
1224  // format a device name string
1225 
1226  if (isalpha(nTarget)) {
1227  // nTarget is a drive letter
1228  // \\.<x>:
1229 #ifndef __REACTOS__
1231 #else
1233 #endif
1234  }
1235  else if (isdigit(nTarget)) {
1236  // nTarget is a device number in character
1237  // \\.\VirtualFD<n>
1238  sprintf(dev_name, VFD_DEVICE_TEMPLATE, nTarget - '0');
1239  }
1240  else {
1241  // nTarget is a device number value
1242  // \\.\VirtualFD<n>
1244  }
1245 
1246  // change error mode in order to avoid "Insert Floppy" dialog
1247 
1249 
1250  // open the target drive
1251 
1252  hDevice = CreateFile(
1253  dev_name,
1256  NULL,
1257  OPEN_EXISTING,
1259  NULL);
1260 
1261  // revert to the original error mode
1262 
1263  SetErrorMode(err_mode);
1264 
1265  if (hDevice != INVALID_HANDLE_VALUE) {
1266 
1267  // check if the target is a valid VFD drive
1268 
1269  ULONG version;
1270 
1271  if (VfdGetDriverVersion(hDevice, &version) != ERROR_SUCCESS) {
1272 
1273  // Failed to get the driver version
1274 
1275  CloseHandle(hDevice);
1276  hDevice = INVALID_HANDLE_VALUE;
1277  }
1278  else if ((version & ~0x80000000) !=
1280 
1281  // the driver version mismatch
1282 
1283 // CloseHandle(hDevice);
1284 // hDevice = INVALID_HANDLE_VALUE;
1285 
1287  }
1288  }
1289  else {
1290  VFDTRACE(0,(
1291  "CreateFile(%s) - %s", dev_name,
1293  }
1294 
1295  return hDevice;
1296 }
1297 
1298 //
1299 // Open a Virtual Floppy Image
1300 //
1302  HANDLE hDevice,
1303  PCSTR sFileName,
1304  VFD_DISKTYPE nDiskType,
1305  VFD_MEDIA nMediaType,
1306  VFD_FLAGS nMediaFlags)
1307 {
1308 #undef FUNC
1309 #define FUNC "VfdOpenImage"
1310  PCSTR prefix;
1311  CHAR abspath[MAX_PATH];
1312  DWORD name_len;
1313  DWORD result;
1315 
1316  PVFD_IMAGE_INFO image_info = NULL;
1317  PUCHAR image_buf = NULL;
1318  ULONG image_size;
1320 
1321  //
1322  // Check parameters
1323  //
1324 
1325  if (hDevice == NULL ||
1326  hDevice == INVALID_HANDLE_VALUE) {
1327  return ERROR_INVALID_HANDLE;
1328  }
1329 
1330  if (nMediaType == VFD_MEDIA_NONE ||
1331  nMediaType >= VFD_MEDIA_MAX) {
1332 
1333  VFDTRACE(0,
1334  (FUNC ": Invalid MediaType - %u\n", nMediaType));
1335 
1336  return ERROR_INVALID_PARAMETER;
1337  }
1338 
1339 
1340  if (sFileName && *sFileName) {
1341 
1342  // check file contents and attributes
1343 
1344  HANDLE hFile = CreateFile(sFileName, GENERIC_READ,
1346 
1347  if (hFile == INVALID_HANDLE_VALUE) {
1348  ret = GetLastError();
1349 
1350  VFDTRACE(0,
1351  (FUNC ": CreateFile(%s) - %s",
1352  sFileName, SystemMessage(ret)));
1353 
1354  return ret;
1355  }
1356 
1357  // try extracting image data from zip compressed file
1358 
1359  ExtractZipImage(hFile, &image_buf, &image_size);
1360 
1361  if (image_buf) {
1362 
1364 
1365  // imz file must be opened in RAM mode
1366 
1367  if (nDiskType == VFD_DISKTYPE_FILE) {
1368 
1369  VFDTRACE(0,
1370  (FUNC ": %s is a zip compressed file",
1371  sFileName));
1372 
1373  CloseHandle(hFile);
1375 
1376  goto exit_func;
1377  }
1378  }
1379  else {
1380 
1382 
1383  if (nDiskType == VFD_DISKTYPE_FILE) {
1384 
1385  // direct image file must not be compressed or encrypted
1386 
1388 
1390  ret = GetLastError();
1391 
1392  VFDTRACE(0,
1393  (FUNC ": GetFileInformationByHandle - %s",
1394  SystemMessage(ret)));
1395 
1396  CloseHandle(hFile);
1397 
1398  return ret;
1399  }
1400 
1401  if (info.dwFileAttributes &
1403 
1404  VFDTRACE(0,
1405  (FUNC ": file is compressed/encrypted"));
1406 
1407  CloseHandle(hFile);
1408 
1409  return ERROR_FILE_ENCRYPTED;
1410  }
1411 
1412  image_size = info.nFileSizeLow;
1413  }
1414  else {
1415 
1416  // prepare image data for a file based RAM disk
1417 
1419 
1420  if (image_size == 0 || image_size == INVALID_FILE_SIZE) {
1421  ret = GetLastError();
1422 
1423  VFDTRACE(0,
1424  (FUNC ": GetFileSize - %s",
1425  SystemMessage(ret)));
1426 
1427  CloseHandle(hFile);
1428 
1429  return ret;
1430  }
1431 
1432  image_buf = (PUCHAR)LocalAlloc(LPTR, image_size);
1433 
1434  if (image_buf == NULL) {
1435  ret = GetLastError();
1436 
1437  VFDTRACE(0,
1438  (FUNC ": LocalAlloc - %s",
1439  SystemMessage(ret)));
1440 
1441  CloseHandle(hFile);
1442 
1443  return ret;
1444  }
1445 
1446  if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) != 0) {
1447  ret = GetLastError();
1448 
1449  VFDTRACE(0,
1450  (FUNC ": SetFilePointer - %s",
1451  SystemMessage(ret)));
1452 
1453  CloseHandle(hFile);
1454 
1455  goto exit_func;
1456  }
1457 
1458  if (!ReadFile(hFile, image_buf, image_size, &result, NULL) ||
1459  image_size != result) {
1460 
1461  ret = GetLastError();
1462 
1463  VFDTRACE(0,
1464  (FUNC ": ReadFile - %s",
1465  SystemMessage(ret)));
1466 
1467  CloseHandle(hFile);
1468 
1469  goto exit_func;
1470  }
1471  }
1472  }
1473 
1474  CloseHandle(hFile);
1475 
1476  // Prepare absolute path in the kernel namespace
1477 
1478  if (*sFileName == '\\' && *(sFileName + 1) == '\\') {
1479 
1480  // \\server\share\path\floppy.img
1481 
1482  prefix = "\\??\\UNC";
1483  sFileName++; // drip the first '\'
1484  }
1485  else {
1486 
1487  // local path
1488 
1489  PSTR file_part;
1490 
1491  if (GetFullPathName(sFileName,
1492  sizeof(abspath), abspath, &file_part) == 0) {
1493 
1494  ret = GetLastError();
1495 
1496  VFDTRACE(0,
1497  (FUNC ": GetFullPathName(%s) - %s\n",
1498  sFileName, SystemMessage(ret)));
1499 
1500  goto exit_func;
1501  }
1502 
1503  prefix = "\\??\\";
1504  sFileName = abspath;
1505  }
1506 
1507  name_len = strlen(prefix) + strlen(sFileName);
1508  }
1509  else {
1510 
1511  // filename is not specified -- pure RAM disk
1512 
1513  nDiskType = VFD_DISKTYPE_RAM;
1515 
1516  prefix = NULL;
1517  name_len = 0;
1518 
1519  // prepare a FAT formatted RAM image
1520 
1521  image_size = VfdGetMediaSize(nMediaType);
1522 
1523  image_buf = (PUCHAR)LocalAlloc(LPTR, image_size);
1524 
1525  if (image_buf == NULL) {
1526  ret = GetLastError();
1527 
1528  VFDTRACE(0,
1529  (FUNC ": LocalAlloc - %s",
1530  SystemMessage(ret)));
1531 
1532  return ret;
1533  }
1534 
1536  }
1537 
1538  if (image_size < VfdGetMediaSize(nMediaType)) {
1539 
1540  // image is too small for the specified media type
1541 
1542  VFDTRACE(0,
1543  (FUNC ": Image is too small for the specified media type\n"));
1544 
1546  goto exit_func;
1547  }
1548 
1549  // prepare VFD_IMAGE_INFO structure
1550 
1551  image_info = (PVFD_IMAGE_INFO)LocalAlloc(LPTR,
1552  sizeof(VFD_IMAGE_INFO) + name_len + 1);
1553 
1554  if (image_info == NULL) {
1555  ret = GetLastError();
1556 
1557  VFDTRACE(0,
1558  (FUNC ": LocalAlloc(%lu) - %s\n",
1559  sizeof(VFD_IMAGE_INFO) + name_len + 1,
1560  SystemMessage(ret)));
1561 
1562  goto exit_func;
1563  }
1564 
1565  ZeroMemory(image_info,
1566  sizeof(VFD_IMAGE_INFO) + name_len + 1);
1567 
1568  if (name_len) {
1569  sprintf(image_info->FileName,
1570  "%s%s", prefix, sFileName);
1571  }
1572 
1573  image_info->NameLength = (USHORT)name_len;
1574 
1575  image_info->DiskType = nDiskType;
1576  image_info->MediaType = nMediaType;
1577  image_info->MediaFlags = nMediaFlags;
1578  image_info->FileType = file_type;
1579  image_info->ImageSize = image_size;
1580 
1581  if (nDiskType != VFD_DISKTYPE_FILE) {
1582  // protect flag for a RAM disk is set after
1583  // initializing the image buffer
1584  image_info->MediaFlags &= ~VFD_FLAG_WRITE_PROTECTED;
1585  }
1586 
1587  VFDTRACE(0,
1588  (FUNC ": Opening file \"%s\" (%lu bytes) %s %s %s %s\n",
1589  name_len ? image_info->FileName : "<RAM>",
1590  image_info->ImageSize,
1591  (file_type == VFD_FILETYPE_ZIP) ? "ZIP image" : "RAW image",
1592  VfdMediaTypeName(nMediaType),
1593  (nDiskType == VFD_DISKTYPE_FILE) ? "FILE disk" : "RAM disk",
1594  (nMediaFlags & VFD_FLAG_WRITE_PROTECTED) ? "Protected" : "Writable"));
1595 
1596  // Open the image file / create a ram disk
1597 
1598  if (!DeviceIoControl(
1599  hDevice,
1601  image_info,
1602  sizeof(VFD_IMAGE_INFO) + name_len,
1603  NULL,
1604  0,
1605  &result,
1606  NULL))
1607  {
1608  ret = GetLastError();
1609 
1610  VFDTRACE(0,
1611  (FUNC ": DeviceIoControl(IOCTL_VFD_OPEN_FILE) - %s",
1612  SystemMessage(ret)));
1613 
1614  goto exit_func;
1615  }
1616 
1617  // initialize the RAM disk image
1618 
1619  if (nDiskType != VFD_DISKTYPE_FILE) {
1620 
1622 
1623  if (SetFilePointer(hDevice, 0, NULL, FILE_BEGIN) != 0) {
1624  ret = GetLastError();
1625 
1626  VFDTRACE(0,
1627  (FUNC ": SetFilePointer - %s",
1628  SystemMessage(ret)));
1629 
1630  goto exit_func;
1631  }
1632 
1633  if (!WriteFile(hDevice, image_buf, image_size, &result, NULL) ||
1634  image_size != result) {
1635 
1636  ret = GetLastError();
1637 
1638  VFDTRACE(0,
1639  (FUNC ": WriteFile - %s",
1640  SystemMessage(ret)));
1641 
1642  goto exit_func;
1643  }
1644 
1645  if (nMediaFlags & VFD_FLAG_WRITE_PROTECTED) {
1646  VfdWriteProtect(hDevice, TRUE);
1647  }
1648 
1649  if (!DeviceIoControl(
1650  hDevice,
1652  NULL,
1653  0,
1654  NULL,
1655  0,
1656  &result,
1657  NULL))
1658  {
1659  VFDTRACE(0,
1660  (FUNC ": DeviceIoControl(IOCTL_VFD_RESET_MODIFY) - %s",
1662  }
1663  }
1664 
1665  // Broadcast the successful operation
1666 
1667  if (ret == ERROR_SUCCESS) {
1668  ULONG number;
1669  CHAR root[] = "A:\\";
1670 
1671  if (VfdGetDeviceNumber(hDevice, &number) == ERROR_SUCCESS) {
1673  }
1674 
1675  VfdGetGlobalLink(hDevice, &root[0]);
1676 
1677  if (isalpha(root[0])) {
1679  }
1680 
1681  while (VfdGetLocalLink(hDevice, &root[0]) == ERROR_SUCCESS &&
1682  isalpha(root[0])) {
1684  }
1685  }
1686 
1687 exit_func:
1688  if (image_info) {
1689  LocalFree(image_info);
1690  }
1691 
1692  if (image_buf) {
1693  LocalFree(image_buf);
1694  }
1695 
1696  return ret;
1697 }
1698 
1699 //
1700 // Close the virtual floppy Image
1701 //
1703  HANDLE hDevice,
1704  BOOL bForce)
1705 {
1706 #undef FUNC
1707 #define FUNC "VfdCloseImage"
1708  DWORD result;
1710  int retry = 0;
1711 
1712 lock_retry:
1713  if (!DeviceIoControl(
1714  hDevice,
1716  NULL,
1717  0,
1718  NULL,
1719  0,
1720  &result,
1721  NULL))
1722  {
1723  ret = GetLastError();
1724 
1725  VFDTRACE(0,
1726  (FUNC ": DeviceIoControl(FSCTL_LOCK_VOLUME) - %s",
1727  SystemMessage(ret)));
1728 
1729  if (ret != ERROR_ACCESS_DENIED || retry == 5) {
1730  // error other than access denied or
1731  // operation kept failing for 5 seconds
1732  return ret;
1733  }
1734 
1735  if (!bForce) {
1736  // error is access denied and
1737  // the force flag is not set
1738 
1739  if (retry == 0) {
1740 
1741  // send the MEDIAREMOVED notification to the shell and
1742  // see if the shell releases the target drive
1743 
1744  CHAR root[] = "A:\\";
1745 
1746  VfdGetGlobalLink(hDevice, &root[0]);
1747 
1748  if (isalpha(root[0])) {
1750  }
1751 
1752  while (VfdGetLocalLink(hDevice, &root[0]) == ERROR_SUCCESS &&
1753  isalpha(root[0])) {
1755  }
1756  }
1757 
1758  Sleep(1000);
1759  retry++;
1760 
1761  goto lock_retry;
1762  }
1763  }
1764 
1765  ret = ERROR_SUCCESS;
1766 
1767  if (!DeviceIoControl(
1768  hDevice,
1770  NULL,
1771  0,
1772  NULL,
1773  0,
1774  &result,
1775  NULL))
1776  {
1777  ret = GetLastError();
1778 
1779  VFDTRACE(0,
1780  (FUNC ": DeviceIoControl(FSCTL_DISMOUNT_VOLUME) - %s",
1781  SystemMessage(ret)));
1782 
1783  return ret;
1784  }
1785 
1786  if (!DeviceIoControl(
1787  hDevice,
1789  NULL,
1790  0,
1791  NULL,
1792  0,
1793  &result,
1794  NULL))
1795  {
1796  ret = GetLastError();
1797 
1798  if (ret != ERROR_NOT_READY) {
1799  VFDTRACE(0,
1800  (FUNC ": DeviceIoControl(IOCTL_VFD_CLOSE_FILE) - %s",
1801  SystemMessage(ret)));
1802  }
1803 
1804  return ret;
1805  }
1806 
1807  if (!DeviceIoControl(
1808  hDevice,
1810  NULL,
1811  0,
1812  NULL,
1813  0,
1814  &result,
1815  NULL))
1816  {
1817  // This should not be fatal because the volume is unlocked
1818  // when the handle is closed anyway
1819  VFDTRACE(0,
1820  (FUNC ": DeviceIoControl(FSCTL_UNLOCK_VOLUME) - %s",
1822  }
1823 
1824  // Broadcast the successful operation
1825  if (ret == ERROR_SUCCESS) {
1826  ULONG number;
1827 
1828  if (VfdGetDeviceNumber(hDevice, &number) == ERROR_SUCCESS) {
1830  }
1831  }
1832 
1833  return ret;
1834 }
1835 
1836 //
1837 // Get Virtual Floppy image info
1838 //
1840  HANDLE hDevice,
1841  PSTR sFileName,
1842  PVFD_DISKTYPE pDiskType,
1843  PVFD_MEDIA pMediaType,
1844  PVFD_FLAGS pMediaFlags,
1845  PVFD_FILETYPE pFileType,
1846  PULONG pImageSize)
1847 {
1848 #undef FUNC
1849 #define FUNC "VfdGetImageInfo"
1850  PVFD_IMAGE_INFO image_info;
1851  DWORD result;
1853 
1854  image_info = (PVFD_IMAGE_INFO)LocalAlloc(
1855  LPTR, sizeof(VFD_IMAGE_INFO) + MAX_PATH);
1856 
1857  if (image_info == NULL) {
1858  ret = GetLastError();
1859 
1860  VFDTRACE(0,
1861  (FUNC ": LocalAlloc(%lu) - %s\n",
1862  sizeof(VFD_IMAGE_INFO) + MAX_PATH, SystemMessage(ret)));
1863 
1864  return ret;
1865  }
1866 
1867  ZeroMemory(image_info, sizeof(VFD_IMAGE_INFO) + MAX_PATH);
1868 
1869  // Query file information
1870 
1871  if (!DeviceIoControl(
1872  hDevice,
1874  NULL,
1875  0,
1876  image_info,
1877  sizeof(VFD_IMAGE_INFO) + MAX_PATH,
1878  &result,
1879  NULL))
1880  {
1881  ret = GetLastError();
1882 
1883  if (ret != ERROR_MORE_DATA) {
1884  VFDTRACE(0,
1885  (FUNC ": DeviceIoControl(IOCTL_VFD_QUERY_FILE) - %s",
1886  SystemMessage(ret)));
1887 
1888  goto cleanup;
1889  }
1890  }
1891 
1892  // copy obtained information to output buffer
1893 
1894  if (sFileName) {
1895 
1896  // if filename is too long, clip it
1897 
1898  if (image_info->NameLength >= MAX_PATH) {
1899  image_info->NameLength = MAX_PATH - 1;
1900  }
1901 
1902  // ensure the name is properly terminated
1903 
1904  image_info->FileName[image_info->NameLength] = '\0';
1905 
1906  if (strncmp(image_info->FileName, "\\??\\UNC", 7) == 0) {
1907  *sFileName = '\\';
1908  strcpy(sFileName + 1, image_info->FileName + 7);
1909  }
1910  else if (strncmp(image_info->FileName, "\\??\\", 4) == 0) {
1911  strcpy(sFileName, image_info->FileName + 4);
1912  }
1913  else {
1914  strcpy(sFileName, image_info->FileName);
1915  }
1916  }
1917 
1918  if (pDiskType) {
1919  *pDiskType = image_info->DiskType;
1920  }
1921 
1922  if (pMediaType) {
1923  *pMediaType = image_info->MediaType;
1924  }
1925 
1926  if (pMediaFlags) {
1927  *pMediaFlags = image_info->MediaFlags;
1928  }
1929 
1930  if (pFileType) {
1931  *pFileType = image_info->FileType;
1932  }
1933 
1934  if (pImageSize) {
1935  *pImageSize = image_info->ImageSize;
1936  }
1937 
1938 cleanup:
1939  if (image_info) {
1940  LocalFree(image_info);
1941  }
1942 
1943  return ret;
1944 }
1945 
1946 //
1947 // Get current media state (opened / write protected)
1948 //
1950  HANDLE hDevice)
1951 {
1952 #undef FUNC
1953 #define FUNC "VfdGetMediaState"
1954  DWORD result;
1956 
1957  // Query file information
1958 
1959  if (!DeviceIoControl(
1960  hDevice,
1962  NULL,
1963  0,
1964  NULL,
1965  0,
1966  &result,
1967  NULL))
1968  {
1969  ret = GetLastError();
1970 
1971  if (ret != ERROR_NOT_READY) {
1972  VFDTRACE(0,
1973  (FUNC ": DeviceIoControl(IOCTL_DISK_IS_WRITABLE) - %s",
1974  SystemMessage(ret)));
1975  }
1976  }
1977 
1978  return ret;
1979 }
1980 
1981 //
1982 // Set or Delete a global drive letter
1983 //
1985  HANDLE hDevice,
1986  CHAR cLetter)
1987 {
1988 #undef FUNC
1989 #define FUNC "VfdSetGlobalLink"
1990  CHAR letter;
1991  ULONG number;
1992  DWORD result;
1993  DWORD ret;
1994 
1995  if (isalpha(cLetter)) {
1996 
1997  // make sure the drive does not have a drive letter
1998 
1999  letter = 0;
2000 
2001  VfdGetGlobalLink(hDevice, &letter);
2002 
2003  if (isalpha(letter)) {
2004  VFDTRACE(0,
2005  (FUNC ": Drive already has a drive letter %c\n", letter));
2006  return ERROR_ALREADY_ASSIGNED;
2007  }
2008 
2009  VfdGetLocalLink(hDevice, &letter);
2010 
2011  if (isalpha(letter)) {
2012  VFDTRACE(0,
2013  (FUNC ": Drive already has a drive letter %c\n", letter));
2014  return ERROR_ALREADY_ASSIGNED;
2015  }
2016 
2017  // make sure drive letter is not in use
2018 
2019  cLetter = (CHAR)toupper(cLetter);
2020 
2021  if (GetLogicalDrives() & (1 << (cLetter - 'A'))) {
2022  VFDTRACE(0,
2023  (FUNC ": Drive letter %c already used\n", cLetter));
2024  return ERROR_ALREADY_ASSIGNED;
2025  }
2026 
2027  // Assign a new drive letter
2028 
2029  if (!DeviceIoControl(
2030  hDevice,
2032  &cLetter,
2033  sizeof(cLetter),
2034  NULL,
2035  0,
2036  &result,
2037  NULL))
2038  {
2039  ret = GetLastError();
2040 
2041  VFDTRACE(0,
2042  (FUNC ": DeviceIoControl(IOCTL_VFD_SET_LINK) - %s",
2043  SystemMessage(ret)));
2044 
2045  return ret;
2046  }
2047 
2048  // broadcast system message
2049 
2051 
2052  // broadcast VFD message
2053 
2054  if (VfdGetDeviceNumber(hDevice, &number) == ERROR_SUCCESS) {
2056  }
2057 
2058  return ERROR_SUCCESS;
2059  }
2060  else if (!cLetter) {
2061 
2062  // make sure the drive has a global drive letter
2063 
2064  letter = 0;
2065 
2066  VfdGetGlobalLink(hDevice, &letter);
2067 
2068  if (!isalpha(letter)) {
2069  VFDTRACE(0,
2070  (FUNC ": Drive does not have a drive letter\n"));
2071  return ERROR_INVALID_FUNCTION;
2072  }
2073 
2074  // Remove drive letters
2075 
2076  if (!DeviceIoControl(
2077  hDevice,
2079  &cLetter,
2080  sizeof(cLetter),
2081  NULL,
2082  0,
2083  &result,
2084  NULL))
2085  {
2086  ret = GetLastError();
2087 
2088  VFDTRACE(0,
2089  (FUNC ": DeviceIoControl(IOCTL_VFD_SET_LINK) - %s",
2090  SystemMessage(ret)));
2091 
2092  return ret;
2093  }
2094 
2095  // broadcast system message
2096 
2098 
2099  // broadcast VFD message
2100  if (VfdGetDeviceNumber(hDevice, &number) == ERROR_SUCCESS) {
2102  }
2103 
2104  return ERROR_SUCCESS;
2105  }
2106  else {
2107  return ERROR_INVALID_PARAMETER;
2108  }
2109 }
2110 
2111 //
2112 // Get a global drive letter
2113 //
2115  HANDLE hDevice,
2116  PCHAR pLetter)
2117 {
2118 #undef FUNC
2119 #define FUNC "VfdGetGlobalLinks"
2120  DWORD result;
2121  DWORD ret;
2122 
2123  if (!pLetter) {
2124  return ERROR_INVALID_PARAMETER;
2125  }
2126 
2127  *pLetter = 0;
2128 
2129  if (!DeviceIoControl(
2130  hDevice,
2132  NULL,
2133  0,
2134  pLetter,
2135  sizeof(*pLetter),
2136  &result,
2137  NULL))
2138  {
2139  ret = GetLastError();
2140 
2141  VFDTRACE(0,
2142  (FUNC ": DeviceIoControl(IOCTL_VFD_QUERY_LINK) - %s",
2143  SystemMessage(ret)));
2144 
2145  return ret;
2146  }
2147 
2148  return ERROR_SUCCESS;
2149 }
2150 
2151 //
2152 // Set or remove a local drive letter
2153 //
2155  HANDLE hDevice,
2156  CHAR cLetter)
2157 {
2158 #undef FUNC
2159 #define FUNC "VfdSetLocalLink"
2160  CHAR letter;
2161  CHAR dos_name[] = "A:";
2163  ULONG number;
2164  DWORD ret;
2165 
2166  if (isalpha(cLetter)) {
2167 
2168  // make sure the drive does not have a drive letter
2169 
2170  letter = 0;
2171 
2172  VfdGetGlobalLink(hDevice, &letter);
2173 
2174  if (isalpha(letter)) {
2175  VFDTRACE(0,
2176  (FUNC ": Drive already has a drive letter %c\n", letter));
2177  return ERROR_ALREADY_ASSIGNED;
2178  }
2179 
2180  VfdGetLocalLink(hDevice, &letter);
2181 
2182  if (isalpha(letter)) {
2183  VFDTRACE(0,
2184  (FUNC ": Drive already has a drive letter %c\n", letter));
2185  return ERROR_ALREADY_ASSIGNED;
2186  }
2187 
2188  // make sure drive letters are not in use
2189 
2190  cLetter = (CHAR)toupper(cLetter);
2191 
2192  if (GetLogicalDrives() & (1 << (cLetter - 'A'))) {
2193  VFDTRACE(0,
2194  (FUNC ": Drive letter already used\n"));
2195 
2196  return ERROR_ALREADY_ASSIGNED;
2197  }
2198 
2199  // get VFD device name
2200 
2201  ret = VfdGetDeviceName(hDevice, dev_name, sizeof(dev_name));
2202 
2203  if (ret != ERROR_SUCCESS) {
2204  return ret;
2205  }
2206 
2207  // assign a drive letter
2208 
2209  dos_name[0] = cLetter;
2210 
2211  if (!DefineDosDevice(DDD_RAW_TARGET_PATH, dos_name, dev_name)) {
2212  ret = GetLastError();
2213 
2214  VFDTRACE(0,
2215  (FUNC ": DefineDosDevice(%s,%s) - %s",
2216  dos_name, dev_name, SystemMessage(ret)));
2217  }
2218 
2219  if (ret == ERROR_SUCCESS) {
2220  // broadcast VFD message
2221 
2222  if (VfdGetDeviceNumber(hDevice, &number) == ERROR_SUCCESS) {
2224  }
2225  }
2226 
2227  return ret;
2228  }
2229  else if (!cLetter) {
2230 
2231  // make sure the drive has a local drive letter
2232 
2233  letter = 0;
2234 
2235  VfdGetLocalLink(hDevice, &letter);
2236 
2237  if (!isalpha(letter)) {
2238  VFDTRACE(0,
2239  (FUNC ": Drive letter is not assigned to this drive\n"));
2240  return ERROR_INVALID_FUNCTION;
2241  }
2242 
2243  // get VFD device name
2244 
2245  ret = VfdGetDeviceName(hDevice, dev_name, sizeof(dev_name));
2246 
2247  if (ret != ERROR_SUCCESS) {
2248  return ret;
2249  }
2250 
2251  // remove drive letters
2252 #define DDD_FLAGS (DDD_REMOVE_DEFINITION | DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE)
2253 
2254  dos_name[0] = (CHAR)toupper(letter);
2255 
2256  if (!DefineDosDevice(DDD_FLAGS, dos_name, dev_name)) {
2257  ret = GetLastError();
2258 
2259  VFDTRACE(0,
2260  (FUNC ": DefineDosDevice(%s,%s) - %s",
2261  dos_name, dev_name, SystemMessage(ret)));
2262  }
2263 
2264  if (ret == ERROR_SUCCESS) {
2265  // broadcast VFD message
2266  if (VfdGetDeviceNumber(hDevice, &number) == ERROR_SUCCESS) {
2268  }
2269  }
2270 
2271  return ret;
2272  }
2273  else {
2274  return ERROR_INVALID_PARAMETER;
2275  }
2276 }
2277 
2278 //
2279 // Get local drive letters
2280 //
2282  HANDLE hDevice,
2283  PCHAR pLetter)
2284 {
2285 #undef FUNC
2286 #define FUNC "VfdGetLocalLinks"
2287  CHAR global;
2288  ULONG logical;
2289  CHAR dos_name[] = "A:";
2291  CHAR dos_target[MAX_PATH * 2];
2292  DWORD ret;
2293 
2294  if (!pLetter) {
2295  return ERROR_INVALID_PARAMETER;
2296  }
2297 
2298  // Get the VFD device name
2299 
2300  ret = VfdGetDeviceName(hDevice, dev_name, sizeof(dev_name));
2301 
2302  if (ret != ERROR_SUCCESS) {
2303  return ret;
2304  }
2305 
2306  // Get global drive letter
2307 
2308  ret = VfdGetGlobalLink(hDevice, &global);
2309 
2310  if (ret != ERROR_SUCCESS) {
2311  return ret;
2312  }
2313 
2314  // Get logical drives
2315 
2316  logical = GetLogicalDrives();
2317 
2318  // exclude the global drive letter
2319 
2320  if (isalpha(global)) {
2321  logical &= ~(1 << (toupper(global) - 'A'));
2322  }
2323 
2324  // start searching from the next drive letter
2325 
2326  if (isalpha(*pLetter)) {
2327  dos_name[0] = (CHAR)(toupper(*pLetter) + 1);
2328  logical >>= (dos_name[0] - 'A');
2329  }
2330 
2331  // Check dos device targets
2332 
2333  *pLetter = '\0';
2334 
2335  while (logical) {
2336  if (logical & 0x01) {
2337  if (QueryDosDevice(dos_name, dos_target, sizeof(dos_target))) {
2338  if (_stricmp(dos_target, dev_name) == 0) {
2339  *pLetter = dos_name[0];
2340  break;
2341  }
2342  }
2343  else {
2344  VFDTRACE(0,
2345  (FUNC ": QueryDosDevice(%s) - %s",
2346  dos_name, SystemMessage(GetLastError())));
2347  }
2348  }
2349  logical >>= 1;
2350  dos_name[0]++;
2351  }
2352 
2353  return ERROR_SUCCESS;
2354 }
2355 
2356 //
2357 // Get the Virtual Floppy device number
2358 //
2360  HANDLE hDevice,
2361  PULONG pNumber)
2362 {
2363 #undef FUNC
2364 #define FUNC "VfdGetDeviceNumber"
2365  DWORD result;
2367 
2368  if (!pNumber) {
2369  return ERROR_INVALID_PARAMETER;
2370  }
2371 
2372  *pNumber = 0;
2373 
2374  if (!DeviceIoControl(
2375  hDevice,
2377  NULL,
2378  0,
2379  pNumber,
2380  sizeof(ULONG),
2381  &result,
2382  NULL))
2383  {
2384  ret = GetLastError();
2385 
2386  VFDTRACE(0,
2387  (FUNC ": DeviceIoControl(IOCTL_VFD_QUERY_NUMBER) - %s",
2388  SystemMessage(ret)));
2389  }
2390 
2391  return ret;
2392 }
2393 
2394 // Get the Virtual Floppy device name
2395 
2397  HANDLE hDevice,
2398  PCHAR pName,
2399  ULONG nLength)
2400 {
2401 #undef FUNC
2402 #define FUNC "VfdGetDeviceName"
2403  DWORD result;
2404  WCHAR wname[MAX_PATH];
2406 
2407  if (!pName || !nLength) {
2408  return ERROR_INVALID_PARAMETER;
2409  }
2410 
2412 
2413  if (!DeviceIoControl(
2414  hDevice,
2416  NULL,
2417  0,
2418  wname,
2419  sizeof(wname),
2420  &result,
2421  NULL))
2422  {
2423  ret = GetLastError();
2424 
2425  VFDTRACE(0,
2426  (FUNC ": DeviceIoControl(IOCTL_VFD_QUERY_NUMBER) - %s",
2427  SystemMessage(ret)));
2428  }
2429 
2430  if (!WideCharToMultiByte(CP_OEMCP, 0, &wname[1],
2431  wname[0] / sizeof(WCHAR), pName, nLength, NULL, NULL)) {
2432 
2433  ret = GetLastError();
2434 
2435  VFDTRACE(0,
2436  (FUNC ": WideCharToMultiByte - %s",
2437  SystemMessage(ret)));
2438  }
2439 
2440  return ret;
2441 }
2442 
2443 //
2444 // Get Virtual Floppy driver version
2445 //
2447  HANDLE hDevice,
2448  PULONG pVersion)
2449 {
2450 #undef FUNC
2451 #define FUNC "VfdGetDriverVersion"
2452  DWORD result;
2454 
2455  if (!pVersion) {
2456  return ERROR_INVALID_PARAMETER;
2457  }
2458 
2459  *pVersion = '\0';
2460 
2461  if (!DeviceIoControl(
2462  hDevice,
2464  NULL,
2465  0,
2466  pVersion,
2467  sizeof(ULONG),
2468  &result,
2469  NULL))
2470  {
2471  ret = GetLastError();
2472 
2473  VFDTRACE(0,
2474  (FUNC ": DeviceIoControl(IOCTL_VFD_QUERY_VERSION) - %s",
2475  SystemMessage(ret)));
2476  }
2477 
2478  return ret;
2479 }
2480 
2481 //
2482 // Change the write protect state of the media
2483 //
2485  HANDLE hDevice,
2486  BOOL bProtect)
2487 {
2488 #undef FUNC
2489 #define FUNC "VfdWriteProtect"
2490  DWORD result;
2492 
2493  if (!DeviceIoControl(
2494  hDevice,
2496  NULL,
2497  0,
2498  NULL,
2499  0,
2500  &result,
2501  NULL))
2502  {
2503  ret = GetLastError();
2504 
2505  VFDTRACE(0,
2506  (FUNC ": DeviceIoControl(IOCTL_VFD_SET_PROTECT) - %s",
2507  SystemMessage(ret)));
2508  }
2509 
2510  if (ret == ERROR_SUCCESS) {
2511  ULONG number;
2512 
2513  if (VfdGetDeviceNumber(hDevice, &number) == ERROR_SUCCESS) {
2515  }
2516  }
2517 
2518  return ret;
2519 }
2520 
2521 // Format the current media with FAT12
2522 
2524  HANDLE hDevice)
2525 {
2526 #undef FUNC
2527 #define FUNC "VfdFormatMedia"
2528  DWORD result;
2530  PUCHAR buf = NULL;
2532 
2533  // Get the media size
2534 
2535  if (!DeviceIoControl(
2536  hDevice,
2538  NULL,
2539  0,
2540  &length,
2541  sizeof(length),
2542  &result,
2543  NULL))
2544  {
2545  ret = GetLastError();
2546 
2547  VFDTRACE(0,
2548  (FUNC ": DeviceIoControl(IOCTL_DISK_GET_LENGTH_INFO) - %s",
2549  SystemMessage(ret)));
2550 
2551  goto exit_func;
2552  }
2553 
2554  // Prepare a formatted image buffer
2555 
2556  buf = (PUCHAR)LocalAlloc(LPTR, length.Length.LowPart);
2557 
2558  if (buf == NULL) {
2559  ret = GetLastError();
2560 
2561  VFDTRACE(0,
2562  (FUNC ": LocalAlloc - %s",
2563  SystemMessage(ret)));
2564 
2565  goto exit_func;
2566  }
2567 
2568  // format the buffer
2569 
2571  VFD_BYTE_TO_SECTOR(length.Length.LowPart));
2572 
2573  if (ret != ERROR_SUCCESS) {
2574  goto exit_func;
2575  }
2576 
2577  // seek the top of the media
2578 
2579  if (SetFilePointer(hDevice, 0, NULL, FILE_BEGIN) != 0) {
2580  ret = GetLastError();
2581 
2582  VFDTRACE(0,
2583  (FUNC ": SetFilePointer - %s",
2584  SystemMessage(ret)));
2585 
2586  goto exit_func;
2587  }
2588 
2589  // write the image into the media
2590 
2591  if (!WriteFile(hDevice, buf, length.Length.LowPart, &result, NULL) ||
2592  result != length.Length.LowPart) {
2593  ret = GetLastError();
2594 
2595  VFDTRACE(0,
2596  (FUNC ": WriteFile - %s",
2597  SystemMessage(ret)));
2598 
2599  goto exit_func;
2600  }
2601 
2602 exit_func:
2603  // unlock the target volume
2604  if (!DeviceIoControl(
2605  hDevice,
2607  NULL,
2608  0,
2609  NULL,
2610  0,
2611  &result,
2612  NULL))
2613  {
2614  VFDTRACE(0,
2615  (FUNC ": DeviceIoControl(FSCTL_UNLOCK_VOLUME) - %s",
2617  }
2618 
2619  // release the format image buffer
2620  if (buf) {
2621  LocalFree(buf);
2622  }
2623 
2624  return ret;
2625 }
2626 
2627 // Dismount the volume (should be called before Save, Format)
2628 
2630  HANDLE hDevice,
2631  BOOL bForce)
2632 {
2633 #undef FUNC
2634 #define FUNC "VfdDismountVolume"
2635  DWORD result;
2637 
2638  // Lock the target volume
2639 
2640  if (!DeviceIoControl(
2641  hDevice,
2643  NULL,
2644  0,
2645  NULL,
2646  0,
2647  &result,
2648  NULL))
2649  {
2650  ret = GetLastError();
2651 
2652  VFDTRACE(0,
2653  (FUNC ": DeviceIoControl(FSCTL_LOCK_VOLUME) - %s",
2654  SystemMessage(ret)));
2655 
2656  if (ret != ERROR_ACCESS_DENIED || !bForce) {
2657  return ret;
2658  }
2659  }
2660 
2661  // Dismount the target volume
2662 
2663  if (!DeviceIoControl(
2664  hDevice,
2666  NULL,
2667  0,
2668  NULL,
2669  0,
2670  &result,
2671  NULL))
2672  {
2673  ret = GetLastError();
2674 
2675  VFDTRACE(0,
2676  (FUNC ": DeviceIoControl(FSCTL_DISMOUNT_VOLUME) - %s",
2677  SystemMessage(ret)));
2678  }
2679 
2680  return ret;
2681 }
2682 
2683 // Save the current image into a file
2684 
2686  HANDLE hDevice,
2687  PCSTR sFileName,
2688  BOOL bOverWrite,
2689  BOOL bTruncate)
2690 {
2691 #undef FUNC
2692 #define FUNC "VfdSaveImage"
2694  DWORD result;
2696  PUCHAR buf = NULL;
2698 
2699 
2700  ret = ERROR_SUCCESS;
2701 
2702  // Get the media size
2703 
2704  if (!DeviceIoControl(
2705  hDevice,
2707  NULL,
2708  0,
2709  &length,
2710  sizeof(length),
2711  &result,
2712  NULL))
2713  {
2714  ret = GetLastError();
2715 
2716  VFDTRACE(0,
2717  (FUNC ": DeviceIoControl(IOCTL_DISK_GET_LENGTH_INFO) - %s",
2718  SystemMessage(ret)));
2719 
2720  goto exit_func;
2721  }
2722 
2723  // Prepare an intermediate image buffer
2724 
2725  buf = (PUCHAR)LocalAlloc(LPTR, length.Length.LowPart);
2726 
2727  if (buf == NULL) {
2728  ret = GetLastError();
2729 
2730  VFDTRACE(0,
2731  (FUNC ": LocalAlloc - %s",
2732  SystemMessage(ret)));
2733 
2734  goto exit_func;
2735  }
2736 
2737  // seek the top of the media
2738 
2739  if (SetFilePointer(hDevice, 0, NULL, FILE_BEGIN) != 0) {
2740  ret = GetLastError();
2741 
2742  VFDTRACE(0,
2743  (FUNC ": SetFilePointer - %s",
2744  SystemMessage(ret)));
2745 
2746  goto exit_func;
2747  }
2748 
2749  // read the image data
2750 
2751  if (!ReadFile(hDevice, buf, length.Length.LowPart, &result, NULL) ||
2752  result != length.Length.LowPart) {
2753  ret = GetLastError();
2754 
2755  VFDTRACE(0,
2756  (FUNC ": ReadFile - %s",
2757  SystemMessage(ret)));
2758 
2759  goto exit_func;
2760  }
2761 
2762  // open the destination file
2763 
2764  hFile = CreateFile(sFileName, GENERIC_WRITE, 0, NULL,
2765  bOverWrite ? OPEN_ALWAYS : CREATE_NEW, 0, NULL);
2766 
2767  if (hFile == INVALID_HANDLE_VALUE) {
2768  ret = GetLastError();
2769 
2770  VFDTRACE(0,
2771  (FUNC ": CreateFile - %s",
2772  SystemMessage(ret)));
2773 
2774  goto exit_func;
2775  }
2776 
2777  // seek the top of the file
2778 
2779  if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) != 0) {
2780  ret = GetLastError();
2781 
2782  VFDTRACE(0,
2783  (FUNC ": SetFilePointer - %s",
2784  SystemMessage(ret)));
2785 
2786  goto exit_func;
2787  }
2788 
2789  // write the image data
2790 
2791  if (!WriteFile(hFile, buf, length.Length.LowPart, &result, NULL) ||
2792  result != length.Length.LowPart) {
2793  ret = GetLastError();
2794 
2795  VFDTRACE(0,
2796  (FUNC ": WriteFile - %s",
2797  SystemMessage(ret)));
2798 
2799  goto exit_func;
2800  }
2801 
2802  // truncate the target file
2803 
2804  if (bTruncate && !SetEndOfFile(hFile)) {
2805  ret = GetLastError();
2806 
2807  VFDTRACE(0,
2808  (FUNC ": SetEndOfFile - %s",
2809  SystemMessage(ret)));
2810 
2811  goto exit_func;
2812  }
2813 
2814  // reset the media modified flag
2815 
2816  if (!DeviceIoControl(
2817  hDevice,
2819  NULL,
2820  0,
2821  NULL,
2822  0,
2823  &result,
2824  NULL))
2825  {
2826  VFDTRACE(0,
2827  (FUNC ": DeviceIoControl(IOCTL_VFD_RESET_MODIFY) - %s",
2829  }
2830 
2831 exit_func:
2832  // unlock the target volume
2833 
2834  if (!DeviceIoControl(
2835  hDevice,
2837  NULL,
2838  0,
2839  NULL,
2840  0,
2841  &result,
2842  NULL))
2843  {
2844  VFDTRACE(0,
2845  (FUNC ": DeviceIoControl(FSCTL_UNLOCK_VOLUME) - %s",
2847  }
2848 
2849  // release the format image buffer
2850 
2851  if (buf) {
2852  LocalFree(buf);
2853  }
2854 
2855  // close the image file
2856 
2857  if (hFile != INVALID_HANDLE_VALUE) {
2858  CloseHandle(hFile);
2859  }
2860 
2861  return ret;
2862 }
2863 
2864 //
2865 // Check if specified file is valid VFD driver
2866 //
2868  PCSTR sFileName,
2869  PULONG pFileVersion)
2870 {
2871 #undef FUNC
2872 #define FUNC "VfdCheckDriverFile"
2873  DWORD result;
2874  DWORD dummy;
2875  PVOID info;
2876  VS_FIXEDFILEINFO *fixedinfo;
2878  PSTR str;
2879 
2880  // Check parameter
2881 
2882  if (!sFileName || !*sFileName) {
2883  return ERROR_INVALID_PARAMETER;
2884  }
2885 
2886  if (pFileVersion) {
2887  *pFileVersion = 0;
2888  }
2889 
2890  // check file existence
2891 
2892  if (GetFileAttributes(sFileName) == INVALID_FILE_ATTRIBUTES) {
2893  ret = GetLastError();
2894 
2895  VFDTRACE(0,
2896  (FUNC ": GetFileAttributes - %s\n",
2897  SystemMessage(ret)));
2898 
2899  return ret;
2900  }
2901 
2902  // check file version
2903 
2904  result = GetFileVersionInfoSize((PSTR)sFileName, &dummy);
2905 
2906  if (result == 0) {
2907  VFDTRACE(0,
2908  (FUNC ": GetFileVersionInfoSize == 0\n"));
2909 
2910  return ERROR_BAD_DRIVER;
2911  }
2912 
2913  info = LocalAlloc(LPTR, result);
2914 
2915  if (info == NULL) {
2916  ret = GetLastError();
2917 
2918  VFDTRACE(0,
2919  (FUNC ": LocalAlloc(%lu) - %s\n",
2920  result, SystemMessage(ret)));
2921 
2922  return ret;
2923  }
2924 
2925  if (!GetFileVersionInfo((PSTR)sFileName, 0, result, info)) {
2926  ret = GetLastError();
2927 
2928  VFDTRACE(0,
2929  (FUNC ": GetFileVersionInfo - %s", SystemMessage(ret)));
2930 
2931  goto cleanup;
2932  }
2933 
2934  result = sizeof(fixedinfo);
2935 
2936  if (!VerQueryValue(info, "\\", (PVOID *)&fixedinfo, (PUINT)&result)) {
2937  ret = GetLastError();
2938 
2939  VFDTRACE(0,
2940  (FUNC ": VerQueryValue(\"\\\") - %s", SystemMessage(ret)));
2941 
2942  goto cleanup;
2943  }
2944 
2945  if (fixedinfo->dwFileOS != VOS_NT_WINDOWS32 ||
2946  fixedinfo->dwFileType != VFT_DRV ||
2947  fixedinfo->dwFileSubtype != VFT2_DRV_SYSTEM) {
2948 
2949  VFDTRACE(0,
2950  (FUNC ": Invalid file type flags\n"));
2951 
2953 
2954  goto cleanup;
2955  }
2956 
2957  if (pFileVersion) {
2958  *pFileVersion = fixedinfo->dwFileVersionMS;
2959 
2960  if (fixedinfo->dwFileFlags & VS_FF_DEBUG) {
2961  *pFileVersion |= 0x80000000;
2962  }
2963  }
2964 
2965  if (!VerQueryValue(info,
2966  "\\StringFileInfo\\" VFD_VERSIONINFO_LANG "\\OriginalFileName",
2967  (PVOID *)&str, (PUINT)&result)) {
2968  ret = GetLastError();
2969 
2970  VFDTRACE(0,
2971  (FUNC ": VerQueryValue(\"OriginalFileName\") - %s",
2972  SystemMessage(ret)));
2973 
2974  goto cleanup;
2975  }
2976 
2977  if (strcmp(str, VFD_DRIVER_FILENAME)) {
2978  VFDTRACE(0,
2979  (FUNC ": Invalid original file name\n"));
2980 
2982 
2983  goto cleanup;
2984  }
2985 
2986  if (fixedinfo->dwFileVersionMS != MAKELONG(VFD_DRIVER_MINOR, VFD_DRIVER_MAJOR) ||
2987  fixedinfo->dwProductVersionMS != MAKELONG(VFD_PRODUCT_MINOR, VFD_PRODUCT_MAJOR)) {
2988 
2989  VFDTRACE(0,
2990  (FUNC ": Invalid version values - file:%08x, prod: %08x\n",
2991  fixedinfo->dwFileVersionMS, fixedinfo->dwProductVersionMS));
2992 
2994 
2995  goto cleanup;
2996  }
2997 
2998  // Ensure that the driver binary is located on a local drive
2999  // because device driver cannot be started on network drives.
3000 
3001  if (*sFileName == '\\' && *(sFileName + 1) == '\\') {
3002  // full path is a UNC path -- \\server\dir\...
3003 
3004  VFDTRACE(0,
3005  (FUNC ": Driver is located on a network drive\n"));
3006 
3008  }
3009  else {
3010  // ensure that the drive letter is not a network drive
3011 
3012  CHAR root[] = " :\\";
3013 
3014  root[0] = *sFileName;
3015 
3016  if (GetDriveType(root) == DRIVE_REMOTE) {
3017  // the drive is a network drive
3018 
3019  VFDTRACE(0,
3020  (FUNC ": Driver is located on a network drive\n"));
3021 
3023  }
3024  }
3025 
3026 cleanup:
3027  LocalFree(info);
3028 
3029  return ret;
3030 }
3031 
3032 //
3033 // check an image file
3034 //
3036  PCSTR sFileName,
3037  PDWORD pAttributes,
3038  PVFD_FILETYPE pFileType,
3039  PULONG pImageSize)
3040 {
3041 #undef FUNC
3042 #define FUNC "VfdCheckImageFile"
3043  HANDLE hFile;
3045 
3046  if (!sFileName || !*sFileName || !pAttributes || !pImageSize || !pFileType) {
3047  return ERROR_INVALID_PARAMETER;
3048  }
3049 
3050  // get file attributes
3051 
3052  *pAttributes = GetFileAttributes(sFileName);
3053 
3054  if (*pAttributes == INVALID_FILE_ATTRIBUTES) {
3055  ret = GetLastError();
3056 
3057  if (ret != ERROR_FILE_NOT_FOUND) {
3058  VFDTRACE(0,
3059  (FUNC ": GetFileAttributes(%s) - %s\n",
3060  sFileName, SystemMessage(ret)));
3061  }
3062 
3063  return ret;
3064  }
3065 
3066  // Open the target file
3067 
3068  hFile = CreateFile(sFileName, GENERIC_READ | GENERIC_WRITE,
3069  0, NULL, OPEN_EXISTING, 0, NULL);
3070 
3071  if (hFile == INVALID_HANDLE_VALUE) {
3072 
3073  // failed to open
3074 
3075  ret = GetLastError();
3076 
3077  if (ret != ERROR_ACCESS_DENIED) {
3078  VFDTRACE(0,
3079  (FUNC ": CreateFile(%s) - %s\n",
3080  sFileName, SystemMessage(ret)));
3081 
3082  return ret;
3083  }
3084 
3085  // try opening it read-only
3086 
3087  hFile = CreateFile(sFileName, GENERIC_READ,
3089 
3090  if (hFile == INVALID_HANDLE_VALUE) {
3091 
3092  // cannot open even read-only
3093 
3094  ret = GetLastError();
3095 
3096  VFDTRACE(0,
3097  (FUNC ": CreateFile(%s) - %s\n",
3098  sFileName, SystemMessage(ret)));
3099 
3100  return ret;
3101  }
3102 
3103  // file can be opened read-only
3104  *pAttributes |= FILE_ATTRIBUTE_READONLY;
3105  ret = ERROR_SUCCESS;
3106  }
3107 
3108  // check if the image is an IMZ file
3109 
3110  if (ExtractZipInfo(hFile, pImageSize) == ERROR_SUCCESS) {
3111  *pFileType = VFD_FILETYPE_ZIP;
3112  }
3113  else {
3114  *pImageSize = GetFileSize(hFile, NULL);
3115  *pFileType = VFD_FILETYPE_RAW;
3116  }
3117 
3118  CloseHandle(hFile);
3119 
3120  return ret;
3121 }
3122 
3123 //
3124 // Create a formatted new image file
3125 //
3127  PCSTR sFileName,
3128  VFD_MEDIA nMediaType,
3129  VFD_FILETYPE nFileType,
3130  BOOL bOverWrite)
3131 {
3132 #undef FUNC
3133 #define FUNC "VfdCreateImageFile"
3134  HANDLE hFile;
3135  ULONG file_size;
3136  PUCHAR image_buf = NULL;
3137  DWORD result;
3139 
3140  if (nFileType != VFD_FILETYPE_RAW) {
3141  return ERROR_INVALID_PARAMETER;
3142  }
3143 
3144  file_size = VfdGetMediaSize(nMediaType);
3145 
3146  if (file_size == 0) {
3147  return ERROR_INVALID_PARAMETER;
3148  }
3149 
3150  hFile = CreateFile(sFileName, GENERIC_WRITE, 0, NULL,
3151  bOverWrite ? CREATE_ALWAYS : CREATE_NEW, 0, NULL);
3152 
3153  if (hFile == INVALID_HANDLE_VALUE) {
3154  ret = GetLastError();
3155 
3156  VFDTRACE(0,
3157  (FUNC ": CreateFile - %s",
3158  SystemMessage(ret)));
3159 
3160  return ret;
3161  }
3162 
3163  image_buf = (PUCHAR)LocalAlloc(LPTR, file_size);
3164 
3165  if (image_buf == NULL) {
3166  ret = GetLastError();
3167 
3168  VFDTRACE(0,
3169  (FUNC ": LocalAlloc - %s",
3170  SystemMessage(ret)));
3171 
3172  goto exit_func;
3173  }
3174 
3176 
3177  if (!WriteFile(hFile, image_buf, file_size, &result, NULL) ||
3178  file_size != result) {
3179 
3180  ret = GetLastError();
3181 
3182  VFDTRACE(0,
3183  (FUNC ": WriteFile - %s",
3184  SystemMessage(ret)));
3185 
3186  goto exit_func;
3187  }
3188 
3190 
3191 exit_func:
3192  CloseHandle(hFile);
3193 
3194  if (image_buf) {
3195  LocalFree(image_buf);
3196  }
3197 
3198  return ret;
3199 }
3200 
3201 
3202 //
3203 // choose first available drive letter
3204 //
3206 {
3207  DWORD logical_drives = GetLogicalDrives();
3208  CHAR drive_letter = 'A';
3209 
3210  if (logical_drives == 0) {
3211  return '\0';
3212  }
3213 
3214  while (logical_drives & 0x1) {
3215  logical_drives >>= 1;
3216  drive_letter++;
3217  }
3218 
3219  if (drive_letter > 'Z') {
3220  return '\0';
3221  }
3222 
3223  return drive_letter;
3224 }
3225 
3226 //
3227 // media type functions
3228 //
3229 static const struct
3230 {
3233 }
3235 {
3236  { 0, "" }, // VFD_MEDIA_NONE,
3237  { VFD_SECTOR_TO_BYTE(320), "5.25\" 160KB" }, // VFD_MEDIA_F5_160
3238  { VFD_SECTOR_TO_BYTE(360), "5.25\" 180KB" }, // VFD_MEDIA_F5_180
3239  { VFD_SECTOR_TO_BYTE(640), "5.25\" 320KB" }, // VFD_MEDIA_F5_320
3240  { VFD_SECTOR_TO_BYTE(720), "5.25\" 360KB" }, // VFD_MEDIA_F5_360
3241  { VFD_SECTOR_TO_BYTE(1280), "3.5\" 640KB" }, // VFD_MEDIA_F3_640
3242  { VFD_SECTOR_TO_BYTE(1280), "5.25\" 640KB" }, // VFD_MEDIA_F5_640
3243  { VFD_SECTOR_TO_BYTE(1440), "3.5\" 720KB" }, // VFD_MEDIA_F3_720
3244  { VFD_SECTOR_TO_BYTE(1440), "5.25\" 720KB" }, // VFD_MEDIA_F5_720
3245  { VFD_SECTOR_TO_BYTE(1640), "3.5\" 820KB" }, // VFD_MEDIA_F3_820
3246  { VFD_SECTOR_TO_BYTE(2400), "3.5\" 1.2MB" }, // VFD_MEDIA_F3_1P2
3247  { VFD_SECTOR_TO_BYTE(2400), "5.25\" 1.2MB" }, // VFD_MEDIA_F5_1P2
3248  { VFD_SECTOR_TO_BYTE(2880), "3.5\" 1.44MB" }, // VFD_MEDIA_F3_1P4
3249  { VFD_SECTOR_TO_BYTE(3360), "3.5\" 1.68MB DMF" }, // VFD_MEDIA_F3_1P6
3250  { VFD_SECTOR_TO_BYTE(3444), "3.5\" 1.72MB DMF" }, // VFD_MEDIA_F3_1P7
3251  { VFD_SECTOR_TO_BYTE(5760), "3.5\" 2.88MB"} // VFD_MEDIA_F3_2P8
3252 };
3253 
3254 // Lookup the largest media to fit in a size
3255 
3257  ULONG nSize)
3258 {
3259  VFD_MEDIA i;
3260 
3261  for (i = 1; i < VFD_MEDIA_MAX; i++) {
3262  if (nSize < media_tbl[i].Size) {
3263  break;
3264  }
3265  }
3266 
3267  return (--i);
3268 }
3269 
3270 // Get media size (in bytes) of a media type
3271 
3273  VFD_MEDIA nMediaType)
3274 {
3275  return nMediaType < VFD_MEDIA_MAX ? media_tbl[nMediaType].Size : 0;
3276 }
3277 
3278 // Get media type name
3279 
3281  VFD_MEDIA nMediaType)
3282 {
3283  return nMediaType < VFD_MEDIA_MAX ? media_tbl[nMediaType].Name : NULL;
3284 }
#define StartService
Definition: winsvc.h:585
#define GetFileVersionInfo
Definition: winver.h:54
#define QueryDosDevice
Definition: winbase.h:3709
signed char * PCHAR
Definition: retypes.h:7
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
#define IOCTL_DISK_GET_LENGTH_INFO
Definition: vfdctl.c:37
DWORD WINAPI VfdDismountVolume(HANDLE hDevice, BOOL bForce)
Definition: vfdctl.c:2629
#define ERROR_BAD_ENVIRONMENT
Definition: winerror.h:113
UINT WINAPI SetErrorMode(IN UINT uMode)
Definition: except.c:753
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
#define DefineDosDevice
Definition: winbase.h:3580
CHAR WINAPI VfdChooseLetter()
Definition: vfdctl.c:3205
#define BSF_FORCEIFHUNG
Definition: dbt.h:54
#define FSCTL_UNLOCK_VOLUME
Definition: nt_native.h:833
#define SERVICE_ERROR_NORMAL
Definition: cmtypes.h:980
#define TRUE
Definition: types.h:120
#define SHCNF_PATH
Definition: shlobj.h:1762
#define CloseHandle
Definition: compat.h:398
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
DWORD WINAPI VfdGetDriverVersion(HANDLE hDevice, PULONG pVersion)
Definition: vfdctl.c:2446
QUERY_SERVICE_CONFIGA * LPQUERY_SERVICE_CONFIG
Definition: winsvc.h:550
DWORD WINAPI VfdGetDeviceNumber(HANDLE hDevice, PULONG pNumber)
Definition: vfdctl.c:2359
#define FindResource
Definition: winbase.h:3610
#define ERROR_SUCCESS
Definition: deptool.c:10
VFD_DISKTYPE DiskType
Definition: vfdio.h:64
#define VFD_LINK_REMOVED
Definition: vfdctl.c:75
#define WideCharToMultiByte
Definition: compat.h:101
#define SEM_FAILCRITICALERRORS
Definition: rtltypes.h:69
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
UCHAR VFD_DISKTYPE
Definition: vfdtypes.h:60
#define VFD_VOLUME_TEMPLATE
Definition: vfdctl.c:54
DWORD WINAPI VfdCloseImage(HANDLE hDevice, BOOL bForce)
Definition: vfdctl.c:1702
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define ERROR_INVALID_FUNCTION
Definition: dderror.h:6
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define VFD_DEVICE_TEMPLATE
Definition: vfdctl.c:50
#define IOCTL_VFD_SET_PROTECT
Definition: vfdio.h:247
#define GetDriveType
Definition: winbase.h:3629
VFD_FLAGS MediaFlags
Definition: vfdio.h:66
DWORD WINAPI VfdGetGlobalLink(HANDLE hDevice, PCHAR pLetter)
Definition: vfdctl.c:2114
#define GetFileVersionInfoSize
Definition: winver.h:53
static __inline void VfdNotify(WPARAM wParam, LPARAM lParam)
Definition: vfdctl.c:120
#define IOCTL_VFD_QUERY_NAME
Definition: vfdio.h:358
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
BOOL WINAPI SetEndOfFile(HANDLE hFile)
Definition: fileinfo.c:1154
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
#define QueryServiceConfig
Definition: winsvc.h:580
*nSize LPSTR _Inout_ LPDWORD nSize
Definition: winbase.h:2024
#define VFD_SECTOR_TO_BYTE(s)
Definition: vfdio.h:45
_In_ DWORD nLength
Definition: wincon.h:461
#define VS_FF_DEBUG
Definition: verrsrc.h:42
#define BSF_NOTIMEOUTIFNOTHUNG
Definition: dbt.h:57
#define VFD_PRODUCT_MAJOR
Definition: vfdver.h:15
#define IOCTL_VFD_CLEAR_PROTECT
Definition: vfdio.h:273
VFD_FILETYPE FileType
Definition: vfdio.h:67
#define S(x)
Definition: test.h:190
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
#define IOCTL_DISK_IS_WRITABLE
Definition: cdrw_usr.h:172
DWORD ExtractZipInfo(HANDLE hFile, ULONG *pSize)
Definition: vfdzip.c:133
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
const char * dev_name(int device)
Definition: wave.c:211
#define ZeroMemory
Definition: winbase.h:1635
LPVOID WINAPI LockResource(HGLOBAL handle)
Definition: res.c:550
#define isalpha(c)
Definition: acclib.h:74
#define VFT_DRV
Definition: verrsrc.h:77
ULONG ImageSize
Definition: vfdio.h:68
UINT_PTR WPARAM
Definition: windef.h:207
UCHAR VFD_FLAGS
Definition: vfdtypes.h:63
#define INVALID_FILE_SIZE
Definition: winbase.h:529
#define ERROR_REVISION_MISMATCH
Definition: winerror.h:788
#define SERVICE_ALL_ACCESS
Definition: winsvc.h:62
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
HICON HCURSOR
Definition: windef.h:284
BOOL WINAPI DeleteService(SC_HANDLE hService)
Definition: scm.c:916
#define DeleteFile
Definition: winbase.h:3581
#define CreateService
Definition: winsvc.h:569
#define BSF_NOHANG
Definition: dbt.h:56
#define _stricmp
Definition: cat.c:22
#define ERROR_SERVICE_NOT_ACTIVE
Definition: winerror.h:613
#define OpenService
Definition: winsvc.h:576
VFD_MEDIA MediaType
Definition: vfdio.h:65
WPARAM wParam
Definition: combotst.c:138
DWORD WINAPI VfdCheckImageFile(PCSTR sFileName, PDWORD pAttributes, PVFD_FILETYPE pFileType, PULONG pImageSize)
Definition: vfdctl.c:3035
LARGE_INTEGER Length
Definition: imports.h:232
#define FILE_SHARE_READ
Definition: compat.h:125
#define IOCTL_VFD_QUERY_VERSION
Definition: vfdio.h:387
DWORD WINAPI DECLSPEC_HOTPATCH SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
Definition: fileinfo.c:204
#define SERVICE_NO_CHANGE
Definition: winsvc.h:20
struct _test_info info[]
Definition: SetCursorPos.c:19
#define VFD_INSTALL_DIRECTORY
Definition: vfdctl.c:56
#define sprintf(buf, format,...)
Definition: sprintf.c:55
DWORD WINAPI VfdCheckDriverFile(PCSTR sFileName, PULONG pFileVersion)
Definition: vfdctl.c:2867
#define ChangeServiceConfig
Definition: winsvc.h:567
#define VFD_PRODUCT_MINOR
Definition: vfdver.h:16
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define VFD_MAXIMUM_DEVICES
Definition: vfdtypes.h:75
#define VFD_BYTE_TO_SECTOR(b)
Definition: vfdio.h:44
#define SERVICE_STOPPED
Definition: winsvc.h:21
#define DRIVE_REMOTE
Definition: winbase.h:250
DWORD WINAPI VfdGetDriverConfig(PSTR sFileName, PDWORD pStart)
Definition: vfdctl.c:959
GLenum const GLfloat * params
Definition: glext.h:5645
#define ERROR_ACCESS_DENIED
Definition: compat.h:87
unsigned int BOOL
Definition: ntddk_ex.h:94
static size_t double number
Definition: printf.c:64
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
Definition: fileinfo.c:786
#define GENERIC_WRITE
Definition: nt_native.h:90
#define SERVICE_RUNNING
Definition: winsvc.h:24
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
_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 DBT_DEVICEREMOVECOMPLETE
Definition: dbt.h:16
struct _VFD_IMAGE_INFO * PVFD_IMAGE_INFO
#define VFD_SECTOR_ALIGN_MASK
Definition: vfdio.h:41
HGLOBAL WINAPI LoadResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:532
const WCHAR * str
BOOL WINAPI CloseServiceHandle(SC_HANDLE hSCObject)
Definition: scm.c:577
#define MAKELONG(a, b)
Definition: typedefs.h:248
smooth NULL
Definition: ftsmooth.c:416
#define ERROR_FILE_ENCRYPTED
Definition: winerror.h:1400
static const WCHAR version[]
Definition: asmname.c:64
#define ERROR_NOT_READY
Definition: winerror.h:124
#define IDC_WAIT
Definition: winuser.h:684
LONG_PTR LPARAM
Definition: windef.h:208
#define IOCTL_VFD_SET_LINK
Definition: vfdio.h:194
static const struct @1541 media_tbl[VFD_MEDIA_MAX]
#define SERVICE_QUERY_STATUS
Definition: winsvc.h:55
DWORD WINAPI VfdGetDeviceName(HANDLE hDevice, PCHAR pName, ULONG nLength)
Definition: vfdctl.c:2396
#define SC_MANAGER_CREATE_SERVICE
Definition: winsvc.h:15
#define isdigit(c)
Definition: acclib.h:68
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define IOCTL_VFD_QUERY_NUMBER
Definition: vfdio.h:325
#define OPEN_EXISTING
Definition: compat.h:426
DWORD FormatBufferFat(PUCHAR pBuffer, ULONG nSectors)
Definition: vfdfat.c:116
UCHAR * PVFD_FLAGS
Definition: vfdtypes.h:63
#define VFD_NOT_INSTALLED
Definition: vfdapi.h:20
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define PostMessage
Definition: winuser.h:5733
#define FSCTL_DISMOUNT_VOLUME
Definition: nt_native.h:834
#define VFD_FLAG_WRITE_PROTECTED
Definition: vfdtypes.h:68
#define VFD_DRIVER_MINOR
Definition: vfdver.h:21
#define OpenSCManager
Definition: winsvc.h:575
#define IOCTL_VFD_QUERY_IMAGE
Definition: vfdio.h:163
int toupper(int c)
Definition: utclib.c:881
static LPSTR pName
Definition: security.c:75
GLsizeiptr size
Definition: glext.h:5919
#define ERROR_BAD_DRIVER
Definition: winerror.h:1180
#define SHCNE_MEDIAREMOVED
Definition: shlobj.h:1726
BOOL WINAPI GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
Definition: fileinfo.c:608
#define VOS_NT_WINDOWS32
Definition: verrsrc.h:71
DWORD WINAPI VfdFormatMedia(HANDLE hDevice)
Definition: vfdctl.c:2523
__wchar_t WCHAR
Definition: xmlstorage.h:180
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define FILE_FLAG_NO_BUFFERING
Definition: disk.h:45
PCSTR SystemMessage(DWORD nError)
Definition: vfdlib.c:147
#define IOCTL_VFD_QUERY_LINK
Definition: vfdio.h:221
#define SERVICE_CHANGE_CONFIG
Definition: winsvc.h:54
#define MAX_PATH
Definition: compat.h:26
#define WINAPI
Definition: msvc.h:8
HINSTANCE g_hDllModule
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
DWORD WINAPI VfdGetMediaState(HANDLE hDevice)
Definition: vfdctl.c:1949
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
unsigned long DWORD
Definition: ntddk_ex.h:95
DWORD WINAPI VfdSaveImage(HANDLE hDevice, PCSTR sFileName, BOOL bOverWrite, BOOL bTruncate)
Definition: vfdctl.c:2685
BOOL WINAPI QueryServiceStatus(SC_HANDLE hService, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:2788
#define VFDTRACE(LEVEL, STRING)
Definition: vfddbg.h:72
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:481
#define VFD_VERSIONINFO_LANG
Definition: vfdver.h:33
#define SetLastError(x)
Definition: compat.h:409
#define GetModuleFileName
Definition: winbase.h:3648
#define VFD_DRIVER_FILENAME
Definition: vfdver.h:19
#define OPEN_ALWAYS
Definition: disk.h:70
FD_TYPE file_type(FDSC **curr, char *fixed)
Definition: file.c:221
DWORD ExtractZipImage(HANDLE hFile, PUCHAR *pBuffer, PULONG pLength)
Definition: vfdzip.c:182
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
UCHAR * PVFD_FILETYPE
Definition: vfdtypes.h:62
ULONG Size
Definition: vfdctl.c:3231
#define DBT_DEVTYP_VOLUME
Definition: dbt.h:21
#define FILE_ATTRIBUTE_COMPRESSED
Definition: nt_native.h:711
ULONG WINAPI VfdGetMediaSize(VFD_MEDIA nMediaType)
Definition: vfdctl.c:3272
int ret
UCHAR VFD_FILETYPE
Definition: vfdtypes.h:62
#define IOCTL_VFD_OPEN_IMAGE
Definition: vfdio.h:107
Definition: stat.h:55
DWORD WINAPI VfdConfigDriver(DWORD nStart)
Definition: vfdctl.c:468
GLenum GLsizei len
Definition: glext.h:6722
#define GetFullPathName
Definition: winbase.h:3638
#define GENERIC_READ
Definition: compat.h:124
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
Definition: changenotify.c:340
_In_ HANDLE hFile
Definition: mswsock.h:90
#define FUNC
#define ERROR_ALREADY_ASSIGNED
Definition: winerror.h:169
#define ERROR_MORE_DATA
Definition: dderror.h:13
DWORD WINAPI VfdStopDriver(PDWORD pState)
Definition: vfdctl.c:801
#define GetFileAttributes
Definition: winbase.h:3632
#define LoadCursor
Definition: winuser.h:5713
#define SERVICE_START
Definition: winsvc.h:57
VFD_MEDIA WINAPI VfdLookupMedia(ULONG nSize)
Definition: vfdctl.c:3256
DWORD WINAPI GetLogicalDrives(VOID)
Definition: disk.c:110
#define DDD_FLAGS
DWORD WINAPI VfdOpenImage(HANDLE hDevice, PCSTR sFileName, VFD_DISKTYPE nDiskType, VFD_MEDIA nMediaType, VFD_FLAGS nMediaFlags)
Definition: vfdctl.c:1301
long WINAPI BroadcastSystemMessage(_In_ DWORD, _Inout_opt_ LPDWORD, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
_CRTIMP int __cdecl stat(const char *_Filename, struct stat *_Stat)
Definition: stat.h:345
#define CREATE_ALWAYS
Definition: disk.h:72
#define FILE_BEGIN
Definition: winbase.h:112
DWORD WINAPI VfdWriteProtect(HANDLE hDevice, BOOL bProtect)
Definition: vfdctl.c:2484
PCSTR Name
Definition: vfdctl.c:3232
DWORD WINAPI VfdCreateImageFile(PCSTR sFileName, VFD_MEDIA nMediaType, VFD_FILETYPE nFileType, BOOL bOverWrite)
Definition: vfdctl.c:3126
#define FILE_ATTRIBUTE_ENCRYPTED
Definition: ntifs_ex.h:385
DWORD WINAPI VfdSetLocalLink(HANDLE hDevice, CHAR cLetter)
Definition: vfdctl.c:2154
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
#define DDD_RAW_TARGET_PATH
Definition: winbase.h:504
#define ERROR_NETWORK_ACCESS_DENIED
Definition: winerror.h:157
DWORD WINAPI VfdRemoveDriver()
Definition: vfdctl.c:557
IN OUT PVCB OUT PDIRENT OUT PBCB IN BOOLEAN CreateFile
Definition: fatprocs.h:904
HCURSOR WINAPI SetCursor(_In_opt_ HCURSOR)
unsigned short USHORT
Definition: pedump.c:61
#define SERVICE_STOP
Definition: winsvc.h:58
#define IOCTL_VFD_CLOSE_IMAGE
Definition: vfdio.h:133
unsigned char dummy
Definition: maze.c:118
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
UINT g_nNotifyMsg
#define DBT_DEVICEARRIVAL
Definition: dbt.h:12
signed char * PSTR
Definition: retypes.h:7
DWORD WINAPI VfdStartDriver(PDWORD pState)
Definition: vfdctl.c:647
BOOL WINAPI ControlService(SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:619
CHAR FileName[0]
Definition: vfdio.h:70
unsigned int * PULONG
Definition: retypes.h:1
unsigned int UINT
Definition: ndis.h:50
#define IOCTL_VFD_RESET_MODIFY
Definition: vfdio.h:299
DWORD WINAPI SizeofResource(HINSTANCE hModule, HRSRC hRsrc)
Definition: res.c:568
DWORD * PDWORD
Definition: pedump.c:68
#define ERROR_SERVICE_DOES_NOT_EXIST
Definition: winerror.h:611
#define WM_DEVICECHANGE
Definition: winuser.h:1793
static LPCWSTR file_name
Definition: protocol.c:146
DWORD WINAPI VfdInstallDriver(PCSTR sFileName, DWORD nStart)
Definition: vfdctl.c:241
#define SHCNE_MEDIAINSERTED
Definition: shlobj.h:1725
#define FSCTL_LOCK_VOLUME
Definition: nt_native.h:832
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
struct _GET_LENGTH_INFORMATION GET_LENGTH_INFORMATION
unsigned int ULONG
Definition: retypes.h:1
#define LPTR
Definition: winbase.h:362
UCHAR * PVFD_MEDIA
Definition: vfdtypes.h:61
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
USHORT NameLength
Definition: vfdio.h:69
char * cleanup(char *str)
Definition: wpickclick.c:99
UCHAR * PVFD_DISKTYPE
Definition: vfdtypes.h:60
#define SERVICE_CONTROL_STOP
Definition: winsvc.h:36
PCSTR WINAPI VfdMediaTypeName(VFD_MEDIA nMediaType)
Definition: vfdctl.c:3280
DWORD WINAPI VfdGetLocalLink(HANDLE hDevice, PCHAR pLetter)
Definition: vfdctl.c:2281
#define SERVICE_QUERY_CONFIG
Definition: winsvc.h:53
#define CREATE_NEW
Definition: disk.h:69
#define VFD_DRIVER_MAJOR
Definition: vfdver.h:20
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1373
const char * PCSTR
Definition: typedefs.h:51
static void VfdBroadcastLink(CHAR cLetter, BOOL bRemoved)
Definition: vfdctl.c:77
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1827
BOOL WINAPI ReadFile(IN HANDLE hFile, IN LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:123
GLuint64EXT * result
Definition: glext.h:11304
#define VFD_LINK_CREATED
Definition: vfdctl.c:74
#define HWND_BROADCAST
Definition: winuser.h:1190
#define GetWindowsDirectory
Definition: winbase.h:3674
#define CHAR(Char)
struct _GET_LENGTH_INFORMATION * PGET_LENGTH_INFORMATION
static SERVICE_STATUS status
Definition: service.c:31
DWORD WINAPI VfdSetGlobalLink(HANDLE hDevice, CHAR cLetter)
Definition: vfdctl.c:1984
LPARAM lParam
Definition: combotst.c:139
DWORD WINAPI VfdGetDriverState(PDWORD pState)
Definition: vfdctl.c:1121
#define CP_OEMCP
Definition: winnls.h:228
#define BSM_APPLICATIONS
Definition: dbt.h:48
UCHAR VFD_MEDIA
Definition: vfdtypes.h:61
unsigned int * PUINT
Definition: ndis.h:50
HANDLE WINAPI VfdOpenDevice(ULONG nTarget)
Definition: vfdctl.c:1215
#define file_size(inode)
Definition: reiserfs_fs.h:1869
#define DELETE
Definition: nt_native.h:57
#define VFT2_DRV_SYSTEM
Definition: verrsrc.h:91
#define VFD_DEVICE_BASENAME
Definition: vfdio.h:35
TCHAR file_path[MAX_PATH]
Definition: sndrec32.cpp:57
static GLint image_size(GLint width, GLint height, GLenum format, GLenum type)
Definition: mipmap.c:4856
#define SERVICE_KERNEL_DRIVER
Definition: cmtypes.h:951
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define VerQueryValue
Definition: winver.h:56
Definition: ps.c:97