1 /*
2 vfdguisave.c
3
4 Virtual Floppy Drive for Windows
5 Driver control library
6 Save image GUI utility function
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 #if !defined(__REACTOS__) || defined(_MSC_VER)
18 #pragma warning(push,3)
19 #endif
20 #include <commdlg.h>
21 #if !defined(__REACTOS__) || defined(_MSC_VER)
22 #pragma warning(pop)
23 #endif
24
25 #include "vfdtypes.h"
26 #include "vfdapi.h"
27 #include "vfdlib.h"
28 #ifndef __REACTOS__
29 #include "vfdmsg.h"
30 #else
31 #include "vfdmsg_lib.h"
32 #endif
33 #include "vfdguirc.h"
34
35 //
36 // local functions
37 //
38 #ifndef __REACTOS__
39 static INT CALLBACK SaveDialogProc(
40 #else
41 static INT_PTR CALLBACK SaveDialogProc(
42 #endif
43 HWND hDlg,
44 UINT uMsg,
45 WPARAM wParam,
46 LPARAM lParam);
47
48 static void OnInit(HWND hDlg, PCSAVE_PARAM pParam);
49 static void OnTarget(HWND hDlg, HWND hEdit);
50 static void OnBrowse(HWND hDlg);
51 static void OnOverwrite(HWND hDlg, HWND hCheck);
52 static void OnTruncate(HWND hDlg, HWND hCheck);
53 static DWORD OnOK(HWND hDlg);
54
55 //
56 // Show Save Image dialog box
57 //
VfdGuiSave(HWND hParent,ULONG nDevice)58 DWORD WINAPI VfdGuiSave(
59 HWND hParent,
60 ULONG nDevice)
61 {
62 SAVE_PARAM param;
63 CHAR path[MAX_PATH];
64 DWORD ret;
65
66 // open the source device
67
68 param.hDevice = VfdOpenDevice(nDevice);
69
70 if (param.hDevice == INVALID_HANDLE_VALUE) {
71 return GetLastError();
72 }
73
74 // get current image information
75
76 param.ImageName = path;
77
78 ret = VfdGetImageInfo(
79 param.hDevice,
80 param.ImageName,
81 ¶m.DiskType,
82 ¶m.MediaType,
83 ¶m.MediaFlags,
84 ¶m.FileType,
85 ¶m.ImageSize);
86
87 if (ret == ERROR_SUCCESS) {
88
89 // show dialog box
90
91 ret = GuiSaveParam(hParent, ¶m);
92 }
93
94 // close the source device
95
96 CloseHandle(param.hDevice);
97
98 return ret;
99 }
100
GuiSaveParam(HWND hParent,PCSAVE_PARAM pParam)101 DWORD GuiSaveParam(
102 HWND hParent,
103 PCSAVE_PARAM pParam)
104 {
105 switch (DialogBoxParam(
106 g_hDllModule,
107 MAKEINTRESOURCE(IDD_SAVEDIALOG),
108 hParent,
109 SaveDialogProc,
110 (LPARAM)pParam))
111 {
112 case IDOK:
113 return ERROR_SUCCESS;
114
115 case IDCANCEL:
116 return ERROR_CANCELLED;
117
118 default:
119 return GetLastError();
120 }
121 }
122
123 //
124 // The dialog procedure
125 //
126 #ifndef __REACTOS__
SaveDialogProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)127 INT CALLBACK SaveDialogProc(
128 #else
129 INT_PTR CALLBACK SaveDialogProc(
130 #endif
131 HWND hDlg,
132 UINT uMsg,
133 WPARAM wParam,
134 LPARAM lParam)
135 {
136 switch (uMsg) {
137 case WM_INITDIALOG:
138 OnInit(hDlg, (PCSAVE_PARAM)lParam);
139 return TRUE;
140
141 case WM_COMMAND:
142 switch (wParam) {
143 case MAKELONG(IDC_TARGETFILE, EN_CHANGE):
144 OnTarget(hDlg, (HWND)lParam);
145 return TRUE;
146
147 case IDC_BROWSE:
148 OnBrowse(hDlg);
149 return TRUE;
150
151 case IDC_OVERWRITE:
152 OnOverwrite(hDlg, (HWND)lParam);
153 return TRUE;
154
155 case IDC_TRUNCATE:
156 OnTruncate(hDlg, (HWND)lParam);
157 return TRUE;
158
159 case IDOK:
160 if (OnOK(hDlg) == ERROR_SUCCESS) {
161 EndDialog(hDlg, IDOK);
162 }
163 return TRUE;
164
165 case IDCANCEL:
166 EndDialog(hDlg, IDCANCEL);
167 return TRUE;
168 }
169 break;
170
171 case WM_CONTEXTMENU:
172 ShowContextMenu(hDlg, (HWND)wParam, lParam);
173 break;
174
175 case WM_HELP:
176 {
177 LPHELPINFO info = (LPHELPINFO)lParam;
178
179 if (info->iContextType == HELPINFO_WINDOW) {
180 ShowHelpWindow(hDlg, info->iCtrlId);
181 }
182 }
183 return TRUE;
184 }
185
186 return FALSE;
187 }
188
189 //
190 // Initialize the dialog
191 //
OnInit(HWND hDlg,PCSAVE_PARAM pParam)192 void OnInit(
193 HWND hDlg,
194 PCSAVE_PARAM pParam)
195 {
196 // Store parameters
197
198 #ifndef __REACTOS__
199 SetWindowLong(hDlg, GWL_USERDATA, (ULONG)pParam);
200 #else
201 SetWindowLongPtr(hDlg, GWLP_USERDATA, (ULONG_PTR)pParam);
202 #endif
203
204 // clear the target existence flag
205
206 SetWindowLong(hDlg, DWL_USER, 0);
207
208 // Set dialog window title
209
210 SetControlText(hDlg, 0, MSG_SAVE_TITLE);
211
212 // Set control captions
213
214 SetControlText(hDlg, IDC_IMAGEFILE_LABEL, MSG_IMAGEFILE_LABEL);
215 SetControlText(hDlg, IDC_DISKTYPE_LABEL, MSG_DISKTYPE_LABEL);
216 SetControlText(hDlg, IDC_MEDIATYPE_LABEL, MSG_MEDIATYPE_LABEL);
217 SetControlText(hDlg, IDC_TARGETFILE_LABEL, MSG_TARGETFILE_LABEL);
218 SetControlText(hDlg, IDC_IMAGEDESC_LABEL, MSG_DESCRIPTION_LABEL);
219 SetControlText(hDlg, IDC_BROWSE, MSG_BROWSE_BUTTON);
220 SetControlText(hDlg, IDC_OVERWRITE, MSG_OVERWRITE_CHECK);
221 SetControlText(hDlg, IDC_TRUNCATE, MSG_TRUNCATE_CHECK);
222 SetControlText(hDlg, IDOK, MSG_SAVE_BUTTON);
223 SetControlText(hDlg, IDCANCEL, MSG_CANCEL_BUTTON);
224
225 // set disk type
226
227 if (pParam->DiskType == VFD_DISKTYPE_FILE) {
228 SetDlgItemText(hDlg, IDC_DISKTYPE, "FILE");
229 }
230 else {
231 SetDlgItemText(hDlg, IDC_DISKTYPE, "RAM");
232 }
233
234 // display media type
235
236 SetDlgItemText(hDlg, IDC_MEDIATYPE,
237 VfdMediaTypeName(pParam->MediaType));
238
239 // set current image and initial target
240
241 if (pParam->ImageName[0]) {
242 SetDlgItemText(hDlg, IDC_IMAGEFILE, pParam->ImageName);
243 SetDlgItemText(hDlg, IDC_TARGETFILE, pParam->ImageName);
244 }
245 else if (pParam->DiskType != VFD_DISKTYPE_FILE) {
246 SetDlgItemText(hDlg, IDC_IMAGEFILE, "<RAM>");
247 OnTarget(hDlg, GetDlgItem(hDlg, IDC_TARGETFILE));
248 }
249 }
250
251 //
252 // Path is changed -- check specified target file
253 //
OnTarget(HWND hDlg,HWND hEdit)254 void OnTarget(
255 HWND hDlg,
256 HWND hEdit)
257 {
258 PCSAVE_PARAM param;
259 CHAR buf[MAX_PATH];
260 ULONG file_size;
261 VFD_FILETYPE file_type;
262 DWORD file_attr;
263 DWORD ret;
264
265 // clear the target existence flag
266
267 SetWindowLong(hDlg, DWL_USER, 0);
268
269 // clear the description and hint text
270
271 SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, NULL);
272 SetDlgItemText(hDlg, IDC_IMAGEFILE_HINT, NULL);
273
274 // get the target file name
275
276 if (GetWindowText(hEdit, buf, sizeof(buf)) == 0) {
277
278 // target file is blank
279
280 EnableWindow(GetDlgItem(hDlg, IDC_OVERWRITE), FALSE);
281 EnableWindow(GetDlgItem(hDlg, IDC_TRUNCATE), FALSE);
282 EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
283
284 return;
285 }
286 else {
287 CHAR full[MAX_PATH];
288 PSTR file;
289
290 // convert into a full path
291
292 if (GetFullPathName(buf, sizeof(full), full, &file)) {
293 strcpy(buf, full);
294 }
295 }
296
297 //
298 // get the current image info
299 //
300 #ifndef __REACTOS__
301 param = (PCSAVE_PARAM)GetWindowLong(hDlg, GWL_USERDATA);
302 #else
303 param = (PCSAVE_PARAM)GetWindowLongPtr(hDlg, GWLP_USERDATA);
304 #endif
305
306 if (_stricmp(param->ImageName, buf) == 0) {
307
308 // target is the current file
309
310 char desc[MAX_PATH];
311
312 VfdMakeFileDesc(desc, sizeof(desc),
313 param->FileType, param->ImageSize,
314 GetFileAttributes(param->ImageName));
315
316 SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, desc);
317 SetControlText(hDlg, IDC_IMAGEFILE_HINT, MSG_CURRENT_FILE);
318
319 if (param->DiskType == VFD_DISKTYPE_FILE) {
320
321 // cannot overwrite the current FILE disk image
322
323 EnableWindow(GetDlgItem(hDlg, IDC_OVERWRITE), FALSE);
324 EnableWindow(GetDlgItem(hDlg, IDC_TRUNCATE), FALSE);
325 EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
326 return;
327 }
328 }
329
330 //
331 // check target image file
332 //
333 ret = VfdCheckImageFile(
334 buf, &file_attr, &file_type, &file_size);
335
336 if (ret == ERROR_FILE_NOT_FOUND) {
337 // file does not exist
338 SetControlText(hDlg, IDC_IMAGEFILE_DESC, MSG_DESC_NEW_FILE);
339 EnableWindow(GetDlgItem(hDlg, IDC_OVERWRITE), FALSE);
340 EnableWindow(GetDlgItem(hDlg, IDC_TRUNCATE), FALSE);
341 EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
342 return;
343 }
344 else if (ret != ERROR_SUCCESS) {
345 SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, SystemMessage(ret));
346 EnableWindow(GetDlgItem(hDlg, IDC_OVERWRITE), FALSE);
347 EnableWindow(GetDlgItem(hDlg, IDC_TRUNCATE), FALSE);
348 EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
349 return;
350 }
351
352 // set target file description
353
354 VfdMakeFileDesc(buf, sizeof(buf),
355 file_type, file_size, file_attr);
356
357 SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, buf);
358
359 // check target file type
360
361 if (file_type == VFD_FILETYPE_ZIP) {
362 SetControlText(hDlg, IDC_IMAGEFILE_HINT, MSG_TARGET_IS_ZIP);
363 EnableWindow(GetDlgItem(hDlg, IDC_OVERWRITE), FALSE);
364 EnableWindow(GetDlgItem(hDlg, IDC_TRUNCATE), FALSE);
365 EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
366 return;
367 }
368
369 // the target is an existing raw file
370
371 EnableWindow(GetDlgItem(hDlg, IDC_OVERWRITE), TRUE);
372
373 // set truncate box
374
375 if (file_size > VfdGetMediaSize(param->MediaType)) {
376 EnableWindow(GetDlgItem(hDlg, IDC_TRUNCATE), TRUE);
377 SetControlText(hDlg, IDC_IMAGEFILE_HINT, MSG_SIZE_MISMATCH);
378 }
379 else {
380 EnableWindow(GetDlgItem(hDlg, IDC_TRUNCATE), FALSE);
381 }
382
383 // check overwrite setting
384
385 if (IsDlgButtonChecked(hDlg, IDC_OVERWRITE) != BST_CHECKED) {
386 EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
387 }
388 else {
389 EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
390 }
391
392 // target file exists and overwritable
393
394 SetWindowLong(hDlg, DWL_USER, 1);
395 }
396
397
398 //
399 // Show save file dialog box
400 //
OnBrowse(HWND hDlg)401 void OnBrowse(
402 HWND hDlg)
403 {
404 OPENFILENAME ofn;
405 PSTR title;
406 CHAR file[MAX_PATH];
407 CHAR dir[MAX_PATH];
408 DWORD len;
409
410 title = ModuleMessage(MSG_SAVE_TITLE);
411
412 ZeroMemory(&ofn, sizeof(ofn));
413 ZeroMemory(file, sizeof(file));
414 ZeroMemory(dir, sizeof(dir));
415
416 len = GetDlgItemText(hDlg, IDC_TARGETFILE, file, sizeof(file));
417
418 if (len && file[len - 1] == '\\') {
419 strcpy(dir, file);
420 ZeroMemory(file, sizeof(file));
421 }
422
423 // Different structure sizes must be used for NT and 2K/XP
424 ofn.lStructSize = IS_WINDOWS_NT() ?
425 OPENFILENAME_SIZE_VERSION_400 : sizeof(ofn);
426
427 ofn.hwndOwner = hDlg;
428 ofn.lpstrFile = file;
429 ofn.nMaxFile = sizeof(file);
430 ofn.lpstrInitialDir = dir;
431 ofn.lpstrTitle = title ? title : "Save Image";
432 ofn.lpstrFilter = "*.*\0*.*\0";
433 #ifndef __REACTOS__
434 ofn.Flags = OFN_ENABLESIZING | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
435 #else
436 ofn.Flags = OFN_EXPLORER | OFN_ENABLESIZING | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
437 #endif
438
439 if (GetSaveFileName(&ofn)) {
440 SetDlgItemText(hDlg, IDC_TARGETFILE, file);
441 SetFocus(GetDlgItem(hDlg, IDC_TARGETFILE));
442 }
443
444 if (title) {
445 LocalFree(title);
446 }
447 }
448
OnOverwrite(HWND hDlg,HWND hCheck)449 void OnOverwrite(
450 HWND hDlg,
451 HWND hCheck)
452 {
453 if (GetWindowLong(hDlg, DWL_USER)) {
454 // the target file exists and overwritable
455 if (SendMessage(hCheck, BM_GETCHECK, 0, 0) != BST_CHECKED) {
456 EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
457 }
458 else {
459 EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
460 }
461 }
462 }
463
OnTruncate(HWND hDlg,HWND hCheck)464 void OnTruncate(
465 HWND hDlg,
466 HWND hCheck)
467 {
468 UNREFERENCED_PARAMETER(hDlg);
469 UNREFERENCED_PARAMETER(hCheck);
470 }
471
472 //
473 // Save image
474 //
OnOK(HWND hDlg)475 DWORD OnOK(
476 HWND hDlg)
477 {
478 PCSAVE_PARAM param;
479 CHAR path[MAX_PATH];
480 BOOL overwrite;
481 BOOL truncate;
482 DWORD ret;
483
484 #ifndef __REACTOS__
485 param = (PCSAVE_PARAM)GetWindowLong(hDlg, GWL_USERDATA);
486 #else
487 param = (PCSAVE_PARAM)GetWindowLongPtr(hDlg, GWLP_USERDATA);
488 #endif
489
490 if (!param) {
491 return ERROR_INVALID_FUNCTION;
492 }
493
494 // get the target image name
495
496 if (GetDlgItemText(hDlg, IDC_TARGETFILE, path, sizeof(path)) == 0) {
497 return ERROR_INVALID_FUNCTION;
498 }
499
500 if (GetWindowLong(hDlg, DWL_USER)) {
501 // the target file exists and overwritable
502 overwrite = (IsDlgButtonChecked(hDlg, IDC_OVERWRITE) == BST_CHECKED);
503 truncate = (IsDlgButtonChecked(hDlg, IDC_TRUNCATE) == BST_CHECKED);
504 }
505 else {
506 overwrite = FALSE;
507 truncate = TRUE;
508 }
509
510 retry:
511 ret = VfdDismountVolume(param->hDevice, FALSE);
512
513 if (ret == ERROR_ACCESS_DENIED) {
514 PSTR msg = ModuleMessage(MSG_UNMOUNT_CONFIRM);
515
516 int reply = MessageBox(
517 hDlg, msg ? msg : "retry", VFD_MSGBOX_TITLE,
518 MB_ICONEXCLAMATION | MB_CANCELTRYCONTINUE);
519
520 if (msg) {
521 LocalFree(msg);
522 }
523
524 if (reply == IDRETRY) {
525 goto retry;
526 }
527 else if (reply == IDCANCEL) {
528 return ERROR_CANCELLED;
529 }
530 else {
531 VfdDismountVolume(param->hDevice, TRUE);
532 }
533 }
534 else if (ret != ERROR_SUCCESS) {
535
536 MessageBox(hDlg, SystemMessage(ret),
537 VFD_MSGBOX_TITLE, MB_ICONSTOP);
538
539 return ret;
540 }
541
542 ret = VfdSaveImage(param->hDevice, path, overwrite, truncate);
543
544 if (ret != ERROR_SUCCESS) {
545
546 // show error message
547
548 MessageBox(hDlg, SystemMessage(ret),
549 VFD_MSGBOX_TITLE, MB_ICONSTOP);
550 }
551
552 return ret;
553 }
554