xref: /reactos/modules/rosapps/lib/vfdlib/vfdguiut.c (revision 25c7e1a8)
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 //
FormatSizeBytes(ULONG size,PSTR buf)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 
FormatSizeUnits(ULONG size,PSTR buf)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 //
VfdGuiClose(HWND hParent,ULONG nDevice)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 		&param.DiskType,
139 		&param.MediaType,
140 		&param.MediaFlags,
141 		&param.FileType,
142 		&param.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, &param) == 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 //
VfdGuiFormat(HWND hParent,ULONG nDevice)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 //
SetControlText(HWND hWnd,UINT nCtrl,DWORD nMsg)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 //
VfdMakeFileDesc(PSTR pBuffer,ULONG nBufSize,VFD_FILETYPE nFileType,ULONG nFileSize,DWORD nFileAttr)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 
ShowContextMenu(HWND hDlg,HWND hCtl,LPARAM lParam)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 //
ShowHelpWindow(HWND hDlg,UINT nCtl)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