Click to See Complete Forum and Search --> : Problem with redirecting STDIO in telnet server app


Mike Ryan
May 7th, 1999, 04:45 PM
I am having trouble redirecting stdio through a socket for a telnet server app.

I can redirect STDOUT from CMD.EXE (my child process) just fine but I get seem to send it any input... :(

Here is my source, Any help is *VERY* appreciated as this has kicked my butt for a while now:


//
// OnReceive(int)
//
// This function will be called when the socket receives data
//
// Return value: none
//
void CClientSocket::OnReceive(int nErrorCode)
{
unsigned char buffer[100];
int numBytes = Receive(buffer, 100);

if (numBytes != SOCKET_ERROR)
{
buffer[numBytes] = 0;
if (!bLoggedIn)
{
if (ProcessCommand(buffer))
{
if (bEcho)
Send(buffer, numBytes);
else
Send("", 1);
}
}
else
{
DWORD dwWritten;
if (WriteFile(hChildStdinWrDup, buffer, 1, &dwWritten, NULL))
{
if (buffer[0] == 13) Send("\r\n", 2);
else Send(buffer, 1);
}
}
}
else
{
}

if (!bSentGoAhead)
{
bSentGoAhead = 1;
unsigned char buf[3];
buf[0] = IAC;
buf[1] = WILL;
buf[2] = SUPPRESS_GO_AHEAD;
buf[3] = 0;
Send(buf, 3);
}
}

//
// CreateChildProcess()
//
// This function will create an instance of CMDEX (or other shell) and reroute standard
// input and output to a pipe so we can access it.
//
// Return value: a handle to the child process
//
int CClientSocket::CreateChildProcess(void)
{
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = true;
saAttr.lpSecurityDescriptor = NULL;

// Remap STDOUT
HANDLE m_hOldStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE hChildStdoutRd;
if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
{
SendError("Can't redirect stdout");
return 0;
}

if (! SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr))
{
SendError("Can't set StdHandle for stdout");
return 0;
}

// dup read handle and kill inheritable read handle
if (!DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, GetCurrentProcess(), &hChildStdoutRdDup,
0, false, DUPLICATE_SAME_ACCESS))
{
SendError("Can't duplicate StdOut Read Handle.");
return 0;
}
CloseHandle(hChildStdoutRd);

// remap std error
/* HANDLE m_hOldStdErr = GetStdHandle(STD_ERROR_HANDLE);
if (! CreatePipe(&hChildStderrRd, &hChildStderrWr, &saAttr, 0))
{
SendError("Can't redirect stderr");
return 0;
}
if (! SetStdHandle(STD_ERROR_HANDLE, hChildStderrWr))
{
SendError("Can't set StdHandle for stdout");
return 0;
}*/

// remap std in
HANDLE m_hOldStdIn = GetStdHandle(STD_INPUT_HANDLE);
HANDLE hChildStdinWr;
if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
{
SendError("Can't redirect stdin");
return 0;
}
if (! SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd))
{
SendError("Can't set StdHandle for stdout");
return 0;
}

if (!DuplicateHandle(GetCurrentProcess(), hChildStdinWr, GetCurrentProcess(), &hChildStdinWrDup,
0, false, DUPLICATE_SAME_ACCESS))
{
SendError("Can't DuplicateHandle");
return 0;
}
CloseHandle(hChildStdinWr);

// create child process
if (!LaunchCMDEX()) return 0;

// remap to originals
if (!SetStdHandle(STD_INPUT_HANDLE, m_hOldStdIn))
{
Send("Can't redirect stdout", strlen("Can't redirect stdout"));
return 0;
}

if (!SetStdHandle(STD_OUTPUT_HANDLE, m_hOldStdOut))
{
Send("Can't redirect stdout", strlen("Can't redirect stdout"));
return 0;
}

/* if (!SetStdHandle(STD_ERROR_HANDLE, m_hOldStdErr))
{
Send("Can't redirect stdout", strlen("Can't redirect stdout"));
return 0;
}*/

return 1;
}

//
// CreateIOThreads()
//
// Create the threads that will handle the input output for the child process and parent
// links.
//
// Return value: 0 on fail, 1 on success
//
int CClientSocket::CreateIOThreads(void)
{
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = true;
saAttr.lpSecurityDescriptor = NULL;

if (!CreateThread(&saAttr, 0, ReadPipeThread, (void*)this, 0, &dwOutThreadID))
return 0;

return 1;
}

//
// ReadPipeThread(void *socket)
//
// Reads from stdout pipe and outputs to socket
//
// Return value: who cares?
//
DWORD WINAPI ReadPipeThread(void *socket)
{
CClientSocket *s = (CClientSocket*)socket;
DWORD dwRead;
char buf[BUFSIZE];

for (;;)
{
if (!ReadFile(s->hChildStdoutRdDup, buf, BUFSIZE-1, &dwRead, NULL) || dwRead == 0) break;
buf[dwRead] = 0;
s->Send(buf, strlen(buf));
}
CloseHandle(s->hChildStdinRd);
CloseHandle(s->hChildStdoutWr);
CloseHandle(s->hChildStdinWrDup);
CloseHandle(s->hChildStdoutRdDup);
s->dwProcessID = DWORD(-1);
return 1;
}




The basic flow is:

Once user has logged in, run CreateChildProcess() which calls LaunchCMDEX() then CreateIOThreads().

After that CMD is launch and the output goes to the telnet client. Then OnReceive will send commands through WriteFile(). No matter what I try to do, CMD is not receiving the commands I send. I even tried sending:

char *buf = "dir\r";
WriteFile(hChildStdinRd, buf, 4, NULL) and got no response from CMD. CMD is running but it is not receiving commands because I tried creating a file on d:\ and then deleteing it but to no avail...

Help!

Thanks in advance,
Mike