I need to use telnet to control console based applications (such as
cmd.exe/command.com) on different machines. Simplest way how to do it is to
listen on some port of the host. When accept() returns (telnet is
connecting), create the desired process with standard handles redirected to
the socket returned by the accept(). I have successfully tested the
following code under WinXP and Win2K.
Unfortunately, under Win9X, the child process is created with no errors, but
the redirection doesn't happen. Even the handle numbers are different (thus
properly passed to the child) than the standard values (tested by calling
GetStdHandle(STD_INPUT_HANDLE) and GetStdHandle(STD_OUTPUT_HANDLE)). When I
try to WriteFile() to GetStdHandle(STD_OUTPUT_HANDLE) within the child
application, I got GetLastError()=ERROR_CALL_NOT_IMPLEMENTED - "This
function is not supported on this system". Nor calling of WSAStartup() in
the child before any read/write helps.
Does anybody know how to make it working under Win9X? I really wouldn't like
to make special thread per each child application for forwarding data
from/to anonymous pipe connecting the thread and the child application
to/from the socket.
The code does not contain any return value tests nor the shutdown mechanism
to be as simple as possible.
void main(void)
{
WSADATA wd;
WSAStartup(MAKEWORD(2,0), &wd);
SOCKET listenSocket=WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
0); //NOT use WSA_FLAG_OVERLAPPED in order to open non-overlapped sockets
struct sockaddr_in service;
service.sin_family=AF_INET;
service.sin_addr.s_addr=htonl(INADDR_ANY);
service.sin_port=htons(12345);
bind(listenSocket, (const struct sockaddr *)&service, sizeof(service));
listen(listenSocket, SOMAXCONN);
for(;

{
SOCKET acceptSocket=accept(listenSocket, NULL, NULL);
printf("server: Client connected.\n");
//create handle for child's process stdout
HANDLE currentProcess;
currentProcess=GetCurrentProcess();
HANDLE output;
DuplicateHandle(currentProcess, (HANDLE)acceptSocket, currentProcess,
&output, 0, TRUE, DUPLICATE_SAME_ACCESS);
//create handle for child's process stdin
HANDLE input;
DuplicateHandle(currentProcess, (HANDLE)acceptSocket, currentProcess,
&input, 0, TRUE, DUPLICATE_SAME_ACCESS);
//execute the executable
PROCESS_INFORMATION pi;
{
STARTUPINFO s;
ZeroMemory(&s, sizeof(s));
s.cb=sizeof(s);
s.dwFlags=STARTF_USESHOWWINDOW|STARTF_USESTDHANDLE S;
s.wShowWindow=SW_SHOWMINNOACTIVE;
s.hStdInput=input;
s.hStdOutput=output;
s.hStdError=GetStdHandle(STD_ERROR_HANDLE); //keep stderr in slave's
console (???)
CreateProcess(getenv("COMSPEC"), getenv("COMSPEC"), NULL, NULL, TRUE,
CREATE_NEW_CONSOLE|IDLE_PRIORITY_CLASS, NULL, NULL, &s, &pi);
}
CloseHandle(pi.hThread);
closesocket(acceptSocket);
WaitForInputIdle(pi.hProcess, INFINITE);
CloseHandle(input);
CloseHandle(output);
CloseHandle(pi.hProcess);
}
closesocket(listenSocket);
}