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