1 /*
2 vfdguiut.c
3
4 Virtual Floppy Drive for Windows
5 Driver control library
6 open / close / format GUI utility 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 <stdio.h>
18
19 #include "vfdtypes.h"
20 #include "vfdapi.h"
21 #include "vfdlib.h"
22 #ifndef __REACTOS__
23 #include "vfdmsg.h"
24 #else
25 #include "vfdmsg_lib.h"
26 #endif
27 #include "vfdguirc.h"
28
29 //
30 // message box constants added since Win2K
31 //
32
33 #ifndef MB_CANCELTRYCONTINUE
34 #define MB_CANCELTRYCONTINUE 0x00000006L
35 #endif
36
37 #ifndef IDTRYAGAIN
38 #define IDTRYAGAIN 10
39 #endif
40
41 #ifndef IDCONTINUE
42 #define IDCONTINUE 11
43 #endif
44
45 //
46 // local funcitons
47 //
FormatSizeBytes(ULONG size,PSTR buf)48 static PSTR FormatSizeBytes(ULONG size, PSTR buf)
49 {
50 ULONG comma = 1;
51 int len;
52
53 while ((comma * 1000) < size) {
54 comma *= 1000;
55 }
56
57 len = sprintf(buf, "%lu", size / comma);
58
59 while (comma > 1) {
60 size %= comma;
61 comma /= 1000;
62 len += sprintf(buf + len, ",%03lu", size / comma);
63 }
64
65 return buf;
66 }
67
FormatSizeUnits(ULONG size,PSTR buf)68 static PSTR FormatSizeUnits(ULONG size, PSTR buf)
69 {
70 static const char *name[3] = {
71 " KB", " MB", " GB"
72 };
73 int unit;
74 double dsize;
75
76 if (size < 1000) {
77 #ifndef __REACTOS__
78 sprintf(buf, "%u", size);
79 #else
80 sprintf(buf, "%lu", size);
81 #endif
82 return buf;
83 }
84
85 dsize = size;
86 dsize /= 1024;
87 unit = 0;
88
89 while (unit < 2 && dsize >= 1000) {
90 dsize /= 1000;
91 unit++;
92 }
93
94 if (dsize < 10) {
95 sprintf(buf, "%3.2f%s", dsize, name[unit]);
96 }
97 else if (dsize < 100) {
98 sprintf(buf, "%3.1f%s", dsize, name[unit]);
99 }
100 else if (dsize < 1000) {
101 sprintf(buf, "%3.0f%s", dsize, name[unit]);
102 }
103 else {
104 FormatSizeBytes((ULONG)dsize, buf);
105 strcat(buf, name[unit]);
106 }
107
108 return buf;
109 }
110
111 //
112 // Close the current image
113 //
VfdGuiClose(HWND hParent,ULONG nDevice)114 DWORD WINAPI VfdGuiClose(
115 HWND hParent, // parent window
116 ULONG nDevice) // device number
117 {
118 HANDLE hDevice;
119 SAVE_PARAM param;
120 CHAR path[MAX_PATH];
121 HCURSOR hourglass;
122 DWORD ret;
123 int reply;
124
125 VFDTRACE(0, ("VfdGuiClose()\n"));
126
127 hDevice = VfdOpenDevice(nDevice);
128
129 if (hDevice == INVALID_HANDLE_VALUE) {
130 return GetLastError();
131 }
132
133 // get current image information
134
135 ret = VfdGetImageInfo(
136 hDevice,
137 path,
138 ¶m.DiskType,
139 ¶m.MediaType,
140 ¶m.MediaFlags,
141 ¶m.FileType,
142 ¶m.ImageSize);
143
144 if (ret != ERROR_SUCCESS) {
145 CloseHandle(hDevice);
146 return ret;
147 }
148
149 param.hDevice = hDevice;
150 param.ImageName = path;
151
152 // check if RAM image is modified
153
154 if (param.MediaFlags & VFD_FLAG_DATA_MODIFIED) {
155 PSTR msg = ModuleMessage(MSG_MEDIA_MODIFIED);
156
157 for (;;) {
158 reply = MessageBox(hParent, msg ? msg : "save?",
159 VFD_MSGBOX_TITLE, MB_ICONQUESTION | MB_YESNOCANCEL);
160
161 if (reply != IDYES) {
162 break;
163 }
164
165 if (GuiSaveParam(hParent, ¶m) == ERROR_SUCCESS) {
166 break;
167 }
168 }
169
170 if (msg) {
171 LocalFree(msg);
172 }
173
174 if (reply == IDCANCEL) {
175 CloseHandle(hDevice);
176 return ERROR_CANCELLED;
177 }
178 }
179
180 // close the image
181
182 hourglass = LoadCursor(NULL, IDC_WAIT);
183
184 for (;;) {
185
186 // show the hourglass cursor
187
188 HCURSOR original = SetCursor(hourglass);
189
190 // close the current image
191
192 ret = VfdCloseImage(hDevice, FALSE);
193
194 // restore the original cursor
195
196 SetCursor(original);
197
198 if (ret != ERROR_ACCESS_DENIED) {
199 // success or errors other than access denied
200 break;
201 }
202
203 if (IS_WINDOWS_NT()) {
204
205 // Windows NT -- cannot force close
206 // show retry / cancel message box
207
208 PSTR msg = ModuleMessage(MSG_UNMOUNT_FAILED);
209
210 reply = MessageBox(
211 hParent, msg ? msg : "retry", VFD_MSGBOX_TITLE,
212 MB_ICONEXCLAMATION | MB_RETRYCANCEL);
213
214 if (msg) {
215 LocalFree(msg);
216 }
217 }
218 else {
219
220 // Windows 2000 and later -- possible to force
221 // show cancel / retry / continue message box
222
223 PSTR msg = ModuleMessage(MSG_UNMOUNT_CONFIRM);
224
225 reply = MessageBox(
226 hParent, msg ? msg : "retry", VFD_MSGBOX_TITLE,
227 MB_ICONEXCLAMATION | MB_CANCELTRYCONTINUE);
228
229 if (msg) {
230 LocalFree(msg);
231 }
232
233 if (reply == IDCONTINUE) {
234
235 // try forced close
236
237 ret = VfdCloseImage(hDevice, TRUE);
238 }
239 }
240
241 if (reply == IDCANCEL) {
242 ret = ERROR_CANCELLED;
243 break;
244 }
245 else if (reply == IDCONTINUE) {
246
247 // try forced close
248
249 ret = VfdCloseImage(hDevice, TRUE);
250 break;
251 }
252 }
253
254 CloseHandle(hDevice);
255
256 return ret;
257 }
258
259 //
260 // Format the current media
261 //
VfdGuiFormat(HWND hParent,ULONG nDevice)262 DWORD WINAPI VfdGuiFormat(
263 HWND hParent, // parent window
264 ULONG nDevice) // device number
265 {
266 HANDLE hDevice;
267 ULONG ret;
268 PSTR msg;
269
270 msg = ModuleMessage(MSG_FORMAT_WARNING);
271
272 ret = MessageBox(hParent,
273 msg ? msg : "Format?",
274 VFD_MSGBOX_TITLE,
275 MB_ICONEXCLAMATION | MB_OKCANCEL);
276
277 if (msg) {
278 LocalFree(msg);
279 }
280
281 if (ret == IDCANCEL) {
282 MessageBox(hParent,
283 SystemMessage(ERROR_CANCELLED),
284 VFD_MSGBOX_TITLE, MB_ICONSTOP);
285
286 return ERROR_CANCELLED;
287 }
288
289 hDevice = VfdOpenDevice(nDevice);
290
291 if (hDevice == INVALID_HANDLE_VALUE) {
292 ret = GetLastError();
293 }
294 else {
295 HCURSOR original;
296
297 retry:
298 original = SetCursor(LoadCursor(NULL, IDC_WAIT));
299
300 ret = VfdDismountVolume(hDevice, FALSE);
301
302 if (ret == ERROR_ACCESS_DENIED) {
303 PSTR msg;
304 int reply;
305
306 SetCursor(original);
307
308 msg = ModuleMessage(MSG_UNMOUNT_CONFIRM);
309
310 reply = MessageBox(
311 hParent, msg ? msg : "retry", VFD_MSGBOX_TITLE,
312 MB_ICONEXCLAMATION | MB_CANCELTRYCONTINUE);
313
314 if (msg) {
315 LocalFree(msg);
316 }
317
318 if (reply == IDRETRY) {
319 goto retry;
320 }
321 else if (reply == IDCANCEL) {
322 ret = ERROR_CANCELLED;
323 }
324 else {
325 VfdDismountVolume(hDevice, TRUE);
326 ret = ERROR_SUCCESS;
327 }
328 }
329
330 if (ret == ERROR_SUCCESS) {
331 ret = VfdFormatMedia(hDevice);
332 }
333
334 SetCursor(original);
335
336 CloseHandle(hDevice);
337 }
338
339 MessageBox(hParent,
340 SystemMessage(ret),
341 VFD_MSGBOX_TITLE,
342 ret == ERROR_SUCCESS ? MB_ICONINFORMATION : MB_ICONSTOP);
343
344 return ret;
345 }
346
347 //
348 // Set a text to a dialog control
349 //
SetControlText(HWND hWnd,UINT nCtrl,DWORD nMsg)350 void SetControlText(
351 HWND hWnd,
352 UINT nCtrl,
353 DWORD nMsg)
354 {
355 PSTR p = NULL;
356
357 if (nMsg) {
358 p = ModuleMessage(nMsg);
359 }
360
361 if (nCtrl) {
362 SetDlgItemText(hWnd, nCtrl, p);
363 }
364 else {
365 SetWindowText(hWnd, p);
366 }
367
368 if (p) {
369 LocalFree(p);
370 }
371 }
372
373 //
374 // Make file description text
375 //
VfdMakeFileDesc(PSTR pBuffer,ULONG nBufSize,VFD_FILETYPE nFileType,ULONG nFileSize,DWORD nFileAttr)376 void WINAPI VfdMakeFileDesc(
377 PSTR pBuffer,
378 ULONG nBufSize,
379 VFD_FILETYPE nFileType,
380 ULONG nFileSize,
381 DWORD nFileAttr)
382 {
383 PSTR type_str;
384 PSTR size_str;
385 PSTR attr_ro;
386 PSTR attr_enc;
387 PSTR attr_cmp;
388
389 ZeroMemory(pBuffer, nBufSize);
390
391 switch (nFileType) {
392 case VFD_FILETYPE_RAW:
393 type_str = ModuleMessage(MSG_FILETYPE_RAW);
394 break;
395
396 case VFD_FILETYPE_ZIP:
397 type_str = ModuleMessage(MSG_FILETYPE_ZIP);
398 break;
399
400 default:
401 type_str = NULL;
402 }
403
404 if (nFileSize == INVALID_FILE_SIZE) {
405 size_str = ModuleMessage(MSG_DESC_NEW_FILE);
406 }
407 else {
408 CHAR buf[20], buf2[20];
409 size_str = ModuleMessage(MSG_DESC_FILESIZE,
410 FormatSizeBytes(nFileSize, buf),
411 FormatSizeUnits(nFileSize, buf2));
412 }
413
414 attr_ro = NULL;
415 attr_cmp = NULL;
416 attr_enc = NULL;
417
418 if (nFileAttr != INVALID_FILE_ATTRIBUTES) {
419 if (nFileAttr & FILE_ATTRIBUTE_READONLY) {
420 attr_ro = ModuleMessage(MSG_ATTR_READONLY);
421 }
422
423 if (nFileAttr & FILE_ATTRIBUTE_COMPRESSED) {
424 attr_cmp = ModuleMessage(MSG_ATTR_COMPRESSED);
425 }
426
427 if (nFileAttr & FILE_ATTRIBUTE_ENCRYPTED) {
428 attr_enc = ModuleMessage(MSG_ATTR_ENCRYPTED);
429 }
430 }
431
432 _snprintf(pBuffer, nBufSize - 1, "%s %s %s %s %s",
433 type_str ? type_str : "",
434 size_str ? size_str : "",
435 attr_ro ? attr_ro : "",
436 attr_cmp ? attr_cmp : "",
437 attr_enc ? attr_enc : "");
438
439 if (type_str) {
440 LocalFree(type_str);
441 }
442 if (size_str) {
443 LocalFree(size_str);
444 }
445 if (attr_ro) {
446 LocalFree(attr_ro);
447 }
448 if (attr_cmp) {
449 LocalFree(attr_cmp);
450 }
451 if (attr_enc) {
452 LocalFree(attr_enc);
453 }
454 }
455
ShowContextMenu(HWND hDlg,HWND hCtl,LPARAM lParam)456 void ShowContextMenu(
457 HWND hDlg,
458 HWND hCtl,
459 LPARAM lParam)
460 {
461 POINT pt;
462 UINT id;
463 HMENU hMenu;
464
465 pt.x = ((int)(short)LOWORD(lParam));
466 pt.y = ((int)(short)HIWORD(lParam));
467
468 if (pt.x == -1 || pt.y == -1) {
469 RECT rc;
470
471 GetWindowRect(hCtl, &rc);
472 pt.x = (rc.left + rc.right) / 2;
473 pt.y = (rc.top + rc.bottom) / 2;
474
475 id = GetDlgCtrlID(hCtl);
476 }
477 else {
478 POINT pt2 = pt;
479
480 ScreenToClient(hDlg, &pt2);
481
482 id = GetDlgCtrlID(
483 ChildWindowFromPoint(hDlg, pt2));
484 }
485
486 if (id < IDC_IMAGEFILE_LABEL ||
487 id > IDC_TRUNCATE) {
488 return;
489 }
490
491 hMenu = CreatePopupMenu();
492
493 AppendMenu(hMenu, MF_STRING, 1, "&What's This");
494
495 if (TrackPopupMenu(hMenu, TPM_RETURNCMD,
496 pt.x, pt.y, 0, hDlg, NULL))
497 {
498 ShowHelpWindow(hDlg, id);
499 }
500
501 DestroyMenu(hMenu);
502 }
503
504 //
505 // Show tool tip help
506 //
ShowHelpWindow(HWND hDlg,UINT nCtl)507 void ShowHelpWindow(
508 HWND hDlg,
509 UINT nCtl)
510 {
511 UINT msg;
512 RECT rc;
513 PSTR help;
514
515 switch (nCtl) {
516 case IDC_IMAGEFILE_LABEL:
517 case IDC_IMAGEFILE:
518 msg = MSG_HELP_IMAGEFILE;
519 break;
520 case IDC_IMAGEDESC_LABEL:
521 case IDC_IMAGEFILE_DESC:
522 msg = MSG_HELP_IMAGEDESC;
523 break;
524 case IDC_TARGETFILE_LABEL:
525 case IDC_TARGETFILE:
526 msg = MSG_HELP_TARGETFILE;
527 break;
528 case IDC_DISKTYPE_LABEL:
529 case IDC_DISKTYPE:
530 case IDC_DISKTYPE_FILE:
531 case IDC_DISKTYPE_RAM:
532 msg = MSG_HELP_DISKTYPE;
533 break;
534 case IDC_MEDIATYPE_LABEL:
535 case IDC_MEDIATYPE:
536 msg = MSG_HELP_MEDIATYPE;
537 break;
538 case IDC_WRITE_PROTECTED:
539 msg = MSG_HELP_PROTECT_NOW;
540 break;
541 case IDC_OPEN_PROTECTED:
542 msg = MSG_HELP_PROTECT_OPEN;
543 break;
544 case IDC_BROWSE:
545 msg = MSG_HELP_BROWSE;
546 break;
547 case IDC_OPEN:
548 msg = MSG_HELP_OPEN;
549 break;
550 case IDC_SAVE:
551 msg = MSG_HELP_SAVE;
552 break;
553 case IDC_CLOSE:
554 msg = MSG_HELP_CLOSE;
555 break;
556 case IDC_FORMAT:
557 msg = MSG_HELP_FORMAT;
558 break;
559 case IDC_CONTROL:
560 msg = MSG_HELP_CONTROL;
561 break;
562 case IDC_OVERWRITE:
563 msg = MSG_HELP_OVERWRITE;
564 break;
565 case IDC_TRUNCATE:
566 msg = MSG_HELP_TRUNCATE;
567 break;
568 default:
569 return;
570 }
571
572 GetWindowRect(GetDlgItem(hDlg, nCtl), &rc);
573
574 help = ModuleMessage(msg);
575
576 if (help) {
577 VfdToolTip(hDlg, help, rc.left, (rc.top + rc.bottom) / 2, TRUE);
578 LocalFree(help);
579 }
580 }
581
582