1 /*
2 	vfdguiopen.c
3 
4 	Virtual Floppy Drive for Windows
5 	Driver control library
6 	Open 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 //	String constants
37 //
38 
39 #define FALLBACK_IMAGE_FILTER	\
40 	"Common image files (bin,dat,fdd,flp,ima,img,vfd)\0" \
41 	"*.bin;*.dat;*.fdd;*.flp;*.ima;*.img;*.vfd\0" \
42 	"Zip compressed image (imz,zip)\0*.imz;*.zip\0" \
43 	"All files (*.*)\0*.*\0"
44 
45 #define FALLBACK_IMAGE_TITLE	"Open Virtual Floppy Image"
46 
47 //
48 //	local functions
49 //
50 #ifndef __REACTOS__
51 static INT CALLBACK OpenDialogProc(
52 #else
53 static INT_PTR CALLBACK OpenDialogProc(
54 #endif
55 	HWND			hDlg,
56 	UINT			uMsg,
57 	WPARAM			wParam,
58 	LPARAM			lParam);
59 
60 static void OnInit(HWND hDlg, ULONG nDevice);
61 static void OnImage(HWND hDlg, HWND hEdit);
62 static void OnBrowse(HWND hDlg);
63 static void OnDiskType(HWND hDlg, HWND hRadio);
64 static void OnMediaType(HWND hDlg, HWND hCombo);
65 static void OnProtect(HWND hDlg, HWND hCheck);
66 static DWORD OnOK(HWND hDlg);
67 
68 //
69 //	Show Open Image dialog box
70 //
71 DWORD WINAPI VfdGuiOpen(
72 	HWND			hParent,
73 	ULONG			nDevice)
74 {
75 	switch (DialogBoxParam(
76 		g_hDllModule,
77 		MAKEINTRESOURCE(IDD_OPENDIALOG),
78 		hParent,
79 		OpenDialogProc,
80 		nDevice))
81 	{
82 	case IDOK:
83 		return ERROR_SUCCESS;
84 
85 	case IDCANCEL:
86 		return ERROR_CANCELLED;
87 
88 	default:
89 		return GetLastError();
90 	}
91 }
92 
93 //
94 // Open image dialog procedure
95 //
96 #ifndef __REACTOS__
97 INT CALLBACK OpenDialogProc(
98 #else
99 INT_PTR CALLBACK OpenDialogProc(
100 #endif
101 	HWND			hDlg,
102 	UINT			uMsg,
103 	WPARAM			wParam,
104 	LPARAM			lParam)
105 {
106 	switch (uMsg) {
107 	case WM_INITDIALOG:
108 		OnInit(hDlg, lParam);
109 		return TRUE;
110 
111 	case WM_COMMAND:
112 		switch (wParam) {
113 		case MAKELONG(IDC_IMAGEFILE, EN_CHANGE):
114 			OnImage(hDlg, (HWND)lParam);
115 			return TRUE;
116 
117 		case IDC_BROWSE:
118 			OnBrowse(hDlg);
119 			return TRUE;
120 
121 		case IDC_DISKTYPE_FILE:
122 		case IDC_DISKTYPE_RAM:
123 			OnDiskType(hDlg, (HWND)lParam);
124 			return TRUE;
125 
126 		case MAKELONG(IDC_MEDIATYPE, CBN_SELCHANGE):
127 			OnMediaType(hDlg, (HWND)lParam);
128 			return TRUE;
129 
130 		case IDC_OPEN_PROTECTED:
131 			OnProtect(hDlg, (HWND)lParam);
132 			return TRUE;
133 
134 		case IDOK:
135 			if (OnOK(hDlg) == ERROR_SUCCESS) {
136 				EndDialog(hDlg, IDOK);
137 			}
138 			return TRUE;
139 
140 		case IDCANCEL:
141 			EndDialog(hDlg, IDCANCEL);
142 			return TRUE;
143 		}
144 		break;
145 
146 	case WM_CONTEXTMENU:
147 		ShowContextMenu(hDlg, (HWND)wParam, lParam);
148 		break;
149 
150 	case WM_HELP:
151 		{
152 			LPHELPINFO info = (LPHELPINFO)lParam;
153 
154 			if (info->iContextType == HELPINFO_WINDOW) {
155 				ShowHelpWindow(hDlg, info->iCtrlId);
156 			}
157 		}
158 		return TRUE;
159 	}
160 
161 	return FALSE;
162 }
163 
164 //
165 //	Initialize the Open Image dialog
166 //
167 void OnInit(
168 	HWND			hDlg,
169 	ULONG			nDevice)
170 {
171 	VFD_MEDIA i;
172 
173 	//	Store the device number
174 
175 	SetWindowLong(hDlg, GWL_USERDATA, nDevice);
176 
177 	//	Store default file size
178 
179 	SetWindowLong(hDlg, DWL_USER, INVALID_FILE_SIZE);
180 
181 	// Set dialog window title
182 
183 	SetControlText(hDlg, 0, MSG_OPEN_TITLE);
184 
185 	// Set control captions
186 
187 	SetControlText(hDlg, IDC_IMAGEFILE_LABEL,	MSG_IMAGEFILE_ACCEL);
188 	SetControlText(hDlg, IDC_IMAGEDESC_LABEL,	MSG_DESCRIPTION_LABEL);
189 	SetControlText(hDlg, IDC_BROWSE,			MSG_BROWSE_BUTTON);
190 	SetControlText(hDlg, IDC_DISKTYPE_LABEL,	MSG_DISKTYPE_LABEL);
191 	SetControlText(hDlg, IDC_MEDIATYPE_LABEL,	MSG_MEDIATYPE_ACCEL);
192 	SetControlText(hDlg, IDC_OPEN_PROTECTED,	MSG_MENU_PROTECT);
193 	SetControlText(hDlg, IDOK,					MSG_CREATE_BUTTON);
194 	SetControlText(hDlg, IDCANCEL,				MSG_CANCEL_BUTTON);
195 
196 	//	select RAM disk as default
197 
198 	CheckRadioButton(hDlg, IDC_DISKTYPE_FILE,
199 		IDC_DISKTYPE_RAM, IDC_DISKTYPE_RAM);
200 
201 	//	setup media type combo list
202 
203 	for (i = 1; i < VFD_MEDIA_MAX; i++) {
204 		SendDlgItemMessage(hDlg, IDC_MEDIATYPE,
205 			CB_ADDSTRING, 0, (LPARAM)VfdMediaTypeName(i));
206 	}
207 
208 	//	select 1.44MB as the default
209 
210 	SendDlgItemMessage(hDlg, IDC_MEDIATYPE, CB_SELECTSTRING,
211 		(WPARAM)-1, (LPARAM)VfdMediaTypeName(VFD_MEDIA_F3_1P4));
212 
213 	//	set up other controls
214 
215 	OnImage(hDlg, GetDlgItem(hDlg, IDC_IMAGEFILE));
216 }
217 
218 //
219 //	Path is changed -- check if the file exists
220 //
221 void OnImage(
222 	HWND			hDlg,
223 	HWND			hEdit)
224 {
225 	CHAR			buf[MAX_PATH];
226 	DWORD			file_attr;
227 	ULONG			image_size;
228 	VFD_FILETYPE	file_type;
229 	VFD_MEDIA		media_type;
230 
231 	DWORD			ret = ERROR_SUCCESS;
232 
233 	//	Store default file size
234 
235 	SetWindowLong(hDlg, DWL_USER, INVALID_FILE_SIZE);
236 
237 	//	get currently selected media type
238 
239 	media_type = (VFD_MEDIA)(SendDlgItemMessage(
240 		hDlg, IDC_MEDIATYPE, CB_GETCURSEL, 0, 0) + 1);
241 
242 	//	clear hint and description text
243 
244 	SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, NULL);
245 	SetDlgItemText(hDlg, IDC_IMAGEFILE_HINT, NULL);
246 
247 	//	get file name and file information
248 
249 	if (GetWindowText(hEdit, buf, sizeof(buf))) {
250 
251 		ret = VfdCheckImageFile(
252 			buf, &file_attr, &file_type, &image_size);
253 
254 		if (ret == ERROR_SUCCESS) {
255 
256 			//	use media type from image size
257 
258 			media_type = VfdLookupMedia(image_size);
259 		}
260 		else if (ret == ERROR_FILE_NOT_FOUND) {
261 
262 			//	new file
263 			//	use the parent directory attributes
264 
265 			PSTR p;
266 
267 			if ((p = strrchr(buf, '\\')) != NULL) {
268 				*p = '\0';
269 			}
270 
271 			file_attr	= GetFileAttributes(buf);
272 
273 			if (file_attr == INVALID_FILE_ATTRIBUTES) {
274 				//	directory access error
275 				EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
276 				SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, SystemMessage(ret));
277 				return;
278 			}
279 
280 			file_attr	&= ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY);
281 			image_size	= INVALID_FILE_SIZE;
282 			file_type	= VFD_FILETYPE_RAW;
283 		}
284 		else {
285 			//	file access error
286 			EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
287 			SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, SystemMessage(ret));
288 			return;
289 		}
290 
291 		//	make file description text
292 
293 		VfdMakeFileDesc(buf, sizeof(buf),
294 			file_type, image_size, file_attr);
295 
296 		//	set file description
297 
298 		SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, buf);
299 	}
300 	else {
301 
302 		//	filename is empty - RAM disk
303 
304 		file_attr	= 0;
305 		image_size	= INVALID_FILE_SIZE;
306 		file_type	= VFD_FILETYPE_NONE;
307 
308 		SetDlgItemText(hDlg, IDC_IMAGEFILE_DESC, "RAM");
309 	}
310 
311 	//	store the image size
312 
313 	SetWindowLong(hDlg, DWL_USER, image_size);
314 
315 	//	setup disktype controls
316 
317 	if (file_type != VFD_FILETYPE_RAW ||
318 		(file_attr & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_ENCRYPTED))) {
319 
320 		//	file cannot be opened directly -- RAM mode is forced
321 
322 		CheckRadioButton(hDlg, IDC_DISKTYPE_FILE,
323 			IDC_DISKTYPE_RAM, IDC_DISKTYPE_RAM);
324 
325 		EnableWindow(GetDlgItem(hDlg, IDC_DISKTYPE_FILE),	FALSE);
326 	}
327 	else {
328 		EnableWindow(GetDlgItem(hDlg, IDC_DISKTYPE_FILE),	TRUE);
329 	}
330 
331 	//	set OK button text
332 
333 	if (image_size == INVALID_FILE_SIZE) {
334 		//	file does not exist - OK button is "Create"
335 
336 		SetControlText(hDlg, IDOK, MSG_CREATE_BUTTON);
337 	}
338 	else {
339 		//	file exists - OK button is "Open"
340 
341 		SetControlText(hDlg, IDOK, MSG_OPEN_BUTTON);
342 	}
343 
344 	//	select media type
345 
346 	SendDlgItemMessage(hDlg, IDC_MEDIATYPE,
347 		CB_SETCURSEL, media_type - 1, 0);
348 
349 	OnMediaType(hDlg, GetDlgItem(hDlg, IDC_MEDIATYPE));
350 }
351 
352 //
353 //	Show open file dialog box
354 //
355 void OnBrowse(
356 	HWND			hDlg)
357 {
358 	OPENFILENAME	ofn;
359 	PSTR			title;
360 	PSTR			filter;
361 	CHAR			file[MAX_PATH];
362 	CHAR			dir[MAX_PATH];
363 	DWORD			len;
364 
365 	//	prepare title and filter text
366 
367 	title = ModuleMessage(MSG_OPEN_TITLE);
368 
369 	filter = ModuleMessage(MSG_OPEN_FILTER);
370 
371 	if (filter) {
372 		PSTR p = filter;
373 
374 		do {
375 			if (*p == '|') {
376 				*p = '\0';
377 			}
378 		}
379 		while (*(++p));
380 	}
381 
382 	//	get current file name from the control
383 
384 	ZeroMemory(file, sizeof(file));
385 	ZeroMemory(dir, sizeof(dir));
386 
387 	len = GetDlgItemText(hDlg, IDC_IMAGEFILE, file, sizeof(file));
388 
389 	if (len && file[len - 1] == '\\') {
390 		strcpy(dir, file);
391 		ZeroMemory(file, sizeof(file));
392 	}
393 
394 	// prepare OPENFILENAME structure
395 
396 	ZeroMemory(&ofn, sizeof(ofn));
397 
398 	ofn.lStructSize = IS_WINDOWS_NT() ?
399 		OPENFILENAME_SIZE_VERSION_400 : sizeof(ofn);
400 
401 	ofn.hwndOwner	= hDlg;
402 	ofn.lpstrFilter = filter ? filter : FALLBACK_IMAGE_FILTER;
403 	ofn.lpstrFile	= file;
404 	ofn.nMaxFile	= sizeof(file);
405 	ofn.lpstrInitialDir = dir;
406 	ofn.lpstrTitle	= title ? title : FALLBACK_IMAGE_TITLE;
407 	ofn.Flags		= OFN_ENABLESIZING | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
408 
409 	//	show the open file dialog box
410 
411 	if (GetOpenFileName(&ofn)) {
412 		SetDlgItemText(hDlg, IDC_IMAGEFILE, file);
413 		SetFocus(GetDlgItem(hDlg, IDC_IMAGEFILE));
414 	}
415 
416 	//	release text buffers
417 
418 	if (filter) {
419 		LocalFree(filter);
420 	}
421 
422 	if (title) {
423 		LocalFree(title);
424 	}
425 }
426 
427 //
428 //	Disk type is changed
429 //
430 void OnDiskType(
431 	HWND			hDlg,
432 	HWND			hRadio)
433 {
434 	UNREFERENCED_PARAMETER(hDlg);
435 	UNREFERENCED_PARAMETER(hRadio);
436 }
437 
438 //
439 //	Media type is changed
440 //
441 void OnMediaType(
442 	HWND			hDlg,
443 	HWND			hCombo)
444 {
445 	VFD_MEDIA		media_type;
446 	ULONG			media_size;
447 	ULONG			image_size;
448 
449 	image_size = GetWindowLong(hDlg, DWL_USER);
450 
451 	if (image_size == INVALID_FILE_SIZE) {
452 		return;
453 	}
454 
455 	media_type = (VFD_MEDIA)(SendMessage(
456 		hCombo, CB_GETCURSEL, 0, 0) + 1);
457 
458 	if (media_type == 0) {
459 		return;
460 	}
461 
462 	media_size = VfdGetMediaSize(media_type);
463 
464 	if (media_size > image_size) {
465 		//	selected media is too large
466 		SetControlText(hDlg, IDC_IMAGEFILE_HINT, MSG_FILE_TOO_SMALL);
467 		EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
468 		return;
469 	}
470 	else if (media_size < image_size) {
471 		SetControlText(hDlg, IDC_IMAGEFILE_HINT, MSG_SIZE_MISMATCH);
472 	}
473 	else {
474 		SetDlgItemText(hDlg, IDC_IMAGEFILE_HINT, NULL);
475 	}
476 
477 	EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
478 }
479 
480 //
481 //	Write Protect check box is clicked
482 //
483 void OnProtect(
484 	HWND			hDlg,
485 	HWND			hCheck)
486 {
487 	UNREFERENCED_PARAMETER(hDlg);
488 	UNREFERENCED_PARAMETER(hCheck);
489 }
490 
491 //
492 //	Create / open an image
493 //
494 DWORD OnOK(
495 	HWND			hDlg)
496 {
497 	CHAR			file_name[MAX_PATH];
498 	VFD_DISKTYPE	disk_type;
499 	VFD_MEDIA		media_type;
500 	VFD_FLAGS		image_flags;
501 	HANDLE			hDevice;
502 	DWORD			ret;
503 
504 	//	get the disk type
505 
506 	if (IsDlgButtonChecked(hDlg, IDC_DISKTYPE_FILE) == BST_CHECKED) {
507 		disk_type = VFD_DISKTYPE_FILE;
508 	}
509 	else {
510 		disk_type = VFD_DISKTYPE_RAM;
511 	}
512 
513 	//	get the media type
514 
515 	media_type = (VFD_MEDIA)(SendDlgItemMessage(
516 		hDlg, IDC_MEDIATYPE, CB_GETCURSEL, 0, 0) + 1);
517 
518 	//	get the protect flag
519 
520 	if (IsDlgButtonChecked(hDlg, IDC_OPEN_PROTECTED) == BST_CHECKED) {
521 		image_flags = VFD_FLAG_WRITE_PROTECTED;
522 	}
523 	else {
524 		image_flags = 0;
525 	}
526 
527 	//	get the image name to create
528 
529 	if (GetDlgItemText(hDlg, IDC_IMAGEFILE, file_name, sizeof(file_name))) {
530 
531 		//	file is specified
532 
533 		if (GetWindowLong(hDlg, DWL_USER) == INVALID_FILE_SIZE) {
534 
535 			//	create a new image
536 
537 			ret = VfdCreateImageFile(
538 				file_name, media_type, VFD_FILETYPE_RAW, FALSE);
539 
540 			if (ret != ERROR_SUCCESS) {
541 				goto exit_func;
542 			}
543 		}
544 	}
545 
546 	//	open the image
547 
548 	hDevice = VfdOpenDevice(GetWindowLong(hDlg, GWL_USERDATA));
549 
550 	if (hDevice == INVALID_HANDLE_VALUE) {
551 		ret = GetLastError();
552 		goto exit_func;
553 	}
554 
555 	ret = VfdOpenImage(
556 		hDevice, file_name, disk_type, media_type, image_flags);
557 
558 	CloseHandle(hDevice);
559 
560 exit_func:
561 	if (ret != ERROR_SUCCESS) {
562 
563 		//	show error message
564 
565 		MessageBox(hDlg, SystemMessage(ret),
566 			VFD_MSGBOX_TITLE, MB_ICONSTOP);
567 	}
568 
569 	return ret;
570 }
571