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