ReactOS  0.4.12-dev-102-g4b7f1e0
dbgchnl.c
Go to the documentation of this file.
1 /*
2  * ReactOS Task Manager
3  *
4  * dbgchnl.c
5  *
6  * Copyright (C) 2003 - 2004 Eric Pouech
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include "precomp.h"
24 
25 #include <stdio.h>
26 
27 /* TODO:
28  * - the dialog box could be non modal
29  * - in that case,
30  * + could refresh channels from time to time
31  * - get a better UI (replace the 'x' by real tick boxes in list view)
32  * - implement a real solution around the get_symbol hack
33  * - enhance visual feedback: the list is large, and it's hard to get the
34  * right line when clicking on rightmost column (trace for example)
35  * - get rid of printfs (error reporting) and use real message boxes
36  * - include the column width settings in the full column management scheme
37  */
38 
40 {
41 #ifdef WINE
42  return TRUE;
43 #endif
44  return FALSE;
45 }
46 
47 static int list_channel_CB(HANDLE hProcess, void* addr, WCHAR* buffer, void* user)
48 {
49  int j;
50  WCHAR val[2];
51  LVITEM lvi;
52  int index;
53  HWND hChannelLV = (HWND)user;
54 
55  memset(&lvi, 0, sizeof(lvi));
56 
57  lvi.mask = LVIF_TEXT;
58  lvi.pszText = buffer + 1;
59 
60  index = ListView_InsertItem(hChannelLV, &lvi);
61  if (index == -1) return 0;
62 
63  val[1] = L'\0';
64  for (j = 0; j < 4; j++)
65  {
66  val[0] = (buffer[0] & (1 << j)) ? L'x' : L' ';
67  ListView_SetItemText(hChannelLV, index, j + 1, val);
68  }
69  return 1;
70 }
71 
72 struct cce_user
73 {
74  LPCWSTR name; /* channel to look for */
75  unsigned value, mask; /* how to change channel */
76  unsigned done; /* number of successful changes */
77  unsigned notdone; /* number of unsuccessful changes */
78 };
79 
80 /******************************************************************
81  * change_channel_CB
82  *
83  * Callback used for changing a given channel attributes
84  */
85 static int change_channel_CB(HANDLE hProcess, void* addr, WCHAR* buffer, void* pmt)
86 {
87  struct cce_user* user = (struct cce_user*)pmt;
88 
89  if (!user->name || !wcscmp(buffer + 1, user->name))
90  {
91  buffer[0] = (buffer[0] & ~user->mask) | (user->value & user->mask);
92  if (WriteProcessMemory(hProcess, addr, buffer, 1, NULL))
93  user->done++;
94  else
95  user->notdone++;
96  }
97  return 1;
98 }
99 
100 #ifdef WINE
101 /******************************************************************
102  * get_symbol
103  *
104  * Here it gets ugly :-(
105  * This is quick hack to get the address of first_dll in a running process
106  * We make the following assumptions:
107  * - libwine (lib) is loaded in all processes at the same address (or
108  * at least at the same address at this process)
109  * - we load the same libwine.so version in this process and in the
110  * examined process
111  * Final address is gotten by: 1/ querying the address of a known exported
112  * symbol out of libwine.so with dlsym, 2/ then querying nm on libwine.so to
113  * get the offset from the data segment of this known symbol and of first_dll,
114  * 3/ computing the actual address of first_dll by adding the result of 1/ and
115  * the delta of 2/.
116  * Ugly, yes, but it somehow works. We should replace that with debughlp
117  * library, that'd be way better. Exporting first_dll from libwine.so would make
118  * this code simpler, but still ugly.
119  */
120 /* FIXME: we only need those includes for the next function */
121 #include <dlfcn.h> /* for RTLD_LAZY */
122 #include <sys/types.h>
123 #include <sys/stat.h>
124 #include <unistd.h>
125 #include <stdio.h>
126 #include "wine/library.h"
127 
128 void* get_symbol(HANDLE hProcess, const char* name, const char* lib)
129 {
130  char buffer[1024];
131  void* h;
132  DWORD addr = 0, tmp = 0;
133  FILE* f;
134  char* env;
135 
136  if (!(h = wine_dlopen(lib, RTLD_LAZY, buffer, sizeof(buffer))))
137  {
138  printf("Couldn't load %s (%s)\n", lib, buffer);
139  return NULL;
140  }
141 
142  env = getenv("LD_LIBRARY_PATH");
143  if (env)
144  {
145  char *next, *ptr;
146  struct stat s;
147 
148  for (ptr = env = strdup(env); ptr; ptr = next)
149  {
150  next = strchr(ptr, ':');
151  if (next) *next++ = '\0';
152  sprintf(buffer, "nm %s", ptr);
153  if (buffer[strlen(buffer) - 1] != '/') strcat(buffer, "/");
154  strcat(buffer, lib);
155  if (stat(buffer + 3, &s) == 0) break;
156  }
157  free(env);
158  if (!ptr)
159  {
160  printf("Couldn't find %s in LD_LIBRARY_PATH\n", lib);
161  return NULL;
162  }
163  }
164  if (!(f = popen(buffer, "r")))
165  {
166  printf("Cannot execute '%s'\n", buffer);
167  return NULL;
168  }
169 
170  while (fgets(buffer, sizeof(buffer), f))
171  {
172  char *p = buffer + strlen(buffer) - 1;
173  if (p < buffer) continue;
174  if (*p == '\n') *p-- = 0;
175  if (p - buffer < 11) continue;
176  buffer[8] = '\0';
177  if (!strcmp(&buffer[11], name)) addr += strtol(buffer, NULL, 16);
178  if (buffer[9] == 'D' && !tmp && (tmp = (DWORD)wine_dlsym(h, &buffer[11], NULL, 0)) != 0)
179  addr += tmp - strtol(buffer, NULL, 16);
180  }
181  pclose(f);
182  return (char*)addr;
183 }
184 #else
185 void* get_symbol(HANDLE hProcess, const char* name, const char* lib)
186 {
187  printf("get_symbol: not implemented on this platform\n");
188  return NULL;
189 }
190 #endif
191 
193 {
194  void* next;
195  void* prev;
196  char* const* channels;
197  unsigned int nb_channels;
198 };
199 
200 typedef int (*EnumChannelCB)(HANDLE, void*, WCHAR*, void*);
201 
202 /******************************************************************
203  * enum_channel
204  *
205  * Enumerates all known channels on process hProcess through callback
206  * ce.
207  */
208 static int enum_channel(HANDLE hProcess, EnumChannelCB ce, void* user, unsigned unique)
209 {
210  struct dll_option_layout dol;
211  int ret = 1;
212  void* buf_addr;
213  WCHAR buffer[32];
214  void* addr;
215  WCHAR** cache = NULL;
216  unsigned i, j, num_cache, used_cache;
217 
218  addr = get_symbol(hProcess, "first_dll", "libwine.so");
219  if (!addr) return -1;
220  if (unique)
221  cache = HeapAlloc(GetProcessHeap(), 0, (num_cache = 32) * sizeof(WCHAR*));
222  else
223  num_cache = 0;
224  used_cache = 0;
225 
226  for (;
227  ret && addr && ReadProcessMemory(hProcess, addr, &dol, sizeof(dol), NULL);
228  addr = dol.next)
229  {
230  for (i = 0; i < dol.nb_channels; i++)
231  {
232  if (ReadProcessMemory(hProcess, (void*)(dol.channels + i), &buf_addr, sizeof(buf_addr), NULL) &&
233  ReadProcessMemory(hProcess, buf_addr, buffer, sizeof(buffer), NULL))
234  {
235  if (unique)
236  {
237  /* since some channels are defined in multiple compilation units,
238  * they will appear several times...
239  * so cache the channel's names we already reported and don't report
240  * them again
241  */
242  for (j = 0; j < used_cache; j++)
243  if (!wcscmp(cache[j], buffer + 1)) break;
244  if (j != used_cache) continue;
245  if (used_cache == num_cache)
246  cache = HeapReAlloc(GetProcessHeap(), 0, cache, (num_cache *= 2) * sizeof(WCHAR*));
247  cache[used_cache++] = wcscpy(HeapAlloc(GetProcessHeap(), 0, (wcslen(buffer + 1) + 1) * sizeof(WCHAR)),
248  buffer + 1);
249  }
250  ret = ce(hProcess, buf_addr, buffer, user);
251  }
252  }
253  }
254  if (unique)
255  {
256  for (j = 0; j < used_cache; j++) HeapFree(GetProcessHeap(), 0, (WCHAR*)cache[j]);
257  HeapFree(GetProcessHeap(), 0, cache);
258  }
259  return 0;
260 }
261 
262 static void DebugChannels_FillList(HWND hChannelLV)
263 {
265 
266  (void)ListView_DeleteAllItems(hChannelLV);
267 
269  if (!hProcess) return; /* FIXME messagebox */
270  SendMessageW(hChannelLV, WM_SETREDRAW, FALSE, 0);
271  enum_channel(hProcess, list_channel_CB, (void*)hChannelLV, TRUE);
272  SendMessageW(hChannelLV, WM_SETREDRAW, TRUE, 0);
273  CloseHandle(hProcess);
274 }
275 
276 static void DebugChannels_OnCreate(HWND hwndDlg)
277 {
278  HWND hLV = GetDlgItem(hwndDlg, IDC_DEBUG_CHANNELS_LIST);
279  LVCOLUMN lvc;
280 
281  lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
282  lvc.fmt = LVCFMT_LEFT;
283  lvc.pszText = L"Debug Channel";
284  lvc.cx = 100;
285  (void)ListView_InsertColumn(hLV, 0, &lvc);
286 
287  lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
288  lvc.fmt = LVCFMT_CENTER;
289  lvc.pszText = L"Fixme";
290  lvc.cx = 55;
291  (void)ListView_InsertColumn(hLV, 1, &lvc);
292 
293  lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
294  lvc.fmt = LVCFMT_CENTER;
295  lvc.pszText = L"Err";
296  lvc.cx = 55;
297  (void)ListView_InsertColumn(hLV, 2, &lvc);
298 
299  lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
300  lvc.fmt = LVCFMT_CENTER;
301  lvc.pszText = L"Warn";
302  lvc.cx = 55;
303  (void)ListView_InsertColumn(hLV, 3, &lvc);
304 
305  lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
306  lvc.fmt = LVCFMT_CENTER;
307  lvc.pszText = L"Trace";
308  lvc.cx = 55;
309  (void)ListView_InsertColumn(hLV, 4, &lvc);
310 
312 }
313 
315 {
316  NMHDR* nmh = (NMHDR*)lParam;
317 
318  switch (nmh->code)
319  {
320  case NM_CLICK:
321  if (nmh->idFrom == IDC_DEBUG_CHANNELS_LIST)
322  {
323  LVHITTESTINFO lhti;
324  HWND hChannelLV;
326  NMITEMACTIVATE* nmia = (NMITEMACTIVATE*)lParam;
327 
329  if (!hProcess) return; /* FIXME message box */
330  lhti.pt = nmia->ptAction;
331  hChannelLV = GetDlgItem(hDlg, IDC_DEBUG_CHANNELS_LIST);
332  SendMessageW(hChannelLV, LVM_SUBITEMHITTEST, 0, (LPARAM)&lhti);
333  if (nmia->iSubItem >= 1 && nmia->iSubItem <= 4)
334  {
335  WCHAR val[2];
336  WCHAR name[32];
337  unsigned bitmask = 1 << (lhti.iSubItem - 1);
338  struct cce_user user;
339 
340  ListView_GetItemText(hChannelLV, lhti.iItem, 0, name, sizeof(name) / sizeof(name[0]));
341  ListView_GetItemText(hChannelLV, lhti.iItem, lhti.iSubItem, val, sizeof(val) / sizeof(val[0]));
342  user.name = name;
343  user.value = (val[0] == L'x') ? 0 : bitmask;
344  user.mask = bitmask;
345  user.done = user.notdone = 0;
346  enum_channel(hProcess, change_channel_CB, &user, FALSE);
347  if (user.done)
348  {
349  val[0] ^= (L'x' ^ L' ');
350  ListView_SetItemText(hChannelLV, lhti.iItem, lhti.iSubItem, val);
351  }
352  if (user.notdone)
353  printf("Some channel instance weren't correctly set\n");
354  }
355  CloseHandle(hProcess);
356  }
357  break;
358  }
359 }
360 
362 {
363  switch (message)
364  {
365  case WM_INITDIALOG:
367  return TRUE;
368  case WM_COMMAND:
369  if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
370  EndDialog(hDlg, LOWORD(wParam));
371  return TRUE;
372  }
373  break;
374  case WM_NOTIFY:
375  DebugChannels_OnNotify(hDlg, lParam);
376  break;
377  }
378  return FALSE;
379 }
380 
382 {
384 }
unsigned int nb_channels
Definition: dbgchnl.c:197
Definition: cache.c:46
Definition: tftpd.h:59
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint 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 GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble const GLfloat const GLdouble const GLfloat GLenum GLint GLint GLint GLint GLint GLint j
Definition: glfuncs.h:98
#define TRUE
Definition: types.h:120
int(* EnumChannelCB)(HANDLE, void *, WCHAR *, void *)
Definition: dbgchnl.c:200
DWORD GetSelectedProcessId(void)
Definition: procpage.c:99
#define IDOK
Definition: winuser.h:824
#define CloseHandle
Definition: compat.h:398
#define IDD_DEBUG_CHANNELS_DIALOG
Definition: resource.h:28
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:47
#define LVCF_WIDTH
Definition: commctrl.h:2557
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
#define LVCF_TEXT
Definition: commctrl.h:2558
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define LVCFMT_CENTER
Definition: commctrl.h:2570
#define ListView_GetItemText(hwndLV, i, iSubItem_, pszText_, cchTextMax_)
Definition: commctrl.h:2654
#define free
Definition: debug_ros.c:5
#define CALLBACK
Definition: compat.h:27
#define WM_SETREDRAW
Definition: winuser.h:1598
HANDLE HWND
Definition: compat.h:13
static void DebugChannels_OnNotify(HWND hDlg, LPARAM lParam)
Definition: dbgchnl.c:314
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define LVCFMT_LEFT
Definition: commctrl.h:2568
GLuint buffer
Definition: glext.h:5915
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:70
void * wine_dlsym(void *handle, const char *symbol, char *error, size_t errorsize)
Definition: loader.c:48
#define ReadProcessMemory(a, b, c, d, e)
Definition: compat.h:415
#define ListView_InsertItem(hwnd, pitem)
Definition: commctrl.h:2378
int32_t INT_PTR
Definition: typedefs.h:62
BOOL WINAPI EndDialog(_In_ HWND, _In_ INT_PTR)
WPARAM wParam
Definition: combotst.c:138
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
UINT_PTR WPARAM
Definition: windef.h:207
#define LVIF_TEXT
Definition: commctrl.h:2279
UINT code
Definition: winuser.h:3112
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define LVCOLUMN
Definition: commctrl.h:2551
GLenum GLclampf GLint i
Definition: glfuncs.h:14
static int list_channel_CB(HANDLE hProcess, void *addr, WCHAR *buffer, void *user)
Definition: dbgchnl.c:47
#define ListView_InsertColumn(hwnd, iCol, pcol)
Definition: commctrl.h:2606
#define LVM_SUBITEMHITTEST
Definition: commctrl.h:2734
LONG_PTR LPARAM
Definition: windef.h:208
_Check_return_ _CRTIMP char *__cdecl strdup(_In_opt_z_ const char *_Src)
UINT_PTR idFrom
Definition: winuser.h:3111
static PVOID ptr
Definition: dispmode.c:27
void * get_symbol(HANDLE hProcess, const char *name, const char *lib)
Definition: dbgchnl.c:185
BOOL DebugChannelsAreSupported(void)
Definition: dbgchnl.c:39
smooth NULL
Definition: ftsmooth.c:416
void * wine_dlopen(const char *filename, int flag, char *error, size_t errorsize)
Definition: loader.c:53
unsigned mask
Definition: dbgchnl.c:75
#define DialogBoxW(i, t, p, f)
Definition: winuser.h:4268
GLuint GLfloat * val
Definition: glext.h:7180
#define ListView_SetItemText(hwndLV, i, iSubItem_, pszText_)
Definition: commctrl.h:2661
static INT_PTR CALLBACK DebugChannelsDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
Definition: dbgchnl.c:361
unsigned int BOOL
Definition: ntddk_ex.h:94
#define PROCESS_VM_WRITE
Definition: pstypes.h:154
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
HWND WINAPI GetDlgItem(_In_opt_ HWND, _In_ int)
#define IDC_DEBUG_CHANNELS_LIST
Definition: resource.h:29
unsigned int UINT
Definition: ndis.h:50
PVOID HANDLE
Definition: typedefs.h:71
unsigned long DWORD
Definition: ntddk_ex.h:95
static void DebugChannels_OnCreate(HWND hwndDlg)
Definition: dbgchnl.c:276
unsigned value
Definition: dbgchnl.c:75
int ret
HWND hMainWnd
Definition: magnifier.c:33
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
GLenum const GLvoid * addr
Definition: glext.h:9621
#define index(s, c)
Definition: various.h:29
static const WCHAR L[]
Definition: oid.c:1087
static void DebugChannels_FillList(HWND hChannelLV)
Definition: dbgchnl.c:262
unsigned done
Definition: dbgchnl.c:76
Definition: stat.h:55
unsigned notdone
Definition: dbgchnl.c:77
#define WM_COMMAND
Definition: winuser.h:1716
#define pclose
Definition: syshdrs.h:73
#define NM_CLICK
Definition: commctrl.h:130
char *const * channels
Definition: dbgchnl.c:196
void ProcessPage_OnDebugChannels(void)
Definition: dbgchnl.c:381
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_Check_return_opt_ _CRTIMP char *__cdecl fgets(_Out_writes_z_(_MaxCount) char *_Buf, _In_ int _MaxCount, _Inout_ FILE *_File)
_CRTIMP int __cdecl stat(const char *_Filename, struct stat *_Stat)
Definition: stat.h:345
#define LVCF_FMT
Definition: commctrl.h:2556
HANDLE WINAPI OpenProcess(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwProcessId)
Definition: proc.c:1257
HINSTANCE hInst
Definition: dxdiag.c:13
static unsigned __int64 next
Definition: rand_nt.c:6
_Check_return_ char *__cdecl getenv(_In_z_ const char *_VarName)
LPCWSTR name
Definition: dbgchnl.c:74
#define popen
Definition: syshdrs.h:72
#define f
Definition: ke_i.h:83
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define HeapReAlloc
Definition: compat.h:393
static int enum_channel(HANDLE hProcess, EnumChannelCB ce, void *user, unsigned unique)
Definition: dbgchnl.c:208
static LPCWSTR LPCWSTR LPCWSTR env
Definition: db.cpp:158
static int change_channel_CB(HANDLE hProcess, void *addr, WCHAR *buffer, void *pmt)
Definition: dbgchnl.c:85
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define PROCESS_VM_READ
Definition: pstypes.h:153
Definition: name.c:36
_Check_return_ long __cdecl strtol(_In_z_ const char *_Str, _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix)
#define LVITEM
Definition: commctrl.h:2345
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define PROCESS_VM_OPERATION
Definition: pstypes.h:152
GLfloat GLfloat p
Definition: glext.h:8902
#define IDCANCEL
Definition: winuser.h:825
#define memset(x, y, z)
Definition: compat.h:39
#define WM_INITDIALOG
Definition: winuser.h:1715
LPARAM lParam
Definition: combotst.c:139
void user(int argc, const char *argv[])
Definition: cmds.c:1350
#define LOWORD(l)
Definition: pedump.c:82
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define HeapFree(x, y, z)
Definition: compat.h:394
BOOL NTAPI WriteProcessMemory(IN HANDLE hProcess, IN LPVOID lpBaseAddress, IN LPCVOID lpBuffer, IN SIZE_T nSize, OUT SIZE_T *lpNumberOfBytesWritten)
Definition: proc.c:2086
#define WM_NOTIFY
Definition: richedit.h:61
#define RTLD_LAZY
Definition: port.h:99
#define ListView_DeleteAllItems(hwnd)
Definition: commctrl.h:2384
#define printf
Definition: config.h:203
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:29