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