Fixed size check in GetCommConfig().
[wine] / dlls / kernel / comm.c
1 /*
2  * DEC 93 Erik Bos <erik@xs4all.nl>
3  *
4  * Copyright 1996 Marcus Meissner
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * History:
21  *
22  * Apr 3, 1999.  Lawson Whitney <lawson_whitney@juno.com>
23  * - Fixed the modem control part of EscapeCommFunction16.
24  *
25  * Mar 31, 1999. Ove Kåven <ovek@arcticnet.no>
26  * - Implemented buffers and EnableCommNotification.
27  *
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.
32  *
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.
37  *
38  * July 6, 1998. Fixes and comments by Valentijn Sessink
39  *                                     <vsessink@ic.uva.nl> [V]
40  *
41  * August 12, 1997.  Take a bash at SetCommEventMask - Lawson Whitney
42  *                                     <lawson_whitney@juno.com>
43  *
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.
50  */
51
52 #include "config.h"
53 #include "wine/port.h"
54
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
87
88 #define NONAMELESSUNION
89 #define NONAMELESSSTRUCT
90 #include "ntstatus.h"
91 #include "windef.h"
92 #include "winbase.h"
93 #include "winerror.h"
94
95 #include "wine/server.h"
96 #include "async.h"
97 #include "heap.h"
98
99 #include "wine/debug.h"
100
101 #ifdef HAVE_LINUX_SERIAL_H
102 #include <linux/serial.h>
103 #endif
104
105 WINE_DEFAULT_DEBUG_CHANNEL(comm);
106
107 /* retrieve the Unix handle corresponding to a comm handle */
108 static int get_comm_fd( HANDLE handle, DWORD access )
109 {
110     int fd, ret;
111
112     ret = wine_server_handle_to_fd( handle, access, &fd, NULL, NULL );
113     if (ret) SetLastError( RtlNtStatusToDosError(ret) );
114     return fd;
115 }
116
117 /* release the Unix handle returned by get_comm_fd */
118 static inline void release_comm_fd( HANDLE handle, int fd )
119 {
120     wine_server_release_fd( handle, fd );
121 }
122
123
124 /***********************************************************************
125  * Asynchronous I/O for asynchronous wait requests                     *
126  */
127
128 static DWORD commio_get_async_count (const async_private *ovp);
129 static void commio_async_cleanup  (async_private *ovp);
130
131 static async_ops commio_async_ops =
132 {
133     commio_get_async_count,        /* get_count */
134     NULL,                          /* call_completion */
135     commio_async_cleanup           /* cleanup */
136 };
137
138 typedef struct async_commio
139 {
140     struct async_private             async;
141     char                             *buffer;
142 } async_commio;
143
144 static DWORD commio_get_async_count (const struct async_private *ovp)
145 {
146     return 0;
147 }
148
149 static void commio_async_cleanup  (async_private *ovp)
150 {
151     HeapFree(GetProcessHeap(), 0, ovp );
152 }
153
154 /***********************************************************************/
155
156 #if !defined(TIOCINQ) && defined(FIONREAD)
157 #define TIOCINQ FIONREAD
158 #endif
159
160 static int COMM_WhackModem(int fd, unsigned int andy, unsigned int orrie)
161 {
162 #ifdef TIOCMGET
163     unsigned int mstat, okay;
164     okay = ioctl(fd, TIOCMGET, &mstat);
165     if (okay) return okay;
166     if (andy) mstat &= andy;
167     mstat |= orrie;
168     return ioctl(fd, TIOCMSET, &mstat);
169 #else
170     return 0;
171 #endif
172 }
173
174 /***********************************************************************
175  *           COMM_Parse*   (Internal)
176  *
177  *  The following COMM_Parse* functions are used by the BuildCommDCB
178  *  functions to help parse the various parts of the device control string.
179  */
180 static LPCSTR COMM_ParseStart(LPCSTR ptr)
181 {
182         /* The device control string may optionally start with "COMx" followed
183            by an optional ':' and spaces. */
184         if(!strncasecmp(ptr, "COM", 3))
185         {
186                 ptr += 3;
187
188                 /* Allow any com port above 0 as Win 9x does (NT only allows
189                    values for com ports which are actually present) */
190                 if(*ptr < '1' || *ptr > '9')
191                         return NULL;
192                 
193                 /* Advance pointer past port number */
194                 while(*ptr >= '0' && *ptr <= '9') ptr++;
195                 
196                 /* The com port number must be followed by a ':' or ' ' */
197                 if(*ptr != ':' && *ptr != ' ')
198                         return NULL;
199
200                 /* Advance pointer to beginning of next parameter */
201                 while(*ptr == ' ') ptr++;
202                 if(*ptr == ':')
203                 {
204                         ptr++;
205                         while(*ptr == ' ') ptr++;
206                 }
207         }
208         /* The device control string must not start with a space. */
209         else if(*ptr == ' ')
210                 return NULL;
211         
212         return ptr;
213 }
214  
215 static LPCSTR COMM_ParseNumber(LPCSTR ptr, LPDWORD lpnumber)
216 {
217         if(*ptr < '0' || *ptr > '9') return NULL;
218         if(!sscanf(ptr, "%lu", lpnumber)) return NULL;
219         while(*ptr >= '0' && *ptr <= '9') ptr++;
220         return ptr;
221 }
222
223 static LPCSTR COMM_ParseParity(LPCSTR ptr, LPBYTE lpparity)
224 {
225         /* Contrary to what you might expect, Windows only sets the Parity
226            member of DCB and not fParity even when parity is specified in the
227            device control string */
228
229         switch(toupper(*ptr++))
230         {
231         case 'E':
232                 *lpparity = EVENPARITY;
233                 break;
234         case 'M':
235                 *lpparity = MARKPARITY;
236                 break;
237         case 'N':
238                 *lpparity = NOPARITY;
239                 break;
240         case 'O':
241                 *lpparity = ODDPARITY;
242                 break;
243         case 'S':
244                 *lpparity = SPACEPARITY;
245                 break;
246         default:
247                 return NULL;
248         }
249
250         return ptr;
251 }
252
253 static LPCSTR COMM_ParseByteSize(LPCSTR ptr, LPBYTE lpbytesize)
254 {
255         DWORD temp;
256
257         if(!(ptr = COMM_ParseNumber(ptr, &temp)))
258                 return NULL;
259
260         if(temp >= 5 && temp <= 8)
261         {
262                 *lpbytesize = temp;
263                 return ptr;
264         }
265         else
266                 return NULL;
267 }
268
269 static LPCSTR COMM_ParseStopBits(LPCSTR ptr, LPBYTE lpstopbits)
270 {
271         DWORD temp;
272
273         if(!strncmp("1.5", ptr, 3))
274         {
275                 ptr += 3;
276                 *lpstopbits = ONE5STOPBITS;
277         }
278         else
279         {
280                 if(!(ptr = COMM_ParseNumber(ptr, &temp)))
281                         return NULL;
282
283                 if(temp == 1)
284                         *lpstopbits = ONESTOPBIT;
285                 else if(temp == 2)
286                         *lpstopbits = TWOSTOPBITS;
287                 else
288                         return NULL;
289         }
290         
291         return ptr;
292 }
293
294 static LPCSTR COMM_ParseOnOff(LPCSTR ptr, LPDWORD lponoff)
295 {
296         if(!strncasecmp("on", ptr, 2))
297         {
298                 ptr += 2;
299                 *lponoff = 1;
300         }
301         else if(!strncasecmp("off", ptr, 3))
302         {
303                 ptr += 3;
304                 *lponoff = 0;
305         }
306         else
307                 return NULL;
308
309         return ptr;
310 }
311
312 /***********************************************************************
313  *           COMM_BuildOldCommDCB   (Internal)
314  *
315  *  Build a DCB using the old style settings string eg: "96,n,8,1"
316  */
317 static BOOL COMM_BuildOldCommDCB(LPCSTR device, LPDCB lpdcb)
318 {
319         char last = 0;
320
321         if(!(device = COMM_ParseNumber(device, &lpdcb->BaudRate)))
322                 return FALSE;
323         
324         switch(lpdcb->BaudRate)
325         {
326         case 11:
327         case 30:
328         case 60:
329                 lpdcb->BaudRate *= 10;
330                 break;
331         case 12:
332         case 24:
333         case 48:
334         case 96:
335                 lpdcb->BaudRate *= 100;
336                 break;
337         case 19:
338                 lpdcb->BaudRate = 19200;
339                 break;
340         }
341
342         while(*device == ' ') device++;
343         if(*device++ != ',') return FALSE;
344         while(*device == ' ') device++;
345
346         if(!(device = COMM_ParseParity(device, &lpdcb->Parity)))
347                 return FALSE;
348
349         while(*device == ' ') device++;
350         if(*device++ != ',') return FALSE;
351         while(*device == ' ') device++;
352                 
353         if(!(device = COMM_ParseByteSize(device, &lpdcb->ByteSize)))
354                 return FALSE;
355
356         while(*device == ' ') device++;
357         if(*device++ != ',') return FALSE;
358         while(*device == ' ') device++;
359
360         if(!(device = COMM_ParseStopBits(device, &lpdcb->StopBits)))
361                 return FALSE;
362
363         /* The last parameter for flow control is optional. */
364         while(*device == ' ') device++;
365         if(*device == ',')
366         {
367                 device++;
368                 while(*device == ' ') device++;
369                 if(*device) last = toupper(*device++);
370                 while(*device == ' ') device++;
371         }
372
373         /* Win NT sets the flow control members based on (or lack of) the last
374            parameter.  Win 9x does not set these members. */
375         switch(last)
376         {
377         case 0:
378                 lpdcb->fInX = FALSE;
379                 lpdcb->fOutX = FALSE;
380                 lpdcb->fOutxCtsFlow = FALSE;
381                 lpdcb->fOutxDsrFlow = FALSE;
382                 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
383                 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
384                 break;
385         case 'X':
386                 lpdcb->fInX = TRUE;
387                 lpdcb->fOutX = TRUE;
388                 lpdcb->fOutxCtsFlow = FALSE;
389                 lpdcb->fOutxDsrFlow = FALSE;
390                 lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
391                 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
392                 break;
393         case 'P':
394                 lpdcb->fInX = FALSE;
395                 lpdcb->fOutX = FALSE;
396                 lpdcb->fOutxCtsFlow = TRUE;
397                 lpdcb->fOutxDsrFlow = TRUE;
398                 lpdcb->fDtrControl = DTR_CONTROL_HANDSHAKE;
399                 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
400                 break;
401         default:
402                 return FALSE;
403         }
404
405         /* This should be the end of the string. */
406         if(*device) return FALSE;
407         
408         return TRUE;
409 }
410
411 /***********************************************************************
412  *           COMM_BuildNewCommDCB   (Internal)
413  *
414  *  Build a DCB using the new style settings string.
415  *   eg: "baud=9600 parity=n data=8 stop=1 xon=on to=on"
416  */
417 static BOOL COMM_BuildNewCommDCB(LPCSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
418 {
419         DWORD temp;
420         BOOL baud = FALSE, stop = FALSE;
421
422         while(*device)
423         {
424                 while(*device == ' ') device++;
425
426                 if(!strncasecmp("baud=", device, 5))
427                 {
428                         baud = TRUE;
429                         
430                         if(!(device = COMM_ParseNumber(device + 5, &lpdcb->BaudRate)))
431                                 return FALSE;
432                 }
433                 else if(!strncasecmp("parity=", device, 7))
434                 {
435                         if(!(device = COMM_ParseParity(device + 7, &lpdcb->Parity)))
436                                 return FALSE;
437                 }
438                 else if(!strncasecmp("data=", device, 5))
439                 {
440                         if(!(device = COMM_ParseByteSize(device + 5, &lpdcb->ByteSize)))
441                                 return FALSE;
442                 }
443                 else if(!strncasecmp("stop=", device, 5))
444                 {
445                         stop = TRUE;
446                         
447                         if(!(device = COMM_ParseStopBits(device + 5, &lpdcb->StopBits)))
448                                 return FALSE;
449                 }
450                 else if(!strncasecmp("to=", device, 3))
451                 {
452                         if(!(device = COMM_ParseOnOff(device + 3, &temp)))
453                                 return FALSE;
454
455                         lptimeouts->ReadIntervalTimeout = 0;
456                         lptimeouts->ReadTotalTimeoutMultiplier = 0;
457                         lptimeouts->ReadTotalTimeoutConstant = 0;
458                         lptimeouts->WriteTotalTimeoutMultiplier = 0;
459                         lptimeouts->WriteTotalTimeoutConstant = temp ? 60000 : 0;
460                 }
461                 else if(!strncasecmp("xon=", device, 4))
462                 {
463                         if(!(device = COMM_ParseOnOff(device + 4, &temp)))
464                                 return FALSE;
465
466                         lpdcb->fOutX = temp;
467                         lpdcb->fInX = temp;
468                 }
469                 else if(!strncasecmp("odsr=", device, 5))
470                 {
471                         if(!(device = COMM_ParseOnOff(device + 5, &temp)))
472                                 return FALSE;
473
474                         lpdcb->fOutxDsrFlow = temp;
475                 }
476                 else if(!strncasecmp("octs=", device, 5))
477                 {
478                         if(!(device = COMM_ParseOnOff(device + 5, &temp)))
479                                 return FALSE;
480
481                         lpdcb->fOutxCtsFlow = temp;
482                 }
483                 else if(!strncasecmp("dtr=", device, 4))
484                 {
485                         if(!(device = COMM_ParseOnOff(device + 4, &temp)))
486                                 return FALSE;
487
488                         lpdcb->fDtrControl = temp;
489                 }
490                 else if(!strncasecmp("rts=", device, 4))
491                 {
492                         if(!(device = COMM_ParseOnOff(device + 4, &temp)))
493                                 return FALSE;
494
495                         lpdcb->fRtsControl = temp;
496                 }
497                 else if(!strncasecmp("idsr=", device, 5))
498                 {
499                         if(!(device = COMM_ParseOnOff(device + 5, &temp)))
500                                 return FALSE;
501
502                         /* Win NT sets the fDsrSensitivity member based on the
503                            idsr parameter.  Win 9x sets fOutxDsrFlow instead. */
504                         lpdcb->fDsrSensitivity = temp;
505                 }
506                 else
507                         return FALSE;
508
509                 /* After the above parsing, the next character (if not the end of
510                    the string) should be a space */
511                 if(*device && *device != ' ')
512                         return FALSE;
513         }
514
515         /* If stop bits were not specified, a default is always supplied. */
516         if(!stop)
517         {
518                 if(baud && lpdcb->BaudRate == 110)
519                         lpdcb->StopBits = TWOSTOPBITS;
520                 else
521                         lpdcb->StopBits = ONESTOPBIT;
522         }
523
524         return TRUE;
525 }
526
527 /**************************************************************************
528  *         BuildCommDCBA                (KERNEL32.@)
529  *
530  *  Updates a device control block data structure with values from an
531  *  ascii device control string.  The device control string has two forms
532  *  normal and extended, it must be exclusively in one or the other form.
533  *
534  * RETURNS
535  *
536  *  True on success, false on a malformed control string.
537  */
538 BOOL WINAPI BuildCommDCBA(
539     LPCSTR device, /* [in] The ascii device control string used to update the DCB. */
540     LPDCB  lpdcb)  /* [out] The device control block to be updated. */
541 {
542         return BuildCommDCBAndTimeoutsA(device,lpdcb,NULL);
543 }
544
545 /**************************************************************************
546  *         BuildCommDCBAndTimeoutsA     (KERNEL32.@)
547  *
548  *  Updates a device control block data structure with values from an
549  *  ascii device control string.  Taking timeout values from a timeouts
550  *  struct if desired by the control string.
551  *
552  * RETURNS
553  *
554  *  True on success, false bad handles etc
555  */
556 BOOL WINAPI BuildCommDCBAndTimeoutsA(
557     LPCSTR         device,     /* [in] The ascii device control string. */
558     LPDCB          lpdcb,      /* [out] The device control block to be updated. */
559     LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
560 {
561         DCB dcb;
562         COMMTIMEOUTS timeouts;
563         BOOL result;
564         LPCSTR ptr = device;
565         
566         TRACE("(%s,%p,%p)\n",device,lpdcb,lptimeouts);
567
568         /* Set DCBlength. (Windows NT does not do this, but 9x does) */
569         lpdcb->DCBlength = sizeof(DCB);
570
571         /* Make a copy of the original data structures to work with since if
572            if there is an error in the device control string the originals
573            should not be modified (except possibly DCBlength) */
574         memcpy(&dcb, lpdcb, sizeof(DCB));
575         if(lptimeouts) memcpy(&timeouts, lptimeouts, sizeof(COMMTIMEOUTS));
576
577         ptr = COMM_ParseStart(ptr);
578
579         if(ptr == NULL)
580                 result = FALSE;
581         else if(strchr(ptr, ','))
582                 result = COMM_BuildOldCommDCB(ptr, &dcb);
583         else
584                 result = COMM_BuildNewCommDCB(ptr, &dcb, &timeouts);
585
586         if(result)
587         {
588                 memcpy(lpdcb, &dcb, sizeof(DCB));
589                 if(lptimeouts) memcpy(lptimeouts, &timeouts, sizeof(COMMTIMEOUTS));
590                 return TRUE;
591         }
592         else
593         {
594                 WARN("Invalid device control string: %s\n", device);
595                 SetLastError(ERROR_INVALID_PARAMETER);
596                 return FALSE;
597         }       
598 }
599
600 /**************************************************************************
601  *         BuildCommDCBAndTimeoutsW             (KERNEL32.@)
602  *
603  *  Updates a device control block data structure with values from an
604  *  unicode device control string.  Taking timeout values from a timeouts
605  *  struct if desired by the control string.
606  *
607  * RETURNS
608  *
609  *  True on success, false bad handles etc.
610  */
611 BOOL WINAPI BuildCommDCBAndTimeoutsW(
612     LPCWSTR        devid,      /* [in] The unicode device control string. */
613     LPDCB          lpdcb,      /* [out] The device control block to be updated. */
614     LPCOMMTIMEOUTS lptimeouts) /* [in] The COMMTIMEOUTS structure to be updated. */
615 {
616         BOOL ret = FALSE;
617         LPSTR   devidA;
618
619         TRACE("(%p,%p,%p)\n",devid,lpdcb,lptimeouts);
620         devidA = HEAP_strdupWtoA( GetProcessHeap(), 0, devid );
621         if (devidA)
622         {
623         ret=BuildCommDCBAndTimeoutsA(devidA,lpdcb,lptimeouts);
624         HeapFree( GetProcessHeap(), 0, devidA );
625         }
626         return ret;
627 }
628
629 /**************************************************************************
630  *         BuildCommDCBW                (KERNEL32.@)
631  *
632  *  Updates a device control block structure with values from an
633  *  unicode device control string.  The device control string has two forms
634  *  normal and extended, it must be exclusively in one or the other form.
635  *
636  * RETURNS
637  *
638  *  True on success, false on an malformed control string.
639  */
640 BOOL WINAPI BuildCommDCBW(
641     LPCWSTR devid, /* [in] The unicode device control string. */
642     LPDCB   lpdcb) /* [out] The device control block to be updated. */
643 {
644         return BuildCommDCBAndTimeoutsW(devid,lpdcb,NULL);
645 }
646
647 static BOOL COMM_SetCommError(HANDLE handle, DWORD error)
648 {
649     DWORD ret;
650
651     SERVER_START_REQ( set_serial_info )
652     {
653         req->handle = handle;
654         req->flags = SERIALINFO_SET_ERROR;
655         req->commerror = error;
656         ret = !wine_server_call_err( req );
657     }
658     SERVER_END_REQ;
659     return ret;
660 }
661
662 static BOOL COMM_GetCommError(HANDLE handle, LPDWORD lperror)
663 {
664     DWORD ret;
665
666     if(!lperror)
667         return FALSE;
668
669     SERVER_START_REQ( get_serial_info )
670     {
671         req->handle = handle;
672         ret = !wine_server_call_err( req );
673         *lperror = reply->commerror;
674     }
675     SERVER_END_REQ;
676
677     return ret;
678 }
679
680 /*****************************************************************************
681  *      SetCommBreak            (KERNEL32.@)
682  *
683  *  Halts the transmission of characters to a communications device.
684  *
685  * RETURNS
686  *
687  *  True on success, and false if the communications device could not be found,
688  *  the control is not supported.
689  *
690  * BUGS
691  *
692  *  Only TIOCSBRK and TIOCCBRK are supported.
693  */
694 BOOL WINAPI SetCommBreak(
695     HANDLE handle) /* [in] The communictions device to suspend. */
696 {
697 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
698         int fd,result;
699
700         fd = get_comm_fd( handle, GENERIC_READ );
701         if(fd<0) return FALSE;
702         result = ioctl(fd,TIOCSBRK,0);
703         release_comm_fd( handle, fd );
704         if (result ==-1)
705           {
706                 TRACE("ioctl failed\n");
707                 SetLastError(ERROR_NOT_SUPPORTED);
708                 return FALSE;
709           }
710         return TRUE;
711 #else
712         FIXME("ioctl not available\n");
713         SetLastError(ERROR_NOT_SUPPORTED);
714         return FALSE;
715 #endif
716 }
717
718 /*****************************************************************************
719  *      ClearCommBreak          (KERNEL32.@)
720  *
721  *  Resumes character transmission from a communication device.
722  *
723  * RETURNS
724  *
725  *  True on success and false if the communications device could not be found.
726  *
727  * BUGS
728  *
729  *  Only TIOCSBRK and TIOCCBRK are supported.
730  */
731 BOOL WINAPI ClearCommBreak(
732     HANDLE handle) /* [in] The halted communication device whose character transmission is to be resumed. */
733 {
734 #if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
735         int fd,result;
736
737         fd = get_comm_fd( handle, GENERIC_READ );
738         if(fd<0) return FALSE;
739         result = ioctl(fd,TIOCCBRK,0);
740         release_comm_fd( handle, fd );
741         if (result ==-1)
742           {
743                 TRACE("ioctl failed\n");
744                 SetLastError(ERROR_NOT_SUPPORTED);
745                 return FALSE;
746           }
747         return TRUE;
748 #else
749         FIXME("ioctl not available\n");
750         SetLastError(ERROR_NOT_SUPPORTED);
751         return FALSE;
752 #endif
753 }
754
755 /*****************************************************************************
756  *      EscapeCommFunction      (KERNEL32.@)
757  *
758  *  Directs a communication device to perform an extended function.
759  *
760  * RETURNS
761  *
762  *  True or requested data on successful completion of the command,
763  *  false if the device is not present cannot execute the command
764  *  or the command failed.
765  */
766 BOOL WINAPI EscapeCommFunction(
767     HANDLE handle,    /* [in] The communication device to perform the extended function. */
768     UINT   nFunction) /* [in] The extended function to be performed. */
769 {
770         int fd,direct=FALSE,result=FALSE;
771         struct termios  port;
772
773         TRACE("handle %p, function=%d\n", handle, nFunction);
774         fd = get_comm_fd( handle, GENERIC_READ );
775         if(fd<0) return FALSE;
776
777         if (tcgetattr(fd,&port) == -1) {
778                 COMM_SetCommError(handle,CE_IOE);
779                 release_comm_fd( handle, fd );
780                 return FALSE;
781         }
782
783         switch (nFunction) {
784                 case RESETDEV:
785                         TRACE("\n");
786                         break;
787
788                 case CLRDTR:
789                         TRACE("CLRDTR\n");
790 #ifdef TIOCM_DTR
791                         direct=TRUE;
792                         result= COMM_WhackModem(fd, ~TIOCM_DTR, 0);
793                         break;
794 #endif
795
796                 case CLRRTS:
797                         TRACE("CLRRTS\n");
798 #ifdef TIOCM_RTS
799                         direct=TRUE;
800                         result= COMM_WhackModem(fd, ~TIOCM_RTS, 0);
801                         break;
802 #endif
803
804                 case SETDTR:
805                         TRACE("SETDTR\n");
806 #ifdef TIOCM_DTR
807                         direct=TRUE;
808                         result= COMM_WhackModem(fd, 0, TIOCM_DTR);
809                         break;
810 #endif
811
812                 case SETRTS:
813                         TRACE("SETRTS\n");
814 #ifdef TIOCM_RTS
815                         direct=TRUE;
816                         result= COMM_WhackModem(fd, 0, TIOCM_RTS);
817                         break;
818 #endif
819
820                 case SETXOFF:
821                         TRACE("SETXOFF\n");
822                         port.c_iflag |= IXOFF;
823                         break;
824
825                 case SETXON:
826                         TRACE("SETXON\n");
827                         port.c_iflag |= IXON;
828                         break;
829                 case SETBREAK:
830                         TRACE("setbreak\n");
831 #ifdef  TIOCSBRK
832                         direct=TRUE;
833                         result = ioctl(fd,TIOCSBRK,0);
834                         break;
835 #endif
836                 case CLRBREAK:
837                         TRACE("clrbreak\n");
838 #ifdef  TIOCSBRK
839                         direct=TRUE;
840                         result = ioctl(fd,TIOCCBRK,0);
841                         break;
842 #endif
843                 default:
844                         WARN("(handle=%p,nFunction=%d): Unknown function\n",
845                         handle, nFunction);
846                         break;
847         }
848
849         if (!direct)
850           if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
851                 release_comm_fd( handle, fd );
852                 COMM_SetCommError(handle,CE_IOE);
853                 return FALSE;
854           } else
855                 result= TRUE;
856         else
857           {
858             if (result == -1)
859               {
860                 result= FALSE;
861                 COMM_SetCommError(handle,CE_IOE);
862               }
863             else
864               result = TRUE;
865           }
866         release_comm_fd( handle, fd );
867         return result;
868 }
869
870 /********************************************************************
871  *      PurgeComm        (KERNEL32.@)
872  *
873  *  Terminates pending operations and/or discards buffers on a
874  *  communication resource.
875  *
876  * RETURNS
877  *
878  *  True on success and false if the communications handle is bad.
879  */
880 BOOL WINAPI PurgeComm(
881     HANDLE handle, /* [in] The communication resource to be purged. */
882     DWORD  flags)  /* [in] Flags for clear pending/buffer on input/output. */
883 {
884      int fd;
885
886      TRACE("handle %p, flags %lx\n", handle, flags);
887
888      fd = get_comm_fd( handle, GENERIC_READ );
889      if(fd<0) return FALSE;
890
891      /*
892      ** not exactly sure how these are different
893      ** Perhaps if we had our own internal queues, one flushes them
894      ** and the other flushes the kernel's buffers.
895      */
896      if(flags&PURGE_TXABORT)
897          tcflush(fd,TCOFLUSH);
898      if(flags&PURGE_RXABORT)
899          tcflush(fd,TCIFLUSH);
900      if(flags&PURGE_TXCLEAR)
901          tcflush(fd,TCOFLUSH);
902      if(flags&PURGE_RXCLEAR)
903          tcflush(fd,TCIFLUSH);
904      release_comm_fd( handle, fd );
905
906      return 1;
907 }
908
909 /*****************************************************************************
910  *      ClearCommError  (KERNEL32.@)
911  *
912  *  Enables further I/O operations on a communications resource after
913  *  supplying error and current status information.
914  *
915  * RETURNS
916  *
917  *  True on success, false if the communication resource handle is bad.
918  */
919 BOOL WINAPI ClearCommError(
920     HANDLE    handle, /* [in] The communication resource with the error. */
921     LPDWORD   errors, /* [out] Flags indicating error the resource experienced. */
922     LPCOMSTAT lpStat) /* [out] The status of the communication resource. */
923 {
924     int fd;
925
926     fd=get_comm_fd( handle, GENERIC_READ );
927     if(0>fd) return FALSE;
928
929     if (lpStat)
930     {
931         lpStat->fCtsHold = 0;
932         lpStat->fDsrHold = 0;
933         lpStat->fRlsdHold = 0;
934         lpStat->fXoffHold = 0;
935         lpStat->fXoffSent = 0;
936         lpStat->fEof = 0;
937         lpStat->fTxim = 0;
938         lpStat->fReserved = 0;
939
940 #ifdef TIOCOUTQ
941         if(ioctl(fd, TIOCOUTQ, &lpStat->cbOutQue))
942             WARN("ioctl returned error\n");
943 #else
944         lpStat->cbOutQue = 0; /* FIXME: find a different way to find out */
945 #endif
946
947 #ifdef TIOCINQ
948         if(ioctl(fd, TIOCINQ, &lpStat->cbInQue))
949             WARN("ioctl returned error\n");
950 #endif
951
952         TRACE("handle %p cbInQue = %ld cbOutQue = %ld\n",
953               handle, lpStat->cbInQue, lpStat->cbOutQue);
954     }
955
956     release_comm_fd( handle, fd );
957
958     COMM_GetCommError(handle, errors);
959     COMM_SetCommError(handle, 0);
960
961     return TRUE;
962 }
963
964 /*****************************************************************************
965  *      SetupComm       (KERNEL32.@)
966  *
967  *  Called after CreateFile to hint to the communication resource to use
968  *  specified sizes for input and output buffers rather than the default values.
969  *
970  * RETURNS
971  *
972  *  True if successful, false if the communications resource handle is bad.
973  *
974  * BUGS
975  *
976  *  Stub.
977  */
978 BOOL WINAPI SetupComm(
979     HANDLE handle,  /* [in] The just created communication resource handle. */
980     DWORD  insize,  /* [in] The suggested size of the communication resources input buffer in bytes. */
981     DWORD  outsize) /* [in] The suggested size of the communication resources output buffer in bytes. */
982 {
983     int fd;
984
985     FIXME("insize %ld outsize %ld unimplemented stub\n", insize, outsize);
986     fd=get_comm_fd( handle, GENERIC_READ );
987     if(0>fd) return FALSE;
988     release_comm_fd( handle, fd );
989     return TRUE;
990 }
991
992 /*****************************************************************************
993  *      GetCommMask     (KERNEL32.@)
994  *
995  *  Obtain the events associated with a communication device that will cause
996  *  a call WaitCommEvent to return.
997  *
998  *  RETURNS
999  *
1000  *   True on success, fail on bad device handle etc.
1001  */
1002 BOOL WINAPI GetCommMask(
1003     HANDLE  handle,  /* [in] The communications device. */
1004     LPDWORD evtmask) /* [out] The events which cause WaitCommEvent to return. */
1005 {
1006     BOOL ret;
1007
1008     TRACE("handle %p, mask %p\n", handle, evtmask);
1009
1010     SERVER_START_REQ( get_serial_info )
1011     {
1012         req->handle = handle;
1013         if ((ret = !wine_server_call_err( req )))
1014         {
1015             if (evtmask) *evtmask = reply->eventmask;
1016         }
1017     }
1018     SERVER_END_REQ;
1019     return ret;
1020 }
1021
1022 /*****************************************************************************
1023  *      SetCommMask     (KERNEL32.@)
1024  *
1025  *  There be some things we need to hear about yon there communications device.
1026  *  (Set which events associated with a communication device should cause
1027  *  a call WaitCommEvent to return.)
1028  *
1029  * RETURNS
1030  *
1031  *  True on success, false on bad handle etc.
1032  */
1033 BOOL WINAPI SetCommMask(
1034     HANDLE handle,  /* [in] The communications device.  */
1035     DWORD  evtmask) /* [in] The events that are to be monitored. */
1036 {
1037     BOOL ret;
1038
1039     TRACE("handle %p, mask %lx\n", handle, evtmask);
1040
1041     SERVER_START_REQ( set_serial_info )
1042     {
1043         req->handle    = handle;
1044         req->flags     = SERIALINFO_SET_MASK;
1045         req->eventmask = evtmask;
1046         ret = !wine_server_call_err( req );
1047     }
1048     SERVER_END_REQ;
1049     return ret;
1050 }
1051
1052 /*****************************************************************************
1053  *      SetCommState    (KERNEL32.@)
1054  *
1055  *  Re-initializes all hardware and control settings of a communications device,
1056  *  with values from a device control block without effecting the input and output
1057  *  queues.
1058  *
1059  * RETURNS
1060  *
1061  *  True on success, false on failure eg if the XonChar is equal to the XoffChar.
1062  */
1063 BOOL WINAPI SetCommState(
1064     HANDLE handle, /* [in] The communications device. */
1065     LPDCB  lpdcb)  /* [out] The device control block. */
1066 {
1067      struct termios port;
1068      int fd, bytesize, stopbits;
1069
1070      TRACE("handle %p, ptr %p\n", handle, lpdcb);
1071      TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1072            lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1073            (lpdcb->StopBits == ONESTOPBIT)?1:
1074            (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1075      TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1076            (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1077
1078      fd = get_comm_fd( handle, GENERIC_READ );
1079      if (fd < 0) return FALSE;
1080
1081      if ((tcgetattr(fd,&port)) == -1) {
1082          int save_error = errno;
1083          COMM_SetCommError(handle,CE_IOE);
1084          release_comm_fd( handle, fd );
1085          ERR("tcgetattr error '%s'\n", strerror(save_error));
1086          return FALSE;
1087      }
1088
1089         port.c_cc[VMIN] = 0;
1090         port.c_cc[VTIME] = 1;
1091
1092 #ifdef IMAXBEL
1093         port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR|IMAXBEL);
1094 #else
1095         port.c_iflag &= ~(ISTRIP|BRKINT|IGNCR|ICRNL|INLCR);
1096 #endif
1097         port.c_iflag |= (IGNBRK);
1098
1099         port.c_oflag &= ~(OPOST);
1100
1101         port.c_cflag &= ~(HUPCL);
1102         port.c_cflag |= CLOCAL | CREAD;
1103
1104         port.c_lflag &= ~(ICANON|ECHO|ISIG);
1105         port.c_lflag |= NOFLSH;
1106
1107 #ifdef CBAUD
1108         port.c_cflag &= ~CBAUD;
1109         switch (lpdcb->BaudRate) {
1110                 case 110:
1111                 case CBR_110:
1112                         port.c_cflag |= B110;
1113                         break;
1114                 case 300:
1115                 case CBR_300:
1116                         port.c_cflag |= B300;
1117                         break;
1118                 case 600:
1119                 case CBR_600:
1120                         port.c_cflag |= B600;
1121                         break;
1122                 case 1200:
1123                 case CBR_1200:
1124                         port.c_cflag |= B1200;
1125                         break;
1126                 case 2400:
1127                 case CBR_2400:
1128                         port.c_cflag |= B2400;
1129                         break;
1130                 case 4800:
1131                 case CBR_4800:
1132                         port.c_cflag |= B4800;
1133                         break;
1134                 case 9600:
1135                 case CBR_9600:
1136                         port.c_cflag |= B9600;
1137                         break;
1138                 case 19200:
1139                 case CBR_19200:
1140                         port.c_cflag |= B19200;
1141                         break;
1142                 case 38400:
1143                 case CBR_38400:
1144                         port.c_cflag |= B38400;
1145                         break;
1146 #ifdef B57600
1147                 case 57600:
1148                         port.c_cflag |= B57600;
1149                         break;
1150 #endif
1151 #ifdef B115200
1152                 case 115200:
1153                         port.c_cflag |= B115200;
1154                         break;
1155 #endif
1156 #ifdef B230400
1157                 case 230400:
1158                         port.c_cflag |= B230400;
1159                         break;
1160 #endif
1161 #ifdef B460800
1162                 case 460800:
1163                         port.c_cflag |= B460800;
1164                         break;
1165 #endif
1166                 default:
1167 #if defined (HAVE_LINUX_SERIAL_H) && defined (TIOCSSERIAL)
1168                         {   struct serial_struct nuts;
1169                             int arby;
1170                             ioctl(fd, TIOCGSERIAL, &nuts);
1171                             nuts.custom_divisor = nuts.baud_base / lpdcb->BaudRate;
1172                             if (!(nuts.custom_divisor)) nuts.custom_divisor = 1;
1173                             arby = nuts.baud_base / nuts.custom_divisor;
1174                             nuts.flags &= ~ASYNC_SPD_MASK;
1175                             nuts.flags |= ASYNC_SPD_CUST;
1176                             WARN("You (or a program acting at your behest) have specified\n"
1177                                  "a non-standard baud rate %ld.  Wine will set the rate to %d,\n"
1178                                  "which is as close as we can get by our present understanding of your\n"
1179                                  "hardware. I hope you know what you are doing.  Any disruption Wine\n"
1180                                  "has caused to your linux system can be undone with setserial \n"
1181                                  "(see man setserial). If you have incapacitated a Hayes type modem,\n"
1182                                  "reset it and it will probably recover.\n", lpdcb->BaudRate, arby);
1183                             ioctl(fd, TIOCSSERIAL, &nuts);
1184                             port.c_cflag |= B38400;
1185                         }
1186                         break;
1187 #endif    /* Don't have linux/serial.h or lack TIOCSSERIAL */
1188
1189
1190                         COMM_SetCommError(handle,IE_BAUDRATE);
1191                         release_comm_fd( handle, fd );
1192                         ERR("baudrate %ld\n",lpdcb->BaudRate);
1193                         return FALSE;
1194         }
1195 #elif !defined(__EMX__)
1196         switch (lpdcb->BaudRate) {
1197                 case 110:
1198                 case CBR_110:
1199                         port.c_ospeed = B110;
1200                         break;
1201                 case 300:
1202                 case CBR_300:
1203                         port.c_ospeed = B300;
1204                         break;
1205                 case 600:
1206                 case CBR_600:
1207                         port.c_ospeed = B600;
1208                         break;
1209                 case 1200:
1210                 case CBR_1200:
1211                         port.c_ospeed = B1200;
1212                         break;
1213                 case 2400:
1214                 case CBR_2400:
1215                         port.c_ospeed = B2400;
1216                         break;
1217                 case 4800:
1218                 case CBR_4800:
1219                         port.c_ospeed = B4800;
1220                         break;
1221                 case 9600:
1222                 case CBR_9600:
1223                         port.c_ospeed = B9600;
1224                         break;
1225                 case 19200:
1226                 case CBR_19200:
1227                         port.c_ospeed = B19200;
1228                         break;
1229                 case 38400:
1230                 case CBR_38400:
1231                         port.c_ospeed = B38400;
1232                         break;
1233 #ifdef B57600
1234                 case 57600:
1235                 case CBR_57600:
1236                         port.c_cflag |= B57600;
1237                         break;
1238 #endif
1239 #ifdef B115200
1240                 case 115200:
1241                 case CBR_115200:
1242                         port.c_cflag |= B115200;
1243                         break;
1244 #endif
1245 #ifdef B230400
1246                 case 230400:
1247                         port.c_cflag |= B230400;
1248                         break;
1249 #endif
1250 #ifdef B460800
1251                 case 460800:
1252                         port.c_cflag |= B460800;
1253                         break;
1254 #endif
1255                 default:
1256                         COMM_SetCommError(handle,IE_BAUDRATE);
1257                         release_comm_fd( handle, fd );
1258                         ERR("baudrate %ld\n",lpdcb->BaudRate);
1259                         return FALSE;
1260         }
1261         port.c_ispeed = port.c_ospeed;
1262 #endif
1263         bytesize=lpdcb->ByteSize;
1264         stopbits=lpdcb->StopBits;
1265
1266 #ifdef CMSPAR
1267         port.c_cflag &= ~(PARENB | PARODD | CMSPAR);
1268 #else
1269         port.c_cflag &= ~(PARENB | PARODD);
1270 #endif
1271         if (lpdcb->fParity)
1272             port.c_iflag |= INPCK;
1273         else
1274             port.c_iflag &= ~INPCK;
1275         switch (lpdcb->Parity) {
1276                 case NOPARITY:
1277                         break;
1278                 case ODDPARITY:
1279                         port.c_cflag |= (PARENB | PARODD);
1280                         break;
1281                 case EVENPARITY:
1282                         port.c_cflag |= PARENB;
1283                         break;
1284 #ifdef CMSPAR
1285                 /* Linux defines mark/space (stick) parity */
1286                 case MARKPARITY:
1287                         port.c_cflag |= (PARENB | CMSPAR);
1288                         break;
1289                 case SPACEPARITY:
1290                         port.c_cflag |= (PARENB | PARODD |  CMSPAR);
1291                         break;
1292 #else
1293                 /* try the POSIX way */
1294                 case MARKPARITY:
1295                         if( stopbits == ONESTOPBIT) {
1296                             stopbits = TWOSTOPBITS;
1297                             port.c_iflag &= ~INPCK;
1298                         } else {
1299                             COMM_SetCommError(handle,IE_BYTESIZE);
1300                             release_comm_fd( handle, fd );
1301                             ERR("Cannot set MARK Parity\n");
1302                             return FALSE;
1303                         }
1304                         break;
1305                 case SPACEPARITY:
1306                         if( bytesize < 8) {
1307                             bytesize +=1;
1308                             port.c_iflag &= ~INPCK;
1309                         } else {
1310                             COMM_SetCommError(handle,IE_BYTESIZE);
1311                             release_comm_fd( handle, fd );
1312                             ERR("Cannot set SPACE Parity\n");
1313                             return FALSE;
1314                         }
1315                         break;
1316 #endif
1317                default:
1318                         COMM_SetCommError(handle,IE_BYTESIZE);
1319                         release_comm_fd( handle, fd );
1320                         ERR("Parity\n");
1321                         return FALSE;
1322         }
1323
1324
1325         port.c_cflag &= ~CSIZE;
1326         switch (bytesize) {
1327                 case 5:
1328                         port.c_cflag |= CS5;
1329                         break;
1330                 case 6:
1331                         port.c_cflag |= CS6;
1332                         break;
1333                 case 7:
1334                         port.c_cflag |= CS7;
1335                         break;
1336                 case 8:
1337                         port.c_cflag |= CS8;
1338                         break;
1339                 default:
1340                         COMM_SetCommError(handle,IE_BYTESIZE);
1341                         release_comm_fd( handle, fd );
1342                         ERR("ByteSize\n");
1343                         return FALSE;
1344         }
1345
1346         switch (stopbits) {
1347                 case ONESTOPBIT:
1348                                 port.c_cflag &= ~CSTOPB;
1349                                 break;
1350                 case ONE5STOPBITS: /* wil be selected if bytesize is 5 */
1351                 case TWOSTOPBITS:
1352                                 port.c_cflag |= CSTOPB;
1353                                 break;
1354                 default:
1355                         COMM_SetCommError(handle,IE_BYTESIZE);
1356                         release_comm_fd( handle, fd );
1357                         ERR("StopBits\n");
1358                         return FALSE;
1359         }
1360 #ifdef CRTSCTS
1361         if (    lpdcb->fOutxCtsFlow                     ||
1362                 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1363         )
1364           {
1365             port.c_cflag |= CRTSCTS;
1366             TRACE("CRTSCTS\n");
1367           }
1368 #endif
1369
1370         if (lpdcb->fDtrControl == DTR_CONTROL_HANDSHAKE)
1371           {
1372              WARN("DSR/DTR flow control not supported\n");
1373           }
1374
1375         if (lpdcb->fInX)
1376                 port.c_iflag |= IXON;
1377         else
1378                 port.c_iflag &= ~IXON;
1379         if (lpdcb->fOutX)
1380                 port.c_iflag |= IXOFF;
1381         else
1382                 port.c_iflag &= ~IXOFF;
1383
1384         if (tcsetattr(fd,TCSANOW,&port)==-1) { /* otherwise it hangs with pending input*/
1385                 int save_error=errno;
1386                 COMM_SetCommError(handle,CE_IOE);
1387                 release_comm_fd( handle, fd );
1388                 ERR("tcsetattr error '%s'\n", strerror(save_error));
1389                 return FALSE;
1390         } else {
1391                 COMM_SetCommError(handle,0);
1392                 release_comm_fd( handle, fd );
1393                 return TRUE;
1394         }
1395 }
1396
1397
1398 /*****************************************************************************
1399  *      GetCommState    (KERNEL32.@)
1400  *
1401  *  Fills in a device control block with information from a communications device.
1402  *
1403  * RETURNS
1404  *
1405  *  True on success, false if the communication device handle is bad etc
1406  *
1407  * BUGS
1408  *
1409  *  XonChar and XoffChar are not set.
1410  */
1411 BOOL WINAPI GetCommState(
1412     HANDLE handle, /* [in] The communications device. */
1413     LPDCB  lpdcb)  /* [out] The device control block. */
1414 {
1415      struct termios port;
1416      int fd,speed;
1417
1418      TRACE("handle %p, ptr %p\n", handle, lpdcb);
1419
1420      fd = get_comm_fd( handle, GENERIC_READ );
1421      if (fd < 0) return FALSE;
1422      if (tcgetattr(fd, &port) == -1) {
1423                 int save_error=errno;
1424                 ERR("tcgetattr error '%s'\n", strerror(save_error));
1425                 COMM_SetCommError(handle,CE_IOE);
1426                 release_comm_fd( handle, fd );
1427                 return FALSE;
1428         }
1429      release_comm_fd( handle, fd );
1430 #ifndef __EMX__
1431 #ifdef CBAUD
1432      speed= (port.c_cflag & CBAUD);
1433 #else
1434      speed= (cfgetospeed(&port));
1435 #endif
1436      switch (speed) {
1437                 case B110:
1438                         lpdcb->BaudRate = 110;
1439                         break;
1440                 case B300:
1441                         lpdcb->BaudRate = 300;
1442                         break;
1443                 case B600:
1444                         lpdcb->BaudRate = 600;
1445                         break;
1446                 case B1200:
1447                         lpdcb->BaudRate = 1200;
1448                         break;
1449                 case B2400:
1450                         lpdcb->BaudRate = 2400;
1451                         break;
1452                 case B4800:
1453                         lpdcb->BaudRate = 4800;
1454                         break;
1455                 case B9600:
1456                         lpdcb->BaudRate = 9600;
1457                         break;
1458                 case B19200:
1459                         lpdcb->BaudRate = 19200;
1460                         break;
1461                 case B38400:
1462                         lpdcb->BaudRate = 38400;
1463                         break;
1464 #ifdef B57600
1465                 case B57600:
1466                         lpdcb->BaudRate = 57600;
1467                         break;
1468 #endif
1469 #ifdef B115200
1470                 case B115200:
1471                         lpdcb->BaudRate = 115200;
1472                         break;
1473 #endif
1474 #ifdef B230400
1475                 case B230400:
1476                         lpdcb->BaudRate = 230400;
1477                         break;
1478 #endif
1479 #ifdef B460800
1480                 case B460800:
1481                         lpdcb->BaudRate = 460800;
1482                         break;
1483 #endif
1484                 default:
1485                         ERR("unknown speed %x \n",speed);
1486         }
1487 #endif
1488         switch (port.c_cflag & CSIZE) {
1489                 case CS5:
1490                         lpdcb->ByteSize = 5;
1491                         break;
1492                 case CS6:
1493                         lpdcb->ByteSize = 6;
1494                         break;
1495                 case CS7:
1496                         lpdcb->ByteSize = 7;
1497                         break;
1498                 case CS8:
1499                         lpdcb->ByteSize = 8;
1500                         break;
1501                 default:
1502                         ERR("unknown size %x \n",port.c_cflag & CSIZE);
1503         }
1504
1505         if(port.c_iflag & INPCK)
1506             lpdcb->fParity = TRUE;
1507         else
1508             lpdcb->fParity = FALSE;
1509 #ifdef CMSPAR
1510         switch (port.c_cflag & (PARENB | PARODD | CMSPAR))
1511 #else
1512         switch (port.c_cflag & (PARENB | PARODD))
1513 #endif
1514         {
1515                 case 0:
1516                         lpdcb->Parity = NOPARITY;
1517                         break;
1518                 case PARENB:
1519                         lpdcb->Parity = EVENPARITY;
1520                         break;
1521                 case (PARENB | PARODD):
1522                         lpdcb->Parity = ODDPARITY;
1523                         break;
1524 #ifdef CMSPAR
1525                 case (PARENB | CMSPAR):
1526                         lpdcb->Parity = MARKPARITY;
1527                         break;
1528                 case (PARENB | PARODD | CMSPAR):
1529                         lpdcb->Parity = SPACEPARITY;
1530                         break;
1531 #endif
1532         }
1533
1534         if (port.c_cflag & CSTOPB)
1535             if(lpdcb->ByteSize == 5)
1536                 lpdcb->StopBits = ONE5STOPBITS;
1537             else
1538                 lpdcb->StopBits = TWOSTOPBITS;
1539         else
1540             lpdcb->StopBits = ONESTOPBIT;
1541
1542         lpdcb->fNull = 0;
1543         lpdcb->fBinary = 1;
1544
1545         /* termios does not support DTR/DSR flow control */
1546         lpdcb->fOutxDsrFlow = 0;
1547         lpdcb->fDtrControl = DTR_CONTROL_ENABLE;
1548
1549 #ifdef CRTSCTS
1550
1551         if (port.c_cflag & CRTSCTS) {
1552                 lpdcb->fRtsControl = RTS_CONTROL_HANDSHAKE;
1553                 lpdcb->fOutxCtsFlow = 1;
1554         } else
1555 #endif
1556         {
1557                 lpdcb->fRtsControl = RTS_CONTROL_ENABLE;
1558                 lpdcb->fOutxCtsFlow = 0;
1559         }
1560         if (port.c_iflag & IXON)
1561                 lpdcb->fInX = 1;
1562         else
1563                 lpdcb->fInX = 0;
1564
1565         if (port.c_iflag & IXOFF)
1566                 lpdcb->fOutX = 1;
1567         else
1568                 lpdcb->fOutX = 0;
1569 /*
1570         lpdcb->XonChar =
1571         lpdcb->XoffChar =
1572  */
1573         lpdcb->XonLim = 10;
1574         lpdcb->XoffLim = 10;
1575
1576         COMM_SetCommError(handle,0);
1577
1578         TRACE("OK\n");
1579
1580         TRACE("bytesize %d baudrate %ld fParity %d Parity %d stopbits %d\n",
1581               lpdcb->ByteSize,lpdcb->BaudRate,lpdcb->fParity, lpdcb->Parity,
1582               (lpdcb->StopBits == ONESTOPBIT)?1:
1583               (lpdcb->StopBits == TWOSTOPBITS)?2:0);
1584         TRACE("%s %s\n",(lpdcb->fInX)?"IXON":"~IXON",
1585               (lpdcb->fOutX)?"IXOFF":"~IXOFF");
1586 #ifdef CRTSCTS
1587         if (    lpdcb->fOutxCtsFlow                     ||
1588                 lpdcb->fRtsControl == RTS_CONTROL_HANDSHAKE
1589                 )
1590           TRACE("CRTSCTS\n");
1591         else
1592
1593           TRACE("~CRTSCTS\n");
1594
1595 #endif
1596         return TRUE;
1597 }
1598
1599 /*****************************************************************************
1600  *      TransmitCommChar        (KERNEL32.@)
1601  *
1602  *  Transmits a single character in front of any pending characters in the
1603  *  output buffer.  Usually used to send an interrupt character to a host.
1604  *
1605  * RETURNS
1606  *
1607  *  True if the call succeeded, false if the previous command character to the
1608  *  same device has not been sent yet the handle is bad etc.
1609  *
1610  * BUGS
1611  *
1612  *  Stub.
1613  */
1614 BOOL WINAPI TransmitCommChar(
1615     HANDLE hComm,      /* [in] The communication device in need of a command character. */
1616     CHAR   chTransmit) /* [in] The character to transmit. */
1617 {
1618     WARN("(%p,'%c') not perfect!\n",hComm,chTransmit);
1619
1620     return WriteFile( hComm, &chTransmit, 1, NULL, NULL );
1621 }
1622
1623
1624 /*****************************************************************************
1625  *      GetCommTimeouts         (KERNEL32.@)
1626  *
1627  *  Obtains the request timeout values for the communications device.
1628  *
1629  * RETURNS
1630  *
1631  *  True on success, false if communications device handle is bad
1632  *  or the target structure is null.
1633  */
1634 BOOL WINAPI GetCommTimeouts(
1635     HANDLE         hComm,      /* [in] The communications device. */
1636     LPCOMMTIMEOUTS lptimeouts) /* [out] The struct of request timeouts. */
1637 {
1638     BOOL ret;
1639
1640     TRACE("(%p,%p)\n",hComm,lptimeouts);
1641
1642     if(!lptimeouts)
1643     {
1644         SetLastError(ERROR_INVALID_PARAMETER);
1645         return FALSE;
1646     }
1647
1648     SERVER_START_REQ( get_serial_info )
1649     {
1650         req->handle = hComm;
1651         if ((ret = !wine_server_call_err( req )))
1652         {
1653             lptimeouts->ReadIntervalTimeout         = reply->readinterval;
1654             lptimeouts->ReadTotalTimeoutMultiplier  = reply->readmult;
1655             lptimeouts->ReadTotalTimeoutConstant    = reply->readconst;
1656             lptimeouts->WriteTotalTimeoutMultiplier = reply->writemult;
1657             lptimeouts->WriteTotalTimeoutConstant   = reply->writeconst;
1658         }
1659     }
1660     SERVER_END_REQ;
1661     return ret;
1662 }
1663
1664 /*****************************************************************************
1665  *      SetCommTimeouts         (KERNEL32.@)
1666  *
1667  * Sets the timeouts used when reading and writing data to/from COMM ports.
1668  *
1669  * ReadIntervalTimeout
1670  *     - converted and passes to linux kernel as c_cc[VTIME]
1671  * ReadTotalTimeoutMultiplier, ReadTotalTimeoutConstant
1672  *     - used in ReadFile to calculate GetOverlappedResult's timeout
1673  * WriteTotalTimeoutMultiplier, WriteTotalTimeoutConstant
1674  *     - used in WriteFile to calculate GetOverlappedResult's timeout
1675  *
1676  * RETURNS
1677  *
1678  *  True if the timeouts were set, false otherwise.
1679  */
1680 BOOL WINAPI SetCommTimeouts(
1681     HANDLE hComm,              /* [in] handle of COMM device */
1682     LPCOMMTIMEOUTS lptimeouts) /* [in] pointer to COMMTIMEOUTS structure */
1683 {
1684     BOOL ret;
1685     int fd;
1686     struct termios tios;
1687
1688     TRACE("(%p,%p)\n",hComm,lptimeouts);
1689
1690     if(!lptimeouts)
1691     {
1692         SetLastError(ERROR_INVALID_PARAMETER);
1693         return FALSE;
1694     }
1695
1696     SERVER_START_REQ( set_serial_info )
1697     {
1698         req->handle       = hComm;
1699         req->flags        = SERIALINFO_SET_TIMEOUTS;
1700         req->readinterval = lptimeouts->ReadIntervalTimeout ;
1701         req->readmult     = lptimeouts->ReadTotalTimeoutMultiplier ;
1702         req->readconst    = lptimeouts->ReadTotalTimeoutConstant ;
1703         req->writemult    = lptimeouts->WriteTotalTimeoutMultiplier ;
1704         req->writeconst   = lptimeouts->WriteTotalTimeoutConstant ;
1705         ret = !wine_server_call_err( req );
1706     }
1707     SERVER_END_REQ;
1708     if (!ret) return FALSE;
1709
1710     /* FIXME: move this stuff to the server */
1711     fd = get_comm_fd( hComm, GENERIC_READ );
1712     if (fd < 0) return FALSE;
1713
1714     if (-1==tcgetattr(fd,&tios)) {
1715         FIXME("tcgetattr on fd %d failed!\n",fd);
1716         release_comm_fd( hComm, fd );
1717         return FALSE;
1718     }
1719
1720     /* VTIME is in 1/10 seconds */
1721         {
1722                 unsigned int ux_timeout;
1723
1724                 if(lptimeouts->ReadIntervalTimeout == 0) /* 0 means no timeout */
1725                 {
1726                         ux_timeout = 0;
1727                 }
1728                 else
1729                 {
1730                         ux_timeout = (lptimeouts->ReadIntervalTimeout+99)/100;
1731                         if(ux_timeout == 0)
1732                         {
1733                                 ux_timeout = 1; /* must be at least some timeout */
1734                         }
1735                 }
1736                 tios.c_cc[VTIME] = ux_timeout;
1737         }
1738
1739     if (-1==tcsetattr(fd,0,&tios)) {
1740         FIXME("tcsetattr on fd %d failed!\n",fd);
1741         release_comm_fd( hComm, fd );
1742         return FALSE;
1743     }
1744     release_comm_fd( hComm, fd );
1745     return TRUE;
1746 }
1747
1748 /***********************************************************************
1749  *           GetCommModemStatus   (KERNEL32.@)
1750  *
1751  *  Obtains the four control register bits if supported by the hardware.
1752  *
1753  * RETURNS
1754  *
1755  *  True if the communications handle was good and for hardware that
1756  *  control register access, false otherwise.
1757  */
1758 BOOL WINAPI GetCommModemStatus(
1759     HANDLE  hFile,       /* [in] The communications device. */
1760     LPDWORD lpModemStat) /* [out] The control register bits. */
1761 {
1762         int fd,mstat, result=FALSE;
1763
1764         *lpModemStat=0;
1765 #ifdef TIOCMGET
1766         fd = get_comm_fd( hFile, GENERIC_READ );
1767         if(fd<0)
1768                 return FALSE;
1769         result = ioctl(fd, TIOCMGET, &mstat);
1770         release_comm_fd( hFile, fd );
1771         if (result == -1)
1772           {
1773             WARN("ioctl failed\n");
1774             return FALSE;
1775           }
1776 #ifdef TIOCM_CTS
1777         if (mstat & TIOCM_CTS)
1778             *lpModemStat |= MS_CTS_ON;
1779 #endif
1780 #ifdef TIOCM_DSR
1781         if (mstat & TIOCM_DSR)
1782           *lpModemStat |= MS_DSR_ON;
1783 #endif
1784 #ifdef TIOCM_RNG
1785         if (mstat & TIOCM_RNG)
1786           *lpModemStat |= MS_RING_ON;
1787 #endif
1788 #ifdef TIOCM_CAR
1789         /*FIXME:  Not really sure about RLSD  UB 990810*/
1790         if (mstat & TIOCM_CAR)
1791           *lpModemStat |= MS_RLSD_ON;
1792 #endif
1793         TRACE("%04x -> %s%s%s%s\n", mstat,
1794               (*lpModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
1795               (*lpModemStat &MS_RING_ON)?"MS_RING_ON ":"",
1796               (*lpModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
1797               (*lpModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
1798         return TRUE;
1799 #else
1800         return FALSE;
1801 #endif
1802 }
1803
1804 /***********************************************************************
1805  *             COMM_WaitCommEventService      (INTERNAL)
1806  *
1807  *  This function is called while the client is waiting on the
1808  *  server, so we can't make any server calls here.
1809  */
1810 static void COMM_WaitCommEventService(async_private *ovp)
1811 {
1812     async_commio *commio = (async_commio*) ovp;
1813     IO_STATUS_BLOCK* iosb = commio->async.iosb;
1814
1815     TRACE("iosb %p\n",iosb);
1816
1817     /* FIXME: detect other events */
1818     *commio->buffer = EV_RXCHAR;
1819
1820     iosb->u.Status = STATUS_SUCCESS;
1821 }
1822
1823
1824 /***********************************************************************
1825  *             COMM_WaitCommEvent         (INTERNAL)
1826  *
1827  *  This function must have an lpOverlapped.
1828  */
1829 static BOOL COMM_WaitCommEvent(
1830     HANDLE hFile,              /* [in] handle of comm port to wait for */
1831     LPDWORD lpdwEvents,        /* [out] event(s) that were detected */
1832     LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1833 {
1834     int fd;
1835     async_commio *ovp;
1836
1837     if(!lpOverlapped)
1838     {
1839         SetLastError(ERROR_INVALID_PARAMETER);
1840         return FALSE;
1841     }
1842
1843     if(NtResetEvent(lpOverlapped->hEvent,NULL))
1844         return FALSE;
1845
1846     fd = get_comm_fd( hFile, GENERIC_WRITE );
1847     if(fd<0)
1848         return FALSE;
1849
1850     ovp = (async_commio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_commio));
1851     if(!ovp)
1852     {
1853         release_comm_fd( hFile, fd );
1854         return FALSE;
1855     }
1856
1857     ovp->async.ops = &commio_async_ops;
1858     ovp->async.handle = hFile;
1859     ovp->async.fd = fd;  /* FIXME */
1860     ovp->async.type = ASYNC_TYPE_WAIT;
1861     ovp->async.func = COMM_WaitCommEventService;
1862     ovp->async.event = lpOverlapped->hEvent;
1863     ovp->async.iosb = (IO_STATUS_BLOCK*)lpOverlapped;
1864     ovp->buffer = (char *)lpdwEvents;
1865
1866     lpOverlapped->InternalHigh = 0;
1867     lpOverlapped->Offset = 0;
1868     lpOverlapped->OffsetHigh = 0;
1869
1870     if ( !register_new_async (&ovp->async) )
1871         SetLastError( ERROR_IO_PENDING );
1872
1873     return FALSE;
1874 }
1875
1876 /***********************************************************************
1877  *           WaitCommEvent   (KERNEL32.@)
1878  *
1879  * Wait until something interesting happens on a COMM port.
1880  * Interesting things (events) are set by calling SetCommMask before
1881  * this function is called.
1882  *
1883  * RETURNS:
1884  *   TRUE if successful
1885  *   FALSE if failure
1886  *
1887  *   The set of detected events will be written to *lpdwEventMask
1888  *   ERROR_IO_PENDING will be returned the overlapped structure was passed
1889  *
1890  * BUGS:
1891  *  Only supports EV_RXCHAR and EV_TXEMPTY
1892  */
1893 BOOL WINAPI WaitCommEvent(
1894     HANDLE hFile,              /* [in] handle of comm port to wait for */
1895     LPDWORD lpdwEvents,        /* [out] event(s) that were detected */
1896     LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
1897 {
1898     OVERLAPPED ov;
1899     int ret;
1900
1901     TRACE("(%p %p %p )\n",hFile, lpdwEvents,lpOverlapped);
1902
1903     if(lpOverlapped)
1904         return COMM_WaitCommEvent(hFile, lpdwEvents, lpOverlapped);
1905
1906     /* if there is no overlapped structure, create our own */
1907     ov.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
1908
1909     COMM_WaitCommEvent(hFile, lpdwEvents, &ov);
1910
1911     /* wait for the overlapped to complete */
1912     ret = GetOverlappedResult(hFile, &ov, NULL, TRUE);
1913     CloseHandle(ov.hEvent);
1914
1915     return ret;
1916 }
1917
1918 /***********************************************************************
1919  *           GetCommProperties   (KERNEL32.@)
1920  *
1921  * This function fills in a structure with the capabilities of the
1922  * communications port driver.
1923  *
1924  * RETURNS
1925  *
1926  *  TRUE on success, FALSE on failure
1927  *  If successful, the lpCommProp structure be filled in with
1928  *  properties of the comm port.
1929  */
1930 BOOL WINAPI GetCommProperties(
1931     HANDLE hFile,          /* [in] handle of the comm port */
1932     LPCOMMPROP lpCommProp) /* [out] pointer to struct to be filled */
1933 {
1934     FIXME("(%p %p )\n",hFile,lpCommProp);
1935     if(!lpCommProp)
1936         return FALSE;
1937
1938     /*
1939      * These values should be valid for LINUX's serial driver
1940      * FIXME: Perhaps they deserve an #ifdef LINUX
1941      */
1942     memset(lpCommProp,0,sizeof(COMMPROP));
1943     lpCommProp->wPacketLength       = 1;
1944     lpCommProp->wPacketVersion      = 1;
1945     lpCommProp->dwServiceMask       = SP_SERIALCOMM;
1946     lpCommProp->dwReserved1         = 0;
1947     lpCommProp->dwMaxTxQueue        = 4096;
1948     lpCommProp->dwMaxRxQueue        = 4096;
1949     lpCommProp->dwMaxBaud           = BAUD_115200;
1950     lpCommProp->dwProvSubType       = PST_RS232;
1951     lpCommProp->dwProvCapabilities  = PCF_DTRDSR | PCF_PARITY_CHECK | PCF_RTSCTS | PCF_TOTALTIMEOUTS;
1952     lpCommProp->dwSettableParams    = SP_BAUD | SP_DATABITS | SP_HANDSHAKING |
1953                                       SP_PARITY | SP_PARITY_CHECK | SP_STOPBITS ;
1954     lpCommProp->dwSettableBaud      = BAUD_075 | BAUD_110 | BAUD_134_5 | BAUD_150 |
1955                 BAUD_300 | BAUD_600 | BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
1956                 BAUD_9600 | BAUD_19200 | BAUD_38400 | BAUD_57600 | BAUD_115200 ;
1957     lpCommProp->wSettableData       = DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8 ;
1958     lpCommProp->wSettableStopParity = STOPBITS_10 | STOPBITS_15 | STOPBITS_20 |
1959                 PARITY_NONE | PARITY_ODD |PARITY_EVEN | PARITY_MARK | PARITY_SPACE;
1960     lpCommProp->dwCurrentTxQueue    = lpCommProp->dwMaxTxQueue;
1961     lpCommProp->dwCurrentRxQueue    = lpCommProp->dwMaxRxQueue;
1962
1963     return TRUE;
1964 }
1965
1966 /***********************************************************************
1967  * FIXME:
1968  * The functionality of CommConfigDialogA, GetDefaultCommConfig and
1969  * SetDefaultCommConfig is implemented in a DLL (usually SERIALUI.DLL).
1970  * This is dependent on the type of COMM port, but since it is doubtful
1971  * anybody will get around to implementing support for fancy serial
1972  * ports in WINE, this is hardcoded for the time being.  The name of
1973  * this DLL should be stored in and read from the system registry in
1974  * the hive HKEY_LOCAL_MACHINE, key
1975  * System\\CurrentControlSet\\Services\\Class\\Ports\\????
1976  * where ???? is the port number... that is determined by PNP
1977  * The DLL should be loaded when the COMM port is opened, and closed
1978  * when the COMM port is closed. - MJM 20 June 2000
1979  ***********************************************************************/
1980 static CHAR lpszSerialUI[] = "serialui.dll";
1981
1982
1983 /***********************************************************************
1984  *           CommConfigDialogA   (KERNEL32.@)
1985  *
1986  * Raises a dialog that allows the user to configure a comm port.
1987  * Fills the COMMCONFIG struct with information specified by the user.
1988  * This function should call a similar routine in the COMM driver...
1989  *
1990  * RETURNS
1991  *
1992  *  TRUE on success, FALSE on failure
1993  *  If successful, the lpCommConfig structure will contain a new
1994  *  configuration for the comm port, as specified by the user.
1995  *
1996  * BUGS
1997  *  The library with the CommConfigDialog code is never unloaded.
1998  * Perhaps this should be done when the comm port is closed?
1999  */
2000 BOOL WINAPI CommConfigDialogA(
2001     LPCSTR lpszDevice,         /* [in] name of communications device */
2002     HANDLE hWnd,               /* [in] parent window for the dialog */
2003     LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2004 {
2005     FARPROC lpfnCommDialog;
2006     HMODULE hConfigModule;
2007     BOOL r;
2008
2009     TRACE("(%p %p %p)\n",lpszDevice, hWnd, lpCommConfig);
2010
2011     hConfigModule = LoadLibraryA(lpszSerialUI);
2012     if(!hConfigModule)
2013         return FALSE;
2014
2015     lpfnCommDialog = GetProcAddress(hConfigModule, (LPCSTR)3L);
2016
2017     if(!lpfnCommDialog)
2018         return FALSE;
2019
2020     r = lpfnCommDialog(lpszDevice,hWnd,lpCommConfig);
2021
2022     /* UnloadLibrary(hConfigModule); */
2023
2024     return r;
2025 }
2026
2027 /***********************************************************************
2028  *           CommConfigDialogW   (KERNEL32.@)
2029  *
2030  * see CommConfigDialogA for more info
2031  */
2032 BOOL WINAPI CommConfigDialogW(
2033     LPCWSTR lpszDevice,        /* [in] name of communications device */
2034     HANDLE hWnd,               /* [in] parent window for the dialog */
2035     LPCOMMCONFIG lpCommConfig) /* [out] pointer to struct to fill */
2036 {
2037     BOOL r;
2038     LPSTR lpDeviceA;
2039
2040     lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2041     if(lpDeviceA)
2042         return FALSE;
2043     r = CommConfigDialogA(lpDeviceA,hWnd,lpCommConfig);
2044     HeapFree( GetProcessHeap(), 0, lpDeviceA );
2045     return r;
2046 }
2047
2048 /***********************************************************************
2049  *           GetCommConfig     (KERNEL32.@)
2050  *
2051  * Fill in the COMMCONFIG structure for the comm port hFile
2052  *
2053  * RETURNS
2054  *
2055  *  TRUE on success, FALSE on failure
2056  *  If successful, lpCommConfig contains the comm port configuration.
2057  *
2058  * BUGS
2059  *
2060  */
2061 BOOL WINAPI GetCommConfig(
2062     HANDLE       hFile,        /* [in] The communications device. */
2063     LPCOMMCONFIG lpCommConfig, /* [out] The communications configuration of the device (if it fits). */
2064     LPDWORD      lpdwSize)     /* [in/out] Initially the size of the configuration buffer/structure,
2065                                   afterwards the number of bytes copied to the buffer or
2066                                   the needed size of the buffer. */
2067 {
2068     BOOL r;
2069
2070     TRACE("(%p %p)\n",hFile,lpCommConfig);
2071
2072     if(lpCommConfig == NULL)
2073         return FALSE;
2074     r = *lpdwSize < sizeof(COMMCONFIG); /* TRUE if not enough space */
2075     *lpdwSize = sizeof(COMMCONFIG);
2076     if(r)
2077         return FALSE;
2078
2079     lpCommConfig->dwSize = sizeof(COMMCONFIG);
2080     lpCommConfig->wVersion = 1;
2081     lpCommConfig->wReserved = 0;
2082     r = GetCommState(hFile,&lpCommConfig->dcb);
2083     lpCommConfig->dwProviderSubType = PST_RS232;
2084     lpCommConfig->dwProviderOffset = 0;
2085     lpCommConfig->dwProviderSize = 0;
2086
2087     return r;
2088 }
2089
2090 /***********************************************************************
2091  *           SetCommConfig     (KERNEL32.@)
2092  *
2093  *  Sets the configuration of the communications device.
2094  *
2095  * RETURNS
2096  *
2097  *  True on success, false if the handle was bad is not a communications device.
2098  */
2099 BOOL WINAPI SetCommConfig(
2100     HANDLE       hFile,         /* [in] The communications device. */
2101     LPCOMMCONFIG lpCommConfig,  /* [in] The desired configuration. */
2102     DWORD dwSize)               /* [in] size of the lpCommConfig struct */
2103 {
2104     TRACE("(%p %p)\n",hFile,lpCommConfig);
2105     return SetCommState(hFile,&lpCommConfig->dcb);
2106 }
2107
2108 /***********************************************************************
2109  *           SetDefaultCommConfigA   (KERNEL32.@)
2110  *
2111  *  Initializes the default configuration for the specified communication
2112  *  device. (ascii)
2113  *
2114  * RETURNS
2115  *
2116  *  True if the device was found and the defaults set, false otherwise
2117  */
2118 BOOL WINAPI SetDefaultCommConfigA(
2119     LPCSTR       lpszDevice,   /* [in] The ascii name of the device targeted for configuration. */
2120     LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2121     DWORD        dwSize)       /* [in] The number of bytes in the configuration structure. */
2122 {
2123     FARPROC lpfnSetDefaultCommConfig;
2124     HMODULE hConfigModule;
2125     BOOL r;
2126
2127     TRACE("(%p %p %lx)\n",lpszDevice, lpCommConfig, dwSize);
2128
2129     hConfigModule = LoadLibraryA(lpszSerialUI);
2130     if(!hConfigModule)
2131         return FALSE;
2132
2133     lpfnSetDefaultCommConfig = GetProcAddress(hConfigModule, (LPCSTR)4L);
2134
2135     if(! lpfnSetDefaultCommConfig)
2136         return TRUE;
2137
2138     r = lpfnSetDefaultCommConfig(lpszDevice, lpCommConfig, dwSize);
2139
2140     /* UnloadLibrary(hConfigModule); */
2141
2142     return r;
2143 }
2144
2145
2146 /***********************************************************************
2147  *           SetDefaultCommConfigW     (KERNEL32.@)
2148  *
2149  *  Initializes the default configuration for the specified
2150  *  communication device. (unicode)
2151  *
2152  * RETURNS
2153  *
2154  */
2155 BOOL WINAPI SetDefaultCommConfigW(
2156     LPCWSTR      lpszDevice,   /* [in] The unicode name of the device targeted for configuration. */
2157     LPCOMMCONFIG lpCommConfig, /* [in] The default configuration for the device. */
2158     DWORD        dwSize)       /* [in] The number of bytes in the configuration structure. */
2159 {
2160     BOOL r;
2161     LPSTR lpDeviceA;
2162
2163     TRACE("(%s %p %lx)\n",debugstr_w(lpszDevice),lpCommConfig,dwSize);
2164
2165     lpDeviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszDevice );
2166     if(lpDeviceA)
2167         return FALSE;
2168     r = SetDefaultCommConfigA(lpDeviceA,lpCommConfig,dwSize);
2169     HeapFree( GetProcessHeap(), 0, lpDeviceA );
2170     return r;
2171 }
2172
2173
2174 /***********************************************************************
2175  *           GetDefaultCommConfigA   (KERNEL32.@)
2176  *
2177  *   Acquires the default configuration of the specified communication device. (unicode)
2178  *
2179  *  RETURNS
2180  *
2181  *   True on successful reading of the default configuration,
2182  *   if the device is not found or the buffer is too small.
2183  */
2184 BOOL WINAPI GetDefaultCommConfigA(
2185     LPCSTR       lpszName, /* [in] The ascii name of the device targeted for configuration. */
2186     LPCOMMCONFIG lpCC,     /* [out] The default configuration for the device. */
2187     LPDWORD      lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2188                               afterwards the number of bytes copied to the buffer or
2189                               the needed size of the buffer. */
2190 {
2191      LPDCB lpdcb = &(lpCC->dcb);
2192      char  temp[40];
2193
2194      if (strncasecmp(lpszName,"COM",3)) {
2195         ERR("not implemented for <%s>\n", lpszName);
2196         return FALSE;
2197      }
2198
2199      TRACE("(%s %p %ld)\n", lpszName, lpCC, *lpdwSize );
2200      if (*lpdwSize < sizeof(COMMCONFIG)) {
2201          *lpdwSize = sizeof(COMMCONFIG);
2202          return FALSE;
2203        }
2204
2205      *lpdwSize = sizeof(COMMCONFIG);
2206
2207      lpCC->dwSize = sizeof(COMMCONFIG);
2208      lpCC->wVersion = 1;
2209      lpCC->dwProviderSubType = PST_RS232;
2210      lpCC->dwProviderOffset = 0L;
2211      lpCC->dwProviderSize = 0L;
2212
2213      sprintf( temp, "COM%c:38400,n,8,1", lpszName[3]);
2214      FIXME("setting %s as default\n", temp);
2215
2216      return BuildCommDCBA( temp, lpdcb);
2217 }
2218
2219 /**************************************************************************
2220  *         GetDefaultCommConfigW                (KERNEL32.@)
2221  *
2222  *   Acquires the default configuration of the specified communication device. (unicode)
2223  *
2224  *  RETURNS
2225  *
2226  *   True on successful reading of the default configuration,
2227  *   if the device is not found or the buffer is too small.
2228  */
2229 BOOL WINAPI GetDefaultCommConfigW(
2230     LPCWSTR      lpszName, /* [in] The unicode name of the device targeted for configuration. */
2231     LPCOMMCONFIG lpCC,     /* [out] The default configuration for the device. */
2232     LPDWORD      lpdwSize) /* [in/out] Initially the size of the default configuration buffer,
2233                               afterwards the number of bytes copied to the buffer or
2234                               the needed size of the buffer. */
2235 {
2236         BOOL ret = FALSE;
2237         LPSTR   lpszNameA;
2238
2239         TRACE("(%p,%p,%ld)\n",lpszName,lpCC,*lpdwSize);
2240         lpszNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpszName );
2241         if (lpszNameA)
2242         {
2243         ret=GetDefaultCommConfigA(lpszNameA,lpCC,lpdwSize);
2244         HeapFree( GetProcessHeap(), 0, lpszNameA );
2245         }
2246         return ret;
2247 }