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