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