[KSUSER] Improve pointer arithmetics
[reactos.git] / sdk / lib / rtl / dbgbuffer.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/rtl/dbgbuffer.c
5 * PROGRAMER: James Tabor
6 */
7
8 /* INCLUDES *****************************************************************/
9
10 #include <rtl.h>
11
12 #define NDEBUG
13 #include <debug.h>
14
15 /* FUNCTIONS *****************************************************************/
16
17 /*
18 * @unimplemented
19 */
20 PRTL_DEBUG_INFORMATION
21 NTAPI
22 RtlCreateQueryDebugBuffer(IN ULONG Size,
23 IN BOOLEAN EventPair)
24 {
25 NTSTATUS Status;
26 PRTL_DEBUG_INFORMATION Buf = NULL;
27 SIZE_T ViewSize = 100 * PAGE_SIZE;
28
29 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
30 (PVOID*)&Buf,
31 0,
32 &ViewSize,
33 MEM_RESERVE | MEM_COMMIT,
34 PAGE_READWRITE);
35 if (!NT_SUCCESS(Status)) return NULL;
36
37 Buf->ViewBaseClient = Buf;
38 Buf->ViewSize = (ULONG)ViewSize;
39
40 DPRINT("RtlCQDB: BA: %p BS: 0x%lx\n", Buf->ViewBaseClient, Buf->ViewSize);
41
42 return Buf;
43 }
44
45 /*
46 * @unimplemented
47 */
48 NTSTATUS
49 NTAPI
50 RtlDestroyQueryDebugBuffer(IN PRTL_DEBUG_INFORMATION Buf)
51 {
52 NTSTATUS Status = STATUS_SUCCESS;
53 SIZE_T ViewSize = 0;
54
55 if (NULL != Buf)
56 {
57 Status = NtFreeVirtualMemory(NtCurrentProcess(),
58 (PVOID*)&Buf,
59 &ViewSize,
60 MEM_RELEASE);
61 }
62 if (!NT_SUCCESS(Status))
63 {
64 DPRINT1("RtlDQDB: Failed to free VM!\n");
65 }
66 return Status;
67 }
68
69 /*
70 * Based on lib/epsapi/enum/modules.c by KJK::Hyperion.
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 if (!NT_SUCCESS(Status))
163 {
164 /* failure */
165 DPRINT( "NtReadVirtualMemory 3 0x%lx \n", Status);
166 return Status;
167 }
168
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;
173
174 Status = NtReadVirtualMemory(ProcessHandle,
175 lmModule.FullDllName.Buffer,
176 Unicode.Buffer,
177 Unicode.Length,
178 NULL);
179
180 if (!NT_SUCCESS(Status))
181 {
182 /* failure */
183 DPRINT( "NtReadVirtualMemory 3 0x%lx \n", Status);
184 return Status;
185 }
186
187 DPRINT(" Module %wZ\n", &Unicode);
188
189 if (UsedSize > Size)
190 {
191 Status = STATUS_INFO_LENGTH_MISMATCH;
192 }
193 else if (Modules != NULL)
194 {
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;
203
204 AnsiString.Length = 0;
205 AnsiString.MaximumLength = 256;
206 AnsiString.Buffer = ModulePtr->FullPathName;
207 RtlUnicodeStringToAnsiString(&AnsiString,
208 &Unicode,
209 FALSE);
210
211 p = strrchr(ModulePtr->FullPathName, '\\');
212 if (p != NULL)
213 ModulePtr->OffsetToFileName = (USHORT)(p - ModulePtr->FullPathName + 1);
214 else
215 ModulePtr->OffsetToFileName = 0;
216
217 ModulePtr++;
218 Modules->NumberOfModules++;
219 }
220 UsedSize += sizeof(RTL_PROCESS_MODULE_INFORMATION);
221
222 /* address of the next module in the list */
223 pleCurEntry = lmModule.InLoadOrderLinks.Flink;
224 }
225
226 if (ReturnedSize != 0)
227 *ReturnedSize = UsedSize;
228
229 DPRINT("RtlpQueryRemoteProcessModules End\n");
230
231 /* success */
232 return (STATUS_SUCCESS);
233 }
234
235 /*
236 * @unimplemented
237 */
238 NTSTATUS
239 NTAPI
240 RtlQueryProcessDebugInformation(IN ULONG ProcessId,
241 IN ULONG DebugInfoMask,
242 IN OUT PRTL_DEBUG_INFORMATION Buf)
243 {
244 NTSTATUS Status = STATUS_SUCCESS;
245 ULONG Pid = (ULONG)(ULONG_PTR) NtCurrentTeb()->ClientId.UniqueProcess;
246
247 Buf->Flags = DebugInfoMask;
248 Buf->OffsetFree = sizeof(RTL_DEBUG_INFORMATION);
249
250 DPRINT("QueryProcessDebugInformation Start\n");
251
252 /*
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
256 */
257 if (ProcessId <= 1)
258 {
259 Status = STATUS_ACCESS_VIOLATION;
260 }
261 else
262 if (Pid == ProcessId)
263 {
264 if (DebugInfoMask & RTL_DEBUG_QUERY_MODULES)
265 {
266 PRTL_PROCESS_MODULES Mp;
267 ULONG ReturnSize = 0;
268 ULONG MSize;
269
270 Mp = (PRTL_PROCESS_MODULES)((PUCHAR)Buf + Buf->OffsetFree);
271
272 /* I like this better than the do & while loop. */
273 Status = LdrQueryProcessModuleInformation(NULL,
274 0,
275 &ReturnSize);
276 Status = LdrQueryProcessModuleInformation(Mp,
277 ReturnSize ,
278 &ReturnSize);
279 if (!NT_SUCCESS(Status))
280 {
281 return Status;
282 }
283
284 MSize = Mp->NumberOfModules * (sizeof(RTL_PROCESS_MODULES) + 8);
285 Buf->Modules = Mp;
286 Buf->OffsetFree = Buf->OffsetFree + MSize;
287 }
288
289 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAPS)
290 {
291 PRTL_PROCESS_HEAPS Hp;
292 ULONG HSize;
293
294 Hp = (PRTL_PROCESS_HEAPS)((PUCHAR)Buf + Buf->OffsetFree);
295 HSize = sizeof(RTL_PROCESS_HEAPS);
296 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAP_TAGS)
297 {
298 // TODO
299 }
300 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAP_BLOCKS)
301 {
302 // TODO
303 }
304 Buf->Heaps = Hp;
305 Buf->OffsetFree = Buf->OffsetFree + HSize;
306
307 }
308
309 if (DebugInfoMask & RTL_DEBUG_QUERY_LOCKS)
310 {
311 PRTL_PROCESS_LOCKS Lp;
312 ULONG LSize;
313
314 Lp = (PRTL_PROCESS_LOCKS)((PUCHAR)Buf + Buf->OffsetFree);
315 LSize = sizeof(RTL_PROCESS_LOCKS);
316 Buf->Locks = Lp;
317 Buf->OffsetFree = Buf->OffsetFree + LSize;
318 }
319
320 DPRINT("QueryProcessDebugInformation end \n");
321 DPRINT("QueryDebugInfo : 0x%lx\n", Buf->OffsetFree);
322 }
323 else
324 {
325 HANDLE hProcess;
326 CLIENT_ID ClientId;
327 OBJECT_ATTRIBUTES ObjectAttributes;
328
329 Buf->TargetProcessHandle = NtCurrentProcess();
330
331 ClientId.UniqueThread = 0;
332 ClientId.UniqueProcess = (HANDLE)(ULONG_PTR)ProcessId;
333 InitializeObjectAttributes(&ObjectAttributes,
334 NULL,
335 0,
336 NULL,
337 NULL);
338
339 Status = NtOpenProcess(&hProcess,
340 (PROCESS_ALL_ACCESS),
341 &ObjectAttributes,
342 &ClientId );
343 if (!NT_SUCCESS(Status))
344 {
345 return Status;
346 }
347
348 if (DebugInfoMask & RTL_DEBUG_QUERY_MODULES)
349 {
350 PRTL_PROCESS_MODULES Mp;
351 ULONG ReturnSize = 0;
352 ULONG MSize;
353
354 Mp = (PRTL_PROCESS_MODULES)((PUCHAR)Buf + Buf->OffsetFree);
355
356 Status = RtlpQueryRemoteProcessModules(hProcess,
357 NULL,
358 0,
359 &ReturnSize);
360
361 Status = RtlpQueryRemoteProcessModules(hProcess,
362 Mp,
363 ReturnSize ,
364 &ReturnSize);
365 if (!NT_SUCCESS(Status))
366 {
367 return Status;
368 }
369
370 MSize = Mp->NumberOfModules * (sizeof(RTL_PROCESS_MODULES) + 8);
371 Buf->Modules = Mp;
372 Buf->OffsetFree = Buf->OffsetFree + MSize;
373 }
374
375 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAPS)
376 {
377 PRTL_PROCESS_HEAPS Hp;
378 ULONG HSize;
379
380 Hp = (PRTL_PROCESS_HEAPS)((PUCHAR)Buf + Buf->OffsetFree);
381 HSize = sizeof(RTL_PROCESS_HEAPS);
382 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAP_TAGS)
383 {
384 // TODO
385 }
386 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAP_BLOCKS)
387 {
388 // TODO
389 }
390 Buf->Heaps = Hp;
391 Buf->OffsetFree = Buf->OffsetFree + HSize;
392
393 }
394
395 if (DebugInfoMask & RTL_DEBUG_QUERY_LOCKS)
396 {
397 PRTL_PROCESS_LOCKS Lp;
398 ULONG LSize;
399
400 Lp = (PRTL_PROCESS_LOCKS)((PUCHAR)Buf + Buf->OffsetFree);
401 LSize = sizeof(RTL_PROCESS_LOCKS);
402 Buf->Locks = Lp;
403 Buf->OffsetFree = Buf->OffsetFree + LSize;
404 }
405
406 DPRINT("QueryProcessDebugInformation end \n");
407 DPRINT("QueryDebugInfo : 0x%lx\n", Buf->OffsetFree);
408 }
409
410 return Status;
411 }
412
413 /* EOL */