Unicodify some comm functions.
[wine.git] / dlls / kernel / comm.c
blob4badac8750079c2dc692e7cdd27258176c7c4238
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * History:
22 * Apr 3, 1999. Lawson Whitney <lawson_whitney@juno.com>
23 * - Fixed the modem control part of EscapeCommFunction16.
25 * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no>
26 * - Implemented buffers and EnableCommNotification.
28 * Mar 3, 1999. Ove Kåven <ovek@arcticnet.no>
29 * - Use port indices instead of unixfds for win16
30 * - Moved things around (separated win16 and win32 routines)
31 * - Added some hints on how to implement buffers and EnableCommNotification.
33 * Oktober 98, Rein Klazes [RHK]
34 * A program that wants to monitor the modem status line (RLSD/DCD) may
35 * poll the modem status register in the commMask structure. I update the bit
36 * in GetCommError, waiting for an implementation of communication events.
38 * July 6, 1998. Fixes and comments by Valentijn Sessink
39 * <vsessink@ic.uva.nl> [V]
41 * August 12, 1997. Take a bash at SetCommEventMask - Lawson Whitney
42 * <lawson_whitney@juno.com>
44 * May 26, 1997. Fixes and comments by Rick Richardson <rick@dgii.com> [RER]
45 * - ptr->fd wasn't getting cleared on close.
46 * - GetCommEventMask() and GetCommError() didn't do much of anything.
47 * IMHO, they are still wrong, but they at least implement the RXCHAR
48 * event and return I/O queue sizes, which makes the app I'm interested
49 * in (analog devices EZKIT DSP development system) work.
52 #include "config.h"
53 #include "wine/port.h"
55 #include <stdlib.h>
56 #include <stdarg.h>
57 #include <stdio.h>
58 #ifdef HAVE_TERMIOS_H
59 #include <termios.h>
60 #endif
61 #include <fcntl.h>
62 #include <string.h>
63 #ifdef HAVE_STRINGS_H
64 # include <strings.h>
65 #endif
66 #include <errno.h>
67 #include <ctype.h>
68 #include <sys/stat.h>
69 #ifdef HAVE_SYS_FILIO_H
70 # include <sys/filio.h>
71 #endif
72 #ifdef HAVE_SYS_IOCTL_H
73 #include <sys/ioctl.h>
74 #endif
75 #ifdef HAVE_UNISTD_H
76 # include <unistd.h>
77 #endif
78 #ifdef HAVE_SYS_POLL_H
79 # include <sys/poll.h>
80 #endif
81 #ifdef HAVE_SYS_MODEM_H
82 # include <sys/modem.h>
83 #endif
84 #ifdef HAVE_SYS_STRTIO_H
85 # include <sys/strtio.h>
86 #endif
88 #define NONAMELESSUNION
89 #define NONAMELESSSTRUCT
90 #include "ntstatus.h"
91 #include "windef.h"
92 #include "winbase.h"
93 #include "winerror.h"
95 #include "wine/server.h"
96 #include "async.h"
97 #include "heap.h"
98 #include "wine/unicode.h"
100 #include "wine/debug.h"
102 #ifdef HAVE_LINUX_SERIAL_H
103 #include <linux/serial.h>
104 #endif
106 WINE_DEFAULT_DEBUG_CHANNEL(comm);
108 /* retrieve the Unix handle corresponding to a comm handle */
109 static int get_comm_fd( HANDLE handle, DWORD access )
111 int fd, ret;
113 ret = wine_server_handle_to_fd( handle, access, &fd, NULL, NULL );
114 if (ret) SetLastError( RtlNtStatusToDosError(ret) );
115 return fd;
118 /* release the Unix handle returned by get_comm_fd */
119 static inline void release_comm_fd( HANDLE handle, int fd )
121 wine_server_release_fd( handle, fd );
125 /***********************************************************************
126 * Asynchronous I/O for asynchronous wait requests *
129 static DWORD commio_get_async_count (const async_private *ovp);
130 static void commio_async_cleanup (async_private *ovp);
132 static async_ops commio_async_ops =
134 commio_get_async_count, /* get_count */
135 NULL, /* call_completion */
136 commio_async_cleanup /* cleanup */
139 typedef struct async_commio
141 struct async_private async;
142 char *buffer;
143 } async_commio;
145 static DWORD commio_get_async_count (const struct async_private *ovp)
147 return 0;
150 static void commio_async_cleanup (async_private *ovp)
152 HeapFree(GetProcessHeap(), 0, ovp );
155 /***********************************************************************/
157 #if !defined(TIOCINQ) && defined(FIONREAD)
158 #define TIOCINQ FIONREAD
159 #endif
161 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
163 #ifdef TIOCMGET
164 unsigned int mstat, okay;
165 okay = ioctl(fd, TIOCMGET, &mstat);
166 if (okay) return okay;
167 if (andy) mstat &= andy;
168 mstat |= orrie;
169 return ioctl(fd, TIOCMSET, &mstat);
170 #else
171 return 0;
172 #endif
175 /***********************************************************************
176 * COMM_Parse* (Internal)
178 * The following COMM_Parse* functions are used by the BuildCommDCB
179 * functions to help parse the various parts of the device control string.
181 static LPCWSTR COMM_ParseStart(LPCWSTR ptr)
183 const WCHAR comW[] = {'C','O','M',0};
185 /* The device control string may optionally start with "COMx" followed
186 by an optional ':' and spaces. */
187 if(!strncmpiW(ptr, comW, 3))
189 ptr += 3;
191 /* Allow any com port above 0 as Win 9x does (NT only allows
192 values for com ports which are actually present) */
193 if(*ptr < '1' || *ptr > '9')
194 return NULL;
196 /* Advance pointer past port number */
197 while(*ptr >= '0' && *ptr <= '9') ptr++;
199 /* The com port number must be followed by a ':' or ' ' */
200 if(*ptr != ':' && *ptr != ' ')
201 return NULL;
203 /* Advance pointer to beginning of next parameter */
204 while(*ptr == ' ') ptr++;
205 if(*ptr == ':')
207 ptr++;
208 while(*ptr == ' ') ptr++;
211 /* The device control string must not start with a space. */
212 else if(*ptr == ' ')
213 return NULL;
215 return ptr;
218 static LPCWSTR COMM_ParseNumber(LPCWSTR ptr, LPDWORD lpnumber)
220 if(*ptr < '0' || *ptr > '9') return NULL;
221 *lpnumber = strtoulW(ptr, NULL, 10);
222 while(*ptr >= '0' && *ptr <= '9') ptr++;
223 return ptr;
226 static LPCWSTR COMM_ParseParity(LPCWSTR ptr, LPBYTE lpparity)
228 /* Contrary to what you might expect, Windows only sets the Parity
229 member of DCB and not fParity even when parity is specified in the
230 device control string */
232 switch(toupperW(*ptr++))
234 case 'E':
235 *lpparity = EVENPARITY;
236 break;
237 case 'M':
238 *lpparity = MARKPARITY;
239 break;
240 case 'N':
241 *lpparity = NOPARITY;
242 break;
243 case 'O':
244 *lpparity = ODDPARITY;
245 break;
246 case 'S':
247 *lpparity = SPACEPARITY;
248 break;
249 default:
250 return NULL;
253 return ptr;
256 static LPCWSTR COMM_ParseByteSize(LPCWSTR ptr, LPBYTE lpbytesize)
258 DWORD temp;
260 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
261 return NULL;
263 if(temp >= 5 && temp <= 8)
265 *lpbytesize = temp;
266 return ptr;
268 else
269 return NULL;
272 static LPCWSTR COMM_ParseStopBits(LPCWSTR ptr, LPBYTE lpstopbits)
274 DWORD temp;
275 const WCHAR stopbits15W[] = {'1','.','5',0};
277 if(!strncmpW(stopbits15W, ptr, 3))
279 ptr += 3;
280 *lpstopbits = ONE5STOPBITS;
282 else
284 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
285 return NULL;
287 if(temp == 1)
288 *lpstopbits = ONESTOPBIT;
289 else if(temp == 2)
290 *lpstopbits = TWOSTOPBITS;
291 else
292 return NULL;
295 return ptr;
298 static LPCWSTR COMM_ParseOnOff(LPCWSTR ptr, LPDWORD lponoff)
300 const WCHAR onW[] = {'o','n',0};
301 const WCHAR offW[] = {'o','f','f',0};
303 if(!strncmpiW(onW, ptr, 2))
305 ptr += 2;
306 *lponoff = 1;
308 else if(!strncmpiW(offW, ptr, 3))
310 ptr += 3;
311 *lponoff = 0;
313 else
314 return NULL;
316 return ptr;
319 /***********************************************************************
320 * COMM_BuildOldCommDCB (Internal)
322 * Build a DCB using the old style settings string eg: "96,n,8,1"
324 static BOOL COMM_BuildOldCommDCB(LPCWSTR device, LPDCB lpdcb)
326 WCHAR last = 0;
328 if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
329 return FALSE;
331 switch(lpdcb->BaudRate)
333 case 11:
334 case 30:
335 case 60:
336 lpdcb->BaudRate *= 10;
337 break;
338 case 12:
339 case 24:
340 case 48:
341 case 96:
342 lpdcb->BaudRate *= 100;
343 break;
344 case 19:
345 lpdcb->BaudRate = 19200;
346 break;
349 while(*device == ' ') device++;
350 if(*device++ != ',') return FALSE;
351 while(*device == ' ') device++;
353 if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
354 return FALSE;
356 while(*device == ' ') device++;
357 if(*device++ != ',') return FALSE;
358 while(*device == ' ') device++;
360 if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
361 return FALSE;
363 while(*device == ' ') device++;
364 if(*device++ != ',') return FALSE;
365 while(*device == ' ') device++;
367 if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
368 return FALSE;
370 /* The last parameter for flow control is optional. */
371 while(*device == ' ') device++;
372 if(*device == ',')
374 device++;
375 while(*device == ' ') device++;
376 if(*device) last = toupperW(*device++);
377 while(*device == ' ') device++;
380 /* Win NT sets the flow control members based on (or lack of) the last
381 parameter. Win 9x does not set these members. */
382 switch(last)
384 case 0:
385 lpdcb->fInX = FALSE;
386 lpdcb->fOutX = FALSE;
387 lpdcb->fOutxCtsFlow = FALSE;
388 lpdcb->fOutxDsrFlow = FALSE;
389 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
390 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
391 break;
392 case 'X':
393 lpdcb->fInX = TRUE;
394 lpdcb->fOutX = TRUE;
395 lpdcb->fOutxCtsFlow = FALSE;
396 lpdcb->fOutxDsrFlow = FALSE;
397 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
398 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
399 break;
400 case 'P':
401 lpdcb->fInX = FALSE;
402 lpdcb->fOutX = FALSE;
403 lpdcb->fOutxCtsFlow = TRUE;
404 lpdcb->fOutxDsrFlow = TRUE;
405 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
406 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
407 break;
408 default:
409 return FALSE;
412 /* This should be the end of the string. */
413 if(*device) return FALSE;
415 return TRUE;
418 /***********************************************************************
419 * COMM_BuildNewCommDCB (Internal)
421 * Build a DCB using the new style settings string.
422 * eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
424 static BOOL COMM_BuildNewCommDCB(LPCWSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
426 DWORD temp;
427 BOOL baud = FALSE, stop = FALSE;
428 const WCHAR baudW[] = {'b','a','u','d','=',0};
429 const WCHAR parityW[] = {'p','a','r','i','t','y','=',0};
430 const WCHAR dataW[] = {'d','a','t','a','=',0};
431 const WCHAR stopW[] = {'s','t','o','p','=',0};
432 const WCHAR toW[] = {'t','o','=',0};
433 const WCHAR xonW[] = {'x','o','n','=',0};
434 const WCHAR odsrW[] = {'o','d','s','r','=',0};
435 const WCHAR octsW[] = {'o','c','t','s','=',0};
436 const WCHAR dtrW[] = {'d','t','r','=',0};
437 const WCHAR rtsW[] = {'r','t','s','=',0};
438 const WCHAR idsrW[] = {'i','d','s','r','=',0};
440 while(*device)
442 while(*device == ' ') device++;
444 if(!strncmpiW(baudW, device, 5))
446 baud = TRUE;
448 if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
449 return FALSE;
451 else if(!strncmpiW(parityW, device, 7))
453 if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
454 return FALSE;
456 else if(!strncmpiW(dataW, device, 5))
458 if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
459 return FALSE;
461 else if(!strncmpiW(stopW, device, 5))
463 stop = TRUE;
465 if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
466 return FALSE;
468 else if(!strncmpiW(toW, device, 3))
470 if(!(device = COMM_ParseOnOff(device + 3, &temp)))
471 return FALSE;
473 lptimeouts->ReadIntervalTimeout = 0;
474 lptimeouts->ReadTotalTimeoutMultiplier = 0;
475 lptimeouts->ReadTotalTimeoutConstant = 0;
476 lptimeouts->WriteTotalTimeoutMultiplier = 0;
477 lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
479 else if(!strncmpiW(xonW, device, 4))
481 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
482 return FALSE;
484 lpdcb->fOutX = temp;
485 lpdcb->fInX = temp;
487 else if(!strncmpiW(odsrW, device, 5))
489 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
490 return FALSE;
492 lpdcb->fOutxDsrFlow = temp;
494 else if(!strncmpiW(octsW, device, 5))
496 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
497 return FALSE;
499 lpdcb->fOutxCtsFlow = temp;
501 else if(!strncmpiW(dtrW, device, 4))
503 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
504 return FALSE;
506 lpdcb->fDtrControl = temp;
508 else if(!strncmpiW(rtsW, device, 4))
510 if(!(device = COMM_ParseOnOff(device + 4, &temp)))
511 return FALSE;
513 lpdcb->fRtsControl = temp;
515 else if(!strncmpiW(idsrW, device, 5))
517 if(!(device = COMM_ParseOnOff(device + 5, &temp)))
518 return FALSE;
520 /* Win NT sets the fDsrSensitivity member based on the
521 idsr parameter. Win 9x sets fOutxDsrFlow instead. */
522 lpdcb->fDsrSensitivity = temp;
524 else
525 return FALSE;
527 /* After the above parsing, the next character (if not the end of
528 the string) should be a space */
529 if(*device && *device != ' ')
530 return FALSE;
533 /* If stop bits were not specified, a default is always supplied. */
534 if(!stop)
536 if(baud && lpdcb->BaudRate == 110)
537 lpdcb->StopBits = TWOSTOPBITS;
538 else
539 lpdcb->StopBits = ONESTOPBIT;
542 return TRUE;
545 /**************************************************************************
546 * BuildCommDCBA (KERNEL32.@)
548 * Updates a device control block data structure with values from an
549 * ascii device control string. The device control string has two forms
550 * normal and extended, it must be exclusively in one or the other form.
552 * RETURNS
554 * True on success, false on a malformed control string.
556 BOOL WINAPI BuildCommDCBA(
557 LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
558 LPDCB lpdcb) /* [out] The device control block to be updated. */
560 return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
563 /**************************************************************************
564 * BuildCommDCBAndTimeoutsA (KERNEL32.@)
566 * Updates a device control block data structure with values from an
567 * ascii device control string. Taking timeout values from a timeouts
568 * struct if desired by the control string.
570 * RETURNS
572 * True on success, false bad handles etc.
574 BOOL WINAPI BuildCommDCBAndTimeoutsA(
575 LPCSTR device, /* [in] The ascii device control string. */
576 LPDCB lpdcb, /* [out] The device control block to be updated. */
577 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
579 BOOL ret = FALSE;
580 UNICODE_STRING deviceW;
582 TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
583 if(device) RtlCreateUnicodeStringFromAsciiz(&deviceW,device);
584 else deviceW.Buffer = NULL;
586 if(deviceW.Buffer) ret = BuildCommDCBAndTimeoutsW(deviceW.Buffer,lpdcb,lptimeouts);
588 RtlFreeUnicodeString(&deviceW);
589 return ret;
592 /**************************************************************************
593 * BuildCommDCBAndTimeoutsW (KERNEL32.@)
595 * Updates a device control block data structure with values from a
596 * unicode device control string. Taking timeout values from a timeouts
597 * struct if desired by the control string.
599 * RETURNS
601 * True on success, false bad handles etc
603 BOOL WINAPI BuildCommDCBAndTimeoutsW(
604 LPCWSTR devid, /* [in] The unicode device control string. */
605 LPDCB lpdcb, /* [out] The device control block to be updated. */
606 LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
608 DCB dcb;
609 COMMTIMEOUTS timeouts;
610 BOOL result;
611 LPCWSTR ptr = devid;
613 TRACE("(%s,%p,%p)\n",debugstr_w(devid),lpdcb,lptimeouts);
615 /* Set DCBlength. (Windows NT does not do this, but 9x does) */
616 lpdcb->DCBlength = sizeof(DCB);
618 /* Make a copy of the original data structures to work with since if
619 if there is an error in the device control string the originals
620 should not be modified (except possibly DCBlength) */
621 memcpy(&dcb, lpdcb, sizeof(DCB));
622 if(lptimeouts) memcpy(&timeouts, lptimeouts, sizeof(COMMTIMEOUTS));
624 ptr = COMM_ParseStart(ptr);
626 if(ptr == NULL)
627 result = FALSE;
628 else if(strchrW(ptr, ','))
629 result = COMM_BuildOldCommDCB(ptr, &dcb);
630 else
631 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
633 if(result)
635 memcpy(lpdcb, &dcb, sizeof(DCB));
636 if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
637 return TRUE;
639 else
641 WARN("Invalid device control string: %s\n", debugstr_w(devid));
642 SetLastError(ERROR_INVALID_PARAMETER);
643 return FALSE;
647 /**************************************************************************
648 * BuildCommDCBW (KERNEL32.@)
650 * Updates a device control block structure with values from an
651 * unicode device control string. The device control string has two forms
652 * normal and extended, it must be exclusively in one or the other form.
654 * RETURNS
656 * True on success, false on an malformed control string.
658 BOOL WINAPI BuildCommDCBW(
659 LPCWSTR devid, /* [in] The unicode device control string. */
660 LPDCB lpdcb) /* [out] The device control block to be updated. */
662 return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
665 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
667 DWORD ret;
669 SERVER_START_REQ( set_serial_info )
671 req->handle = handle;
672 req->flags = SERIALINFO_SET_ERROR;
673 req->commerror = error;
674 ret = !wine_server_call_err( req );
676 SERVER_END_REQ;
677 return ret;
680 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
682 DWORD ret;
684 if(!lperror)
685 return FALSE;
687 SERVER_START_REQ( get_serial_info )
689 req->handle = handle;
690 ret = !wine_server_call_err( req );
691 *lperror = reply->commerror;
693 SERVER_END_REQ;
695 return ret;
698 /*****************************************************************************
699 * SetCommBreak (KERNEL32.@)
701 * Halts the transmission of characters to a communications device.
703 * RETURNS
705 * True on success, and false if the communications device could not be found,
706 * the control is not supported.
708 * BUGS
710 * Only TIOCSBRK and TIOCCBRK are supported.
712 BOOL WINAPI SetCommBreak(
713 HANDLE handle) /* [in] The communictions device to suspend. */
715 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
716 int fd,result;
718 fd = get_comm_fd( handle, GENERIC_READ );
719 if(fd<0) return FALSE;
720 result = ioctl(fd,TIOCSBRK,0);
721 release_comm_fd( handle, fd );
722 if (result ==-1)
724 TRACE("ioctl failed\n");
725 SetLastError(ERROR_NOT_SUPPORTED);
726 return FALSE;
728 return TRUE;
729 #else
730 FIXME("ioctl not available\n");
731 SetLastError(ERROR_NOT_SUPPORTED);
732 return FALSE;
733 #endif
736 /*****************************************************************************
737 * ClearCommBreak (KERNEL32.@)
739 * Resumes character transmission from a communication device.
741 * RETURNS
743 * True on success and false if the communications device could not be found.
745 * BUGS
747 * Only TIOCSBRK and TIOCCBRK are supported.
749 BOOL WINAPI ClearCommBreak(
750 HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
752 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
753 int fd,result;
755 fd = get_comm_fd( handle, GENERIC_READ );
756 if(fd<0) return FALSE;
757 result = ioctl(fd,TIOCCBRK,0);
758 release_comm_fd( handle, fd );
759 if (result ==-1)
761 TRACE("ioctl failed\n");
762 SetLastError(ERROR_NOT_SUPPORTED);
763 return FALSE;
765 return TRUE;
766 #else
767 FIXME("ioctl not available\n");
768 SetLastError(ERROR_NOT_SUPPORTED);
769 return FALSE;
770 #endif
773 /*****************************************************************************
774 * EscapeCommFunction (KERNEL32.@)
776 * Directs a communication device to perform an extended function.
778 * RETURNS
780 * True or requested data on successful completion of the command,
781 * false if the device is not present cannot execute the command
782 * or the command failed.
784 BOOL WINAPI EscapeCommFunction(
785 HANDLE handle, /* [in] The communication device to perform the extended function. */
786 UINT nFunction) /* [in] The extended function to be performed. */
788 int fd,direct=FALSE,result=FALSE;
789 struct termios port;
791 TRACE("handle %p, function=%d\n", handle, nFunction);
792 fd = get_comm_fd( handle, GENERIC_READ );
793 if(fd<0) return FALSE;
795 if (tcgetattr(fd,&port) == -1) {
796 COMM_SetCommError(handle,CE_IOE);
797 release_comm_fd( handle, fd );
798 return FALSE;
801 switch (nFunction) {
802 case RESETDEV:
803 TRACE("\n");
804 break;
806 case CLRDTR:
807 TRACE("CLRDTR\n");
808 #ifdef TIOCM_DTR
809 direct=TRUE;
810 result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
811 break;
812 #endif
814 case CLRRTS:
815 TRACE("CLRRTS\n");
816 #ifdef TIOCM_RTS
817 direct=TRUE;
818 result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
819 break;
820 #endif
822 case SETDTR:
823 TRACE("SETDTR\n");
824 #ifdef TIOCM_DTR
825 direct=TRUE;
826 result= COMM_WhackModem(fd, 0, TIOCM_DTR);
827 break;
828 #endif
830 case SETRTS:
831 TRACE("SETRTS\n");
832 #ifdef TIOCM_RTS
833 direct=TRUE;
834 result= COMM_WhackModem(fd, 0, TIOCM_RTS);
835 break;
836 #endif
838 case SETXOFF:
839 TRACE("SETXOFF\n");
840 port.c_iflag |= IXOFF;
841 break;
843 case SETXON:
844 TRACE("SETXON\n");
845 port.c_iflag |= IXON;
846 break;
847 case SETBREAK:
848 TRACE("setbreak\n");
849 #ifdef TIOCSBRK
850 direct=TRUE;
851 result = ioctl(fd,TIOCSBRK,0);
852 break;
853 #endif
854 case CLRBREAK:
855 TRACE("clrbreak\n");
856 #ifdef TIOCSBRK
857 direct=TRUE;
858 result = ioctl(fd,TIOCCBRK,0);
859 break;
860 #endif
861 default:
862 WARN("(handle=%p,nFunction=%d): Unknown function\n",
863 handle, nFunction);
864 break;
867 if (!direct)
868 if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
869 release_comm_fd( handle, fd );
870 COMM_SetCommError(handle,CE_IOE);
871 return FALSE;
872 } else
873 result= TRUE;
874 else
876 if (result == -1)
878 result= FALSE;
879 COMM_SetCommError(handle,CE_IOE);
881 else
882 result = TRUE;
884 release_comm_fd( handle, fd );
885 return result;
888 /********************************************************************
889 * PurgeComm (KERNEL32.@)
891 * Terminates pending operations and/or discards buffers on a
892 * communication resource.
894 * RETURNS
896 * True on success and false if the communications handle is bad.
898 BOOL WINAPI PurgeComm(
899 HANDLE handle, /* [in] The communication resource to be purged. */
900 DWORD flags) /* [in] Flags for clear pending/buffer on input/output. */
902 int fd;
904 TRACE("handle %p, flags %lx\n", handle, flags);
906 fd = get_comm_fd( handle, GENERIC_READ );
907 if(fd<0) return FALSE;
910 ** not exactly sure how these are different
911 ** Perhaps if we had our own internal queues, one flushes them
912 ** and the other flushes the kernel's buffers.
914 if(flags&PURGE_TXABORT)
915 tcflush(fd,TCOFLUSH);
916 if(flags&PURGE_RXABORT)
917 tcflush(fd,TCIFLUSH);
918 if(flags&PURGE_TXCLEAR)
919 tcflush(fd,TCOFLUSH);
920 if(flags&PURGE_RXCLEAR)
921 tcflush(fd,TCIFLUSH);
922 release_comm_fd( handle, fd );
924 return 1;
927 /*****************************************************************************
928 * ClearCommError (KERNEL32.@)
930 * Enables further I/O operations on a communications resource after
931 * supplying error and current status information.
933 * RETURNS
935 * True on success, false if the communication resource handle is bad.
937 BOOL WINAPI ClearCommError(
938 HANDLE handle, /* [in] The communication resource with the error. */
939 LPDWORD errors, /* [out] Flags indicating error the resource experienced. */
940 LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
942 int fd;
944 fd=get_comm_fd( handle, GENERIC_READ );
945 if(0>fd) return FALSE;
947 if (lpStat)
949 lpStat->fCtsHold = 0;
950 lpStat->fDsrHold = 0;
951 lpStat->fRlsdHold = 0;
952 lpStat->fXoffHold = 0;
953 lpStat->fXoffSent = 0;
954 lpStat->fEof = 0;
955 lpStat->fTxim = 0;
956 lpStat->fReserved = 0;
958 #ifdef TIOCOUTQ
959 if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
960 WARN("ioctl returned error\n");
961 #else
962 lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
963 #endif
965 #ifdef TIOCINQ
966 if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
967 WARN("ioctl returned error\n");
968 #endif
970 TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
971 handle, lpStat->cbInQue, lpStat->cbOutQue);
974 release_comm_fd( handle, fd );
976 COMM_GetCommError(handle, errors);
977 COMM_SetCommError(handle, 0);
979 return TRUE;
982 /*****************************************************************************
983 * SetupComm (KERNEL32.@)
985 * Called after CreateFile to hint to the communication resource to use
986 * specified sizes for input and output buffers rather than the default values.
988 * RETURNS
990 * True if successful, false if the communications resource handle is bad.
992 * BUGS
994 * Stub.
996 BOOL WINAPI SetupComm(
997 HANDLE handle, /* [in] The just created communication resource handle. */
998 DWORD insize, /* [in] The suggested size of the communication resources input buffer in bytes. */
999 DWORD outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
1001 int fd;
1003 FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
1004 fd=get_comm_fd( handle, GENERIC_READ );
1005 if(0>fd) return FALSE;
1006 release_comm_fd( handle, fd );
1007 return TRUE;
1010 /*****************************************************************************
1011 * GetCommMask (KERNEL32.@)
1013 * Obtain the events associated with a communication device that will cause
1014 * a call WaitCommEvent to return.
1016 * RETURNS
1018 * True on success, fail on bad device handle etc.
1020 BOOL WINAPI GetCommMask(
1021 HANDLE handle, /* [in] The communications device. */
1022 LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
1024 BOOL ret;
1026 TRACE("handle %p, mask %p\n", handle, evtmask);
1028 SERVER_START_REQ( get_serial_info )
1030 req->handle = handle;
1031 if ((ret = !wine_server_call_err( req )))
1033 if (evtmask) *evtmask = reply->eventmask;
1036 SERVER_END_REQ;
1037 return ret;
1040 /*****************************************************************************
1041 * SetCommMask (KERNEL32.@)
1043 * There be some things we need to hear about yon there communications device.
1044 * (Set which events associated with a communication device should cause
1045 * a call WaitCommEvent to return.)
1047 * RETURNS
1049 * True on success, false on bad handle etc.
1051 BOOL WINAPI SetCommMask(
1052 HANDLE handle, /* [in] The communications device. */
1053 DWORD evtmask) /* [in] The events that are to be monitored. */
1055 BOOL ret;
1057 TRACE("handle %p, mask %lx\n", handle, evtmask);
1059 SERVER_START_REQ( set_serial_info )
1061 req->handle = handle;
1062 req->flags = SERIALINFO_SET_MASK;
1063 req->eventmask = evtmask;
1064 ret = !wine_server_call_err( req );
1066 SERVER_END_REQ;
1067 return ret;
1070 /*****************************************************************************
1071 * SetCommState (KERNEL32.@)
1073 * Re-initializes all hardware and control settings of a communications device,
1074 * with values from a device control block without effecting the input and output
1075 * queues.
1077 * RETURNS
1079 * True on success, false on failure eg if the XonChar is equal to the XoffChar.
1081 BOOL WINAPI SetCommState(
1082 HANDLE handle, /* [in] The communications device. */
1083 LPDCB lpdcb) /* [out] The device control block. */
1085 struct termios port;
1086 int fd, bytesize, stopbits;
1088 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1089 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1090 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1091 (lpdcb->StopBits == ONESTOPBIT)?1:
1092 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1093 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1094 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1096 fd = get_comm_fd( handle, GENERIC_READ );
1097 if (fd < 0) return FALSE;
1099 if ((tcgetattr(fd,&port)) == -1) {
1100 int save_error = errno;
1101 COMM_SetCommError(handle,CE_IOE);
1102 release_comm_fd( handle, fd );
1103 ERR("tcgetattr error '%s'\n", strerror(save_error));
1104 return FALSE;
1107 port.c_cc[VMIN] = 0;
1108 port.c_cc[VTIME] = 1;
1110 #ifdef IMAXBEL
1111 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1112 #else
1113 port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1114 #endif
1115 port.c_iflag |= (IGNBRK);
1117 port.c_oflag &= ~(OPOST);
1119 port.c_cflag &= ~(HUPCL);
1120 port.c_cflag |= CLOCAL | CREAD;
1122 port.c_lflag &= ~(ICANON|ECHO|ISIG);
1123 port.c_lflag |= NOFLSH;
1125 #ifdef CBAUD
1126 port.c_cflag &= ~CBAUD;
1127 switch (lpdcb->BaudRate) {
1128 case 110:
1129 case CBR_110:
1130 port.c_cflag |= B110;
1131 break;
1132 case 300:
1133 case CBR_300:
1134 port.c_cflag |= B300;
1135 break;
1136 case 600:
1137 case CBR_600:
1138 port.c_cflag |= B600;
1139 break;
1140 case 1200:
1141 case CBR_1200:
1142 port.c_cflag |= B1200;
1143 break;
1144 case 2400:
1145 case CBR_2400:
1146 port.c_cflag |= B2400;
1147 break;
1148 case 4800:
1149 case CBR_4800:
1150 port.c_cflag |= B4800;
1151 break;
1152 case 9600:
1153 case CBR_9600:
1154 port.c_cflag |= B9600;
1155 break;
1156 case 19200:
1157 case CBR_19200:
1158 port.c_cflag |= B19200;
1159 break;
1160 case 38400:
1161 case CBR_38400:
1162 port.c_cflag |= B38400;
1163 break;
1164 #ifdef B57600
1165 case 57600:
1166 port.c_cflag |= B57600;
1167 break;
1168 #endif
1169 #ifdef B115200
1170 case 115200:
1171 port.c_cflag |= B115200;
1172 break;
1173 #endif
1174 #ifdef B230400
1175 case 230400:
1176 port.c_cflag |= B230400;
1177 break;
1178 #endif
1179 #ifdef B460800
1180 case 460800:
1181 port.c_cflag |= B460800;
1182 break;
1183 #endif
1184 default:
1185 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1186 { struct serial_struct nuts;
1187 int arby;
1188 ioctl(fd, TIOCGSERIAL, &nuts);
1189 nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1190 if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1191 arby = nuts.baud_base / nuts.custom_divisor;
1192 nuts.flags &= ~ASYNC_SPD_MASK;
1193 nuts.flags |= ASYNC_SPD_CUST;
1194 WARN("You (or a program acting at your behest) have specified\n"
1195 "a non-standard baud rate %ld. Wine will set the rate to %d,\n"
1196 "which is as close as we can get by our present understanding of your\n"
1197 "hardware. I hope you know what you are doing. Any disruption Wine\n"
1198 "has caused to your linux system can be undone with setserial \n"
1199 "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1200 "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1201 ioctl(fd, TIOCSSERIAL, &nuts);
1202 port.c_cflag |= B38400;
1204 break;
1205 #endif /* Don't have linux/serial.h or lack TIOCSSERIAL */
1208 COMM_SetCommError(handle,IE_BAUDRATE);
1209 release_comm_fd( handle, fd );
1210 ERR("baudrate %ld\n",lpdcb->BaudRate);
1211 return FALSE;
1213 #elif !defined(__EMX__)
1214 switch (lpdcb->BaudRate) {
1215 case 110:
1216 case CBR_110:
1217 port.c_ospeed = B110;
1218 break;
1219 case 300:
1220 case CBR_300:
1221 port.c_ospeed = B300;
1222 break;
1223 case 600:
1224 case CBR_600:
1225 port.c_ospeed = B600;
1226 break;
1227 case 1200:
1228 case CBR_1200:
1229 port.c_ospeed = B1200;
1230 break;
1231 case 2400:
1232 case CBR_2400:
1233 port.c_ospeed = B2400;
1234 break;
1235 case 4800:
1236 case CBR_4800:
1237 port.c_ospeed = B4800;
1238 break;
1239 case 9600:
1240 case CBR_9600:
1241 port.c_ospeed = B9600;
1242 break;
1243 case 19200:
1244 case CBR_19200:
1245 port.c_ospeed = B19200;
1246 break;
1247 case 38400:
1248 case CBR_38400:
1249 port.c_ospeed = B38400;
1250 break;
1251 #ifdef B57600
1252 case 57600:
1253 case CBR_57600:
1254 port.c_cflag |= B57600;
1255 break;
1256 #endif
1257 #ifdef B115200
1258 case 115200:
1259 case CBR_115200:
1260 port.c_cflag |= B115200;
1261 break;
1262 #endif
1263 #ifdef B230400
1264 case 230400:
1265 port.c_cflag |= B230400;
1266 break;
1267 #endif
1268 #ifdef B460800
1269 case 460800:
1270 port.c_cflag |= B460800;
1271 break;
1272 #endif
1273 default:
1274 COMM_SetCommError(handle,IE_BAUDRATE);
1275 release_comm_fd( handle, fd );
1276 ERR("baudrate %ld\n",lpdcb->BaudRate);
1277 return FALSE;
1279 port.c_ispeed = port.c_ospeed;
1280 #endif
1281 bytesize=lpdcb->ByteSize;
1282 stopbits=lpdcb->StopBits;
1284 #ifdef CMSPAR
1285 port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1286 #else
1287 port.c_cflag &= ~(PARENB | PARODD);
1288 #endif
1289 if (lpdcb->fParity)
1290 port.c_iflag |= INPCK;
1291 else
1292 port.c_iflag &= ~INPCK;
1293 switch (lpdcb->Parity) {
1294 case NOPARITY:
1295 break;
1296 case ODDPARITY:
1297 port.c_cflag |= (PARENB | PARODD);
1298 break;
1299 case EVENPARITY:
1300 port.c_cflag |= PARENB;
1301 break;
1302 #ifdef CMSPAR
1303 /* Linux defines mark/space (stick) parity */
1304 case MARKPARITY:
1305 port.c_cflag |= (PARENB | CMSPAR);
1306 break;
1307 case SPACEPARITY:
1308 port.c_cflag |= (PARENB | PARODD | CMSPAR);
1309 break;
1310 #else
1311 /* try the POSIX way */
1312 case MARKPARITY:
1313 if( stopbits == ONESTOPBIT) {
1314 stopbits = TWOSTOPBITS;
1315 port.c_iflag &= ~INPCK;
1316 } else {
1317 COMM_SetCommError(handle,IE_BYTESIZE);
1318 release_comm_fd( handle, fd );
1319 ERR("Cannot set MARK Parity\n");
1320 return FALSE;
1322 break;
1323 case SPACEPARITY:
1324 if( bytesize < 8) {
1325 bytesize +=1;
1326 port.c_iflag &= ~INPCK;
1327 } else {
1328 COMM_SetCommError(handle,IE_BYTESIZE);
1329 release_comm_fd( handle, fd );
1330 ERR("Cannot set SPACE Parity\n");
1331 return FALSE;
1333 break;
1334 #endif
1335 default:
1336 COMM_SetCommError(handle,IE_BYTESIZE);
1337 release_comm_fd( handle, fd );
1338 ERR("Parity\n");
1339 return FALSE;
1343 port.c_cflag &= ~CSIZE;
1344 switch (bytesize) {
1345 case 5:
1346 port.c_cflag |= CS5;
1347 break;
1348 case 6:
1349 port.c_cflag |= CS6;
1350 break;
1351 case 7:
1352 port.c_cflag |= CS7;
1353 break;
1354 case 8:
1355 port.c_cflag |= CS8;
1356 break;
1357 default:
1358 COMM_SetCommError(handle,IE_BYTESIZE);
1359 release_comm_fd( handle, fd );
1360 ERR("ByteSize\n");
1361 return FALSE;
1364 switch (stopbits) {
1365 case ONESTOPBIT:
1366 port.c_cflag &= ~CSTOPB;
1367 break;
1368 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1369 case TWOSTOPBITS:
1370 port.c_cflag |= CSTOPB;
1371 break;
1372 default:
1373 COMM_SetCommError(handle,IE_BYTESIZE);
1374 release_comm_fd( handle, fd );
1375 ERR("StopBits\n");
1376 return FALSE;
1378 #ifdef CRTSCTS
1379 if ( lpdcb->fOutxCtsFlow ||
1380 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1383 port.c_cflag |= CRTSCTS;
1384 TRACE("CRTSCTS\n");
1386 #endif
1388 if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1390 WARN("DSR/DTR flow control not supported\n");
1393 if (lpdcb->fInX)
1394 port.c_iflag |= IXON;
1395 else
1396 port.c_iflag &= ~IXON;
1397 if (lpdcb->fOutX)
1398 port.c_iflag |= IXOFF;
1399 else
1400 port.c_iflag &= ~IXOFF;
1402 if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1403 int save_error=errno;
1404 COMM_SetCommError(handle,CE_IOE);
1405 release_comm_fd( handle, fd );
1406 ERR("tcsetattr error '%s'\n", strerror(save_error));
1407 return FALSE;
1408 } else {
1409 COMM_SetCommError(handle,0);
1410 release_comm_fd( handle, fd );
1411 return TRUE;
1416 /*****************************************************************************
1417 * GetCommState (KERNEL32.@)
1419 * Fills in a device control block with information from a communications device.
1421 * RETURNS
1423 * True on success, false if the communication device handle is bad etc
1425 * BUGS
1427 * XonChar and XoffChar are not set.
1429 BOOL WINAPI GetCommState(
1430 HANDLE handle, /* [in] The communications device. */
1431 LPDCB lpdcb) /* [out] The device control block. */
1433 struct termios port;
1434 int fd,speed;
1436 TRACE("handle %p, ptr %p\n", handle, lpdcb);
1438 fd = get_comm_fd( handle, GENERIC_READ );
1439 if (fd < 0) return FALSE;
1440 if (tcgetattr(fd, &port) == -1) {
1441 int save_error=errno;
1442 ERR("tcgetattr error '%s'\n", strerror(save_error));
1443 COMM_SetCommError(handle,CE_IOE);
1444 release_comm_fd( handle, fd );
1445 return FALSE;
1447 release_comm_fd( handle, fd );
1448 #ifndef __EMX__
1449 #ifdef CBAUD
1450 speed= (port.c_cflag & CBAUD);
1451 #else
1452 speed= (cfgetospeed(&port));
1453 #endif
1454 switch (speed) {
1455 case B110:
1456 lpdcb->BaudRate = 110;
1457 break;
1458 case B300:
1459 lpdcb->BaudRate = 300;
1460 break;
1461 case B600:
1462 lpdcb->BaudRate = 600;
1463 break;
1464 case B1200:
1465 lpdcb->BaudRate = 1200;
1466 break;
1467 case B2400:
1468 lpdcb->BaudRate = 2400;
1469 break;
1470 case B4800:
1471 lpdcb->BaudRate = 4800;
1472 break;
1473 case B9600:
1474 lpdcb->BaudRate = 9600;
1475 break;
1476 case B19200:
1477 lpdcb->BaudRate = 19200;
1478 break;
1479 case B38400:
1480 lpdcb->BaudRate = 38400;
1481 break;
1482 #ifdef B57600
1483 case B57600:
1484 lpdcb->BaudRate = 57600;
1485 break;
1486 #endif
1487 #ifdef B115200
1488 case B115200:
1489 lpdcb->BaudRate = 115200;
1490 break;
1491 #endif
1492 #ifdef B230400
1493 case B230400:
1494 lpdcb->BaudRate = 230400;
1495 break;
1496 #endif
1497 #ifdef B460800
1498 case B460800:
1499 lpdcb->BaudRate = 460800;
1500 break;
1501 #endif
1502 default:
1503 ERR("unknown speed %x \n",speed);
1505 #endif
1506 switch (port.c_cflag & CSIZE) {
1507 case CS5:
1508 lpdcb->ByteSize = 5;
1509 break;
1510 case CS6:
1511 lpdcb->ByteSize = 6;
1512 break;
1513 case CS7:
1514 lpdcb->ByteSize = 7;
1515 break;
1516 case CS8:
1517 lpdcb->ByteSize = 8;
1518 break;
1519 default:
1520 ERR("unknown size %x \n",port.c_cflag & CSIZE);
1523 if(port.c_iflag & INPCK)
1524 lpdcb->fParity = TRUE;
1525 else
1526 lpdcb->fParity = FALSE;
1527 #ifdef CMSPAR
1528 switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1529 #else
1530 switch (port.c_cflag & (PARENB | PARODD))
1531 #endif
1533 case 0:
1534 lpdcb->Parity = NOPARITY;
1535 break;
1536 case PARENB:
1537 lpdcb->Parity = EVENPARITY;
1538 break;
1539 case (PARENB | PARODD):
1540 lpdcb->Parity = ODDPARITY;
1541 break;
1542 #ifdef CMSPAR
1543 case (PARENB | CMSPAR):
1544 lpdcb->Parity = MARKPARITY;
1545 break;
1546 case (PARENB | PARODD | CMSPAR):
1547 lpdcb->Parity = SPACEPARITY;
1548 break;
1549 #endif
1552 if (port.c_cflag & CSTOPB)
1553 if(lpdcb->ByteSize == 5)
1554 lpdcb->StopBits = ONE5STOPBITS;
1555 else
1556 lpdcb->StopBits = TWOSTOPBITS;
1557 else
1558 lpdcb->StopBits = ONESTOPBIT;
1560 lpdcb->fNull = 0;
1561 lpdcb->fBinary = 1;
1563 /* termios does not support DTR/DSR flow control */
1564 lpdcb->fOutxDsrFlow = 0;
1565 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1567 #ifdef CRTSCTS
1569 if (port.c_cflag & CRTSCTS) {
1570 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1571 lpdcb->fOutxCtsFlow = 1;
1572 } else
1573 #endif
1575 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1576 lpdcb->fOutxCtsFlow = 0;
1578 if (port.c_iflag & IXON)
1579 lpdcb->fInX = 1;
1580 else
1581 lpdcb->fInX = 0;
1583 if (port.c_iflag & IXOFF)
1584 lpdcb->fOutX = 1;
1585 else
1586 lpdcb->fOutX = 0;
1588 lpdcb->XonChar =
1589 lpdcb->XoffChar =
1591 lpdcb->XonLim = 10;
1592 lpdcb->XoffLim = 10;
1594 COMM_SetCommError(handle,0);
1596 TRACE("OK\n");
1598 TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1599 lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1600 (lpdcb->StopBits == ONESTOPBIT)?1:
1601 (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1602 TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1603 (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1604 #ifdef CRTSCTS
1605 if ( lpdcb->fOutxCtsFlow ||
1606 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1608 TRACE("CRTSCTS\n");
1609 else
1611 TRACE("~CRTSCTS\n");
1613 #endif
1614 return TRUE;
1617 /*****************************************************************************
1618 * TransmitCommChar (KERNEL32.@)
1620 * Transmits a single character in front of any pending characters in the
1621 * output buffer. Usually used to send an interrupt character to a host.
1623 * RETURNS
1625 * True if the call succeeded, false if the previous command character to the
1626 * same device has not been sent yet the handle is bad etc.
1628 * BUGS
1630 * Stub.
1632 BOOL WINAPI TransmitCommChar(
1633 HANDLE hComm, /* [in] The communication device in need of a command character. */
1634 CHAR chTransmit) /* [in] The character to transmit. */
1636 WARN("(%p,'%c') not perfect!\n",hComm,chTransmit);
1638 return WriteFile( hComm, &chTransmit, 1, NULL, NULL );
1642 /*****************************************************************************
1643 * GetCommTimeouts (KERNEL32.@)
1645 * Obtains the request timeout values for the communications device.
1647 * RETURNS
1649 * True on success, false if communications device handle is bad
1650 * or the target structure is null.
1652 BOOL WINAPI GetCommTimeouts(
1653 HANDLE hComm, /* [in] The communications device. */
1654 LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1656 BOOL ret;
1658 TRACE("(%p,%p)\n",hComm,lptimeouts);
1660 if(!lptimeouts)
1662 SetLastError(ERROR_INVALID_PARAMETER);
1663 return FALSE;
1666 SERVER_START_REQ( get_serial_info )
1668 req->handle = hComm;
1669 if ((ret = !wine_server_call_err( req )))
1671 lptimeouts->ReadIntervalTimeout = reply->readinterval;
1672 lptimeouts->ReadTotalTimeoutMultiplier = reply->readmult;
1673 lptimeouts->ReadTotalTimeoutConstant = reply->readconst;
1674 lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1675 lptimeouts->WriteTotalTimeoutConstant = reply->writeconst;
1678 SERVER_END_REQ;
1679 return ret;
1682 /*****************************************************************************
1683 * SetCommTimeouts (KERNEL32.@)
1685 * Sets the timeouts used when reading and writing data to/from COMM ports.
1687 * ReadIntervalTimeout
1688 * - converted and passes to linux kernel as c_cc[VTIME]
1689 * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1690 * - used in ReadFile to calculate GetOverlappedResult's timeout
1691 * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1692 * - used in WriteFile to calculate GetOverlappedResult's timeout
1694 * RETURNS
1696 * True if the timeouts were set, false otherwise.
1698 BOOL WINAPI SetCommTimeouts(
1699 HANDLE hComm, /* [in] handle of COMM device */
1700 LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1702 BOOL ret;
1703 int fd;
1704 struct termios tios;
1706 TRACE("(%p,%p)\n",hComm,lptimeouts);
1708 if(!lptimeouts)
1710 SetLastError(ERROR_INVALID_PARAMETER);
1711 return FALSE;
1714 SERVER_START_REQ( set_serial_info )
1716 req->handle = hComm;
1717 req->flags = SERIALINFO_SET_TIMEOUTS;
1718 req->readinterval = lptimeouts->ReadIntervalTimeout ;
1719 req->readmult = lptimeouts->ReadTotalTimeoutMultiplier ;
1720 req->readconst = lptimeouts->ReadTotalTimeoutConstant ;
1721 req->writemult = lptimeouts->WriteTotalTimeoutMultiplier ;
1722 req->writeconst = lptimeouts->WriteTotalTimeoutConstant ;
1723 ret = !wine_server_call_err( req );
1725 SERVER_END_REQ;
1726 if (!ret) return FALSE;
1728 /* FIXME: move this stuff to the server */
1729 fd = get_comm_fd( hComm, GENERIC_READ );
1730 if (fd < 0) return FALSE;
1732 if (-1==tcgetattr(fd,&tios)) {
1733 FIXME("tcgetattr on fd %d failed!\n",fd);
1734 release_comm_fd( hComm, fd );
1735 return FALSE;
1738 /* VTIME is in 1/10 seconds */
1740 unsigned int ux_timeout;
1742 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1744 ux_timeout = 0;
1746 else
1748 ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1749 if(ux_timeout == 0)
1751 ux_timeout = 1; /* must be at least some timeout */
1754 tios.c_cc[VTIME] = ux_timeout;
1757 if (-1==tcsetattr(fd,0,&tios)) {
1758 FIXME("tcsetattr on fd %d failed!\n",fd);
1759 release_comm_fd( hComm, fd );
1760 return FALSE;
1762 release_comm_fd( hComm, fd );
1763 return TRUE;
1766 /***********************************************************************
1767 * GetCommModemStatus (KERNEL32.@)
1769 * Obtains the four control register bits if supported by the hardware.
1771 * RETURNS
1773 * True if the communications handle was good and for hardware that
1774 * control register access, false otherwise.
1776 BOOL WINAPI GetCommModemStatus(
1777 HANDLE hFile, /* [in] The communications device. */
1778 LPDWORD lpModemStat) /* [out] The control register bits. */
1780 int fd,mstat, result=FALSE;
1782 *lpModemStat=0;
1783 #ifdef TIOCMGET
1784 fd = get_comm_fd( hFile, GENERIC_READ );
1785 if(fd<0)
1786 return FALSE;
1787 result = ioctl(fd, TIOCMGET, &mstat);
1788 release_comm_fd( hFile, fd );
1789 if (result == -1)
1791 WARN("ioctl failed\n");
1792 return FALSE;
1794 #ifdef TIOCM_CTS
1795 if (mstat & TIOCM_CTS)
1796 *lpModemStat |= MS_CTS_ON;
1797 #endif
1798 #ifdef TIOCM_DSR
1799 if (mstat & TIOCM_DSR)
1800 *lpModemStat |= MS_DSR_ON;
1801 #endif
1802 #ifdef TIOCM_RNG
1803 if (mstat & TIOCM_RNG)
1804 *lpModemStat |= MS_RING_ON;
1805 #endif
1806 #ifdef TIOCM_CAR
1807 /*FIXME: Not really sure about RLSD UB 990810*/
1808 if (mstat & TIOCM_CAR)
1809 *lpModemStat |= MS_RLSD_ON;
1810 #endif
1811 TRACE("%04x -> %s%s%s%s\n", mstat,
1812 (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1813 (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1814 (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1815 (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1816 return TRUE;
1817 #else
1818 return FALSE;
1819 #endif
1822 /***********************************************************************
1823 * COMM_WaitCommEventService (INTERNAL)
1825 * This function is called while the client is waiting on the
1826 * server, so we can't make any server calls here.
1828 static void COMM_WaitCommEventService(async_private *ovp)
1830 async_commio *commio = (async_commio*) ovp;
1831 IO_STATUS_BLOCK* iosb = commio->async.iosb;
1833 TRACE("iosb %p\n",iosb);
1835 /* FIXME: detect other events */
1836 *commio->buffer = EV_RXCHAR;
1838 iosb->u.Status = STATUS_SUCCESS;
1842 /***********************************************************************
1843 * COMM_WaitCommEvent (INTERNAL)
1845 * This function must have an lpOverlapped.
1847 static BOOL COMM_WaitCommEvent(
1848 HANDLE hFile, /* [in] handle of comm port to wait for */
1849 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1850 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1852 int fd;
1853 async_commio *ovp;
1855 if(!lpOverlapped)
1857 SetLastError(ERROR_INVALID_PARAMETER);
1858 return FALSE;
1861 if(NtResetEvent(lpOverlapped->hEvent,NULL))
1862 return FALSE;
1864 fd = get_comm_fd( hFile, GENERIC_WRITE );
1865 if(fd<0)
1866 return FALSE;
1868 ovp = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1869 if(!ovp)
1871 release_comm_fd( hFile, fd );
1872 return FALSE;
1875 ovp->async.ops = &commio_async_ops;
1876 ovp->async.handle = hFile;
1877 ovp->async.fd = fd; /* FIXME */
1878 ovp->async.type = ASYNC_TYPE_WAIT;
1879 ovp->async.func = COMM_WaitCommEventService;
1880 ovp->async.event = lpOverlapped->hEvent;
1881 ovp->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
1882 ovp->buffer = (char *)lpdwEvents;
1884 lpOverlapped->InternalHigh = 0;
1885 lpOverlapped->Offset = 0;
1886 lpOverlapped->OffsetHigh = 0;
1888 if ( !register_new_async (&ovp->async) )
1889 SetLastError( ERROR_IO_PENDING );
1891 return FALSE;
1894 /***********************************************************************
1895 * WaitCommEvent (KERNEL32.@)
1897 * Wait until something interesting happens on a COMM port.
1898 * Interesting things (events) are set by calling SetCommMask before
1899 * this function is called.
1901 * RETURNS:
1902 * TRUE if successful
1903 * FALSE if failure
1905 * The set of detected events will be written to *lpdwEventMask
1906 * ERROR_IO_PENDING will be returned the overlapped structure was passed
1908 * BUGS:
1909 * Only supports EV_RXCHAR and EV_TXEMPTY
1911 BOOL WINAPI WaitCommEvent(
1912 HANDLE hFile, /* [in] handle of comm port to wait for */
1913 LPDWORD lpdwEvents, /* [out] event(s) that were detected */
1914 LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1916 OVERLAPPED ov;
1917 int ret;
1919 TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
1921 if(lpOverlapped)
1922 return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
1924 /* if there is no overlapped structure, create our own */
1925 ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
1927 COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
1929 /* wait for the overlapped to complete */
1930 ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
1931 CloseHandle(ov.hEvent);
1933 return ret;
1936 /***********************************************************************
1937 * GetCommProperties (KERNEL32.@)
1939 * This function fills in a structure with the capabilities of the
1940 * communications port driver.
1942 * RETURNS
1944 * TRUE on success, FALSE on failure
1945 * If successful, the lpCommProp structure be filled in with
1946 * properties of the comm port.
1948 BOOL WINAPI GetCommProperties(
1949 HANDLE hFile, /* [in] handle of the comm port */
1950 LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
1952 FIXME("(%p %p )\n",hFile,lpCommProp);
1953 if(!lpCommProp)
1954 return FALSE;
1957 * These values should be valid for LINUX's serial driver
1958 * FIXME: Perhaps they deserve an #ifdef LINUX
1960 memset(lpCommProp,0,sizeof(COMMPROP));
1961 lpCommProp->wPacketLength = 1;
1962 lpCommProp->wPacketVersion = 1;
1963 lpCommProp->dwServiceMask = SP_SERIALCOMM;
1964 lpCommProp->dwReserved1 = 0;
1965 lpCommProp->dwMaxTxQueue = 4096;
1966 lpCommProp->dwMaxRxQueue = 4096;
1967 lpCommProp->dwMaxBaud = BAUD_115200;
1968 lpCommProp->dwProvSubType = PST_RS232;
1969 lpCommProp->dwProvCapabilities = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
1970 lpCommProp->dwSettableParams = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
1971 SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
1972 lpCommProp->dwSettableBaud = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
1973 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
1974 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
1975 lpCommProp->wSettableData = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
1976 lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
1977 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
1978 lpCommProp->dwCurrentTxQueue = lpCommProp->dwMaxTxQueue;
1979 lpCommProp->dwCurrentRxQueue = lpCommProp->dwMaxRxQueue;
1981 return TRUE;
1984 /***********************************************************************
1985 * FIXME:
1986 * The functionality of CommConfigDialogA, GetDefaultCommConfig and
1987 * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
1988 * This is dependent on the type of COMM port, but since it is doubtful
1989 * anybody will get around to implementing support for fancy serial
1990 * ports in WINE, this is hardcoded for the time being. The name of
1991 * this DLL should be stored in and read from the system registry in
1992 * the hive HKEY_LOCAL_MACHINE, key
1993 * System\\CurrentControlSet\\Services\\Class\\Ports\\????
1994 * where ???? is the port number... that is determined by PNP
1995 * The DLL should be loaded when the COMM port is opened, and closed
1996 * when the COMM port is closed. - MJM 20 June 2000
1997 ***********************************************************************/
1998 static CHAR lpszSerialUI[] = "serialui.dll";
2001 /***********************************************************************
2002 * CommConfigDialogA (KERNEL32.@)
2004 * Raises a dialog that allows the user to configure a comm port.
2005 * Fills the COMMCONFIG struct with information specified by the user.
2006 * This function should call a similar routine in the COMM driver...
2008 * RETURNS
2010 * TRUE on success, FALSE on failure
2011 * If successful, the lpCommConfig structure will contain a new
2012 * configuration for the comm port, as specified by the user.
2014 * BUGS
2015 * The library with the CommConfigDialog code is never unloaded.
2016 * Perhaps this should be done when the comm port is closed?
2018 BOOL WINAPI CommConfigDialogA(
2019 LPCSTR lpszDevice, /* [in] name of communications device */
2020 HANDLE hWnd, /* [in] parent window for the dialog */
2021 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2023 FARPROC lpfnCommDialog;
2024 HMODULE hConfigModule;
2025 BOOL r;
2027 TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2029 hConfigModule = LoadLibraryA(lpszSerialUI);
2030 if(!hConfigModule)
2031 return FALSE;
2033 lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
2035 if(!lpfnCommDialog)
2036 return FALSE;
2038 r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2040 /* UnloadLibrary(hConfigModule); */
2042 return r;
2045 /***********************************************************************
2046 * CommConfigDialogW (KERNEL32.@)
2048 * see CommConfigDialogA for more info
2050 BOOL WINAPI CommConfigDialogW(
2051 LPCWSTR lpszDevice, /* [in] name of communications device */
2052 HANDLE hWnd, /* [in] parent window for the dialog */
2053 LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2055 BOOL r;
2056 LPSTR lpDeviceA;
2058 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2059 if(lpDeviceA)
2060 return FALSE;
2061 r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
2062 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2063 return r;
2066 /***********************************************************************
2067 * GetCommConfig (KERNEL32.@)
2069 * Fill in the COMMCONFIG structure for the comm port hFile
2071 * RETURNS
2073 * TRUE on success, FALSE on failure
2074 * If successful, lpCommConfig contains the comm port configuration.
2076 * BUGS
2079 BOOL WINAPI GetCommConfig(
2080 HANDLE hFile, /* [in] The communications device. */
2081 LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2082 LPDWORD lpdwSize) /* [in/out] Initially the size of the configuration buffer/structure,
2083 afterwards the number of bytes copied to the buffer or
2084 the needed size of the buffer. */
2086 BOOL r;
2088 TRACE("(%p %p)\n",hFile,lpCommConfig);
2090 if(lpCommConfig == NULL)
2091 return FALSE;
2092 r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
2093 *lpdwSize = sizeof(COMMCONFIG);
2094 if(r)
2095 return FALSE;
2097 lpCommConfig->dwSize = sizeof(COMMCONFIG);
2098 lpCommConfig->wVersion = 1;
2099 lpCommConfig->wReserved = 0;
2100 r = GetCommState(hFile,&lpCommConfig->dcb);
2101 lpCommConfig->dwProviderSubType = PST_RS232;
2102 lpCommConfig->dwProviderOffset = 0;
2103 lpCommConfig->dwProviderSize = 0;
2105 return r;
2108 /***********************************************************************
2109 * SetCommConfig (KERNEL32.@)
2111 * Sets the configuration of the communications device.
2113 * RETURNS
2115 * True on success, false if the handle was bad is not a communications device.
2117 BOOL WINAPI SetCommConfig(
2118 HANDLE hFile, /* [in] The communications device. */
2119 LPCOMMCONFIG lpCommConfig, /* [in] The desired configuration. */
2120 DWORD dwSize) /* [in] size of the lpCommConfig struct */
2122 TRACE("(%p %p)\n",hFile,lpCommConfig);
2123 return SetCommState(hFile,&lpCommConfig->dcb);
2126 /***********************************************************************
2127 * SetDefaultCommConfigA (KERNEL32.@)
2129 * Initializes the default configuration for the specified communication
2130 * device. (ascii)
2132 * RETURNS
2134 * True if the device was found and the defaults set, false otherwise
2136 BOOL WINAPI SetDefaultCommConfigA(
2137 LPCSTR lpszDevice, /* [in] The ascii name of the device targeted for configuration. */
2138 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2139 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2141 FARPROC lpfnSetDefaultCommConfig;
2142 HMODULE hConfigModule;
2143 BOOL r;
2145 TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2147 hConfigModule = LoadLibraryA(lpszSerialUI);
2148 if(!hConfigModule)
2149 return FALSE;
2151 lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
2153 if(! lpfnSetDefaultCommConfig)
2154 return TRUE;
2156 r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2158 /* UnloadLibrary(hConfigModule); */
2160 return r;
2164 /***********************************************************************
2165 * SetDefaultCommConfigW (KERNEL32.@)
2167 * Initializes the default configuration for the specified
2168 * communication device. (unicode)
2170 * RETURNS
2173 BOOL WINAPI SetDefaultCommConfigW(
2174 LPCWSTR lpszDevice, /* [in] The unicode name of the device targeted for configuration. */
2175 LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2176 DWORD dwSize) /* [in] The number of bytes in the configuration structure. */
2178 BOOL r;
2179 LPSTR lpDeviceA;
2181 TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
2183 lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2184 if(lpDeviceA)
2185 return FALSE;
2186 r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
2187 HeapFree( GetProcessHeap(), 0, lpDeviceA );
2188 return r;
2192 /***********************************************************************
2193 * GetDefaultCommConfigA (KERNEL32.@)
2195 * Acquires the default configuration of the specified communication device. (unicode)
2197 * RETURNS
2199 * True on successful reading of the default configuration,
2200 * if the device is not found or the buffer is too small.
2202 BOOL WINAPI GetDefaultCommConfigA(
2203 LPCSTR lpszName, /* [in] The ascii name of the device targeted for configuration. */
2204 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2205 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2206 afterwards the number of bytes copied to the buffer or
2207 the needed size of the buffer. */
2209 LPDCB lpdcb = &(lpCC->dcb);
2210 char temp[40];
2212 if (strncasecmp(lpszName,"COM",3)) {
2213 ERR("not implemented for <%s>\n", lpszName);
2214 return FALSE;
2217 TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
2218 if (*lpdwSize < sizeof(COMMCONFIG)) {
2219 *lpdwSize = sizeof(COMMCONFIG);
2220 return FALSE;
2223 *lpdwSize = sizeof(COMMCONFIG);
2225 lpCC->dwSize = sizeof(COMMCONFIG);
2226 lpCC->wVersion = 1;
2227 lpCC->dwProviderSubType = PST_RS232;
2228 lpCC->dwProviderOffset = 0L;
2229 lpCC->dwProviderSize = 0L;
2231 sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
2232 FIXME("setting %s as default\n", temp);
2234 return BuildCommDCBA( temp, lpdcb);
2237 /**************************************************************************
2238 * GetDefaultCommConfigW (KERNEL32.@)
2240 * Acquires the default configuration of the specified communication device. (unicode)
2242 * RETURNS
2244 * True on successful reading of the default configuration,
2245 * if the device is not found or the buffer is too small.
2247 BOOL WINAPI GetDefaultCommConfigW(
2248 LPCWSTR lpszName, /* [in] The unicode name of the device targeted for configuration. */
2249 LPCOMMCONFIG lpCC, /* [out] The default configuration for the device. */
2250 LPDWORD lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2251 afterwards the number of bytes copied to the buffer or
2252 the needed size of the buffer. */
2254 BOOL ret = FALSE;
2255 LPSTR lpszNameA;
2257 TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2258 lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
2259 if (lpszNameA)
2261 ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
2262 HeapFree( GetProcessHeap(), 0, lpszNameA );
2264 return ret;