reactos/sdk/tools/pipetools/pipespy.cpp

252 lines
8.5 KiB
C++

/*
* PipeSpy
* Copyright (c) 2004, Skywing (skywing@valhallalegends.com)
* Released under the GNU GPL for the ReactOS project
*
* This program can be used to spy on a named pipe in Windows NT(+)
* or ReactOS. It is particularly intended to be used for
* understanding the remote kernel debugging protocol used
* by windows kd.
*
* USE:
*
* PipeSpy \\.\pipe\debug_server \\.\pipe\debug_client > PipeSpy.log
*
* VMware: act as client, connect to \\.\pipe\debug_server, pipe is connected
* to application
*
* WinDbg -k com:pipe,port=\\.\pipe\debug_client,resets=0
*
* NOTE:
*
* This program hasn't really been tested against ReactOS, and has only
* been built with Visual Studio .NET 2003.
*/
#include <process.h>
#include <windows.h>
#include <stdio.h>
HANDLE g_DebugServerPipe, g_DebugClientPipe;
CRITICAL_SECTION g_OutputLock;
void dumphex(const char *buf, int len, int pos)
{
int i, j;
for(j = 0; j < len; j += 16) {
for(i = 0; i < 16; i++) {
if(i + j < len)
printf("%02x%c", (unsigned char)buf[i + j], j + i + 1 == pos ? '*' : ' ');
else
printf(" ");
}
for(i = 0; i < 16; i++) {
if(i + j < len)
printf("%c", buf[i + j] >= ' ' ? buf[i + j] : '.');
else
printf(" ");
}
printf("\n");
}
}
enum {
PIPEBUF_INITIAL_SIZE = 4096,
PIPEBUF_MAX_SIZE = 16384
};
typedef struct _READ_OVERLAPPED {
OVERLAPPED ReadOverlapped;
char* Buffer;
HANDLE Pipe, OtherPipe;
bool Server;
bool Connected;
} READ_OVERLAPPED;
VOID WINAPI WritePipeCompletion(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
{
if(dwErrorCode) {
EnterCriticalSection(&g_OutputLock);
printf(lpOverlapped->hEvent ? "Server> Error %u writing to client pipe\n" : "Client> Error %u writing to server pipe\n", dwErrorCode);
LeaveCriticalSection(&g_OutputLock);
}
free((void*)lpOverlapped);
}
VOID WINAPI ReadPipeCompletion(DWORD dwErrorCode, DWORD dwNumberOfBytesTransferred, LPOVERLAPPED lpOverlapped)
{
READ_OVERLAPPED* ReadOverlapped = (READ_OVERLAPPED*)lpOverlapped;
LPOVERLAPPED WriteOverlapped;
EnterCriticalSection(&g_OutputLock);
if(dwErrorCode) {
printf(ReadOverlapped->Server ? "Server> Error %u reading from pipe\n" : "Client> Error %u reading from pipe\n", dwErrorCode);
ReadOverlapped->Connected = false;
} else {
SYSTEMTIME SystemTime;
GetLocalTime(&SystemTime);
printf(ReadOverlapped->Server ? "Server> [%02u:%02u:%02u.%03u] Received %u byte message:\n" : "Client> [%02u:%02u:%02u.%03u] Received %u byte message:\n",
SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond, SystemTime.wMilliseconds, dwNumberOfBytesTransferred);
dumphex(ReadOverlapped->Buffer, (int)dwNumberOfBytesTransferred, -1);
printf("\n");
}
LeaveCriticalSection(&g_OutputLock);
WriteOverlapped = (LPOVERLAPPED)malloc(sizeof(OVERLAPPED)+dwNumberOfBytesTransferred);
if(!WriteOverlapped)
printf(ReadOverlapped->Server ? "Server> Out of memory\n" : "Client> Out of memory\n");
else {
ZeroMemory(WriteOverlapped, sizeof(OVERLAPPED));
WriteOverlapped->hEvent = (HANDLE)ReadOverlapped->Server;
memcpy(((char*)WriteOverlapped)+sizeof(OVERLAPPED), ReadOverlapped->Buffer, dwNumberOfBytesTransferred);
WriteFileEx(ReadOverlapped->OtherPipe, ((char*)WriteOverlapped)+sizeof(OVERLAPPED), dwNumberOfBytesTransferred, WriteOverlapped,
WritePipeCompletion);
}
if(!dwErrorCode) {
ZeroMemory(ReadOverlapped, sizeof(OVERLAPPED));
ReadFileEx(ReadOverlapped->Pipe, ReadOverlapped->Buffer, PIPEBUF_INITIAL_SIZE, &ReadOverlapped->ReadOverlapped, ReadPipeCompletion);
}
}
void __cdecl pipeserver(void* param)
{
READ_OVERLAPPED ReadOverlapped;
ReadOverlapped.Pipe = (HANDLE)param, ReadOverlapped.OtherPipe = ReadOverlapped.Pipe == g_DebugServerPipe ? g_DebugClientPipe : g_DebugServerPipe;
ReadOverlapped.Server = ReadOverlapped.Pipe == g_DebugServerPipe;
ReadOverlapped.Buffer = (char*)malloc(PIPEBUF_INITIAL_SIZE);
for(;;) {
if(!ConnectNamedPipe(ReadOverlapped.Pipe, 0) && GetLastError() != ERROR_PIPE_CONNECTED) {
printf(ReadOverlapped.Server ? "Server> Error %u accepting pipe connection\n" : "Client> Error %u accepting pipe connection\n",
GetLastError());
break;
}
ReadOverlapped.Connected = true;
printf(ReadOverlapped.Server ? "Server> Connected\n" : "Client> Connected\n");
ZeroMemory(&ReadOverlapped.ReadOverlapped, sizeof(OVERLAPPED));
ReadFileEx(ReadOverlapped.Pipe, ReadOverlapped.Buffer, PIPEBUF_INITIAL_SIZE, &ReadOverlapped.ReadOverlapped, ReadPipeCompletion);
do {
SleepEx(INFINITE, TRUE);
} while(ReadOverlapped.Connected) ;
DisconnectNamedPipe(ReadOverlapped.Pipe);
printf(ReadOverlapped.Server ? "Server> Disconnected\n" : "Client> Disconnected\n");
}
printf(ReadOverlapped.Server ? "Server> Shutting down\n" : "Client> Shutting down\n");
free(ReadOverlapped.Buffer);
CloseHandle(ReadOverlapped.Pipe);
SleepEx(0, TRUE);
}
int main(int ac, char **av)
{
if(ac != 3) {
printf("syntax: pipespy serverpipe clientpipe\n");
return 0;
}
g_DebugServerPipe = CreateNamedPipe(av[1], PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
1, 4096, 4096, NMPWAIT_WAIT_FOREVER, 0);
if(g_DebugServerPipe == INVALID_HANDLE_VALUE) {
printf("Error %u creating server pipe\n", GetLastError());
return 0;
}
g_DebugClientPipe = CreateNamedPipe(av[2], PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
1, 4096, 4096, NMPWAIT_WAIT_FOREVER, 0);
if(g_DebugClientPipe == INVALID_HANDLE_VALUE) {
printf("Error %u creating client pipe\n", GetLastError());
CloseHandle(g_DebugServerPipe);
return 0;
}
InitializeCriticalSection(&g_OutputLock);
_beginthread(pipeserver, 0, (void*)g_DebugServerPipe);
pipeserver((void*)g_DebugClientPipe);
DeleteCriticalSection(&g_OutputLock);
return 0;
}
/*
while(!Error) {
SleepEx(0, TRUE);
BufferPos = 0;
if(BufferSize > PIPEBUF_MAX_SIZE) {
char* NewBuf = (char*)realloc(Buffer, PIPEBUF_MAX_SIZE);
if(NewBuf) {
Buffer = NewBuf;
BufferSize = PIPEBUF_MAX_SIZE;
}
}
for(;;) {
char* NewBuf;
if(ReadFile(Pipe, Buffer+BufferPos, BufferSize-BufferPos, &Read, 0)) {
BufferPos += Read;
Error = 0;
break;
}
Error = GetLastError();
printf("Error=%u read=%u\n", Error, Read);
if(Error != ERROR_MORE_DATA) {
printf(Server ? "Server> Error %u reading from pipe\n" : "Client> Error %u reading from pipe\n", GetLastError());
break;
}
NewBuf = (char*)realloc(Buffer, BufferSize << 1);
if(!NewBuf) {
printf(Server ? "Server> Out of memory\n" : "Client> Out of memory\n");
break;
}
BufferSize <<= 1;
BufferPos += Read;
Error = 0;
}
if(Error)
break;
WriteOverlapped = (LPOVERLAPPED)malloc(sizeof(OVERLAPPED)+BufferPos);
if(!WriteOverlapped)
printf(Server ? "Server> Out of memory\n" : "Client> Out of memory\n");
else {
ZeroMemory(WriteOverlapped, sizeof(OVERLAPPED));
memcpy(((char*)WriteOverlapped)+sizeof(OVERLAPPED), Buffer, BufferPos);
WriteFileEx(OtherPipe, ((char*)WriteOverlapped)+sizeof(OVERLAPPED), BufferPos, WriteOverlapped, WritePipeCompletion);
}
EnterCriticalSection(&g_OutputLock);
printf(Server ? "Server> Received %u byte message:\n" : "Client> Received %u byte message:\n", BufferPos);
dumphex(Buffer, (int)BufferPos, -1);
printf("\n");
LeaveCriticalSection(&g_OutputLock);
}
DisconnectNamedPipe(Pipe);
printf(Server ? "Server> Disconnected\n" : "Client> Disconnected\n");
*/