xref: /reactos/dll/win32/serialui/serialui.c (revision 80774a2f)
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS SerialUI DLL
4  * FILE:        serialui.c
5  * PUROPSE:     A dialog box to configure COM port.
6  *              Functions to set (and get too) default configuration.
7  * PROGRAMMERS: Saveliy Tretiakov (saveliyt@mail.ru)
8  * REVISIONS:
9  *              ST   (05/04/2005) Created. Implemented drvCommConfigDialog.
10  */
11 
12 #include "serialui.h"
13 
14 static HINSTANCE hDllInstance;
15 
16 /************************************
17  *
18  *  DATA
19  *
20  ************************************/
21 
22 const DWORD Bauds[] = {
23 	CBR_110,
24 	CBR_300,
25 	CBR_600,
26 	CBR_1200,
27 	CBR_2400,
28 	CBR_4800,
29 	CBR_9600,
30 	CBR_14400,
31 	CBR_19200,
32 	CBR_38400,
33 	CBR_56000,
34 	CBR_57600,
35 	CBR_115200,
36 	CBR_128000,
37 	CBR_256000,
38 	0
39 };
40 
41 const BYTE ByteSizes[] = {
42 	5,
43 	6,
44 	7,
45 	8,
46 	0
47 };
48 
49 
50 const PARITY_INFO Parities[] = {
51 	{ EVENPARITY, IDS_EVENPARITY },
52 	{ MARKPARITY, IDS_MARKPARITY },
53 	{ NOPARITY, IDS_NOPARITY },
54 	{ ODDPARITY, IDS_ODDPARITY },
55 	{ SPACEPARITY, IDS_SPACEPARITY },
56 	{ 0, 0 }
57 };
58 
59 const STOPBIT_INFO StopBits[] = {
60 	{ ONESTOPBIT, IDS_ONESTOPBIT },
61 	{ ONE5STOPBITS, IDS_ONE5STOPBITS },
62 	{ TWOSTOPBITS, IDS_TWOSTOPBITS },
63 	{ 0, 0 }
64 };
65 
66 
67 /************************************
68  *
69  *  DLLMAIN
70  *
71  ************************************/
72 
73 BOOL
74 WINAPI
75 DllMain(HINSTANCE hInstance,
76 	DWORD dwReason,
77 	LPVOID reserved)
78 {
79 	if(dwReason==DLL_PROCESS_ATTACH)
80 	{
81 		hDllInstance = hInstance;
82 	}
83 	else if(dwReason==DLL_THREAD_ATTACH)
84 	{
85 		DisableThreadLibraryCalls(hInstance);
86 	}
87 
88 	return TRUE;
89 }
90 
91 
92 /************************************
93  *
94  *  EXPORTS
95  *
96  ************************************/
97 
98 /*
99  * @implemented
100  */
101 DWORD WINAPI drvCommConfigDialogW(LPCWSTR lpszDevice,
102 	HWND hWnd,
103 	LPCOMMCONFIG lpCommConfig)
104 {
105 	DIALOG_INFO DialogInfo;
106 
107 	if(!lpszDevice || !lpCommConfig)
108 	{
109 		return ERROR_INVALID_PARAMETER;
110 	}
111 
112 	DialogInfo.lpszDevice = lpszDevice;
113 	DialogInfo.lpCC = lpCommConfig;
114 
115 	return DialogBoxParamW(hDllInstance, MAKEINTRESOURCEW(IDD_COMMDLG),
116 					hWnd, CommDlgProc, (LPARAM)&DialogInfo);
117 }
118 
119 /*
120  * @implemented
121  */
122 DWORD WINAPI drvCommConfigDialogA(LPCSTR lpszDevice,
123 	HWND hWnd,
124 	LPCOMMCONFIG lpCommConfig)
125 {
126 	BOOL result;
127 	UINT len;
128 	WCHAR *wstr;
129 
130 	len = MultiByteToWideChar(CP_ACP, 0, lpszDevice, -1, NULL, 0);
131 	if((wstr = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR))))
132 	{
133 		MultiByteToWideChar(CP_ACP, 0, lpszDevice, -1, wstr, len);
134 		result = drvCommConfigDialogW(wstr, hWnd, lpCommConfig);
135 		HeapFree(GetProcessHeap(), 0, wstr);
136 		return result;
137 	}
138 	else
139 		return ERROR_NOT_ENOUGH_MEMORY;
140 }
141 
142 /*
143  * @unimplemented
144  */
145 DWORD WINAPI drvSetDefaultCommConfigW(LPCWSTR lpszDevice,
146 	LPCOMMCONFIG lpCommConfig,
147 	DWORD dwSize)
148 {
149 	UNIMPLEMENTED
150 }
151 
152 /*
153  * @unimplemented
154  */
155 DWORD WINAPI drvSetDefaultCommConfigA(LPCSTR lpszDevice,
156 	LPCOMMCONFIG lpCommConfig,
157 	DWORD dwSize)
158 {
159 	UNIMPLEMENTED
160 }
161 
162 /*
163  * @unimplemented
164  */
165 DWORD WINAPI drvGetDefaultCommConfigW(LPCWSTR lpszDevice,
166 	LPCOMMCONFIG lpCommConfig,
167 	LPDWORD lpdwSize)
168 {
169 	UNIMPLEMENTED
170 }
171 
172 /*
173  * @unimplemented
174  */
175 DWORD WINAPI drvGetDefaultCommConfigA(LPCSTR lpszDevice,
176 	LPCOMMCONFIG lpCommConfig,
177 	LPDWORD lpdwSize)
178 {
179 	UNIMPLEMENTED
180 }
181 
182 
183 /************************************
184  *
185  *  INTERNALS
186  *
187  ************************************/
188 
189 INT_PTR
190 CALLBACK
191 CommDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
192 {
193 	LPDIALOG_INFO lpDlgInfo = NULL;
194 	HWND hBox;
195 
196 	switch (Msg)
197 	{
198 
199 		case WM_INITDIALOG:
200 		{
201 			WCHAR wstr[255];
202 			RECT rc, rcDlg, rcOwner;
203 			HWND hOwner;
204 			INT i;
205 
206 			lpDlgInfo = (LPDIALOG_INFO)lParam;
207 			SetWindowLongPtrW(hDlg, DWL_USER, (LONG_PTR)lpDlgInfo);
208 
209 			/* Set title */
210 			if(LoadStringW(hDllInstance, IDS_TITLE, wstr, sizeof(wstr) / sizeof(wstr[0])))
211 			{
212     				SetWindowTextW(hDlg, wstr);
213 			}
214 
215                         /* FIXME - this won't work correctly systems with multiple monitors! */
216                         if(!(hOwner = GetParent(hDlg)))
217 				hOwner = GetDesktopWindow();
218 
219 			/* Position dialog in the center of owner window */
220 			GetWindowRect(hOwner, &rcOwner);
221 			GetWindowRect(hDlg, &rcDlg);
222 			CopyRect(&rc, &rcOwner);
223 			OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top);
224 			OffsetRect(&rc, -rc.left, -rc.top);
225 			OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
226 			SetWindowPos(hDlg, HWND_TOP,
227 				rcOwner.left + (rc.right / 2),
228 				rcOwner.top + (rc.bottom / 2),
229 				0, 0, SWP_NOSIZE);
230 
231 			/* Initialize baud rate combo */
232 			if(!(hBox = GetDlgItem(hDlg, IDC_BAUDRATE)))
233 				EndDialog(hDlg, ERROR_CANCELLED);
234 
235 			for(i = 0; Bauds[i]; i++)
236 			{
237                                 wsprintf(wstr, L"%d", Bauds[i]);
238                                 SendMessageW(hBox, CB_INSERTSTRING, (WPARAM)i, (LPARAM)wstr);
239 				if(Bauds[i] == lpDlgInfo->lpCC->dcb.BaudRate)
240 					SendMessageW(hBox, CB_SETCURSEL, (WPARAM)i, 0);
241 			}
242 
243 			if(SendMessageW(hBox, CB_GETCURSEL, 0, 0) == CB_ERR)
244 				SendMessageW(hBox, CB_SETCURSEL, DEFAULT_BAUD_INDEX, 0);
245 
246 			/* Initialize byte size combo */
247 			if(!(hBox = GetDlgItem(hDlg, IDC_BYTESIZE)))
248 				EndDialog(hDlg, ERROR_CANCELLED);
249 
250 			for(i = 0; ByteSizes[i]; i++)
251 			{
252                                 wsprintf(wstr, L"%d", Bauds[i]);
253                                 SendMessageW(hBox, CB_INSERTSTRING, (WPARAM)i, (LPARAM)wstr);
254 				if(ByteSizes[i] == lpDlgInfo->lpCC->dcb.ByteSize)
255 					SendMessageW(hBox, CB_SETCURSEL, (WPARAM)i, 0);
256 			}
257 
258 			if(SendMessageW(hBox, CB_GETCURSEL, 0, 0) == CB_ERR)
259 				SendMessageW(hBox, CB_SETCURSEL, DEFAULT_BYTESIZE_INDEX, 0);
260 
261 			/* Initialize parity combo */
262 			if(!(hBox = GetDlgItem(hDlg, IDC_PARITY)))
263 				EndDialog(hDlg, ERROR_CANCELLED);
264 
265 			for(i = 0; Parities[i].StrId; i++)
266 			{
267 				if(LoadStringW(hDllInstance, Parities[i].StrId, wstr, sizeof(wstr) / sizeof(wstr[0])))
268 				{
269 					SendMessageW(hBox, CB_INSERTSTRING, (WPARAM)i, (LPARAM)wstr);
270 					if(Parities[i].Parity == lpDlgInfo->lpCC->dcb.Parity)
271 						SendMessageW(hBox, CB_SETCURSEL, (WPARAM)i, 0);
272 				}
273 			}
274 
275 			if(SendMessageW(hBox, CB_GETCURSEL, 0, 0)==CB_ERR)
276 				SendMessageW(hBox, CB_SETCURSEL, DEFAULT_PARITY_INDEX, 0);
277 
278 			/* Initialize stop bits combo */
279 			if(!(hBox = GetDlgItem(hDlg, IDC_STOPBITS)))
280 				EndDialog(hDlg, ERROR_CANCELLED);
281 
282 			for(i = 0; StopBits[i].StrId; i++)
283 			{
284 				if(LoadStringW(hDllInstance, StopBits[i].StrId, wstr, sizeof(wstr) / sizeof(wstr[0])))
285 				{
286 					SendMessageW(hBox, CB_INSERTSTRING, (WPARAM)i, (LPARAM)wstr);
287 					if(StopBits[i].StopBit == lpDlgInfo->lpCC->dcb.StopBits)
288 						SendMessageW(hBox, CB_SETCURSEL, (WPARAM)i, 0);
289 				}
290 			}
291 
292 			if(SendMessageW(hBox, CB_GETCURSEL, 0, 0)==CB_ERR)
293 				SendMessageW(hBox, CB_SETCURSEL, DEFAULT_STOPBITS_INDEX, 0);
294 
295 			/* Initialize flow control combo */
296 			if(!(hBox = GetDlgItem(hDlg, IDC_FLOW)))
297 				EndDialog(hDlg, ERROR_CANCELLED);
298 
299 			if(LoadStringW(hDllInstance, IDS_FC_NO, wstr, sizeof(wstr) / sizeof(wstr[0])))
300 			{
301 				SendMessageW(hBox, CB_INSERTSTRING, 0, (LPARAM)wstr);
302 				SendMessageW(hBox, CB_SETCURSEL, 0, 0);
303 				lpDlgInfo->InitialFlowIndex = 0;
304 			}
305 
306 
307 			if(LoadStringW(hDllInstance, IDS_FC_CTSRTS, wstr, sizeof(wstr) / sizeof(wstr[0])))
308 			{
309 				SendMessageW(hBox, CB_INSERTSTRING, 1, (LPARAM)wstr);
310 				if(lpDlgInfo->lpCC->dcb.fRtsControl == RTS_CONTROL_HANDSHAKE
311 					|| lpDlgInfo->lpCC->dcb.fOutxCtsFlow != FALSE)
312 				{
313 					SendMessageW(hBox, CB_SETCURSEL, 1, 0);
314 					lpDlgInfo->InitialFlowIndex = 1;
315 				}
316 			}
317 
318 			if(LoadStringW(hDllInstance, IDS_FC_XONXOFF, wstr, sizeof(wstr) / sizeof(wstr[0])))
319 			{
320 				SendMessageW(hBox, CB_INSERTSTRING, 2, (LPARAM)wstr);
321 				if(lpDlgInfo->lpCC->dcb.fOutX || lpDlgInfo->lpCC->dcb.fInX)
322 				{
323 					SendMessageW(hBox, CB_SETCURSEL, 2, 0);
324 					lpDlgInfo->InitialFlowIndex = 2;
325 				}
326 			}
327 
328 			/* Set focus */
329 			SetFocus(GetDlgItem(hDlg, IDC_OKBTN));
330 
331 			return FALSE;
332 		} /* WM_INITDIALOG */
333 
334 		case WM_COMMAND:
335 		{
336 			switch(wParam)
337 			{
338 				case IDC_CANCELBTN:
339 					EndDialog(hDlg, ERROR_CANCELLED);
340 					break;
341 				case IDC_OKBTN:
342 					OkButton(hDlg);
343 					EndDialog(hDlg, ERROR_SUCCESS);
344 					break;
345 			}
346 			return TRUE;
347 		} /* WM_COMMAND */
348 
349 		case WM_CLOSE:
350 		{
351 			EndDialog(hDlg, ERROR_CANCELLED);
352 			return TRUE;
353 		} /* WM_CLOSE */
354 
355 		default:
356 			return FALSE;
357 	}
358 
359 }
360 
361 
362 VOID OkButton(HWND hDlg)
363 {
364 	LPDIALOG_INFO lpDlgInfo;
365 	UINT Index;
366 
367 	lpDlgInfo = (LPDIALOG_INFO) GetWindowLongPtrW(hDlg, DWL_USER);
368 
369 	/* Baud rate */
370 	Index = SendMessageW(GetDlgItem(hDlg, IDC_BAUDRATE), CB_GETCURSEL, 0, 0);
371 	lpDlgInfo->lpCC->dcb.BaudRate = Bauds[Index];
372 
373 	/* Byte size */
374 	Index = SendMessageW(GetDlgItem(hDlg, IDC_BYTESIZE), CB_GETCURSEL, 0, 0);
375 	lpDlgInfo->lpCC->dcb.ByteSize = ByteSizes[Index];
376 
377 	/* Parity */
378 	Index = SendMessageW(GetDlgItem(hDlg, IDC_PARITY), CB_GETCURSEL, 0, 0);
379 	lpDlgInfo->lpCC->dcb.Parity = Parities[Index].Parity;
380 
381 	/* Stop bits */
382 	Index = SendMessageW(GetDlgItem(hDlg, IDC_STOPBITS), CB_GETCURSEL, 0, 0);
383 	lpDlgInfo->lpCC->dcb.StopBits = StopBits[Index].StopBit;
384 
385 	/* Flow Control */
386 	Index = SendMessageW(GetDlgItem(hDlg, IDC_FLOW), CB_GETCURSEL, 0, 0);
387 	if(lpDlgInfo->InitialFlowIndex != Index)
388 	{
389 		switch(Index)
390 		{
391 			case 0: /* NO */
392 				lpDlgInfo->lpCC->dcb.fDtrControl = DTR_CONTROL_DISABLE;
393 				lpDlgInfo->lpCC->dcb.fRtsControl = RTS_CONTROL_DISABLE;
394 				lpDlgInfo->lpCC->dcb.fOutxCtsFlow = FALSE;
395 				lpDlgInfo->lpCC->dcb.fOutxDsrFlow = FALSE;
396 				lpDlgInfo->lpCC->dcb.fOutX = FALSE;
397 				lpDlgInfo->lpCC->dcb.fInX = FALSE;
398 				break;
399 			case 1: /* CTS/RTS */
400 				lpDlgInfo->lpCC->dcb.fDtrControl = DTR_CONTROL_DISABLE;
401 				lpDlgInfo->lpCC->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
402 				lpDlgInfo->lpCC->dcb.fOutxCtsFlow = TRUE;
403 				lpDlgInfo->lpCC->dcb.fOutxDsrFlow = FALSE;
404 				lpDlgInfo->lpCC->dcb.fOutX = FALSE;
405 				lpDlgInfo->lpCC->dcb.fInX = FALSE;
406 				break;
407 			case 2: /* XON/XOFF */
408 				lpDlgInfo->lpCC->dcb.fDtrControl = DTR_CONTROL_DISABLE;
409 				lpDlgInfo->lpCC->dcb.fRtsControl = RTS_CONTROL_DISABLE;
410 				lpDlgInfo->lpCC->dcb.fOutxCtsFlow = FALSE;
411 				lpDlgInfo->lpCC->dcb.fOutxDsrFlow = FALSE;
412 				lpDlgInfo->lpCC->dcb.fOutX = TRUE;
413 				lpDlgInfo->lpCC->dcb.fInX = TRUE;
414 				break;
415 		}
416 	}
417 }
418