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 // 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 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__ 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 // 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 // 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 // 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 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 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 // 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