Sync with trunk r58151 to bring the latest changes from Amine and Timo.
[reactos.git] / dll / win32 / serialui / serialui.c
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, (DLGPROC)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 LRESULT CommDlgProc(HWND hDlg,
190 UINT Msg,
191 WPARAM wParam,
192 LPARAM lParam)
193 {
194 LPDIALOG_INFO lpDlgInfo = NULL;
195 HWND hBox;
196
197 switch (Msg)
198 {
199
200 case WM_INITDIALOG:
201 {
202 WCHAR wstr[255];
203 RECT rc, rcDlg, rcOwner;
204 HWND hOwner;
205 INT i;
206
207 lpDlgInfo = (LPDIALOG_INFO)lParam;
208 SetWindowLongPtrW(hDlg, DWL_USER, (LONG_PTR)lpDlgInfo);
209
210 /* Set title */
211 if(LoadStringW(hDllInstance, IDS_TITLE, wstr, sizeof(wstr) / sizeof(wstr[0])))
212 {
213 SetWindowTextW(hDlg, wstr);
214 }
215
216 /* FIXME - this won't work correctly systems with multiple monitors! */
217 if(!(hOwner = GetParent(hDlg)))
218 hOwner = GetDesktopWindow();
219
220 /* Position dialog in the center of owner window */
221 GetWindowRect(hOwner, &rcOwner);
222 GetWindowRect(hDlg, &rcDlg);
223 CopyRect(&rc, &rcOwner);
224 OffsetRect(&rcDlg, -rcDlg.left, -rcDlg.top);
225 OffsetRect(&rc, -rc.left, -rc.top);
226 OffsetRect(&rc, -rcDlg.right, -rcDlg.bottom);
227 SetWindowPos(hDlg, HWND_TOP,
228 rcOwner.left + (rc.right / 2),
229 rcOwner.top + (rc.bottom / 2),
230 0, 0, SWP_NOSIZE);
231
232 /* Initialize baud rate combo */
233 if(!(hBox = GetDlgItem(hDlg, IDC_BAUDRATE)))
234 EndDialog(hDlg, ERROR_CANCELLED);
235
236 for(i = 0; Bauds[i]; i++)
237 {
238 wsprintf(wstr, L"%d", Bauds[i]);
239 SendMessageW(hBox, CB_INSERTSTRING, (WPARAM)i, (LPARAM)wstr);
240 if(Bauds[i] == lpDlgInfo->lpCC->dcb.BaudRate)
241 SendMessageW(hBox, CB_SETCURSEL, (WPARAM)i, 0);
242 }
243
244 if(SendMessageW(hBox, CB_GETCURSEL, 0, 0) == CB_ERR)
245 SendMessageW(hBox, CB_SETCURSEL, DEFAULT_BAUD_INDEX, 0);
246
247 /* Initialize byte size combo */
248 if(!(hBox = GetDlgItem(hDlg, IDC_BYTESIZE)))
249 EndDialog(hDlg, ERROR_CANCELLED);
250
251 for(i = 0; ByteSizes[i]; i++)
252 {
253 wsprintf(wstr, L"%d", Bauds[i]);
254 SendMessageW(hBox, CB_INSERTSTRING, (WPARAM)i, (LPARAM)wstr);
255 if(ByteSizes[i] == lpDlgInfo->lpCC->dcb.ByteSize)
256 SendMessageW(hBox, CB_SETCURSEL, (WPARAM)i, 0);
257 }
258
259 if(SendMessageW(hBox, CB_GETCURSEL, 0, 0) == CB_ERR)
260 SendMessageW(hBox, CB_SETCURSEL, DEFAULT_BYTESIZE_INDEX, 0);
261
262 /* Initialize parity combo */
263 if(!(hBox = GetDlgItem(hDlg, IDC_PARITY)))
264 EndDialog(hDlg, ERROR_CANCELLED);
265
266 for(i = 0; Parities[i].StrId; i++)
267 {
268 if(LoadStringW(hDllInstance, Parities[i].StrId, wstr, sizeof(wstr) / sizeof(wstr[0])))
269 {
270 SendMessageW(hBox, CB_INSERTSTRING, (WPARAM)i, (LPARAM)wstr);
271 if(Parities[i].Parity == lpDlgInfo->lpCC->dcb.Parity)
272 SendMessageW(hBox, CB_SETCURSEL, (WPARAM)i, 0);
273 }
274 }
275
276 if(SendMessageW(hBox, CB_GETCURSEL, 0, 0)==CB_ERR)
277 SendMessageW(hBox, CB_SETCURSEL, DEFAULT_PARITY_INDEX, 0);
278
279 /* Initialize stop bits combo */
280 if(!(hBox = GetDlgItem(hDlg, IDC_STOPBITS)))
281 EndDialog(hDlg, ERROR_CANCELLED);
282
283 for(i = 0; StopBits[i].StrId; i++)
284 {
285 if(LoadStringW(hDllInstance, StopBits[i].StrId, wstr, sizeof(wstr) / sizeof(wstr[0])))
286 {
287 SendMessageW(hBox, CB_INSERTSTRING, (WPARAM)i, (LPARAM)wstr);
288 if(StopBits[i].StopBit == lpDlgInfo->lpCC->dcb.StopBits)
289 SendMessageW(hBox, CB_SETCURSEL, (WPARAM)i, 0);
290 }
291 }
292
293 if(SendMessageW(hBox, CB_GETCURSEL, 0, 0)==CB_ERR)
294 SendMessageW(hBox, CB_SETCURSEL, DEFAULT_STOPBITS_INDEX, 0);
295
296 /* Initialize flow control combo */
297 if(!(hBox = GetDlgItem(hDlg, IDC_FLOW)))
298 EndDialog(hDlg, ERROR_CANCELLED);
299
300 if(LoadStringW(hDllInstance, IDS_FC_NO, wstr, sizeof(wstr) / sizeof(wstr[0])))
301 {
302 SendMessageW(hBox, CB_INSERTSTRING, 0, (LPARAM)wstr);
303 SendMessageW(hBox, CB_SETCURSEL, 0, 0);
304 lpDlgInfo->InitialFlowIndex = 0;
305 }
306
307
308 if(LoadStringW(hDllInstance, IDS_FC_CTSRTS, wstr, sizeof(wstr) / sizeof(wstr[0])))
309 {
310 SendMessageW(hBox, CB_INSERTSTRING, 1, (LPARAM)wstr);
311 if(lpDlgInfo->lpCC->dcb.fRtsControl == RTS_CONTROL_HANDSHAKE
312 || lpDlgInfo->lpCC->dcb.fOutxCtsFlow == TRUE)
313 {
314 SendMessageW(hBox, CB_SETCURSEL, 1, 0);
315 lpDlgInfo->InitialFlowIndex = 1;
316 }
317 }
318
319 if(LoadStringW(hDllInstance, IDS_FC_XONXOFF, wstr, sizeof(wstr) / sizeof(wstr[0])))
320 {
321 SendMessageW(hBox, CB_INSERTSTRING, 2, (LPARAM)wstr);
322 if(lpDlgInfo->lpCC->dcb.fOutX || lpDlgInfo->lpCC->dcb.fInX)
323 {
324 SendMessageW(hBox, CB_SETCURSEL, 2, 0);
325 lpDlgInfo->InitialFlowIndex = 2;
326 }
327 }
328
329 /* Set focus */
330 SetFocus(GetDlgItem(hDlg, IDC_OKBTN));
331
332 return FALSE;
333 } /* WM_INITDIALOG */
334
335 case WM_COMMAND:
336 {
337 switch(wParam)
338 {
339 case IDC_CANCELBTN:
340 EndDialog(hDlg, ERROR_CANCELLED);
341 break;
342 case IDC_OKBTN:
343 OkButton(hDlg);
344 EndDialog(hDlg, ERROR_SUCCESS);
345 break;
346 }
347 return TRUE;
348 } /* WM_COMMAND */
349
350 case WM_CLOSE:
351 {
352 EndDialog(hDlg, ERROR_CANCELLED);
353 return TRUE;
354 } /* WM_CLOSE */
355
356 default:
357 return FALSE;
358 }
359
360 }
361
362
363 VOID OkButton(HWND hDlg)
364 {
365 LPDIALOG_INFO lpDlgInfo;
366 UINT Index;
367
368 lpDlgInfo = (LPDIALOG_INFO) GetWindowLongPtrW(hDlg, DWL_USER);
369
370 /* Baud rate */
371 Index = SendMessageW(GetDlgItem(hDlg, IDC_BAUDRATE), CB_GETCURSEL, 0, 0);
372 lpDlgInfo->lpCC->dcb.BaudRate = Bauds[Index];
373
374 /* Byte size */
375 Index = SendMessageW(GetDlgItem(hDlg, IDC_BYTESIZE), CB_GETCURSEL, 0, 0);
376 lpDlgInfo->lpCC->dcb.ByteSize = ByteSizes[Index];
377
378 /* Parity */
379 Index = SendMessageW(GetDlgItem(hDlg, IDC_PARITY), CB_GETCURSEL, 0, 0);
380 lpDlgInfo->lpCC->dcb.Parity = Parities[Index].Parity;
381
382 /* Stop bits */
383 Index = SendMessageW(GetDlgItem(hDlg, IDC_STOPBITS), CB_GETCURSEL, 0, 0);
384 lpDlgInfo->lpCC->dcb.StopBits = StopBits[Index].StopBit;
385
386 /* Flow Control */
387 Index = SendMessageW(GetDlgItem(hDlg, IDC_FLOW), CB_GETCURSEL, 0, 0);
388 if(lpDlgInfo->InitialFlowIndex != Index)
389 {
390 switch(Index)
391 {
392 case 0: /* NO */
393 lpDlgInfo->lpCC->dcb.fDtrControl = DTR_CONTROL_DISABLE;
394 lpDlgInfo->lpCC->dcb.fRtsControl = RTS_CONTROL_DISABLE;
395 lpDlgInfo->lpCC->dcb.fOutxCtsFlow = FALSE;
396 lpDlgInfo->lpCC->dcb.fOutxDsrFlow = FALSE;
397 lpDlgInfo->lpCC->dcb.fOutX = FALSE;
398 lpDlgInfo->lpCC->dcb.fInX = FALSE;
399 break;
400 case 1: /* CTS/RTS */
401 lpDlgInfo->lpCC->dcb.fDtrControl = DTR_CONTROL_DISABLE;
402 lpDlgInfo->lpCC->dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
403 lpDlgInfo->lpCC->dcb.fOutxCtsFlow = TRUE;
404 lpDlgInfo->lpCC->dcb.fOutxDsrFlow = FALSE;
405 lpDlgInfo->lpCC->dcb.fOutX = FALSE;
406 lpDlgInfo->lpCC->dcb.fInX = FALSE;
407 break;
408 case 2: /* XON/XOFF */
409 lpDlgInfo->lpCC->dcb.fDtrControl = DTR_CONTROL_DISABLE;
410 lpDlgInfo->lpCC->dcb.fRtsControl = RTS_CONTROL_DISABLE;
411 lpDlgInfo->lpCC->dcb.fOutxCtsFlow = FALSE;
412 lpDlgInfo->lpCC->dcb.fOutxDsrFlow = FALSE;
413 lpDlgInfo->lpCC->dcb.fOutX = TRUE;
414 lpDlgInfo->lpCC->dcb.fInX = TRUE;
415 break;
416 }
417 }
418 }