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