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