Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

470 lines
10 KiB

  1. #include <string.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include "nt.h"
  5. #include "ntrtl.h"
  6. #include "nturtl.h"
  7. #include "ntddser.h"
  8. #include "windows.h"
  9. void main(int argc,char *argv[]) {
  10. HANDLE hFile;
  11. DCB MyDcb;
  12. char *MyPort = "COM1";
  13. DWORD NumberActuallyWritten;
  14. DWORD NumberToWrite = 1000;
  15. DWORD UseBaud = 1200;
  16. DWORD NumberOfDataBits = 8;
  17. COMMTIMEOUTS To;
  18. OVERLAPPED WriteOl = {0};
  19. BOOL WriteDone;
  20. char Char = 'z';
  21. int j;
  22. HANDLE Evt1;
  23. HANDLE Evt2;
  24. HANDLE Evt3;
  25. HANDLE Evt4;
  26. HANDLE Evt5;
  27. SERIAL_XOFF_COUNTER Xc1 = {10000,10,'a'};
  28. SERIAL_XOFF_COUNTER Xc2 = {10000,10,'b'};
  29. SERIAL_XOFF_COUNTER Xc3 = {10000,10,'c'};
  30. SERIAL_XOFF_COUNTER Xc4 = {10000,10,'d'};
  31. SERIAL_XOFF_COUNTER Xc5 = {10000,10,'e'};
  32. IO_STATUS_BLOCK Iosb1;
  33. IO_STATUS_BLOCK Iosb2;
  34. IO_STATUS_BLOCK Iosb3;
  35. IO_STATUS_BLOCK Iosb4;
  36. IO_STATUS_BLOCK Iosb5;
  37. NTSTATUS Status1;
  38. NTSTATUS Status2;
  39. NTSTATUS Status3;
  40. NTSTATUS Status4;
  41. NTSTATUS Status5;
  42. UNREFERENCED_PARAMETER(argc);
  43. UNREFERENCED_PARAMETER(argv);
  44. if (!(WriteOl.hEvent = CreateEvent(
  45. NULL,
  46. FALSE,
  47. FALSE,
  48. NULL
  49. ))) {
  50. printf("Could not create the write event.\n");
  51. exit(1);
  52. } else {
  53. WriteOl.Internal = 0;
  54. WriteOl.InternalHigh = 0;
  55. WriteOl.Offset = 0;
  56. WriteOl.OffsetHigh = 0;
  57. }
  58. if ((hFile = CreateFile(
  59. MyPort,
  60. GENERIC_READ | GENERIC_WRITE,
  61. 0,
  62. NULL,
  63. CREATE_ALWAYS,
  64. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
  65. NULL
  66. )) == ((HANDLE)-1)) {
  67. printf("Couldn't open the comm port\n");
  68. exit(1);
  69. }
  70. To.ReadIntervalTimeout = 0;
  71. To.ReadTotalTimeoutMultiplier = ((1000+(((UseBaud+9)/10)-1))/((UseBaud+9)/10));
  72. if (!To.ReadTotalTimeoutMultiplier) {
  73. To.ReadTotalTimeoutMultiplier = 1;
  74. }
  75. To.WriteTotalTimeoutMultiplier = ((1000+(((UseBaud+9)/10)-1))/((UseBaud+9)/10));
  76. if (!To.WriteTotalTimeoutMultiplier) {
  77. To.WriteTotalTimeoutMultiplier = 1;
  78. }
  79. To.ReadTotalTimeoutConstant = 5000;
  80. To.WriteTotalTimeoutConstant = 5000;
  81. if (!SetCommTimeouts(
  82. hFile,
  83. &To
  84. )) {
  85. printf("Couldn't set the timeouts\n");
  86. exit(1);
  87. }
  88. //
  89. // We've successfully opened the file. Set the state of
  90. // the comm device. First we get the old values and
  91. // adjust to our own.
  92. //
  93. if (!GetCommState(
  94. hFile,
  95. &MyDcb
  96. )) {
  97. printf("Couldn't get the comm state: %d\n",GetLastError());
  98. exit(1);
  99. }
  100. MyDcb.BaudRate = UseBaud;
  101. MyDcb.ByteSize = (BYTE)NumberOfDataBits;
  102. MyDcb.Parity = NOPARITY;
  103. MyDcb.StopBits = ONESTOPBIT;
  104. if (!SetCommState(
  105. hFile,
  106. &MyDcb
  107. )) {
  108. printf("Couldn't set the comm state.\n");
  109. exit(1);
  110. }
  111. //
  112. // Create 5 event handles to use to process the
  113. // vdm ioctls.
  114. //
  115. if (!(Evt1 = CreateEvent(NULL,
  116. FALSE,
  117. FALSE,
  118. NULL))) {
  119. printf("Couldn't create event 1\n");
  120. exit(1);
  121. }
  122. if (!(Evt2 = CreateEvent(NULL,
  123. FALSE,
  124. FALSE,
  125. NULL))) {
  126. printf("Couldn't create event 2\n");
  127. exit(1);
  128. }
  129. if (!(Evt3 = CreateEvent(NULL,
  130. FALSE,
  131. FALSE,
  132. NULL))) {
  133. printf("Couldn't create event 3\n");
  134. exit(1);
  135. }
  136. if (!(Evt4 = CreateEvent(NULL,
  137. FALSE,
  138. FALSE,
  139. NULL))) {
  140. printf("Couldn't create event 4\n");
  141. exit(1);
  142. }
  143. if (!(Evt5 = CreateEvent(NULL,
  144. FALSE,
  145. FALSE,
  146. NULL))) {
  147. printf("Couldn't create event 5\n");
  148. exit(1);
  149. }
  150. //
  151. // Start up the vdm ioctl and give it a second to get well
  152. // established as a counter.
  153. //
  154. Status1 = NtDeviceIoControlFile(
  155. hFile,
  156. Evt1,
  157. NULL,
  158. NULL,
  159. &Iosb1,
  160. IOCTL_SERIAL_XOFF_COUNTER,
  161. &Xc1,
  162. sizeof(SERIAL_XOFF_COUNTER),
  163. NULL,
  164. 0
  165. );
  166. if ( Status1 != STATUS_PENDING) {
  167. printf("1: Non pending status: %x\n",Status1);
  168. exit(1);
  169. }
  170. Sleep(1000);
  171. //
  172. // Do the second vdm ioctl. Wait one second then test to
  173. // make sure that the first one is finished by checking
  174. // its event handle. Then make sure that it was killed
  175. // because of writes
  176. //
  177. Status2 = NtDeviceIoControlFile(
  178. hFile,
  179. Evt2,
  180. NULL,
  181. NULL,
  182. &Iosb2,
  183. IOCTL_SERIAL_XOFF_COUNTER,
  184. &Xc2,
  185. sizeof(SERIAL_XOFF_COUNTER),
  186. NULL,
  187. 0
  188. );
  189. if ( Status2 != STATUS_PENDING) {
  190. printf("2: Non pending status: %x\n",Status1);
  191. exit(1);
  192. }
  193. //
  194. // Wait up to a second for the first one to be killed.
  195. //
  196. if (WaitForSingleObject(Evt1,1000)) {
  197. printf("Evt1 has not attained a signalled state.\n");
  198. exit(1);
  199. }
  200. if (Iosb1.Status != STATUS_SERIAL_MORE_WRITES) {
  201. printf("Iosb1 not more writes: %x\n",Iosb1.Status);
  202. exit(1);
  203. }
  204. //
  205. // Start up an 1 character asynchronous write and wait for a second and
  206. // the make sure that the previous vdm ioctl is done.
  207. //
  208. WriteDone = WriteFile(
  209. hFile,
  210. &Char,
  211. 1,
  212. &NumberActuallyWritten,
  213. &WriteOl
  214. );
  215. if (!WriteDone) {
  216. DWORD LastError;
  217. LastError = GetLastError();
  218. if (LastError != ERROR_IO_PENDING) {
  219. printf("Couldn't write the %s device.\n",MyPort);
  220. printf("Status of failed write is: %x\n",LastError);
  221. exit(1);
  222. }
  223. }
  224. if (WaitForSingleObject(Evt2,1000)) {
  225. printf("Evt2 has not attained a signalled state.\n");
  226. exit(1);
  227. }
  228. if (Iosb2.Status != STATUS_SERIAL_MORE_WRITES) {
  229. printf("Iosb2 not more writes: %x\n",Iosb2.Status);
  230. exit(1);
  231. }
  232. //
  233. // Wait up to 10 seconds for the write to finish.
  234. //
  235. if (WaitForSingleObject(WriteOl.hEvent,10000)) {
  236. printf("The write never finished\n");
  237. exit(1);
  238. }
  239. //
  240. // Set up a third vdm ioctl as before.
  241. //
  242. Status3 = NtDeviceIoControlFile(
  243. hFile,
  244. Evt3,
  245. NULL,
  246. NULL,
  247. &Iosb3,
  248. IOCTL_SERIAL_XOFF_COUNTER,
  249. &Xc3,
  250. sizeof(SERIAL_XOFF_COUNTER),
  251. NULL,
  252. 0
  253. );
  254. if ( Status3 != STATUS_PENDING) {
  255. printf("3: Non pending status: %x\n",Status3);
  256. exit(1);
  257. }
  258. //
  259. // Set up a fourth vdm ioctl, make sure that the previous ioctl
  260. // has been killed. Then wait for 15 seconds and then make sure
  261. // that the fourth vdm ioctl is finished and that it finished
  262. // due to the timer expiring before the the counter expired
  263. //
  264. Status4 = NtDeviceIoControlFile(
  265. hFile,
  266. Evt4,
  267. NULL,
  268. NULL,
  269. &Iosb4,
  270. IOCTL_SERIAL_XOFF_COUNTER,
  271. &Xc4,
  272. sizeof(SERIAL_XOFF_COUNTER),
  273. NULL,
  274. 0
  275. );
  276. if ( Status4 != STATUS_PENDING) {
  277. printf("4: Non pending status: %x\n",Status4);
  278. exit(1);
  279. }
  280. if (WaitForSingleObject(Evt3,1000)) {
  281. printf("Evt3 has not attained a signalled state.\n");
  282. exit(1);
  283. }
  284. if (Iosb3.Status != STATUS_SERIAL_MORE_WRITES) {
  285. printf("Iosb3 not more writes: %x\n",Iosb3.Status);
  286. exit(1);
  287. }
  288. //
  289. // Wait up to one second beyond the countdown timeout.
  290. //
  291. printf("Waiting %d seconds for the timer to time out.\n",(Xc4.Timeout+1000)/1000);
  292. if (WaitForSingleObject(Evt4,Xc4.Timeout+1000)) {
  293. printf("Evt4 has not attained a signalled state.\n");
  294. exit(1);
  295. }
  296. printf("Done with the timeout.\n");
  297. if (Iosb4.Status != STATUS_SERIAL_COUNTER_TIMEOUT) {
  298. printf("Iosb4 not counter timeout: %x\n",Iosb4.Status);
  299. exit(1);
  300. }
  301. //
  302. // Set up a fifth vdm ioctl, with a counter of ten,
  303. // then do 15 transmit immediate writes. If a loopback
  304. // connector is connected to the port then the characters
  305. // will then be received. This should cause the counter to
  306. // count down and cause the vdm ioctl to complete with
  307. // status success.
  308. //
  309. // NOTE NOTE: Transmit immediates DO NOT cause vdm ioctls
  310. // to complete with a status of MORE_WRITES.
  311. //
  312. Status5 = NtDeviceIoControlFile(
  313. hFile,
  314. Evt5,
  315. NULL,
  316. NULL,
  317. &Iosb5,
  318. IOCTL_SERIAL_XOFF_COUNTER,
  319. &Xc5,
  320. sizeof(SERIAL_XOFF_COUNTER),
  321. NULL,
  322. 0
  323. );
  324. if ( Status5 != STATUS_PENDING) {
  325. printf("5: Non pending status: %x\n",Status5);
  326. exit(1);
  327. }
  328. for (
  329. j = 0;
  330. j < Xc5.Counter+5;
  331. j++
  332. ) {
  333. if (!TransmitCommChar(hFile,'u')) {
  334. printf("A transmit comm char failed: %d\n",j);
  335. exit(1);
  336. }
  337. }
  338. //
  339. // Well we'll give it at least a second.
  340. //
  341. if (WaitForSingleObject(Evt5,1000)) {
  342. printf("Evt5 has not attained a signalled state.\n");
  343. exit(1);
  344. }
  345. if (Iosb5.Status != STATUS_SUCCESS) {
  346. printf("Iosb5 not SUCCEESS: %x\n",Iosb5.Status);
  347. exit(1);
  348. }
  349. }