ReactOS  0.4.15-dev-1377-ga59cecd
dbgbuffer.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS system libraries
3  * LICENSE: GPL-2.0 (https://spdx.org/licenses/GPL-2.0)
4  * PURPOSE: RTL_DEBUG_INFORMATION implementation
5  * COPYRIGHT: Copyright James Tabor
6  * Copyright 2020 Mark Jansen (mark.jansen@reactos.org)
7  */
8 
9 /* INCLUDES *****************************************************************/
10 
11 #include <rtl.h>
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* FUNCTIONS *****************************************************************/
17 
18 PVOID
19 NTAPI
22 {
23  ULONG Remaining = Buffer->CommitSize - Buffer->OffsetFree;
24  PVOID Result;
26 
27  if (Size > MAXLONG)
28  return NULL;
29 
30  if (Remaining < Size)
31  {
32  PVOID Buf;
34 
35  Buf = (PVOID)((ULONG_PTR)Buffer->ViewBaseClient + Buffer->CommitSize);
36  CommitSize = Size - Remaining;
37 
38  /* this is not going to end well.. */
39  if (CommitSize > MAXLONG)
40  return NULL;
41 
43  if (!NT_SUCCESS(Status))
44  return NULL;
45 
46  Buffer->CommitSize += CommitSize;
47  Remaining = Buffer->CommitSize - Buffer->OffsetFree;
48  /* Sanity check */
49  ASSERT(Remaining >= Size);
50  if (Remaining < Size)
51  return NULL;
52  }
53 
54  Result = (PBYTE)Buffer->ViewBaseClient + Buffer->OffsetFree;
55  Buffer->OffsetFree += Size;
56 
57  return Result;
58 }
59 
60 
61 /*
62  * @unimplemented
63  */
65 NTAPI
67  _In_ BOOLEAN EventPair)
68 {
71  SIZE_T AllocationSize = Size ? Size : 0x400 * PAGE_SIZE;
72  SIZE_T CommitSize = sizeof(*Buf);
73 
74  /* Reserve the memory */
76  if (!NT_SUCCESS(Status))
77  return NULL;
78 
79  /* Commit the first data, CommitSize is updated with the actual committed data */
81  if (!NT_SUCCESS(Status))
82  {
84  return NULL;
85  }
86 
87  /* Fill out the minimum data required */
88  Buf->ViewBaseClient = Buf;
89  Buf->ViewSize = (ULONG)AllocationSize;
90  Buf->CommitSize = CommitSize;
91  Buf->OffsetFree = sizeof(*Buf);
92 
93  return Buf;
94 }
95 
96 /*
97  * @unimplemented
98  */
100 NTAPI
102 {
104  SIZE_T ViewSize = 0;
105 
106  if (NULL != Buf)
107  {
109  (PVOID*)&Buf,
110  &ViewSize,
111  MEM_RELEASE);
112  }
113  if (!NT_SUCCESS(Status))
114  {
115  DPRINT1("RtlDQDB: Failed to free VM!\n");
116  }
117  return Status;
118 }
119 
120 /*
121  * Based on lib/epsapi/enum/modules.c by KJK::Hyperion.
122  */
123 NTSTATUS
124 NTAPI
128  OUT PULONG ReturnedSize)
129 {
131  PPEB_LDR_DATA ppldLdrData;
132  LDR_DATA_TABLE_ENTRY lmModule;
133  PLIST_ENTRY pleListHead;
134  PLIST_ENTRY pleCurEntry;
135 
138  ULONG UsedSize = sizeof(ULONG);
140  PCHAR p;
141 
142  DPRINT("RtlpQueryRemoteProcessModules Start\n");
143 
144  /* query the process basic information (includes the PEB address) */
147  &pbiInfo,
149  NULL);
150 
151  if (!NT_SUCCESS(Status))
152  {
153  /* failure */
154  DPRINT("NtQueryInformationProcess 1 0x%lx \n", Status);
155  return Status;
156  }
157 
158  if (Modules == NULL || Size == 0)
159  {
161  }
162  else
163  {
164  Modules->NumberOfModules = 0;
165  ModulePtr = &Modules->Modules[0];
167  }
168 
169  /* get the address of the PE Loader data */
171  &(pbiInfo.PebBaseAddress->Ldr),
172  &ppldLdrData,
173  sizeof(ppldLdrData),
174  NULL);
175 
176  if (!NT_SUCCESS(Status))
177  {
178  /* failure */
179  DPRINT("NtReadVirtualMemory 1 0x%lx \n", Status);
180  return Status;
181  }
182 
183 
184  /* head of the module list: the last element in the list will point to this */
185  pleListHead = &ppldLdrData->InLoadOrderModuleList;
186 
187  /* get the address of the first element in the list */
189  &(ppldLdrData->InLoadOrderModuleList.Flink),
190  &pleCurEntry,
191  sizeof(pleCurEntry),
192  NULL);
193 
194  if (!NT_SUCCESS(Status))
195  {
196  /* failure */
197  DPRINT("NtReadVirtualMemory 2 0x%lx \n", Status);
198  return Status;
199  }
200 
201  while(pleCurEntry != pleListHead)
202  {
203  UNICODE_STRING Unicode;
204  WCHAR Buffer[256 * sizeof(WCHAR)];
205 
206  /* read the current module */
208  CONTAINING_RECORD(pleCurEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks),
209  &lmModule,
210  sizeof(LDR_DATA_TABLE_ENTRY),
211  NULL);
212 
213  if (!NT_SUCCESS(Status))
214  {
215  /* failure */
216  DPRINT( "NtReadVirtualMemory 3 0x%lx \n", Status);
217  return Status;
218  }
219 
220  /* Import module name from remote Process user space. */
221  Unicode.Length = lmModule.FullDllName.Length;
222  Unicode.MaximumLength = lmModule.FullDllName.MaximumLength;
223  Unicode.Buffer = Buffer;
224 
226  lmModule.FullDllName.Buffer,
227  Unicode.Buffer,
228  Unicode.Length,
229  NULL);
230 
231  if (!NT_SUCCESS(Status))
232  {
233  /* failure */
234  DPRINT( "NtReadVirtualMemory 3 0x%lx \n", Status);
235  return Status;
236  }
237 
238  DPRINT(" Module %wZ\n", &Unicode);
239 
240  if (UsedSize > Size)
241  {
243  }
244  else if (Modules != NULL)
245  {
246  ModulePtr->Section = 0;
247  ModulePtr->MappedBase = NULL; // FIXME: ??
248  ModulePtr->ImageBase = lmModule.DllBase;
249  ModulePtr->ImageSize = lmModule.SizeOfImage;
250  ModulePtr->Flags = lmModule.Flags;
251  ModulePtr->LoadOrderIndex = 0; // FIXME: ??
252  ModulePtr->InitOrderIndex = 0; // FIXME: ??
253  ModulePtr->LoadCount = lmModule.LoadCount;
254 
255  AnsiString.Length = 0;
256  AnsiString.MaximumLength = 256;
257  AnsiString.Buffer = ModulePtr->FullPathName;
259  &Unicode,
260  FALSE);
261 
262  p = strrchr(ModulePtr->FullPathName, '\\');
263  if (p != NULL)
264  ModulePtr->OffsetToFileName = (USHORT)(p - ModulePtr->FullPathName + 1);
265  else
266  ModulePtr->OffsetToFileName = 0;
267 
268  ModulePtr++;
269  Modules->NumberOfModules++;
270  }
271  UsedSize += sizeof(RTL_PROCESS_MODULE_INFORMATION);
272 
273  /* address of the next module in the list */
274  pleCurEntry = lmModule.InLoadOrderLinks.Flink;
275  }
276 
277  if (ReturnedSize != 0)
278  *ReturnedSize = UsedSize;
279 
280  DPRINT("RtlpQueryRemoteProcessModules End\n");
281 
282  /* success */
283  return (STATUS_SUCCESS);
284 }
285 
286 /*
287  * @unimplemented
288  */
289 NTSTATUS
290 NTAPI
292  IN ULONG DebugInfoMask,
294 {
296  ULONG Pid = (ULONG)(ULONG_PTR) NtCurrentTeb()->ClientId.UniqueProcess;
297 
298  Buf->Flags = DebugInfoMask;
299  Buf->OffsetFree = sizeof(RTL_DEBUG_INFORMATION);
300 
301  DPRINT("QueryProcessDebugInformation Start\n");
302 
303  /*
304  Currently ROS can not read-only from kenrel space, and doesn't
305  check for boundaries inside kernel space that are page protected
306  from every one but the kernel. aka page 0 - 2
307  */
308  if (ProcessId <= 1)
309  {
311  }
312  else
313  if (Pid == ProcessId)
314  {
315  if (DebugInfoMask & RTL_DEBUG_QUERY_MODULES)
316  {
318  ULONG ReturnSize = 0;
319 
320  /* I like this better than the do & while loop. */
322  0,
323  &ReturnSize);
324 
325  Mp = RtlpDebugBufferCommit(Buf, ReturnSize);
326  if (!Mp)
327  {
328  DPRINT1("RtlQueryProcessDebugInformation: Unable to commit %u\n", ReturnSize);
329  }
330 
332  ReturnSize,
333  &ReturnSize);
334  if (!NT_SUCCESS(Status))
335  {
336  return Status;
337  }
338 
339  Buf->Modules = Mp;
340  }
341 
342  if (DebugInfoMask & RTL_DEBUG_QUERY_HEAPS)
343  {
345  ULONG HSize;
346 
347  Hp = (PRTL_PROCESS_HEAPS)((PUCHAR)Buf + Buf->OffsetFree);
348  HSize = sizeof(RTL_PROCESS_HEAPS);
349  if (DebugInfoMask & RTL_DEBUG_QUERY_HEAP_TAGS)
350  {
351  // TODO
352  }
353  if (DebugInfoMask & RTL_DEBUG_QUERY_HEAP_BLOCKS)
354  {
355  // TODO
356  }
357  Buf->Heaps = Hp;
358  Buf->OffsetFree = Buf->OffsetFree + HSize;
359 
360  }
361 
362  if (DebugInfoMask & RTL_DEBUG_QUERY_LOCKS)
363  {
365  ULONG LSize;
366 
367  Lp = (PRTL_PROCESS_LOCKS)((PUCHAR)Buf + Buf->OffsetFree);
368  LSize = sizeof(RTL_PROCESS_LOCKS);
369  Buf->Locks = Lp;
370  Buf->OffsetFree = Buf->OffsetFree + LSize;
371  }
372 
373  DPRINT("QueryProcessDebugInformation end \n");
374  DPRINT("QueryDebugInfo : 0x%lx\n", Buf->OffsetFree);
375  }
376  else
377  {
381 
382  Buf->TargetProcessHandle = NtCurrentProcess();
383 
387  NULL,
388  0,
389  NULL,
390  NULL);
391 
395  &ClientId );
396  if (!NT_SUCCESS(Status))
397  {
398  return Status;
399  }
400 
401  if (DebugInfoMask & RTL_DEBUG_QUERY_MODULES)
402  {
404  ULONG ReturnSize = 0;
405 
407  NULL,
408  0,
409  &ReturnSize);
410 
411  Mp = RtlpDebugBufferCommit(Buf, ReturnSize);
412  if (!Mp)
413  {
414  DPRINT1("RtlQueryProcessDebugInformation: Unable to commit %u\n", ReturnSize);
415  }
416 
418  Mp,
419  ReturnSize ,
420  &ReturnSize);
421  if (!NT_SUCCESS(Status))
422  {
423  return Status;
424  }
425 
426  Buf->Modules = Mp;
427  }
428 
429  if (DebugInfoMask & RTL_DEBUG_QUERY_HEAPS)
430  {
432  ULONG HSize;
433 
434  Hp = (PRTL_PROCESS_HEAPS)((PUCHAR)Buf + Buf->OffsetFree);
435  HSize = sizeof(RTL_PROCESS_HEAPS);
436  if (DebugInfoMask & RTL_DEBUG_QUERY_HEAP_TAGS)
437  {
438  // TODO
439  }
440  if (DebugInfoMask & RTL_DEBUG_QUERY_HEAP_BLOCKS)
441  {
442  // TODO
443  }
444  Buf->Heaps = Hp;
445  Buf->OffsetFree = Buf->OffsetFree + HSize;
446 
447  }
448 
449  if (DebugInfoMask & RTL_DEBUG_QUERY_LOCKS)
450  {
452  ULONG LSize;
453 
454  Lp = (PRTL_PROCESS_LOCKS)((PUCHAR)Buf + Buf->OffsetFree);
455  LSize = sizeof(RTL_PROCESS_LOCKS);
456  Buf->Locks = Lp;
457  Buf->OffsetFree = Buf->OffsetFree + LSize;
458  }
459 
460  DPRINT("QueryProcessDebugInformation end \n");
461  DPRINT("QueryDebugInfo : 0x%lx\n", Buf->OffsetFree);
462  }
463 
464  return Status;
465 }
466 
467 /* EOL */
signed char * PCHAR
Definition: retypes.h:7
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define IN
Definition: typedefs.h:39
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ProcessId
Definition: fatprocs.h:2706
#define RTL_DEBUG_QUERY_LOCKS
Definition: rtltypes.h:369
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define PROCESS_ALL_ACCESS
Definition: nt_native.h:1324
#define RTL_DEBUG_QUERY_HEAP_TAGS
Definition: rtltypes.h:367
#define MAXLONG
Definition: umtypes.h:116
USHORT MaximumLength
Definition: env_spec_w32.h:370
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
LIST_ENTRY InLoadOrderModuleList
Definition: ldrtypes.h:120
unsigned char * PUCHAR
Definition: retypes.h:3
#define RTL_DEBUG_QUERY_HEAP_BLOCKS
Definition: rtltypes.h:368
LONG NTSTATUS
Definition: precomp.h:26
struct _RTL_DEBUG_INFORMATION RTL_DEBUG_INFORMATION
NTSTATUS NTAPI NtQueryInformationProcess(IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:59
PVOID NTAPI RtlpDebugBufferCommit(_Inout_ PRTL_DEBUG_INFORMATION Buffer, _In_ SIZE_T Size)
Definition: dbgbuffer.c:20
ULONG SizeOfImage
Definition: ldrtypes.h:143
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:70
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
HANDLE UniqueProcess
Definition: compat.h:684
struct _RTL_PROCESS_HEAPS RTL_PROCESS_HEAPS
#define MEM_COMMIT
Definition: nt_native.h:1313
NTSTATUS NTAPI NtOpenProcess(OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId)
Definition: process.c:1440
uint32_t ULONG_PTR
Definition: typedefs.h:65
PVOID DllBase
Definition: btrfs_drv.h:1926
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
#define MEM_RESERVE
Definition: nt_native.h:1314
#define RTL_DEBUG_QUERY_HEAPS
Definition: rtltypes.h:366
RTL_PROCESS_LOCK_INFORMATION Locks[1]
Definition: rtltypes.h:1153
unsigned char BOOLEAN
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
#define RTL_DEBUG_QUERY_MODULES
Definition: rtltypes.h:364
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
void * PVOID
Definition: retypes.h:9
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define NtCurrentProcess()
Definition: nt_native.h:1657
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1163
#define ASSERT(a)
Definition: mode.c:45
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T CommitSize
Definition: mmfuncs.h:404
NTSTATUS NTAPI RtlQueryProcessDebugInformation(IN ULONG ProcessId, IN ULONG DebugInfoMask, IN OUT PRTL_DEBUG_INFORMATION Buf)
Definition: dbgbuffer.c:291
PVOID HANDLE
Definition: typedefs.h:73
#define _Inout_
Definition: no_sal2.h:162
NTSTATUS NTAPI NtReadVirtualMemory(IN HANDLE ProcessHandle, IN PVOID BaseAddress, OUT PVOID Buffer, IN SIZE_T NumberOfBytesToRead, OUT PSIZE_T NumberOfBytesRead OPTIONAL)
Definition: virtual.c:2731
NTSTATUS NTAPI LdrQueryProcessModuleInformation(IN PRTL_PROCESS_MODULES ModuleInformation, IN ULONG Size, OUT PULONG ReturnedSize OPTIONAL)
Definition: ldrapi.c:1107
HANDLE UniqueThread
Definition: compat.h:685
struct _RTL_PROCESS_MODULE_INFORMATION RTL_PROCESS_MODULE_INFORMATION
PRTL_DEBUG_INFORMATION NTAPI RtlCreateQueryDebugBuffer(_In_ ULONG Size, _In_ BOOLEAN EventPair)
Definition: dbgbuffer.c:66
Definition: btrfs_drv.h:1922
struct _RTL_PROCESS_LOCKS * PRTL_PROCESS_LOCKS
struct _RTL_PROCESS_LOCKS RTL_PROCESS_LOCKS
struct _RTL_PROCESS_HEAPS * PRTL_PROCESS_HEAPS
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:119
#define Mp
Definition: i386-dis.c:353
LIST_ENTRY InLoadOrderLinks
Definition: ldrtypes.h:138
#define _In_
Definition: no_sal2.h:158
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:319
ULONG_PTR SIZE_T
Definition: typedefs.h:80
NTSTATUS NTAPI RtlpQueryRemoteProcessModules(HANDLE ProcessHandle, IN PRTL_PROCESS_MODULES Modules OPTIONAL, IN ULONG Size OPTIONAL, OUT PULONG ReturnedSize)
Definition: dbgbuffer.c:125
NTSTATUS NTAPI NtAllocateVirtualMemory(IN HANDLE ProcessHandle, IN OUT PVOID *UBaseAddress, IN ULONG_PTR ZeroBits, IN OUT PSIZE_T URegionSize, IN ULONG AllocationType, IN ULONG Protect)
Definition: virtual.c:4407
FORCEINLINE struct _TEB * NtCurrentTeb(VOID)
Definition: psfuncs.h:420
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
unsigned short USHORT
Definition: pedump.c:61
PPEB_LDR_DATA Ldr
Definition: btrfs_drv.h:1958
UNICODE_STRING FullDllName
Definition: btrfs_drv.h:1928
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
NTSTATUS NTAPI RtlDestroyQueryDebugBuffer(_In_ PRTL_DEBUG_INFORMATION Buf)
Definition: dbgbuffer.c:101
#define MEM_RELEASE
Definition: nt_native.h:1316
#define OUT
Definition: typedefs.h:40
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:404
ULONG Flags
Definition: ntddk_ex.h:207
unsigned int ULONG
Definition: retypes.h:1
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
RTL_HEAP_INFORMATION Heaps[1]
Definition: rtltypes.h:1133
#define STATUS_SUCCESS
Definition: shellext.h:65
GLfloat GLfloat p
Definition: glext.h:8902
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
BYTE * PBYTE
Definition: pedump.c:66
USHORT LoadCount
Definition: ntddk_ex.h:208
#define PAGE_READWRITE
Definition: nt_native.h:1304
NTSTATUS NTAPI NtFreeVirtualMemory(IN HANDLE ProcessHandle, IN PVOID *UBaseAddress, IN PSIZE_T URegionSize, IN ULONG FreeType)
Definition: virtual.c:5130
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68