Fix gcc 4.0 -Wpointer-sign warnings.
[wine] / dlls / kernel / tests / comm.c
1 /* Unit test suite for comm functions
2  *
3  * Copyright 2003 Kevin Groeneveld
4  * Copyright 2005 Uwe Bonnes
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
21 #include <stdio.h>
22
23 #include "wine/test.h"
24 #include "winbase.h"
25 #include "winnls.h"
26
27 #define TIMEOUT 1000   /* one second for Timeouts*/
28 #define SLOWBAUD 150
29 #define FASTBAUD 115200
30 #define TIMEDELTA 100  /* 100 ms uncertainty allowed */
31
32 /* Define the appropriate LOOPBACK(s) TRUE if you have a Loopback cable with
33  * the mentioned shorts connected to your Serial port
34  */
35 #define LOOPBACK_TXD_RXD  FALSE /* Sub-D 9: Short 2-3 */
36 #define LOOPBACK_CTS_RTS  FALSE /* Sub-D 9: Short 7-8 */
37 #define LOOPBACK_DTR_DSR  FALSE /* Sub-D 9: Short 4-6 */
38 #define LOOPBACK_DTR_RING FALSE /* Sub-D 9: Short 4-9 */
39 #define LOOPBACK_DTR_DCD  FALSE /* Sub-D 9: Short 4-1 */
40
41 /* SETBREAK seems to give instable results, MSDN mentions possible problems
42  *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcedebug5/\
43  *         html/wce50conSerialPortDriverTest.asp
44  * but perhaps it's only a programming error, that causes it...  */
45 #define BROKEN_SETBREAK TRUE
46
47 typedef struct
48 {
49         char string[100];
50         BOOL result;
51         BOOL old_style;
52         DCB dcb1, dcb2;
53         COMMTIMEOUTS timeouts1, timeouts2;
54 } TEST;
55
56 static TEST test[] =
57 {
58         {
59                 "baud=9600 parity=e data=5 stop=1 xon=on odsr=off octs=off dtr=on rts=on idsr=on",
60                 TRUE, FALSE,
61                 { 0x00000000, 0x00002580, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x05, 0x02, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
62                 { 0xffffffff, 0x00002580, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x05, 0x02, 0x00, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
63                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
64                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
65         },
66         {
67                 "baud=0 parity=M data=6 stop=1.5 xon=off odsr=on octs=ON dtr=off rts=off idsr=OFF",
68                 TRUE, FALSE,
69                 { 0x00000000, 0x00000000, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x06, 0x03, 0x01, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
70                 { 0xffffffff, 0x00000000, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x06, 0x03, 0x01, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
71                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
72                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
73         },
74         {
75                 "BAUD=4000000000 parity=n data=7 stop=2 to=off",
76                 TRUE, FALSE,
77                 { 0x00000000, 0xee6b2800, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x07, 0x00, 0x02, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
78                 { 0xffffffff, 0xee6b2800, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x07, 0x00, 0x02, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
79                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
80                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }
81         },
82         {
83                 "Baud=115200 Parity=O Data=8 To=On",
84                 TRUE, FALSE,
85                 { 0x00000000, 0x0001c200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x08, 0x01, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
86                 { 0xffffffff, 0x0001c200, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x08, 0x01, 0x00, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
87                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000EA60 },
88                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000EA60 }
89         },
90         {
91                 "PaRiTy=s           Data=7          DTR=on",
92                 TRUE, FALSE,
93                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x07, 0x04, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
94                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x07, 0x04, 0x00, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
95                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
96                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
97         },
98         {
99                 "data=4",
100                 FALSE, FALSE,
101                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
102                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
103                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
104                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
105         },
106         {
107                 "data=9",
108                 FALSE, FALSE,
109                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
110                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
111                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
112                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
113         },
114         {
115                 "parity=no",
116                 FALSE, FALSE,
117                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
118                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
119                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
120                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
121         },
122         {
123                 "stop=0",
124                 FALSE, FALSE,
125                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
126                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
127                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
128                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
129         },
130         {
131                 "stop=1.501",
132                 FALSE, FALSE,
133                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
134                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
135                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
136                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
137         },
138         {
139                 "stop=3",
140                 FALSE, FALSE,
141                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
142                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
143                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
144                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
145         },
146         {
147                 "to=foobar",
148                 FALSE, FALSE,
149                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
150                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
151                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
152                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
153         },
154         {
155                 " baud=9600",
156                 FALSE, FALSE,
157                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
158                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
159                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
160                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
161         },
162         {
163                 "baud= 9600",
164                 FALSE, FALSE,
165                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
166                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
167                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
168                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
169         },
170         {
171                 "baud=9600,data=8",
172                 FALSE, FALSE,
173                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
174                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
175                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
176                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
177         },
178         {
179                 "11,n,8,1",
180                 TRUE, TRUE,
181                 { 0x00000000, 0x0000006e, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x08, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
182                 { 0xffffffff, 0x0000006e, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x08, 0x00, 0x00, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
183                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
184                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
185         },
186         {
187                 "30 ,E, 5,1.5",
188                 TRUE, TRUE,
189                 { 0x00000000, 0x0000012c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x05, 0x02, 0x01, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
190                 { 0xffffffff, 0x0000012c, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x05, 0x02, 0x01, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
191                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
192                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
193         },
194         {
195                 "60, m, 6, 2 ",
196                 TRUE, TRUE,
197                 { 0x00000000, 0x00000258, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x06, 0x03, 0x02, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
198                 { 0xffffffff, 0x00000258, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x06, 0x03, 0x02, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
199                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
200                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
201         },
202         {
203                 "12 , o , 7 , 1",
204                 TRUE, TRUE,
205                 { 0x00000000, 0x000004b0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x07, 0x01, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
206                 { 0xffffffff, 0x000004b0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x07, 0x01, 0x00, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
207                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
208                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
209         },
210         {
211                 "24,s,8,1.5",
212                 TRUE, TRUE,
213                 { 0x00000000, 0x00000960, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x08, 0x04, 0x01, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
214                 { 0xffffffff, 0x00000960, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x08, 0x04, 0x01, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
215                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
216                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
217         },
218         {
219                 "48,n,8,1,p",
220                 TRUE, TRUE,
221                 { 0x00000000, 0x000012c0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x08, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
222                 { 0xffffffff, 0x000012c0, 1, 1, 1, 1, 2, 1, 1, 0, 0, 1, 1, 2, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x08, 0x00, 0x00, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
223                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
224                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
225         },
226         {
227                 "96,N,8,1 , x ",
228                 TRUE, TRUE,
229                 { 0x00000000, 0x00002580, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x08, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
230                 { 0xffffffff, 0x00002580, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x08, 0x00, 0x00, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
231                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
232                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
233         },
234         {
235                 "19, e, 7, 1, x",
236                 TRUE, TRUE,
237                 { 0x00000000, 0x00004b00, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x07, 0x02, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
238                 { 0xffffffff, 0x00004b00, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x07, 0x02, 0x00, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
239                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
240                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
241         },
242         {
243                 "0,M,7,1,P",
244                 TRUE, TRUE,
245                 { 0x00000000, 0x00000000, 0, 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x07, 0x03, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
246                 { 0xffffffff, 0x00000000, 1, 1, 1, 1, 2, 1, 1, 0, 0, 1, 1, 2, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x07, 0x03, 0x00, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
247                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
248                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
249         },
250         {
251                 "4000000000,O,7,1.5,X",
252                 TRUE, TRUE,
253                 { 0x00000000, 0xee6b2800, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x07, 0x01, 0x01, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
254                 { 0xffffffff, 0xee6b2800, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x07, 0x01, 0x01, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
255                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
256                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
257         },
258         {
259                 "96,N,8,1 to=on",
260                 FALSE, TRUE,
261                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
262                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
263                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
264                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
265         },
266         {
267                 "96,NO,8,1",
268                 FALSE, TRUE,
269                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
270                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
271                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
272                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
273         },
274         {
275                 "96,N,4,1",
276                 FALSE, TRUE,
277                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
278                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
279                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
280                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
281         },
282         {
283                 "96,N,9,1",
284                 FALSE, TRUE,
285                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
286                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
287                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
288                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
289         },
290         {
291                 "96,N,8,0",
292                 FALSE, TRUE,
293                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
294                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
295                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
296                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
297         },
298         {
299                 "96,N,8,3",
300                 FALSE, TRUE,
301                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
302                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
303                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
304                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
305         },
306         {
307                 "96,N,8,1,K",
308                 FALSE, TRUE,
309                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
310                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
311                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
312                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
313         },
314         {
315                 "COM0:baud=115200",
316                 FALSE, FALSE,
317                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
318                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
319                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
320                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
321         },
322         {
323                 "COMx:baud=38400 data=8",
324                 TRUE, FALSE,
325                 { 0x00000000, 0x00009600, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x08, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
326                 { 0xffffffff, 0x00009600, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x08, 0xff, 0x00, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
327                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
328                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
329         },
330         {
331                 "COMx  :to=on stop=1.5",
332                 TRUE, FALSE,
333                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x01, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
334                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0x01, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
335                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000EA60 },
336                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000EA60 }
337         },
338         {
339                 "COMx:               baud=12345     data=7",
340                 TRUE, FALSE,
341                 { 0x00000000, 0x00003039, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x07, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
342                 { 0xffffffff, 0x00003039, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x07, 0xff, 0x00, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
343                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
344                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
345         },
346         {
347                 "COMx : xon=on odsr=off",
348                 TRUE, FALSE,
349                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
350                 { 0xffffffff, 0xffffffff, 1, 1, 1, 0, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0x00, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
351                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
352                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
353         },
354         {
355                 "COM0:9600,N,8,1",
356                 FALSE, TRUE,
357                 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
358                 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
359                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
360                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
361         },
362         {
363                 "COMx:9600,N,8,1",
364                 TRUE, TRUE,
365                 { 0x00000000, 0x00002580, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x08, 0x00, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
366                 { 0xffffffff, 0x00002580, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x08, 0x00, 0x00, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
367                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
368                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
369         },
370         {
371                 "COMx:  11,E,7,2",
372                 TRUE, TRUE,
373                 { 0x00000000, 0x0000006e, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x07, 0x02, 0x02, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
374                 { 0xffffffff, 0x0000006e, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x07, 0x02, 0x02, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
375                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
376                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
377         },
378         {
379                 "COMx  :19,M,5,1",
380                 TRUE, TRUE,
381                 { 0x00000000, 0x00004b00, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x05, 0x03, 0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
382                 { 0xffffffff, 0x00004b00, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x05, 0x03, 0x00, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
383                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
384                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
385         },
386         {
387                 "COMx  :    57600,S,6,2,x",
388                 TRUE, TRUE,
389                 { 0x00000000, 0x0000e100, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x06, 0x04, 0x02, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 0x0000 },
390                 { 0xffffffff, 0x0000e100, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x06, 0x04, 0x02, (char)0xff, (char)0xff, (char)0xff, (char)0xff, (char)0xff, 0xffff },
391                 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
392                 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
393         },
394 };
395
396 #define TEST_COUNT (sizeof(test) / sizeof(TEST))
397
398 /* This function can be useful if you are modifiying the test cases and want to
399    output the contents of a DCB structure. */
400 /*static print_dcb(DCB *pdcb)
401 {
402         printf("0x%08x, 0x%08x, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, 0x%05x, 0x%04x, 0x%04x, 0x%04x, 0x%02x, 0x%02x, 0x%02x, (char)0x%02x, (char)0x%02x, (char)0x%02x, (char)0x%02x, (char)0x%02x, 0x%04x\n",
403                 pdcb->DCBlength,
404                 pdcb->BaudRate,
405                 pdcb->fBinary,
406                 pdcb->fParity,
407                 pdcb->fOutxCtsFlow,
408                 pdcb->fOutxDsrFlow,
409                 pdcb->fDtrControl,
410                 pdcb->fDsrSensitivity,
411                 pdcb->fTXContinueOnXoff,
412                 pdcb->fOutX,
413                 pdcb->fInX,
414                 pdcb->fErrorChar,
415                 pdcb->fNull,
416                 pdcb->fRtsControl,
417                 pdcb->fAbortOnError,
418                 pdcb->fDummy2,
419                 pdcb->wReserved,
420                 pdcb->XonLim,
421                 pdcb->XoffLim,
422                 pdcb->ByteSize,
423                 pdcb->Parity,
424                 pdcb->StopBits,
425                 pdcb->XonChar & 0xff,
426                 pdcb->XoffChar & 0xff,
427                 pdcb->ErrorChar & 0xff,
428                 pdcb->EofChar & 0xff,
429                 pdcb->EvtChar & 0xff,
430                 pdcb->wReserved1 & 0xffff );
431 } */
432
433 static void check_result(const char *function, TEST *ptest, int initial_value, BOOL result)
434 {
435         DWORD LastError = GetLastError();
436         DWORD CorrectError = (ptest->result ? 0xdeadbeef : ERROR_INVALID_PARAMETER);
437
438         ok(LastError == CorrectError, "%s(\"%s\"), 0x%02x: GetLastError() returned 0x%08lx, should be 0x%08lx\n", function, ptest->string, initial_value, LastError, CorrectError);
439         ok(result == ptest->result, "%s(\"%s\"), 0x%02x: return value should be %s\n", function, ptest->string, initial_value, ptest->result ? "TRUE" : "FALSE");
440 }
441
442 #define check_dcb_member(a,b) ok(pdcb1->a == pdcb2->a, "%s(\"%s\"), 0x%02x: "#a" is "b", should be "b"\n", function, ptest->string, initial_value, pdcb1->a, pdcb2->a)
443 #define check_dcb_member2(a,c,b) if(pdcb2->a == c) { check_dcb_member(a,b); } else { ok(pdcb1->a == pdcb2->a || pdcb1->a == c, "%s(\"%s\"), 0x%02x: "#a" is "b", should be "b" or "b"\n", function, ptest->string, initial_value, pdcb1->a, pdcb2->a, c); }
444
445 static void check_dcb(const char *function, TEST *ptest, int initial_value, DCB *pdcb1, DCB *pdcb2)
446 {
447         /* DCBlength is a special case since Win 9x sets it but NT does not.
448            We will accept either as correct. */
449         check_dcb_member2(DCBlength, (DWORD)sizeof(DCB), "%lu");
450
451         /* For old style control strings Win 9x does not set the next five members, NT does. */
452         if(ptest->old_style && ptest->result)
453         {
454                 check_dcb_member2(fOutxCtsFlow, ((unsigned int)initial_value & 1), "%u");
455                 check_dcb_member2(fDtrControl, ((unsigned int)initial_value & 3), "%u");
456                 check_dcb_member2(fOutX, ((unsigned int)initial_value & 1), "%u");
457                 check_dcb_member2(fInX, ((unsigned)initial_value & 1), "%u");
458                 check_dcb_member2(fRtsControl, ((unsigned)initial_value & 3), "%u");
459         }
460         else
461         {
462                 check_dcb_member(fOutxCtsFlow, "%u");
463                 check_dcb_member(fDtrControl, "%u");
464                 check_dcb_member(fOutX, "%u");
465                 check_dcb_member(fInX, "%u");
466                 check_dcb_member(fRtsControl, "%u");
467         }
468
469         if(ptest->result)
470         {
471                 /* For the idsr=xxx parameter, NT sets fDsrSensitivity, 9x sets
472                    fOutxDsrFlow. */
473                 if(!ptest->old_style)
474                 {
475                         check_dcb_member2(fOutxDsrFlow, pdcb2->fDsrSensitivity, "%u");
476                         check_dcb_member2(fDsrSensitivity, pdcb2->fOutxDsrFlow, "%u");
477                 }
478                 else
479                 {
480                         /* For old style control strings Win 9x does not set the
481                            fOutxDsrFlow member, NT does. */
482                         check_dcb_member2(fOutxDsrFlow, ((unsigned int)initial_value & 1), "%u");
483                         check_dcb_member(fDsrSensitivity, "%u");
484                 }
485         }
486         else
487         {
488                 check_dcb_member(fOutxDsrFlow, "%u");
489                 check_dcb_member(fDsrSensitivity, "%u");
490         }
491
492         /* Check the result of the DCB members. */
493         check_dcb_member(BaudRate, "%lu");
494         check_dcb_member(fBinary, "%u");
495         check_dcb_member(fParity, "%u");
496         check_dcb_member(fTXContinueOnXoff, "%u");
497         check_dcb_member(fErrorChar, "%u");
498         check_dcb_member(fNull, "%u");
499         check_dcb_member(fAbortOnError, "%u");
500         check_dcb_member(fDummy2, "%u");
501         check_dcb_member(wReserved, "%u");
502         check_dcb_member(XonLim, "%u");
503         check_dcb_member(XoffLim, "%u");
504         check_dcb_member(ByteSize, "%u");
505         check_dcb_member(Parity, "%u");
506         check_dcb_member(StopBits, "%u");
507         check_dcb_member(XonChar, "%d");
508         check_dcb_member(XoffChar, "%d");
509         check_dcb_member(ErrorChar, "%d");
510         check_dcb_member(EofChar, "%d");
511         check_dcb_member(EvtChar, "%d");
512         check_dcb_member(wReserved1, "%u");
513 }
514
515 #define check_timeouts_member(a) ok(ptimeouts1->a == ptimeouts2->a, "%s(\"%s\"), 0x%02x: "#a" is %lu, should be %lu\n", function, ptest->string, initial_value, ptimeouts1->a, ptimeouts2->a);
516
517 static void check_timeouts(const char *function, TEST *ptest, int initial_value, COMMTIMEOUTS *ptimeouts1, COMMTIMEOUTS *ptimeouts2)
518 {
519         check_timeouts_member(ReadIntervalTimeout);
520         check_timeouts_member(ReadTotalTimeoutMultiplier);
521         check_timeouts_member(ReadTotalTimeoutConstant);
522         check_timeouts_member(WriteTotalTimeoutMultiplier);
523         check_timeouts_member(WriteTotalTimeoutConstant);
524 }
525
526 static void test_BuildCommDCBA(TEST *ptest, int initial_value, DCB *pexpected_dcb)
527 {
528         BOOL result;
529         DCB dcb;
530
531         /* set initial conditions */
532         memset(&dcb, initial_value, sizeof(DCB));
533         SetLastError(0xdeadbeef);
534
535         result = BuildCommDCBA(ptest->string, &dcb);
536
537         /* check results */
538         check_result("BuildCommDCBA", ptest, initial_value, result);
539         check_dcb("BuildCommDCBA", ptest, initial_value, &dcb, pexpected_dcb);
540 }
541
542 static void test_BuildCommDCBAndTimeoutsA(TEST *ptest, int initial_value, DCB *pexpected_dcb, COMMTIMEOUTS *pexpected_timeouts)
543 {
544         BOOL result;
545         DCB dcb;
546         COMMTIMEOUTS timeouts;
547
548         /* set initial conditions */
549         memset(&dcb, initial_value, sizeof(DCB));
550         memset(&timeouts, initial_value, sizeof(COMMTIMEOUTS));
551         SetLastError(0xdeadbeef);
552
553         result = BuildCommDCBAndTimeoutsA(ptest->string, &dcb, &timeouts);
554
555         /* check results */
556         check_result("BuildCommDCBAndTimeoutsA", ptest, initial_value, result);
557         check_dcb("BuildCommDCBAndTimeoutsA", ptest, initial_value, &dcb, pexpected_dcb);
558         check_timeouts("BuildCommDCBAndTimeoutsA", ptest, initial_value, &timeouts, pexpected_timeouts);
559 }
560
561 static void test_BuildCommDCBW(TEST *ptest, int initial_value, DCB *pexpected_dcb)
562 {
563         BOOL result;
564         DCB dcb;
565         WCHAR wide_string[sizeof(ptest->string)];
566
567         MultiByteToWideChar(CP_ACP, 0, ptest->string, -1, wide_string, sizeof(wide_string) / sizeof(WCHAR));
568
569         /* set initial conditions */
570         memset(&dcb, initial_value, sizeof(DCB));
571         SetLastError(0xdeadbeef);
572
573         result = BuildCommDCBW(wide_string, &dcb);
574
575         if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
576                 return;
577
578         /* check results */
579         check_result("BuildCommDCBW", ptest, initial_value, result);
580         check_dcb("BuildCommDCBW", ptest, initial_value, &dcb, pexpected_dcb);
581 }
582
583 static void test_BuildCommDCBAndTimeoutsW(TEST *ptest, int initial_value, DCB *pexpected_dcb, COMMTIMEOUTS *pexpected_timeouts)
584 {
585         BOOL result;
586         DCB dcb;
587         COMMTIMEOUTS timeouts;
588         WCHAR wide_string[sizeof(ptest->string)];
589
590         MultiByteToWideChar(CP_ACP, 0, ptest->string, -1, wide_string, sizeof(wide_string) / sizeof(WCHAR));
591
592         /* set initial conditions */
593         memset(&dcb, initial_value, sizeof(DCB));
594         memset(&timeouts, initial_value, sizeof(COMMTIMEOUTS));
595         SetLastError(0xdeadbeef);
596
597         result = BuildCommDCBAndTimeoutsW(wide_string, &dcb, &timeouts);
598
599         if(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
600                 return;
601
602         /* check results */
603         check_result("BuildCommDCBAndTimeoutsA", ptest, initial_value, result);
604         check_dcb("BuildCommDCBAndTimeoutsA", ptest, initial_value, &dcb, pexpected_dcb);
605         check_timeouts("BuildCommDCBAndTimeoutsA", ptest, initial_value, &timeouts, pexpected_timeouts);
606 }
607
608 static void test_BuildCommDCB(void)
609 {
610         char port_name[] = "COMx";
611         char port = 0;
612         unsigned int i;
613         char *ptr;
614
615         /* Some of these tests require a valid COM port.  This loop will try to find
616            a valid port. */
617         for(port_name[3] = '1'; port_name[3] <= '9'; port_name[3]++)
618         {
619                 COMMCONFIG commconfig;
620                 DWORD size = sizeof(COMMCONFIG);
621
622                 if(GetDefaultCommConfig(port_name, &commconfig, &size))
623                 {
624                         port = port_name[3];
625                         break;
626                 }
627         }
628
629         if(!port)
630                 trace("Could not find a valid COM port.  Some tests will be skipped.\n");
631
632         for(i = 0; i < TEST_COUNT; i++)
633         {
634                 /* Check if this test case needs a valid COM port. */
635                 ptr = strstr(test[i].string, "COMx");
636
637                 /* If required, substitute valid port number into device control string. */
638                 if(ptr)
639                 {
640                         if(port)
641                                 ptr[3] = port;
642                         else
643                                 continue;
644                 }
645
646                 test_BuildCommDCBA(&test[i], 0x00, &test[i].dcb1);
647                 test_BuildCommDCBA(&test[i], 0xff, &test[i].dcb2);
648                 test_BuildCommDCBAndTimeoutsA(&test[i], 0x00, &test[i].dcb1, &test[i].timeouts1);
649                 test_BuildCommDCBAndTimeoutsA(&test[i], 0xff, &test[i].dcb2, &test[i].timeouts2);
650
651                 test_BuildCommDCBW(&test[i], 0x00, &test[i].dcb1);
652                 test_BuildCommDCBW(&test[i], 0xff, &test[i].dcb2);
653                 test_BuildCommDCBAndTimeoutsW(&test[i], 0x00, &test[i].dcb1, &test[i].timeouts1);
654                 test_BuildCommDCBAndTimeoutsW(&test[i], 0xff, &test[i].dcb2, &test[i].timeouts2);
655         }
656 }
657
658 static HANDLE test_OpenComm(BOOL doOverlap)
659 {
660     HANDLE hcom = INVALID_HANDLE_VALUE;
661     char port_name[] = "COMx";
662     static BOOL shown = FALSE;
663
664     /* Try to find a port */
665     for(port_name[3] = '1'; port_name[3] <= '9'; port_name[3]++)
666     {
667         hcom = CreateFile( port_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
668                            (doOverlap)?FILE_FLAG_OVERLAPPED:0, NULL );
669         if (hcom != INVALID_HANDLE_VALUE)
670             break;
671     }
672     if(!shown)
673     {
674         if (hcom == INVALID_HANDLE_VALUE)
675             trace("Could not find a valid COM port.  Skipping test_ReadTimeOut\n");
676         else
677             trace("Found Com port %s. Connected devices may disturbe results\n", port_name);
678         /*shown = TRUE; */
679     }
680     return hcom;
681 }
682
683 static void test_GetModemStatus(HANDLE hcom)
684 {
685     DWORD ModemStat;
686
687     ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
688     trace("GetCommModemStatus returned 0x%08lx->%s%s%s%s\n", ModemStat,
689           (ModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
690           (ModemStat &MS_RING_ON)?"MS_RING_ON ":"",
691           (ModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
692           (ModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
693 }
694
695 /* When we don't write anything, Read should time out even on a loopbacked port */
696 static void test_ReadTimeOut(HANDLE hcom)
697 {
698     DCB dcb;
699     COMMTIMEOUTS timeouts;
700     char rbuf[32];
701     DWORD before, after, read, timediff, LastError;
702     BOOL res;
703
704     ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
705     dcb.BaudRate = FASTBAUD;
706     dcb.ByteSize = 8;
707     dcb.Parity = NOPARITY;
708     dcb.StopBits = ONESTOPBIT;
709     ok(SetCommState(hcom, &dcb), "SetCommState failed\n");
710
711     ZeroMemory( &timeouts, sizeof(timeouts));
712     timeouts.ReadTotalTimeoutConstant = TIMEOUT;
713     ok(SetCommTimeouts(hcom, &timeouts),"SetCommTimeouts failed\n");
714
715     before = GetTickCount();
716     res = ReadFile(hcom, rbuf, sizeof(rbuf), &read, NULL);
717     LastError = GetLastError();
718     after = GetTickCount();
719     todo_wine ok( res == TRUE, "A timed-out read should return TRUE\n");
720     todo_wine ok( LastError == NO_ERROR, "A timed-out read is not an error\n");
721     timediff = after - before;
722     ok( timediff > TIMEOUT>>2 && timediff < TIMEOUT *2,
723         "Unexpected TimeOut %ld, expected %d\n", timediff, TIMEOUT);
724 }
725
726 static void test_waittxempty(HANDLE hcom)
727 {
728     DCB dcb;
729     COMMTIMEOUTS timeouts;
730     char tbuf[]="Some Characters\n";
731     DWORD before, after, written, timediff, evtmask = 0;
732     BOOL res_write, res;
733     DWORD baud = SLOWBAUD;
734
735     /* set a low baud rate to have ample time*/
736     ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
737     dcb.BaudRate = baud;
738     dcb.ByteSize = 8;
739     dcb.Parity = NOPARITY;
740     dcb.StopBits = ONESTOPBIT;
741     ok(SetCommState(hcom, &dcb), "SetCommState failed\n");
742
743     ZeroMemory( &timeouts, sizeof(timeouts));
744     timeouts.ReadTotalTimeoutConstant = TIMEOUT;
745     ok(SetCommTimeouts(hcom, &timeouts),"SetCommTimeouts failed\n");
746
747     ok(SetupComm(hcom,1024,1024),"SetUpComm failed\n");
748     ok(SetCommMask(hcom, EV_TXEMPTY), "SetCommMask failed\n");
749
750     before = GetTickCount();
751     res_write=WriteFile(hcom, tbuf, sizeof(tbuf), &written, NULL);
752     after = GetTickCount();
753     ok(res_write == TRUE, "WriteFile failed\n");
754     ok(written == sizeof(tbuf),
755        "WriteFile: Unexpected write_size %ld , expected %d\n", written, sizeof(tbuf));
756
757     trace("WriteFile succeeded, took %ld ms to write %d Bytes at %ld Baud\n",
758           after - before, sizeof(tbuf), baud);
759
760     before = GetTickCount();
761     res = WaitCommEvent(hcom, &evtmask, NULL);
762     after = GetTickCount();
763
764     todo_wine ok(res == TRUE, "WaitCommEvent failed\n");
765     todo_wine ok(evtmask == EV_TXEMPTY,
766                  "WaitCommEvent: Unexpected EvtMask 0x%08lx, expected 0x%08x\n",
767                  evtmask, EV_TXEMPTY);
768
769     timediff = after - before;
770
771     trace("WaitCommEvent for EV_TXEMPTY took %ld ms\n", timediff);
772     /* 050604: This shows a difference between XP (tested with mingw compiled crosstest):
773        XP returns Writefile only after everything went out of the Serial port,
774        while wine returns immedate.
775        Thus on XP, WaintCommEvent after setting the CommMask for EV_TXEMPTY
776        nearly return immediate,
777        while on wine the most time is spent here
778     */
779
780 }
781
782 /* A new open handle should not return error or have bytes in the Queues */
783 static void test_ClearCommErrors(HANDLE hcom)
784 {
785     DWORD   errors;
786     COMSTAT lpStat;
787
788     ok(ClearCommError(hcom, &errors, &lpStat), "ClearCommError failed\n");
789     ok(lpStat.cbInQue == 0, "Unexpected %ld Bytes in InQueue\n", lpStat.cbInQue);
790     ok(lpStat.cbOutQue == 0, "Unexpected %ld Bytes in OutQueue\n", lpStat.cbOutQue);
791     ok(errors == 0, "ClearCommErrors: Unexpected error 0x%08lx\n", errors);
792 }
793
794 /**/
795 static void test_LoopbackRead(HANDLE hcom)
796 {
797     DCB dcb;
798     COMMTIMEOUTS timeouts;
799     char rbuf[32];
800     DWORD before, after, diff, read, written, evtmask=0;
801     BOOL res;
802     char tbuf[]="Some Characters\n";
803
804     ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
805     dcb.BaudRate = FASTBAUD;
806     dcb.ByteSize = 8;
807     dcb.Parity = NOPARITY;
808     dcb.StopBits = ONESTOPBIT;
809     ok(SetCommState(hcom, &dcb), "SetCommState failed\n");
810
811     ZeroMemory( &timeouts, sizeof(timeouts));
812     timeouts.ReadTotalTimeoutConstant = TIMEOUT;
813     ok(SetCommTimeouts(hcom, &timeouts),"SetCommTimeouts failed\n");
814
815     ok(SetCommMask(hcom, EV_TXEMPTY), "SetCommMask failed\n");
816
817     ok(WriteFile(hcom,tbuf,sizeof(tbuf),&written, NULL), "WriteFile failed\n");
818     ok(written == sizeof(tbuf),"WriteFile %ld bytes written, expected %d\n",
819        written, sizeof(tbuf));
820
821     /* make sure all bytes are written, so Readfile will succeed in one call*/
822     todo_wine ok(WaitCommEvent(hcom, &evtmask, NULL), "WaitCommEvent failed\n");
823     todo_wine ok(evtmask == EV_TXEMPTY,
824                  "WaitCommEvent: Unexpected EvtMask 0x%08lx, expected 0x%08x\n",
825                  evtmask, EV_TXEMPTY);
826
827     read=0;
828     todo_wine ok(ReadFile(hcom, rbuf, sizeof(rbuf), &read, NULL), "Readfile failed\n");
829     todo_wine ok(read == sizeof(tbuf),"ReadFile read %ld bytes, expected %d\n", read, sizeof(tbuf));
830
831     /* Now do the same withe a slow Baud rate.
832        On XP, nothing should change, as WriteFile only returns
833        after all Bytes have gone to the physical line
834     */
835
836     ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
837     dcb.BaudRate = 9600;
838     dcb.ByteSize = 8;
839     dcb.Parity = NOPARITY;
840     dcb.StopBits = ONESTOPBIT;
841     ok(SetCommState(hcom, &dcb), "SetCommState failed\n");
842
843     ok(SetCommMask(hcom, EV_RXCHAR), "SetCommMask failed\n");
844     ok(WriteFile(hcom,tbuf,sizeof(tbuf),&written, NULL), "WriteFile failed\n");
845     ok(written == sizeof(tbuf),"WriteFile %ld bytes written, expected %d\n",
846        written, sizeof(tbuf));
847
848     todo_wine ok(WaitCommEvent(hcom, &evtmask, NULL), "WaitCommEvent failed\n");
849     todo_wine ok(evtmask == EV_RXCHAR, "WaitCommEvent: Unexpected EvtMask 0x%08lx, expected 0x%08x\n",
850        evtmask, EV_RXCHAR);
851
852     before = GetTickCount();
853     res = ReadFile(hcom, rbuf, sizeof(rbuf), &read, NULL);
854     after = GetTickCount();
855     todo_wine ok(res, "Readfile failed\n");
856     todo_wine ok(read == sizeof(tbuf),"ReadFile read %ld bytes, expected %d\n", read, sizeof(tbuf));
857     diff = after - before;
858     trace("Readfile for %d chars with %d avail took %ld ms\n",
859           sizeof(rbuf), sizeof(tbuf), diff);
860     ok( (diff > TIMEOUT - TIMEDELTA) && (diff < TIMEOUT + TIMEDELTA),
861         "Timedout Wait took %ld ms, expected around %d\n", diff, TIMEOUT);
862 }
863
864 static void test_LoopbackCtsRts(HANDLE hcom)
865 {
866     DWORD ModemStat, defaultStat;
867     DCB dcb;
868
869     ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
870     if (dcb.fRtsControl == RTS_CONTROL_HANDSHAKE)
871     {
872         trace("RTS_CONTROL_HANDSHAKE is set, so don't manipulate RTS\n");
873         return;
874     }
875     ok(GetCommModemStatus(hcom, &defaultStat), "GetCommModemStatus failed\n");
876     /* XP returns some values in the low nibble, so mask them out*/
877     defaultStat &= MS_CTS_ON|MS_DSR_ON|MS_RING_ON|MS_RLSD_ON;
878     if(defaultStat & MS_CTS_ON)
879     {
880         ok(EscapeCommFunction(hcom, CLRRTS), "EscapeCommFunction failed to clear RTS\n");
881         ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
882         ok ((ModemStat & MS_CTS_ON) == 0, "CTS didn't react: 0x%04lx,  expected 0x%04lx\n",
883             ModemStat, (defaultStat & ~MS_CTS_ON));
884         ok(EscapeCommFunction(hcom, SETRTS), "EscapeCommFunction failed to clear RTS\n");
885         ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
886         ok (ModemStat ==  defaultStat, "Failed to restore CTS: 0x%04lx, expected 0x%04lx\n",
887             ModemStat, defaultStat);
888     }
889     else
890     {
891         ok(EscapeCommFunction(hcom, SETRTS), "EscapeCommFunction failed to set RTS\n");
892         ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
893         todo_wine ok ((ModemStat & MS_CTS_ON) == MS_CTS_ON,
894             "CTS didn't react: 0x%04lx,  expected 0x%04lx\n",
895             ModemStat, (defaultStat | MS_CTS_ON));
896         ok(EscapeCommFunction(hcom, CLRRTS), "EscapeCommFunction failed to clear RTS\n");
897         ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
898         ok (ModemStat ==  defaultStat, "Failed to restore CTS: 0x%04lx, expected 0x%04lx\n",
899             ModemStat, defaultStat);
900     }
901 }
902
903 static void test_LoopbackDtrDcd(HANDLE hcom)
904 {
905     DWORD ModemStat, defaultStat;
906     DCB dcb;
907
908     ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
909     if (dcb.fDtrControl == DTR_CONTROL_HANDSHAKE)
910     {
911         trace("DTR_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
912         return;
913     }
914     ok(GetCommModemStatus(hcom, &defaultStat), "GetCommModemStatus failed\n");
915     /* XP returns some values in the low nibble, so mask them out*/
916     defaultStat &= MS_CTS_ON|MS_DSR_ON|MS_RING_ON|MS_RLSD_ON;
917     if(defaultStat & MS_RLSD_ON)
918     {
919         ok(EscapeCommFunction(hcom, CLRDTR), "EscapeCommFunction failed to clear DTR\n");
920         ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
921         ok ((ModemStat & MS_RLSD_ON) == 0, "RLSD didn't react: 0x%04lx,  expected 0x%04lx\n",
922             ModemStat, (defaultStat & ~MS_RLSD_ON));
923         ok(EscapeCommFunction(hcom, SETDTR), "EscapeCommFunction failed to set DTR\n");
924         ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
925         ok (ModemStat ==  defaultStat, "Failed to restore RLSD: 0x%04lx, expected 0x%04lx\n",
926             ModemStat, defaultStat);
927     }
928     else
929     {
930         ok(EscapeCommFunction(hcom, SETDTR), "EscapeCommFunction failed to set DTR\n");
931         ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
932         todo_wine ok ((ModemStat & MS_RLSD_ON) == MS_RLSD_ON,
933             "RLSD didn't react: 0x%04lx,  expected 0x%04lx\n",
934             ModemStat, (defaultStat | MS_RLSD_ON));
935         ok(EscapeCommFunction(hcom, CLRDTR), "EscapeCommFunction failed to clear DTR\n");
936         ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
937         ok (ModemStat ==  defaultStat, "Failed to restore RLSD: 0x%04lx, expected 0x%04lx\n",
938             ModemStat, defaultStat);
939     }
940 }
941
942 static void test_LoopbackDtrDsr(HANDLE hcom)
943 {
944     DWORD ModemStat, defaultStat;
945     DCB dcb;
946
947     ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
948     if (dcb.fDtrControl == DTR_CONTROL_DISABLE)
949     {
950         trace("DTR_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
951         return;
952     }
953     ok(GetCommModemStatus(hcom, &defaultStat), "GetCommModemStatus failed\n");
954     /* XP returns some values in the low nibble, so mask them out*/
955     defaultStat &= MS_CTS_ON|MS_DSR_ON|MS_RING_ON|MS_RLSD_ON;
956     if(defaultStat & MS_DSR_ON)
957     {
958         ok(EscapeCommFunction(hcom, CLRDTR), "EscapeCommFunction failed to clear DTR\n");
959         ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
960         ok ((ModemStat & MS_DSR_ON) == 0, "CTS didn't react: 0x%04lx,  expected 0x%04lx\n",
961             ModemStat, (defaultStat & ~MS_DSR_ON));
962         ok(EscapeCommFunction(hcom, SETDTR), "EscapeCommFunction failed to clear DTR\n");
963         ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
964         todo_wine ok (ModemStat ==  defaultStat, "Failed to restore DSR: 0x%04lx, expected 0x%04lx\n",
965             ModemStat, defaultStat);
966     }
967     else
968     {
969         ok(EscapeCommFunction(hcom, SETDTR), "EscapeCommFunction failed to set DTR\n");
970         ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
971         todo_wine ok ((ModemStat & MS_DSR_ON) == MS_DSR_ON,
972             "CTS didn't react: 0x%04lx,expected 0x%04lx\n",
973             ModemStat, (defaultStat | MS_DSR_ON));
974         ok(EscapeCommFunction(hcom, CLRDTR), "EscapeCommFunction failed to clear DTR\n");
975         ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
976         ok (ModemStat ==  defaultStat, "Failed to restore DSR: 0x%04lx, expected 0x%04lx\n",
977             ModemStat, defaultStat);
978     }
979 }
980
981 static void test_LoopbackDtrRing(HANDLE hcom)
982 {
983     DWORD ModemStat, defaultStat;
984     DCB dcb;
985
986     ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
987     if (dcb.fDtrControl == DTR_CONTROL_HANDSHAKE)
988     {
989         trace("DTR_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
990         return;
991     }
992     ok(GetCommModemStatus(hcom, &defaultStat), "GetCommModemStatus failed\n");
993     /* XP returns some values in the low nibble, so mask them out*/
994     defaultStat &= MS_CTS_ON|MS_DSR_ON|MS_RING_ON|MS_RLSD_ON;
995     if(defaultStat & MS_RING_ON)
996     {
997         ok(EscapeCommFunction(hcom, CLRDTR), "EscapeCommFunction failed to clear DTR\n");
998         ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
999         ok ((ModemStat & MS_RING_ON) == 0, "RING didn't react: 0x%04lx,  expected 0x%04lx\n",
1000             ModemStat, (defaultStat & ~MS_RING_ON));
1001         ok(EscapeCommFunction(hcom, SETDTR), "EscapeCommFunction failed to set DTR\n");
1002         ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1003         ok (ModemStat ==  defaultStat, "Failed to restore RING: 0x%04lx, expected 0x%04lx\n",
1004             ModemStat, defaultStat);
1005     }
1006     else
1007     {
1008         ok(EscapeCommFunction(hcom, SETDTR), "EscapeCommFunction failed to set DTR\n");
1009         ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1010         todo_wine ok ((ModemStat & MS_RING_ON) == MS_RING_ON,
1011             "RING didn't react: 0x%04lx,expected 0x%04lx\n",
1012             ModemStat, (defaultStat | MS_RING_ON));
1013         ok(EscapeCommFunction(hcom, CLRDTR), "EscapeCommFunction failed to clear DTR\n");
1014         ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1015         ok (ModemStat ==  defaultStat, "Failed to restore RING: 0x%04lx, expected 0x%04lx\n",
1016             ModemStat, defaultStat);
1017     }
1018 }
1019
1020 /*
1021   Set up a WaitCommEvent for anything in the receive buffer,
1022   then write to TX to put a character
1023   into the RX buffer via the Loopback
1024 */
1025
1026 static void  test_WaitRx(HANDLE hcom)
1027 {
1028     OVERLAPPED overlapped, overlapped_w;
1029     HANDLE hComPortEvent, hComWriteEvent;
1030     DWORD before, after, after1, diff, success_wait = FALSE, success_write;
1031     DWORD err_wait, err_write, written, evtmask=0;
1032
1033     ok(SetCommMask(hcom, EV_RXCHAR), "SetCommMask failed\n");
1034     hComPortEvent =  CreateEvent( NULL, TRUE, FALSE, NULL );
1035     ok(hComPortEvent != 0, "CreateEvent failed\n");
1036     ZeroMemory( &overlapped, sizeof(overlapped));
1037     overlapped.hEvent = hComPortEvent;
1038
1039     ok((hComWriteEvent =  CreateEvent( NULL, TRUE, FALSE, NULL )) !=0,
1040        "CreateEvent res 0x%08lx\n",
1041        GetLastError());
1042     ZeroMemory( &overlapped_w, sizeof(overlapped_w));
1043     overlapped_w.hEvent = hComWriteEvent;
1044
1045     before = GetTickCount();
1046     todo_wine {success_wait = WaitCommEvent(hcom, &evtmask, &overlapped);}
1047     err_wait = GetLastError();
1048     after = GetTickCount();
1049     trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx\n", success_wait, err_wait, evtmask);
1050     todo_wine ok(success_wait || err_wait == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
1051     trace("overlapped WriteCommEvent returned.\n");
1052
1053     success_write= WriteFile(hcom, "X", 1, &written, &overlapped_w);
1054     err_write = GetLastError();
1055     ok(success_write || err_write == ERROR_IO_PENDING,
1056        "overlapped WriteFile failed, err 0x%08lx\n",
1057        err_write);
1058
1059     if (!success_write && (err_write == ERROR_IO_PENDING)) {
1060       success_write = WaitForSingleObjectEx(hComWriteEvent, TIMEOUT, TRUE);
1061       err_write = GetLastError();
1062       ok(success_write == WAIT_OBJECT_0, "WaitForSingleObjectEx, res 0x%08lx, err 0x%08lx\n",
1063          success_write, err_write);
1064     }
1065     Sleep(TIMEOUT >>1);
1066     success_write = GetOverlappedResult(hcom, &overlapped_w, &written, FALSE);
1067     err_write = GetLastError();
1068
1069     trace("Write after Wait res 0x%08lx err 0x%08lx\n",success_write, err_write);
1070     ok(success_write && written ==1, "Write after Wait res 0x%08lx err 0x%08lx\n",
1071        success_write, err_write);
1072
1073     if (!success_wait && (err_wait == ERROR_IO_PENDING)) {
1074       success_wait = WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE);
1075       err_wait = GetLastError();
1076       ok(success_wait == WAIT_OBJECT_0, "wait hComPortEvent, res 0x%08lx, err 0x%08lx\n",
1077          success_wait, err_wait);
1078     }
1079     success_wait = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
1080     err_wait = GetLastError();
1081     after1 = GetTickCount();
1082     trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx diff1 %ld, diff2 %ld\n",
1083           success_wait, err_wait, evtmask, after-before, after1-before);
1084
1085     todo_wine ok(evtmask & EV_RXCHAR, "Detect  EV_RXCHAR: 0x%08lx, expected 0x%08x\n",
1086        evtmask, EV_RXCHAR);
1087     diff = after1 - before;
1088     ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
1089         "Unexpected time %ld, expected around %d\n", diff, TIMEOUT>>1);
1090
1091 }
1092
1093 /* Change the controling line after the given timeout to the given state
1094    By the loopback, this should trigger the WaitCommEvent
1095 */
1096 static DWORD CALLBACK toggle_ctlLine(LPVOID arg)
1097 {
1098     DWORD *args = (DWORD *) arg;
1099     DWORD timeout = args[0];
1100     DWORD ctl     = args[1];
1101     HANDLE hcom   = (HANDLE) args[2];
1102     HANDLE hComPortEvent = (HANDLE) args[3];
1103     DWORD success, err;
1104
1105     trace("toggle_ctlLine timeout %ld clt 0x%08lx handle 0x%08lx\n",
1106           args[0], args[1], args[2]);
1107     Sleep(timeout);
1108     ok(EscapeCommFunction(hcom, ctl),"EscapeCommFunction 0x%08lx failed\n", ctl);
1109     trace("toggle_ctline done\n");
1110     success = WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE);
1111     err = GetLastError();
1112     trace("toggle_ctline WaitForSingleObjectEx res 0x%08lx err 0x%08lx\n",
1113           success, err);
1114     return 0;
1115 }
1116
1117 static void  test_WaitCts(HANDLE hcom)
1118 {
1119     DCB dcb;
1120     OVERLAPPED overlapped;
1121     HANDLE hComPortEvent;
1122     HANDLE alarmThread;
1123     DWORD args[4], defaultStat;
1124     DWORD alarmThreadId, before, after, after1, diff, success, err, written, evtmask=0;
1125
1126     ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
1127     if (dcb.fDtrControl == RTS_CONTROL_DISABLE)
1128     {
1129         trace("RTS_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
1130         return;
1131     }
1132     args[0]= TIMEOUT >>1;
1133     ok(GetCommModemStatus(hcom, &defaultStat), "GetCommModemStatus failed\n");
1134     if(defaultStat & MS_CTS_ON)
1135         args[1] = CLRRTS;
1136     else
1137         args[1] = SETRTS;
1138     args[2]=(DWORD) hcom;
1139
1140     trace("test_WaitCts timeout %ld clt 0x%08lx handle 0x%08lx\n",args[0], args[1], args[2]);
1141
1142     ok(SetCommMask(hcom, EV_CTS), "SetCommMask failed\n");
1143     hComPortEvent =  CreateEvent( NULL, TRUE, FALSE, NULL );
1144     ok(hComPortEvent != 0, "CreateEvent failed\n");
1145     args[3] = (DWORD) hComPortEvent;
1146     alarmThread = CreateThread(NULL, 0, toggle_ctlLine, (void *) &args, 0, &alarmThreadId);
1147     Sleep(100);
1148     trace("Thread created\n");
1149     ok(alarmThread !=0 , "CreateThread Failed\n");
1150
1151     ZeroMemory( &overlapped, sizeof(overlapped));
1152     overlapped.hEvent = hComPortEvent;
1153     before = GetTickCount();
1154     success = WaitCommEvent(hcom, &evtmask, &overlapped);
1155     err = GetLastError();
1156     after = GetTickCount();
1157
1158     trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx\n", success, err, evtmask);
1159     todo_wine ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
1160     trace("overlapped WriteCommEvent returned.\n");
1161     if (!success && (err == ERROR_IO_PENDING))
1162         todo_wine ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
1163                      "wait hComPortEvent failed\n");
1164     success = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
1165     err = GetLastError();
1166     after1 = GetTickCount();
1167     trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx diff1 %ld, diff2 %ld\n",
1168           success, err, evtmask, after-before, after1-before);
1169
1170     todo_wine ok(evtmask & EV_CTS, "Failed to detect  EV_CTS: 0x%08lx, expected 0x%08x\n",
1171                  evtmask, EV_CTS);
1172     ok(GetCommModemStatus(hcom, &evtmask), "GetCommModemStatus failed\n");
1173     if(defaultStat & MS_CTS_ON)
1174         todo_wine ok((evtmask & MS_CTS_ON) == 0,"CTS didn't change state!\n");
1175     else
1176         todo_wine ok((evtmask & MS_CTS_ON), "CTS didn't change state!\n");
1177
1178     diff = after1 - before;
1179     todo_wine ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
1180                   "Unexpected time %ld, expected around %d\n", diff, TIMEOUT>>1);
1181
1182     /*restore RTS Settings*/
1183     if(defaultStat & MS_CTS_ON)
1184         args[1] = SETRTS;
1185     else
1186         args[1] = CLRRTS;
1187 }
1188
1189 static void  test_WaitDsr(HANDLE hcom)
1190 {
1191     DCB dcb;
1192     OVERLAPPED overlapped;
1193     HANDLE hComPortEvent;
1194     HANDLE alarmThread;
1195     DWORD args[3], defaultStat;
1196     DWORD alarmThreadId, before, after, after1, diff, success, err, written, evtmask=0;
1197
1198     ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
1199     if (dcb.fDtrControl == DTR_CONTROL_DISABLE)
1200     {
1201         trace("DTR_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
1202         return;
1203     }
1204     args[0]= TIMEOUT >>1;
1205     ok(GetCommModemStatus(hcom, &defaultStat), "GetCommModemStatus failed\n");
1206     if(defaultStat & MS_DSR_ON)
1207         args[1] = CLRDTR;
1208     else
1209         args[1] = SETDTR;
1210     args[2]=(DWORD) hcom;
1211
1212     trace("test_WaitDsr timeout %ld clt 0x%08lx handle 0x%08lx\n",args[0], args[1], args[2]);
1213
1214     ok(SetCommMask(hcom, EV_DSR), "SetCommMask failed\n");
1215     hComPortEvent =  CreateEvent( NULL, TRUE, FALSE, NULL );
1216     ok(hComPortEvent != 0, "CreateEvent failed\n");
1217     alarmThread = CreateThread(NULL, 0, toggle_ctlLine, (void *) &args, 0, &alarmThreadId);
1218     ok(alarmThread !=0 , "CreateThread Failed\n");
1219
1220     ZeroMemory( &overlapped, sizeof(overlapped));
1221     overlapped.hEvent = hComPortEvent;
1222     before = GetTickCount();
1223     success = WaitCommEvent(hcom, &evtmask, &overlapped);
1224     err = GetLastError();
1225     after = GetTickCount();
1226
1227     trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx\n", success, err, evtmask);
1228     todo_wine ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
1229     trace("overlapped WriteCommEvent returned.\n");
1230     if (!success && (err == ERROR_IO_PENDING))
1231         todo_wine ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
1232                      "wait hComPortEvent failed\n");
1233     success = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
1234     err = GetLastError();
1235     after1 = GetTickCount();
1236     trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx diff1 %ld, diff2 %ld\n",
1237           success, err, evtmask, after-before, after1-before);
1238
1239     todo_wine ok(evtmask & EV_DSR, "Failed to detect  EV_DSR: 0x%08lx, expected 0x%08x\n",
1240                  evtmask, EV_CTS);
1241     ok(GetCommModemStatus(hcom, &evtmask), "GetCommModemStatus failed\n");
1242     if(defaultStat & MS_DSR_ON)
1243         todo_wine ok((evtmask & MS_DSR_ON) == 0,"DTR didn't change state!\n");
1244     else
1245         todo_wine ok((evtmask & MS_DSR_ON), "DTR didn't change state!\n");
1246
1247     diff = after1 - before;
1248     todo_wine ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
1249                   "Unexpected time %ld, expected around %d\n", diff, TIMEOUT>>1);
1250
1251     /*restore RTS Settings*/
1252     if(defaultStat & MS_DSR_ON)
1253         args[1] = SETDTR;
1254     else
1255         args[1] = CLRDTR;
1256 }
1257
1258 static void  test_WaitRing(HANDLE hcom)
1259 {
1260     DCB dcb;
1261     OVERLAPPED overlapped;
1262     HANDLE hComPortEvent;
1263     HANDLE alarmThread;
1264     DWORD args[3], defaultStat;
1265     DWORD alarmThreadId, before, after, after1, diff, success, err, written, evtmask=0;
1266
1267     ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
1268     if (dcb.fDtrControl == DTR_CONTROL_DISABLE)
1269     {
1270         trace("DTR_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
1271         return;
1272     }
1273     args[0]= TIMEOUT >>1;
1274     ok(GetCommModemStatus(hcom, &defaultStat), "GetCommModemStatus failed\n");
1275     if(defaultStat & MS_RING_ON)
1276         args[1] = CLRDTR;
1277     else
1278         args[1] = SETDTR;
1279     args[2]=(DWORD) hcom;
1280
1281     trace("test_WaitRing timeout %ld clt 0x%08lx handle 0x%08lx\n",args[0], args[1], args[2]);
1282
1283     ok(SetCommMask(hcom, EV_RING), "SetCommMask failed\n");
1284     hComPortEvent =  CreateEvent( NULL, TRUE, FALSE, NULL );
1285     ok(hComPortEvent != 0, "CreateEvent failed\n");
1286     alarmThread = CreateThread(NULL, 0, toggle_ctlLine, (void *) &args, 0, &alarmThreadId);
1287     ok(alarmThread !=0 , "CreateThread Failed\n");
1288
1289     ZeroMemory( &overlapped, sizeof(overlapped));
1290     overlapped.hEvent = hComPortEvent;
1291     before = GetTickCount();
1292     success = WaitCommEvent(hcom, &evtmask, &overlapped);
1293     err = GetLastError();
1294     after = GetTickCount();
1295
1296     trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx\n", success, err, evtmask);
1297     todo_wine ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
1298     trace("overlapped WriteCommEvent returned.\n");
1299     if (!success && (err == ERROR_IO_PENDING))
1300         todo_wine ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
1301                      "wait hComPortEvent failed\n");
1302     success = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
1303     err = GetLastError();
1304     after1 = GetTickCount();
1305     trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx diff1 %ld, diff2 %ld\n",
1306           success, err, evtmask, after-before, after1-before);
1307
1308     todo_wine ok(evtmask & EV_RING, "Failed to detect  EV_RING: 0x%08lx, expected 0x%08x\n",
1309        evtmask, EV_CTS);
1310     ok(GetCommModemStatus(hcom, &evtmask), "GetCommModemStatus failed\n");
1311     if(defaultStat & MS_RING_ON)
1312         todo_wine ok((evtmask & MS_RING_ON) == 0,"DTR didn't change state!\n");
1313     else
1314         todo_wine ok((evtmask & MS_RING_ON), "DTR didn't change state!\n");
1315
1316     diff = after1 - before;
1317     todo_wine ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
1318                   "Unexpected time %ld, expected around %d\n", diff, TIMEOUT>>1);
1319
1320     /*restore RTS Settings*/
1321     if(defaultStat & MS_RING_ON)
1322         args[1] = SETDTR;
1323     else
1324         args[1] = CLRDTR;
1325 }
1326
1327 static void  test_WaitDcd(HANDLE hcom)
1328 {
1329     DCB dcb;
1330     OVERLAPPED overlapped;
1331     HANDLE hComPortEvent;
1332     HANDLE alarmThread;
1333     DWORD args[3], defaultStat;
1334     DWORD alarmThreadId, before, after, after1, diff, success, err, written, evtmask=0;
1335
1336     ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
1337     if (dcb.fDtrControl == DTR_CONTROL_DISABLE)
1338     {
1339         trace("DTR_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
1340         return;
1341     }
1342     args[0]= TIMEOUT >>1;
1343     ok(GetCommModemStatus(hcom, &defaultStat), "GetCommModemStatus failed\n");
1344     if(defaultStat & MS_RLSD_ON)
1345         args[1] = CLRDTR;
1346     else
1347         args[1] = SETDTR;
1348     args[2]=(DWORD) hcom;
1349
1350     trace("test_WaitDcd timeout %ld clt 0x%08lx handle 0x%08lx\n",args[0], args[1], args[2]);
1351
1352     ok(SetCommMask(hcom, EV_RLSD), "SetCommMask failed\n");
1353     hComPortEvent =  CreateEvent( NULL, TRUE, FALSE, NULL );
1354     ok(hComPortEvent != 0, "CreateEvent failed\n");
1355     alarmThread = CreateThread(NULL, 0, toggle_ctlLine, (void *) &args, 0, &alarmThreadId);
1356     ok(alarmThread !=0 , "CreateThread Failed\n");
1357
1358     ZeroMemory( &overlapped, sizeof(overlapped));
1359     overlapped.hEvent = hComPortEvent;
1360     before = GetTickCount();
1361     success = WaitCommEvent(hcom, &evtmask, &overlapped);
1362     err = GetLastError();
1363     after = GetTickCount();
1364
1365     trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx\n", success, err, evtmask);
1366     todo_wine ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
1367     trace("overlapped WriteCommEvent returned.\n");
1368     if (!success && (err == ERROR_IO_PENDING))
1369         todo_wine ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
1370                      "wait hComPortEvent failed\n");
1371     success = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
1372     err = GetLastError();
1373     after1 = GetTickCount();
1374     trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx diff1 %ld, diff2 %ld\n",
1375           success, err, evtmask, after-before, after1-before);
1376
1377     todo_wine ok(evtmask & EV_RLSD, "Failed to detect  EV_RLSD: 0x%08lx, expected 0x%08x\n",
1378                  evtmask, EV_CTS);
1379     ok(GetCommModemStatus(hcom, &evtmask), "GetCommModemStatus failed\n");
1380     if(defaultStat & MS_RLSD_ON)
1381         todo_wine ok((evtmask & MS_RLSD_ON) == 0,"DTR didn't change state!\n");
1382     else
1383         todo_wine ok((evtmask & MS_RLSD_ON), "DTR didn't change state!\n");
1384
1385     diff = after1 - before;
1386     todo_wine ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
1387                   "Unexpected time %ld, expected around %d\n", diff, TIMEOUT>>1);
1388
1389     /*restore RTS Settings*/
1390     if(defaultStat & MS_RLSD_ON)
1391         args[1] = SETDTR;
1392     else
1393         args[1] = CLRDTR;
1394 }
1395
1396 /*
1397    Set the Break status after the given timeout to the given state
1398 */
1399 static void  test_WaitBreak(HANDLE hcom)
1400 {
1401     OVERLAPPED overlapped;
1402     HANDLE hComPortEvent;
1403     DWORD before, after, after1, diff, success, err, written, evtmask=0;
1404
1405     ok(SetCommMask(hcom, EV_BREAK), "SetCommMask failed\n");
1406     hComPortEvent =  CreateEvent( NULL, TRUE, FALSE, NULL );
1407     ok(hComPortEvent != 0, "CreateEvent failed\n");
1408
1409     ZeroMemory( &overlapped, sizeof(overlapped));
1410     overlapped.hEvent = hComPortEvent;
1411     before = GetTickCount();
1412     success = WaitCommEvent(hcom, &evtmask, &overlapped);
1413     err = GetLastError();
1414     after = GetTickCount();
1415
1416     trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx\n", success, err, evtmask);
1417     ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
1418     trace("overlapped WriteCommEvent returned.\n");
1419
1420     Sleep(TIMEOUT >>1);
1421
1422     ok(SetCommBreak(hcom), "SetCommBreak err 0x%08lx\n", GetLastError());
1423     trace("Break set\n");
1424     ok(ClearCommError(hcom, &err, NULL),"ClearCommError err 0x%08lx\n", GetLastError());
1425     ok((err & CE_BREAK)!= 0, "Break condition should be reported\n");
1426     ok(ClearCommBreak(hcom), "ClearCommBreak err 0x%08lx\n", GetLastError());
1427     trace("Break cleared\n");
1428     ok(ClearCommError(hcom, &err, NULL),"ClearCommError err 0x%08lx\n", GetLastError());
1429     ok((err & CE_BREAK)== 0, "Break should be cleared now\n");
1430
1431     if (!success && (err == ERROR_IO_PENDING))
1432         ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
1433            "wait hComPortEvent res 0x%08lx\n", GetLastError());
1434     success = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
1435     err = GetLastError();
1436     after1 = GetTickCount();
1437     trace("Success 0x%08lx err 0x%08lx evtmask 0x%08lx diff1 %ld, diff2 %ld\n",
1438           success, err, evtmask, after-before, after1-before);
1439
1440     ok(evtmask & EV_BREAK, "Failed to detect  EV_BREAK: 0x%08lx, expected 0x%08x\n",
1441        evtmask, EV_BREAK);
1442     ok(GetCommModemStatus(hcom, &evtmask), "GetCommModemStatus failed\n");
1443
1444     diff = after1 - before;
1445     ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
1446         "Unexpected time %ld, expected around %d\n", diff, TIMEOUT>>1);
1447
1448 }
1449
1450 START_TEST(comm)
1451 {
1452     HANDLE hcom;
1453     /* use variabel and not #define to compile the code */
1454     BOOL loopback_txd_rxd  = LOOPBACK_TXD_RXD;
1455     BOOL loopback_rts_cts  = LOOPBACK_CTS_RTS;
1456     BOOL loopback_dtr_dsr  = LOOPBACK_DTR_DSR;
1457     BOOL loopback_dtr_ring = LOOPBACK_DTR_RING;
1458     BOOL loopback_dtr_dcd  = LOOPBACK_DTR_DCD;
1459     BOOL broken_setbreak = BROKEN_SETBREAK;
1460
1461 #if 1
1462     test_BuildCommDCB();
1463     hcom = test_OpenComm(FALSE);
1464     if (hcom != INVALID_HANDLE_VALUE)
1465     {
1466         test_GetModemStatus(hcom);
1467         test_ReadTimeOut(hcom);
1468         test_waittxempty(hcom);
1469         CloseHandle(hcom);
1470     }
1471     hcom = test_OpenComm(FALSE);
1472     if (hcom != INVALID_HANDLE_VALUE)
1473     {
1474         test_ClearCommErrors(hcom);
1475         CloseHandle(hcom);
1476     }
1477     if((loopback_txd_rxd) && ((hcom = test_OpenComm(FALSE))!=INVALID_HANDLE_VALUE))
1478     {
1479         test_LoopbackRead(hcom);
1480         CloseHandle(hcom);
1481     }
1482     if((loopback_rts_cts) && ((hcom = test_OpenComm(FALSE))!=INVALID_HANDLE_VALUE))
1483     {
1484         test_LoopbackCtsRts(hcom);
1485         CloseHandle(hcom);
1486     }
1487     if((loopback_dtr_dsr) && ((hcom = test_OpenComm(FALSE))!=INVALID_HANDLE_VALUE))
1488     {
1489         test_LoopbackDtrDsr(hcom);
1490         CloseHandle(hcom);
1491     }
1492     if((loopback_dtr_ring) && ((hcom = test_OpenComm(FALSE))!=INVALID_HANDLE_VALUE))
1493     {
1494         test_LoopbackDtrRing(hcom);
1495         CloseHandle(hcom);
1496     }
1497     if((loopback_dtr_dcd) && ((hcom = test_OpenComm(FALSE))!=INVALID_HANDLE_VALUE))
1498     {
1499         test_LoopbackDtrDcd(hcom);
1500         CloseHandle(hcom);
1501     }
1502 #endif
1503     if((loopback_txd_rxd) && ((hcom = test_OpenComm(TRUE))!=INVALID_HANDLE_VALUE))
1504     {
1505         test_WaitRx(hcom);
1506         CloseHandle(hcom);
1507     }
1508 #if 1
1509     if((loopback_rts_cts) && ((hcom = test_OpenComm(TRUE))!=INVALID_HANDLE_VALUE))
1510     {
1511         test_WaitCts(hcom);
1512         CloseHandle(hcom);
1513     }
1514     if((loopback_dtr_dsr) && ((hcom = test_OpenComm(TRUE))!=INVALID_HANDLE_VALUE))
1515     {
1516         test_WaitDsr(hcom);
1517         CloseHandle(hcom);
1518     }
1519     if((loopback_dtr_ring) && ((hcom = test_OpenComm(TRUE))!=INVALID_HANDLE_VALUE))
1520     {
1521         test_WaitRing(hcom);
1522         CloseHandle(hcom);
1523     }
1524     if((loopback_dtr_dcd) && ((hcom = test_OpenComm(TRUE))!=INVALID_HANDLE_VALUE))
1525     {
1526         test_WaitDcd(hcom);
1527         CloseHandle(hcom);
1528     }
1529     if(!broken_setbreak && (hcom = test_OpenComm(TRUE))!=INVALID_HANDLE_VALUE)
1530     {
1531         test_WaitBreak(hcom);
1532         CloseHandle(hcom);
1533     }
1534 #endif
1535 }