ReactOS  0.4.14-dev-115-g4576127
gdb2.cpp
Go to the documentation of this file.
1 /*
2  * gdb2 - gdb output splitter
3  *
4  * Copyright (C) 2000,2001 Nedko Arnaoudov <nedkohome@atia.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; see the file COPYING. If not, write to
18  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
22 #include "ph.h"
23 
24 #define GDB_INITIAL_COMMAND "gdb.exe"
25 #define PARAMS_SEPARATOR " "
26 #define PARAMS_SEPARATOR_LEN strlen(PARAMS_SEPARATOR);
27 
28 void DisplayError(const char *pszAPI);
29 void ReadAndHandleOutput(HANDLE hPipeRead);
30 void PrepAndLaunchRedirectedChild(HANDLE hChildStdOut,
31  HANDLE hChildStdIn,
32  HANDLE hChildStdErr,
33  char *pchCommandLine);
34 
37 HANDLE hStdIn = NULL; // Handle to parents std input.
39 
40 int main(int argc, char* argv[])
41 {
42  HANDLE hOutputReadTmp,hOutputRead,hOutputWrite;
43  HANDLE hInputWriteTmp,hInputRead,hInputWrite;
44  HANDLE hErrorWrite;
46  DWORD ThreadId;
48 
49  // Set up the security attributes struct.
50  sa.nLength= sizeof(SECURITY_ATTRIBUTES);
51  sa.lpSecurityDescriptor = NULL;
52  sa.bInheritHandle = TRUE;
53 
54 
55  // Create the child output pipe.
56  if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0))
57  DisplayError("CreatePipe");
58 
59 
60  // Create a duplicate of the output write handle for the std error
61  // write handle. This is necessary in case the child application
62  // closes one of its std output handles.
63  if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite,
64  GetCurrentProcess(),&hErrorWrite,0,
66  DisplayError("DuplicateHandle");
67 
68 
69  // Create the child input pipe.
70  if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0))
71  DisplayError("CreatePipe");
72 
73 
74  // Create new output read handle and the input write handles. Set
75  // the Properties to FALSE. Otherwise, the child inherits the
76  // properties and, as a result, non-closeable handles to the pipes
77  // are created.
78  if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp,
80  &hOutputRead, // Address of new handle.
81  0,FALSE, // Make it uninheritable.
83  DisplayError("DupliateHandle");
84 
85  if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp,
87  &hInputWrite, // Address of new handle.
88  0,FALSE, // Make it uninheritable.
90  DisplayError("DupliateHandle");
91 
92 
93  // Close inheritable copies of the handles you do not want to be
94  // inherited.
95  if (!CloseHandle(hOutputReadTmp)) DisplayError("CloseHandle");
96  if (!CloseHandle(hInputWriteTmp)) DisplayError("CloseHandle");
97 
98 
99  // Get std input handle so you can close it and force the ReadFile to
100  // fail when you want the input thread to exit.
103  DisplayError("GetStdHandle");
104 
105  SetConsoleTitle("gdb control console");
106 
108 
109  // get parameters length
110  for (int i = 1 ; i < argc ; i++)
112 
113  size++; // terminating null
114 
115  char *pszCommandLine = new char [size];
116  if (!pszCommandLine)
117  {
118  printf("out of memory.\n");
119  return -1;
120  }
121 
122  strcpy(pszCommandLine,GDB_INITIAL_COMMAND);
123  for (int i = 1 ; i < argc ; i++)
124  {
125  strcat(pszCommandLine,PARAMS_SEPARATOR);
126  strcat(pszCommandLine,argv[i]);
127  }
128 
129  PrepAndLaunchRedirectedChild(hOutputWrite,hInputRead,hErrorWrite,pszCommandLine);
130 
131 
132  // Close pipe handles (do not continue to modify the parent).
133  // You need to make sure that no handles to the write end of the
134  // output pipe are maintained in this process or else the pipe will
135  // not close when the child process exits and the ReadFile will hang.
136  if (!CloseHandle(hOutputWrite)) DisplayError("CloseHandle");
137  if (!CloseHandle(hInputRead )) DisplayError("CloseHandle");
138  if (!CloseHandle(hErrorWrite)) DisplayError("CloseHandle");
139 
140 
141  // Launch the thread that gets the input and sends it to the child.
143  (LPVOID)hInputWrite,0,&ThreadId);
144  if (hThread == NULL) DisplayError("CreateThread");
145 
146 
147  // Read the child's output.
148  ReadAndHandleOutput(hOutputRead);
149  // Redirection is complete
150 
151 
152  // Force the read on the input to return by closing the stdin handle.
153  if (!CloseHandle(hStdIn)) DisplayError("CloseHandle");
154 
155 
156  // Tell the thread to exit and wait for thread to die.
157  bRunThread = FALSE;
158 
160  DisplayError("WaitForSingleObject");
161 
162  if (!CloseHandle(hOutputRead)) DisplayError("CloseHandle");
163  if (!CloseHandle(hInputWrite)) DisplayError("CloseHandle");
164 
165  return 0;
166 }
167 
169 // PrepAndLaunchRedirectedChild
170 // Sets up STARTUPINFO structure, and launches redirected child.
173  HANDLE hChildStdIn,
174  HANDLE hChildStdErr,
175  char *pchCommandLine)
176 {
178  STARTUPINFO si;
179  static CHAR Title[] = "debugged program console";
180 
181  // Set up the start up info struct.
182  ZeroMemory(&si,sizeof(STARTUPINFO));
183  si.cb = sizeof(STARTUPINFO);
185  si.hStdOutput = hChildStdOut;
186  si.hStdInput = hChildStdIn;
187  si.hStdError = hChildStdErr;
188  si.lpTitle = Title;
189  // Use this if you want to hide the child:
190  // si.wShowWindow = SW_HIDE;
191  // Note that dwFlags must include STARTF_USESHOWWINDOW if you want to
192  // use the wShowWindow flags.
193 
194 
195  // Launch the process that you want to redirect (in this case,
196  // Child.exe). Make sure Child.exe is in the same directory as
197  // redirect.c launch redirect from a command line to prevent location
198  // confusion.
199  if (!CreateProcess(NULL,pchCommandLine,NULL,NULL,TRUE,
201  DisplayError("CreateProcess");
202 
203 
204  // Set global child process handle to cause threads to exit.
205  hChildProcess = pi.hProcess;
206 
207 
208  // Close any unnecessary handles.
209  if (!CloseHandle(pi.hThread)) DisplayError("CloseHandle");
210 }
211 
213 // ReadAndHandleOutput
214 // Monitors handle for input. Exits when child exits or pipe breaks.
217 {
218  CHAR lpBuffer[256];
219  DWORD nBytesRead;
220  DWORD nCharsWritten;
221 
222  while(TRUE)
223  {
224  if (!ReadFile(hPipeRead,lpBuffer,sizeof(lpBuffer),
225  &nBytesRead,NULL) || !nBytesRead)
226  {
228  break; // pipe done - normal exit path.
229  else
230  DisplayError("ReadFile"); // Something bad happened.
231  }
232 
233  // Display the character read on the screen.
235  nBytesRead,&nCharsWritten,NULL))
236  DisplayError("WriteConsole");
237  }
238 }
239 
240 
242 // GetAndSendInputThread
243 // Thread procedure that monitors the console for input and sends input
244 // to the child process through the input pipe.
245 // This thread ends when the child application exits.
248 {
249  CHAR read_buff[256];
250  DWORD nBytesRead,nBytesWrote;
251  HANDLE hPipeWrite = (HANDLE)lpvThreadParam;
252 
253  // Get input from our console and send it to child through the pipe.
254  while (bRunThread)
255  {
256  if(!ReadConsole(hStdIn,read_buff,1,&nBytesRead,NULL))
257  DisplayError("ReadConsole");
258 
259  read_buff[nBytesRead] = '\0'; // Follow input with a NULL.
260 
261  if (!WriteFile(hPipeWrite,read_buff,nBytesRead,&nBytesWrote,NULL))
262  {
263  if (GetLastError() == ERROR_NO_DATA)
264  break; // Pipe was closed (normal exit path).
265  else
266  DisplayError("WriteFile");
267  }
268  }
269 
270  return 1;
271 }
272 
274 // DisplayError
275 // Displays the error number and corresponding message.
277 void DisplayError(const char *pszAPI)
278 {
279  LPVOID lpvMessageBuffer;
280  CHAR szPrintBuffer[512];
281  DWORD nCharsWritten;
282 
285  NULL, GetLastError(),
287  (LPTSTR)&lpvMessageBuffer, 0, NULL);
288 
289  wsprintf(szPrintBuffer,
290  "ERROR: API = %s.\n error code = %d.\n message = %s.\n",
291  pszAPI, GetLastError(), (char *)lpvMessageBuffer);
292 
294  lstrlen(szPrintBuffer),&nCharsWritten,NULL);
295 
296  LocalFree(lpvMessageBuffer);
298 }
void ReadAndHandleOutput(HANDLE hPipeRead)
Definition: gdb2.cpp:216
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
static int argc
Definition: ServiceArgs.c:12
HANDLE hChildProcess
Definition: gdb2.cpp:36
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
LPSTR lpTitle
Definition: winbase.h:806
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
void PrepAndLaunchRedirectedChild(HANDLE hChildStdOut, HANDLE hChildStdIn, HANDLE hChildStdErr, char *pchCommandLine)
Definition: gdb2.cpp:172
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define LANG_NEUTRAL
Definition: nls.h:22
char CHAR
Definition: xmlstorage.h:175
#define SUBLANG_DEFAULT
Definition: nls.h:168
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1487
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1642
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:152
DWORD dwFlags
Definition: winbase.h:814
#define argv
Definition: mplay32.c:18
CHAR * LPTSTR
Definition: xmlstorage.h:192
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define DUPLICATE_SAME_ACCESS
unsigned int BOOL
Definition: ntddk_ex.h:94
static TAGREF LPCWSTR LPDWORD LPVOID lpBuffer
Definition: db.cpp:173
#define FORMAT_MESSAGE_ALLOCATE_BUFFER
Definition: winbase.h:400
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:136
smooth NULL
Definition: ftsmooth.c:416
#define STD_INPUT_HANDLE
Definition: winbase.h:264
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:404
#define STARTF_USESTDHANDLES
Definition: winbase.h:480
GLsizeiptr size
Definition: glext.h:5919
#define CREATE_NEW_CONSOLE
Definition: winbase.h:180
DWORD cb
Definition: winbase.h:803
static const WCHAR Title[]
Definition: oid.c:1259
int main(int argc, char *argv[])
Definition: gdb2.cpp:40
#define ERROR_NO_DATA
Definition: winerror.h:284
HANDLE WINAPI GetCurrentProcess(VOID)
Definition: proc.c:1138
#define WINAPI
Definition: msvc.h:8
PVOID HANDLE
Definition: typedefs.h:71
unsigned long DWORD
Definition: ntddk_ex.h:95
#define WAIT_FAILED
Definition: winbase.h:394
#define ERROR_BROKEN_PIPE
Definition: winerror.h:183
HANDLE hStdOutput
Definition: winbase.h:819
#define GDB_INITIAL_COMMAND
Definition: gdb2.cpp:24
HANDLE hStdIn
Definition: gdb2.cpp:37
static DWORD pi
Definition: protocol.c:150
#define FormatMessage
Definition: winbase.h:3619
#define STD_OUTPUT_HANDLE
Definition: winbase.h:265
#define CreateProcess
Definition: winbase.h:3582
BOOL WINAPI CreatePipe(PHANDLE hReadPipe, PHANDLE hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize)
Definition: npipe.c:117
#define PARAMS_SEPARATOR
Definition: gdb2.cpp:25
#define ReadConsole
Definition: wincon.h:765
void DisplayError(const char *pszAPI)
Definition: gdb2.cpp:277
#define lstrlen
Definition: winbase.h:3700
STARTUPINFOA STARTUPINFO
Definition: winbase.h:3543
HANDLE hStdInput
Definition: winbase.h:818
#define SetConsoleTitle
Definition: wincon.h:771
DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam)
Definition: gdb2.cpp:247
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
#define WriteConsole
Definition: wincon.h:772
HANDLE hThread
Definition: wizard.c:27
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define MAKELANGID(p, s)
Definition: nls.h:15
#define PARAMS_SEPARATOR_LEN
Definition: gdb2.cpp:26
#define wsprintf
Definition: winuser.h:5766
#define INFINITE
Definition: serial.h:102
BOOL WINAPI ReadFile(IN HANDLE hFile, IN LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:123
HANDLE hStdError
Definition: winbase.h:820
BOOL bRunThread
Definition: gdb2.cpp:38
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
BOOL WINAPI DuplicateHandle(IN HANDLE hSourceProcessHandle, IN HANDLE hSourceHandle, IN HANDLE hTargetProcessHandle, OUT LPHANDLE lpTargetHandle, IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwOptions)
Definition: handle.c:149
struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES
#define printf
Definition: config.h:203