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