|
|
#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);
}
}
|