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