836 lines
22 KiB
C
836 lines
22 KiB
C
|
/*++
|
||
|
Copyright (c) 1992 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
remote.c
|
||
|
|
||
|
Abstract:
|
||
|
This file implements a remote server for REMOTE.EXE that services the windbg command window.
|
||
|
This provides a "NTSD/KD" style debugging from a REMOTE.EXE client to WINDBG.EXE.
|
||
|
|
||
|
Author:
|
||
|
Wesley Witt (wesw) 5-Dec-1993
|
||
|
|
||
|
Environment:
|
||
|
Win32, User Mode
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
|
||
|
extern HANDLE hFileLog;
|
||
|
extern CRITICAL_SECTION csLog;
|
||
|
|
||
|
#define BUFFSIZE 256
|
||
|
|
||
|
SESSION_TYPE ClientList[MAX_SESSION];
|
||
|
|
||
|
HANDLE RemoteServerThreadH;
|
||
|
HANDLE hEventRemoteTerm;
|
||
|
CHAR HostName[MAX_PATH];
|
||
|
CHAR PipeName[MAX_PATH];
|
||
|
CHAR Server[MAX_PATH];
|
||
|
|
||
|
|
||
|
DWORD RemoteServerThread(char* pipe);
|
||
|
BOOL FilterCommand(LPSESSION_TYPE cl, LPSTR buf, DWORD cb);
|
||
|
DWORD RemoteSessionThread(SESSION_TYPE* Client);
|
||
|
VOID SendStatus(LPSESSION_TYPE cl);
|
||
|
DWORD ShowPopupThread(char* mssg);
|
||
|
VOID CloseClient(SESSION_TYPE* Client);
|
||
|
VOID InitClientList(void);
|
||
|
DWORD ReadFixBytes(LPSESSION_TYPE MyClient, LPSTR lpBuf, DWORD cbRead);
|
||
|
VOID PrintDebuggerMsg(BOOL fInsert, BOOL fLog, LPSTR lpFmt, ...);
|
||
|
VOID PrintCmdMsg(LPSESSION_TYPE MyClient, BOOL fInsert, BOOL fLog, LPSTR InpBuf);
|
||
|
|
||
|
|
||
|
VOID StartRemoteServer(LPSTR szPipeName, BOOL fAppend)
|
||
|
{
|
||
|
DWORD ThreadID;
|
||
|
DWORD i;
|
||
|
DWORD j;
|
||
|
int tmp_int;
|
||
|
|
||
|
if (_stricmp(szPipeName, "stop") == 0) {
|
||
|
if (!RemoteRunning) {
|
||
|
CmdLogFmt("Remote server is not running\r\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < MAX_SESSION; i++) {
|
||
|
if (ClientList[i].Active) {
|
||
|
SetEvent(ClientList[i].hEventTerm);
|
||
|
if (WaitForSingleObject(ClientList[i].hThread, 10 * 10000) == WAIT_TIMEOUT) {
|
||
|
TerminateThread(ClientList[i].hThread, 0);
|
||
|
}
|
||
|
CloseHandle(ClientList[i].hEventTerm);
|
||
|
|
||
|
CloseHandle(ClientList[i].PipeWriteH);
|
||
|
CloseHandle(ClientList[i].PipeReadH);
|
||
|
CloseHandle(ClientList[i].OverlappedRead.hEvent);
|
||
|
CloseHandle(ClientList[i].OverlappedWrite.hEvent);
|
||
|
CloseHandle(ClientList[i].hThread);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SetEvent(hEventRemoteTerm);
|
||
|
if (WaitForSingleObject(RemoteServerThreadH, 10 * 1000) == WAIT_TIMEOUT) {
|
||
|
TerminateThread(RemoteServerThreadH, 0);
|
||
|
}
|
||
|
CloseHandle(hEventRemoteTerm);
|
||
|
|
||
|
CmdLogFmt("Remote server stopped for %s\r\n", PipeName);
|
||
|
RemoteRunning = FALSE;
|
||
|
FREE_STR(g_contWorkspace_WkSp.m_pszRemotePipe);
|
||
|
NoPopups = FALSE;
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (RemoteRunning) {
|
||
|
CmdLogFmt("Remote server running for pipe <%s>\r\n", PipeName);
|
||
|
for (i = 0, j = 0; i < MAX_SESSION; i++) {
|
||
|
if (ClientList[i].Active) {
|
||
|
j++;
|
||
|
}
|
||
|
}
|
||
|
if (j) {
|
||
|
CmdLogFmt("%d remote connections:\r\n", j);
|
||
|
for (i = 0; i < MAX_SESSION; i++) {
|
||
|
if (ClientList[i].Active) {
|
||
|
CmdLogFmt("\tClient: %s\r\n", ClientList[i].Name);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!*szPipeName) {
|
||
|
CmdLogFmt("Remote server is not running\r\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
InitClientList();
|
||
|
|
||
|
g_contWorkspace_WkSp.m_bIgnoreAllSymbolErrors = TRUE;
|
||
|
|
||
|
NoPopups = TRUE;
|
||
|
strcpy(PipeName, szPipeName);
|
||
|
|
||
|
FREE_STR(g_contWorkspace_WkSp.m_pszRemotePipe);
|
||
|
g_contWorkspace_WkSp.m_pszRemotePipe = _strdup(szPipeName);
|
||
|
|
||
|
HostName[0] = '\0';
|
||
|
Server[0] = '\0';
|
||
|
|
||
|
if (hFileLog == INVALID_HANDLE_VALUE) {
|
||
|
HANDLE hMap;
|
||
|
LPBYTE lpBase, lpb;
|
||
|
CHAR buf[MAX_PATH];
|
||
|
char szLogFileName[MAX_PATH];
|
||
|
strncpy(szLogFileName, szPipeName, 8);
|
||
|
tmp_int = strlen(szPipeName);
|
||
|
szLogFileName[min(tmp_int, 8)] = 0;
|
||
|
strcat(szLogFileName, ".log");
|
||
|
LogFileOpen(szLogFileName, fAppend);
|
||
|
if (fAppend) {
|
||
|
hMap = CreateFileMapping(hFileLog, NULL, PAGE_READONLY, 0, 0, NULL);
|
||
|
if (hMap) {
|
||
|
lpb = lpBase = (PUCHAR)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
|
||
|
i = GetFileSize(hFileLog, NULL);
|
||
|
while (i) {
|
||
|
j = 0;
|
||
|
while ((*lpb != '\n') && (i)) {
|
||
|
buf[j++] = *lpb++;
|
||
|
i--;
|
||
|
}
|
||
|
if (*lpb == '\n') {
|
||
|
i--;
|
||
|
buf[j++] = *lpb++;
|
||
|
}
|
||
|
buf[j] = 0;
|
||
|
CmdLogFmt("%s", buf);
|
||
|
}
|
||
|
UnmapViewOfFile(lpBase);
|
||
|
CloseHandle(lpb);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hEventRemoteTerm = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||
|
|
||
|
RemoteServerThreadH = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RemoteServerThread, (LPVOID)PipeName, 0, &ThreadID);
|
||
|
if (!RemoteServerThreadH) {
|
||
|
CmdLogFmt("Cannot start remote server for %s\r\n", szPipeName);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
CmdLogFmt("Remote server started for %s\r\n", szPipeName);
|
||
|
|
||
|
RemoteRunning = TRUE;
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
PipeConnect(
|
||
|
HANDLE hPipe,
|
||
|
LPOVERLAPPED OverlappedPipe,
|
||
|
DWORD dwTimeout
|
||
|
)
|
||
|
{
|
||
|
DWORD ec;
|
||
|
DWORD status;
|
||
|
|
||
|
if (INVALID_HANDLE_VALUE == hPipe || NULL == hPipe) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
ResetEvent(OverlappedPipe->hEvent);
|
||
|
status = ConnectNamedPipe(hPipe, OverlappedPipe);
|
||
|
|
||
|
if (!status) {
|
||
|
ec = GetLastError();
|
||
|
switch (ec) {
|
||
|
case ERROR_PIPE_CONNECTED:
|
||
|
goto connected;
|
||
|
case ERROR_IO_PENDING:
|
||
|
break;
|
||
|
default:
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
status = WaitForSingleObject(OverlappedPipe->hEvent, dwTimeout);
|
||
|
switch (status) {
|
||
|
case WAIT_OBJECT_0:
|
||
|
goto connected;
|
||
|
case WAIT_TIMEOUT:
|
||
|
default:
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
connected:
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
PipeRead(
|
||
|
LPSESSION_TYPE MyClient,
|
||
|
PUCHAR pch,
|
||
|
DWORD cch
|
||
|
)
|
||
|
{
|
||
|
DWORD cb;
|
||
|
|
||
|
ResetEvent(MyClient->OverlappedRead.hEvent);
|
||
|
|
||
|
if (ReadFile(MyClient->PipeReadH, pch, cch, &cb, &MyClient->OverlappedRead)) {
|
||
|
// Read was successful and finished return packet size and exit.
|
||
|
return cb;
|
||
|
}
|
||
|
|
||
|
// We got a failure case -- there are now two possibities.
|
||
|
// 1. -- we have overlapped I/O, or
|
||
|
// 2. -- we are messed up.
|
||
|
|
||
|
if (GetLastError() == ERROR_IO_PENDING) {
|
||
|
cb = 0;
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
while (TRUE) {
|
||
|
if (GetOverlappedResult(MyClient->PipeReadH, &MyClient->OverlappedRead, &cb, FALSE)) {
|
||
|
// Read has successfully completed
|
||
|
return cb;
|
||
|
}
|
||
|
if (GetLastError() == ERROR_BROKEN_PIPE) {
|
||
|
break;
|
||
|
}
|
||
|
if (WaitForSingleObject(MyClient->hEventTerm, 0) == WAIT_OBJECT_0) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
Sleep(100);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
PipeWrite(
|
||
|
LPSESSION_TYPE MyClient,
|
||
|
const UCHAR* pch,
|
||
|
DWORD cch,
|
||
|
BOOL fAsynch
|
||
|
)
|
||
|
{
|
||
|
DWORD cb;
|
||
|
|
||
|
if (WriteFile(MyClient->PipeWriteH, pch, cch, &cb, &MyClient->OverlappedWrite)) {
|
||
|
// Write was successful and finished
|
||
|
return cb;
|
||
|
}
|
||
|
|
||
|
// We got a failure case -- there are now two possiblities.
|
||
|
// 1. -- we have overlapped I/O or
|
||
|
// 2. -- we are messed up
|
||
|
if (GetLastError() == ERROR_IO_PENDING) {
|
||
|
cb = 0;
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (GetOverlappedResult(MyClient->PipeWriteH, &MyClient->OverlappedWrite, &cb, !fAsynch)) {
|
||
|
// Write has successfully completed
|
||
|
return cb;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD RemoteServerThread(LPSTR pipename)
|
||
|
{
|
||
|
int i;
|
||
|
DWORD ThreadID;
|
||
|
HANDLE PipeH[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
|
||
|
OVERLAPPED OverlappedPipe[2];
|
||
|
HANDLE TokenHandle;
|
||
|
char fullnameIn[BUFFSIZE];
|
||
|
char fullnameOut[BUFFSIZE];
|
||
|
SECURITY_ATTRIBUTES lsa;
|
||
|
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
||
|
BYTE SDBuffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
|
||
|
PACL Acl;
|
||
|
BYTE AclBuffer[1024];
|
||
|
|
||
|
static PSID EveryoneSid = NULL;
|
||
|
|
||
|
sprintf(fullnameIn, SERVER_READ_PIPE, ".", pipename);
|
||
|
sprintf(fullnameOut, SERVER_WRITE_PIPE, ".", pipename);
|
||
|
|
||
|
// Initialize the security descriptor that we're going to use.
|
||
|
if (!EveryoneSid) {
|
||
|
SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
|
||
|
AllocateAndInitializeSid(&WorldAuthority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &EveryoneSid);
|
||
|
}
|
||
|
|
||
|
SecurityDescriptor = (PSECURITY_DESCRIPTOR)SDBuffer;
|
||
|
Acl = (PACL)AclBuffer;
|
||
|
InitializeSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
|
||
|
InitializeAcl(Acl, 1024, ACL_REVISION);
|
||
|
AddAccessAllowedAce(Acl, ACL_REVISION, GENERIC_ALL, EveryoneSid);
|
||
|
SetSecurityDescriptorDacl(SecurityDescriptor, TRUE, Acl, FALSE);
|
||
|
|
||
|
lsa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||
|
lsa.lpSecurityDescriptor = SecurityDescriptor;
|
||
|
lsa.bInheritHandle = FALSE;
|
||
|
|
||
|
OverlappedPipe[0].hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||
|
OverlappedPipe[1].hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||
|
|
||
|
while (TRUE) {
|
||
|
PipeH[0] = CreateNamedPipe(fullnameIn,
|
||
|
PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
|
||
|
PIPE_TYPE_BYTE,
|
||
|
PIPE_UNLIMITED_INSTANCES,
|
||
|
0,
|
||
|
0,
|
||
|
1000,
|
||
|
&lsa);
|
||
|
PipeH[1] = CreateNamedPipe(fullnameOut,
|
||
|
PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED,
|
||
|
PIPE_TYPE_BYTE,
|
||
|
PIPE_UNLIMITED_INSTANCES,
|
||
|
0,
|
||
|
0,
|
||
|
1000,
|
||
|
&lsa);
|
||
|
|
||
|
if (INVALID_HANDLE_VALUE == PipeH[0]
|
||
|
|| INVALID_HANDLE_VALUE == PipeH[1]
|
||
|
|| !PipeConnect(PipeH[0], &OverlappedPipe[0], 1000)) {
|
||
|
CloseHandle(PipeH[0]);
|
||
|
CloseHandle(PipeH[1]);
|
||
|
if (WaitForSingleObject(hEventRemoteTerm, 0) == WAIT_OBJECT_0) {
|
||
|
return 0;
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (!PipeConnect(PipeH[1], &OverlappedPipe[1], INFINITE)) {
|
||
|
CloseHandle(PipeH[0]);
|
||
|
CloseHandle(PipeH[1]);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Look For a Free Slot & if not- then terminate connection
|
||
|
for (i = 1; i < MAX_SESSION; i++) {
|
||
|
// Locate a Free Client block
|
||
|
if (!ClientList[i].Active) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (i < MAX_SESSION) {
|
||
|
// Initialize the Client
|
||
|
ClientList[i].PipeReadH = PipeH[0];
|
||
|
ClientList[i].PipeWriteH = PipeH[1];
|
||
|
ClientList[i].Active = TRUE;
|
||
|
ClientList[i].SendOutput = TRUE;
|
||
|
ClientList[i].CommandRcvd = FALSE;
|
||
|
ClientList[i].OverlappedRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||
|
ClientList[i].OverlappedWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||
|
ClientList[i].hEventTerm = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||
|
} else {
|
||
|
PrintDebuggerMsg(TRUE, FALSE, "Remote:Closing New Session - No more slots\n");
|
||
|
CloseHandle(PipeH[0]);
|
||
|
CloseHandle(PipeH[1]);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// start new thread for this connection
|
||
|
ClientList[i].hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RemoteSessionThread, &ClientList[i], 0, &ThreadID);
|
||
|
if (!ClientList[i].hThread) {
|
||
|
CloseClient(&ClientList[i]);
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL DeliverHistory(LPSESSION_TYPE MyClient, DWORD MaxLines)
|
||
|
{
|
||
|
HANDLE LogMap;
|
||
|
LPBYTE lpLog;
|
||
|
LPBYTE p;
|
||
|
DWORD i;
|
||
|
DWORD cb;
|
||
|
DWORD lines;
|
||
|
|
||
|
if (hFileLog == INVALID_HANDLE_VALUE) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
EnterCriticalSection(&csLog);
|
||
|
SetFilePointer(hFileLog, 0, NULL, FILE_BEGIN);
|
||
|
|
||
|
LogMap = CreateFileMapping(hFileLog, NULL, PAGE_READONLY, 0, 0, NULL);
|
||
|
if (LogMap == 0) {
|
||
|
LeaveCriticalSection(&csLog);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
lpLog = (PUCHAR)MapViewOfFile(LogMap, FILE_MAP_READ, 0, 0, 0);
|
||
|
if (lpLog == NULL) {
|
||
|
LeaveCriticalSection(&csLog);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
cb = GetFileSize(hFileLog, NULL);
|
||
|
p = lpLog + cb - 1;
|
||
|
i = 0;
|
||
|
lines = 0;
|
||
|
while (i < cb) {
|
||
|
if (*p == '\n') {
|
||
|
++lines;
|
||
|
}
|
||
|
if (lines == MaxLines) {
|
||
|
break;
|
||
|
}
|
||
|
--p;
|
||
|
++i;
|
||
|
}
|
||
|
|
||
|
PipeWrite(MyClient, p + 1, i, FALSE);
|
||
|
SetFilePointer(hFileLog, 0, NULL, FILE_END);
|
||
|
UnmapViewOfFile(lpLog);
|
||
|
CloseHandle(LogMap);
|
||
|
LeaveCriticalSection(&csLog);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD RemoteSessionThread(LPSESSION_TYPE MyClient)
|
||
|
{
|
||
|
DWORD cb;
|
||
|
DWORD ReadCnt;
|
||
|
SESSION_STARTUPINFO ssi;
|
||
|
LPSTR headerbuff;
|
||
|
CHAR msg[BUFFSIZE];
|
||
|
SESSION_STARTREPLY ssr;
|
||
|
SYSTEMTIME st;
|
||
|
DWORD reply = 0;
|
||
|
LPSTR ptr;
|
||
|
LPSTR pPacket;
|
||
|
|
||
|
|
||
|
GetLocalTime(&st);
|
||
|
ZeroMemory(&ssi, sizeof(ssi));
|
||
|
|
||
|
ReadFixBytes(MyClient, (LPSTR)MyClient->Name, HOSTNAMELEN - 1);
|
||
|
|
||
|
//Last four Bytes contains a code
|
||
|
memcpy((LPSTR)&reply, (LPSTR) & (MyClient->Name[11]), 4);
|
||
|
|
||
|
if (reply != MAGICNUMBER) {
|
||
|
// Unknown client
|
||
|
CloseClient(MyClient);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
ssr.MagicNumber = MAGICNUMBER;
|
||
|
ssr.Size = sizeof(ssr);
|
||
|
ssr.FileSize = 0;
|
||
|
|
||
|
PipeWrite(MyClient, (PUCHAR)&ssr, sizeof(ssr), FALSE);
|
||
|
|
||
|
if (ReadFixBytes(MyClient, (char*)&(ssi.Size), sizeof(ssi.Size)) != 0) {
|
||
|
CloseClient(MyClient);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if (ssi.Size > 1024) {
|
||
|
sprintf(msg, "%s", "Server:Unknown Header..Terminating session\n");
|
||
|
PipeWrite(MyClient, (PUCHAR)msg, strlen(msg), FALSE);
|
||
|
CloseClient(MyClient);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if ((headerbuff = (char*)calloc(ssi.Size, 1)) == NULL) {
|
||
|
sprintf(msg, "%s", "Server:Not Enough Memory..Terminating session\n");
|
||
|
PipeWrite(MyClient, (PUCHAR)msg, strlen(msg), FALSE);
|
||
|
CloseClient(MyClient);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
ReadCnt = ssi.Size - sizeof(ssi.Size);
|
||
|
if (ReadFixBytes(MyClient, (char*)headerbuff, ReadCnt) != 0) {
|
||
|
CloseClient(MyClient);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
memcpy((char*)&ssi + sizeof(ssi.Size), headerbuff, sizeof(ssi) - sizeof(ssi.Size));
|
||
|
free(headerbuff);
|
||
|
|
||
|
// Version
|
||
|
if (ssi.Version != VERSION) {
|
||
|
sprintf(msg, "Remote Warning:Server Version=%d Client Version=%d\n", VERSION, ssi.Version);
|
||
|
PipeWrite(MyClient, (PUCHAR)msg, strlen(msg), FALSE);
|
||
|
}
|
||
|
|
||
|
// Name
|
||
|
memcpy(MyClient->Name, ssi.ClientName, 15);
|
||
|
MyClient->Name[14] = 0;
|
||
|
|
||
|
DeliverHistory(MyClient, ssi.LinesToSend);
|
||
|
|
||
|
PrintDebuggerMsg(TRUE, FALSE, "Remote:Connected To %s [%02d:%02d]\n", MyClient->Name, st.wHour, st.wMinute);
|
||
|
|
||
|
MyClient->lpBuf = (PSTR)malloc(BUFFSIZE);
|
||
|
|
||
|
CmdExecutePrompt(TRUE, FALSE);
|
||
|
|
||
|
while (TRUE) {
|
||
|
cb = PipeRead(MyClient, (PUCHAR)MyClient->lpBuf, BUFFSIZE);
|
||
|
if (!cb) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
MyClient->lpBuf[cb] = 0;
|
||
|
MyClient->CommandRcvd = TRUE;
|
||
|
|
||
|
if (FilterCommand(MyClient, MyClient->lpBuf, cb)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
ptr = &MyClient->lpBuf[strlen(MyClient->lpBuf) - 1];
|
||
|
while (*ptr == '\n' || *ptr == '\r') {
|
||
|
*ptr-- = '\0';
|
||
|
}
|
||
|
|
||
|
PrintCmdMsg(MyClient, FALSE, FALSE, (LPSTR)MyClient->lpBuf);
|
||
|
|
||
|
pPacket = (PSTR)malloc(strlen(MyClient->lpBuf) + 1);
|
||
|
Assert(pPacket);
|
||
|
strcpy(pPacket, MyClient->lpBuf);
|
||
|
PostMessage(Views[cmdView].hwndClient, WU_LOG_REMOTE_CMD, TRUE, (LPARAM)pPacket);
|
||
|
}
|
||
|
|
||
|
PrintDebuggerMsg(TRUE, FALSE, "Remote:Disconnected From %s [%02d:%02d]\n", MyClient->Name, st.wHour, st.wMinute);
|
||
|
|
||
|
CloseClient(MyClient);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
VOID SendClientOutput(LPCSTR lpBuf, DWORD cbBuf)
|
||
|
{
|
||
|
DWORD i;
|
||
|
|
||
|
for (i=0;i<MAX_SESSION;i++) {
|
||
|
if (ClientList[i].Active) {
|
||
|
PipeWrite( &ClientList[i], (PUCHAR) lpBuf, cbBuf, TRUE );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
|
||
|
BOOL FilterCommand(LPSESSION_TYPE cl, LPSTR buf, DWORD cb)
|
||
|
{
|
||
|
SYSTEMTIME st;
|
||
|
char inp_buf[4096];
|
||
|
DWORD ThreadID;
|
||
|
LPSTR mssg;
|
||
|
LPSTR ack;
|
||
|
BOOL ret = FALSE;
|
||
|
|
||
|
if (!cb) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
buf[cb] = 0;
|
||
|
|
||
|
GetLocalTime(&st);
|
||
|
|
||
|
if (buf[0] == COMMANDCHAR) {
|
||
|
switch (tolower(buf[1])) {
|
||
|
case 'o':
|
||
|
cl->SendOutput = !cl->SendOutput;
|
||
|
break;
|
||
|
case 's':
|
||
|
SendStatus(cl);
|
||
|
break;
|
||
|
case 'p':
|
||
|
mssg = (LPSTR)calloc(4096, 1);
|
||
|
ack = "Remote:Popup Shown..\n";
|
||
|
|
||
|
if (!mssg) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
sprintf(mssg, "From %s [%d:%d]\n\n%s\n", cl->Name, st.wHour, st.wMinute, &buf[2]);
|
||
|
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ShowPopupThread, mssg, 0, &ThreadID);
|
||
|
PipeWrite(cl, (PUCHAR)ack, strlen(ack), FALSE);
|
||
|
break;
|
||
|
case 'm':
|
||
|
buf[cb - 2] = 0;
|
||
|
PrintCmdMsg(cl, TRUE, TRUE, buf);
|
||
|
break;
|
||
|
case '@':
|
||
|
buf[cb - 2] = 0;
|
||
|
PrintCmdMsg(cl, TRUE, TRUE, buf);
|
||
|
|
||
|
// Remove the first @ sign
|
||
|
|
||
|
MoveMemory(buf, &buf[1], cb - 1);
|
||
|
buf[cb - 1] = ' ';
|
||
|
return FALSE;
|
||
|
break;
|
||
|
default:
|
||
|
sprintf(inp_buf, "%s", "** Unknown Command **\n");
|
||
|
PipeWrite(cl, (PUCHAR)inp_buf, strlen(inp_buf), FALSE);
|
||
|
|
||
|
// fall through
|
||
|
case 'h':
|
||
|
case 'H':
|
||
|
sprintf(inp_buf, "%cM: To Send Message\n", COMMANDCHAR);
|
||
|
PipeWrite(cl, (PUCHAR)inp_buf, strlen(inp_buf), FALSE);
|
||
|
sprintf(inp_buf, "%cP: To Generate popup\n", COMMANDCHAR);
|
||
|
PipeWrite(cl, (PUCHAR)inp_buf, strlen(inp_buf), FALSE);
|
||
|
sprintf(inp_buf, "%cK: To kill the server\n", COMMANDCHAR);
|
||
|
PipeWrite(cl, (PUCHAR)inp_buf, strlen(inp_buf), FALSE);
|
||
|
sprintf(inp_buf, "%cH: This Help\n", COMMANDCHAR);
|
||
|
PipeWrite(cl, (PUCHAR)inp_buf, strlen(inp_buf), FALSE);
|
||
|
break;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
if (buf[0] < 26) {
|
||
|
if (buf[0] == CTRLC) {
|
||
|
cl->CommandRcvd = FALSE;
|
||
|
DispatchCtrlCEvent();
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID SendStatus(LPSESSION_TYPE cl)
|
||
|
{
|
||
|
CHAR buf[1024];
|
||
|
DWORD i;
|
||
|
LPSTR env;
|
||
|
DWORD ver;
|
||
|
|
||
|
env = GetEnvironmentStrings();
|
||
|
ver = GetVersion();
|
||
|
|
||
|
sprintf(buf, "Server = %s PIPE=%s\n", HostName, PipeName);
|
||
|
PipeWrite(cl, (PUCHAR)buf, strlen(buf), FALSE);
|
||
|
|
||
|
sprintf(buf, "Build = %d \n", ((WORD*)&ver)[1]);
|
||
|
PipeWrite(cl, (PUCHAR)buf, strlen(buf), FALSE);
|
||
|
|
||
|
for (i = 1; i < MAX_SESSION; i++) {
|
||
|
if (ClientList[i].Active) {
|
||
|
sprintf(buf, "ACTIVE SESSION=%s\n", ClientList[i].Name);
|
||
|
PipeWrite(cl, (PUCHAR)buf, strlen(buf), FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sprintf(buf, "====================\n"/*,Server,PipeName*/);
|
||
|
PipeWrite(cl, (PUCHAR)buf, strlen(buf), FALSE);
|
||
|
|
||
|
sprintf(buf, "ENVIRONMENT VARIABLES\n"/*,Server,PipeName*/);
|
||
|
PipeWrite(cl, (PUCHAR)buf, strlen(buf), FALSE);
|
||
|
|
||
|
sprintf(buf, "====================\n"/*,Server,PipeName*/);
|
||
|
PipeWrite(cl, (PUCHAR)buf, strlen(buf), FALSE);
|
||
|
|
||
|
__try {
|
||
|
while (*env != 0) {
|
||
|
sprintf(buf, "%s\n", env);
|
||
|
PipeWrite(cl, (PUCHAR)buf, strlen(buf), FALSE);
|
||
|
|
||
|
while (*(env++) != 0);
|
||
|
}
|
||
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
sprintf(buf, "Exception Generated Getting Environment Block\n", env);
|
||
|
PipeWrite(cl, (PUCHAR)buf, strlen(buf), FALSE);
|
||
|
}
|
||
|
|
||
|
sprintf(buf, "====================\n", Server, PipeName);
|
||
|
PipeWrite(cl, (PUCHAR)buf, strlen(buf), FALSE);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD ShowPopupThread(LPSTR mssg)
|
||
|
{
|
||
|
MessageBox(GetActiveWindow(), mssg, "**WinDbg Remote**", MB_OK | MB_SETFOREGROUND);
|
||
|
free(mssg);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID InitClientList(void)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < MAX_SESSION; i++) {
|
||
|
ZeroMemory(ClientList[i].Name, HOSTNAMELEN);
|
||
|
ClientList[i].PipeReadH = INVALID_HANDLE_VALUE;
|
||
|
ClientList[i].PipeWriteH = INVALID_HANDLE_VALUE;
|
||
|
ClientList[i].Active = FALSE;
|
||
|
ClientList[i].CommandRcvd = FALSE;
|
||
|
ClientList[i].SendOutput = FALSE;
|
||
|
ClientList[i].hThread = NULL;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
ReadFixBytes(
|
||
|
LPSESSION_TYPE MyClient,
|
||
|
LPSTR lpBuf,
|
||
|
DWORD cbRead
|
||
|
)
|
||
|
{
|
||
|
DWORD cb;
|
||
|
DWORD xyzBytesRead = 0;
|
||
|
DWORD xyzBytesToRead = cbRead;
|
||
|
LPSTR xyzbuf = lpBuf;
|
||
|
|
||
|
while (xyzBytesToRead != 0) {
|
||
|
cb = PipeRead(MyClient, (PUCHAR)xyzbuf, xyzBytesToRead);
|
||
|
if (!cb) {
|
||
|
return xyzBytesToRead;
|
||
|
}
|
||
|
|
||
|
xyzBytesToRead -= cb;
|
||
|
xyzbuf += cb;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID CloseClient(SESSION_TYPE* Client)
|
||
|
{
|
||
|
ZeroMemory(Client->Name, HOSTNAMELEN);
|
||
|
|
||
|
if (Client->PipeReadH != INVALID_HANDLE_VALUE) {
|
||
|
CloseHandle(Client->PipeReadH);
|
||
|
Client->PipeReadH = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
|
||
|
if (Client->PipeWriteH != INVALID_HANDLE_VALUE) {
|
||
|
CloseHandle(Client->PipeWriteH);
|
||
|
Client->PipeWriteH = INVALID_HANDLE_VALUE;
|
||
|
}
|
||
|
|
||
|
Client->Active = FALSE; //Keep it last else synch problem.
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
PrintCmdMsg(
|
||
|
LPSESSION_TYPE MyClient,
|
||
|
BOOL fInsert,
|
||
|
BOOL fLog,
|
||
|
LPSTR InpBuf
|
||
|
)
|
||
|
{
|
||
|
SYSTEMTIME st;
|
||
|
|
||
|
GetLocalTime(&st);
|
||
|
|
||
|
PrintDebuggerMsg(
|
||
|
fInsert,
|
||
|
fLog,
|
||
|
"%-15s [%-15s %2d:%02d %2d/%2d/%4d]\n",
|
||
|
InpBuf,
|
||
|
MyClient->Name,
|
||
|
st.wHour,
|
||
|
st.wMinute,
|
||
|
st.wMonth,
|
||
|
st.wDay,
|
||
|
st.wYear);
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID PrintDebuggerMsg(BOOL fInsert, BOOL fLog, LPSTR lpFmt, ...)
|
||
|
{
|
||
|
LPSTR lpText;
|
||
|
va_list vargs;
|
||
|
|
||
|
lpText = (PSTR)malloc(MAX_VAR_MSG_TXT);
|
||
|
|
||
|
va_start(vargs, lpFmt);
|
||
|
_vsnprintf(lpText, MAX_VAR_MSG_TXT, lpFmt, vargs);
|
||
|
va_end(vargs);
|
||
|
|
||
|
if (fLog) {
|
||
|
LogFileWrite((PUCHAR)lpText, strlen(lpText));
|
||
|
}
|
||
|
|
||
|
PostMessage(Views[cmdView].hwndClient, WU_LOG_REMOTE_MSG, fInsert, (LPARAM)lpText);
|
||
|
}
|