NT4/private/ntos/dd/serial/tvdm.c
2020-09-30 17:12:29 +02:00

471 lines
10 KiB
C

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "nt.h"
#include "ntrtl.h"
#include "nturtl.h"
#include "ntddser.h"
#include "windows.h"
void main(int argc,char *argv[]) {
HANDLE hFile;
DCB MyDcb;
char *MyPort = "COM1";
DWORD NumberActuallyWritten;
DWORD NumberToWrite = 1000;
DWORD UseBaud = 1200;
DWORD NumberOfDataBits = 8;
COMMTIMEOUTS To;
OVERLAPPED WriteOl = {0};
BOOL WriteDone;
char Char = 'z';
int j;
HANDLE Evt1;
HANDLE Evt2;
HANDLE Evt3;
HANDLE Evt4;
HANDLE Evt5;
SERIAL_XOFF_COUNTER Xc1 = {10000,10,'a'};
SERIAL_XOFF_COUNTER Xc2 = {10000,10,'b'};
SERIAL_XOFF_COUNTER Xc3 = {10000,10,'c'};
SERIAL_XOFF_COUNTER Xc4 = {10000,10,'d'};
SERIAL_XOFF_COUNTER Xc5 = {10000,10,'e'};
IO_STATUS_BLOCK Iosb1;
IO_STATUS_BLOCK Iosb2;
IO_STATUS_BLOCK Iosb3;
IO_STATUS_BLOCK Iosb4;
IO_STATUS_BLOCK Iosb5;
NTSTATUS Status1;
NTSTATUS Status2;
NTSTATUS Status3;
NTSTATUS Status4;
NTSTATUS Status5;
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
if (!(WriteOl.hEvent = CreateEvent(
NULL,
FALSE,
FALSE,
NULL
))) {
printf("Could not create the write event.\n");
exit(1);
} else {
WriteOl.Internal = 0;
WriteOl.InternalHigh = 0;
WriteOl.Offset = 0;
WriteOl.OffsetHigh = 0;
}
if ((hFile = CreateFile(
MyPort,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL
)) == ((HANDLE)-1)) {
printf("Couldn't open the comm port\n");
exit(1);
}
To.ReadIntervalTimeout = 0;
To.ReadTotalTimeoutMultiplier = ((1000+(((UseBaud+9)/10)-1))/((UseBaud+9)/10));
if (!To.ReadTotalTimeoutMultiplier) {
To.ReadTotalTimeoutMultiplier = 1;
}
To.WriteTotalTimeoutMultiplier = ((1000+(((UseBaud+9)/10)-1))/((UseBaud+9)/10));
if (!To.WriteTotalTimeoutMultiplier) {
To.WriteTotalTimeoutMultiplier = 1;
}
To.ReadTotalTimeoutConstant = 5000;
To.WriteTotalTimeoutConstant = 5000;
if (!SetCommTimeouts(
hFile,
&To
)) {
printf("Couldn't set the timeouts\n");
exit(1);
}
//
// We've successfully opened the file. Set the state of
// the comm device. First we get the old values and
// adjust to our own.
//
if (!GetCommState(
hFile,
&MyDcb
)) {
printf("Couldn't get the comm state: %d\n",GetLastError());
exit(1);
}
MyDcb.BaudRate = UseBaud;
MyDcb.ByteSize = (BYTE)NumberOfDataBits;
MyDcb.Parity = NOPARITY;
MyDcb.StopBits = ONESTOPBIT;
if (!SetCommState(
hFile,
&MyDcb
)) {
printf("Couldn't set the comm state.\n");
exit(1);
}
//
// Create 5 event handles to use to process the
// vdm ioctls.
//
if (!(Evt1 = CreateEvent(NULL,
FALSE,
FALSE,
NULL))) {
printf("Couldn't create event 1\n");
exit(1);
}
if (!(Evt2 = CreateEvent(NULL,
FALSE,
FALSE,
NULL))) {
printf("Couldn't create event 2\n");
exit(1);
}
if (!(Evt3 = CreateEvent(NULL,
FALSE,
FALSE,
NULL))) {
printf("Couldn't create event 3\n");
exit(1);
}
if (!(Evt4 = CreateEvent(NULL,
FALSE,
FALSE,
NULL))) {
printf("Couldn't create event 4\n");
exit(1);
}
if (!(Evt5 = CreateEvent(NULL,
FALSE,
FALSE,
NULL))) {
printf("Couldn't create event 5\n");
exit(1);
}
//
// Start up the vdm ioctl and give it a second to get well
// established as a counter.
//
Status1 = NtDeviceIoControlFile(
hFile,
Evt1,
NULL,
NULL,
&Iosb1,
IOCTL_SERIAL_XOFF_COUNTER,
&Xc1,
sizeof(SERIAL_XOFF_COUNTER),
NULL,
0
);
if ( Status1 != STATUS_PENDING) {
printf("1: Non pending status: %x\n",Status1);
exit(1);
}
Sleep(1000);
//
// Do the second vdm ioctl. Wait one second then test to
// make sure that the first one is finished by checking
// its event handle. Then make sure that it was killed
// because of writes
//
Status2 = NtDeviceIoControlFile(
hFile,
Evt2,
NULL,
NULL,
&Iosb2,
IOCTL_SERIAL_XOFF_COUNTER,
&Xc2,
sizeof(SERIAL_XOFF_COUNTER),
NULL,
0
);
if ( Status2 != STATUS_PENDING) {
printf("2: Non pending status: %x\n",Status1);
exit(1);
}
//
// Wait up to a second for the first one to be killed.
//
if (WaitForSingleObject(Evt1,1000)) {
printf("Evt1 has not attained a signalled state.\n");
exit(1);
}
if (Iosb1.Status != STATUS_SERIAL_MORE_WRITES) {
printf("Iosb1 not more writes: %x\n",Iosb1.Status);
exit(1);
}
//
// Start up an 1 character asynchronous write and wait for a second and
// the make sure that the previous vdm ioctl is done.
//
WriteDone = WriteFile(
hFile,
&Char,
1,
&NumberActuallyWritten,
&WriteOl
);
if (!WriteDone) {
DWORD LastError;
LastError = GetLastError();
if (LastError != ERROR_IO_PENDING) {
printf("Couldn't write the %s device.\n",MyPort);
printf("Status of failed write is: %x\n",LastError);
exit(1);
}
}
if (WaitForSingleObject(Evt2,1000)) {
printf("Evt2 has not attained a signalled state.\n");
exit(1);
}
if (Iosb2.Status != STATUS_SERIAL_MORE_WRITES) {
printf("Iosb2 not more writes: %x\n",Iosb2.Status);
exit(1);
}
//
// Wait up to 10 seconds for the write to finish.
//
if (WaitForSingleObject(WriteOl.hEvent,10000)) {
printf("The write never finished\n");
exit(1);
}
//
// Set up a third vdm ioctl as before.
//
Status3 = NtDeviceIoControlFile(
hFile,
Evt3,
NULL,
NULL,
&Iosb3,
IOCTL_SERIAL_XOFF_COUNTER,
&Xc3,
sizeof(SERIAL_XOFF_COUNTER),
NULL,
0
);
if ( Status3 != STATUS_PENDING) {
printf("3: Non pending status: %x\n",Status3);
exit(1);
}
//
// Set up a fourth vdm ioctl, make sure that the previous ioctl
// has been killed. Then wait for 15 seconds and then make sure
// that the fourth vdm ioctl is finished and that it finished
// due to the timer expiring before the the counter expired
//
Status4 = NtDeviceIoControlFile(
hFile,
Evt4,
NULL,
NULL,
&Iosb4,
IOCTL_SERIAL_XOFF_COUNTER,
&Xc4,
sizeof(SERIAL_XOFF_COUNTER),
NULL,
0
);
if ( Status4 != STATUS_PENDING) {
printf("4: Non pending status: %x\n",Status4);
exit(1);
}
if (WaitForSingleObject(Evt3,1000)) {
printf("Evt3 has not attained a signalled state.\n");
exit(1);
}
if (Iosb3.Status != STATUS_SERIAL_MORE_WRITES) {
printf("Iosb3 not more writes: %x\n",Iosb3.Status);
exit(1);
}
//
// Wait up to one second beyond the countdown timeout.
//
printf("Waiting %d seconds for the timer to time out.\n",(Xc4.Timeout+1000)/1000);
if (WaitForSingleObject(Evt4,Xc4.Timeout+1000)) {
printf("Evt4 has not attained a signalled state.\n");
exit(1);
}
printf("Done with the timeout.\n");
if (Iosb4.Status != STATUS_SERIAL_COUNTER_TIMEOUT) {
printf("Iosb4 not counter timeout: %x\n",Iosb4.Status);
exit(1);
}
//
// Set up a fifth vdm ioctl, with a counter of ten,
// then do 15 transmit immediate writes. If a loopback
// connector is connected to the port then the characters
// will then be received. This should cause the counter to
// count down and cause the vdm ioctl to complete with
// status success.
//
// NOTE NOTE: Transmit immediates DO NOT cause vdm ioctls
// to complete with a status of MORE_WRITES.
//
Status5 = NtDeviceIoControlFile(
hFile,
Evt5,
NULL,
NULL,
&Iosb5,
IOCTL_SERIAL_XOFF_COUNTER,
&Xc5,
sizeof(SERIAL_XOFF_COUNTER),
NULL,
0
);
if ( Status5 != STATUS_PENDING) {
printf("5: Non pending status: %x\n",Status5);
exit(1);
}
for (
j = 0;
j < Xc5.Counter+5;
j++
) {
if (!TransmitCommChar(hFile,'u')) {
printf("A transmit comm char failed: %d\n",j);
exit(1);
}
}
//
// Well we'll give it at least a second.
//
if (WaitForSingleObject(Evt5,1000)) {
printf("Evt5 has not attained a signalled state.\n");
exit(1);
}
if (Iosb5.Status != STATUS_SUCCESS) {
printf("Iosb5 not SUCCEESS: %x\n",Iosb5.Status);
exit(1);
}
}