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