ReactOS 0.4.15-dev-8413-gc1c91f2
comm.c
Go to the documentation of this file.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include <stdio.h>
22
23#include "ntstatus.h"
24#define WIN32_NO_STATUS
25#include "wine/test.h"
26#include "winternl.h"
27#include "winbase.h"
28#include "winnls.h"
29
30#define TIMEOUT 1000 /* one second for Timeouts*/
31#define SLOWBAUD 150
32#define FASTBAUD 115200
33#define TIMEDELTA 150 /* 150 ms uncertainty allowed */
34
35/* Define the appropriate LOOPBACK(s) TRUE if you have a Loopback cable with
36 * the mentioned shorts connected to your Serial port
37 */
38#define LOOPBACK_TXD_RXD FALSE /* Sub-D 9: Short 2-3 */
39#define LOOPBACK_CTS_RTS FALSE /* Sub-D 9: Short 7-8 */
40#define LOOPBACK_DTR_DSR FALSE /* Sub-D 9: Short 4-6 */
41#define LOOPBACK_DTR_RING FALSE /* Sub-D 9: Short 4-9 */
42#define LOOPBACK_DTR_DCD FALSE /* Sub-D 9: Short 4-1 */
43/* Many Linux serial drivers have the TIOCM_LOOP flag in the TIOCM_SET ioctl
44 * available. For the 8250 this is equivalent to TXD->RXD, OUT2->DCD,
45 * OUT1->RI, RTS->CTS and DTR->DSR
46 */
47/* use variables and not #define to compile the code */
53
54static NTSTATUS (WINAPI *pNtReadFile)(HANDLE hFile, HANDLE hEvent,
58static NTSTATUS (WINAPI *pNtWriteFile)(HANDLE hFile, HANDLE hEvent,
61 const void* buffer, ULONG length,
63
64typedef struct
65{
66 char string[100];
69 DCB dcb1, dcb2;
71} TEST;
72
73static const TEST test[] =
74{
75 {
76 "baud=9600 parity=e data=5 stop=1 xon=on odsr=off octs=off dtr=on rts=on idsr=on",
77 TRUE, FALSE,
78 { 0x00000000, 0x00002580, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
79 { 0xffffffff, 0x00002580, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x05, 0x02, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
80 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
81 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
82 },
83 {
84 "baud=0 parity=M data=6 stop=1.5 xon=off odsr=on octs=ON dtr=off rts=off idsr=OFF",
85 TRUE, FALSE,
86 { 0x00000000, 0x00000000, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x06, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
87 { 0xffffffff, 0x00000000, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x06, 0x03, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
88 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
89 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
90 },
91 {
92 "BAUD=4000000000 parity=n data=7 stop=2 to=off",
93 TRUE, FALSE,
94 { 0x00000000, 0xee6b2800, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
95 { 0xffffffff, 0xee6b2800, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x07, 0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
96 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
97 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }
98 },
99 {
100 "Baud=115200 Parity=O Data=8 To=On",
101 TRUE, FALSE,
102 { 0x00000000, 0x0001c200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
103 { 0xffffffff, 0x0001c200, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x08, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
104 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000EA60 },
105 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000EA60 }
106 },
107 {
108 "PaRiTy=s Data=7 DTR=on",
109 TRUE, FALSE,
110 { 0x00000000, 0x00000000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
111 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x07, 0x04, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
112 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
113 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
114 },
115 {
116 "data=4",
117 FALSE, FALSE,
118 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
119 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
120 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
121 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
122 },
123 {
124 "data=9",
125 FALSE, FALSE,
126 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
127 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
128 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
129 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
130 },
131 {
132 "parity=no",
133 FALSE, FALSE,
134 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
135 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
136 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
137 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
138 },
139 {
140 "stop=0",
141 FALSE, FALSE,
142 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
143 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
144 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
145 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
146 },
147 {
148 "stop=1.501",
149 FALSE, FALSE,
150 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
151 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
152 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
153 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
154 },
155 {
156 "stop=3",
157 FALSE, FALSE,
158 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
159 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
160 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
161 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
162 },
163 {
164 "to=foobar",
165 FALSE, FALSE,
166 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
167 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
168 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
169 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
170 },
171 {
172 " baud=9600",
173 FALSE, FALSE,
174 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
175 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
176 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
177 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
178 },
179 {
180 "baud= 9600",
181 FALSE, FALSE,
182 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
183 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
184 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
185 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
186 },
187 {
188 "baud=9600,data=8",
189 FALSE, FALSE,
190 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
191 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
192 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
193 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
194 },
195 {
196 "11,n,8,1",
197 TRUE, TRUE,
198 { 0x00000000, 0x0000006e, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
199 { 0xffffffff, 0x0000006e, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
200 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
201 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
202 },
203 {
204 "30 ,E, 5,1.5",
205 TRUE, TRUE,
206 { 0x00000000, 0x0000012c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x05, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
207 { 0xffffffff, 0x0000012c, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x05, 0x02, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
208 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
209 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
210 },
211 {
212 "60, m, 6, 2 ",
213 TRUE, TRUE,
214 { 0x00000000, 0x00000258, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x06, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
215 { 0xffffffff, 0x00000258, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x06, 0x03, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
216 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
217 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
218 },
219 {
220 "12 , o , 7 , 1",
221 TRUE, TRUE,
222 { 0x00000000, 0x000004b0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
223 { 0xffffffff, 0x000004b0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x07, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
224 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
225 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
226 },
227 {
228 "24,s,8,1.5",
229 TRUE, TRUE,
230 { 0x00000000, 0x00000960, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x08, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
231 { 0xffffffff, 0x00000960, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x08, 0x04, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
232 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
233 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
234 },
235 {
236 "48,n,8,1,p",
237 TRUE, TRUE,
238 { 0x00000000, 0x000012c0, 0, 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
239 { 0xffffffff, 0x000012c0, 1, 1, 1, 1, 2, 1, 1, 0, 0, 1, 1, 2, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
240 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
241 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
242 },
243 {
244 "96,N,8,1 , x ",
245 TRUE, TRUE,
246 { 0x00000000, 0x00002580, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
247 { 0xffffffff, 0x00002580, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
248 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
249 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
250 },
251 {
252 "19, e, 7, 1, x",
253 TRUE, TRUE,
254 { 0x00000000, 0x00004b00, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x07, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
255 { 0xffffffff, 0x00004b00, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x07, 0x02, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
256 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
257 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
258 },
259 {
260 "0,M,7,1,P",
261 TRUE, TRUE,
262 { 0x00000000, 0x00000000, 0, 0, 1, 1, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
263 { 0xffffffff, 0x00000000, 1, 1, 1, 1, 2, 1, 1, 0, 0, 1, 1, 2, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x07, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
264 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
265 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
266 },
267 {
268 "4000000000,O,7,1.5,X",
269 TRUE, TRUE,
270 { 0x00000000, 0xee6b2800, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x07, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
271 { 0xffffffff, 0xee6b2800, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x07, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
272 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
273 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
274 },
275 {
276 "96,N,8,1 to=on",
277 FALSE, TRUE,
278 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
279 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
280 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
281 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
282 },
283 {
284 "96,NO,8,1",
285 FALSE, TRUE,
286 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
287 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
288 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
289 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
290 },
291 {
292 "96,N,4,1",
293 FALSE, TRUE,
294 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
295 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
296 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
297 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
298 },
299 {
300 "96,N,9,1",
301 FALSE, TRUE,
302 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
303 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
304 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
305 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
306 },
307 {
308 "96,N,8,0",
309 FALSE, TRUE,
310 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
311 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
312 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
313 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
314 },
315 {
316 "96,N,8,3",
317 FALSE, TRUE,
318 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
319 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
320 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
321 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
322 },
323 {
324 "96,N,8,1,K",
325 FALSE, TRUE,
326 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
327 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
328 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
329 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
330 },
331 {
332 "COM0:baud=115200",
333 FALSE, FALSE,
334 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
335 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
336 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
337 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
338 },
339 {
340 "COMx:baud=38400 data=8",
341 TRUE, FALSE,
342 { 0x00000000, 0x00009600, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
343 { 0xffffffff, 0x00009600, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x08, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
344 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
345 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
346 },
347 {
348 "COMx :to=on stop=1.5",
349 TRUE, FALSE,
350 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
351 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
352 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000EA60 },
353 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000EA60 }
354 },
355 {
356 "COMx: baud=12345 data=7",
357 TRUE, FALSE,
358 { 0x00000000, 0x00003039, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
359 { 0xffffffff, 0x00003039, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x07, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
360 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
361 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
362 },
363 {
364 "COMx : xon=on odsr=off",
365 TRUE, FALSE,
366 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
367 { 0xffffffff, 0xffffffff, 1, 1, 1, 0, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
368 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
369 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
370 },
371 {
372 "COM0:9600,N,8,1",
373 FALSE, TRUE,
374 { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
375 { 0xffffffff, 0xffffffff, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
376 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
377 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
378 },
379 {
380 "COMx:9600,N,8,1",
381 TRUE, TRUE,
382 { 0x00000000, 0x00002580, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
383 { 0xffffffff, 0x00002580, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
384 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
385 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
386 },
387 {
388 "COMx: 11,E,7,2",
389 TRUE, TRUE,
390 { 0x00000000, 0x0000006e, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x07, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
391 { 0xffffffff, 0x0000006e, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x07, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
392 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
393 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
394 },
395 {
396 "COMx :19,M,5,1",
397 TRUE, TRUE,
398 { 0x00000000, 0x00004b00, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x05, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
399 { 0xffffffff, 0x00004b00, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x05, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
400 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
401 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
402 },
403 {
404 "COMx : 57600,S,6,2,x",
405 TRUE, TRUE,
406 { 0x00000000, 0x0000e100, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0x00000, 0x0000, 0x0000, 0x0000, 0x06, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0000 },
407 { 0xffffffff, 0x0000e100, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0x1ffff, 0xffff, 0xffff, 0xffff, 0x06, 0x04, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xffff },
408 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
409 { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
410 },
411};
412
413#define TEST_COUNT (sizeof(test) / sizeof(TEST))
414
415/* This function can be useful if you are modifying the test cases and want to
416 output the contents of a DCB structure. */
417/*static print_dcb(DCB *pdcb)
418{
419 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, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%04x\n",
420 pdcb->DCBlength,
421 pdcb->BaudRate,
422 pdcb->fBinary,
423 pdcb->fParity,
424 pdcb->fOutxCtsFlow,
425 pdcb->fOutxDsrFlow,
426 pdcb->fDtrControl,
427 pdcb->fDsrSensitivity,
428 pdcb->fTXContinueOnXoff,
429 pdcb->fOutX,
430 pdcb->fInX,
431 pdcb->fErrorChar,
432 pdcb->fNull,
433 pdcb->fRtsControl,
434 pdcb->fAbortOnError,
435 pdcb->fDummy2,
436 pdcb->wReserved,
437 pdcb->XonLim,
438 pdcb->XoffLim,
439 pdcb->ByteSize,
440 pdcb->Parity,
441 pdcb->StopBits,
442 pdcb->XonChar & 0xff,
443 pdcb->XoffChar & 0xff,
444 pdcb->ErrorChar & 0xff,
445 pdcb->EofChar & 0xff,
446 pdcb->EvtChar & 0xff,
447 pdcb->wReserved1 & 0xffff );
448} */
449
450static void check_result(const char *function, const TEST *ptest, int initial_value, BOOL result)
451{
452 DWORD LastError = GetLastError();
453 DWORD CorrectError = (ptest->result ? 0xdeadbeef : ERROR_INVALID_PARAMETER);
454
455 ok(LastError == CorrectError, "%s(\"%s\"), 0x%02x: GetLastError() returned %d, should be %d\n", function, ptest->string, initial_value, LastError, CorrectError);
456 ok(result == ptest->result, "%s(\"%s\"), 0x%02x: return value should be %s\n", function, ptest->string, initial_value, ptest->result ? "TRUE" : "FALSE");
457}
458
459#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)
460#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); }
461
462static void check_dcb(const char *function, const TEST *ptest, int initial_value, const DCB *pdcb1, const DCB *pdcb2)
463{
464 /* DCBlength is a special case since Win 9x sets it but NT does not.
465 We will accept either as correct. */
466 check_dcb_member2(DCBlength, (DWORD)sizeof(DCB), "%u");
467
468 /* For old style control strings Win 9x does not set the next five members, NT does. */
469 if(ptest->old_style && ptest->result)
470 {
471 check_dcb_member2(fOutxCtsFlow, ((unsigned int)initial_value & 1), "%u");
472 check_dcb_member2(fDtrControl, ((unsigned int)initial_value & 3), "%u");
473 check_dcb_member2(fOutX, ((unsigned int)initial_value & 1), "%u");
474 check_dcb_member2(fInX, ((unsigned)initial_value & 1), "%u");
475 check_dcb_member2(fRtsControl, ((unsigned)initial_value & 3), "%u");
476 }
477 else
478 {
479 check_dcb_member(fOutxCtsFlow, "%u");
480 check_dcb_member(fDtrControl, "%u");
481 check_dcb_member(fOutX, "%u");
482 check_dcb_member(fInX, "%u");
483 check_dcb_member(fRtsControl, "%u");
484 }
485
486 if(ptest->result)
487 {
488 /* For the idsr=xxx parameter, NT sets fDsrSensitivity, 9x sets
489 fOutxDsrFlow. */
490 if(!ptest->old_style)
491 {
492 check_dcb_member2(fOutxDsrFlow, pdcb2->fDsrSensitivity, "%u");
493 check_dcb_member2(fDsrSensitivity, pdcb2->fOutxDsrFlow, "%u");
494 }
495 else
496 {
497 /* For old style control strings Win 9x does not set the
498 fOutxDsrFlow member, NT does. */
499 check_dcb_member2(fOutxDsrFlow, ((unsigned int)initial_value & 1), "%u");
500 check_dcb_member(fDsrSensitivity, "%u");
501 }
502 }
503 else
504 {
505 check_dcb_member(fOutxDsrFlow, "%u");
506 check_dcb_member(fDsrSensitivity, "%u");
507 }
508
509 /* Check the result of the DCB members. */
510 check_dcb_member(BaudRate, "%u");
511 check_dcb_member(fBinary, "%u");
512 check_dcb_member(fParity, "%u");
513 check_dcb_member(fTXContinueOnXoff, "%u");
514 check_dcb_member(fErrorChar, "%u");
515 check_dcb_member(fNull, "%u");
516 check_dcb_member(fAbortOnError, "%u");
517 check_dcb_member(fDummy2, "%u");
518 check_dcb_member(wReserved, "%u");
519 check_dcb_member(XonLim, "%u");
520 check_dcb_member(XoffLim, "%u");
522 check_dcb_member(Parity, "%u");
524 check_dcb_member(XonChar, "%d");
525 check_dcb_member(XoffChar, "%d");
526 check_dcb_member(ErrorChar, "%d");
527 check_dcb_member(EofChar, "%d");
528 check_dcb_member(EvtChar, "%d");
529 check_dcb_member(wReserved1, "%u");
530}
531
532#define check_timeouts_member(a) ok(ptimeouts1->a == ptimeouts2->a, "%s(\"%s\"), 0x%02x: "#a" is %u, should be %u\n", function, ptest->string, initial_value, ptimeouts1->a, ptimeouts2->a);
533
534static void check_timeouts(const char *function, const TEST *ptest, int initial_value, const COMMTIMEOUTS *ptimeouts1, const COMMTIMEOUTS *ptimeouts2)
535{
536 check_timeouts_member(ReadIntervalTimeout);
537 check_timeouts_member(ReadTotalTimeoutMultiplier);
538 check_timeouts_member(ReadTotalTimeoutConstant);
539 check_timeouts_member(WriteTotalTimeoutMultiplier);
540 check_timeouts_member(WriteTotalTimeoutConstant);
541}
542
543static void test_BuildCommDCBA(const char *string, const TEST *ptest, int initial_value, const DCB *pexpected_dcb)
544{
545 BOOL result;
546 DCB dcb;
547
548 /* set initial conditions */
549 memset(&dcb, initial_value, sizeof(DCB));
550 SetLastError(0xdeadbeef);
551
552 result = BuildCommDCBA(string, &dcb);
553
554 /* check results */
555 check_result("BuildCommDCBA", ptest, initial_value, result);
556 check_dcb("BuildCommDCBA", ptest, initial_value, &dcb, pexpected_dcb);
557}
558
559static void test_BuildCommDCBAndTimeoutsA(const char *string, const TEST *ptest, int initial_value, const DCB *pexpected_dcb, const COMMTIMEOUTS *pexpected_timeouts)
560{
561 BOOL result;
562 DCB dcb;
564
565 /* set initial conditions */
566 memset(&dcb, initial_value, sizeof(DCB));
567 memset(&timeouts, initial_value, sizeof(COMMTIMEOUTS));
568 SetLastError(0xdeadbeef);
569
570 result = BuildCommDCBAndTimeoutsA(string, &dcb, &timeouts);
571
572 /* check results */
573 check_result("BuildCommDCBAndTimeoutsA", ptest, initial_value, result);
574 check_dcb("BuildCommDCBAndTimeoutsA", ptest, initial_value, &dcb, pexpected_dcb);
575 check_timeouts("BuildCommDCBAndTimeoutsA", ptest, initial_value, &timeouts, pexpected_timeouts);
576}
577
578static void test_BuildCommDCBW(const char *string, const TEST *ptest, int initial_value, const DCB *pexpected_dcb)
579{
580 BOOL result;
581 DCB dcb;
582 WCHAR wide_string[sizeof(ptest->string)];
583 static int reportedDCBW = 0;
584
585 MultiByteToWideChar(CP_ACP, 0, string, -1, wide_string, sizeof(wide_string) / sizeof(WCHAR));
586
587 /* set initial conditions */
588 memset(&dcb, initial_value, sizeof(DCB));
589 SetLastError(0xdeadbeef);
590
591 result = BuildCommDCBW(wide_string, &dcb);
592
594 {
595 if(!reportedDCBW++)
596 win_skip("BuildCommDCBW is not implemented\n");
597 return;
598 }
599
600 /* check results */
601 check_result("BuildCommDCBW", ptest, initial_value, result);
602 check_dcb("BuildCommDCBW", ptest, initial_value, &dcb, pexpected_dcb);
603}
604
605static void test_BuildCommDCBAndTimeoutsW(const char *string, const TEST *ptest, int initial_value, const DCB *pexpected_dcb, const COMMTIMEOUTS *pexpected_timeouts)
606{
607 BOOL result;
608 DCB dcb;
610 WCHAR wide_string[sizeof(ptest->string)];
611 static int reportedDCBAndTW = 0;
612
613 MultiByteToWideChar(CP_ACP, 0, string, -1, wide_string, sizeof(wide_string) / sizeof(WCHAR));
614
615 /* set initial conditions */
616 memset(&dcb, initial_value, sizeof(DCB));
617 memset(&timeouts, initial_value, sizeof(COMMTIMEOUTS));
618 SetLastError(0xdeadbeef);
619
620 result = BuildCommDCBAndTimeoutsW(wide_string, &dcb, &timeouts);
621
623 {
624 if(!reportedDCBAndTW++)
625 win_skip("BuildCommDCBAndTimeoutsW is not implemented\n");
626 return;
627 }
628
629 /* check results */
630 check_result("BuildCommDCBAndTimeoutsW", ptest, initial_value, result);
631 check_dcb("BuildCommDCBAndTimeoutsW", ptest, initial_value, &dcb, pexpected_dcb);
632 check_timeouts("BuildCommDCBAndTimeoutsW", ptest, initial_value, &timeouts, pexpected_timeouts);
633}
634
635static void test_BuildCommDCB(void)
636{
637 char port_name[] = "COMx";
638 char port = 0;
639 unsigned int i;
640 char *ptr;
641
642 /* Some of these tests require a valid COM port. This loop will try to find
643 a valid port. */
644 for(port_name[3] = '1'; port_name[3] <= '9'; port_name[3]++)
645 {
646 COMMCONFIG commconfig;
647 DWORD size = sizeof(COMMCONFIG);
648
649 if(GetDefaultCommConfigA(port_name, &commconfig, &size))
650 {
651 port = port_name[3];
652 break;
653 }
654 }
655
656 if(!port)
657 trace("Could not find a valid COM port. Some tests will be skipped.\n");
658
659 for(i = 0; i < TEST_COUNT; i++)
660 {
661 char string[sizeof(test[i].string)];
662
663 strcpy(string, test[i].string);
664
665 /* Check if this test case needs a valid COM port. */
666 ptr = strstr(string, "COMx");
667
668 /* If required, substitute valid port number into device control string. */
669 if(ptr)
670 {
671 if(port)
672 ptr[3] = port;
673 else
674 continue;
675 }
676
677 test_BuildCommDCBA(string, &test[i], 0x00, &test[i].dcb1);
678 test_BuildCommDCBA(string, &test[i], 0xff, &test[i].dcb2);
679 test_BuildCommDCBAndTimeoutsA(string, &test[i], 0x00, &test[i].dcb1, &test[i].timeouts1);
680 test_BuildCommDCBAndTimeoutsA(string, &test[i], 0xff, &test[i].dcb2, &test[i].timeouts2);
681
682 test_BuildCommDCBW(string, &test[i], 0x00, &test[i].dcb1);
683 test_BuildCommDCBW(string, &test[i], 0xff, &test[i].dcb2);
684 test_BuildCommDCBAndTimeoutsW(string, &test[i], 0x00, &test[i].dcb1, &test[i].timeouts1);
685 test_BuildCommDCBAndTimeoutsW(string, &test[i], 0xff, &test[i].dcb2, &test[i].timeouts2);
686 }
687}
688
689static HANDLE test_OpenComm(BOOL doOverlap)
690{
692 char port_name[] = "COMx";
693 static BOOL shown = FALSE;
694 DWORD errors;
695 COMSTAT comstat;
696
697 /* Try to find a port */
698 for(port_name[3] = '1'; port_name[3] <= '9'; port_name[3]++)
699 {
700 hcom = CreateFileA( port_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
701 (doOverlap)?FILE_FLAG_OVERLAPPED:0, NULL );
702 if (hcom != INVALID_HANDLE_VALUE)
703 break;
704 }
705 if(!shown)
706 {
707 if (hcom == INVALID_HANDLE_VALUE)
708 trace("Could not find a valid COM port.\n");
709 else
710 trace("Found Com port %s. Connected devices may disturb results\n", port_name);
711 /*shown = TRUE; */
712 }
713 if (hcom != INVALID_HANDLE_VALUE)
714 {
715 BOOL ret;
716
717 ret = ClearCommError(hcom, &errors, &comstat);
719 {
721 trace("%s doesn't respond, skipping the test\n", port_name);
722 else
723 trace("%s is not a real serial port, skipping the test\n", port_name);
724 CloseHandle(hcom);
726 }
727
728 ok(ret, "Unexpected error %u on open\n", GetLastError());
729 ok(comstat.cbInQue == 0, "Unexpected %d chars in InQueue\n",comstat.cbInQue);
730 ok(comstat.cbOutQue == 0, "Still pending %d charcters in OutQueue\n", comstat.cbOutQue);
731 ok(errors == 0, "Unexpected errors 0x%08x\n", errors);
732 }
733 return hcom;
734}
735
737{
738 DWORD ModemStat = 0;
739
740 ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
741 trace("GetCommModemStatus returned 0x%08x->%s%s%s%s\n", ModemStat,
742 (ModemStat &MS_RLSD_ON)?"MS_RLSD_ON ":"",
743 (ModemStat &MS_RING_ON)?"MS_RING_ON ":"",
744 (ModemStat &MS_DSR_ON)?"MS_DSR_ON ":"",
745 (ModemStat &MS_CTS_ON)?"MS_CTS_ON ":"");
746}
747
748/* When we don't write anything, Read should time out even on a loopbacked port */
749static void test_ReadTimeOut(void)
750{
751 HANDLE hcom;
752 DCB dcb;
754 char rbuf[32];
755 DWORD before, after, read, timediff, LastError;
756 BOOL res;
757
758 hcom = test_OpenComm(FALSE);
759 if (hcom == INVALID_HANDLE_VALUE) return;
760
762
763 ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
764 dcb.BaudRate = FASTBAUD;
765 dcb.ByteSize = 8;
766 dcb.Parity = NOPARITY;
767 dcb.fRtsControl=RTS_CONTROL_ENABLE;
768 dcb.fDtrControl=DTR_CONTROL_ENABLE;
769 dcb.StopBits = ONESTOPBIT;
770 ok(SetCommState(hcom, &dcb), "SetCommState failed\n");
771
772 ZeroMemory( &timeouts, sizeof(timeouts));
773 timeouts.ReadTotalTimeoutConstant = TIMEOUT;
774 ok(SetCommTimeouts(hcom, &timeouts),"SetCommTimeouts failed\n");
775
777 SetLastError(0xdeadbeef);
778 res = ReadFile(hcom, rbuf, sizeof(rbuf), &read, NULL);
779 LastError = GetLastError();
781 ok( res == TRUE, "A timed-out read should return TRUE\n");
782 ok( LastError == 0xdeadbeef, "err=%d\n", LastError);
783 timediff = after - before;
784 ok( timediff > TIMEOUT>>2 && timediff < TIMEOUT *2,
785 "Unexpected TimeOut %d, expected %d\n", timediff, TIMEOUT);
786
787 CloseHandle(hcom);
788}
789
790static void test_waittxempty(void)
791{
792 HANDLE hcom;
793 DCB dcb;
795 char tbuf[]="test_waittxempty";
796 DWORD before, after, bytes, timediff, evtmask, errors, i;
797 BOOL res;
798 DWORD baud = SLOWBAUD;
799 OVERLAPPED ovl_write, ovl_wait, ovl_wait2;
801
802 hcom = test_OpenComm(TRUE);
803 if (hcom == INVALID_HANDLE_VALUE) return;
804
805 /* set a low baud rate to have ample time*/
806 res = GetCommState(hcom, &dcb);
807 ok(res, "GetCommState error %d\n", GetLastError());
808 dcb.BaudRate = baud;
809 dcb.ByteSize = 8;
810 dcb.Parity = NOPARITY;
811 dcb.fRtsControl=RTS_CONTROL_ENABLE;
812 dcb.fDtrControl=DTR_CONTROL_ENABLE;
813 dcb.StopBits = ONESTOPBIT;
814 res = SetCommState(hcom, &dcb);
815 ok(res, "SetCommState error %d\n", GetLastError());
816
817 ZeroMemory( &timeouts, sizeof(timeouts));
818 timeouts.ReadTotalTimeoutConstant = TIMEOUT;
819 res = SetCommTimeouts(hcom, &timeouts);
820 ok(res,"SetCommTimeouts error %d\n", GetLastError());
821
822 res = SetupComm(hcom, 1024, 1024);
823 ok(res, "SetUpComm error %d\n", GetLastError());
824
825 /* calling SetCommMask after WriteFile leads to WaitCommEvent failures
826 * due to timeout (no events) under testbot VMs and VirtualBox
827 */
828 res = SetCommMask(hcom, EV_TXEMPTY);
829 ok(res, "SetCommMask error %d\n", GetLastError());
830
831 SetLastError(0xdeadbeef);
832 res = WriteFile(hcom, tbuf, sizeof(tbuf), &bytes, NULL);
833 ok(!res, "WriteFile on an overlapped handle without ovl structure should fail\n");
834 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
835
836 S(U(ovl_write)).Offset = 0;
837 S(U(ovl_write)).OffsetHigh = 0;
838 ovl_write.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
840 SetLastError(0xdeadbeef);
841 res = WriteFile(hcom, tbuf, sizeof(tbuf), &bytes, &ovl_write);
843 ok((!res && GetLastError() == ERROR_IO_PENDING) || (res && bytes == sizeof(tbuf)),
844 "WriteFile returned %d, written %u bytes, error %d\n", res, bytes, GetLastError());
845 if (!res) ok(!bytes, "expected 0, got %u\n", bytes);
846 ok(after - before < 30, "WriteFile took %d ms to write %d Bytes at %d Baud\n",
847 after - before, bytes, baud);
848 /* don't wait for WriteFile completion */
849
850 S(U(ovl_wait)).Offset = 0;
851 S(U(ovl_wait)).OffsetHigh = 0;
852 ovl_wait.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
853 evtmask = 0;
855 SetLastError(0xdeadbeef);
856 res = WaitCommEvent(hcom, &evtmask, &ovl_wait);
857 ok(!res && GetLastError() == ERROR_IO_PENDING, "WaitCommEvent error %d\n", GetLastError());
859 ok(after - before < 30, "WaitCommEvent should have returned immediately, took %d ms\n", after - before);
860 res = WaitForSingleObject(ovl_wait.hEvent, 1500);
861 ok(res == WAIT_OBJECT_0, "WaitCommEvent failed with a timeout\n");
862 if (res == WAIT_OBJECT_0)
863 {
864 res = GetOverlappedResult(hcom, &ovl_wait, &bytes, FALSE);
865 ok(res, "GetOverlappedResult reported error %d\n", GetLastError());
866 ok(bytes == sizeof(evtmask), "expected %u, written %u\n", (UINT)sizeof(evtmask), bytes);
867 res = TRUE;
868 }
869 else
870 {
871 /* unblock pending wait */
872 trace("recovering after WAIT_TIMEOUT...\n");
873 res = SetCommMask(hcom, EV_TXEMPTY);
874 ok(res, "SetCommMask error %d\n", GetLastError());
875
877 ok(res == WAIT_OBJECT_0, "WaitCommEvent failed with a timeout\n");
878
879 res = FALSE;
880 }
882 ok(res, "WaitCommEvent error %d\n", GetLastError());
883 ok(evtmask & EV_TXEMPTY, "WaitCommEvent: expected EV_TXEMPTY, got %#x\n", evtmask);
884 CloseHandle(ovl_wait.hEvent);
885
886 timediff = after - before;
887 trace("WaitCommEvent for EV_TXEMPTY took %d ms (timeout 1500)\n", timediff);
888 ok(timediff < 1200, "WaitCommEvent used %d ms for waiting\n", timediff);
889
890 res = WaitForSingleObject(ovl_write.hEvent, 0);
891 ok(res == WAIT_OBJECT_0, "WriteFile failed with a timeout\n");
892 res = GetOverlappedResult(hcom, &ovl_write, &bytes, FALSE);
893 ok(res, "GetOverlappedResult reported error %d\n", GetLastError());
894 ok(bytes == sizeof(tbuf), "expected %u, written %u\n", (UINT)sizeof(tbuf), bytes);
895 CloseHandle(ovl_write.hEvent);
896
897 CloseHandle(hcom);
898
899 for (i = 0; i < 2; i++)
900 {
901 hcom = test_OpenComm(TRUE);
902 if (hcom == INVALID_HANDLE_VALUE) return;
903
904 res = SetCommMask(hcom, EV_TXEMPTY);
905 ok(res, "SetCommMask error %d\n", GetLastError());
906
907 if (i == 0)
908 {
909 S(U(ovl_write)).Offset = 0;
910 S(U(ovl_write)).OffsetHigh = 0;
911 ovl_write.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
913 SetLastError(0xdeadbeef);
914 res = WriteFile(hcom, tbuf, sizeof(tbuf), &bytes, &ovl_write);
915 ok((!res && GetLastError() == ERROR_IO_PENDING) || (res && bytes == sizeof(tbuf)),
916 "WriteFile returned %d, written %u bytes, error %d\n", res, bytes, GetLastError());
917 if (!res) ok(!bytes, "expected 0, got %u\n", bytes);
918
919 ClearCommError(hcom, &errors, &stat);
920 ok(stat.cbInQue == 0, "InQueue should be empty, got %d bytes\n", stat.cbInQue);
921 ok(stat.cbOutQue != 0 || broken(stat.cbOutQue == 0) /* VM */, "OutQueue should not be empty\n");
922 ok(errors == 0, "ClearCommErrors: Unexpected error 0x%08x\n", errors);
923
924 res = GetOverlappedResult(hcom, &ovl_write, &bytes, TRUE);
925 ok(res, "GetOverlappedResult reported error %d\n", GetLastError());
926 ok(bytes == sizeof(tbuf), "expected %u, written %u\n", (UINT)sizeof(tbuf), bytes);
927 CloseHandle(ovl_write.hEvent);
928
929 res = FlushFileBuffers(hcom);
930 ok(res, "FlushFileBuffers error %d\n", GetLastError());
931 }
932
933 ClearCommError(hcom, &errors, &stat);
934 ok(stat.cbInQue == 0, "InQueue should be empty, got %d bytes\n", stat.cbInQue);
935 ok(stat.cbOutQue == 0, "OutQueue should be empty, got %d bytes\n", stat.cbOutQue);
936 ok(errors == 0, "ClearCommErrors: Unexpected error 0x%08x\n", errors);
937
938 S(U(ovl_wait)).Offset = 0;
939 S(U(ovl_wait)).OffsetHigh = 0;
940 ovl_wait.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
941 evtmask = 0;
942 SetLastError(0xdeadbeef);
943 res = WaitCommEvent(hcom, &evtmask, &ovl_wait);
944 ok(res /* busy system */ || GetLastError() == ERROR_IO_PENDING,
945 "%d: WaitCommEvent error %d\n", i, GetLastError());
946
948 if (i == 0)
949 ok(res == WAIT_OBJECT_0, "WaitCommEvent failed with a timeout\n");
950 else
951 ok(res == WAIT_TIMEOUT, "WaitCommEvent should fail with a timeout\n");
952 if (res == WAIT_OBJECT_0)
953 {
954 res = GetOverlappedResult(hcom, &ovl_wait, &bytes, FALSE);
955 ok(res, "GetOverlappedResult reported error %d\n", GetLastError());
956 ok(bytes == sizeof(evtmask), "expected %u, written %u\n", (UINT)sizeof(evtmask), bytes);
957 ok(res, "WaitCommEvent error %d\n", GetLastError());
958 ok(evtmask & EV_TXEMPTY, "WaitCommEvent: expected EV_TXEMPTY, got %#x\n", evtmask);
959 }
960 else
961 {
962 ok(!evtmask, "WaitCommEvent: expected 0, got %#x\n", evtmask);
963
964 S(U(ovl_wait2)).Offset = 0;
965 S(U(ovl_wait2)).OffsetHigh = 0;
966 ovl_wait2.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
967 SetLastError(0xdeadbeef);
968 res = WaitCommEvent(hcom, &evtmask, &ovl_wait2);
969 ok(!res, "WaitCommEvent should fail if there is a pending wait\n");
970 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
971 CloseHandle(ovl_wait2.hEvent);
972
973 /* unblock pending wait */
974 trace("recovering after WAIT_TIMEOUT...\n");
975 res = SetCommMask(hcom, EV_TXEMPTY);
976 ok(res, "SetCommMask error %d\n", GetLastError());
977
979 ok(res == WAIT_OBJECT_0, "WaitCommEvent failed with a timeout\n");
980 CloseHandle(ovl_wait.hEvent);
981 }
982
983 CloseHandle(hcom);
984 }
985}
986
987/* A new open handle should not return error or have bytes in the Queues */
988static void test_ClearCommError(void)
989{
990 HANDLE hcom;
991 DWORD errors;
992 COMSTAT lpStat;
993
994 hcom = test_OpenComm(FALSE);
995 if (hcom == INVALID_HANDLE_VALUE) return;
996
997 ok(ClearCommError(hcom, &errors, &lpStat), "ClearCommError failed\n");
998 ok(lpStat.cbInQue == 0, "Unexpected %d chars in InQueue\n", lpStat.cbInQue);
999 ok(lpStat.cbOutQue == 0, "Unexpected %d chars in OutQueue\n", lpStat.cbOutQue);
1000 ok(errors == 0, "ClearCommErrors: Unexpected error 0x%08x\n", errors);
1001
1002 CloseHandle(hcom);
1003}
1004
1006{
1007 HANDLE hcom;
1008 DCB dcb;
1009 DWORD err;
1010
1011 hcom = test_OpenComm(FALSE);
1012 if (hcom == INVALID_HANDLE_VALUE) return;
1013
1014 ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
1015 dcb.ByteSize = 255; /* likely bogus */
1016 ok(!SetCommState(hcom, &dcb), "SetCommState should have failed\n");
1017 ok(ClearCommError(hcom, &err, NULL), "ClearCommError should succeed\n");
1018 ok(!(err & CE_MODE), "ClearCommError shouldn't set CE_MODE byte in this case (%x)\n", err);
1019
1020 CloseHandle(hcom);
1021}
1022
1023static void test_LoopbackRead(void)
1024{
1025 HANDLE hcom;
1026 DCB dcb;
1028 char rbuf[32];
1029 DWORD before, after, diff, read, read1, written, evtmask=0, i;
1030 BOOL res;
1031 char tbuf[]="test_LoopbackRead";
1032
1033 if (!loopback_txd_rxd) return;
1034
1035 hcom = test_OpenComm(FALSE);
1036 if (hcom == INVALID_HANDLE_VALUE) return;
1037
1038 trace("Starting test_LoopbackRead\n");
1039 ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
1040 dcb.BaudRate = FASTBAUD;
1041 dcb.ByteSize = 8;
1042 dcb.Parity = NOPARITY;
1043 dcb.fRtsControl=RTS_CONTROL_ENABLE;
1044 dcb.fDtrControl=DTR_CONTROL_ENABLE;
1045 dcb.StopBits = ONESTOPBIT;
1046 ok(SetCommState(hcom, &dcb), "SetCommState failed\n");
1047
1048 ZeroMemory( &timeouts, sizeof(timeouts));
1049 timeouts.ReadTotalTimeoutConstant = TIMEOUT;
1050 ok(SetCommTimeouts(hcom, &timeouts),"SetCommTimeouts failed\n");
1051
1052 ok(SetCommMask(hcom, EV_TXEMPTY), "SetCommMask failed\n");
1053
1054 before = GetTickCount();
1055 ok(WriteFile(hcom,tbuf,sizeof(tbuf),&written, NULL), "WriteFile failed\n");
1056 after = GetTickCount();
1057 ok(written == sizeof(tbuf),"WriteFile %d bytes written\n", written);
1058 diff = after -before;
1059
1060 /* make sure all bytes are written, so Readfile will succeed in one call*/
1061 ok(WaitCommEvent(hcom, &evtmask, NULL), "WaitCommEvent failed\n");
1062 before = GetTickCount();
1063 ok(evtmask == EV_TXEMPTY,
1064 "WaitCommEvent: Unexpected EvtMask 0x%08x, expected 0x%08x\n",
1065 evtmask, EV_TXEMPTY);
1066 trace("Write %d ms WaitCommEvent EV_TXEMPTY %d ms\n", diff, before- after);
1067
1068 read=0;
1069 ok(ReadFile(hcom, rbuf, sizeof(rbuf), &read, NULL), "Readfile failed\n");
1070 ok(read == sizeof(tbuf),"ReadFile read %d bytes, expected \"%s\"\n", read,rbuf);
1071
1072 /* Now do the same with a slower Baud rate.
1073 As we request more characters than written, we will hit the timeout
1074 */
1075
1076 ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
1077 dcb.BaudRate = 9600;
1078 dcb.ByteSize = 8;
1079 dcb.Parity = NOPARITY;
1080 dcb.fRtsControl=RTS_CONTROL_ENABLE;
1081 dcb.fDtrControl=DTR_CONTROL_ENABLE;
1082 dcb.StopBits = ONESTOPBIT;
1083 ok(SetCommState(hcom, &dcb), "SetCommState failed\n");
1084
1085 ok(SetCommMask(hcom, EV_RXCHAR), "SetCommMask failed\n");
1086 ok(WriteFile(hcom,tbuf,sizeof(tbuf),&written, NULL), "WriteFile failed\n");
1087 ok(written == sizeof(tbuf),"WriteFile %d bytes written\n", written);
1088
1089 trace("WaitCommEventEV_RXCHAR\n");
1090 ok(WaitCommEvent(hcom, &evtmask, NULL), "WaitCommEvent failed\n");
1091 ok(evtmask == EV_RXCHAR, "WaitCommEvent: Unexpected EvtMask 0x%08x, expected 0x%08x\n",
1092 evtmask, EV_RXCHAR);
1093
1094 before = GetTickCount();
1095 res = ReadFile(hcom, rbuf, sizeof(rbuf), &read, NULL);
1096 after = GetTickCount();
1097 ok(res, "Readfile failed\n");
1098 ok(read == sizeof(tbuf),"ReadFile read %d bytes\n", read);
1099 diff = after - before;
1100 trace("Readfile for %d chars took %d ms\n", read, diff);
1101 ok( (diff > TIMEOUT - TIMEDELTA) && (diff < TIMEOUT + TIMEDELTA),
1102 "Timedout Wait took %d ms, expected around %d\n", diff, TIMEOUT);
1103
1104 /* now do a plain read with slow speed
1105 * This will result in several low level reads and a timeout to happen
1106 */
1107 dcb.BaudRate = SLOWBAUD;
1108 ok(SetCommState(hcom, &dcb), "SetCommState failed\n");
1109 ok(WriteFile(hcom,tbuf,sizeof(tbuf),&written, NULL), "WriteFile failed\n");
1110 before = GetTickCount();
1111 read = 0;
1112 read1 =0;
1113 i=0;
1114 do
1115 {
1116 res = ReadFile(hcom, rbuf+read, sizeof(rbuf)-read, &read1, NULL);
1117 ok(res, "Readfile failed\n");
1118 read += read1;
1119 i++;
1120 }
1121 while ((read < sizeof(tbuf)) && (i <10));
1122 after = GetTickCount();
1123 ok( read == sizeof(tbuf),"ReadFile read %d bytes\n", read);
1124 trace("Plain Read for %d char at %d baud took %d ms\n", read, SLOWBAUD, after-before);
1125
1126 CloseHandle(hcom);
1127}
1128
1129static void test_LoopbackCtsRts(void)
1130{
1131 HANDLE hcom;
1132 DWORD ModemStat = 0, defaultStat = 0;
1133 DCB dcb;
1134
1135 if (!loopback_rts_cts) return;
1136
1137 hcom = test_OpenComm(FALSE);
1138 if (hcom == INVALID_HANDLE_VALUE) return;
1139
1140 memset (&dcb, 0, sizeof (dcb));
1141 ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
1142 if (dcb.fRtsControl == RTS_CONTROL_HANDSHAKE)
1143 {
1144 trace("RTS_CONTROL_HANDSHAKE is set, so don't manipulate RTS\n");
1145 CloseHandle(hcom);
1146 return;
1147 }
1148 ok(GetCommModemStatus(hcom, &defaultStat), "GetCommModemStatus failed\n");
1149 /* XP returns some values in the low nibble, so mask them out*/
1151 if(defaultStat & MS_CTS_ON)
1152 {
1153 ok(EscapeCommFunction(hcom, CLRRTS), "EscapeCommFunction failed to clear RTS\n");
1154 ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1155 ok ((ModemStat & MS_CTS_ON) == 0, "CTS didn't react: 0x%04x, expected 0x%04x\n",
1156 ModemStat, (defaultStat & ~MS_CTS_ON));
1157 ok(EscapeCommFunction(hcom, SETRTS), "EscapeCommFunction failed to clear RTS\n");
1158 ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1159 ok (ModemStat == defaultStat, "Failed to restore CTS: 0x%04x, expected 0x%04x\n",
1160 ModemStat, defaultStat);
1161 }
1162 else
1163 {
1164 ok(EscapeCommFunction(hcom, SETRTS), "EscapeCommFunction failed to set RTS\n");
1165 ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1166 ok ((ModemStat & MS_CTS_ON) == MS_CTS_ON,
1167 "CTS didn't react: 0x%04x, expected 0x%04x\n",
1168 ModemStat, (defaultStat | MS_CTS_ON));
1169 ok(EscapeCommFunction(hcom, CLRRTS), "EscapeCommFunction failed to clear RTS\n");
1170 ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1171 ok (ModemStat == defaultStat, "Failed to restore CTS: 0x%04x, expected 0x%04x\n",
1172 ModemStat, defaultStat);
1173 }
1174
1175 CloseHandle(hcom);
1176}
1177
1178static void test_LoopbackDtrDcd(void)
1179{
1180 HANDLE hcom;
1181 DWORD ModemStat = 0, defaultStat = 0;
1182 DCB dcb;
1183
1184 if (!loopback_dtr_dcd) return;
1185
1186 hcom = test_OpenComm(FALSE);
1187 if (hcom == INVALID_HANDLE_VALUE) return;
1188
1189 ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
1190 if (dcb.fDtrControl == DTR_CONTROL_HANDSHAKE)
1191 {
1192 trace("DTR_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
1193 CloseHandle(hcom);
1194 return;
1195 }
1196 ok(GetCommModemStatus(hcom, &defaultStat), "GetCommModemStatus failed\n");
1197 /* XP returns some values in the low nibble, so mask them out*/
1199 if(defaultStat & MS_RLSD_ON)
1200 {
1201 ok(EscapeCommFunction(hcom, CLRDTR), "EscapeCommFunction failed to clear DTR\n");
1202 ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1203 ok ((ModemStat & MS_RLSD_ON) == 0, "RLSD didn't react: 0x%04x, expected 0x%04x\n",
1204 ModemStat, (defaultStat & ~MS_RLSD_ON));
1205 ok(EscapeCommFunction(hcom, SETDTR), "EscapeCommFunction failed to set DTR\n");
1206 ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1207 ok (ModemStat == defaultStat, "Failed to restore RLSD: 0x%04x, expected 0x%04x\n",
1208 ModemStat, defaultStat);
1209 }
1210 else
1211 {
1212 ok(EscapeCommFunction(hcom, SETDTR), "EscapeCommFunction failed to set DTR\n");
1213 ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1214 ok ((ModemStat & MS_RLSD_ON) == MS_RLSD_ON,
1215 "RLSD didn't react: 0x%04x, expected 0x%04x\n",
1216 ModemStat, (defaultStat | MS_RLSD_ON));
1217 ok(EscapeCommFunction(hcom, CLRDTR), "EscapeCommFunction failed to clear DTR\n");
1218 ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1219 ok (ModemStat == defaultStat, "Failed to restore RLSD: 0x%04x, expected 0x%04x\n",
1220 ModemStat, defaultStat);
1221 }
1222
1223 CloseHandle(hcom);
1224}
1225
1226static void test_LoopbackDtrDsr(void)
1227{
1228 HANDLE hcom;
1229 DWORD ModemStat = 0, defaultStat = 0;
1230 DCB dcb;
1231
1232 if (!loopback_dtr_dsr) return;
1233
1234 hcom = test_OpenComm(FALSE);
1235 if (hcom == INVALID_HANDLE_VALUE) return;
1236
1237 ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
1238 if (dcb.fDtrControl == DTR_CONTROL_DISABLE)
1239 {
1240 trace("DTR_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
1241 CloseHandle(hcom);
1242 return;
1243 }
1244 ok(GetCommModemStatus(hcom, &defaultStat), "GetCommModemStatus failed\n");
1245 /* XP returns some values in the low nibble, so mask them out*/
1247 if(defaultStat & MS_DSR_ON)
1248 {
1249 ok(EscapeCommFunction(hcom, CLRDTR), "EscapeCommFunction failed to clear DTR\n");
1250 ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1251 ok ((ModemStat & MS_DSR_ON) == 0, "CTS didn't react: 0x%04x, expected 0x%04x\n",
1252 ModemStat, (defaultStat & ~MS_DSR_ON));
1253 ok(EscapeCommFunction(hcom, SETDTR), "EscapeCommFunction failed to clear DTR\n");
1254 ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1255 ok (ModemStat == defaultStat, "Failed to restore DSR: 0x%04x, expected 0x%04x\n",
1256 ModemStat, defaultStat);
1257 }
1258 else
1259 {
1260 ok(EscapeCommFunction(hcom, SETDTR), "EscapeCommFunction failed to set DTR\n");
1261 ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1262 ok ((ModemStat & MS_DSR_ON) == MS_DSR_ON,
1263 "CTS didn't react: 0x%04x,expected 0x%04x\n",
1264 ModemStat, (defaultStat | MS_DSR_ON));
1265 ok(EscapeCommFunction(hcom, CLRDTR), "EscapeCommFunction failed to clear DTR\n");
1266 ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1267 ok (ModemStat == defaultStat, "Failed to restore DSR: 0x%04x, expected 0x%04x\n",
1268 ModemStat, defaultStat);
1269 }
1270
1271 CloseHandle(hcom);
1272}
1273
1274static void test_LoopbackDtrRing(void)
1275{
1276 HANDLE hcom;
1277 DWORD ModemStat = 0, defaultStat = 0;
1278 DCB dcb;
1279
1280 if (!loopback_dtr_ring) return;
1281
1282 hcom = test_OpenComm(FALSE);
1283 if (hcom == INVALID_HANDLE_VALUE) return;
1284
1285 ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
1286 if (dcb.fDtrControl == DTR_CONTROL_HANDSHAKE)
1287 {
1288 trace("DTR_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
1289 CloseHandle(hcom);
1290 return;
1291 }
1292 ok(GetCommModemStatus(hcom, &defaultStat), "GetCommModemStatus failed\n");
1293 /* XP returns some values in the low nibble, so mask them out*/
1295 if(defaultStat & MS_RING_ON)
1296 {
1297 ok(EscapeCommFunction(hcom, CLRDTR), "EscapeCommFunction failed to clear DTR\n");
1298 ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1299 ok ((ModemStat & MS_RING_ON) == 0, "RING didn't react: 0x%04x, expected 0x%04x\n",
1300 ModemStat, (defaultStat & ~MS_RING_ON));
1301 ok(EscapeCommFunction(hcom, SETDTR), "EscapeCommFunction failed to set DTR\n");
1302 ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1303 ok (ModemStat == defaultStat, "Failed to restore RING: 0x%04x, expected 0x%04x\n",
1304 ModemStat, defaultStat);
1305 }
1306 else
1307 {
1308 ok(EscapeCommFunction(hcom, SETDTR), "EscapeCommFunction failed to set DTR\n");
1309 ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1310 ok ((ModemStat & MS_RING_ON) == MS_RING_ON,
1311 "RING didn't react: 0x%04x,expected 0x%04x\n",
1312 ModemStat, (defaultStat | MS_RING_ON));
1313 ok(EscapeCommFunction(hcom, CLRDTR), "EscapeCommFunction failed to clear DTR\n");
1314 ok(GetCommModemStatus(hcom, &ModemStat), "GetCommModemStatus failed\n");
1315 ok (ModemStat == defaultStat, "Failed to restore RING: 0x%04x, expected 0x%04x\n",
1316 ModemStat, defaultStat);
1317 }
1318
1319 CloseHandle(hcom);
1320}
1321
1322/*
1323 * Set up a WaitCommEvent for anything in the receive buffer,
1324 * then write to TX to put a character
1325 * into the RX buffer
1326 * Need Loopback TX->RX
1327*/
1328
1329static void test_WaitRx(void)
1330{
1331 OVERLAPPED overlapped, overlapped_w;
1332 HANDLE hcom, hComPortEvent, hComWriteEvent;
1333 DWORD before, after, after1, diff, success_wait = FALSE, success_write;
1334 DWORD err_wait, err_write, written, evtmask=0;
1335
1336 if (!loopback_txd_rxd) return;
1337
1338 hcom = test_OpenComm(TRUE);
1339 if (hcom == INVALID_HANDLE_VALUE) return;
1340
1341 ok(SetCommMask(hcom, EV_RXCHAR), "SetCommMask failed\n");
1342 hComPortEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
1343 ok(hComPortEvent != 0, "CreateEvent failed\n");
1344 ZeroMemory( &overlapped, sizeof(overlapped));
1345 overlapped.hEvent = hComPortEvent;
1346
1347 hComWriteEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
1348 ok(hComWriteEvent != NULL, "CreateEvent res %d\n", GetLastError());
1349 ZeroMemory( &overlapped_w, sizeof(overlapped_w));
1350 overlapped_w.hEvent = hComWriteEvent;
1351
1352 before = GetTickCount();
1353 success_wait = WaitCommEvent(hcom, &evtmask, &overlapped);
1354 err_wait = GetLastError();
1355 after = GetTickCount();
1356 trace("Success 0x%08x err %d evtmask 0x%08x\n", success_wait, err_wait, evtmask);
1357 ok(success_wait || err_wait == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
1358 trace("overlapped WaitCommEvent returned.\n");
1359
1360 success_write= WriteFile(hcom, "X", 1, &written, &overlapped_w);
1361 err_write = GetLastError();
1362 ok(success_write || err_write == ERROR_IO_PENDING,
1363 "overlapped WriteFile failed, err %d\n",
1364 err_write);
1365
1366 if (!success_write && (err_write == ERROR_IO_PENDING)) {
1367 success_write = WaitForSingleObjectEx(hComWriteEvent, TIMEOUT, TRUE);
1368 err_write = GetLastError();
1369 ok(success_write == WAIT_OBJECT_0, "WaitForSingleObjectEx, res %d, err %d\n",
1370 success_write, err_write);
1371 }
1372 Sleep(TIMEOUT >>1);
1373 success_write = GetOverlappedResult(hcom, &overlapped_w, &written, FALSE);
1374 err_write = GetLastError();
1375
1376 trace("Write after Wait res 0x%08x err %d\n",success_write, err_write);
1377 ok(success_write && written ==1, "Write after Wait res 0x%08x err %d\n",
1378 success_write, err_write);
1379
1380 if (!success_wait && (err_wait == ERROR_IO_PENDING)) {
1381 success_wait = WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE);
1382 err_wait = GetLastError();
1383 ok(success_wait == WAIT_OBJECT_0, "wait hComPortEvent, res 0x%08x, err %d\n",
1384 success_wait, err_wait);
1385 }
1386 success_wait = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
1387 err_wait = GetLastError();
1388 after1 = GetTickCount();
1389 trace("Success 0x%08x err %d evtmask 0x%08x diff1 %d, diff2 %d\n",
1390 success_wait, err_wait, evtmask, after-before, after1-before);
1391
1392 ok(evtmask & EV_RXCHAR, "Detect EV_RXCHAR: 0x%08x, expected 0x%08x\n",
1393 evtmask, EV_RXCHAR);
1394 diff = after1 - before;
1395 ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
1396 "Unexpected time %d, expected around %d\n", diff, TIMEOUT>>1);
1397
1398 CloseHandle(hcom);
1399}
1400
1401/* Change the controlling line after the given timeout to the given state
1402 By the loopback, this should trigger the WaitCommEvent
1403*/
1405{
1406 DWORD_PTR *args = arg;
1407 DWORD timeout = args[0];
1408 DWORD ctl = args[1];
1409 HANDLE hcom = (HANDLE) args[2];
1410 HANDLE hComPortEvent = (HANDLE) args[3];
1411 DWORD success, err;
1412
1413 trace("toggle_ctlLine timeout %d ctl 0x%08x handle %p\n", timeout, ctl, hcom );
1414 Sleep(timeout);
1415 ok(EscapeCommFunction(hcom, ctl),"EscapeCommFunction 0x%08x failed\n", ctl);
1416 trace("toggle_ctline done\n");
1417 success = WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE);
1418 err = GetLastError();
1419 trace("toggle_ctline WaitForSingleObjectEx res 0x%08x err %d\n",
1420 success, err);
1421 return 0;
1422}
1423
1424/*
1425 * Wait for a change in CTS
1426 * Needs Loopback from DTR to CTS
1427 */
1428static void test_WaitCts(void)
1429{
1430 DCB dcb;
1432 HANDLE hcom, hComPortEvent, alarmThread;
1433 DWORD_PTR args[4];
1434 DWORD alarmThreadId, before, after, after1, diff, success, err, written, evtmask=0, defaultStat = 0;
1435
1436 if (!loopback_rts_cts) return;
1437
1438 hcom = test_OpenComm(TRUE);
1439 if (hcom == INVALID_HANDLE_VALUE) return;
1440
1441 ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
1442 dcb.fRtsControl=RTS_CONTROL_ENABLE;
1443 dcb.fDtrControl=DTR_CONTROL_ENABLE;
1444 ok(SetCommState(hcom, &dcb), "SetCommState failed\n");
1445 if (dcb.fDtrControl == RTS_CONTROL_DISABLE)
1446 {
1447 trace("RTS_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
1448 CloseHandle(hcom);
1449 return;
1450 }
1451 args[0]= TIMEOUT >>1;
1452 ok(GetCommModemStatus(hcom, &defaultStat), "GetCommModemStatus failed\n");
1453 if(defaultStat & MS_CTS_ON)
1454 args[1] = CLRRTS;
1455 else
1456 args[1] = SETRTS;
1457 args[2]=(DWORD_PTR)hcom;
1458
1459 trace("test_WaitCts timeout %ld clt 0x%08lx handle %p\n",args[0], args[1], hcom);
1460
1461 ok(SetCommMask(hcom, EV_CTS), "SetCommMask failed\n");
1462 hComPortEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
1463 ok(hComPortEvent != 0, "CreateEvent failed\n");
1464 args[3] = (DWORD_PTR)hComPortEvent;
1465 alarmThread = CreateThread(NULL, 0, toggle_ctlLine, args, 0, &alarmThreadId);
1466 /* Wait a minimum to let the thread start up */
1467 Sleep(10);
1468 trace("Thread created\n");
1469 ok(alarmThread !=0 , "CreateThread Failed\n");
1470
1471 ZeroMemory( &overlapped, sizeof(overlapped));
1472 overlapped.hEvent = hComPortEvent;
1473 before = GetTickCount();
1474 success = WaitCommEvent(hcom, &evtmask, &overlapped);
1475 err = GetLastError();
1476 after = GetTickCount();
1477
1478 trace("Success 0x%08x err %d evtmask 0x%08x\n", success, err, evtmask);
1479 ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
1480 trace("overlapped WaitCommEvent returned.\n");
1481 if (!success && (err == ERROR_IO_PENDING))
1482 ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
1483 "WaitCts hComPortEvent failed\n");
1484 success = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
1485 err = GetLastError();
1486 after1 = GetTickCount();
1487 trace("Success 0x%08x err %d evtmask 0x%08x diff1 %d, diff2 %d\n",
1488 success, err, evtmask, after-before, after1-before);
1489
1490 ok(evtmask & EV_CTS, "Failed to detect EV_CTS: 0x%08x, expected 0x%08x\n",
1491 evtmask, EV_CTS);
1492 ok(GetCommModemStatus(hcom, &evtmask), "GetCommModemStatus failed\n");
1493 if(defaultStat & MS_CTS_ON)
1494 ok((evtmask & MS_CTS_ON) == 0,"CTS didn't change state!\n");
1495 else
1496 ok((evtmask & MS_CTS_ON), "CTS didn't change state!\n");
1497
1498 diff = after1 - before;
1499 ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
1500 "Unexpected time %d, expected around %d\n", diff, TIMEOUT>>1);
1501
1502 /*restore RTS Settings*/
1503 if(defaultStat & MS_CTS_ON)
1504 args[1] = SETRTS;
1505 else
1506 args[1] = CLRRTS;
1507
1508 CloseHandle(hcom);
1509 ok( !WaitForSingleObject( alarmThread, 10000 ), "thread still running\n" );
1510 CloseHandle( alarmThread );
1511}
1512
1513/* Change the Comm Mask while a Wait is going on
1514 WaitCommevent should return with a EVTMASK set to zero
1515*/
1517{
1518 DWORD_PTR *args = arg;
1519 DWORD timeout = args[0];
1520 HANDLE hcom = (HANDLE) args[1];
1521
1522 trace(" Changing CommMask on the fly for handle %p after timeout %d\n",
1523 hcom, timeout);
1524 Sleep(timeout);
1525 ok(SetCommMask(hcom, 0),"SetCommMask %p failed\n", hcom);
1526 trace("SetCommMask changed\n");
1527 return 0;
1528}
1529
1530/* Set up a Wait for a change on CTS. We don't toggle any line, but we
1531 reset the CommMask and expect the wait to return with a mask of 0
1532 No special port connections needed
1533*/
1534static void test_AbortWaitCts(void)
1535{
1536 DCB dcb;
1538 HANDLE hcom, hComPortEvent, alarmThread;
1539 DWORD_PTR args[2];
1540 DWORD alarmThreadId, before, after, after1, diff, success, err, written, evtmask=0;
1541
1542 hcom = test_OpenComm(TRUE);
1543 if (hcom == INVALID_HANDLE_VALUE) return;
1544
1545 ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
1546 if (dcb.fDtrControl == RTS_CONTROL_DISABLE)
1547 {
1548 trace("RTS_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
1549 CloseHandle(hcom);
1550 return;
1551 }
1552 args[0]= TIMEOUT >>1;
1553 args[1]= (DWORD_PTR)hcom;
1554
1555 trace("test_AbortWaitCts timeout %ld handle %p\n",args[0], hcom);
1556
1557 ok(SetCommMask(hcom, EV_CTS), "SetCommMask failed\n");
1558 hComPortEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
1559 ok(hComPortEvent != 0, "CreateEvent failed\n");
1560 alarmThread = CreateThread(NULL, 0, reset_CommMask, args, 0, &alarmThreadId);
1561 /* Wait a minimum to let the thread start up */
1562 Sleep(10);
1563 trace("Thread created\n");
1564 ok(alarmThread !=0 , "CreateThread Failed\n");
1565
1566 ZeroMemory( &overlapped, sizeof(overlapped));
1567 overlapped.hEvent = hComPortEvent;
1568 before = GetTickCount();
1569 success = WaitCommEvent(hcom, &evtmask, &overlapped);
1570 err = GetLastError();
1571 after = GetTickCount();
1572
1573 trace("Success 0x%08x err %d evtmask 0x%08x\n", success, err, evtmask);
1574 ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
1575 trace("overlapped WaitCommEvent returned.\n");
1576 if (!success && (err == ERROR_IO_PENDING))
1577 ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
1578 "AbortWaitCts hComPortEvent failed\n");
1579 success = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
1580 err = GetLastError();
1581 after1 = GetTickCount();
1582 trace("Success 0x%08x err %d evtmask 0x%08x diff1 %d, diff2 %d\n",
1583 success, err, evtmask, after-before, after1-before);
1584
1585 ok(evtmask == 0, "Incorrect EventMask 0x%08x returned on Wait aborted bu SetCommMask, expected 0x%08x\n",
1586 evtmask, 0);
1587 ok(GetCommModemStatus(hcom, &evtmask), "GetCommModemStatus failed\n");
1588 diff = after1 - before;
1589 ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
1590 "Unexpected time %d, expected around %d\n", diff, TIMEOUT>>1);
1591
1592 CloseHandle(hcom);
1593 ok( !WaitForSingleObject( alarmThread, 10000 ), "thread still running\n" );
1594 CloseHandle( alarmThread );
1595}
1596
1597/*
1598 * Wait for a change in DSR
1599 * Needs Loopback from DTR to DSR
1600 */
1601static void test_WaitDsr(void)
1602{
1603 DCB dcb;
1605 HANDLE hcom, hComPortEvent, alarmThread;
1606 DWORD_PTR args[3];
1607 DWORD alarmThreadId, before, after, after1, diff, success, err, written, evtmask=0, defaultStat = 0;
1608
1609 if (!loopback_dtr_dsr) return;
1610
1611 hcom = test_OpenComm(TRUE);
1612 if (hcom == INVALID_HANDLE_VALUE) return;
1613
1614 ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
1615 if (dcb.fDtrControl == DTR_CONTROL_DISABLE)
1616 {
1617 trace("DTR_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
1618 CloseHandle(hcom);
1619 return;
1620 }
1621 args[0]= TIMEOUT >>1;
1622 ok(GetCommModemStatus(hcom, &defaultStat), "GetCommModemStatus failed\n");
1623 if(defaultStat & MS_DSR_ON)
1624 args[1] = CLRDTR;
1625 else
1626 args[1] = SETDTR;
1627 args[2]= (DWORD_PTR)hcom;
1628
1629 trace("test_WaitDsr timeout %ld clt 0x%08lx handle %p\n",args[0], args[1], hcom);
1630
1631 ok(SetCommMask(hcom, EV_DSR), "SetCommMask failed\n");
1632 hComPortEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
1633 ok(hComPortEvent != 0, "CreateEvent failed\n");
1634 alarmThread = CreateThread(NULL, 0, toggle_ctlLine, args, 0, &alarmThreadId);
1635 ok(alarmThread !=0 , "CreateThread Failed\n");
1636
1637 ZeroMemory( &overlapped, sizeof(overlapped));
1638 overlapped.hEvent = hComPortEvent;
1639 before = GetTickCount();
1640 success = WaitCommEvent(hcom, &evtmask, &overlapped);
1641 err = GetLastError();
1642 after = GetTickCount();
1643
1644 trace("Success 0x%08x err %d evtmask 0x%08x\n", success, err, evtmask);
1645 ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
1646 trace("overlapped WaitCommEvent returned.\n");
1647 if (!success && (err == ERROR_IO_PENDING))
1648 ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
1649 "wait hComPortEvent failed\n");
1650 success = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
1651 err = GetLastError();
1652 after1 = GetTickCount();
1653 trace("Success 0x%08x err %d evtmask 0x%08x diff1 %d, diff2 %d\n",
1654 success, err, evtmask, after-before, after1-before);
1655
1656 ok(evtmask & EV_DSR, "Failed to detect EV_DSR: 0x%08x, expected 0x%08x\n",
1657 evtmask, EV_DSR);
1658 ok(GetCommModemStatus(hcom, &evtmask), "GetCommModemStatus failed\n");
1659 if(defaultStat & MS_DSR_ON)
1660 ok((evtmask & MS_DSR_ON) == 0,"DTR didn't change state!\n");
1661 else
1662 ok((evtmask & MS_DSR_ON), "DTR didn't change state!\n");
1663
1664 diff = after1 - before;
1665 ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
1666 "Unexpected time %d, expected around %d\n", diff, TIMEOUT>>1);
1667
1668 /*restore RTS Settings*/
1669 if(defaultStat & MS_DSR_ON)
1670 args[1] = SETDTR;
1671 else
1672 args[1] = CLRDTR;
1673
1674 CloseHandle(hcom);
1675 ok( !WaitForSingleObject( alarmThread, 10000 ), "thread still running\n" );
1676 CloseHandle( alarmThread );
1677}
1678
1679/*
1680 * Wait for a Ring
1681 * Needs Loopback from DTR to RING
1682 */
1683static void test_WaitRing(void)
1684{
1685 DCB dcb;
1687 HANDLE hcom, hComPortEvent, alarmThread;
1688 DWORD_PTR args[3];
1689 DWORD alarmThreadId, before, after, after1, diff, success, err, written, evtmask=0, defaultStat;
1690 BOOL ret;
1691
1692 if (!loopback_dtr_ring) return;
1693
1694 hcom = test_OpenComm(TRUE);
1695 if (hcom == INVALID_HANDLE_VALUE) return;
1696
1697 ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
1698 if (dcb.fDtrControl == DTR_CONTROL_DISABLE)
1699 {
1700 trace("DTR_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
1701 CloseHandle(hcom);
1702 return;
1703 }
1704 args[0]= TIMEOUT >>1;
1705 ok((ret = GetCommModemStatus(hcom, &defaultStat)), "GetCommModemStatus failed\n");
1706 if (!ret) {
1707 skip("modem status failed -> skip.\n");
1708 CloseHandle(hcom);
1709 return;
1710 }
1711 if(defaultStat & MS_RING_ON)
1712 args[1] = CLRDTR;
1713 else
1714 args[1] = SETDTR;
1715 args[2]=(DWORD_PTR) hcom;
1716
1717 trace("test_WaitRing timeout %ld clt 0x%08lx handle %p\n",args[0], args[1], hcom);
1718
1719 ok(SetCommMask(hcom, EV_RING), "SetCommMask failed\n");
1720 hComPortEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
1721 ok(hComPortEvent != 0, "CreateEvent failed\n");
1722 alarmThread = CreateThread(NULL, 0, toggle_ctlLine, args, 0, &alarmThreadId);
1723 ok(alarmThread !=0 , "CreateThread Failed\n");
1724
1725 ZeroMemory( &overlapped, sizeof(overlapped));
1726 overlapped.hEvent = hComPortEvent;
1727 before = GetTickCount();
1728 success = WaitCommEvent(hcom, &evtmask, &overlapped);
1729 err = GetLastError();
1730 after = GetTickCount();
1731
1732 trace("Success 0x%08x err %d evtmask 0x%08x\n", success, err, evtmask);
1733 ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
1734 trace("overlapped WaitCommEvent returned.\n");
1735 if (!success && (err == ERROR_IO_PENDING))
1736 ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
1737 "wait hComPortEvent failed\n");
1738 success = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
1739 err = GetLastError();
1740 after1 = GetTickCount();
1741 trace("Success 0x%08x err %d evtmask 0x%08x diff1 %d, diff2 %d\n",
1742 success, err, evtmask, after-before, after1-before);
1743
1744 ok(evtmask & EV_RING, "Failed to detect EV_RING: 0x%08x, expected 0x%08x\n",
1745 evtmask, EV_RING);
1746 ok(GetCommModemStatus(hcom, &evtmask), "GetCommModemStatus failed\n");
1747 if(defaultStat & MS_RING_ON)
1748 ok((evtmask & MS_RING_ON) == 0,"DTR didn't change state!\n");
1749 else
1750 ok((evtmask & MS_RING_ON), "DTR didn't change state!\n");
1751
1752 diff = after1 - before;
1753 ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
1754 "Unexpected time %d, expected around %d\n", diff, TIMEOUT>>1);
1755
1756 /*restore RTS Settings*/
1757 if(defaultStat & MS_RING_ON)
1758 args[1] = SETDTR;
1759 else
1760 args[1] = CLRDTR;
1761
1762 CloseHandle(hcom);
1763 ok( !WaitForSingleObject( alarmThread, 10000 ), "thread still running\n" );
1764 CloseHandle( alarmThread );
1765}
1766/*
1767 * Wait for a change in DCD
1768 * Needs Loopback from DTR to DCD
1769 */
1770static void test_WaitDcd(void)
1771{
1772 DCB dcb;
1774 HANDLE hcom, hComPortEvent, alarmThread;
1775 DWORD_PTR args[3];
1776 DWORD alarmThreadId, before, after, after1, diff, success, err, written, evtmask=0, defaultStat = 0;
1777
1778 if (!loopback_dtr_dcd) return;
1779
1780 hcom = test_OpenComm(TRUE);
1781 if (hcom == INVALID_HANDLE_VALUE) return;
1782
1783 ok(GetCommState(hcom, &dcb), "GetCommState failed\n");
1784 if (dcb.fDtrControl == DTR_CONTROL_DISABLE)
1785 {
1786 trace("DTR_CONTROL_HANDSHAKE is set, so don't manipulate DTR\n");
1787 CloseHandle(hcom);
1788 return;
1789 }
1790 args[0]= TIMEOUT >>1;
1791 ok(GetCommModemStatus(hcom, &defaultStat), "GetCommModemStatus failed\n");
1792 if(defaultStat & MS_RLSD_ON)
1793 args[1] = CLRDTR;
1794 else
1795 args[1] = SETDTR;
1796 args[2]= (DWORD_PTR)hcom;
1797
1798 trace("test_WaitDcd timeout %ld clt 0x%08lx handle %p\n",args[0], args[1], hcom);
1799
1800 ok(SetCommMask(hcom, EV_RLSD), "SetCommMask failed\n");
1801 hComPortEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
1802 ok(hComPortEvent != 0, "CreateEvent failed\n");
1803 alarmThread = CreateThread(NULL, 0, toggle_ctlLine, args, 0, &alarmThreadId);
1804 ok(alarmThread !=0 , "CreateThread Failed\n");
1805
1806 ZeroMemory( &overlapped, sizeof(overlapped));
1807 overlapped.hEvent = hComPortEvent;
1808 before = GetTickCount();
1809 success = WaitCommEvent(hcom, &evtmask, &overlapped);
1810 err = GetLastError();
1811 after = GetTickCount();
1812
1813 trace("Success 0x%08x err %d evtmask 0x%08x\n", success, err, evtmask);
1814 ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
1815 trace("overlapped WaitCommEvent returned.\n");
1816 if (!success && (err == ERROR_IO_PENDING))
1817 ok(WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE) == 0,
1818 "wait hComPortEvent failed\n");
1819 success = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
1820 err = GetLastError();
1821 after1 = GetTickCount();
1822 trace("Success 0x%08x err %d evtmask 0x%08x diff1 %d, diff2 %d\n",
1823 success, err, evtmask, after-before, after1-before);
1824
1825 ok(evtmask & EV_RLSD, "Failed to detect EV_RLSD: 0x%08x, expected 0x%08x\n",
1826 evtmask, EV_RLSD);
1827 ok(GetCommModemStatus(hcom, &evtmask), "GetCommModemStatus failed\n");
1828 if(defaultStat & MS_RLSD_ON)
1829 ok((evtmask & MS_RLSD_ON) == 0,"DTR didn't change state!\n");
1830 else
1831 ok((evtmask & MS_RLSD_ON), "DTR didn't change state!\n");
1832
1833 diff = after1 - before;
1834 ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
1835 "Unexpected time %d, expected around %d\n", diff, TIMEOUT>>1);
1836
1837 /*restore RTS Settings*/
1838 if(defaultStat & MS_RLSD_ON)
1839 args[1] = SETDTR;
1840 else
1841 args[1] = CLRDTR;
1842
1843 CloseHandle(hcom);
1844 ok( !WaitForSingleObject( alarmThread, 10000 ), "thread still running\n" );
1845 CloseHandle( alarmThread );
1846}
1847
1848/*
1849 Set Break after timeout
1850*/
1852{
1853 DWORD_PTR *args = arg;
1854 DWORD timeout = args[0];
1855 HANDLE hcom = (HANDLE) args[1];
1856
1857 trace("SetCommBreak for handle %p after timeout %d\n",
1858 hcom, timeout);
1859 Sleep(timeout);
1860 ok(SetCommBreak(hcom),"SetCommBreak %p failed\n", hcom);
1861 trace("SetCommBreak done\n");
1862 return 0;
1863}
1864
1865/*
1866 Wait for the Break condition (TX resp. RX active)
1867 Needs Loopback TX-RX
1868*/
1869static void test_WaitBreak(void)
1870{
1872 HANDLE hcom, hComPortEvent, alarmThread;
1873 DWORD_PTR args[2];
1874 DWORD alarmThreadId, before, after, after1, diff, success, err, written, evtmask=0;
1875
1876 if (!loopback_txd_rxd) return;
1877
1878 hcom = test_OpenComm(TRUE);
1879 if (hcom == INVALID_HANDLE_VALUE) return;
1880
1881 ok(SetCommMask(hcom, EV_BREAK), "SetCommMask failed\n");
1882 hComPortEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
1883 ok(hComPortEvent != 0, "CreateEvent failed\n");
1884
1885 trace("test_WaitBreak\n");
1886 args[0]= TIMEOUT >>1;
1887 args[1]= (DWORD_PTR)hcom;
1888 alarmThread = CreateThread(NULL, 0, set_CommBreak, args, 0, &alarmThreadId);
1889 /* Wait a minimum to let the thread start up */
1890 Sleep(10);
1891 trace("Thread created\n");
1892 ok(alarmThread !=0 , "CreateThread Failed\n");
1893
1894 ZeroMemory( &overlapped, sizeof(overlapped));
1895 overlapped.hEvent = hComPortEvent;
1896 before = GetTickCount();
1897 success = WaitCommEvent(hcom, &evtmask, &overlapped);
1898 err = GetLastError();
1899 after = GetTickCount();
1900
1901 trace("Success 0x%08x err %d evtmask 0x%08x\n", success, err, evtmask);
1902 ok(success || err == ERROR_IO_PENDING, "overlapped WaitCommEvent failed\n");
1903 trace("overlapped WaitCommEvent returned.\n");
1904
1905 if (!success && (err == ERROR_IO_PENDING))
1906 {
1907 success = WaitForSingleObjectEx(hComPortEvent, TIMEOUT, TRUE);
1908 ok(!success, "wait hComPortEvent res %d\n", GetLastError());
1909 }
1910 success = GetOverlappedResult(hcom, &overlapped, &written, FALSE);
1911 err = GetLastError();
1912 after1 = GetTickCount();
1913 trace("Success 0x%08x err %d evtmask 0x%08x diff1 %d, diff2 %d\n",
1914 success, err, evtmask, after-before, after1-before);
1915
1916 ok(evtmask & EV_BREAK, "Failed to detect EV_BREAK: 0x%08x, expected 0x%08x\n",
1917 evtmask, EV_BREAK);
1918 ok(GetCommModemStatus(hcom, &evtmask), "GetCommModemStatus failed\n");
1919
1920 diff = after1 - before;
1921 ok ((diff > (TIMEOUT>>1) -TIMEDELTA) && (diff < (TIMEOUT>>1) + TIMEDELTA),
1922 "Unexpected time %d, expected around %d\n", diff, TIMEOUT>>1);
1923
1924 ok(ClearCommBreak(hcom), "ClearCommBreak failed\n");
1925
1926 CloseHandle(hcom);
1927 ok( !WaitForSingleObject( alarmThread, 10000 ), "thread still running\n" );
1928 CloseHandle( alarmThread );
1929}
1930
1931static void test_stdio(void)
1932{
1933 DCB dcb;
1934
1935 /* cygwin tries this to determine the stdin handle type */
1936 ok( !GetCommState( GetStdHandle(STD_INPUT_HANDLE), &dcb ), "GetCommState succeeded on stdin\n" );
1938 "got error %u\n", GetLastError() );
1939}
1940
1941static void test_WaitCommEvent(void)
1942{
1943 HANDLE hcom;
1944 DWORD evtmask, ret, bytes, before, after, last_event_time;
1945 OVERLAPPED ovl_wait;
1946
1947 hcom = test_OpenComm(TRUE);
1948 if (hcom == INVALID_HANDLE_VALUE) return;
1949
1950 test_GetModemStatus(hcom);
1951
1952 ret = SetCommMask(hcom, 0x1fff);
1953 ok(ret, "SetCommMask error %d\n", GetLastError());
1954
1955 S(U(ovl_wait)).Offset = 0;
1956 S(U(ovl_wait)).OffsetHigh = 0;
1957 ovl_wait.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
1958
1959 trace("waiting 10 secs for com port events (turn on/off the device)...\n");
1960 last_event_time = 0;
1961 before = GetTickCount();
1962 do
1963 {
1964 evtmask = 0;
1965 SetLastError(0xdeadbeef);
1966 ret = WaitCommEvent(hcom, &evtmask, &ovl_wait);
1967 ok(!ret && GetLastError() == ERROR_IO_PENDING, "WaitCommEvent returned %d, error %d\n", ret, GetLastError());
1968 if (GetLastError() != ERROR_IO_PENDING) goto done; /* no point in further testing */
1969 for (;;)
1970 {
1971 ret = WaitForSingleObject(ovl_wait.hEvent, 500);
1972 after = GetTickCount();
1973 if (ret == WAIT_OBJECT_0)
1974 {
1975 last_event_time = after;
1976 ret = GetOverlappedResult(hcom, &ovl_wait, &bytes, FALSE);
1977 ok(ret, "GetOverlappedResult reported error %d\n", GetLastError());
1978 ok(bytes == sizeof(evtmask), "expected %u, written %u\n", (UINT)sizeof(evtmask), bytes);
1979 trace("WaitCommEvent: got events %#x\n", evtmask);
1980 test_GetModemStatus(hcom);
1981 break;
1982 }
1983 else
1984 {
1985 if (last_event_time || after - before >= 10000) goto done;
1986 }
1987 }
1988 } while (after - before < 10000);
1989
1990done:
1991 CloseHandle(ovl_wait.hEvent);
1992 CloseHandle(hcom);
1993}
1994
1995static void test_FlushFileBuffers(void)
1996{
1997 HANDLE hcom;
1998 DWORD ret, bytes, errors;
1999 COMSTAT stat;
2000
2001 hcom = test_OpenComm(FALSE);
2002 if (hcom == INVALID_HANDLE_VALUE) return;
2003
2004 ret = WriteFile(hcom, "\0\0\0\0\0\0\0", 7, &bytes, NULL);
2005 ok(ret, "WriteFile error %d\n", GetLastError());
2006 ok(bytes == 7, "expected 7, got %u\n", bytes);
2007
2008 ret = FlushFileBuffers(hcom);
2009 ok(ret, "FlushFileBuffers error %d\n", GetLastError());
2010
2011 ret = ClearCommError(hcom, &errors, &stat);
2012 ok(ret, "ClearCommError error %d\n", GetLastError());
2013 ok(stat.cbInQue == 0, "expected 0, got %d bytes in InQueue\n", stat.cbInQue);
2014 ok(stat.cbOutQue == 0, "expected 0, got %d bytes in OutQueue\n", stat.cbOutQue);
2015 ok(errors == 0, "expected errors 0, got %#x\n", errors);
2016
2017 CloseHandle(hcom);
2018}
2019
2020static void test_read_write(void)
2021{
2022 static const char atz[]="ATZ\r\n";
2023 char buf[256];
2024 HANDLE hcom;
2025 DCB dcb;
2027 DWORD ret, bytes, status, evtmask, before, after, last_event_time;
2028 OVERLAPPED ovl_wait;
2029 IO_STATUS_BLOCK iob;
2031 LONG i;
2032
2033 if (!pNtReadFile || !pNtWriteFile)
2034 {
2035 win_skip("not running on NT, skipping test\n");
2036 return;
2037 }
2038
2039 hcom = test_OpenComm(TRUE);
2040 if (hcom == INVALID_HANDLE_VALUE) return;
2041
2042 ret = GetCommState(hcom, &dcb);
2043 ok(ret, "GetCommState error %d\n", GetLastError());
2044 dcb.BaudRate = 9600;
2045 dcb.ByteSize = 8;
2046 dcb.Parity = NOPARITY;
2047 dcb.fRtsControl = RTS_CONTROL_ENABLE;
2048 dcb.fDtrControl = DTR_CONTROL_ENABLE;
2049 dcb.StopBits = ONESTOPBIT;
2050 ret = SetCommState(hcom, &dcb);
2051 ok(ret, "SetCommState error %d\n", GetLastError());
2052
2053 memset(&timeouts, 0, sizeof(timeouts));
2054 timeouts.ReadTotalTimeoutConstant = TIMEOUT;
2055 ret = SetCommTimeouts(hcom, &timeouts);
2056 ok(ret,"SetCommTimeouts error %d\n", GetLastError());
2057
2058 ret = SetupComm(hcom, 1024, 1024);
2059 ok(ret, "SetUpComm error %d\n", GetLastError());
2060
2061 bytes = 0xdeadbeef;
2062 SetLastError(0xdeadbeef);
2063 ret = WriteFile(hcom, atz, 0, &bytes, NULL);
2064 ok(!ret, "WriteFile should fail\n");
2065 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2066 ok(bytes == 0, "bytes %u\n", bytes);
2067
2068 U(iob).Status = -1;
2069 iob.Information = -1;
2070 status = pNtWriteFile(hcom, 0, NULL, NULL, &iob, atz, 0, NULL, NULL);
2071 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
2072 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2073 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
2074
2075 for (i = -20; i < 20; i++)
2076 {
2077 U(iob).Status = -1;
2078 iob.Information = -1;
2079 offset.QuadPart = (LONGLONG)i;
2080 status = pNtWriteFile(hcom, 0, NULL, NULL, &iob, atz, 0, &offset, NULL);
2081 if (i >= 0 || i == -1)
2082 {
2083 ok(status == STATUS_SUCCESS, "%d: expected STATUS_SUCCESS, got %#x\n", i, status);
2084 ok(U(iob).Status == STATUS_SUCCESS, "%d: expected STATUS_SUCCESS, got %#x\n", i, U(iob).Status);
2085 ok(iob.Information == 0, "%d: expected 0, got %lu\n", i, iob.Information);
2086 }
2087 else
2088 {
2089 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
2090 ok(U(iob).Status == -1, "%d: expected -1, got %#x\n", i, U(iob).Status);
2091 ok(iob.Information == -1, "%d: expected -1, got %ld\n", i, iob.Information);
2092 }
2093 }
2094
2095 U(iob).Status = -1;
2096 iob.Information = -1;
2097 offset.QuadPart = 0;
2098 status = pNtWriteFile(hcom, 0, NULL, NULL, &iob, atz, sizeof(atz), &offset, NULL);
2099 ok(status == STATUS_PENDING || status == STATUS_SUCCESS, "expected STATUS_PENDING or STATUS_SUCCESS, got %#x\n", status);
2100 /* Under Windows checking IO_STATUS_BLOCK right after the call leads
2101 * to races, iob.Status is either -1 or STATUS_SUCCESS, which means
2102 * that it's set only when the operation completes.
2103 */
2105 if (ret == WAIT_TIMEOUT)
2106 {
2107 skip("Probably modem is not connected.\n");
2108 CloseHandle(hcom);
2109 return;
2110 }
2111 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject error %d\n", ret);
2112 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2113 ok(iob.Information == sizeof(atz), "expected sizeof(atz), got %lu\n", iob.Information);
2114
2115 ret = SetCommMask(hcom, EV_RXCHAR);
2116 ok(ret, "SetCommMask error %d\n", GetLastError());
2117
2118 S(U(ovl_wait)).Offset = 0;
2119 S(U(ovl_wait)).OffsetHigh = 0;
2120 ovl_wait.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
2121
2122 trace("waiting 3 secs for modem response...\n");
2123 last_event_time = 0;
2124 before = GetTickCount();
2125 do
2126 {
2127 evtmask = 0;
2128 SetLastError(0xdeadbeef);
2129 ret = WaitCommEvent(hcom, &evtmask, &ovl_wait);
2130 ok(!ret && GetLastError() == ERROR_IO_PENDING, "WaitCommEvent returned %d, error %d\n", ret, GetLastError());
2131 if (GetLastError() != ERROR_IO_PENDING) goto done; /* no point in further testing */
2132 for (;;)
2133 {
2134 ret = WaitForSingleObject(ovl_wait.hEvent, 100);
2135 after = GetTickCount();
2136 if (ret == WAIT_OBJECT_0)
2137 {
2138 trace("got modem response.\n");
2139
2140 last_event_time = after;
2141 ret = GetOverlappedResult(hcom, &ovl_wait, &bytes, FALSE);
2142 ok(ret, "GetOverlappedResult reported error %d\n", GetLastError());
2143 ok(bytes == sizeof(evtmask), "expected sizeof(evtmask), got %u\n", bytes);
2144 ok(evtmask & EV_RXCHAR, "EV_RXCHAR should be set\n");
2145
2146 bytes = 0xdeadbeef;
2147 SetLastError(0xdeadbeef);
2148 ret = ReadFile(hcom, buf, 0, &bytes, NULL);
2149 ok(!ret, "ReadFile should fail\n");
2150 ok(GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
2151 ok(bytes == 0, "bytes %u\n", bytes);
2152
2153 U(iob).Status = -1;
2154 iob.Information = -1;
2155 status = pNtReadFile(hcom, 0, NULL, NULL, &iob, buf, 0, NULL, NULL);
2156 ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got %#x\n", status);
2157 ok(U(iob).Status == -1, "expected -1, got %#x\n", U(iob).Status);
2158 ok(iob.Information == -1, "expected -1, got %ld\n", iob.Information);
2159
2160 for (i = -20; i < 20; i++)
2161 {
2162 U(iob).Status = -1;
2163 iob.Information = -1;
2164 offset.QuadPart = (LONGLONG)i;
2165 status = pNtReadFile(hcom, 0, NULL, NULL, &iob, buf, 0, &offset, NULL);
2166 if (i >= 0)
2167 {
2168 ok(status == STATUS_SUCCESS, "%d: expected STATUS_SUCCESS, got %#x\n", i, status);
2169 ok(U(iob).Status == STATUS_SUCCESS, "%d: expected STATUS_SUCCESS, got %#x\n", i, U(iob).Status);
2170 ok(iob.Information == 0, "%d: expected 0, got %lu\n", i, iob.Information);
2171 }
2172 else
2173 {
2174 ok(status == STATUS_INVALID_PARAMETER, "%d: expected STATUS_INVALID_PARAMETER, got %#x\n", i, status);
2175 ok(U(iob).Status == -1, "%d: expected -1, got %#x\n", i, U(iob).Status);
2176 ok(iob.Information == -1, "%d: expected -1, got %ld\n", i, iob.Information);
2177 }
2178 }
2179
2180 U(iob).Status = -1;
2181 iob.Information = -1;
2182 offset.QuadPart = 0;
2183 status = pNtReadFile(hcom, 0, NULL, NULL, &iob, buf, 1, &offset, NULL);
2184 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", status);
2185 ok(U(iob).Status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %#x\n", U(iob).Status);
2186 ok(iob.Information == 1, "expected 1, got %lu\n", iob.Information);
2187 goto done;
2188 }
2189 else
2190 {
2191 if (last_event_time || after - before >= 3000) goto done;
2192 }
2193 }
2194 } while (after - before < 3000);
2195
2196done:
2197 CloseHandle(ovl_wait.hEvent);
2198 CloseHandle(hcom);
2199}
2200
2202{
2203 HMODULE ntdll = GetModuleHandleA("ntdll.dll");
2204 if (ntdll)
2205 {
2206 pNtReadFile = (void *)GetProcAddress(ntdll, "NtReadFile");
2207 pNtWriteFile = (void *)GetProcAddress(ntdll, "NtWriteFile");
2208 }
2209
2210 test_ClearCommError(); /* keep it the very first test */
2221 test_WaitRx();
2222 test_WaitCts();
2224 test_WaitDsr();
2225 test_WaitRing();
2226 test_WaitDcd();
2228 test_stdio();
2230
2232 {
2233 skip("interactive tests (set WINETEST_INTERACTIVE=1)\n");
2234 return;
2235 }
2236
2238}
#define broken(x)
Definition: _sntprintf.h:21
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define stat
Definition: acwin.h:99
#define read
Definition: acwin.h:96
static unsigned char bytes[4]
Definition: adnsresfilter.c:74
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define U(x)
Definition: wordpad.c:45
struct timeout * timeouts
Definition: dispatch.c:57
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define ERROR_IO_PENDING
Definition: dderror.h:15
#define ERROR_INVALID_FUNCTION
Definition: dderror.h:6
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NTSTATUS
Definition: precomp.h:21
#define CloseHandle
Definition: compat.h:739
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define CP_ACP
Definition: compat.h:109
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define SetLastError(x)
Definition: compat.h:752
#define GetProcAddress(x, y)
Definition: compat.h:753
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define GENERIC_READ
Definition: compat.h:135
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define CALLBACK
Definition: compat.h:35
#define MultiByteToWideChar
Definition: compat.h:110
BOOL WINAPI FlushFileBuffers(IN HANDLE hFile)
Definition: fileinfo.c:25
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
BOOL WINAPI GetDefaultCommConfigA(LPCSTR lpszName, LPCOMMCONFIG lpCC, LPDWORD lpdwSize)
Definition: comm.c:1436
BOOL WINAPI BuildCommDCBAndTimeoutsW(LPCWSTR devid, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
Definition: comm.c:476
BOOL WINAPI SetCommBreak(HANDLE handle)
Definition: comm.c:557
BOOL WINAPI SetCommTimeouts(HANDLE hComm, LPCOMMTIMEOUTS lptimeouts)
Definition: comm.c:1062
BOOL WINAPI SetupComm(HANDLE handle, DWORD insize, DWORD outsize)
Definition: comm.c:718
BOOL WINAPI SetCommMask(HANDLE handle, DWORD evtmask)
Definition: comm.c:768
BOOL WINAPI SetCommState(HANDLE handle, LPDCB lpdcb)
Definition: comm.c:807
BOOL WINAPI GetCommState(HANDLE handle, LPDCB lpdcb)
Definition: comm.c:904
BOOL WINAPI BuildCommDCBA(LPCSTR device, LPDCB lpdcb)
Definition: comm.c:429
BOOL WINAPI BuildCommDCBW(LPCWSTR devid, LPDCB lpdcb)
Definition: comm.c:533
BOOL WINAPI GetCommModemStatus(HANDLE hFile, LPDWORD lpModemStat)
Definition: comm.c:1099
BOOL WINAPI BuildCommDCBAndTimeoutsA(LPCSTR device, LPDCB lpdcb, LPCOMMTIMEOUTS lptimeouts)
Definition: comm.c:447
BOOL WINAPI EscapeCommFunction(HANDLE handle, DWORD func)
Definition: comm.c:602
BOOL WINAPI ClearCommBreak(HANDLE handle)
Definition: comm.c:580
BOOL WINAPI WaitCommEvent(HANDLE hFile, LPDWORD lpdwEvents, LPOVERLAPPED lpOverlapped)
Definition: comm.c:1123
BOOL WINAPI ClearCommError(HANDLE handle, LPDWORD errors, LPCOMSTAT lpStat)
Definition: comm.c:663
PWSTR StopBits[]
Definition: serial.c:37
USHORT port
Definition: uri.c:228
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
Status
Definition: gdiplustypes.h:25
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint64EXT * result
Definition: glext.h:11304
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
BOOL WINAPI GetOverlappedResult(IN HANDLE hFile, IN LPOVERLAPPED lpOverlapped, OUT LPDWORD lpNumberOfBytesTransferred, IN BOOL bWait)
Definition: iocompl.c:221
#define comm
Definition: kernel32.h:11
#define FILE_FLAG_OVERLAPPED
Definition: disk.h:46
static PVOID ptr
Definition: dispmode.c:27
static HANDLE PIO_APC_ROUTINE void PIO_STATUS_BLOCK void ULONG PLARGE_INTEGER PULONG key
Definition: comm.c:57
static void test_BuildCommDCBAndTimeoutsA(const char *string, const TEST *ptest, int initial_value, const DCB *pexpected_dcb, const COMMTIMEOUTS *pexpected_timeouts)
Definition: comm.c:559
static void test_stdio(void)
Definition: comm.c:1931
static void test_WaitCts(void)
Definition: comm.c:1428
static HANDLE PIO_APC_ROUTINE void PIO_STATUS_BLOCK io_status
Definition: comm.c:56
#define LOOPBACK_TXD_RXD
Definition: comm.c:38
#define TIMEDELTA
Definition: comm.c:33
static BOOL loopback_dtr_dsr
Definition: comm.c:50
static HANDLE test_OpenComm(BOOL doOverlap)
Definition: comm.c:689
#define LOOPBACK_DTR_RING
Definition: comm.c:41
static HANDLE hEvent
Definition: comm.c:54
static const TEST test[]
Definition: comm.c:73
static void test_ReadTimeOut(void)
Definition: comm.c:749
static void test_LoopbackDtrRing(void)
Definition: comm.c:1274
static void test_waittxempty(void)
Definition: comm.c:790
#define FASTBAUD
Definition: comm.c:32
static void test_BuildCommDCBW(const char *string, const TEST *ptest, int initial_value, const DCB *pexpected_dcb)
Definition: comm.c:578
#define LOOPBACK_CTS_RTS
Definition: comm.c:39
#define TIMEOUT
Definition: comm.c:30
static DWORD CALLBACK toggle_ctlLine(LPVOID arg)
Definition: comm.c:1404
static DWORD CALLBACK reset_CommMask(LPVOID arg)
Definition: comm.c:1516
static HANDLE PIO_APC_ROUTINE void * apc_user
Definition: comm.c:55
static void test_WaitBreak(void)
Definition: comm.c:1869
#define TEST_COUNT
Definition: comm.c:413
static DWORD CALLBACK set_CommBreak(LPVOID arg)
Definition: comm.c:1851
#define LOOPBACK_DTR_DSR
Definition: comm.c:40
static void test_BuildCommDCB(void)
Definition: comm.c:635
static void check_timeouts(const char *function, const TEST *ptest, int initial_value, const COMMTIMEOUTS *ptimeouts1, const COMMTIMEOUTS *ptimeouts2)
Definition: comm.c:534
static BOOL loopback_dtr_dcd
Definition: comm.c:52
static void test_BuildCommDCBAndTimeoutsW(const char *string, const TEST *ptest, int initial_value, const DCB *pexpected_dcb, const COMMTIMEOUTS *pexpected_timeouts)
Definition: comm.c:605
static void test_BuildCommDCBA(const char *string, const TEST *ptest, int initial_value, const DCB *pexpected_dcb)
Definition: comm.c:543
#define check_timeouts_member(a)
Definition: comm.c:532
static BOOL loopback_rts_cts
Definition: comm.c:49
static HANDLE PIO_APC_ROUTINE void PIO_STATUS_BLOCK void ULONG PLARGE_INTEGER offset
Definition: comm.c:57
static HANDLE PIO_APC_ROUTINE apc
Definition: comm.c:55
static void test_GetModemStatus(HANDLE hcom)
Definition: comm.c:736
#define check_dcb_member(a, b)
Definition: comm.c:459
static void test_WaitRing(void)
Definition: comm.c:1683
static void test_LoopbackRead(void)
Definition: comm.c:1023
static void test_LoopbackDtrDsr(void)
Definition: comm.c:1226
static void test_LoopbackCtsRts(void)
Definition: comm.c:1129
static void test_FlushFileBuffers(void)
Definition: comm.c:1995
#define SLOWBAUD
Definition: comm.c:31
#define check_dcb_member2(a, c, b)
Definition: comm.c:460
static void test_WaitRx(void)
Definition: comm.c:1329
static void check_dcb(const char *function, const TEST *ptest, int initial_value, const DCB *pdcb1, const DCB *pdcb2)
Definition: comm.c:462
static void check_result(const char *function, const TEST *ptest, int initial_value, BOOL result)
Definition: comm.c:450
static void test_WaitDsr(void)
Definition: comm.c:1601
static void test_WaitDcd(void)
Definition: comm.c:1770
static void test_AbortWaitCts(void)
Definition: comm.c:1534
static HANDLE PIO_APC_ROUTINE void PIO_STATUS_BLOCK void * buffer
Definition: comm.c:56
static BOOL loopback_txd_rxd
Definition: comm.c:48
static void test_non_pending_errors(void)
Definition: comm.c:1005
static void test_read_write(void)
Definition: comm.c:2020
static BOOL loopback_dtr_ring
Definition: comm.c:51
static HANDLE PIO_APC_ROUTINE void PIO_STATUS_BLOCK void ULONG length
Definition: comm.c:56
static void test_ClearCommError(void)
Definition: comm.c:988
static void test_WaitCommEvent(void)
Definition: comm.c:1941
#define LOOPBACK_DTR_DCD
Definition: comm.c:42
static void test_LoopbackDtrDcd(void)
Definition: comm.c:1178
_In_ HANDLE hFile
Definition: mswsock.h:90
unsigned int UINT
Definition: ndis.h:50
#define GENERIC_WRITE
Definition: nt_native.h:90
VOID(* PIO_APC_ROUTINE)(IN PVOID ApcContext, IN PIO_STATUS_BLOCK IoStatusBlock, IN ULONG Reserved)
Definition: nt_native.h:877
#define STATUS_PENDING
Definition: ntstatus.h:82
long LONG
Definition: pedump.c:60
#define err(...)
#define win_skip
Definition: test.h:163
int winetest_interactive
#define S(x)
Definition: test.h:220
#define memset(x, y, z)
Definition: compat.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED * overlapped
Definition: sock.c:81
Definition: comm.c:65
BOOL old_style
Definition: comm.c:68
DCB dcb1
Definition: comm.c:69
char string[100]
Definition: comm.c:66
COMMTIMEOUTS timeouts1
Definition: comm.c:70
BOOL result
Definition: comm.c:67
DWORD cbInQue
Definition: winbase.h:725
DWORD cbOutQue
Definition: winbase.h:726
Definition: cdstruc.h:902
HANDLE hEvent
Definition: winbase.h:820
Definition: match.c:390
Definition: stat.h:55
Definition: ps.c:97
Definition: dhcpd.h:245
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
DWORD WINAPI WaitForSingleObjectEx(IN HANDLE hHandle, IN DWORD dwMilliseconds, IN BOOL bAlertable)
Definition: synch.c:94
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
__inline int before(__u32 seq1, __u32 seq2)
Definition: tcpcore.h:2390
__inline int after(__u32 seq1, __u32 seq2)
Definition: tcpcore.h:2395
#define DWORD_PTR
Definition: treelist.c:76
uint32_t * PULONG
Definition: typedefs.h:59
uint32_t DWORD_PTR
Definition: typedefs.h:65
int64_t LONGLONG
Definition: typedefs.h:68
PVOID HANDLE
Definition: typedefs.h:73
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
int ret
#define success(from, fromstr, to, tostr)
struct _COMM_CONFIG COMMCONFIG
#define ZeroMemory
Definition: winbase.h:1712
#define CLRRTS
Definition: winbase.h:225
#define STD_INPUT_HANDLE
Definition: winbase.h:267
#define RTS_CONTROL_ENABLE
Definition: winbase.h:537
#define MS_RING_ON
Definition: winbase.h:531
#define CE_MODE
Definition: winbase.h:139
#define DTR_CONTROL_HANDSHAKE
Definition: winbase.h:535
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define MS_DSR_ON
Definition: winbase.h:530
#define ONESTOPBIT
Definition: winbase.h:458
#define CLRDTR
Definition: winbase.h:224
#define RTS_CONTROL_HANDSHAKE
Definition: winbase.h:538
#define EV_RXCHAR
Definition: winbase.h:436
#define SETDTR
Definition: winbase.h:226
#define EV_TXEMPTY
Definition: winbase.h:438
#define DTR_CONTROL_DISABLE
Definition: winbase.h:533
#define EV_BREAK
Definition: winbase.h:426
#define RTS_CONTROL_DISABLE
Definition: winbase.h:536
#define DTR_CONTROL_ENABLE
Definition: winbase.h:534
#define MS_RLSD_ON
Definition: winbase.h:532
#define EV_RLSD
Definition: winbase.h:434
#define EV_RING
Definition: winbase.h:433
#define MS_CTS_ON
Definition: winbase.h:529
#define WAIT_OBJECT_0
Definition: winbase.h:406
#define NOPARITY
Definition: winbase.h:453
#define EV_DSR
Definition: winbase.h:428
#define EV_CTS
Definition: winbase.h:427
#define SETRTS
Definition: winbase.h:227
void * arg
Definition: msvc.h:10
#define WINAPI
Definition: msvc.h:6
#define ERROR_NOT_READY
Definition: winerror.h:124
_IRQL_requires_same_ _In_ CLONG ByteSize
Definition: rtltypes.h:412
__wchar_t WCHAR
Definition: xmlstorage.h:180