configure: Changes from running autconf after previous patch.
[wine/hacks.git] / dlls / kernel32 / comm.c
blobf4edfd3650188f7d1d5bce32260e0a0476722777
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 #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"
36 #include "wine/server.h"
37 #include "wine/unicode.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(comm);
43 /***********************************************************************
44 * COMM_Parse* (Internal)
46 * The following COMM_Parse* functions are used by the BuildCommDCB
47 * functions to help parse the various parts of the device control string.
49 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
51 static const WCHAR comW[] = {'C','O','M',0};
53 /* The device control string may optionally start with "COMx" followed
54 by an optional ':' and spaces. */
55 if(!strncmpiW(ptr, comW, 3))
57 ptr += 3;
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;
64 /* Advance pointer past port number */
65 while(*ptr >= '0' && *ptr <= '9') ptr++;
67 /* The com port number must be followed by a ':' or ' ' */
68 if(*ptr != ':' && *ptr != ' ')
69 return NULL;
71 /* Advance pointer to beginning of next parameter */
72 while(*ptr == ' ') ptr++;
73 if(*ptr == ':')
75 ptr++;
76 while(*ptr == ' ') ptr++;
79 /* The device control string must not start with a space. */
80 else if(*ptr == ' ')
81 return NULL;
83 return ptr;
86 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
88 if(*ptr < '0' || *ptr > '9') return NULL;
89 *lpnumber = strtoulW(ptr, NULL, 10);
90 while(*ptr >= '0' && *ptr <= '9') ptr++;
91 return ptr;
94 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
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 */
100 switch(toupperW(*ptr++))
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;
121 return ptr;
124 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
126 DWORD temp;
128 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
129 return NULL;
131 if(temp >= 5 && temp <= 8)
133 *lpbytesize = temp;
134 return ptr;
136 else
137 return NULL;
140 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
142 DWORD temp;
143 static const WCHAR stopbits15W[] = {'1','.','5',0};
145 if(!strncmpW(stopbits15W, ptr, 3))
147 ptr += 3;
148 *lpstopbits = ONE5STOPBITS;
150 else
152 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
153 return NULL;
155 if(temp == 1)
156 *lpstopbits = ONESTOPBIT;
157 else if(temp == 2)
158 *lpstopbits = TWOSTOPBITS;
159 else
160 return NULL;
163 return ptr;
166 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
168 static const WCHAR onW[] = {'o','n',0};
169 static const WCHAR offW[] = {'o','f','f',0};
171 if(!strncmpiW(onW, ptr, 2))
173 ptr += 2;
174 *lponoff = 1;
176 else if(!strncmpiW(offW, ptr, 3))
178 ptr += 3;
179 *lponoff = 0;
181 else
182 return NULL;
184 return ptr;
187 /***********************************************************************
188 * COMM_BuildOldCommDCB (Internal)
190 * Build a DCB using the old style settings string eg: "96,n,8,1"
192 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
194 WCHAR last = 0;
196 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
197 return FALSE;
199 switch(lpdcb->BaudRate)
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;
217 while(*device == ' ') device++;
218 if(*device++ != ',') return FALSE;
219 while(*device == ' ') device++;
221 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
222 return FALSE;
224 while(*device == ' ') device++;
225 if(*device++ != ',') return FALSE;
226 while(*device == ' ') device++;
228 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
229 return FALSE;
231 while(*device == ' ') device++;
232 if(*device++ != ',') return FALSE;
233 while(*device == ' ') device++;
235 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
236 return FALSE;
238 /* The last parameter for flow control is optional. */
239 while(*device == ' ') device++;
240 if(*device == ',')
242 device++;
243 while(*device == ' ') device++;
244 if(*device) last = toupperW(*device++);
245 while(*device == ' ') device++;
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)
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;
280 /* This should be the end of the string. */
281 if(*device) return FALSE;
283 return TRUE;
286 /***********************************************************************
287 * COMM_BuildNewCommDCB (Internal)
289 * Build a DCB using the new style settings string.
290 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
292 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
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};
308 while(*device)
310 while(*device == ' ') device++;
312 if(!strncmpiW(baudW, device, 5))
314 baud = TRUE;
316 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
317 return FALSE;
319 else if(!strncmpiW(parityW, device, 7))
321 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
322 return FALSE;
324 else if(!strncmpiW(dataW, device, 5))
326 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
327 return FALSE;
329 else if(!strncmpiW(stopW, device, 5))
331 stop = TRUE;
333 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
334 return FALSE;
336 else if(!strncmpiW(toW, device, 3))
338 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
339 return FALSE;
341 lptimeouts->ReadIntervalTimeout = 0;
342 lptimeouts->ReadTotalTimeoutMultiplier = 0;
343 lptimeouts->ReadTotalTimeoutConstant = 0;
344 lptimeouts->WriteTotalTimeoutMultiplier = 0;
345 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
347 else if(!strncmpiW(xonW, device, 4))
349 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
350 return FALSE;
352 lpdcb->fOutX = temp;
353 lpdcb->fInX = temp;
355 else if(!strncmpiW(odsrW, device, 5))
357 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
358 return FALSE;
360 lpdcb->fOutxDsrFlow = temp;
362 else if(!strncmpiW(octsW, device, 5))
364 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
365 return FALSE;
367 lpdcb->fOutxCtsFlow = temp;
369 else if(!strncmpiW(dtrW, device, 4))
371 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
372 return FALSE;
374 lpdcb->fDtrControl = temp;
376 else if(!strncmpiW(rtsW, device, 4))
378 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
379 return FALSE;
381 lpdcb->fRtsControl = temp;
383 else if(!strncmpiW(idsrW, device, 5))
385 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
386 return FALSE;
388 /* Win NT sets the fDsrSensitivity member based on the
389 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
390 lpdcb->fDsrSensitivity = temp;
392 else
393 return FALSE;
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;
401 /* If stop bits were not specified, a default is always supplied. */
402 if(!stop)
404 if(baud && lpdcb->BaudRate == 110)
405 lpdcb->StopBits = TWOSTOPBITS;
406 else
407 lpdcb->StopBits = ONESTOPBIT;
410 return TRUE;
413 /**************************************************************************
414 * BuildCommDCBA (KERNEL32.@)
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.
420 * RETURNS
422 * True on success, false on a malformed control string.
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. */
428 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
431 /**************************************************************************
432 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
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.
438 * RETURNS
440 * True on success, false bad handles etc.
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. */
447 BOOL ret = FALSE;
448 UNICODE_STRING deviceW;
450 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
451 if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
452 else deviceW.Buffer = NULL;
454 if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
456 RtlFreeUnicodeString(&deviceW);
457 return ret;
460 /**************************************************************************
461 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
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.
467 * RETURNS
469 * True on success, false bad handles etc
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. */
476 DCB dcb;
477 COMMTIMEOUTS timeouts;
478 BOOL result;
479 LPCWSTR ptr = devid;
481 TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
483 memset(&timeouts, 0, sizeof timeouts);
485 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
486 lpdcb->DCBlength = sizeof(DCB);
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;
494 ptr = COMM_ParseStart(ptr);
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);
503 if(result)
505 *lpdcb = dcb;
506 if(lptimeouts) *lptimeouts = timeouts;
507 return TRUE;
509 else
511 WARN("Invalid device control string: %s\n", debugstr_w(devid));
512 SetLastError(ERROR_INVALID_PARAMETER);
513 return FALSE;
517 /**************************************************************************
518 * BuildCommDCBW (KERNEL32.@)
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.
524 * RETURNS
526 * True on success, false on a malformed control string.
528 BOOL WINAPI BuildCommDCBW(
529 LPCWSTR devid, /* [in] The unicode device control string. */
530 LPDCB lpdcb) /* [out] The device control block to be updated. */
532 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
535 /*****************************************************************************
536 * SetCommBreak (KERNEL32.@)
538 * Halts the transmission of characters to a communications device.
540 * PARAMS
541 * handle [in] The communications device to suspend
543 * RETURNS
545 * True on success, and false if the communications device could not be found,
546 * the control is not supported.
548 * BUGS
550 * Only TIOCSBRK and TIOCCBRK are supported.
552 BOOL WINAPI SetCommBreak(HANDLE handle)
554 DWORD dwBytesReturned;
555 return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_ON, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
558 /*****************************************************************************
559 * ClearCommBreak (KERNEL32.@)
561 * Resumes character transmission from a communication device.
563 * PARAMS
565 * handle [in] The halted communication device whose character transmission is to be resumed
567 * RETURNS
569 * True on success and false if the communications device could not be found.
571 * BUGS
573 * Only TIOCSBRK and TIOCCBRK are supported.
575 BOOL WINAPI ClearCommBreak(HANDLE handle)
577 DWORD dwBytesReturned;
578 return DeviceIoControl(handle, IOCTL_SERIAL_SET_BREAK_OFF, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
581 /*****************************************************************************
582 * EscapeCommFunction (KERNEL32.@)
584 * Directs a communication device to perform an extended function.
586 * PARAMS
588 * handle [in] The communication device to perform the extended function
589 * nFunction [in] The extended function to be performed
591 * RETURNS
593 * True or requested data on successful completion of the command,
594 * false if the device is not present cannot execute the command
595 * or the command failed.
597 BOOL WINAPI EscapeCommFunction(HANDLE handle, UINT func)
599 DWORD ioc;
600 DWORD dwBytesReturned;
602 switch (func)
604 case CLRDTR: ioc = IOCTL_SERIAL_CLR_DTR; break;
605 case CLRRTS: ioc = IOCTL_SERIAL_CLR_RTS; break;
606 case SETDTR: ioc = IOCTL_SERIAL_SET_DTR; break;
607 case SETRTS: ioc = IOCTL_SERIAL_SET_RTS; break;
608 case SETXOFF: ioc = IOCTL_SERIAL_SET_XOFF; break;
609 case SETXON: ioc = IOCTL_SERIAL_SET_XON; break;
610 case SETBREAK: ioc = IOCTL_SERIAL_SET_BREAK_ON; break;
611 case CLRBREAK: ioc = IOCTL_SERIAL_SET_BREAK_OFF; break;
612 case RESETDEV: ioc = IOCTL_SERIAL_RESET_DEVICE; break;
613 default:
614 ERR("Unknown function code (%u)\n", func);
615 SetLastError(ERROR_INVALID_PARAMETER);
616 return FALSE;
618 return DeviceIoControl(handle, ioc, NULL, 0, NULL, 0, &dwBytesReturned, NULL);
621 /********************************************************************
622 * PurgeComm (KERNEL32.@)
624 * Terminates pending operations and/or discards buffers on a
625 * communication resource.
627 * PARAMS
629 * handle [in] The communication resource to be purged
630 * flags [in] Flags for clear pending/buffer on input/output
632 * RETURNS
634 * True on success and false if the communications handle is bad.
636 BOOL WINAPI PurgeComm(HANDLE handle, DWORD flags)
638 DWORD dwBytesReturned;
639 return DeviceIoControl(handle, IOCTL_SERIAL_PURGE, &flags, sizeof(flags),
640 NULL, 0, &dwBytesReturned, NULL);
643 /*****************************************************************************
644 * ClearCommError (KERNEL32.@)
646 * Enables further I/O operations on a communications resource after
647 * supplying error and current status information.
649 * PARAMS
651 * handle [in] The communication resource with the error
652 * errors [out] Flags indicating error the resource experienced
653 * lpStat [out] The status of the communication resource
654 * RETURNS
656 * True on success, false if the communication resource handle is bad.
658 BOOL WINAPI ClearCommError(HANDLE handle, LPDWORD errors, LPCOMSTAT lpStat)
660 SERIAL_STATUS ss;
661 DWORD dwBytesReturned;
663 if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_COMMSTATUS, NULL, 0,
664 &ss, sizeof(ss), &dwBytesReturned, NULL))
665 return FALSE;
667 if (errors)
669 *errors = 0;
670 if (ss.Errors & SERIAL_ERROR_BREAK) *errors |= CE_BREAK;
671 if (ss.Errors & SERIAL_ERROR_FRAMING) *errors |= CE_FRAME;
672 if (ss.Errors & SERIAL_ERROR_OVERRUN) *errors |= CE_OVERRUN;
673 if (ss.Errors & SERIAL_ERROR_QUEUEOVERRUN) *errors |= CE_RXOVER;
674 if (ss.Errors & SERIAL_ERROR_PARITY) *errors |= CE_RXPARITY;
677 if (lpStat)
679 memset(lpStat, 0, sizeof(*lpStat));
681 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_CTS) lpStat->fCtsHold = TRUE;
682 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DSR) lpStat->fDsrHold = TRUE;
683 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_DCD) lpStat->fRlsdHold = TRUE;
684 if (ss.HoldReasons & SERIAL_TX_WAITING_FOR_XON) lpStat->fXoffHold = TRUE;
685 if (ss.HoldReasons & SERIAL_TX_WAITING_XOFF_SENT) lpStat->fXoffSent = TRUE;
686 if (ss.EofReceived) lpStat->fEof = TRUE;
687 if (ss.WaitForImmediate) lpStat->fTxim = TRUE;
688 lpStat->cbInQue = ss.AmountInInQueue;
689 lpStat->cbOutQue = ss.AmountInOutQueue;
691 return TRUE;
694 /*****************************************************************************
695 * SetupComm (KERNEL32.@)
697 * Called after CreateFile to hint to the communication resource to use
698 * specified sizes for input and output buffers rather than the default values.
700 * PARAMS
701 * handle [in] The just created communication resource handle
702 * insize [in] The suggested size of the communication resources input buffer in bytes
703 * outsize [in] The suggested size of the communication resources output buffer in bytes
705 * RETURNS
707 * True if successful, false if the communications resource handle is bad.
709 * BUGS
711 * Stub.
713 BOOL WINAPI SetupComm(HANDLE handle, DWORD insize, DWORD outsize)
715 SERIAL_QUEUE_SIZE sqs;
716 DWORD dwBytesReturned;
718 sqs.InSize = insize;
719 sqs.OutSize = outsize;
720 return DeviceIoControl(handle, IOCTL_SERIAL_SET_QUEUE_SIZE,
721 &sqs, sizeof(sqs), NULL, 0, &dwBytesReturned, NULL);
724 /*****************************************************************************
725 * GetCommMask (KERNEL32.@)
727 * Obtain the events associated with a communication device that will cause
728 * a call WaitCommEvent to return.
730 * PARAMS
732 * handle [in] The communications device
733 * evtmask [out] The events which cause WaitCommEvent to return
735 * RETURNS
737 * True on success, fail on bad device handle etc.
739 BOOL WINAPI GetCommMask(HANDLE handle, LPDWORD evtmask)
741 DWORD dwBytesReturned;
742 TRACE("handle %p, mask %p\n", handle, evtmask);
743 return DeviceIoControl(handle, IOCTL_SERIAL_GET_WAIT_MASK,
744 NULL, 0, evtmask, sizeof(*evtmask), &dwBytesReturned, NULL);
747 /*****************************************************************************
748 * SetCommMask (KERNEL32.@)
750 * There be some things we need to hear about yon there communications device.
751 * (Set which events associated with a communication device should cause
752 * a call WaitCommEvent to return.)
754 * PARAMS
756 * handle [in] The communications device
757 * evtmask [in] The events that are to be monitored
759 * RETURNS
761 * True on success, false on bad handle etc.
763 BOOL WINAPI SetCommMask(HANDLE handle, DWORD evtmask)
765 DWORD dwBytesReturned;
766 TRACE("handle %p, mask %x\n", handle, evtmask);
767 return DeviceIoControl(handle, IOCTL_SERIAL_SET_WAIT_MASK,
768 &evtmask, sizeof(evtmask), NULL, 0, &dwBytesReturned, NULL);
771 static void dump_dcb(const DCB* lpdcb)
773 TRACE("bytesize=%d baudrate=%d fParity=%d Parity=%d stopbits=%d\n",
774 lpdcb->ByteSize, lpdcb->BaudRate, lpdcb->fParity, lpdcb->Parity,
775 (lpdcb->StopBits == ONESTOPBIT) ? 1 :
776 (lpdcb->StopBits == TWOSTOPBITS) ? 2 : 0);
777 TRACE("%sIXON %sIXOFF\n", (lpdcb->fInX) ? "" : "~", (lpdcb->fOutX) ? "" : "~");
778 TRACE("fOutxCtsFlow=%d fRtsControl=%d\n", lpdcb->fOutxCtsFlow, lpdcb->fRtsControl);
779 TRACE("fOutxDsrFlow=%d fDtrControl=%d\n", lpdcb->fOutxDsrFlow, lpdcb->fDtrControl);
780 if (lpdcb->fOutxCtsFlow || lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE)
781 TRACE("CRTSCTS\n");
782 else
783 TRACE("~CRTSCTS\n");
786 /*****************************************************************************
787 * SetCommState (KERNEL32.@)
789 * Re-initializes all hardware and control settings of a communications device,
790 * with values from a device control block without affecting the input and output
791 * queues.
793 * PARAMS
795 * handle [in] The communications device
796 * lpdcb [out] The device control block
798 * RETURNS
800 * True on success, false on failure, e.g., if the XonChar is equal to the XoffChar.
802 BOOL WINAPI SetCommState( HANDLE handle, LPDCB lpdcb)
804 SERIAL_BAUD_RATE sbr;
805 SERIAL_LINE_CONTROL slc;
806 SERIAL_HANDFLOW shf;
807 SERIAL_CHARS sc;
808 DWORD dwBytesReturned;
810 if (lpdcb == NULL)
812 SetLastError(ERROR_INVALID_PARAMETER);
813 return FALSE;
815 dump_dcb(lpdcb);
817 sbr.BaudRate = lpdcb->BaudRate;
819 slc.StopBits = lpdcb->StopBits;
820 slc.Parity = lpdcb->Parity;
821 slc.WordLength = lpdcb->ByteSize;
823 shf.ControlHandShake = 0;
824 shf.FlowReplace = 0;
825 if (lpdcb->fOutxCtsFlow) shf.ControlHandShake |= SERIAL_CTS_HANDSHAKE;
826 if (lpdcb->fOutxDsrFlow) shf.ControlHandShake |= SERIAL_DSR_HANDSHAKE;
827 switch (lpdcb->fDtrControl)
829 case DTR_CONTROL_DISABLE: break;
830 case DTR_CONTROL_ENABLE: shf.ControlHandShake |= SERIAL_DTR_CONTROL; break;
831 case DTR_CONTROL_HANDSHAKE: shf.ControlHandShake |= SERIAL_DTR_HANDSHAKE;break;
832 default:
833 SetLastError(ERROR_INVALID_PARAMETER);
834 return FALSE;
836 switch (lpdcb->fRtsControl)
838 case RTS_CONTROL_DISABLE: break;
839 case RTS_CONTROL_ENABLE: shf.FlowReplace |= SERIAL_RTS_CONTROL; break;
840 case RTS_CONTROL_HANDSHAKE: shf.FlowReplace |= SERIAL_RTS_HANDSHAKE; break;
841 case RTS_CONTROL_TOGGLE: shf.FlowReplace |= SERIAL_RTS_CONTROL |
842 SERIAL_RTS_HANDSHAKE; break;
843 default:
844 SetLastError(ERROR_INVALID_PARAMETER);
845 return FALSE;
847 if (lpdcb->fDsrSensitivity) shf.ControlHandShake |= SERIAL_DSR_SENSITIVITY;
848 if (lpdcb->fAbortOnError) shf.ControlHandShake |= SERIAL_ERROR_ABORT;
850 if (lpdcb->fErrorChar) shf.FlowReplace |= SERIAL_ERROR_CHAR;
851 if (lpdcb->fNull) shf.FlowReplace |= SERIAL_NULL_STRIPPING;
852 if (lpdcb->fTXContinueOnXoff) shf.FlowReplace |= SERIAL_XOFF_CONTINUE;
853 if (lpdcb->fOutX) shf.FlowReplace |= SERIAL_AUTO_TRANSMIT;
854 if (lpdcb->fInX) shf.FlowReplace |= SERIAL_AUTO_RECEIVE;
856 shf.XonLimit = lpdcb->XonLim;
857 shf.XoffLimit = lpdcb->XoffLim;
859 sc.EofChar = lpdcb->EofChar;
860 sc.ErrorChar = lpdcb->ErrorChar;
861 sc.BreakChar = 0;
862 sc.EventChar = lpdcb->EvtChar;
863 sc.XonChar = lpdcb->XonChar;
864 sc.XoffChar = lpdcb->XoffChar;
866 /* note: change DTR/RTS lines after setting the comm attributes,
867 * so flow control does not interfere.
869 return (DeviceIoControl(handle, IOCTL_SERIAL_SET_BAUD_RATE,
870 &sbr, sizeof(sbr), NULL, 0, &dwBytesReturned, NULL) &&
871 DeviceIoControl(handle, IOCTL_SERIAL_SET_LINE_CONTROL,
872 &slc, sizeof(slc), NULL, 0, &dwBytesReturned, NULL) &&
873 DeviceIoControl(handle, IOCTL_SERIAL_SET_HANDFLOW,
874 &shf, sizeof(shf), NULL, 0, &dwBytesReturned, NULL) &&
875 DeviceIoControl(handle, IOCTL_SERIAL_SET_CHARS,
876 &sc, sizeof(sc), NULL, 0, &dwBytesReturned, NULL));
880 /*****************************************************************************
881 * GetCommState (KERNEL32.@)
883 * Fills in a device control block with information from a communications device.
885 * PARAMS
886 * handle [in] The communications device
887 * lpdcb [out] The device control block
889 * RETURNS
891 * True on success, false if the communication device handle is bad etc
893 * BUGS
895 * XonChar and XoffChar are not set.
897 BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb)
899 SERIAL_BAUD_RATE sbr;
900 SERIAL_LINE_CONTROL slc;
901 SERIAL_HANDFLOW shf;
902 SERIAL_CHARS sc;
903 DWORD dwBytesReturned;
905 TRACE("handle %p, ptr %p\n", handle, lpdcb);
907 if (!lpdcb)
909 SetLastError(ERROR_INVALID_PARAMETER);
910 return FALSE;
913 if (!DeviceIoControl(handle, IOCTL_SERIAL_GET_BAUD_RATE,
914 NULL, 0, &sbr, sizeof(sbr), &dwBytesReturned, NULL) ||
915 !DeviceIoControl(handle, IOCTL_SERIAL_GET_LINE_CONTROL,
916 NULL, 0, &slc, sizeof(slc), &dwBytesReturned, NULL) ||
917 !DeviceIoControl(handle, IOCTL_SERIAL_GET_HANDFLOW,
918 NULL, 0, &shf, sizeof(shf), &dwBytesReturned, NULL) ||
919 !DeviceIoControl(handle, IOCTL_SERIAL_GET_CHARS,
920 NULL, 0, &sc, sizeof(sc), &dwBytesReturned, NULL))
921 return FALSE;
923 memset(lpdcb, 0, sizeof(*lpdcb));
924 lpdcb->DCBlength = sizeof(*lpdcb);
926 /* yes, they seem no never be (re)set on NT */
927 lpdcb->fBinary = 1;
928 lpdcb->fParity = 0;
930 lpdcb->BaudRate = sbr.BaudRate;
932 lpdcb->StopBits = slc.StopBits;
933 lpdcb->Parity = slc.Parity;
934 lpdcb->ByteSize = slc.WordLength;
936 if (shf.ControlHandShake & SERIAL_CTS_HANDSHAKE) lpdcb->fOutxCtsFlow = 1;
937 if (shf.ControlHandShake & SERIAL_DSR_HANDSHAKE) lpdcb->fOutxDsrFlow = 1;
938 switch (shf.ControlHandShake & (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE))
940 case 0: lpdcb->fDtrControl = DTR_CONTROL_DISABLE; break;
941 case SERIAL_DTR_CONTROL: lpdcb->fDtrControl = DTR_CONTROL_ENABLE; break;
942 case SERIAL_DTR_HANDSHAKE: lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE; break;
944 switch (shf.FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE))
946 case 0: lpdcb->fRtsControl = RTS_CONTROL_DISABLE; break;
947 case SERIAL_RTS_CONTROL: lpdcb->fRtsControl = RTS_CONTROL_ENABLE; break;
948 case SERIAL_RTS_HANDSHAKE: lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE; break;
949 case SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE:
950 lpdcb->fRtsControl = RTS_CONTROL_TOGGLE; break;
952 if (shf.ControlHandShake & SERIAL_DSR_SENSITIVITY) lpdcb->fDsrSensitivity = 1;
953 if (shf.ControlHandShake & SERIAL_ERROR_ABORT) lpdcb->fAbortOnError = 1;
954 if (shf.FlowReplace & SERIAL_ERROR_CHAR) lpdcb->fErrorChar = 1;
955 if (shf.FlowReplace & SERIAL_NULL_STRIPPING) lpdcb->fNull = 1;
956 if (shf.FlowReplace & SERIAL_XOFF_CONTINUE) lpdcb->fTXContinueOnXoff = 1;
957 lpdcb->XonLim = shf.XonLimit;
958 lpdcb->XoffLim = shf.XoffLimit;
960 if (shf.FlowReplace & SERIAL_AUTO_TRANSMIT) lpdcb->fOutX = 1;
961 if (shf.FlowReplace & SERIAL_AUTO_RECEIVE) lpdcb->fInX = 1;
963 lpdcb->EofChar = sc.EofChar;
964 lpdcb->ErrorChar = sc.ErrorChar;
965 lpdcb->EvtChar = sc.EventChar;
966 lpdcb->XonChar = sc.XonChar;
967 lpdcb->XoffChar = sc.XoffChar;
969 TRACE("OK\n");
970 dump_dcb(lpdcb);
972 return TRUE;
975 /*****************************************************************************
976 * TransmitCommChar (KERNEL32.@)
978 * Transmits a single character in front of any pending characters in the
979 * output buffer. Usually used to send an interrupt character to a host.
981 * PARAMS
982 * hComm [in] The communication device in need of a command character
983 * chTransmit [in] The character to transmit
985 * RETURNS
987 * True if the call succeeded, false if the previous command character to the
988 * same device has not been sent yet the handle is bad etc.
991 BOOL WINAPI TransmitCommChar(HANDLE hComm, CHAR chTransmit)
993 DWORD dwBytesReturned;
994 return DeviceIoControl(hComm, IOCTL_SERIAL_IMMEDIATE_CHAR,
995 &chTransmit, sizeof(chTransmit), NULL, 0, &dwBytesReturned, NULL);
999 /*****************************************************************************
1000 * GetCommTimeouts (KERNEL32.@)
1002 * Obtains the request timeout values for the communications device.
1004 * PARAMS
1005 * hComm [in] The communications device
1006 * lptimeouts [out] The struct of request timeouts
1008 * RETURNS
1010 * True on success, false if communications device handle is bad
1011 * or the target structure is null.
1013 BOOL WINAPI GetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts)
1015 SERIAL_TIMEOUTS st;
1016 DWORD dwBytesReturned;
1018 TRACE("(%p, %p)\n", hComm, lptimeouts);
1019 if (!lptimeouts)
1021 SetLastError(ERROR_INVALID_PARAMETER);
1022 return FALSE;
1024 if (!DeviceIoControl(hComm, IOCTL_SERIAL_GET_TIMEOUTS,
1025 NULL, 0, &st, sizeof(st), &dwBytesReturned, NULL))
1026 return FALSE;
1027 lptimeouts->ReadIntervalTimeout = st.ReadIntervalTimeout;
1028 lptimeouts->ReadTotalTimeoutMultiplier = st.ReadTotalTimeoutMultiplier;
1029 lptimeouts->ReadTotalTimeoutConstant = st.ReadTotalTimeoutConstant;
1030 lptimeouts->WriteTotalTimeoutMultiplier = st.WriteTotalTimeoutMultiplier;
1031 lptimeouts->WriteTotalTimeoutConstant = st.WriteTotalTimeoutConstant;
1032 return TRUE;
1035 /*****************************************************************************
1036 * SetCommTimeouts (KERNEL32.@)
1038 * Sets the timeouts used when reading and writing data to/from COMM ports.
1040 * PARAMS
1041 * hComm [in] handle of COMM device
1042 * lptimeouts [in] pointer to COMMTIMEOUTS structure
1044 * ReadIntervalTimeout
1045 * - converted and passes to linux kernel as c_cc[VTIME]
1046 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1047 * - used in ReadFile to calculate GetOverlappedResult's timeout
1048 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1049 * - used in WriteFile to calculate GetOverlappedResult's timeout
1051 * RETURNS
1053 * True if the timeouts were set, false otherwise.
1055 BOOL WINAPI SetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts)
1057 SERIAL_TIMEOUTS st;
1058 DWORD dwBytesReturned;
1060 TRACE("(%p, %p)\n", hComm, lptimeouts);
1062 if (lptimeouts == NULL)
1064 SetLastError(ERROR_INVALID_PARAMETER);
1065 return FALSE;
1067 st.ReadIntervalTimeout = lptimeouts->ReadIntervalTimeout;
1068 st.ReadTotalTimeoutMultiplier = lptimeouts->ReadTotalTimeoutMultiplier;
1069 st.ReadTotalTimeoutConstant = lptimeouts->ReadTotalTimeoutConstant;
1070 st.WriteTotalTimeoutMultiplier = lptimeouts->WriteTotalTimeoutMultiplier;
1071 st.WriteTotalTimeoutConstant = lptimeouts->WriteTotalTimeoutConstant;
1073 return DeviceIoControl(hComm, IOCTL_SERIAL_SET_TIMEOUTS,
1074 &st, sizeof(st), NULL, 0, &dwBytesReturned, NULL);
1077 /***********************************************************************
1078 * GetCommModemStatus (KERNEL32.@)
1080 * Obtains the four control register bits if supported by the hardware.
1082 * PARAMS
1084 * hFile [in] The communications device
1085 * lpModemStat [out] The control register bits
1087 * RETURNS
1089 * True if the communications handle was good and for hardware that
1090 * control register access, false otherwise.
1092 BOOL WINAPI GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat)
1094 DWORD dwBytesReturned;
1095 return DeviceIoControl(hFile, IOCTL_SERIAL_GET_MODEMSTATUS,
1096 NULL, 0, lpModemStat, sizeof(DWORD), &dwBytesReturned, NULL);
1099 /***********************************************************************
1100 * WaitCommEvent (KERNEL32.@)
1102 * Wait until something interesting happens on a COMM port.
1103 * Interesting things (events) are set by calling SetCommMask before
1104 * this function is called.
1106 * RETURNS
1107 * TRUE if successful
1108 * FALSE if failure
1110 * The set of detected events will be written to *lpdwEventMask
1111 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1113 * BUGS:
1114 * Only supports EV_RXCHAR and EV_TXEMPTY
1116 BOOL WINAPI WaitCommEvent(
1117 HANDLE hFile, /* [in] handle of comm port to wait for */
1118 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1119 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1121 return DeviceIoControl(hFile, IOCTL_SERIAL_WAIT_ON_MASK, NULL, 0,
1122 lpdwEvents, sizeof(DWORD), NULL, lpOverlapped);
1125 /***********************************************************************
1126 * GetCommProperties (KERNEL32.@)
1128 * This function fills in a structure with the capabilities of the
1129 * communications port driver.
1131 * RETURNS
1133 * TRUE on success, FALSE on failure
1134 * If successful, the lpCommProp structure be filled in with
1135 * properties of the comm port.
1137 BOOL WINAPI GetCommProperties(
1138 HANDLE hFile, /* [in] handle of the comm port */
1139 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
1141 FIXME("(%p %p )\n",hFile,lpCommProp);
1142 if(!lpCommProp)
1143 return FALSE;
1146 * These values should be valid for LINUX's serial driver
1147 * FIXME: Perhaps they deserve an #ifdef LINUX
1149 memset(lpCommProp,0,sizeof(COMMPROP));
1150 lpCommProp->wPacketLength = 1;
1151 lpCommProp->wPacketVersion = 1;
1152 lpCommProp->dwServiceMask = SP_SERIALCOMM;
1153 lpCommProp->dwReserved1 = 0;
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;
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;