2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/rtl/dbgbuffer.c
5 * PROGRAMER: James Tabor
8 /* INCLUDES *****************************************************************/
15 /* FUNCTIONS *****************************************************************/
20 PRTL_DEBUG_INFORMATION
22 RtlCreateQueryDebugBuffer(IN ULONG Size
,
26 PRTL_DEBUG_INFORMATION Buf
= NULL
;
27 SIZE_T ViewSize
= 100 * PAGE_SIZE
;
29 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
33 MEM_RESERVE
| MEM_COMMIT
,
35 if (!NT_SUCCESS(Status
)) return NULL
;
37 Buf
->ViewBaseClient
= Buf
;
38 Buf
->ViewSize
= (ULONG
)ViewSize
;
40 DPRINT("RtlCQDB: BA: %p BS: 0x%lx\n", Buf
->ViewBaseClient
, Buf
->ViewSize
);
50 RtlDestroyQueryDebugBuffer(IN PRTL_DEBUG_INFORMATION Buf
)
52 NTSTATUS Status
= STATUS_SUCCESS
;
57 Status
= NtFreeVirtualMemory(NtCurrentProcess(),
62 if (!NT_SUCCESS(Status
))
64 DPRINT1("RtlDQDB: Failed to free VM!\n");
70 * Based on lib/epsapi/enum/modules.c by KJK::Hyperion.
74 RtlpQueryRemoteProcessModules(HANDLE ProcessHandle
,
75 IN PRTL_PROCESS_MODULES Modules OPTIONAL
,
76 IN ULONG Size OPTIONAL
,
77 OUT PULONG ReturnedSize
)
79 PROCESS_BASIC_INFORMATION pbiInfo
;
80 PPEB_LDR_DATA ppldLdrData
;
81 LDR_DATA_TABLE_ENTRY lmModule
;
82 PLIST_ENTRY pleListHead
;
83 PLIST_ENTRY pleCurEntry
;
85 PRTL_PROCESS_MODULE_INFORMATION ModulePtr
= NULL
;
86 NTSTATUS Status
= STATUS_SUCCESS
;
87 ULONG UsedSize
= sizeof(ULONG
);
88 ANSI_STRING AnsiString
;
91 DPRINT("RtlpQueryRemoteProcessModules Start\n");
93 /* query the process basic information (includes the PEB address) */
94 Status
= NtQueryInformationProcess(ProcessHandle
,
95 ProcessBasicInformation
,
97 sizeof(PROCESS_BASIC_INFORMATION
),
100 if (!NT_SUCCESS(Status
))
103 DPRINT("NtQueryInformationProcess 1 0x%lx \n", Status
);
107 if (Modules
== NULL
|| Size
== 0)
109 Status
= STATUS_INFO_LENGTH_MISMATCH
;
113 Modules
->NumberOfModules
= 0;
114 ModulePtr
= &Modules
->Modules
[0];
115 Status
= STATUS_SUCCESS
;
118 /* get the address of the PE Loader data */
119 Status
= NtReadVirtualMemory(ProcessHandle
,
120 &(pbiInfo
.PebBaseAddress
->Ldr
),
125 if (!NT_SUCCESS(Status
))
128 DPRINT("NtReadVirtualMemory 1 0x%lx \n", Status
);
133 /* head of the module list: the last element in the list will point to this */
134 pleListHead
= &ppldLdrData
->InLoadOrderModuleList
;
136 /* get the address of the first element in the list */
137 Status
= NtReadVirtualMemory(ProcessHandle
,
138 &(ppldLdrData
->InLoadOrderModuleList
.Flink
),
143 if (!NT_SUCCESS(Status
))
146 DPRINT("NtReadVirtualMemory 2 0x%lx \n", Status
);
150 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
, InLoadOrderLinks
),
159 sizeof(LDR_DATA_TABLE_ENTRY
),
162 if (!NT_SUCCESS(Status
))
165 DPRINT( "NtReadVirtualMemory 3 0x%lx \n", Status
);
169 /* Import module name from remote Process user space. */
170 Unicode
.Length
= lmModule
.FullDllName
.Length
;
171 Unicode
.MaximumLength
= lmModule
.FullDllName
.MaximumLength
;
172 Unicode
.Buffer
= Buffer
;
174 Status
= NtReadVirtualMemory(ProcessHandle
,
175 lmModule
.FullDllName
.Buffer
,
180 if (!NT_SUCCESS(Status
))
183 DPRINT( "NtReadVirtualMemory 3 0x%lx \n", Status
);
187 DPRINT(" Module %wZ\n", &Unicode
);
191 Status
= STATUS_INFO_LENGTH_MISMATCH
;
193 else if (Modules
!= NULL
)
195 ModulePtr
->Section
= 0;
196 ModulePtr
->MappedBase
= NULL
; // FIXME: ??
197 ModulePtr
->ImageBase
= lmModule
.DllBase
;
198 ModulePtr
->ImageSize
= lmModule
.SizeOfImage
;
199 ModulePtr
->Flags
= lmModule
.Flags
;
200 ModulePtr
->LoadOrderIndex
= 0; // FIXME: ??
201 ModulePtr
->InitOrderIndex
= 0; // FIXME: ??
202 ModulePtr
->LoadCount
= lmModule
.LoadCount
;
204 AnsiString
.Length
= 0;
205 AnsiString
.MaximumLength
= 256;
206 AnsiString
.Buffer
= ModulePtr
->FullPathName
;
207 RtlUnicodeStringToAnsiString(&AnsiString
,
211 p
= strrchr(ModulePtr
->FullPathName
, '\\');
213 ModulePtr
->OffsetToFileName
= (USHORT
)(p
- ModulePtr
->FullPathName
+ 1);
215 ModulePtr
->OffsetToFileName
= 0;
218 Modules
->NumberOfModules
++;
220 UsedSize
+= sizeof(RTL_PROCESS_MODULE_INFORMATION
);
222 /* address of the next module in the list */
223 pleCurEntry
= lmModule
.InLoadOrderLinks
.Flink
;
226 if (ReturnedSize
!= 0)
227 *ReturnedSize
= UsedSize
;
229 DPRINT("RtlpQueryRemoteProcessModules End\n");
232 return (STATUS_SUCCESS
);
240 RtlQueryProcessDebugInformation(IN ULONG ProcessId
,
241 IN ULONG DebugInfoMask
,
242 IN OUT PRTL_DEBUG_INFORMATION Buf
)
244 NTSTATUS Status
= STATUS_SUCCESS
;
245 ULONG Pid
= (ULONG
)(ULONG_PTR
) NtCurrentTeb()->ClientId
.UniqueProcess
;
247 Buf
->Flags
= DebugInfoMask
;
248 Buf
->OffsetFree
= sizeof(RTL_DEBUG_INFORMATION
);
250 DPRINT("QueryProcessDebugInformation Start\n");
253 Currently ROS can not read-only from kenrel space, and doesn't
254 check for boundaries inside kernel space that are page protected
255 from every one but the kernel. aka page 0 - 2
259 Status
= STATUS_ACCESS_VIOLATION
;
262 if (Pid
== ProcessId
)
264 if (DebugInfoMask
& RTL_DEBUG_QUERY_MODULES
)
266 PRTL_PROCESS_MODULES Mp
;
267 ULONG ReturnSize
= 0;
270 Mp
= (PRTL_PROCESS_MODULES
)((PUCHAR
)Buf
+ Buf
->OffsetFree
);
272 /* I like this better than the do & while loop. */
273 Status
= LdrQueryProcessModuleInformation(NULL
,
276 Status
= LdrQueryProcessModuleInformation(Mp
,
279 if (!NT_SUCCESS(Status
))
284 MSize
= Mp
->NumberOfModules
* (sizeof(RTL_PROCESS_MODULES
) + 8);
286 Buf
->OffsetFree
= Buf
->OffsetFree
+ MSize
;
289 if (DebugInfoMask
& RTL_DEBUG_QUERY_HEAPS
)
291 PRTL_PROCESS_HEAPS Hp
;
294 Hp
= (PRTL_PROCESS_HEAPS
)((PUCHAR
)Buf
+ Buf
->OffsetFree
);
295 HSize
= sizeof(RTL_PROCESS_HEAPS
);
296 if (DebugInfoMask
& RTL_DEBUG_QUERY_HEAP_TAGS
)
300 if (DebugInfoMask
& RTL_DEBUG_QUERY_HEAP_BLOCKS
)
305 Buf
->OffsetFree
= Buf
->OffsetFree
+ HSize
;
309 if (DebugInfoMask
& RTL_DEBUG_QUERY_LOCKS
)
311 PRTL_PROCESS_LOCKS Lp
;
314 Lp
= (PRTL_PROCESS_LOCKS
)((PUCHAR
)Buf
+ Buf
->OffsetFree
);
315 LSize
= sizeof(RTL_PROCESS_LOCKS
);
317 Buf
->OffsetFree
= Buf
->OffsetFree
+ LSize
;
320 DPRINT("QueryProcessDebugInformation end \n");
321 DPRINT("QueryDebugInfo : 0x%lx\n", Buf
->OffsetFree
);
327 OBJECT_ATTRIBUTES ObjectAttributes
;
329 Buf
->TargetProcessHandle
= NtCurrentProcess();
331 ClientId
.UniqueThread
= 0;
332 ClientId
.UniqueProcess
= (HANDLE
)(ULONG_PTR
)ProcessId
;
333 InitializeObjectAttributes(&ObjectAttributes
,
339 Status
= NtOpenProcess(&hProcess
,
340 (PROCESS_ALL_ACCESS
),
343 if (!NT_SUCCESS(Status
))
348 if (DebugInfoMask
& RTL_DEBUG_QUERY_MODULES
)
350 PRTL_PROCESS_MODULES Mp
;
351 ULONG ReturnSize
= 0;
354 Mp
= (PRTL_PROCESS_MODULES
)((PUCHAR
)Buf
+ Buf
->OffsetFree
);
356 Status
= RtlpQueryRemoteProcessModules(hProcess
,
361 Status
= RtlpQueryRemoteProcessModules(hProcess
,
365 if (!NT_SUCCESS(Status
))
370 MSize
= Mp
->NumberOfModules
* (sizeof(RTL_PROCESS_MODULES
) + 8);
372 Buf
->OffsetFree
= Buf
->OffsetFree
+ MSize
;
375 if (DebugInfoMask
& RTL_DEBUG_QUERY_HEAPS
)
377 PRTL_PROCESS_HEAPS Hp
;
380 Hp
= (PRTL_PROCESS_HEAPS
)((PUCHAR
)Buf
+ Buf
->OffsetFree
);
381 HSize
= sizeof(RTL_PROCESS_HEAPS
);
382 if (DebugInfoMask
& RTL_DEBUG_QUERY_HEAP_TAGS
)
386 if (DebugInfoMask
& RTL_DEBUG_QUERY_HEAP_BLOCKS
)
391 Buf
->OffsetFree
= Buf
->OffsetFree
+ HSize
;
395 if (DebugInfoMask
& RTL_DEBUG_QUERY_LOCKS
)
397 PRTL_PROCESS_LOCKS Lp
;
400 Lp
= (PRTL_PROCESS_LOCKS
)((PUCHAR
)Buf
+ Buf
->OffsetFree
);
401 LSize
= sizeof(RTL_PROCESS_LOCKS
);
403 Buf
->OffsetFree
= Buf
->OffsetFree
+ LSize
;
406 DPRINT("QueryProcessDebugInformation end \n");
407 DPRINT("QueryDebugInfo : 0x%lx\n", Buf
->OffsetFree
);