mirror of https://github.com/lianthony/NT4.0
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.
1258 lines
26 KiB
1258 lines
26 KiB
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include "ntddmodm.h"
|
|
|
|
#include "windows.h"
|
|
#include "t2prot.h"
|
|
|
|
|
|
VOID
|
|
SndProt(
|
|
IN HANDLE Pipe,
|
|
IN UCHAR TokenToSend,
|
|
IN ULONG CurrentLine
|
|
);
|
|
|
|
BOOL
|
|
RcvProt(
|
|
IN HANDLE Pipe,
|
|
IN UCHAR ExpectedProt,
|
|
IN ULONG CurrentLine
|
|
);
|
|
|
|
int _CRTAPI1 main(int argc,char *argv[]) {
|
|
|
|
HANDLE hFile1;
|
|
HANDLE hFile2;
|
|
HANDLE pipeHandle;
|
|
HANDLE remoteHandle;
|
|
HANDLE targetProcessHandle;
|
|
DWORD targetProcessId;
|
|
DWORD numberOfBytesRead;
|
|
DWORD numberOfBytesWritten1;
|
|
DWORD numberOfBytesWritten2;
|
|
DWORD numberOfBytesWritten3;
|
|
UCHAR protocolToken;
|
|
DWORD lastError;
|
|
DWORD waitResult;
|
|
HANDLE duplicatedHandle;
|
|
DWORD numberOfBytesWritten;
|
|
DWORD modemStatus;
|
|
char *MyPort = "\\\\.\\Hayes Optima 144";
|
|
OVERLAPPED olControl;
|
|
OVERLAPPED ol1;
|
|
OVERLAPPED ol2;
|
|
OVERLAPPED ol3;
|
|
OVERLAPPED olMask;
|
|
HANDLE eventArray[3];
|
|
DWORD whatState;
|
|
char writeBuffer1[10];
|
|
char writeBuffer2[10];
|
|
char writeBuffer3[10];
|
|
COMMTIMEOUTS timeOuts = {0};
|
|
DCB hFile1Dcb;
|
|
DWORD repititions = 1000;
|
|
DWORD satisfiedMask;
|
|
|
|
|
|
//
|
|
// Get the number of types to attempt the test.
|
|
//
|
|
|
|
if (argc > 1) {
|
|
|
|
sscanf(argv[1],"%d",&repititions);
|
|
|
|
}
|
|
|
|
if (!(olControl.hEvent = CreateEvent(
|
|
NULL,
|
|
FALSE,
|
|
FALSE,
|
|
NULL
|
|
))) {
|
|
|
|
FAILURE(0);
|
|
|
|
} else {
|
|
|
|
olControl.Internal = 0;
|
|
olControl.InternalHigh = 0;
|
|
olControl.Offset = 0;
|
|
olControl.OffsetHigh = 0;
|
|
|
|
}
|
|
|
|
if (!(ol1.hEvent = CreateEvent(
|
|
NULL,
|
|
FALSE,
|
|
FALSE,
|
|
NULL
|
|
))) {
|
|
|
|
FAILURE(0);
|
|
|
|
} else {
|
|
|
|
ol1.Internal = 0;
|
|
ol1.InternalHigh = 0;
|
|
ol1.Offset = 0;
|
|
ol1.OffsetHigh = 0;
|
|
|
|
}
|
|
|
|
if (!(ol2.hEvent = CreateEvent(
|
|
NULL,
|
|
FALSE,
|
|
FALSE,
|
|
NULL
|
|
))) {
|
|
|
|
FAILURE(0);
|
|
|
|
} else {
|
|
|
|
ol2.Internal = 0;
|
|
ol2.InternalHigh = 0;
|
|
ol2.Offset = 0;
|
|
ol2.OffsetHigh = 0;
|
|
|
|
}
|
|
|
|
if (!(ol3.hEvent = CreateEvent(
|
|
NULL,
|
|
FALSE,
|
|
FALSE,
|
|
NULL
|
|
))) {
|
|
|
|
FAILURE(0);
|
|
|
|
} else {
|
|
|
|
ol3.Internal = 0;
|
|
ol3.InternalHigh = 0;
|
|
ol3.Offset = 0;
|
|
ol3.OffsetHigh = 0;
|
|
|
|
}
|
|
|
|
if (!(olMask.hEvent = CreateEvent(
|
|
NULL,
|
|
FALSE,
|
|
FALSE,
|
|
NULL
|
|
))) {
|
|
|
|
FAILURE(0);
|
|
|
|
} else {
|
|
|
|
olMask.Internal = 0;
|
|
olMask.InternalHigh = 0;
|
|
olMask.Offset = 0;
|
|
olMask.OffsetHigh = 0;
|
|
|
|
}
|
|
|
|
//
|
|
// Create/Open the named pipe.
|
|
//
|
|
|
|
if ((pipeHandle = CreateNamedPipe(
|
|
"\\\\.\\pipe\\unitest",
|
|
PIPE_ACCESS_DUPLEX,
|
|
0,
|
|
PIPE_UNLIMITED_INSTANCES,
|
|
1000,
|
|
1000,
|
|
MYPIPETIMEOUT,
|
|
0
|
|
)) == INVALID_HANDLE_VALUE) {
|
|
|
|
FAILURE(0);
|
|
|
|
}
|
|
|
|
//
|
|
// Open the named pipe to the remote machine that will
|
|
// set lines for us.
|
|
//
|
|
if ((remoteHandle = CreateFile(
|
|
"\\\\.\\pipe\\uniremote",
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
)) == ((HANDLE)-1)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// We created the named pipe. Now connect to it so that
|
|
// we can wait for the client to start up.
|
|
//
|
|
|
|
if (!ConnectNamedPipe(
|
|
pipeHandle,
|
|
NULL
|
|
)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
eventArray[0] = ol1.hEvent;
|
|
eventArray[1] = ol2.hEvent;
|
|
eventArray[2] = ol3.hEvent;
|
|
|
|
//
|
|
// Read the process handle for the process that wants the
|
|
// duplicate
|
|
//
|
|
|
|
if (!ReadFile(
|
|
pipeHandle,
|
|
&targetProcessId,
|
|
sizeof(targetProcessId),
|
|
&numberOfBytesRead,
|
|
NULL
|
|
)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
//
|
|
// Get the target process Handle.
|
|
//
|
|
|
|
targetProcessHandle = OpenProcess(
|
|
PROCESS_DUP_HANDLE,
|
|
FALSE,
|
|
targetProcessId
|
|
);
|
|
|
|
if (targetProcessHandle == NULL) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
//
|
|
// We opened the modem twice. Get our current process handle.
|
|
//
|
|
// Open the pipe \\.\pipe\unitest
|
|
//
|
|
// Read from the pipe the process handle of the client
|
|
//
|
|
// Create a duplicate of the second handle using the process
|
|
// handle of the client.
|
|
//
|
|
// Send the duplicate file handle to the client. Wait on the
|
|
// process handle of the client to go away. Then we can exit
|
|
// also.
|
|
//
|
|
|
|
do {
|
|
|
|
if ((hFile1 = CreateFile(
|
|
MyPort,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
|
|
NULL
|
|
)) == ((HANDLE)-1)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
if (!GetCommState(
|
|
hFile1,
|
|
&hFile1Dcb
|
|
)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
//
|
|
// Set the state just how we want it.
|
|
//
|
|
|
|
hFile1Dcb.BaudRate = 9600;
|
|
hFile1Dcb.ByteSize = 8;
|
|
hFile1Dcb.Parity = NOPARITY;
|
|
hFile1Dcb.StopBits = ONESTOPBIT;
|
|
|
|
//
|
|
// Make sure that no flow control is turned on.
|
|
//
|
|
|
|
hFile1Dcb.fOutxDsrFlow = FALSE;
|
|
hFile1Dcb.fOutxCtsFlow = FALSE;
|
|
hFile1Dcb.fDsrSensitivity = FALSE;
|
|
hFile1Dcb.fOutX = FALSE;
|
|
hFile1Dcb.fInX = FALSE;
|
|
hFile1Dcb.fDtrControl = DTR_CONTROL_ENABLE;
|
|
hFile1Dcb.fRtsControl = RTS_CONTROL_ENABLE;
|
|
|
|
if (!SetCommState(
|
|
hFile1,
|
|
&hFile1Dcb
|
|
)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
if (!SetCommTimeouts(
|
|
hFile1,
|
|
&timeOuts
|
|
)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
if ((hFile2 = CreateFile(
|
|
MyPort,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
|
|
NULL
|
|
)) == ((HANDLE)-1)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
if (!DuplicateHandle(
|
|
GetCurrentProcess(),
|
|
hFile2,
|
|
targetProcessHandle,
|
|
&duplicatedHandle,
|
|
0,
|
|
TRUE,
|
|
DUPLICATE_SAME_ACCESS
|
|
)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
//
|
|
// We have the duplicated handle. Close the original one.
|
|
//
|
|
|
|
if (!CloseHandle(hFile2)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
//
|
|
// Send the handle back to the client.
|
|
//
|
|
|
|
if (!WriteFile(
|
|
pipeHandle,
|
|
&duplicatedHandle,
|
|
sizeof(duplicatedHandle),
|
|
&numberOfBytesWritten,
|
|
NULL
|
|
)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
//
|
|
// Wait for the next byte from the client. This tells us
|
|
// that the client has queued off a bunch of IO's.
|
|
//
|
|
|
|
RCVPROT(
|
|
pipeHandle,
|
|
TPROT_CLIENT_STRTED_1_IOS
|
|
);
|
|
|
|
//
|
|
// At this point we are going to put the device into no-passthrough.
|
|
// This should cause all of the io's to complete.
|
|
//
|
|
|
|
whatState = MODEM_NOPASSTHROUGH;
|
|
if (!DeviceIoControl(
|
|
hFile1,
|
|
IOCTL_MODEM_SET_PASSTHROUGH,
|
|
&whatState,
|
|
sizeof(whatState),
|
|
NULL,
|
|
0,
|
|
&numberOfBytesWritten,
|
|
&olControl
|
|
)) {
|
|
|
|
lastError = GetLastError();
|
|
|
|
if (lastError != ERROR_IO_PENDING) {
|
|
|
|
FAILURE(lastError);
|
|
|
|
}
|
|
|
|
waitResult = WaitForSingleObject(
|
|
olControl.hEvent,
|
|
10000
|
|
);
|
|
if (waitResult == WAIT_FAILED) {
|
|
|
|
FAILURE(waitResult);
|
|
|
|
} else {
|
|
|
|
if (waitResult != WAIT_OBJECT_0) {
|
|
|
|
FAILURE(waitResult);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Read that the clients are all done with the io.
|
|
//
|
|
|
|
RCVPROT(
|
|
pipeHandle,
|
|
TPROT_CLIENT_DONE_1_IOS
|
|
);
|
|
|
|
//
|
|
// Write out a byte to the client. This will be our indication that
|
|
// we've gone into no passthrough mode and it should try a doomed write.
|
|
//
|
|
|
|
SNDPROT(
|
|
pipeHandle,
|
|
TPROT_SRVR_SET_NOPASS
|
|
);
|
|
|
|
//
|
|
// All of the IO's are done from the client. send io's to
|
|
// the device to make sure we the owner can still do io.
|
|
//
|
|
|
|
if (!WriteFile(
|
|
hFile1,
|
|
&writeBuffer1[0],
|
|
sizeof(writeBuffer1),
|
|
&numberOfBytesWritten1,
|
|
&ol1
|
|
)) {
|
|
|
|
lastError = GetLastError();
|
|
if (lastError != ERROR_IO_PENDING) {
|
|
|
|
FAILURE(lastError);
|
|
|
|
}
|
|
|
|
}
|
|
if (!WriteFile(
|
|
hFile1,
|
|
&writeBuffer2[0],
|
|
sizeof(writeBuffer2),
|
|
&numberOfBytesWritten2,
|
|
&ol2
|
|
)) {
|
|
|
|
lastError = GetLastError();
|
|
if (lastError != ERROR_IO_PENDING) {
|
|
|
|
FAILURE(lastError);
|
|
|
|
}
|
|
|
|
}
|
|
if (!WriteFile(
|
|
hFile1,
|
|
&writeBuffer3[0],
|
|
sizeof(writeBuffer3),
|
|
&numberOfBytesWritten3,
|
|
&ol3
|
|
)) {
|
|
|
|
lastError = GetLastError();
|
|
if (lastError != ERROR_IO_PENDING) {
|
|
|
|
FAILURE(lastError);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Wait for all the writes to complete.
|
|
//
|
|
|
|
waitResult = WaitForMultipleObjects(
|
|
3,
|
|
&eventArray[0],
|
|
TRUE,
|
|
10000
|
|
);
|
|
|
|
if (waitResult == WAIT_FAILED) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
if ((waitResult < WAIT_OBJECT_0) ||
|
|
(waitResult > (WAIT_OBJECT_0 + 2))) {
|
|
|
|
FAILURE(waitResult);
|
|
|
|
}
|
|
|
|
RCVPROT(
|
|
pipeHandle,
|
|
TPROT_CLIENT_TRIED_DOOM_WRITE
|
|
);
|
|
|
|
//
|
|
// Put it back into non-sniffing passthrough mode.
|
|
//
|
|
whatState = MODEM_PASSTHROUGH;
|
|
if (!DeviceIoControl(
|
|
hFile1,
|
|
IOCTL_MODEM_SET_PASSTHROUGH,
|
|
&whatState,
|
|
sizeof(whatState),
|
|
NULL,
|
|
0,
|
|
&numberOfBytesWritten,
|
|
&olControl
|
|
)) {
|
|
|
|
|
|
lastError = GetLastError();
|
|
|
|
if (lastError != ERROR_IO_PENDING) {
|
|
|
|
FAILURE(lastError);
|
|
|
|
}
|
|
|
|
waitResult = WaitForSingleObject(
|
|
olControl.hEvent,
|
|
10000
|
|
);
|
|
if (waitResult == WAIT_FAILED) {
|
|
|
|
FAILURE(waitResult);
|
|
|
|
} else {
|
|
|
|
if (waitResult != WAIT_OBJECT_0) {
|
|
|
|
FAILURE(waitResult);
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// Send a byte to the client so that it will try to do some
|
|
// io's cause we are back in passthrough mode again.
|
|
//
|
|
|
|
SNDPROT(
|
|
pipeHandle,
|
|
TPROT_SRVR_SET_PASS
|
|
);
|
|
|
|
//
|
|
// Wait for a byte from the client telling us that it strted ios.
|
|
//
|
|
RCVPROT(
|
|
pipeHandle,
|
|
TPROT_CLIENT_STRTED_2_IOS
|
|
);
|
|
|
|
//
|
|
// Wait for a byte from the client telling us that it finished ios.
|
|
//
|
|
RCVPROT(
|
|
pipeHandle,
|
|
TPROT_CLIENT_DONE_2_IOS
|
|
);
|
|
|
|
//
|
|
// Put the device into dcd sniff mode.
|
|
//
|
|
|
|
whatState = MODEM_DCDSNIFF;
|
|
if (!DeviceIoControl(
|
|
hFile1,
|
|
IOCTL_MODEM_SET_PASSTHROUGH,
|
|
&whatState,
|
|
sizeof(whatState),
|
|
NULL,
|
|
0,
|
|
&numberOfBytesWritten,
|
|
&olControl
|
|
)) {
|
|
|
|
lastError = GetLastError();
|
|
|
|
if (lastError != ERROR_IO_PENDING) {
|
|
|
|
FAILURE(lastError);
|
|
|
|
}
|
|
|
|
waitResult = WaitForSingleObject(
|
|
olControl.hEvent,
|
|
10000
|
|
);
|
|
if (waitResult == WAIT_FAILED) {
|
|
|
|
FAILURE(waitResult);
|
|
|
|
} else {
|
|
|
|
if (waitResult != WAIT_OBJECT_0) {
|
|
|
|
FAILURE(waitResult);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Tell the client we are sniff mode.
|
|
//
|
|
|
|
SNDPROT(
|
|
pipeHandle,
|
|
TPROT_SRVR_SET_SNIFF
|
|
);
|
|
|
|
//
|
|
// Wait for a byte from the client telling us that it knows.
|
|
// about the sniff and that it queued operations
|
|
//
|
|
RCVPROT(
|
|
pipeHandle,
|
|
TPROT_CLIENT_ACK_SNIFF
|
|
);
|
|
|
|
//
|
|
// Wait for a byte from the client telling us that it
|
|
// is done doing various setmasks.
|
|
//
|
|
|
|
RCVPROT(
|
|
pipeHandle,
|
|
TPROT_CLIENT_DID_SETMASKS
|
|
);
|
|
|
|
if (!SetCommMask(
|
|
hFile1,
|
|
EV_RXFLAG
|
|
)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
if (!SetCommMask(
|
|
hFile1,
|
|
EV_RXFLAG | EV_DSR | EV_RLSD
|
|
)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
//
|
|
// Tell the client we are done with setmasks
|
|
//
|
|
|
|
SNDPROT(
|
|
pipeHandle,
|
|
TPROT_SRVR_SET_SETMASKS
|
|
);
|
|
|
|
//
|
|
// Tell the remote end that we are done setting masks
|
|
// and that we want a dcd transition.
|
|
//
|
|
SNDPROT(
|
|
remoteHandle,
|
|
TPROT_SRVR_DO_DCDTRANS
|
|
);
|
|
|
|
//
|
|
// Wait for the client to tell us it did the
|
|
// transition. We should be able to check the
|
|
// modem state and find our that we are in
|
|
// no passthrough. We should tell our local
|
|
// client to check that it's ios are all done.
|
|
//
|
|
|
|
RCVPROT(
|
|
remoteHandle,
|
|
TPROT_CLIENT_DID_DCDTRANS
|
|
);
|
|
|
|
if (!DeviceIoControl(
|
|
hFile1,
|
|
IOCTL_MODEM_GET_PASSTHROUGH,
|
|
&whatState,
|
|
sizeof(whatState),
|
|
&whatState,
|
|
sizeof(whatState),
|
|
&numberOfBytesWritten,
|
|
&olControl
|
|
)) {
|
|
|
|
lastError = GetLastError();
|
|
|
|
if (lastError != ERROR_IO_PENDING) {
|
|
|
|
FAILURE(lastError);
|
|
|
|
}
|
|
|
|
waitResult = WaitForSingleObject(
|
|
olControl.hEvent,
|
|
10000
|
|
);
|
|
if (waitResult == WAIT_FAILED) {
|
|
|
|
FAILURE(waitResult);
|
|
|
|
} else {
|
|
|
|
if (waitResult != WAIT_OBJECT_0) {
|
|
|
|
FAILURE(waitResult);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (whatState != MODEM_NOPASSTHROUGH) {
|
|
|
|
FAILURE(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Now tell the local client to check that its ios are all
|
|
// done.
|
|
//
|
|
|
|
SNDPROT(
|
|
pipeHandle,
|
|
TPROT_CLIENT_DID_DCDTRANS
|
|
);
|
|
|
|
//
|
|
// The local client should tell us it's done with dcd trans
|
|
// ios.
|
|
//
|
|
|
|
RCVPROT(
|
|
pipeHandle,
|
|
TPROT_CLIENT_DONE_DCDTRANS
|
|
);
|
|
|
|
//
|
|
// Tell the remote client all done with dcd trans
|
|
//
|
|
|
|
SNDPROT(
|
|
remoteHandle,
|
|
TPROT_CLIENT_DONE_DCDTRANS
|
|
);
|
|
|
|
//
|
|
// The local client no should ask us for a break.
|
|
//
|
|
|
|
RCVPROT(
|
|
pipeHandle,
|
|
TPROT_CLIENT_WANTS_BREAK
|
|
);
|
|
|
|
SNDPROT(
|
|
remoteHandle,
|
|
TPROT_CLIENT_WANTS_BREAK
|
|
);
|
|
|
|
RCVPROT(
|
|
remoteHandle,
|
|
TPROT_CLIENT_SHOULDA_BROKE
|
|
);
|
|
|
|
SNDPROT(
|
|
pipeHandle,
|
|
TPROT_CLIENT_SHOULDA_BROKE
|
|
);
|
|
|
|
RCVPROT(
|
|
pipeHandle,
|
|
TPROT_DONE_BREAK
|
|
);
|
|
|
|
//
|
|
// Put us into passthrough for the next test.
|
|
//
|
|
|
|
whatState = MODEM_PASSTHROUGH;
|
|
if (!DeviceIoControl(
|
|
hFile1,
|
|
IOCTL_MODEM_SET_PASSTHROUGH,
|
|
&whatState,
|
|
sizeof(whatState),
|
|
NULL,
|
|
0,
|
|
&numberOfBytesWritten,
|
|
&olControl
|
|
)) {
|
|
|
|
lastError = GetLastError();
|
|
|
|
if (lastError != ERROR_IO_PENDING) {
|
|
|
|
FAILURE(lastError);
|
|
|
|
}
|
|
|
|
waitResult = WaitForSingleObject(
|
|
olControl.hEvent,
|
|
10000
|
|
);
|
|
if (waitResult == WAIT_FAILED) {
|
|
|
|
FAILURE(waitResult);
|
|
|
|
} else {
|
|
|
|
if (waitResult != WAIT_OBJECT_0) {
|
|
|
|
FAILURE(waitResult);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Wait for the client to tell us it wants to set it mask up.
|
|
//
|
|
|
|
RCVPROT(
|
|
pipeHandle,
|
|
TPROT_CLIENT_WANTS_NEWMASK
|
|
);
|
|
|
|
if (!SetCommMask(
|
|
hFile1,
|
|
0
|
|
)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
if (!SetCommMask(
|
|
hFile1,
|
|
EV_DSR | EV_RLSD
|
|
)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
SNDPROT(
|
|
pipeHandle,
|
|
TPROT_SRVR_SAYS_DONEWMASK
|
|
);
|
|
|
|
//
|
|
// After the client sets up its mask, we queue off a wait so
|
|
// that we can make sure that we are the passed down wait
|
|
// in the modem driver.
|
|
//
|
|
|
|
RCVPROT(
|
|
pipeHandle,
|
|
TPROT_CLIENT_DONE_NEWMASK
|
|
);
|
|
|
|
//
|
|
// Start off the wait.
|
|
//
|
|
|
|
satisfiedMask = 0;
|
|
if (!WaitCommEvent(
|
|
hFile1,
|
|
&satisfiedMask,
|
|
&olMask
|
|
)) {
|
|
|
|
lastError = GetLastError();
|
|
if (lastError != ERROR_IO_PENDING) {
|
|
|
|
FAILURE(lastError);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
FAILURE(satisfiedMask);
|
|
|
|
}
|
|
|
|
//
|
|
// Tell the client to go ahead.
|
|
//
|
|
|
|
SNDPROT(
|
|
pipeHandle,
|
|
TPROT_SRVR_HEARD_DONENEWMASK
|
|
);
|
|
|
|
//
|
|
// Wait for the client to tell us he set up the wait.
|
|
//
|
|
|
|
RCVPROT(
|
|
pipeHandle,
|
|
TPROT_CLIENT_DONE_NEWWAITMASK
|
|
);
|
|
|
|
//
|
|
// Make sure that our wait is still pending.
|
|
//
|
|
|
|
waitResult = WaitForSingleObject(
|
|
olMask.hEvent,
|
|
0
|
|
);
|
|
|
|
if (waitResult != WAIT_TIMEOUT) {
|
|
|
|
FAILURE(waitResult);
|
|
|
|
}
|
|
|
|
//
|
|
// Tell the remote pipe to go ahead and send the break.
|
|
//
|
|
|
|
SNDPROT(
|
|
remoteHandle,
|
|
TPROT_REMOTE_SEND_NEW_BREAK
|
|
);
|
|
|
|
//
|
|
// Wait for the remote to tell us that it set and then cleared
|
|
// the break.
|
|
//
|
|
|
|
RCVPROT(
|
|
remoteHandle,
|
|
TPROT_REMOTE_DONE_NEW_BREAK
|
|
);
|
|
|
|
//
|
|
// Make sure that our wait is still pending.
|
|
//
|
|
|
|
waitResult = WaitForSingleObject(
|
|
olMask.hEvent,
|
|
0
|
|
);
|
|
|
|
if (waitResult != WAIT_TIMEOUT) {
|
|
|
|
FAILURE(satisfiedMask);
|
|
|
|
}
|
|
|
|
//
|
|
// Tell the client to make sure that it's wait is done.
|
|
//
|
|
|
|
SNDPROT(
|
|
pipeHandle,
|
|
TPROT_SRVR_HEARD_DONENEWWAITMASK
|
|
);
|
|
|
|
RCVPROT(
|
|
pipeHandle,
|
|
TPROT_CLIENT_DONE_NEWGETRESULTS
|
|
);
|
|
|
|
//
|
|
// Make sure ours is still not finished.
|
|
//
|
|
// Do a setmask to make sure ours is done.
|
|
//
|
|
|
|
waitResult = WaitForSingleObject(
|
|
olMask.hEvent,
|
|
0
|
|
);
|
|
|
|
if (waitResult != WAIT_TIMEOUT) {
|
|
|
|
FAILURE(satisfiedMask);
|
|
|
|
}
|
|
|
|
if (!SetCommMask(
|
|
hFile1,
|
|
0
|
|
)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
waitResult = WaitForSingleObject(
|
|
olMask.hEvent,
|
|
0
|
|
);
|
|
|
|
if (waitResult != WAIT_OBJECT_0) {
|
|
|
|
FAILURE(waitResult);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Make sure that it's return value is zero.
|
|
//
|
|
|
|
if (!GetOverlappedResult(
|
|
hFile1,
|
|
&olMask,
|
|
&numberOfBytesWritten,
|
|
FALSE
|
|
)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
if (numberOfBytesWritten != sizeof(DWORD)) {
|
|
|
|
FAILURE(numberOfBytesWritten);
|
|
|
|
}
|
|
|
|
if (satisfiedMask) {
|
|
|
|
FAILURE(satisfiedMask);
|
|
|
|
}
|
|
|
|
//
|
|
// Close the main file handle
|
|
//
|
|
|
|
if (!CloseHandle(hFile1)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
repititions--;
|
|
|
|
if (repititions > 0) {
|
|
|
|
//
|
|
// Pipe through that we are going to do another round.
|
|
//
|
|
|
|
SNDPROT(
|
|
pipeHandle,
|
|
TPROT_SRVR_ANOTHER_TEST
|
|
);
|
|
|
|
SNDPROT(
|
|
remoteHandle,
|
|
TPROT_SRVR_ANOTHER_TEST
|
|
);
|
|
|
|
//
|
|
// Wait for acknowledgement of another round.
|
|
//
|
|
RCVPROT(
|
|
pipeHandle,
|
|
TPROT_CLIENT_ACK_ANOTHER_TEST
|
|
);
|
|
RCVPROT(
|
|
remoteHandle,
|
|
TPROT_CLIENT_ACK_ANOTHER_TEST
|
|
);
|
|
|
|
} else {
|
|
|
|
SNDPROT(
|
|
pipeHandle,
|
|
TPROT_SRVR_DONE_TEST
|
|
);
|
|
SNDPROT(
|
|
remoteHandle,
|
|
TPROT_SRVR_DONE_TEST
|
|
);
|
|
|
|
//
|
|
// Wait for acknowledgement of no more rounds.
|
|
//
|
|
RCVPROT(
|
|
pipeHandle,
|
|
TPROT_CLIENT_ACK_DONE_TEST
|
|
);
|
|
RCVPROT(
|
|
remoteHandle,
|
|
TPROT_CLIENT_ACK_DONE_TEST
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (TRUE);
|
|
|
|
if (!CloseHandle(pipeHandle)) {
|
|
|
|
FAILURE(GetLastError());
|
|
|
|
}
|
|
|
|
exit(1);
|
|
return 1;
|
|
}
|
|
VOID
|
|
SndProt(
|
|
IN HANDLE Pipe,
|
|
IN UCHAR TokenToSend,
|
|
IN ULONG CurrentLine
|
|
)
|
|
|
|
{
|
|
|
|
UCHAR protocolToken = TokenToSend;
|
|
DWORD numberOfBytesWritten;
|
|
|
|
if (!WriteFile(
|
|
Pipe,
|
|
&protocolToken,
|
|
sizeof(protocolToken),
|
|
&numberOfBytesWritten,
|
|
NULL
|
|
)) {
|
|
|
|
printf(
|
|
"\nCouldn't send token: %d - at line:%d - error: %d\n",
|
|
protocolToken,
|
|
CurrentLine,
|
|
GetLastError()
|
|
);
|
|
exit(1);
|
|
|
|
}
|
|
}
|
|
BOOL
|
|
RcvProt(
|
|
IN HANDLE Pipe,
|
|
IN UCHAR ExpectedProt,
|
|
IN ULONG CurrentLine
|
|
)
|
|
|
|
{
|
|
UCHAR protocolToken = ExpectedProt;
|
|
DWORD numberOfBytesPiped;
|
|
|
|
if (!ReadFile(
|
|
Pipe,
|
|
&protocolToken,
|
|
sizeof(protocolToken),
|
|
&numberOfBytesPiped,
|
|
NULL
|
|
)) {
|
|
|
|
printf(
|
|
"\nCouldn't read the protocol value at line %d - error: %d\n",
|
|
CurrentLine,
|
|
GetLastError()
|
|
);
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if (protocolToken != ExpectedProt) {
|
|
|
|
//
|
|
// If it isn't the expected protocol perhaps it's the
|
|
// terminating protocol. If it is return TRUE.
|
|
//
|
|
|
|
if (protocolToken == TPROT_SRVR_DONE_TEST) {
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
printf(
|
|
"Protocol out of sync: %d/%d (token/required) at line: %d\n",
|
|
protocolToken,
|
|
ExpectedProt,
|
|
CurrentLine
|
|
);
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|