[RTL]
[reactos.git] / reactos / lib / rtl / dbgbuffer.c
1 /* COPYRIGHT: See COPYING in the top level directory
2 * PROJECT: ReactOS system libraries
3 * FILE: lib/rtl/dbgbuffer.c
4 * PROGRAMER: James Tabor
5 */
6
7 /* INCLUDES *****************************************************************/
8
9 #include <rtl.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 /* FUNCTIONS *****************************************************************/
15
16 /*
17 * @unimplemented
18 */
19 PRTL_DEBUG_INFORMATION
20 NTAPI
21 RtlCreateQueryDebugBuffer(IN ULONG Size,
22 IN BOOLEAN EventPair)
23 {
24 NTSTATUS Status;
25 PRTL_DEBUG_INFORMATION Buf = NULL;
26 SIZE_T ViewSize = 100 * PAGE_SIZE;
27
28 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
29 (PVOID*)&Buf,
30 0,
31 &ViewSize,
32 MEM_RESERVE | MEM_COMMIT,
33 PAGE_READWRITE);
34 if (!NT_SUCCESS(Status)) return NULL;
35
36 Buf->ViewBaseClient = Buf;
37 Buf->ViewSize = (ULONG)ViewSize;
38
39 DPRINT("RtlCQDB: BA: %p BS: 0x%lx\n", Buf->ViewBaseClient, Buf->ViewSize);
40
41 return Buf;
42 }
43
44 /*
45 * @unimplemented
46 */
47 NTSTATUS
48 NTAPI
49 RtlDestroyQueryDebugBuffer(IN PRTL_DEBUG_INFORMATION Buf)
50 {
51 NTSTATUS Status = STATUS_SUCCESS;
52 SIZE_T ViewSize = 0;
53
54 if (NULL != Buf)
55 {
56 Status = NtFreeVirtualMemory(NtCurrentProcess(),
57 (PVOID*)&Buf,
58 &ViewSize,
59 MEM_RELEASE);
60 }
61 if (!NT_SUCCESS(Status))
62 {
63 DPRINT1("RtlDQDB: Failed to free VM!\n");
64 }
65 return Status;
66 }
67
68 /*
69 * Based on lib/epsapi/enum/modules.c by KJK::Hyperion.
70 *
71 */
72 NTSTATUS
73 NTAPI
74 RtlpQueryRemoteProcessModules(HANDLE ProcessHandle,
75 IN PRTL_PROCESS_MODULES Modules OPTIONAL,
76 IN ULONG Size OPTIONAL,
77 OUT PULONG ReturnedSize)
78 {
79 PROCESS_BASIC_INFORMATION pbiInfo;
80 PPEB_LDR_DATA ppldLdrData;
81 LDR_DATA_TABLE_ENTRY lmModule;
82 PLIST_ENTRY pleListHead;
83 PLIST_ENTRY pleCurEntry;
84
85 PRTL_PROCESS_MODULE_INFORMATION ModulePtr = NULL;
86 NTSTATUS Status = STATUS_SUCCESS;
87 ULONG UsedSize = sizeof(ULONG);
88 ANSI_STRING AnsiString;
89 PCHAR p;
90
91 DPRINT("RtlpQueryRemoteProcessModules Start\n");
92
93 /* query the process basic information (includes the PEB address) */
94 Status = NtQueryInformationProcess(ProcessHandle,
95 ProcessBasicInformation,
96 &pbiInfo,
97 sizeof(PROCESS_BASIC_INFORMATION),
98 NULL);
99
100 if (!NT_SUCCESS(Status))
101 {
102 /* failure */
103 DPRINT("NtQueryInformationProcess 1 0x%lx \n", Status);
104 return Status;
105 }
106
107 if (Modules == NULL || Size == 0)
108 {
109 Status = STATUS_INFO_LENGTH_MISMATCH;
110 }
111 else
112 {
113 Modules->NumberOfModules = 0;
114 ModulePtr = &Modules->Modules[0];
115 Status = STATUS_SUCCESS;
116 }
117
118 /* get the address of the PE Loader data */
119 Status = NtReadVirtualMemory(ProcessHandle,
120 &(pbiInfo.PebBaseAddress->Ldr),
121 &ppldLdrData,
122 sizeof(ppldLdrData),
123 NULL);
124
125 if (!NT_SUCCESS(Status))
126 {
127 /* failure */
128 DPRINT("NtReadVirtualMemory 1 0x%lx \n", Status);
129 return Status;
130 }
131
132
133 /* head of the module list: the last element in the list will point to this */
134 pleListHead = &ppldLdrData->InLoadOrderModuleList;
135
136 /* get the address of the first element in the list */
137 Status = NtReadVirtualMemory(ProcessHandle,
138 &(ppldLdrData->InLoadOrderModuleList.Flink),
139 &pleCurEntry,
140 sizeof(pleCurEntry),
141 NULL);
142
143 if (!NT_SUCCESS(Status))
144 {
145 /* failure */
146 DPRINT("NtReadVirtualMemory 2 0x%lx \n", Status);
147 return Status;
148 }
149
150 while(pleCurEntry != pleListHead)
151 {
152 UNICODE_STRING Unicode;
153 WCHAR Buffer[256 * sizeof(WCHAR)];
154
155 /* read the current module */
156 Status = NtReadVirtualMemory(ProcessHandle,
157 CONTAINING_RECORD(pleCurEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks),
158 &lmModule,
159 sizeof(LDR_DATA_TABLE_ENTRY),
160 NULL);
161
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;
166
167 Status = NtReadVirtualMemory(ProcessHandle,
168 lmModule.FullDllName.Buffer,
169 Unicode.Buffer,
170 Unicode.Length,
171 NULL);
172
173 if (!NT_SUCCESS(Status))
174 {
175 /* failure */
176 DPRINT( "NtReadVirtualMemory 3 0x%lx \n", Status);
177 return Status;
178 }
179
180 DPRINT(" Module %wZ\n", &Unicode);
181
182 if (UsedSize > Size)
183 {
184 Status = STATUS_INFO_LENGTH_MISMATCH;
185 }
186 else if (Modules != NULL)
187 {
188 ModulePtr->Section = 0;
189 ModulePtr->MappedBase = NULL; // FIXME: ??
190 ModulePtr->ImageBase = lmModule.DllBase;
191 ModulePtr->ImageSize = lmModule.SizeOfImage;
192 ModulePtr->Flags = lmModule.Flags;
193 ModulePtr->LoadOrderIndex = 0; // FIXME: ??
194 ModulePtr->InitOrderIndex = 0; // FIXME: ??
195 ModulePtr->LoadCount = lmModule.LoadCount;
196
197 AnsiString.Length = 0;
198 AnsiString.MaximumLength = 256;
199 AnsiString.Buffer = ModulePtr->FullPathName;
200 RtlUnicodeStringToAnsiString(&AnsiString,
201 &Unicode,
202 FALSE);
203
204 p = strrchr(ModulePtr->FullPathName, '\\');
205 if (p != NULL)
206 ModulePtr->OffsetToFileName = (USHORT)(p - ModulePtr->FullPathName + 1);
207 else
208 ModulePtr->OffsetToFileName = 0;
209
210 ModulePtr++;
211 Modules->NumberOfModules++;
212 }
213 UsedSize += sizeof(RTL_PROCESS_MODULE_INFORMATION);
214
215 /* address of the next module in the list */
216 pleCurEntry = lmModule.InLoadOrderLinks.Flink;
217 }
218
219 if (ReturnedSize != 0)
220 *ReturnedSize = UsedSize;
221
222 DPRINT("RtlpQueryRemoteProcessModules End\n");
223
224 /* success */
225 return (STATUS_SUCCESS);
226 }
227
228 /*
229 * @unimplemented
230 */
231 NTSTATUS
232 NTAPI
233 RtlQueryProcessDebugInformation(IN ULONG ProcessId,
234 IN ULONG DebugInfoMask,
235 IN OUT PRTL_DEBUG_INFORMATION Buf)
236 {
237 NTSTATUS Status = STATUS_SUCCESS;
238 ULONG Pid = (ULONG)(ULONG_PTR) NtCurrentTeb()->ClientId.UniqueProcess;
239
240 Buf->Flags = DebugInfoMask;
241 Buf->OffsetFree = sizeof(RTL_DEBUG_INFORMATION);
242
243 DPRINT("QueryProcessDebugInformation Start\n");
244
245 /*
246 Currently ROS can not read-only from kenrel space, and doesn't
247 check for boundaries inside kernel space that are page protected
248 from every one but the kernel. aka page 0 - 2
249 */
250 if (ProcessId <= 1)
251 {
252 Status = STATUS_ACCESS_VIOLATION;
253 }
254 else
255 if (Pid == ProcessId)
256 {
257 if (DebugInfoMask & RTL_DEBUG_QUERY_MODULES)
258 {
259 PRTL_PROCESS_MODULES Mp;
260 ULONG ReturnSize = 0;
261 ULONG MSize;
262
263 Mp = (PRTL_PROCESS_MODULES)((PUCHAR)Buf + Buf->OffsetFree);
264
265 /* I like this better than the do & while loop. */
266 Status = LdrQueryProcessModuleInformation(NULL,
267 0,
268 &ReturnSize);
269 Status = LdrQueryProcessModuleInformation(Mp,
270 ReturnSize ,
271 &ReturnSize);
272 if (!NT_SUCCESS(Status))
273 {
274 return Status;
275 }
276
277 MSize = Mp->NumberOfModules * (sizeof(RTL_PROCESS_MODULES) + 8);
278 Buf->Modules = Mp;
279 Buf->OffsetFree = Buf->OffsetFree + MSize;
280 }
281
282 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAPS)
283 {
284 PRTL_PROCESS_HEAPS Hp;
285 ULONG HSize;
286
287 Hp = (PRTL_PROCESS_HEAPS)((PUCHAR)Buf + Buf->OffsetFree);
288 HSize = sizeof(RTL_PROCESS_HEAPS);
289 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAP_TAGS)
290 {
291 // TODO
292 }
293 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAP_BLOCKS)
294 {
295 // TODO
296 }
297 Buf->Heaps = Hp;
298 Buf->OffsetFree = Buf->OffsetFree + HSize;
299
300 }
301
302 if (DebugInfoMask & RTL_DEBUG_QUERY_LOCKS)
303 {
304 PRTL_PROCESS_LOCKS Lp;
305 ULONG LSize;
306
307 Lp = (PRTL_PROCESS_LOCKS)((PUCHAR)Buf + Buf->OffsetFree);
308 LSize = sizeof(RTL_PROCESS_LOCKS);
309 Buf->Locks = Lp;
310 Buf->OffsetFree = Buf->OffsetFree + LSize;
311 }
312
313 DPRINT("QueryProcessDebugInformation end \n");
314 DPRINT("QueryDebugInfo : 0x%lx\n", Buf->OffsetFree);
315 }
316 else
317 {
318 HANDLE hProcess;
319 CLIENT_ID ClientId;
320 OBJECT_ATTRIBUTES ObjectAttributes;
321
322 Buf->TargetProcessHandle = NtCurrentProcess();
323
324 ClientId.UniqueThread = 0;
325 ClientId.UniqueProcess = (HANDLE)(ULONG_PTR)ProcessId;
326 InitializeObjectAttributes(&ObjectAttributes,
327 NULL,
328 0,
329 NULL,
330 NULL);
331
332 Status = NtOpenProcess(&hProcess,
333 (PROCESS_ALL_ACCESS),
334 &ObjectAttributes,
335 &ClientId );
336 if (!NT_SUCCESS(Status))
337 {
338 return Status;
339 }
340
341 if (DebugInfoMask & RTL_DEBUG_QUERY_MODULES)
342 {
343 PRTL_PROCESS_MODULES Mp;
344 ULONG ReturnSize = 0;
345 ULONG MSize;
346
347 Mp = (PRTL_PROCESS_MODULES)((PUCHAR)Buf + Buf->OffsetFree);
348
349 Status = RtlpQueryRemoteProcessModules(hProcess,
350 NULL,
351 0,
352 &ReturnSize);
353
354 Status = RtlpQueryRemoteProcessModules(hProcess,
355 Mp,
356 ReturnSize ,
357 &ReturnSize);
358 if (!NT_SUCCESS(Status))
359 {
360 return Status;
361 }
362
363 MSize = Mp->NumberOfModules * (sizeof(RTL_PROCESS_MODULES) + 8);
364 Buf->Modules = Mp;
365 Buf->OffsetFree = Buf->OffsetFree + MSize;
366 }
367
368 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAPS)
369 {
370 PRTL_PROCESS_HEAPS Hp;
371 ULONG HSize;
372
373 Hp = (PRTL_PROCESS_HEAPS)((PUCHAR)Buf + Buf->OffsetFree);
374 HSize = sizeof(RTL_PROCESS_HEAPS);
375 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAP_TAGS)
376 {
377 // TODO
378 }
379 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAP_BLOCKS)
380 {
381 // TODO
382 }
383 Buf->Heaps = Hp;
384 Buf->OffsetFree = Buf->OffsetFree + HSize;
385
386 }
387
388 if (DebugInfoMask & RTL_DEBUG_QUERY_LOCKS)
389 {
390 PRTL_PROCESS_LOCKS Lp;
391 ULONG LSize;
392
393 Lp = (PRTL_PROCESS_LOCKS)((PUCHAR)Buf + Buf->OffsetFree);
394 LSize = sizeof(RTL_PROCESS_LOCKS);
395 Buf->Locks = Lp;
396 Buf->OffsetFree = Buf->OffsetFree + LSize;
397 }
398
399 DPRINT("QueryProcessDebugInformation end \n");
400 DPRINT("QueryDebugInfo : 0x%lx\n", Buf->OffsetFree);
401 }
402
403 return Status;
404 }
405
406 /* EOL */