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