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 ¶m.DiskType, 78 ¶m.MediaType, 79 ¶m.MediaFlags, 80 ¶m.FileType, 81 ¶m.ImageSize); 82 83 if (ret == ERROR_SUCCESS) { 84 85 // show dialog box 86 87 ret = GuiSaveParam(hParent, ¶m); 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 } 530