mirror of
https://github.com/reactos/reactos.git
synced 2024-10-31 20:02:55 +00:00
252 lines
8.5 KiB
C++
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");
|
|
|
|
*/
|