3 * Copyright (c) 2004, Skywing (skywing@valhallalegends.com)
4 * Released under the GNU GPL for the ReactOS project
6 * This program can be used to spy on a named pipe in Windows NT(+)
7 * or ReactOS. It is particularly intended to be used for
8 * understanding the remote kernel debugging protocol used
13 * PipeSpy \\.\pipe\debug_server \\.\pipe\debug_client > PipeSpy.log
15 * VMware: act as client, connect to \\.\pipe\debug_server, pipe is connected
18 * WinDbg -k com:pipe,port=\\.\pipe\debug_client,resets=0
22 * This program hasn't really been tested against ReactOS, and has only
23 * been built with Visual Studio .NET 2003.
29 HANDLE g_DebugServerPipe
, g_DebugClientPipe
;
30 CRITICAL_SECTION g_OutputLock
;
32 void dumphex(const char *buf
, int len
, int pos
)
35 for(j
= 0; j
< len
; j
+= 16) {
36 for(i
= 0; i
< 16; i
++) {
38 printf("%02x%c", (unsigned char)buf
[i
+ j
], j
+ i
+ 1 == pos
? '*' : ' ');
42 for(i
= 0; i
< 16; i
++) {
44 printf("%c", buf
[i
+ j
] >= ' ' ? buf
[i
+ j
] : '.');
53 PIPEBUF_INITIAL_SIZE
= 4096,
54 PIPEBUF_MAX_SIZE
= 16384
57 typedef struct _READ_OVERLAPPED
{
58 OVERLAPPED ReadOverlapped
;
60 HANDLE Pipe
, OtherPipe
;
65 VOID WINAPI
WritePipeCompletion(DWORD dwErrorCode
, DWORD dwNumberOfBytesTransferred
, LPOVERLAPPED lpOverlapped
)
68 EnterCriticalSection(&g_OutputLock
);
69 printf(lpOverlapped
->hEvent
? "Server> Error %u writing to client pipe\n" : "Client> Error %u writing to server pipe\n", dwErrorCode
);
70 LeaveCriticalSection(&g_OutputLock
);
73 free((void*)lpOverlapped
);
76 VOID WINAPI
ReadPipeCompletion(DWORD dwErrorCode
, DWORD dwNumberOfBytesTransferred
, LPOVERLAPPED lpOverlapped
)
78 READ_OVERLAPPED
* ReadOverlapped
= (READ_OVERLAPPED
*)lpOverlapped
;
79 LPOVERLAPPED WriteOverlapped
;
81 EnterCriticalSection(&g_OutputLock
);
84 printf(ReadOverlapped
->Server
? "Server> Error %u reading from pipe\n" : "Client> Error %u reading from pipe\n", dwErrorCode
);
85 ReadOverlapped
->Connected
= false;
87 SYSTEMTIME SystemTime
;
89 GetLocalTime(&SystemTime
);
90 printf(ReadOverlapped
->Server
? "Server> [%02u:%02u:%02u.%03u] Received %u byte message:\n" : "Client> [%02u:%02u:%02u.%03u] Received %u byte message:\n",
91 SystemTime
.wHour
, SystemTime
.wMinute
, SystemTime
.wSecond
, SystemTime
.wMilliseconds
, dwNumberOfBytesTransferred
);
92 dumphex(ReadOverlapped
->Buffer
, (int)dwNumberOfBytesTransferred
, -1);
96 LeaveCriticalSection(&g_OutputLock
);
98 WriteOverlapped
= (LPOVERLAPPED
)malloc(sizeof(OVERLAPPED
)+dwNumberOfBytesTransferred
);
101 printf(ReadOverlapped
->Server
? "Server> Out of memory\n" : "Client> Out of memory\n");
103 ZeroMemory(WriteOverlapped
, sizeof(OVERLAPPED
));
104 WriteOverlapped
->hEvent
= (HANDLE
)ReadOverlapped
->Server
;
105 memcpy(((char*)WriteOverlapped
)+sizeof(OVERLAPPED
), ReadOverlapped
->Buffer
, dwNumberOfBytesTransferred
);
106 WriteFileEx(ReadOverlapped
->OtherPipe
, ((char*)WriteOverlapped
)+sizeof(OVERLAPPED
), dwNumberOfBytesTransferred
, WriteOverlapped
,
107 WritePipeCompletion
);
111 ZeroMemory(ReadOverlapped
, sizeof(OVERLAPPED
));
112 ReadFileEx(ReadOverlapped
->Pipe
, ReadOverlapped
->Buffer
, PIPEBUF_INITIAL_SIZE
, &ReadOverlapped
->ReadOverlapped
, ReadPipeCompletion
);
116 void __cdecl
pipeserver(void* param
)
118 READ_OVERLAPPED ReadOverlapped
;
120 ReadOverlapped
.Pipe
= (HANDLE
)param
, ReadOverlapped
.OtherPipe
= ReadOverlapped
.Pipe
== g_DebugServerPipe
? g_DebugClientPipe
: g_DebugServerPipe
;
121 ReadOverlapped
.Server
= ReadOverlapped
.Pipe
== g_DebugServerPipe
;
122 ReadOverlapped
.Buffer
= (char*)malloc(PIPEBUF_INITIAL_SIZE
);
125 if(!ConnectNamedPipe(ReadOverlapped
.Pipe
, 0) && GetLastError() != ERROR_PIPE_CONNECTED
) {
126 printf(ReadOverlapped
.Server
? "Server> Error %u accepting pipe connection\n" : "Client> Error %u accepting pipe connection\n",
131 ReadOverlapped
.Connected
= true;
132 printf(ReadOverlapped
.Server
? "Server> Connected\n" : "Client> Connected\n");
134 ZeroMemory(&ReadOverlapped
.ReadOverlapped
, sizeof(OVERLAPPED
));
135 ReadFileEx(ReadOverlapped
.Pipe
, ReadOverlapped
.Buffer
, PIPEBUF_INITIAL_SIZE
, &ReadOverlapped
.ReadOverlapped
, ReadPipeCompletion
);
138 SleepEx(INFINITE
, TRUE
);
139 } while(ReadOverlapped
.Connected
) ;
141 DisconnectNamedPipe(ReadOverlapped
.Pipe
);
142 printf(ReadOverlapped
.Server
? "Server> Disconnected\n" : "Client> Disconnected\n");
145 printf(ReadOverlapped
.Server
? "Server> Shutting down\n" : "Client> Shutting down\n");
147 free(ReadOverlapped
.Buffer
);
148 CloseHandle(ReadOverlapped
.Pipe
);
152 int main(int ac
, char **av
)
155 printf("syntax: pipespy serverpipe clientpipe\n");
159 g_DebugServerPipe
= CreateNamedPipe(av
[1], PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
, PIPE_TYPE_BYTE
| PIPE_READMODE_BYTE
| PIPE_WAIT
,
160 1, 4096, 4096, NMPWAIT_WAIT_FOREVER
, 0);
162 if(g_DebugServerPipe
== INVALID_HANDLE_VALUE
) {
163 printf("Error %u creating server pipe\n", GetLastError());
167 g_DebugClientPipe
= CreateNamedPipe(av
[2], PIPE_ACCESS_DUPLEX
| FILE_FLAG_OVERLAPPED
, PIPE_TYPE_BYTE
| PIPE_READMODE_BYTE
| PIPE_WAIT
,
168 1, 4096, 4096, NMPWAIT_WAIT_FOREVER
, 0);
170 if(g_DebugClientPipe
== INVALID_HANDLE_VALUE
) {
171 printf("Error %u creating client pipe\n", GetLastError());
172 CloseHandle(g_DebugServerPipe
);
176 InitializeCriticalSection(&g_OutputLock
);
177 _beginthread(pipeserver
, 0, (void*)g_DebugServerPipe
);
178 pipeserver((void*)g_DebugClientPipe
);
179 DeleteCriticalSection(&g_OutputLock
);
189 if(BufferSize > PIPEBUF_MAX_SIZE) {
190 char* NewBuf = (char*)realloc(Buffer, PIPEBUF_MAX_SIZE);
194 BufferSize = PIPEBUF_MAX_SIZE;
201 if(ReadFile(Pipe, Buffer+BufferPos, BufferSize-BufferPos, &Read, 0)) {
207 Error = GetLastError();
209 printf("Error=%u read=%u\n", Error, Read);
211 if(Error != ERROR_MORE_DATA) {
212 printf(Server ? "Server> Error %u reading from pipe\n" : "Client> Error %u reading from pipe\n", GetLastError());
216 NewBuf = (char*)realloc(Buffer, BufferSize << 1);
219 printf(Server ? "Server> Out of memory\n" : "Client> Out of memory\n");
231 WriteOverlapped = (LPOVERLAPPED)malloc(sizeof(OVERLAPPED)+BufferPos);
234 printf(Server ? "Server> Out of memory\n" : "Client> Out of memory\n");
236 ZeroMemory(WriteOverlapped, sizeof(OVERLAPPED));
237 memcpy(((char*)WriteOverlapped)+sizeof(OVERLAPPED), Buffer, BufferPos);
238 WriteFileEx(OtherPipe, ((char*)WriteOverlapped)+sizeof(OVERLAPPED), BufferPos, WriteOverlapped, WritePipeCompletion);
241 EnterCriticalSection(&g_OutputLock);
242 printf(Server ? "Server> Received %u byte message:\n" : "Client> Received %u byte message:\n", BufferPos);
243 dumphex(Buffer, (int)BufferPos, -1);
245 LeaveCriticalSection(&g_OutputLock);
248 DisconnectNamedPipe(Pipe);
249 printf(Server ? "Server> Disconnected\n" : "Client> Disconnected\n");