1 /*
2 * DEC 93 Erik Bos <erik@xs4all.nl>
3 *
4 * Copyright 1996 Marcus Meissner
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winerror.h"
33 #include "winioctl.h"
34 #include "ddk/ntddser.h"
35
36 #include "wine/server.h"
37 #include "wine/unicode.h"
38
39 #include "wine/debug.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(comm);
42
43 /***********************************************************************
44 * COMM_Parse* (Internal)
45 *
46 * The following COMM_Parse* functions are used by the BuildCommDCB
47 * functions to help parse the various parts of the device control string.
48 */
49 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
50 {
51 static const WCHAR comW[] = {'C','O','M',0};
52
53 /* The device control string may optionally start with "COMx" followed
54 by an optional ':' and spaces. */
55 if(!strncmpiW(ptr, comW, 3))
56 {
57 ptr += 3;
58
59 /* Allow any com port above 0 as Win 9x does (NT only allows
60 values for com ports which are actually present) */
61 if(*ptr < '1' || *ptr > '9')
62 return NULL;
63
64 /* Advance pointer past port number */
65 while(*ptr >= '' && *ptr <= '9') ptr++;
66
67 /* The com port number must be followed by a ':' or ' ' */
68 if(*ptr != ':' && *ptr != ' ')
69 return NULL;
70
71 /* Advance pointer to beginning of next parameter */
72 while(*ptr == ' ') ptr++;
73 if(*ptr == ':')
74 {
75 ptr++;
76 while(*ptr == ' ') ptr++;
77 }
78 }
79 /* The device control string must not start with a space. */
80 else if(*ptr == ' ')
81 return NULL;
82
83 return ptr;
84 }
85
86 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
87 {
88 if(*ptr < '' || *ptr > '9') return NULL;
89 *lpnumber = strtoulW(ptr, NULL, 10);
90 while(*ptr >= '' && *ptr <= '9') ptr++;
91 return ptr;
92 }
93
94 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
95 {
96 /* Contrary to what you might expect, Windows only sets the Parity
97 member of DCB and not fParity even when parity is specified in the
98 device control string */
99
100 switch(toupperW(*ptr++))
101 {
102 case 'E':
103 *lpparity = EVENPARITY;
104 break;
105 case 'M':
106 *lpparity = MARKPARITY;
107 break;
108 case 'N':
109 *lpparity = NOPARITY;
110 break;
111 case 'O':
112 *lpparity = ODDPARITY;
113 break;
114 case 'S':
115 *lpparity = SPACEPARITY;
116 break;
117 default:
118 return NULL;
119 }
120
121 return ptr;
122 }
123
124 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
125 {
126 DWORD temp;
127
128 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
129 return NULL;
130
131 if(temp >= 5 && temp <= 8)
132 {
133 *lpbytesize = temp;
134 return ptr;
135 }
136 else
137 return NULL;
138 }
139
140 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
141 {
142 DWORD temp;
143 static const WCHAR stopbits15W[] = {'1','.','5',0};
144
145 if(!strncmpW(stopbits15W, ptr, 3))
146 {
147 ptr += 3;
148 *lpstopbits = ONE5STOPBITS;
149 }
150 else
151 {
152 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
153 return NULL;
154
155 if(temp == 1)
156 *lpstopbits = ONESTOPBIT;
157 else if(temp == 2)
158 *lpstopbits = TWOSTOPBITS;
159 else
160 return NULL;
161 }
162
163 return ptr;
164 }
165
166 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
167 {
168 static const WCHAR onW[] = {'o','n',0};
169 static const WCHAR offW[] = {'o','f','f',0};
170
171 if(!strncmpiW(onW, ptr, 2))
172 {
173 ptr += 2;
174 *lponoff = 1;
175 }
176 else if(!strncmpiW(offW, ptr, 3))
177 {
178 ptr += 3;
179 *lponoff = 0;
180 }
181 else
182 return NULL;
183
184 return ptr;
185 }
186
187 /***********************************************************************
188 * COMM_BuildOldCommDCB (Internal)
189 *
190 * Build a DCB using the old style settings string eg: "96,n,8,1"
191 */
192 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
193 {
194 WCHAR last = 0;
195
196 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
197 return FALSE;
198
199 switch(lpdcb->BaudRate)
200 {
201 case 11:
202 case 30:
203 case 60:
204 lpdcb->BaudRate *= 10;
205 break;
206 case 12:
207 case 24:
208 case 48:
209 case 96:
210 lpdcb->BaudRate *= 100;
211 break;
212 case 19:
213 lpdcb->BaudRate = 19200;
214 break;
215 }
216
217 while(*device == ' ') device++;
218 if(*device++ != ',') return FALSE;
219 while(*device == ' ') device++;
220
221 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
222 return FALSE;
223
224 while(*device == ' ') device++;
225 if(*device++ != ',') return FALSE;
226 while(*device == ' ') device++;
227
228 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
229 return FALSE;
230
231 while(*device == ' ') device++;
232 if(*device++ != ',') return FALSE;
233 while(*device == ' ') device++;
234
235 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
236 return FALSE;
237
238 /* The last parameter for flow control is optional. */
239 while(*device == ' ') device++;
240 if(*device == ',')
241 {
242 device++;
243 while(*device == ' ') device++;
244 if(*device) last = toupperW(*device++);
245 while(*device == ' ') device++;
246 }
247
248 /* Win NT sets the flow control members based on (or lack of) the last
249 parameter. Win 9x does not set these members. */
250 switch(last)
251 {
252 case 0:
253 lpdcb->fInX = FALSE;
254 lpdcb->fOutX = FALSE;
255 lpdcb->fOutxCtsFlow = FALSE;
256 lpdcb->fOutxDsrFlow = FALSE;
257 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
258 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
259 break;
260 case 'X':
261 lpdcb->fInX = TRUE;
262 lpdcb->fOutX = TRUE;
263 lpdcb->fOutxCtsFlow = FALSE;
264 lpdcb->fOutxDsrFlow = FALSE;
265 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
266 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
267 break;
268 case 'P':
269 lpdcb->fInX = FALSE;
270 lpdcb->fOutX = FALSE;
271 lpdcb->fOutxCtsFlow = TRUE;
272 lpdcb->fOutxDsrFlow = TRUE;
273 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
274 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
275 break;
276 default:
277 return FALSE;
278 }
279
280 /* This should be the end of the string. */
281 if(*device) return FALSE;
282
283 return TRUE;
284 }
285
286 /***********************************************************************
287 * COMM_BuildNewCommDCB (Internal)
288 *
289 * Build a DCB using the new style settings string.
290 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
291 */
292 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
293 {
294 DWORD temp;
295 BOOL baud = FALSE, stop = FALSE;
296 static const WCHAR baudW[] = {'b','a','u','d','=',0};
297 static const WCHAR parityW[] = {'p','a','r','i','t','y','=',0};
298 static const WCHAR dataW[] = {'d','a','t','a','=',0};
299 static const WCHAR stopW[] = {'s','t','o','p','=',0};
300 static const WCHAR toW[] = {'t','o','=',0};
301 static const WCHAR xonW[] = {'x','o','n','=',0};
302 static const WCHAR odsrW[] = {'o','d','s','r','=',0};
303 static const WCHAR octsW[] = {'o','c','t','s','=',0};
304 static const WCHAR dtrW[] = {'d','t','r','=',0};
305 static const WCHAR rtsW[] = {'r','t','s','=',0};
306 static const WCHAR idsrW[] = {'i','d','s','r','=',0};
307
308 while(*device)
309 {
310 while(*device == ' ') device++;
311
312 if(!strncmpiW(baudW, device, 5))
313 {
314 baud = TRUE;
315
316 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
317 return FALSE;
318 }
319 else if(!strncmpiW(parityW, device, 7))
320 {
321 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
322 return FALSE;
323 }
324 else if(!strncmpiW(dataW, device, 5))
325 {
326 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
327 return FALSE;
328 }
329 else if(!strncmpiW(stopW, device, 5))
330 {
331 stop = TRUE;
332
333 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
334 return FALSE;
335 }
336 else if(!strncmpiW(toW, device, 3))
337 {
338 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
339 return FALSE;
340
341 lptimeouts->ReadIntervalTimeout = 0;
342 lptimeouts->ReadTotalTimeoutMultiplier = 0;
343 lptimeouts->ReadTotalTimeoutConstant = 0;
344 lptimeouts->WriteTotalTimeoutMultiplier = 0;
345 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
346 }
347 else if(!strncmpiW(xonW, device, 4))
348 {
349 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
350 return FALSE;
351
352 lpdcb->fOutX = temp;
353 lpdcb->fInX = temp;
354 }
355 else if(!strncmpiW(odsrW, device, 5))
356 {
357 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
358 return FALSE;
359
360 lpdcb->fOutxDsrFlow = temp;
361 }
362 else if(!strncmpiW(octsW, device, 5))
363 {
364 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
365 return FALSE;
366
367 lpdcb->fOutxCtsFlow = temp;
368 }
369 else if(!strncmpiW(dtrW, device, 4))
370 {
371 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
372 return FALSE;
373
374 lpdcb->fDtrControl = temp;
375 }
376 else if(!strncmpiW(rtsW, device, 4))
377 {
378 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
379 return FALSE;
380
381 lpdcb->fRtsControl = temp;
382 }
383 else if(!strncmpiW(idsrW, device, 5))
384 {
385 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
386 return FALSE;
387
388 /* Win NT sets the fDsrSensitivity member based on the
389 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
390 lpdcb->fDsrSensitivity = temp;
391 }
392 else
393 return FALSE;
394
395 /* After the above parsing, the next character (if not the end of
396 the string) should be a space */
397 if(*device && *device != ' ')
398 return FALSE;
399 }
400
401 /* If stop bits were not specified, a default is always supplied. */
402 if(!stop)
403 {
404 if(baud && lpdcb->BaudRate == 110)
405 lpdcb->StopBits = TWOSTOPBITS;
406 else
407 lpdcb->StopBits = ONESTOPBIT;
408 }
409
410 return TRUE;
411 }
412
413 /**************************************************************************
414 * BuildCommDCBA (KERNEL32.@)
415 *
416 * Updates a device control block data structure with values from an
417 * ascii device control string. The device control string has two forms
418 * normal and extended, it must be exclusively in one or the other form.
419 *
420 * RETURNS
421 *
422 * True on success, false on a malformed control string.
423 */
424 BOOL WINAPI BuildCommDCBA(
425 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
426 LPDCB lpdcb) /* [out] The device control block to be updated. */
427 {
428 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
429 }
430
431 /**************************************************************************
432 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
433 *
434 * Updates a device control block data structure with values from an
435 * ascii device control string. Taking timeout values from a timeouts
436 * struct if desired by the control string.
437 *
438 * RETURNS
439 *
440 * True on success, false bad handles etc.
441 */
442 BOOL WINAPI BuildCommDCBAndTimeoutsA(
443 LPCSTR device, /* [in] The ascii device control string. */
444 LPDCB lpdcb, /* [out] The device control block to be updated. */
445 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
446 {
447 BOOL ret = FALSE;
448 UNICODE_STRING deviceW;
449
450 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
451 if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
452 else deviceW.Buffer = NULL;
453
454 if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
455
456 RtlFreeUnicodeString(&deviceW);
457 return ret;
458 }
459
460 /**************************************************************************
461 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
462 *
463 * Updates a device control block data structure with values from a
464 * unicode device control string. Taking timeout values from a timeouts
465 * struct if desired by the control string.
466 *
467 * RETURNS
468 *
469 * True on success, false bad handles etc
470 */
471 BOOL WINAPI BuildCommDCBAndTimeoutsW(
472 LPCWSTR devid, /* [in] The unicode device control string. */
473 LPDCB lpdcb, /* [out] The device control block to be updated. */
474 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
475 {
476 DCB dcb;
477 COMMTIMEOUTS timeouts;
478 BOOL result;
479 LPCWSTR ptr = devid;
480
481 TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
482
483 memset(&timeouts, 0, sizeof timeouts);
484
485 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
486 lpdcb->DCBlength = sizeof(DCB);
487
488 /* Make a copy of the original data structures to work with since if
489 if there is an error in the device control string the originals
490 should not be modified (except possibly DCBlength) */
491 dcb = *lpdcb;
492 if(lptimeouts) timeouts = *lptimeouts;
493
494 ptr = COMM_ParseStart(ptr);
495
496 if(ptr == NULL)
497 result = FALSE;
498 else if(strchrW(ptr, ','))
499 result = COMM_BuildOldCommDCB(ptr, &dcb);
500 else
501 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
502
503 if(result)
504 {
505 *lpdcb = dcb;
506 if(lptimeouts) *lptimeouts = timeouts;
507 return TRUE;
508 }
509 else
510 {
511 WARN("Invalid device control string: %s\n", debugstr_w(devid));
512 SetLastError(ERROR_INVALID_PARAMETER);
513 return FALSE;
514 }
515 }
516
517 /**************************************************************************
518 * BuildCommDCBW (KERNEL32.@)
519 *
520 * Updates a device control block structure with values from an
521 * unicode device control string. The device control string has two forms
522 * normal and extended, it must be exclusively in one or the other form.
523 *
524 * RETURNS
525 *
526 * True on success, false on a malformed control string.
527 */
528 BOOL WINAPI BuildCommDCBW(
529 LPCWSTR devid, /* [in] The unicode device control string. */
530 LPDCB lpdcb) /* [out] The device control block to be updated. */
531 {
532 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
533 }
534
535 /*****************************************************************************
536 * SetCommBreak (KERNEL32.@)
537 *
538 * Halts the transmission of characters to a communications device.
539 *
540 * PARAMS
541 * handle [in] The communications device to suspend
542 *
543 * RETURNS
544 *
545 * True on success, and false if the communications device could not be found,
546 * the control is not supported.
547 *
548 * BUGS
549 *
550 * Only TIOCSBRK and TIOCCBRK are supported.
551 */
552 BOOL WINAPI SetCommBreak(HANDLE handle)
553 {
554 return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, NULL, NULL);
555 }
556
557 /*****************************************************************************
558 * ClearCommBreak (KERNEL32.@)
559 *
560 * Resumes character transmission from a communication device.
561 *
562 * PARAMS
563 *
564 * handle [in] The halted communication device whose character transmission is to be resumed
565 *
566 * RETURNS
567 *
568 * True on success and false if the communications device could not be found.
569 *
570 * BUGS
571 *
572 * Only TIOCSBRK and TIOCCBRK are supported.
573 */
574 BOOL WINAPI ClearCommBreak(HANDLE handle)
575 {
576 return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, NULL, NULL);
577 }
578
579 /*****************************************************************************
580 * EscapeCommFunction (KERNEL32.@)
581 *
582 * Directs a communication device to perform an extended function.
583 *
584 * PARAMS
585 *
586 * handle [in] The communication device to perform the extended function
587 * nFunction [in] The extended function to be performed
588 *
589 * RETURNS
590 *
591 * True or requested data on successful completion of the command,
592 * false if the device is not present cannot execute the command
593 * or the command failed.
594 */
595 BOOL WINAPI EscapeCommFunction(HANDLE handle, UINT func)
596 {
597 DWORD ioc;
598
599 switch (func)
600 {
601 case CLRDTR: ioc = IOCTL_SERIAL_CLR_DTR; break;
602 case CLRRTS: ioc = IOCTL_SERIAL_CLR_RTS; break;
603 case SETDTR: ioc = IOCTL_SERIAL_SET_DTR; break;
604 case SETRTS: ioc = IOCTL_SERIAL_SET_RTS; break;
605 case SETXOFF: ioc = IOCTL_SERIAL_SET_XOFF; break;
606 case SETXON: ioc = IOCTL_SERIAL_SET_XON; break;
607 case SETBREAK: ioc = IOCTL_SERIAL_SET_BREAK_ON; break;
608 case CLRBREAK: ioc = IOCTL_SERIAL_SET_BREAK_OFF; break;
609 case RESETDEV: ioc = IOCTL_SERIAL_RESET_DEVICE; break;
610 default:
611 ERR("Unknown function code (%u)\n", func);
612 SetLastError(ERROR_INVALID_PARAMETER);
613 return FALSE;
614 }
615 return DeviceIoControl(handle, ioc, NULL, 0, NULL, 0, NULL, NULL);
616 }
617
618 /********************************************************************
619 * PurgeComm (KERNEL32.@)
620 *
621 * Terminates pending operations and/or discards buffers on a
622 * communication resource.
623 *
624 * PARAMS
625 *
626 * handle [in] The communication resource to be purged
627 * flags [in] Flags for clear pending/buffer on input/output
628 *
629 * RETURNS
630 *
631 * True on success and false if the communications handle is bad.
632 */
633 BOOL WINAPI PurgeComm(HANDLE handle, DWORD flags)
634 {
635 return DeviceIoControl(handle, IOCTL_SERIAL_PURGE, &flags, sizeof(flags),
636 NULL, 0, NULL, NULL);
637 }
638
639 /*****************************************************************************
640 * ClearCommError (KERNEL32.@)
641 *
642 * Enables further I/O operations on a communications resource after
643 * supplying error and current status information.
644 *
645 * PARAMS
646 *
647 * handle [in] The communication resource with the error
648 * errors [out] Flags indicating error the resource experienced
649 * lpStat [out] The status of the communication resource
650 * RETURNS
651 *
652 * True on success, false if the communication resource handle is bad.
653 */
654 BOOL WINAPI ClearCommError(HANDLE handle, LPDWORD errors, LPCOMSTAT lpStat)
655 {
656 SERIAL_STATUS ss;
657
658 if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_COMMSTATUS, NULL, 0,
659 &ss, sizeof(ss), NULL, NULL))
660 return FALSE;
661
662 if (errors)
663 {
664 *errors = 0;
665 if (ss.Errors & SERIAL_ERROR_BREAK) *errors |= CE_BREAK;
666 if (ss.Errors & SERIAL_ERROR_FRAMING) *errors |= CE_FRAME;
667 if (ss.Errors & SERIAL_ERROR_OVERRUN) *errors |= CE_OVERRUN;
668 if (ss.Errors & SERIAL_ERROR_QUEUEOVERRUN) *errors |= CE_RXOVER;
669 if (ss.Errors & SERIAL_ERROR_PARITY) *errors |= CE_RXPARITY;
670 }
671
672 if (lpStat)
673 {
674 memset(lpStat, 0, sizeof(*lpStat));
675
676 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_CTS) lpStat->fCtsHold = TRUE;
677 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DSR) lpStat->fDsrHold = TRUE;
678 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DCD) lpStat->fRlsdHold = TRUE;
679 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_XON) lpStat->fXoffHold = TRUE;
680 if (ss.HoldReasons & SERIAL_TX_WAITING_XOFF_SENT) lpStat->fXoffSent = TRUE;
681 if (ss.EofReceived) lpStat->fEof = TRUE;
682 if (ss.WaitForImmediate) lpStat->fTxim = TRUE;
683 lpStat->cbInQue = ss.AmountInInQueue;
684 lpStat->cbOutQue = ss.AmountInOutQueue;
685 }
686 return TRUE;
687 }
688
689 /*****************************************************************************
690 * SetupComm (KERNEL32.@)
691 *
692 * Called after CreateFile to hint to the communication resource to use
693 * specified sizes for input and output buffers rather than the default values.
694 *
695 * PARAMS
696 * handle [in] The just created communication resource handle
697 * insize [in] The suggested size of the communication resources input buffer in bytes
698 * outsize [in] The suggested size of the communication resources output buffer in bytes
699 *
700 * RETURNS
701 *
702 * True if successful, false if the communications resource handle is bad.
703 *
704 * BUGS
705 *
706 * Stub.
707 */
708 BOOL WINAPI SetupComm(HANDLE handle, DWORD insize, DWORD outsize)
709 {
710 SERIAL_QUEUE_SIZE sqs;
711
712 sqs.InSize = insize;
713 sqs.OutSize = outsize;
714 return DeviceIoControl(handle, IOCTL_SERIAL_SET_QUEUE_SIZE,
715 &sqs, sizeof(sqs), NULL, 0, NULL, NULL);
716 }
717
718 /*****************************************************************************
719 * GetCommMask (KERNEL32.@)
720 *
721 * Obtain the events associated with a communication device that will cause
722 * a call WaitCommEvent to return.
723 *
724 * PARAMS
725 *
726 * handle [in] The communications device
727 * evtmask [out] The events which cause WaitCommEvent to return
728 *
729 * RETURNS
730 *
731 * True on success, fail on bad device handle etc.
732 */
733 BOOL WINAPI GetCommMask(HANDLE handle, LPDWORD evtmask)
734 {
735 TRACE("handle %p, mask %p\n", handle, evtmask);
736 return DeviceIoControl(handle, IOCTL_SERIAL_GET_WAIT_MASK,
737 NULL, 0, evtmask, sizeof(*evtmask), NULL, NULL);
738 }
739
740 /*****************************************************************************
741 * SetCommMask (KERNEL32.@)
742 *
743 * There be some things we need to hear about yon there communications device.
744 * (Set which events associated with a communication device should cause
745 * a call WaitCommEvent to return.)
746 *
747 * PARAMS
748 *
749 * handle [in] The communications device
750 * evtmask [in] The events that are to be monitored
751 *
752 * RETURNS
753 *
754 * True on success, false on bad handle etc.
755 */
756 BOOL WINAPI SetCommMask(HANDLE handle, DWORD evtmask)
757 {
758 TRACE("handle %p, mask %x\n", handle, evtmask);
759 return DeviceIoControl(handle, IOCTL_SERIAL_SET_WAIT_MASK,
760 &evtmask, sizeof(evtmask), NULL, 0, NULL, NULL);
761 }
762
763 static void dump_dcb(const DCB* lpdcb)
764 {
765 TRACE("bytesize=%d baudrate=%d fParity=%d Parity=%d stopbits=%d\n",
766 lpdcb->ByteSize, lpdcb->BaudRate, lpdcb->fParity, lpdcb->Parity,
767 (lpdcb->StopBits == ONESTOPBIT) ? 1 :
768 (lpdcb->StopBits == TWOSTOPBITS) ? 2 : 0);
769 TRACE("%sIXON %sIXOFF\n", (lpdcb->fInX) ? "" : "~", (lpdcb->fOutX) ? "" : "~");
770 TRACE("fOutxCtsFlow=%d fRtsControl=%d\n", lpdcb->fOutxCtsFlow, lpdcb->fRtsControl);
771 TRACE("fOutxDsrFlow=%d fDtrControl=%d\n", lpdcb->fOutxDsrFlow, lpdcb->fDtrControl);
772 if (lpdcb->fOutxCtsFlow || lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE)
773 TRACE("CRTSCTS\n");
774 else
775 TRACE("~CRTSCTS\n");
776 }
777
778 /*****************************************************************************
779 * SetCommState (KERNEL32.@)
780 *
781 * Re-initializes all hardware and control settings of a communications device,
782 * with values from a device control block without affecting the input and output
783 * queues.
784 *
785 * PARAMS
786 *
787 * handle [in] The communications device
788 * lpdcb [out] The device control block
789 *
790 * RETURNS
791 *
792 * True on success, false on failure, e.g., if the XonChar is equal to the XoffChar.
793 */
794 BOOL WINAPI SetCommState( HANDLE handle, LPDCB lpdcb)
795 {
796 SERIAL_BAUD_RATE sbr;
797 SERIAL_LINE_CONTROL slc;
798 SERIAL_HANDFLOW shf;
799 SERIAL_CHARS sc;
800
801 if (lpdcb == NULL)
802 {
803 SetLastError(ERROR_INVALID_PARAMETER);
804 return FALSE;
805 }
806 dump_dcb(lpdcb);
807
808 sbr.BaudRate = lpdcb->BaudRate;
809
810 slc.StopBits = lpdcb->StopBits;
811 slc.Parity = lpdcb->Parity;
812 slc.WordLength = lpdcb->ByteSize;
813
814 shf.ControlHandShake = 0;
815 shf.FlowReplace = 0;
816 if (lpdcb->fOutxCtsFlow) shf.ControlHandShake |= SERIAL_CTS_HANDSHAKE;
817 if (lpdcb->fOutxDsrFlow) shf.ControlHandShake |= SERIAL_DSR_HANDSHAKE;
818 switch (lpdcb->fDtrControl)
819 {
820 case DTR_CONTROL_DISABLE: break;
821 case DTR_CONTROL_ENABLE: shf.ControlHandShake |= SERIAL_DTR_CONTROL; break;
822 case DTR_CONTROL_HANDSHAKE: shf.ControlHandShake |= SERIAL_DTR_HANDSHAKE;break;
823 default:
824 SetLastError(ERROR_INVALID_PARAMETER);
825 return FALSE;
826 }
827 switch (lpdcb->fRtsControl)
828 {
829 case RTS_CONTROL_DISABLE: break;
830 case RTS_CONTROL_ENABLE: shf.FlowReplace |= SERIAL_RTS_CONTROL; break;
831 case RTS_CONTROL_HANDSHAKE: shf.FlowReplace |= SERIAL_RTS_HANDSHAKE; break;
832 case RTS_CONTROL_TOGGLE: shf.FlowReplace |= SERIAL_RTS_CONTROL |
833 SERIAL_RTS_HANDSHAKE; break;
834 default:
835 SetLastError(ERROR_INVALID_PARAMETER);
836 return FALSE;
837 }
838 if (lpdcb->fDsrSensitivity) shf.ControlHandShake |= SERIAL_DSR_SENSITIVITY;
839 if (lpdcb->fAbortOnError) shf.ControlHandShake |= SERIAL_ERROR_ABORT;
840
841 if (lpdcb->fErrorChar) shf.FlowReplace |= SERIAL_ERROR_CHAR;
842 if (lpdcb->fNull) shf.FlowReplace |= SERIAL_NULL_STRIPPING;
843 if (lpdcb->fTXContinueOnXoff) shf.FlowReplace |= SERIAL_XOFF_CONTINUE;
844 if (lpdcb->fOutX) shf.FlowReplace |= SERIAL_AUTO_TRANSMIT;
845 if (lpdcb->fInX) shf.FlowReplace |= SERIAL_AUTO_RECEIVE;
846
847 shf.XonLimit = lpdcb->XonLim;
848 shf.XoffLimit = lpdcb->XoffLim;
849
850 sc.EofChar = lpdcb->EofChar;
851 sc.ErrorChar = lpdcb->ErrorChar;
852 sc.BreakChar = 0;
853 sc.EventChar = lpdcb->EvtChar;
854 sc.XonChar = lpdcb->XonChar;
855 sc.XoffChar = lpdcb->XoffChar;
856
857 /* note: change DTR/RTS lines after setting the comm attributes,
858 * so flow control does not interfere.
859 */
860 return (DeviceIoControl(handle, IOCTL_SERIAL_SET_BAUD_RATE,
861 &sbr, sizeof(sbr), NULL, 0, NULL, NULL) &&
862 DeviceIoControl(handle, IOCTL_SERIAL_SET_LINE_CONTROL,
863 &slc, sizeof(slc), NULL, 0, NULL, NULL) &&
864 DeviceIoControl(handle, IOCTL_SERIAL_SET_HANDFLOW,
865 &shf, sizeof(shf), NULL, 0, NULL, NULL) &&
866 DeviceIoControl(handle, IOCTL_SERIAL_SET_CHARS,
867 &sc, sizeof(sc), NULL, 0, NULL, NULL));
868 }
869
870
871 /*****************************************************************************
872 * GetCommState (KERNEL32.@)
873 *
874 * Fills in a device control block with information from a communications device.
875 *
876 * PARAMS
877 * handle [in] The communications device
878 * lpdcb [out] The device control block
879 *
880 * RETURNS
881 *
882 * True on success, false if the communication device handle is bad etc
883 *
884 * BUGS
885 *
886 * XonChar and XoffChar are not set.
887 */
888 BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb)
889 {
890 SERIAL_BAUD_RATE sbr;
891 SERIAL_LINE_CONTROL slc;
892 SERIAL_HANDFLOW shf;
893 SERIAL_CHARS sc;
894
895 TRACE("handle %p, ptr %p\n", handle, lpdcb);
896
897 if (!lpdcb)
898 {
899 SetLastError(ERROR_INVALID_PARAMETER);
900 return FALSE;
901 }
902
903 if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_BAUD_RATE,
904 NULL, 0, &sbr, sizeof(sbr), NULL, NULL) ||
905 !DeviceIoControl(handle, IOCTL_SERIAL_GET_LINE_CONTROL,
906 NULL, 0, &slc, sizeof(slc), NULL, NULL) ||
907 !DeviceIoControl(handle, IOCTL_SERIAL_GET_HANDFLOW,
908 NULL, 0, &shf, sizeof(shf), NULL, NULL) ||
909 !DeviceIoControl(handle, IOCTL_SERIAL_GET_CHARS,
910 NULL, 0, &sc, sizeof(sc), NULL, NULL))
911 return FALSE;
912
913 memset(lpdcb, 0, sizeof(*lpdcb));
914 lpdcb->DCBlength = sizeof(*lpdcb);
915
916 /* yes, they seem no never be (re)set on NT */
917 lpdcb->fBinary = 1;
918 lpdcb->fParity = 0;
919
920 lpdcb->BaudRate = sbr.BaudRate;
921
922 lpdcb->StopBits = slc.StopBits;
923 lpdcb->Parity = slc.Parity;
924 lpdcb->ByteSize = slc.WordLength;
925
926 if (shf.ControlHandShake & SERIAL_CTS_HANDSHAKE) lpdcb->fOutxCtsFlow = 1;
927 if (shf.ControlHandShake & SERIAL_DSR_HANDSHAKE) lpdcb->fOutxDsrFlow = 1;
928 switch (shf.ControlHandShake & (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE))
929 {
930 case 0: lpdcb->fDtrControl = DTR_CONTROL_DISABLE; break;
931 case SERIAL_DTR_CONTROL: lpdcb->fDtrControl = DTR_CONTROL_ENABLE; break;
932 case SERIAL_DTR_HANDSHAKE: lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE; break;
933 }
934 switch (shf.FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE))
935 {
936 case 0: lpdcb->fRtsControl = RTS_CONTROL_DISABLE; break;
937 case SERIAL_RTS_CONTROL: lpdcb->fRtsControl = RTS_CONTROL_ENABLE; break;
938 case SERIAL_RTS_HANDSHAKE: lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE; break;
939 case SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE:
940 lpdcb->fRtsControl = RTS_CONTROL_TOGGLE; break;
941 }
942 if (shf.ControlHandShake & SERIAL_DSR_SENSITIVITY) lpdcb->fDsrSensitivity = 1;
943 if (shf.ControlHandShake & SERIAL_ERROR_ABORT) lpdcb->fAbortOnError = 1;
944 if (shf.FlowReplace & SERIAL_ERROR_CHAR) lpdcb->fErrorChar = 1;
945 if (shf.FlowReplace & SERIAL_NULL_STRIPPING) lpdcb->fNull = 1;
946 if (shf.FlowReplace & SERIAL_XOFF_CONTINUE) lpdcb->fTXContinueOnXoff = 1;
947 lpdcb->XonLim = shf.XonLimit;
948 lpdcb->XoffLim = shf.XoffLimit;
949
950 if (shf.FlowReplace & SERIAL_AUTO_TRANSMIT) lpdcb->fOutX = 1;
951 if (shf.FlowReplace & SERIAL_AUTO_RECEIVE) lpdcb->fInX = 1;
952
953 lpdcb->EofChar = sc.EofChar;
954 lpdcb->ErrorChar = sc.ErrorChar;
955 lpdcb->EvtChar = sc.EventChar;
956 lpdcb->XonChar = sc.XonChar;
957 lpdcb->XoffChar = sc.XoffChar;
958
959 TRACE("OK\n");
960 dump_dcb(lpdcb);
961
962 return TRUE;
963 }
964
965 /*****************************************************************************
966 * TransmitCommChar (KERNEL32.@)
967 *
968 * Transmits a single character in front of any pending characters in the
969 * output buffer. Usually used to send an interrupt character to a host.
970 *
971 * PARAMS
972 * hComm [in] The communication device in need of a command character
973 * chTransmit [in] The character to transmit
974 *
975 * RETURNS
976 *
977 * True if the call succeeded, false if the previous command character to the
978 * same device has not been sent yet the handle is bad etc.
979 *
980 */
981 BOOL WINAPI TransmitCommChar(HANDLE hComm, CHAR chTransmit)
982 {
983 return DeviceIoControl(hComm, IOCTL_SERIAL_IMMEDIATE_CHAR,
984 &chTransmit, sizeof(chTransmit), NULL, 0, NULL, NULL);
985 }
986
987
988 /*****************************************************************************
989 * GetCommTimeouts (KERNEL32.@)
990 *
991 * Obtains the request timeout values for the communications device.
992 *
993 * PARAMS
994 * hComm [in] The communications device
995 * lptimeouts [out] The struct of request timeouts
996 *
997 * RETURNS
998 *
999 * True on success, false if communications device handle is bad
1000 * or the target structure is null.
1001 */
1002 BOOL WINAPI GetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts)
1003 {
1004 SERIAL_TIMEOUTS st;
1005
1006 TRACE("(%p, %p)\n", hComm, lptimeouts);
1007 if (!lptimeouts)
1008 {
1009 SetLastError(ERROR_INVALID_PARAMETER);
1010 return FALSE;
1011 }
1012 if (!DeviceIoControl(hComm, IOCTL_SERIAL_GET_TIMEOUTS,
1013 NULL, 0, &st, sizeof(st), NULL, NULL))
1014 return FALSE;
1015 lptimeouts->ReadIntervalTimeout = st.ReadIntervalTimeout;
1016 lptimeouts->ReadTotalTimeoutMultiplier = st.ReadTotalTimeoutMultiplier;
1017 lptimeouts->ReadTotalTimeoutConstant = st.ReadTotalTimeoutConstant;
1018 lptimeouts->WriteTotalTimeoutMultiplier = st.WriteTotalTimeoutMultiplier;
1019 lptimeouts->WriteTotalTimeoutConstant = st.WriteTotalTimeoutConstant;
1020 return TRUE;
1021 }
1022
1023 /*****************************************************************************
1024 * SetCommTimeouts (KERNEL32.@)
1025 *
1026 * Sets the timeouts used when reading and writing data to/from COMM ports.
1027 *
1028 * PARAMS
1029 * hComm [in] handle of COMM device
1030 * lptimeouts [in] pointer to COMMTIMEOUTS structure
1031 *
1032 * ReadIntervalTimeout
1033 * - converted and passes to linux kernel as c_cc[VTIME]
1034 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1035 * - used in ReadFile to calculate GetOverlappedResult's timeout
1036 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1037 * - used in WriteFile to calculate GetOverlappedResult's timeout
1038 *
1039 * RETURNS
1040 *
1041 * True if the timeouts were set, false otherwise.
1042 */
1043 BOOL WINAPI SetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts)
1044 {
1045 SERIAL_TIMEOUTS st;
1046
1047 TRACE("(%p, %p)\n", hComm, lptimeouts);
1048
1049 if (lptimeouts == NULL)
1050 {
1051 SetLastError(ERROR_INVALID_PARAMETER);
1052 return FALSE;
1053 }
1054 st.ReadIntervalTimeout = lptimeouts->ReadIntervalTimeout;
1055 st.ReadTotalTimeoutMultiplier = lptimeouts->ReadTotalTimeoutMultiplier;
1056 st.ReadTotalTimeoutConstant = lptimeouts->ReadTotalTimeoutConstant;
1057 st.WriteTotalTimeoutMultiplier = lptimeouts->WriteTotalTimeoutMultiplier;
1058 st.WriteTotalTimeoutConstant = lptimeouts->WriteTotalTimeoutConstant;
1059
1060 return DeviceIoControl(hComm, IOCTL_SERIAL_SET_TIMEOUTS,
1061 &st, sizeof(st), NULL, 0, NULL, NULL);
1062 }
1063
1064 /***********************************************************************
1065 * GetCommModemStatus (KERNEL32.@)
1066 *
1067 * Obtains the four control register bits if supported by the hardware.
1068 *
1069 * PARAMS
1070 *
1071 * hFile [in] The communications device
1072 * lpModemStat [out] The control register bits
1073 *
1074 * RETURNS
1075 *
1076 * True if the communications handle was good and for hardware that
1077 * control register access, false otherwise.
1078 */
1079 BOOL WINAPI GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat)
1080 {
1081 return DeviceIoControl(hFile, IOCTL_SERIAL_GET_MODEMSTATUS,
1082 NULL, 0, lpModemStat, sizeof(DWORD), NULL, NULL);
1083 }
1084
1085 /***********************************************************************
1086 * WaitCommEvent (KERNEL32.@)
1087 *
1088 * Wait until something interesting happens on a COMM port.
1089 * Interesting things (events) are set by calling SetCommMask before
1090 * this function is called.
1091 *
1092 * RETURNS
1093 * TRUE if successful
1094 * FALSE if failure
1095 *
1096 * The set of detected events will be written to *lpdwEventMask
1097 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1098 *
1099 * BUGS:
1100 * Only supports EV_RXCHAR and EV_TXEMPTY
1101 */
1102 BOOL WINAPI WaitCommEvent(
1103 HANDLE hFile, /* [in] handle of comm port to wait for */
1104 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1105 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1106 {
1107 return DeviceIoControl(hFile, IOCTL_SERIAL_WAIT_ON_MASK, NULL, 0,
1108 lpdwEvents, sizeof(DWORD), NULL, lpOverlapped);
1109 }
1110
1111 /***********************************************************************
1112 * GetCommProperties (KERNEL32.@)
1113 *
1114 * This function fills in a structure with the capabilities of the
1115 * communications port driver.
1116 *
1117 * RETURNS
1118 *
1119 * TRUE on success, FALSE on failure
1120 * If successful, the lpCommProp structure be filled in with
1121 * properties of the comm port.
1122 */
1123 BOOL WINAPI GetCommProperties(
1124 HANDLE hFile, /* [in] handle of the comm port */
1125 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
1126 {
1127 FIXME("(%p %p )\n",hFile,lpCommProp);
1128 if(!lpCommProp)
1129 return FALSE;
1130
1131 /*
1132 * These values should be valid for LINUX's serial driver
1133 * FIXME: Perhaps they deserve an #ifdef LINUX
1134 */
1135 memset(lpCommProp,0,sizeof(COMMPROP));
1136 lpCommProp->wPacketLength = 1;
1137 lpCommProp->wPacketVersion = 1;
1138 lpCommProp->dwServiceMask = SP_SERIALCOMM;
1139 lpCommProp->dwReserved1 = 0;
1140 lpCommProp->dwMaxTxQueue = 4096;
1141 lpCommProp->dwMaxRxQueue = 4096;
1142 lpCommProp->dwMaxBaud = BAUD_115200;
1143 lpCommProp->dwProvSubType = PST_RS232;
1144 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
1145 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
1146 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
1147 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
1148 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
1149 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
1150 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
1151 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
1152 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
1153 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
1154 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
1155
1156 return TRUE;
1157 }
1158
1159 /***********************************************************************
1160 * FIXME:
1161 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
1162 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
1163 * This is dependent on the type of COMM port, but since it is doubtful
1164 * anybody will get around to implementing support for fancy serial
1165 * ports in WINE, this is hardcoded for the time being. The name of
1166 * this DLL should be stored in and read from the system registry in
1167 * the hive HKEY_LOCAL_MACHINE, key
1168 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
1169 * where ???? is the port number... that is determined by PNP
1170 * The DLL should be loaded when the COMM port is opened, and closed
1171 * when the COMM port is closed. - MJM 20 June 2000
1172 ***********************************************************************/
1173 static const WCHAR lpszSerialUI[] = {
1174 's','e','r','i','a','l','u','i','.','d','l','l',0 };
1175
1176
1177 /***********************************************************************
1178 * CommConfigDialogA (KERNEL32.@)
1179 *
1180 * Raises a dialog that allows the user to configure a comm port.
1181 * Fills the COMMCONFIG struct with information specified by the user.
1182 * This function should call a similar routine in the COMM driver...
1183 *
1184 * RETURNS
1185 *
1186 * TRUE on success, FALSE on failure
1187 * If successful, the lpCommConfig structure will contain a new
1188 * configuration for the comm port, as specified by the user.
1189 *
1190 * BUGS
1191 * The library with the CommConfigDialog code is never unloaded.
1192 * Perhaps this should be done when the comm port is closed?
1193 */
1194 BOOL WINAPI CommConfigDialogA(
1195 LPCSTR lpszDevice, /* [in] name of communications device */
1196 HWND hWnd, /* [in] parent window for the dialog */
1197 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1198 {
1199 LPWSTR lpDeviceW = NULL;
1200 DWORD len;
1201 BOOL r;
1202
1203 TRACE("(%s, %p, %p)\n", debugstr_a(lpszDevice), hWnd, lpCommConfig);
1204
1205 if (lpszDevice)
1206 {
1207 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
1208 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
1209 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
1210 }
1211 r = CommConfigDialogW(lpDeviceW, hWnd, lpCommConfig);
1212 HeapFree( GetProcessHeap(), 0, lpDeviceW );
1213 return r;
1214 }
1215
1216 /***********************************************************************
1217 * CommConfigDialogW (KERNEL32.@)
1218 *
1219 * See CommConfigDialogA.
1220 */
1221 BOOL WINAPI CommConfigDialogW(
1222 LPCWSTR lpszDevice, /* [in] name of communications device */
1223 HWND hWnd, /* [in] parent window for the dialog */
1224 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1225 {
1226 FARPROC pCommConfigDialog;
1227 HMODULE hConfigModule;
1228 DWORD res = ERROR_INVALID_PARAMETER;
1229
1230 TRACE("(%s, %p, %p)\n", debugstr_w(lpszDevice), hWnd, lpCommConfig);
1231 hConfigModule = LoadLibraryW(lpszSerialUI);
1232
1233 if (hConfigModule) {
1234 pCommConfigDialog = GetProcAddress(hConfigModule, "drvCommConfigDialogW");
1235 if (pCommConfigDialog) {
1236 res = pCommConfigDialog(lpszDevice, hWnd, lpCommConfig);
1237 }
1238 FreeLibrary(hConfigModule);
1239 }
1240
1241 if (res) SetLastError(res);
1242 return (res == ERROR_SUCCESS);
1243 }
1244
1245 /***********************************************************************
1246 * GetCommConfig (KERNEL32.@)
1247 *
1248 * Fill in the COMMCONFIG structure for the comm port hFile
1249 *
1250 * RETURNS
1251 *
1252 * TRUE on success, FALSE on failure
1253 * If successful, lpCommConfig contains the comm port configuration.
1254 *
1255 * BUGS
1256 *
1257 */
1258 BOOL WINAPI GetCommConfig(
1259 HANDLE hFile, /* [in] The communications device. */
1260 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
1261 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
1262 afterwards the number of bytes copied to the buffer or
1263 the needed size of the buffer. */
1264 {
1265 BOOL r;
1266
1267 TRACE("(%p, %p, %p) *lpdwSize: %u\n", hFile, lpCommConfig, lpdwSize, lpdwSize ? *lpdwSize : 0 );
1268
1269 if(lpCommConfig == NULL)
1270 return FALSE;
1271 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
1272 *lpdwSize = sizeof(COMMCONFIG);
1273 if(r)
1274 return FALSE;
1275
1276 lpCommConfig->dwSize = sizeof(COMMCONFIG);
1277 lpCommConfig->wVersion = 1;
1278 lpCommConfig->wReserved = 0;
1279 r = GetCommState(hFile,&lpCommConfig->dcb);
1280 lpCommConfig->dwProviderSubType = PST_RS232;
1281 lpCommConfig->dwProviderOffset = 0;
1282 lpCommConfig->dwProviderSize = 0;
1283
1284 return r;
1285 }
1286
1287 /***********************************************************************
1288 * SetCommConfig (KERNEL32.@)
1289 *
1290 * Sets the configuration of the communications device.
1291 *
1292 * RETURNS
1293 *
1294 * True on success, false if the handle was bad is not a communications device.
1295 */
1296 BOOL WINAPI SetCommConfig(
1297 HANDLE hFile, /* [in] The communications device. */
1298 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
1299 DWORD dwSize) /* [in] size of the lpCommConfig struct */
1300 {
1301 TRACE("(%p, %p, %u)\n", hFile, lpCommConfig, dwSize);
1302 return SetCommState(hFile,&lpCommConfig->dcb);
1303 }
1304
1305 /***********************************************************************
1306 * SetDefaultCommConfigW (KERNEL32.@)
1307 *
1308 * Initializes the default configuration for a communication device.
1309 *
1310 * PARAMS
1311 * lpszDevice [I] Name of the device targeted for configuration
1312 * lpCommConfig [I] PTR to a buffer with the configuration for the device
1313 * dwSize [I] Number of bytes in the buffer
1314 *
1315 * RETURNS
1316 * Failure: FALSE
1317 * Success: TRUE, and default configuration saved
1318 *
1319 */
1320 BOOL WINAPI SetDefaultCommConfigW(LPCWSTR lpszDevice, LPCOMMCONFIG lpCommConfig, DWORD dwSize)
1321 {
1322 FARPROC lpfnSetDefaultCommConfig;
1323 HMODULE hConfigModule;
1324 BOOL r = FALSE;
1325
1326 TRACE("(%s, %p, %u)\n", debugstr_w(lpszDevice), lpCommConfig, dwSize);
1327
1328 hConfigModule = LoadLibraryW(lpszSerialUI);
1329 if(!hConfigModule)
1330 return r;
1331
1332 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
1333 if (lpfnSetDefaultCommConfig)
1334 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
1335
1336 FreeLibrary(hConfigModule);
1337
1338 return r;
1339 }
1340
1341
1342 /***********************************************************************
1343 * SetDefaultCommConfigA (KERNEL32.@)
1344 *
1345 * Initializes the default configuration for a communication device.
1346 *
1347 * See SetDefaultCommConfigW.
1348 *
1349 */
1350 BOOL WINAPI SetDefaultCommConfigA(LPCSTR lpszDevice, LPCOMMCONFIG lpCommConfig, DWORD dwSize)
1351 {
1352 BOOL r;
1353 LPWSTR lpDeviceW = NULL;
1354 DWORD len;
1355
1356 TRACE("(%s, %p, %u)\n", debugstr_a(lpszDevice), lpCommConfig, dwSize);
1357
1358 if (lpszDevice)
1359 {
1360 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
1361 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1362 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
1363 }
1364 r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
1365 HeapFree( GetProcessHeap(), 0, lpDeviceW );
1366 return r;
1367 }
1368
1369
1370 /***********************************************************************
1371 * GetDefaultCommConfigW (KERNEL32.@)
1372 *
1373 * Acquires the default configuration of the specified communication device. (unicode)
1374 *
1375 * RETURNS
1376 *
1377 * True on successful reading of the default configuration,
1378 * if the device is not found or the buffer is too small.
1379 */
1380 BOOL WINAPI GetDefaultCommConfigW(
1381 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
1382 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
1383 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
1384 afterwards the number of bytes copied to the buffer or
1385 the needed size of the buffer. */
1386 {
1387 FARPROC pGetDefaultCommConfig;
1388 HMODULE hConfigModule;
1389 DWORD res = ERROR_INVALID_PARAMETER;
1390
1391 TRACE("(%s, %p, %p) *lpdwSize: %u\n", debugstr_w(lpszName), lpCC, lpdwSize, lpdwSize ? *lpdwSize : 0 );
1392 hConfigModule = LoadLibraryW(lpszSerialUI);
1393
1394 if (hConfigModule) {
1395 pGetDefaultCommConfig = GetProcAddress(hConfigModule, "drvGetDefaultCommConfigW");
1396 if (pGetDefaultCommConfig) {
1397 res = pGetDefaultCommConfig(lpszName, lpCC, lpdwSize);
1398 }
1399 FreeLibrary(hConfigModule);
1400 }
1401
1402 if (res) SetLastError(res);
1403 return (res == ERROR_SUCCESS);
1404 }
1405
1406 /**************************************************************************
1407 * GetDefaultCommConfigA (KERNEL32.@)
1408 *
1409 * Acquires the default configuration of the specified communication device. (ascii)
1410 *
1411 * RETURNS
1412 *
1413 * True on successful reading of the default configuration,
1414 * if the device is not found or the buffer is too small.
1415 */
1416 BOOL WINAPI GetDefaultCommConfigA(
1417 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
1418 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
1419 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
1420 afterwards the number of bytes copied to the buffer or
1421 the needed size of the buffer. */
1422 {
1423 BOOL ret = FALSE;
1424 UNICODE_STRING lpszNameW;
1425
1426 TRACE("(%s, %p, %p) *lpdwSize: %u\n", debugstr_a(lpszName), lpCC, lpdwSize, lpdwSize ? *lpdwSize : 0 );
1427 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
1428 else lpszNameW.Buffer = NULL;
1429
1430 ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
1431
1432 RtlFreeUnicodeString(&lpszNameW);
1433 return ret;
1434 }
1435
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.