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