winejoystick: Fix a crash on accessing a CFArray past its end due to an off-by-one...
[wine/multimedia.git] / dlls / kernel32 / comm.c
blob1c6f1affdc323c8e82f95deb2f19db74ae2ab170
1 /*
2 * DEC 93 Erik Bos <erik@xs4all.nl>
4 * Copyright 1996 Marcus Meissner
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.
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.
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stdio.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winerror.h"
31 #include "winioctl.h"
32 #include "ddk/ntddser.h"
34 #include "wine/server.h"
35 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(comm);
41 /***********************************************************************
42 * COMM_Parse* (Internal)
44 * The following COMM_Parse* functions are used by the BuildCommDCB
45 * functions to help parse the various parts of the device control string.
47 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
49 static const WCHAR comW[] = {'C','O','M',0};
51 /* The device control string may optionally start with "COMx" followed
52 by an optional ':' and spaces. */
53 if(!strncmpiW(ptr, comW, 3))
55 ptr += 3;
57 /* Allow any com port above 0 as Win 9x does (NT only allows
58 values for com ports which are actually present) */
59 if(*ptr < '1' || *ptr > '9')
60 return NULL;
62 /* Advance pointer past port number */
63 while(*ptr >= '0' && *ptr <= '9') ptr++;
65 /* The com port number must be followed by a ':' or ' ' */
66 if(*ptr != ':' && *ptr != ' ')
67 return NULL;
69 /* Advance pointer to beginning of next parameter */
70 while(*ptr == ' ') ptr++;
71 if(*ptr == ':')
73 ptr++;
74 while(*ptr == ' ') ptr++;
77 /* The device control string must not start with a space. */
78 else if(*ptr == ' ')
79 return NULL;
81 return ptr;
84 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
86 if(*ptr < '0' || *ptr > '9') return NULL;
87 *lpnumber = strtoulW(ptr, NULL, 10);
88 while(*ptr >= '0' && *ptr <= '9') ptr++;
89 return ptr;
92 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
94 /* Contrary to what you might expect, Windows only sets the Parity
95 member of DCB and not fParity even when parity is specified in the
96 device control string */
98 switch(toupperW(*ptr++))
100 case 'E':
101 *lpparity = EVENPARITY;
102 break;
103 case 'M':
104 *lpparity = MARKPARITY;
105 break;
106 case 'N':
107 *lpparity = NOPARITY;
108 break;
109 case 'O':
110 *lpparity = ODDPARITY;
111 break;
112 case 'S':
113 *lpparity = SPACEPARITY;
114 break;
115 default:
116 return NULL;
119 return ptr;
122 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
124 DWORD temp;
126 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
127 return NULL;
129 if(temp >= 5 && temp <= 8)
131 *lpbytesize = temp;
132 return ptr;
134 else
135 return NULL;
138 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
140 DWORD temp;
141 static const WCHAR stopbits15W[] = {'1','.','5',0};
143 if(!strncmpW(stopbits15W, ptr, 3))
145 ptr += 3;
146 *lpstopbits = ONE5STOPBITS;
148 else
150 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
151 return NULL;
153 if(temp == 1)
154 *lpstopbits = ONESTOPBIT;
155 else if(temp == 2)
156 *lpstopbits = TWOSTOPBITS;
157 else
158 return NULL;
161 return ptr;
164 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
166 static const WCHAR onW[] = {'o','n',0};
167 static const WCHAR offW[] = {'o','f','f',0};
169 if(!strncmpiW(onW, ptr, 2))
171 ptr += 2;
172 *lponoff = 1;
174 else if(!strncmpiW(offW, ptr, 3))
176 ptr += 3;
177 *lponoff = 0;
179 else
180 return NULL;
182 return ptr;
185 /***********************************************************************
186 * COMM_BuildOldCommDCB (Internal)
188 * Build a DCB using the old style settings string eg: "96,n,8,1"
190 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
192 WCHAR last = 0;
194 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
195 return FALSE;
197 switch(lpdcb->BaudRate)
199 case 11:
200 case 30:
201 case 60:
202 lpdcb->BaudRate *= 10;
203 break;
204 case 12:
205 case 24:
206 case 48:
207 case 96:
208 lpdcb->BaudRate *= 100;
209 break;
210 case 19:
211 lpdcb->BaudRate = 19200;
212 break;
215 while(*device == ' ') device++;
216 if(*device++ != ',') return FALSE;
217 while(*device == ' ') device++;
219 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
220 return FALSE;
222 while(*device == ' ') device++;
223 if(*device++ != ',') return FALSE;
224 while(*device == ' ') device++;
226 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
227 return FALSE;
229 while(*device == ' ') device++;
230 if(*device++ != ',') return FALSE;
231 while(*device == ' ') device++;
233 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
234 return FALSE;
236 /* The last parameter for flow control is optional. */
237 while(*device == ' ') device++;
238 if(*device == ',')
240 device++;
241 while(*device == ' ') device++;
242 if(*device) last = toupperW(*device++);
243 while(*device == ' ') device++;
246 /* Win NT sets the flow control members based on (or lack of) the last
247 parameter. Win 9x does not set these members. */
248 switch(last)
250 case 0:
251 lpdcb->fInX = FALSE;
252 lpdcb->fOutX = FALSE;
253 lpdcb->fOutxCtsFlow = FALSE;
254 lpdcb->fOutxDsrFlow = FALSE;
255 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
256 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
257 break;
258 case 'X':
259 lpdcb->fInX = TRUE;
260 lpdcb->fOutX = TRUE;
261 lpdcb->fOutxCtsFlow = FALSE;
262 lpdcb->fOutxDsrFlow = FALSE;
263 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
264 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
265 break;
266 case 'P':
267 lpdcb->fInX = FALSE;
268 lpdcb->fOutX = FALSE;
269 lpdcb->fOutxCtsFlow = TRUE;
270 lpdcb->fOutxDsrFlow = TRUE;
271 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
272 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
273 break;
274 default:
275 return FALSE;
278 /* This should be the end of the string. */
279 if(*device) return FALSE;
281 return TRUE;
284 /***********************************************************************
285 * COMM_BuildNewCommDCB (Internal)
287 * Build a DCB using the new style settings string.
288 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
290 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
292 DWORD temp;
293 BOOL baud = FALSE, stop = FALSE;
294 static const WCHAR baudW[] = {'b','a','u','d','=',0};
295 static const WCHAR parityW[] = {'p','a','r','i','t','y','=',0};
296 static const WCHAR dataW[] = {'d','a','t','a','=',0};
297 static const WCHAR stopW[] = {'s','t','o','p','=',0};
298 static const WCHAR toW[] = {'t','o','=',0};
299 static const WCHAR xonW[] = {'x','o','n','=',0};
300 static const WCHAR odsrW[] = {'o','d','s','r','=',0};
301 static const WCHAR octsW[] = {'o','c','t','s','=',0};
302 static const WCHAR dtrW[] = {'d','t','r','=',0};
303 static const WCHAR rtsW[] = {'r','t','s','=',0};
304 static const WCHAR idsrW[] = {'i','d','s','r','=',0};
306 while(*device)
308 while(*device == ' ') device++;
310 if(!strncmpiW(baudW, device, 5))
312 baud = TRUE;
314 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
315 return FALSE;
317 else if(!strncmpiW(parityW, device, 7))
319 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
320 return FALSE;
322 else if(!strncmpiW(dataW, device, 5))
324 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
325 return FALSE;
327 else if(!strncmpiW(stopW, device, 5))
329 stop = TRUE;
331 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
332 return FALSE;
334 else if(!strncmpiW(toW, device, 3))
336 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
337 return FALSE;
339 lptimeouts->ReadIntervalTimeout = 0;
340 lptimeouts->ReadTotalTimeoutMultiplier = 0;
341 lptimeouts->ReadTotalTimeoutConstant = 0;
342 lptimeouts->WriteTotalTimeoutMultiplier = 0;
343 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
345 else if(!strncmpiW(xonW, device, 4))
347 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
348 return FALSE;
350 lpdcb->fOutX = temp;
351 lpdcb->fInX = temp;
353 else if(!strncmpiW(odsrW, device, 5))
355 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
356 return FALSE;
358 lpdcb->fOutxDsrFlow = temp;
360 else if(!strncmpiW(octsW, device, 5))
362 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
363 return FALSE;
365 lpdcb->fOutxCtsFlow = temp;
367 else if(!strncmpiW(dtrW, device, 4))
369 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
370 return FALSE;
372 lpdcb->fDtrControl = temp;
374 else if(!strncmpiW(rtsW, device, 4))
376 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
377 return FALSE;
379 lpdcb->fRtsControl = temp;
381 else if(!strncmpiW(idsrW, device, 5))
383 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
384 return FALSE;
386 /* Win NT sets the fDsrSensitivity member based on the
387 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
388 lpdcb->fDsrSensitivity = temp;
390 else
391 return FALSE;
393 /* After the above parsing, the next character (if not the end of
394 the string) should be a space */
395 if(*device && *device != ' ')
396 return FALSE;
399 /* If stop bits were not specified, a default is always supplied. */
400 if(!stop)
402 if(baud && lpdcb->BaudRate == 110)
403 lpdcb->StopBits = TWOSTOPBITS;
404 else
405 lpdcb->StopBits = ONESTOPBIT;
408 return TRUE;
411 /**************************************************************************
412 * BuildCommDCBA (KERNEL32.@)
414 * Updates a device control block data structure with values from an
415 * ascii device control string. The device control string has two forms
416 * normal and extended, it must be exclusively in one or the other form.
418 * RETURNS
420 * True on success, false on a malformed control string.
422 BOOL WINAPI BuildCommDCBA(
423 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
424 LPDCB lpdcb) /* [out] The device control block to be updated. */
426 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
429 /**************************************************************************
430 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
432 * Updates a device control block data structure with values from an
433 * ascii device control string. Taking timeout values from a timeouts
434 * struct if desired by the control string.
436 * RETURNS
438 * True on success, false bad handles etc.
440 BOOL WINAPI BuildCommDCBAndTimeoutsA(
441 LPCSTR device, /* [in] The ascii device control string. */
442 LPDCB lpdcb, /* [out] The device control block to be updated. */
443 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
445 BOOL ret = FALSE;
446 UNICODE_STRING deviceW;
448 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
449 if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
450 else deviceW.Buffer = NULL;
452 if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
454 RtlFreeUnicodeString(&deviceW);
455 return ret;
458 /**************************************************************************
459 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
461 * Updates a device control block data structure with values from a
462 * unicode device control string. Taking timeout values from a timeouts
463 * struct if desired by the control string.
465 * RETURNS
467 * True on success, false bad handles etc
469 BOOL WINAPI BuildCommDCBAndTimeoutsW(
470 LPCWSTR devid, /* [in] The unicode device control string. */
471 LPDCB lpdcb, /* [out] The device control block to be updated. */
472 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
474 DCB dcb;
475 COMMTIMEOUTS timeouts;
476 BOOL result;
477 LPCWSTR ptr = devid;
479 TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
481 memset(&timeouts, 0, sizeof timeouts);
483 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
484 lpdcb->DCBlength = sizeof(DCB);
486 /* Make a copy of the original data structures to work with since if
487 if there is an error in the device control string the originals
488 should not be modified (except possibly DCBlength) */
489 dcb = *lpdcb;
490 if(lptimeouts) timeouts = *lptimeouts;
492 ptr = COMM_ParseStart(ptr);
494 if(ptr == NULL)
495 result = FALSE;
496 else if(strchrW(ptr, ','))
497 result = COMM_BuildOldCommDCB(ptr, &dcb);
498 else
499 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
501 if(result)
503 *lpdcb = dcb;
504 if(lptimeouts) *lptimeouts = timeouts;
505 return TRUE;
507 else
509 WARN("Invalid device control string: %s\n", debugstr_w(devid));
510 SetLastError(ERROR_INVALID_PARAMETER);
511 return FALSE;
515 /**************************************************************************
516 * BuildCommDCBW (KERNEL32.@)
518 * Updates a device control block structure with values from an
519 * unicode device control string. The device control string has two forms
520 * normal and extended, it must be exclusively in one or the other form.
522 * RETURNS
524 * True on success, false on a malformed control string.
526 BOOL WINAPI BuildCommDCBW(
527 LPCWSTR devid, /* [in] The unicode device control string. */
528 LPDCB lpdcb) /* [out] The device control block to be updated. */
530 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
533 /*****************************************************************************
534 * SetCommBreak (KERNEL32.@)
536 * Halts the transmission of characters to a communications device.
538 * PARAMS
539 * handle [in] The communications device to suspend
541 * RETURNS
543 * True on success, and false if the communications device could not be found,
544 * the control is not supported.
546 * BUGS
548 * Only TIOCSBRK and TIOCCBRK are supported.
550 BOOL WINAPI SetCommBreak(HANDLE handle)
552 DWORD dwBytesReturned;
553 return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
556 /*****************************************************************************
557 * ClearCommBreak (KERNEL32.@)
559 * Resumes character transmission from a communication device.
561 * PARAMS
563 * handle [in] The halted communication device whose character transmission is to be resumed
565 * RETURNS
567 * True on success and false if the communications device could not be found.
569 * BUGS
571 * Only TIOCSBRK and TIOCCBRK are supported.
573 BOOL WINAPI ClearCommBreak(HANDLE handle)
575 DWORD dwBytesReturned;
576 return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
579 /*****************************************************************************
580 * EscapeCommFunction (KERNEL32.@)
582 * Directs a communication device to perform an extended function.
584 * PARAMS
586 * handle [in] The communication device to perform the extended function
587 * nFunction [in] The extended function to be performed
589 * RETURNS
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.
595 BOOL WINAPI EscapeCommFunction(HANDLE handle, UINT func)
597 DWORD ioc;
598 DWORD dwBytesReturned;
600 switch (func)
602 case CLRDTR: ioc = IOCTL_SERIAL_CLR_DTR; break;
603 case CLRRTS: ioc = IOCTL_SERIAL_CLR_RTS; break;
604 case SETDTR: ioc = IOCTL_SERIAL_SET_DTR; break;
605 case SETRTS: ioc = IOCTL_SERIAL_SET_RTS; break;
606 case SETXOFF: ioc = IOCTL_SERIAL_SET_XOFF; break;
607 case SETXON: ioc = IOCTL_SERIAL_SET_XON; break;
608 case SETBREAK: ioc = IOCTL_SERIAL_SET_BREAK_ON; break;
609 case CLRBREAK: ioc = IOCTL_SERIAL_SET_BREAK_OFF; break;
610 case RESETDEV: ioc = IOCTL_SERIAL_RESET_DEVICE; break;
611 default:
612 ERR("Unknown function code (%u)\n", func);
613 SetLastError(ERROR_INVALID_PARAMETER);
614 return FALSE;
616 return DeviceIoControl(handle, ioc, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
619 /********************************************************************
620 * PurgeComm (KERNEL32.@)
622 * Terminates pending operations and/or discards buffers on a
623 * communication resource.
625 * PARAMS
627 * handle [in] The communication resource to be purged
628 * flags [in] Flags for clear pending/buffer on input/output
630 * RETURNS
632 * True on success and false if the communications handle is bad.
634 BOOL WINAPI PurgeComm(HANDLE handle, DWORD flags)
636 DWORD dwBytesReturned;
637 return DeviceIoControl(handle, IOCTL_SERIAL_PURGE, &flags, sizeof(flags),
638 NULL, 0, &dwBytesReturned, NULL);
641 /*****************************************************************************
642 * ClearCommError (KERNEL32.@)
644 * Enables further I/O operations on a communications resource after
645 * supplying error and current status information.
647 * PARAMS
649 * handle [in] The communication resource with the error
650 * errors [out] Flags indicating error the resource experienced
651 * lpStat [out] The status of the communication resource
652 * RETURNS
654 * True on success, false if the communication resource handle is bad.
656 BOOL WINAPI ClearCommError(HANDLE handle, LPDWORD errors, LPCOMSTAT lpStat)
658 SERIAL_STATUS ss;
659 DWORD dwBytesReturned;
661 if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_COMMSTATUS, NULL, 0,
662 &ss, sizeof(ss), &dwBytesReturned, NULL))
663 return FALSE;
665 TRACE("=> status %#x,%#x, in %u, out %u, eof %d, wait %d\n", ss.Errors, ss.HoldReasons,
666 ss.AmountInInQueue, ss.AmountInOutQueue, ss.EofReceived, ss.WaitForImmediate);
668 if (errors)
670 *errors = 0;
671 if (ss.Errors & SERIAL_ERROR_BREAK) *errors |= CE_BREAK;
672 if (ss.Errors & SERIAL_ERROR_FRAMING) *errors |= CE_FRAME;
673 if (ss.Errors & SERIAL_ERROR_OVERRUN) *errors |= CE_OVERRUN;
674 if (ss.Errors & SERIAL_ERROR_QUEUEOVERRUN) *errors |= CE_RXOVER;
675 if (ss.Errors & SERIAL_ERROR_PARITY) *errors |= CE_RXPARITY;
678 if (lpStat)
680 memset(lpStat, 0, sizeof(*lpStat));
682 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_CTS) lpStat->fCtsHold = TRUE;
683 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DSR) lpStat->fDsrHold = TRUE;
684 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DCD) lpStat->fRlsdHold = TRUE;
685 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_XON) lpStat->fXoffHold = TRUE;
686 if (ss.HoldReasons & SERIAL_TX_WAITING_XOFF_SENT) lpStat->fXoffSent = TRUE;
687 if (ss.EofReceived) lpStat->fEof = TRUE;
688 if (ss.WaitForImmediate) lpStat->fTxim = TRUE;
689 lpStat->cbInQue = ss.AmountInInQueue;
690 lpStat->cbOutQue = ss.AmountInOutQueue;
692 return TRUE;
695 /*****************************************************************************
696 * SetupComm (KERNEL32.@)
698 * Called after CreateFile to hint to the communication resource to use
699 * specified sizes for input and output buffers rather than the default values.
701 * PARAMS
702 * handle [in] The just created communication resource handle
703 * insize [in] The suggested size of the communication resources input buffer in bytes
704 * outsize [in] The suggested size of the communication resources output buffer in bytes
706 * RETURNS
708 * True if successful, false if the communications resource handle is bad.
710 * BUGS
712 * Stub.
714 BOOL WINAPI SetupComm(HANDLE handle, DWORD insize, DWORD outsize)
716 SERIAL_QUEUE_SIZE sqs;
717 DWORD dwBytesReturned;
719 sqs.InSize = insize;
720 sqs.OutSize = outsize;
721 return DeviceIoControl(handle, IOCTL_SERIAL_SET_QUEUE_SIZE,
722 &sqs, sizeof(sqs), NULL, 0, &dwBytesReturned, NULL);
725 /*****************************************************************************
726 * GetCommMask (KERNEL32.@)
728 * Obtain the events associated with a communication device that will cause
729 * a call WaitCommEvent to return.
731 * PARAMS
733 * handle [in] The communications device
734 * evtmask [out] The events which cause WaitCommEvent to return
736 * RETURNS
738 * True on success, fail on bad device handle etc.
740 BOOL WINAPI GetCommMask(HANDLE handle, LPDWORD evtmask)
742 DWORD dwBytesReturned;
743 TRACE("handle %p, mask %p\n", handle, evtmask);
744 return DeviceIoControl(handle, IOCTL_SERIAL_GET_WAIT_MASK,
745 NULL, 0, evtmask, sizeof(*evtmask), &dwBytesReturned, NULL);
748 /*****************************************************************************
749 * SetCommMask (KERNEL32.@)
751 * There be some things we need to hear about yon there communications device.
752 * (Set which events associated with a communication device should cause
753 * a call WaitCommEvent to return.)
755 * PARAMS
757 * handle [in] The communications device
758 * evtmask [in] The events that are to be monitored
760 * RETURNS
762 * True on success, false on bad handle etc.
764 BOOL WINAPI SetCommMask(HANDLE handle, DWORD evtmask)
766 DWORD dwBytesReturned;
767 TRACE("handle %p, mask %x\n", handle, evtmask);
768 return DeviceIoControl(handle, IOCTL_SERIAL_SET_WAIT_MASK,
769 &evtmask, sizeof(evtmask), NULL, 0, &dwBytesReturned, NULL);
772 static void dump_dcb(const DCB* lpdcb)
774 TRACE("bytesize=%d baudrate=%d fParity=%d Parity=%d stopbits=%d\n",
775 lpdcb->ByteSize, lpdcb->BaudRate, lpdcb->fParity, lpdcb->Parity,
776 (lpdcb->StopBits == ONESTOPBIT) ? 1 :
777 (lpdcb->StopBits == TWOSTOPBITS) ? 2 : 0);
778 TRACE("%sIXON %sIXOFF\n", (lpdcb->fOutX) ? "" : "~", (lpdcb->fInX) ? "" : "~");
779 TRACE("fOutxCtsFlow=%d fRtsControl=%d\n", lpdcb->fOutxCtsFlow, lpdcb->fRtsControl);
780 TRACE("fOutxDsrFlow=%d fDtrControl=%d\n", lpdcb->fOutxDsrFlow, lpdcb->fDtrControl);
781 if (lpdcb->fOutxCtsFlow || lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE)
782 TRACE("CRTSCTS\n");
783 else
784 TRACE("~CRTSCTS\n");
787 /*****************************************************************************
788 * SetCommState (KERNEL32.@)
790 * Re-initializes all hardware and control settings of a communications device,
791 * with values from a device control block without affecting the input and output
792 * queues.
794 * PARAMS
796 * handle [in] The communications device
797 * lpdcb [out] The device control block
799 * RETURNS
801 * True on success, false on failure, e.g., if the XonChar is equal to the XoffChar.
803 BOOL WINAPI SetCommState( HANDLE handle, LPDCB lpdcb)
805 SERIAL_BAUD_RATE sbr;
806 SERIAL_LINE_CONTROL slc;
807 SERIAL_HANDFLOW shf;
808 SERIAL_CHARS sc;
809 DWORD dwBytesReturned;
811 if (lpdcb == NULL)
813 SetLastError(ERROR_INVALID_PARAMETER);
814 return FALSE;
816 dump_dcb(lpdcb);
818 sbr.BaudRate = lpdcb->BaudRate;
820 slc.StopBits = lpdcb->StopBits;
821 slc.Parity = lpdcb->Parity;
822 slc.WordLength = lpdcb->ByteSize;
824 shf.ControlHandShake = 0;
825 shf.FlowReplace = 0;
826 if (lpdcb->fOutxCtsFlow) shf.ControlHandShake |= SERIAL_CTS_HANDSHAKE;
827 if (lpdcb->fOutxDsrFlow) shf.ControlHandShake |= SERIAL_DSR_HANDSHAKE;
828 switch (lpdcb->fDtrControl)
830 case DTR_CONTROL_DISABLE: break;
831 case DTR_CONTROL_ENABLE: shf.ControlHandShake |= SERIAL_DTR_CONTROL; break;
832 case DTR_CONTROL_HANDSHAKE: shf.ControlHandShake |= SERIAL_DTR_HANDSHAKE;break;
833 default:
834 SetLastError(ERROR_INVALID_PARAMETER);
835 return FALSE;
837 switch (lpdcb->fRtsControl)
839 case RTS_CONTROL_DISABLE: break;
840 case RTS_CONTROL_ENABLE: shf.FlowReplace |= SERIAL_RTS_CONTROL; break;
841 case RTS_CONTROL_HANDSHAKE: shf.FlowReplace |= SERIAL_RTS_HANDSHAKE; break;
842 case RTS_CONTROL_TOGGLE: shf.FlowReplace |= SERIAL_RTS_CONTROL |
843 SERIAL_RTS_HANDSHAKE; break;
844 default:
845 SetLastError(ERROR_INVALID_PARAMETER);
846 return FALSE;
848 if (lpdcb->fDsrSensitivity) shf.ControlHandShake |= SERIAL_DSR_SENSITIVITY;
849 if (lpdcb->fAbortOnError) shf.ControlHandShake |= SERIAL_ERROR_ABORT;
851 if (lpdcb->fErrorChar) shf.FlowReplace |= SERIAL_ERROR_CHAR;
852 if (lpdcb->fNull) shf.FlowReplace |= SERIAL_NULL_STRIPPING;
853 if (lpdcb->fTXContinueOnXoff) shf.FlowReplace |= SERIAL_XOFF_CONTINUE;
854 if (lpdcb->fOutX) shf.FlowReplace |= SERIAL_AUTO_TRANSMIT;
855 if (lpdcb->fInX) shf.FlowReplace |= SERIAL_AUTO_RECEIVE;
857 shf.XonLimit = lpdcb->XonLim;
858 shf.XoffLimit = lpdcb->XoffLim;
860 sc.EofChar = lpdcb->EofChar;
861 sc.ErrorChar = lpdcb->ErrorChar;
862 sc.BreakChar = 0;
863 sc.EventChar = lpdcb->EvtChar;
864 sc.XonChar = lpdcb->XonChar;
865 sc.XoffChar = lpdcb->XoffChar;
867 /* note: change DTR/RTS lines after setting the comm attributes,
868 * so flow control does not interfere.
870 return (DeviceIoControl(handle, IOCTL_SERIAL_SET_BAUD_RATE,
871 &sbr, sizeof(sbr), NULL, 0, &dwBytesReturned, NULL) &&
872 DeviceIoControl(handle, IOCTL_SERIAL_SET_LINE_CONTROL,
873 &slc, sizeof(slc), NULL, 0, &dwBytesReturned, NULL) &&
874 DeviceIoControl(handle, IOCTL_SERIAL_SET_HANDFLOW,
875 &shf, sizeof(shf), NULL, 0, &dwBytesReturned, NULL) &&
876 DeviceIoControl(handle, IOCTL_SERIAL_SET_CHARS,
877 &sc, sizeof(sc), NULL, 0, &dwBytesReturned, NULL));
881 /*****************************************************************************
882 * GetCommState (KERNEL32.@)
884 * Fills in a device control block with information from a communications device.
886 * PARAMS
887 * handle [in] The communications device
888 * lpdcb [out] The device control block
890 * RETURNS
892 * True on success, false if the communication device handle is bad etc
894 * BUGS
896 * XonChar and XoffChar are not set.
898 BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb)
900 SERIAL_BAUD_RATE sbr;
901 SERIAL_LINE_CONTROL slc;
902 SERIAL_HANDFLOW shf;
903 SERIAL_CHARS sc;
904 DWORD dwBytesReturned;
906 TRACE("handle %p, ptr %p\n", handle, lpdcb);
908 if (!lpdcb)
910 SetLastError(ERROR_INVALID_PARAMETER);
911 return FALSE;
914 if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_BAUD_RATE,
915 NULL, 0, &sbr, sizeof(sbr), &dwBytesReturned, NULL) ||
916 !DeviceIoControl(handle, IOCTL_SERIAL_GET_LINE_CONTROL,
917 NULL, 0, &slc, sizeof(slc), &dwBytesReturned, NULL) ||
918 !DeviceIoControl(handle, IOCTL_SERIAL_GET_HANDFLOW,
919 NULL, 0, &shf, sizeof(shf), &dwBytesReturned, NULL) ||
920 !DeviceIoControl(handle, IOCTL_SERIAL_GET_CHARS,
921 NULL, 0, &sc, sizeof(sc), &dwBytesReturned, NULL))
922 return FALSE;
924 memset(lpdcb, 0, sizeof(*lpdcb));
925 lpdcb->DCBlength = sizeof(*lpdcb);
927 /* yes, they seem no never be (re)set on NT */
928 lpdcb->fBinary = 1;
929 lpdcb->fParity = 0;
931 lpdcb->BaudRate = sbr.BaudRate;
933 lpdcb->StopBits = slc.StopBits;
934 lpdcb->Parity = slc.Parity;
935 lpdcb->ByteSize = slc.WordLength;
937 if (shf.ControlHandShake & SERIAL_CTS_HANDSHAKE) lpdcb->fOutxCtsFlow = 1;
938 if (shf.ControlHandShake & SERIAL_DSR_HANDSHAKE) lpdcb->fOutxDsrFlow = 1;
939 switch (shf.ControlHandShake & (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE))
941 case 0: lpdcb->fDtrControl = DTR_CONTROL_DISABLE; break;
942 case SERIAL_DTR_CONTROL: lpdcb->fDtrControl = DTR_CONTROL_ENABLE; break;
943 case SERIAL_DTR_HANDSHAKE: lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE; break;
945 switch (shf.FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE))
947 case 0: lpdcb->fRtsControl = RTS_CONTROL_DISABLE; break;
948 case SERIAL_RTS_CONTROL: lpdcb->fRtsControl = RTS_CONTROL_ENABLE; break;
949 case SERIAL_RTS_HANDSHAKE: lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE; break;
950 case SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE:
951 lpdcb->fRtsControl = RTS_CONTROL_TOGGLE; break;
953 if (shf.ControlHandShake & SERIAL_DSR_SENSITIVITY) lpdcb->fDsrSensitivity = 1;
954 if (shf.ControlHandShake & SERIAL_ERROR_ABORT) lpdcb->fAbortOnError = 1;
955 if (shf.FlowReplace & SERIAL_ERROR_CHAR) lpdcb->fErrorChar = 1;
956 if (shf.FlowReplace & SERIAL_NULL_STRIPPING) lpdcb->fNull = 1;
957 if (shf.FlowReplace & SERIAL_XOFF_CONTINUE) lpdcb->fTXContinueOnXoff = 1;
958 lpdcb->XonLim = shf.XonLimit;
959 lpdcb->XoffLim = shf.XoffLimit;
961 if (shf.FlowReplace & SERIAL_AUTO_TRANSMIT) lpdcb->fOutX = 1;
962 if (shf.FlowReplace & SERIAL_AUTO_RECEIVE) lpdcb->fInX = 1;
964 lpdcb->EofChar = sc.EofChar;
965 lpdcb->ErrorChar = sc.ErrorChar;
966 lpdcb->EvtChar = sc.EventChar;
967 lpdcb->XonChar = sc.XonChar;
968 lpdcb->XoffChar = sc.XoffChar;
970 TRACE("OK\n");
971 dump_dcb(lpdcb);
973 return TRUE;
976 /*****************************************************************************
977 * TransmitCommChar (KERNEL32.@)
979 * Transmits a single character in front of any pending characters in the
980 * output buffer. Usually used to send an interrupt character to a host.
982 * PARAMS
983 * hComm [in] The communication device in need of a command character
984 * chTransmit [in] The character to transmit
986 * RETURNS
988 * True if the call succeeded, false if the previous command character to the
989 * same device has not been sent yet the handle is bad etc.
992 BOOL WINAPI TransmitCommChar(HANDLE hComm, CHAR chTransmit)
994 DWORD dwBytesReturned;
995 return DeviceIoControl(hComm, IOCTL_SERIAL_IMMEDIATE_CHAR,
996 &chTransmit, sizeof(chTransmit), NULL, 0, &dwBytesReturned, NULL);
1000 /*****************************************************************************
1001 * GetCommTimeouts (KERNEL32.@)
1003 * Obtains the request timeout values for the communications device.
1005 * PARAMS
1006 * hComm [in] The communications device
1007 * lptimeouts [out] The struct of request timeouts
1009 * RETURNS
1011 * True on success, false if communications device handle is bad
1012 * or the target structure is null.
1014 BOOL WINAPI GetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts)
1016 SERIAL_TIMEOUTS st;
1017 DWORD dwBytesReturned;
1019 TRACE("(%p, %p)\n", hComm, lptimeouts);
1020 if (!lptimeouts)
1022 SetLastError(ERROR_INVALID_PARAMETER);
1023 return FALSE;
1025 if (!DeviceIoControl(hComm, IOCTL_SERIAL_GET_TIMEOUTS,
1026 NULL, 0, &st, sizeof(st), &dwBytesReturned, NULL))
1027 return FALSE;
1028 lptimeouts->ReadIntervalTimeout = st.ReadIntervalTimeout;
1029 lptimeouts->ReadTotalTimeoutMultiplier = st.ReadTotalTimeoutMultiplier;
1030 lptimeouts->ReadTotalTimeoutConstant = st.ReadTotalTimeoutConstant;
1031 lptimeouts->WriteTotalTimeoutMultiplier = st.WriteTotalTimeoutMultiplier;
1032 lptimeouts->WriteTotalTimeoutConstant = st.WriteTotalTimeoutConstant;
1033 return TRUE;
1036 /*****************************************************************************
1037 * SetCommTimeouts (KERNEL32.@)
1039 * Sets the timeouts used when reading and writing data to/from COMM ports.
1041 * PARAMS
1042 * hComm [in] handle of COMM device
1043 * lptimeouts [in] pointer to COMMTIMEOUTS structure
1045 * ReadIntervalTimeout
1046 * - converted and passes to linux kernel as c_cc[VTIME]
1047 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1048 * - used in ReadFile to calculate GetOverlappedResult's timeout
1049 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1050 * - used in WriteFile to calculate GetOverlappedResult's timeout
1052 * RETURNS
1054 * True if the timeouts were set, false otherwise.
1056 BOOL WINAPI SetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts)
1058 SERIAL_TIMEOUTS st;
1059 DWORD dwBytesReturned;
1061 TRACE("(%p, %p)\n", hComm, lptimeouts);
1063 if (lptimeouts == NULL)
1065 SetLastError(ERROR_INVALID_PARAMETER);
1066 return FALSE;
1068 st.ReadIntervalTimeout = lptimeouts->ReadIntervalTimeout;
1069 st.ReadTotalTimeoutMultiplier = lptimeouts->ReadTotalTimeoutMultiplier;
1070 st.ReadTotalTimeoutConstant = lptimeouts->ReadTotalTimeoutConstant;
1071 st.WriteTotalTimeoutMultiplier = lptimeouts->WriteTotalTimeoutMultiplier;
1072 st.WriteTotalTimeoutConstant = lptimeouts->WriteTotalTimeoutConstant;
1074 return DeviceIoControl(hComm, IOCTL_SERIAL_SET_TIMEOUTS,
1075 &st, sizeof(st), NULL, 0, &dwBytesReturned, NULL);
1078 /***********************************************************************
1079 * GetCommModemStatus (KERNEL32.@)
1081 * Obtains the four control register bits if supported by the hardware.
1083 * PARAMS
1085 * hFile [in] The communications device
1086 * lpModemStat [out] The control register bits
1088 * RETURNS
1090 * True if the communications handle was good and for hardware that
1091 * control register access, false otherwise.
1093 BOOL WINAPI GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat)
1095 DWORD dwBytesReturned;
1096 return DeviceIoControl(hFile, IOCTL_SERIAL_GET_MODEMSTATUS,
1097 NULL, 0, lpModemStat, sizeof(DWORD), &dwBytesReturned, NULL);
1100 /***********************************************************************
1101 * WaitCommEvent (KERNEL32.@)
1103 * Wait until something interesting happens on a COMM port.
1104 * Interesting things (events) are set by calling SetCommMask before
1105 * this function is called.
1107 * RETURNS
1108 * TRUE if successful
1109 * FALSE if failure
1111 * The set of detected events will be written to *lpdwEventMask
1112 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1114 * BUGS:
1115 * Only supports EV_RXCHAR and EV_TXEMPTY
1117 BOOL WINAPI WaitCommEvent(
1118 HANDLE hFile, /* [in] handle of comm port to wait for */
1119 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1120 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1122 return DeviceIoControl(hFile, IOCTL_SERIAL_WAIT_ON_MASK, NULL, 0,
1123 lpdwEvents, sizeof(DWORD), NULL, lpOverlapped);
1126 /***********************************************************************
1127 * GetCommProperties (KERNEL32.@)
1129 * This function fills in a structure with the capabilities of the
1130 * communications port driver.
1132 * RETURNS
1134 * TRUE on success, FALSE on failure
1135 * If successful, the lpCommProp structure be filled in with
1136 * properties of the comm port.
1138 BOOL WINAPI GetCommProperties(
1139 HANDLE hFile, /* [in] handle of the comm port */
1140 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
1142 TRACE("(%p %p)\n",hFile,lpCommProp);
1143 if(!lpCommProp)
1144 return FALSE;
1147 * These values should be valid for LINUX's serial driver
1148 * FIXME: Perhaps they deserve an #ifdef LINUX
1150 memset(lpCommProp,0,sizeof(COMMPROP));
1151 lpCommProp->wPacketLength = 1;
1152 lpCommProp->wPacketVersion = 1;
1153 lpCommProp->dwServiceMask = SP_SERIALCOMM;
1154 lpCommProp->dwMaxTxQueue = 4096;
1155 lpCommProp->dwMaxRxQueue = 4096;
1156 lpCommProp->dwMaxBaud = BAUD_115200;
1157 lpCommProp->dwProvSubType = PST_RS232;
1158 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS | PCF_INTTIMEOUTS;
1159 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
1160 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
1161 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
1162 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
1163 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
1164 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
1165 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
1166 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
1167 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
1168 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
1170 return TRUE;
1173 /***********************************************************************
1174 * FIXME:
1175 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
1176 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
1177 * This is dependent on the type of COMM port, but since it is doubtful
1178 * anybody will get around to implementing support for fancy serial
1179 * ports in WINE, this is hardcoded for the time being. The name of
1180 * this DLL should be stored in and read from the system registry in
1181 * the hive HKEY_LOCAL_MACHINE, key
1182 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
1183 * where ???? is the port number... that is determined by PNP
1184 * The DLL should be loaded when the COMM port is opened, and closed
1185 * when the COMM port is closed. - MJM 20 June 2000
1186 ***********************************************************************/
1187 static const WCHAR lpszSerialUI[] = {
1188 's','e','r','i','a','l','u','i','.','d','l','l',0 };
1191 /***********************************************************************
1192 * CommConfigDialogA (KERNEL32.@)
1194 * Raises a dialog that allows the user to configure a comm port.
1195 * Fills the COMMCONFIG struct with information specified by the user.
1196 * This function should call a similar routine in the COMM driver...
1198 * RETURNS
1200 * TRUE on success, FALSE on failure
1201 * If successful, the lpCommConfig structure will contain a new
1202 * configuration for the comm port, as specified by the user.
1204 * BUGS
1205 * The library with the CommConfigDialog code is never unloaded.
1206 * Perhaps this should be done when the comm port is closed?
1208 BOOL WINAPI CommConfigDialogA(
1209 LPCSTR lpszDevice, /* [in] name of communications device */
1210 HWND hWnd, /* [in] parent window for the dialog */
1211 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1213 LPWSTR lpDeviceW = NULL;
1214 DWORD len;
1215 BOOL r;
1217 TRACE("(%s, %p, %p)\n", debugstr_a(lpszDevice), hWnd, lpCommConfig);
1219 if (lpszDevice)
1221 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
1222 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
1223 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
1225 r = CommConfigDialogW(lpDeviceW, hWnd, lpCommConfig);
1226 HeapFree( GetProcessHeap(), 0, lpDeviceW );
1227 return r;
1230 /***********************************************************************
1231 * CommConfigDialogW (KERNEL32.@)
1233 * See CommConfigDialogA.
1235 BOOL WINAPI CommConfigDialogW(
1236 LPCWSTR lpszDevice, /* [in] name of communications device */
1237 HWND hWnd, /* [in] parent window for the dialog */
1238 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
1240 DWORD (WINAPI *pCommConfigDialog)(LPCWSTR, HWND, LPCOMMCONFIG);
1241 HMODULE hConfigModule;
1242 DWORD res = ERROR_INVALID_PARAMETER;
1244 TRACE("(%s, %p, %p)\n", debugstr_w(lpszDevice), hWnd, lpCommConfig);
1245 hConfigModule = LoadLibraryW(lpszSerialUI);
1247 if (hConfigModule) {
1248 pCommConfigDialog = (void *)GetProcAddress(hConfigModule, "drvCommConfigDialogW");
1249 if (pCommConfigDialog) {
1250 res = pCommConfigDialog(lpszDevice, hWnd, lpCommConfig);
1252 FreeLibrary(hConfigModule);
1255 if (res) SetLastError(res);
1256 return (res == ERROR_SUCCESS);
1259 /***********************************************************************
1260 * GetCommConfig (KERNEL32.@)
1262 * Fill in the COMMCONFIG structure for the comm port hFile
1264 * RETURNS
1266 * TRUE on success, FALSE on failure
1267 * If successful, lpCommConfig contains the comm port configuration.
1269 * BUGS
1272 BOOL WINAPI GetCommConfig(
1273 HANDLE hFile, /* [in] The communications device. */
1274 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
1275 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
1276 afterwards the number of bytes copied to the buffer or
1277 the needed size of the buffer. */
1279 BOOL r;
1281 TRACE("(%p, %p, %p) *lpdwSize: %u\n", hFile, lpCommConfig, lpdwSize, lpdwSize ? *lpdwSize : 0 );
1283 if(lpCommConfig == NULL)
1284 return FALSE;
1285 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
1286 *lpdwSize = sizeof(COMMCONFIG);
1287 if(r)
1288 return FALSE;
1290 lpCommConfig->dwSize = sizeof(COMMCONFIG);
1291 lpCommConfig->wVersion = 1;
1292 lpCommConfig->wReserved = 0;
1293 r = GetCommState(hFile,&lpCommConfig->dcb);
1294 lpCommConfig->dwProviderSubType = PST_RS232;
1295 lpCommConfig->dwProviderOffset = 0;
1296 lpCommConfig->dwProviderSize = 0;
1298 return r;
1301 /***********************************************************************
1302 * SetCommConfig (KERNEL32.@)
1304 * Sets the configuration of the communications device.
1306 * RETURNS
1308 * True on success, false if the handle was bad is not a communications device.
1310 BOOL WINAPI SetCommConfig(
1311 HANDLE hFile, /* [in] The communications device. */
1312 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
1313 DWORD dwSize) /* [in] size of the lpCommConfig struct */
1315 TRACE("(%p, %p, %u)\n", hFile, lpCommConfig, dwSize);
1316 return SetCommState(hFile,&lpCommConfig->dcb);
1319 /***********************************************************************
1320 * SetDefaultCommConfigW (KERNEL32.@)
1322 * Initializes the default configuration for a communication device.
1324 * PARAMS
1325 * lpszDevice [I] Name of the device targeted for configuration
1326 * lpCommConfig [I] PTR to a buffer with the configuration for the device
1327 * dwSize [I] Number of bytes in the buffer
1329 * RETURNS
1330 * Failure: FALSE
1331 * Success: TRUE, and default configuration saved
1334 BOOL WINAPI SetDefaultCommConfigW(LPCWSTR lpszDevice, LPCOMMCONFIG lpCommConfig, DWORD dwSize)
1336 BOOL (WINAPI *lpfnSetDefaultCommConfig)(LPCWSTR, LPCOMMCONFIG, DWORD);
1337 HMODULE hConfigModule;
1338 BOOL r = FALSE;
1340 TRACE("(%s, %p, %u)\n", debugstr_w(lpszDevice), lpCommConfig, dwSize);
1342 hConfigModule = LoadLibraryW(lpszSerialUI);
1343 if(!hConfigModule)
1344 return r;
1346 lpfnSetDefaultCommConfig = (void *)GetProcAddress(hConfigModule, "drvSetDefaultCommConfigW");
1347 if (lpfnSetDefaultCommConfig)
1348 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
1350 FreeLibrary(hConfigModule);
1352 return r;
1356 /***********************************************************************
1357 * SetDefaultCommConfigA (KERNEL32.@)
1359 * Initializes the default configuration for a communication device.
1361 * See SetDefaultCommConfigW.
1364 BOOL WINAPI SetDefaultCommConfigA(LPCSTR lpszDevice, LPCOMMCONFIG lpCommConfig, DWORD dwSize)
1366 BOOL r;
1367 LPWSTR lpDeviceW = NULL;
1368 DWORD len;
1370 TRACE("(%s, %p, %u)\n", debugstr_a(lpszDevice), lpCommConfig, dwSize);
1372 if (lpszDevice)
1374 len = MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, NULL, 0 );
1375 lpDeviceW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
1376 MultiByteToWideChar( CP_ACP, 0, lpszDevice, -1, lpDeviceW, len );
1378 r = SetDefaultCommConfigW(lpDeviceW,lpCommConfig,dwSize);
1379 HeapFree( GetProcessHeap(), 0, lpDeviceW );
1380 return r;
1384 /***********************************************************************
1385 * GetDefaultCommConfigW (KERNEL32.@)
1387 * Acquires the default configuration of the specified communication device. (unicode)
1389 * RETURNS
1391 * True on successful reading of the default configuration,
1392 * if the device is not found or the buffer is too small.
1394 BOOL WINAPI GetDefaultCommConfigW(
1395 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
1396 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
1397 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
1398 afterwards the number of bytes copied to the buffer or
1399 the needed size of the buffer. */
1401 DWORD (WINAPI *pGetDefaultCommConfig)(LPCWSTR, LPCOMMCONFIG, LPDWORD);
1402 HMODULE hConfigModule;
1403 DWORD res = ERROR_INVALID_PARAMETER;
1405 TRACE("(%s, %p, %p) *lpdwSize: %u\n", debugstr_w(lpszName), lpCC, lpdwSize, lpdwSize ? *lpdwSize : 0 );
1406 hConfigModule = LoadLibraryW(lpszSerialUI);
1408 if (hConfigModule) {
1409 pGetDefaultCommConfig = (void *)GetProcAddress(hConfigModule, "drvGetDefaultCommConfigW");
1410 if (pGetDefaultCommConfig) {
1411 res = pGetDefaultCommConfig(lpszName, lpCC, lpdwSize);
1413 FreeLibrary(hConfigModule);
1416 if (res) SetLastError(res);
1417 return (res == ERROR_SUCCESS);
1420 /**************************************************************************
1421 * GetDefaultCommConfigA (KERNEL32.@)
1423 * Acquires the default configuration of the specified communication device. (ascii)
1425 * RETURNS
1427 * True on successful reading of the default configuration,
1428 * if the device is not found or the buffer is too small.
1430 BOOL WINAPI GetDefaultCommConfigA(
1431 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
1432 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
1433 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
1434 afterwards the number of bytes copied to the buffer or
1435 the needed size of the buffer. */
1437 BOOL ret = FALSE;
1438 UNICODE_STRING lpszNameW;
1440 TRACE("(%s, %p, %p) *lpdwSize: %u\n", debugstr_a(lpszName), lpCC, lpdwSize, lpdwSize ? *lpdwSize : 0 );
1441 if(lpszName) RtlCreateUnicodeStringFromAsciiz(&lpszNameW,lpszName);
1442 else lpszNameW.Buffer = NULL;
1444 ret = GetDefaultCommConfigW(lpszNameW.Buffer,lpCC,lpdwSize);
1446 RtlFreeUnicodeString(&lpszNameW);
1447 return ret;