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