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