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