1 /* COPYRIGHT: See COPYING in the top level directory
2 * PROJECT: ReactOS system libraries
3 * FILE: lib/rtl/dbgbuffer.c
4 * PROGRAMER: James Tabor
7 /* INCLUDES *****************************************************************/
14 /* FUNCTIONS *****************************************************************/
20 RtlCreateQueryDebugBuffer(IN ULONG Size
,
24 PDEBUG_BUFFER Buf
= NULL
;
25 ULONG SectionSize
= 100 * PAGE_SIZE
;
27 Status
= NtAllocateVirtualMemory( NtCurrentProcess(),
33 if (!NT_SUCCESS(Status
))
38 Buf
->SectionBase
= Buf
;
39 Buf
->SectionSize
= SectionSize
;
41 DPRINT("RtlCQDB: BA: %x BS: %d\n", Buf
->SectionBase
, Buf
->SectionSize
);
50 RtlDestroyQueryDebugBuffer(IN PDEBUG_BUFFER Buf
)
52 NTSTATUS Status
= STATUS_SUCCESS
;
56 Status
= NtFreeVirtualMemory( NtCurrentProcess(),
61 if (!NT_SUCCESS(Status
))
63 DPRINT1("RtlDQDB: Failed to free VM!\n");
69 * Based on lib/epsapi/enum/modules.c by KJK::Hyperion.
73 RtlpQueryRemoteProcessModules(HANDLE ProcessHandle
,
74 IN PMODULE_INFORMATION ModuleInformation OPTIONAL
,
75 IN ULONG Size OPTIONAL
,
76 OUT PULONG ReturnedSize
)
78 PROCESS_BASIC_INFORMATION pbiInfo
;
79 PPEB_LDR_DATA ppldLdrData
;
80 LDR_DATA_TABLE_ENTRY lmModule
;
81 PLIST_ENTRY pleListHead
;
82 PLIST_ENTRY pleCurEntry
;
84 PDEBUG_MODULE_INFORMATION ModulePtr
= NULL
;
85 NTSTATUS Status
= STATUS_SUCCESS
;
86 ULONG UsedSize
= sizeof(ULONG
);
87 ANSI_STRING AnsiString
;
90 DPRINT("RtlpQueryRemoteProcessModules Start\n");
92 /* query the process basic information (includes the PEB address) */
93 Status
= NtQueryInformationProcess ( ProcessHandle
,
94 ProcessBasicInformation
,
96 sizeof(PROCESS_BASIC_INFORMATION
),
99 if (!NT_SUCCESS(Status
))
102 DPRINT("NtQueryInformationProcess 1 &x \n", Status
);
106 if (ModuleInformation
== NULL
|| Size
== 0)
108 Status
= STATUS_INFO_LENGTH_MISMATCH
;
112 ModuleInformation
->ModuleCount
= 0;
113 ModulePtr
= &ModuleInformation
->ModuleEntry
[0];
114 Status
= STATUS_SUCCESS
;
117 /* get the address of the PE Loader data */
118 Status
= NtReadVirtualMemory ( ProcessHandle
,
119 &(pbiInfo
.PebBaseAddress
->Ldr
),
124 if (!NT_SUCCESS(Status
))
127 DPRINT("NtReadVirtualMemory 1 %x \n", Status
);
132 /* head of the module list: the last element in the list will point to this */
133 pleListHead
= &ppldLdrData
->InLoadOrderModuleList
;
135 /* get the address of the first element in the list */
136 Status
= NtReadVirtualMemory ( ProcessHandle
,
137 &(ppldLdrData
->InLoadOrderModuleList
.Flink
),
142 if (!NT_SUCCESS(Status
))
145 DPRINT("NtReadVirtualMemory 2 %x \n", Status
);
149 while(pleCurEntry
!= pleListHead
)
152 UNICODE_STRING Unicode
;
153 WCHAR Buffer
[256 * sizeof(WCHAR
)];
155 /* read the current module */
156 Status
= NtReadVirtualMemory ( ProcessHandle
,
157 CONTAINING_RECORD(pleCurEntry
, LDR_DATA_TABLE_ENTRY
, InLoadOrderModuleList
),
159 sizeof(LDR_DATA_TABLE_ENTRY
),
162 /* Import module name from remote Process user space. */
163 Unicode
.Length
= lmModule
.FullDllName
.Length
;
164 Unicode
.MaximumLength
= lmModule
.FullDllName
.MaximumLength
;
165 Unicode
.Buffer
= Buffer
;
167 Status
= NtReadVirtualMemory ( ProcessHandle
,
168 lmModule
.FullDllName
.Buffer
,
173 if (!NT_SUCCESS(Status
))
176 DPRINT( "NtReadVirtualMemory 3 %x \n", Status
);
180 DPRINT(" Module %wZ\n", &Unicode
);
184 Status
= STATUS_INFO_LENGTH_MISMATCH
;
186 else if (ModuleInformation
!= NULL
)
188 ModulePtr
->Reserved
[0] = ModulePtr
->Reserved
[1] = 0; // FIXME: ??
189 ModulePtr
->Base
= lmModule
.DllBase
;
190 ModulePtr
->Size
= lmModule
.SizeOfImage
;
191 ModulePtr
->Flags
= lmModule
.Flags
;
192 ModulePtr
->Index
= 0; // FIXME: ??
193 ModulePtr
->Unknown
= 0; // FIXME: ??
194 ModulePtr
->LoadCount
= lmModule
.LoadCount
;
196 AnsiString
.Length
= 0;
197 AnsiString
.MaximumLength
= 256;
198 AnsiString
.Buffer
= ModulePtr
->ImageName
;
199 RtlUnicodeStringToAnsiString(&AnsiString
,
203 p
= strrchr(ModulePtr
->ImageName
, '\\');
205 ModulePtr
->ModuleNameOffset
= p
- ModulePtr
->ImageName
+ 1;
207 ModulePtr
->ModuleNameOffset
= 0;
210 ModuleInformation
->ModuleCount
++;
212 UsedSize
+= sizeof(DEBUG_MODULE_INFORMATION
);
214 /* address of the next module in the list */
215 pleCurEntry
= lmModule
.InLoadOrderModuleList
.Flink
;
218 if (ReturnedSize
!= 0)
219 *ReturnedSize
= UsedSize
;
221 DPRINT("RtlpQueryRemoteProcessModules End\n");
224 return (STATUS_SUCCESS
);
231 RtlQueryProcessDebugInformation(IN ULONG ProcessId
,
232 IN ULONG DebugInfoMask
,
233 IN OUT PDEBUG_BUFFER Buf
)
235 NTSTATUS Status
= STATUS_SUCCESS
;
236 ULONG Pid
= (ULONG
) NtCurrentTeb()->Cid
.UniqueProcess
;
238 Buf
->InfoClassMask
= DebugInfoMask
;
239 Buf
->SizeOfInfo
= sizeof(DEBUG_BUFFER
);
241 DPRINT("QueryProcessDebugInformation Start\n");
244 Currently ROS can not read-only from kenrel space, and doesn't
245 check for boundaries inside kernel space that are page protected
246 from every one but the kernel. aka page 0 - 2
250 Status
= STATUS_ACCESS_VIOLATION
;
253 if (Pid
== ProcessId
)
255 if (DebugInfoMask
& PDI_MODULES
)
257 PMODULE_INFORMATION Mp
;
258 ULONG ReturnSize
= 0;
261 Mp
= (PMODULE_INFORMATION
)(Buf
+ Buf
->SizeOfInfo
);
263 /* I like this better than the do & while loop. */
264 Status
= LdrQueryProcessModuleInformation( NULL
,
267 Status
= LdrQueryProcessModuleInformation( Mp
,
270 if (!NT_SUCCESS(Status
))
275 MSize
= Mp
->ModuleCount
* (sizeof(MODULE_INFORMATION
) + 8);
276 Buf
->ModuleInformation
= Mp
;
277 Buf
->SizeOfInfo
= Buf
->SizeOfInfo
+ MSize
;
280 if (DebugInfoMask
& PDI_HEAPS
)
282 PHEAP_INFORMATION Hp
;
285 Hp
= (PHEAP_INFORMATION
)(Buf
+ Buf
->SizeOfInfo
);
286 HSize
= sizeof(HEAP_INFORMATION
);
287 if (DebugInfoMask
& PDI_HEAP_TAGS
)
290 if (DebugInfoMask
& PDI_HEAP_BLOCKS
)
293 Buf
->HeapInformation
= Hp
;
294 Buf
->SizeOfInfo
= Buf
->SizeOfInfo
+ HSize
;
298 if (DebugInfoMask
& PDI_LOCKS
)
300 PLOCK_INFORMATION Lp
;
303 Lp
= (PLOCK_INFORMATION
)(Buf
+ Buf
->SizeOfInfo
);
304 LSize
= sizeof(LOCK_INFORMATION
);
305 Buf
->LockInformation
= Lp
;
306 Buf
->SizeOfInfo
= Buf
->SizeOfInfo
+ LSize
;
309 DPRINT("QueryProcessDebugInformation end \n");
310 DPRINT("QueryDebugInfo : %d\n", Buf
->SizeOfInfo
);
316 OBJECT_ATTRIBUTES ObjectAttributes
;
318 Buf
->Unknown
[0] = (ULONG
)NtCurrentProcess();
320 ClientId
.UniqueThread
= 0;
321 ClientId
.UniqueProcess
= (HANDLE
)ProcessId
;
322 InitializeObjectAttributes(&ObjectAttributes
,
328 Status
= NtOpenProcess( &hProcess
,
329 (PROCESS_ALL_ACCESS
),
332 if (!NT_SUCCESS(Status
))
337 if (DebugInfoMask
& PDI_MODULES
)
339 PMODULE_INFORMATION Mp
;
340 ULONG ReturnSize
= 0;
343 Mp
= (PMODULE_INFORMATION
)(Buf
+ Buf
->SizeOfInfo
);
345 Status
= RtlpQueryRemoteProcessModules( hProcess
,
350 Status
= RtlpQueryRemoteProcessModules( hProcess
,
354 if (!NT_SUCCESS(Status
))
359 MSize
= Mp
->ModuleCount
* (sizeof(MODULE_INFORMATION
) + 8);
360 Buf
->ModuleInformation
= Mp
;
361 Buf
->SizeOfInfo
= Buf
->SizeOfInfo
+ MSize
;
364 if (DebugInfoMask
& PDI_HEAPS
)
366 PHEAP_INFORMATION Hp
;
369 Hp
= (PHEAP_INFORMATION
)(Buf
+ Buf
->SizeOfInfo
);
370 HSize
= sizeof(HEAP_INFORMATION
);
371 if (DebugInfoMask
& PDI_HEAP_TAGS
)
374 if (DebugInfoMask
& PDI_HEAP_BLOCKS
)
377 Buf
->HeapInformation
= Hp
;
378 Buf
->SizeOfInfo
= Buf
->SizeOfInfo
+ HSize
;
382 if (DebugInfoMask
& PDI_LOCKS
)
384 PLOCK_INFORMATION Lp
;
387 Lp
= (PLOCK_INFORMATION
)(Buf
+ Buf
->SizeOfInfo
);
388 LSize
= sizeof(LOCK_INFORMATION
);
389 Buf
->LockInformation
= Lp
;
390 Buf
->SizeOfInfo
= Buf
->SizeOfInfo
+ LSize
;
393 DPRINT("QueryProcessDebugInformation end \n");
394 DPRINT("QueryDebugInfo : %d\n", Buf
->SizeOfInfo
);