indent with astyle v1.15.3: --style=ansi -c -s3 -S --convert-tabs
[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 PDEBUG_BUFFER STDCALL
20 RtlCreateQueryDebugBuffer(IN ULONG Size,
21 IN BOOLEAN EventPair)
22 {
23 NTSTATUS Status;
24 PDEBUG_BUFFER Buf = NULL;
25 ULONG SectionSize = 100 * PAGE_SIZE;
26
27 Status = NtAllocateVirtualMemory( NtCurrentProcess(),
28 (PVOID)&Buf,
29 0,
30 &SectionSize,
31 MEM_COMMIT,
32 PAGE_READWRITE);
33 if (!NT_SUCCESS(Status))
34 {
35 return NULL;
36 }
37
38 Buf->SectionBase = Buf;
39 Buf->SectionSize = SectionSize;
40
41 DPRINT("RtlCQDB: BA: %x BS: %d\n", Buf->SectionBase, Buf->SectionSize);
42
43 return Buf;
44 }
45
46 /*
47 * @unimplemented
48 */
49 NTSTATUS STDCALL
50 RtlDestroyQueryDebugBuffer(IN PDEBUG_BUFFER Buf)
51 {
52 NTSTATUS Status = STATUS_SUCCESS;
53
54 if (NULL != Buf)
55 {
56 Status = NtFreeVirtualMemory( NtCurrentProcess(),
57 (PVOID)&Buf,
58 &Buf->SectionSize,
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 STDCALL
73 RtlpQueryRemoteProcessModules(HANDLE ProcessHandle,
74 IN PMODULE_INFORMATION ModuleInformation OPTIONAL,
75 IN ULONG Size OPTIONAL,
76 OUT PULONG ReturnedSize)
77 {
78 PROCESS_BASIC_INFORMATION pbiInfo;
79 PPEB_LDR_DATA ppldLdrData;
80 LDR_DATA_TABLE_ENTRY lmModule;
81 PLIST_ENTRY pleListHead;
82 PLIST_ENTRY pleCurEntry;
83
84 PDEBUG_MODULE_INFORMATION ModulePtr = NULL;
85 NTSTATUS Status = STATUS_SUCCESS;
86 ULONG UsedSize = sizeof(ULONG);
87 ANSI_STRING AnsiString;
88 PCHAR p;
89
90 DPRINT("RtlpQueryRemoteProcessModules Start\n");
91
92 /* query the process basic information (includes the PEB address) */
93 Status = NtQueryInformationProcess ( ProcessHandle,
94 ProcessBasicInformation,
95 &pbiInfo,
96 sizeof(PROCESS_BASIC_INFORMATION),
97 NULL);
98
99 if (!NT_SUCCESS(Status))
100 {
101 /* failure */
102 DPRINT("NtQueryInformationProcess 1 &x \n", Status);
103 return Status;
104 }
105
106 if (ModuleInformation == NULL || Size == 0)
107 {
108 Status = STATUS_INFO_LENGTH_MISMATCH;
109 }
110 else
111 {
112 ModuleInformation->ModuleCount = 0;
113 ModulePtr = &ModuleInformation->ModuleEntry[0];
114 Status = STATUS_SUCCESS;
115 }
116
117 /* get the address of the PE Loader data */
118 Status = NtReadVirtualMemory ( ProcessHandle,
119 &(pbiInfo.PebBaseAddress->Ldr),
120 &ppldLdrData,
121 sizeof(ppldLdrData),
122 NULL );
123
124 if (!NT_SUCCESS(Status))
125 {
126 /* failure */
127 DPRINT("NtReadVirtualMemory 1 %x \n", Status);
128 return Status;
129 }
130
131
132 /* head of the module list: the last element in the list will point to this */
133 pleListHead = &ppldLdrData->InLoadOrderModuleList;
134
135 /* get the address of the first element in the list */
136 Status = NtReadVirtualMemory ( ProcessHandle,
137 &(ppldLdrData->InLoadOrderModuleList.Flink),
138 &pleCurEntry,
139 sizeof(pleCurEntry),
140 NULL );
141
142 if (!NT_SUCCESS(Status))
143 {
144 /* failure */
145 DPRINT("NtReadVirtualMemory 2 %x \n", Status);
146 return Status;
147 }
148
149 while(pleCurEntry != pleListHead)
150 {
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, InLoadOrderModuleList),
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 %x \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 (ModuleInformation != NULL)
187 {
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;
195
196 AnsiString.Length = 0;
197 AnsiString.MaximumLength = 256;
198 AnsiString.Buffer = ModulePtr->ImageName;
199 RtlUnicodeStringToAnsiString(&AnsiString,
200 &Unicode,
201 FALSE);
202
203 p = strrchr(ModulePtr->ImageName, '\\');
204 if (p != NULL)
205 ModulePtr->ModuleNameOffset = p - ModulePtr->ImageName + 1;
206 else
207 ModulePtr->ModuleNameOffset = 0;
208
209 ModulePtr++;
210 ModuleInformation->ModuleCount++;
211 }
212 UsedSize += sizeof(DEBUG_MODULE_INFORMATION);
213
214 /* address of the next module in the list */
215 pleCurEntry = lmModule.InLoadOrderModuleList.Flink;
216 }
217
218 if (ReturnedSize != 0)
219 *ReturnedSize = UsedSize;
220
221 DPRINT("RtlpQueryRemoteProcessModules End\n");
222
223 /* success */
224 return (STATUS_SUCCESS);
225 }
226
227 /*
228 * @unimplemented
229 */
230 NTSTATUS STDCALL
231 RtlQueryProcessDebugInformation(IN ULONG ProcessId,
232 IN ULONG DebugInfoMask,
233 IN OUT PDEBUG_BUFFER Buf)
234 {
235 NTSTATUS Status = STATUS_SUCCESS;
236 ULONG Pid = (ULONG) NtCurrentTeb()->Cid.UniqueProcess;
237
238 Buf->InfoClassMask = DebugInfoMask;
239 Buf->SizeOfInfo = sizeof(DEBUG_BUFFER);
240
241 DPRINT("QueryProcessDebugInformation Start\n");
242
243 /*
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
247 */
248 if (ProcessId <= 1)
249 {
250 Status = STATUS_ACCESS_VIOLATION;
251 }
252 else
253 if (Pid == ProcessId)
254 {
255 if (DebugInfoMask & PDI_MODULES)
256 {
257 PMODULE_INFORMATION Mp;
258 ULONG ReturnSize = 0;
259 ULONG MSize;
260
261 Mp = (PMODULE_INFORMATION)(Buf + Buf->SizeOfInfo);
262
263 /* I like this better than the do & while loop. */
264 Status = LdrQueryProcessModuleInformation( NULL,
265 0 ,
266 &ReturnSize);
267 Status = LdrQueryProcessModuleInformation( Mp,
268 ReturnSize ,
269 &ReturnSize);
270 if (!NT_SUCCESS(Status))
271 {
272 return Status;
273 }
274
275 MSize = Mp->ModuleCount * (sizeof(MODULE_INFORMATION) + 8);
276 Buf->ModuleInformation = Mp;
277 Buf->SizeOfInfo = Buf->SizeOfInfo + MSize;
278 }
279
280 if (DebugInfoMask & PDI_HEAPS)
281 {
282 PHEAP_INFORMATION Hp;
283 ULONG HSize;
284
285 Hp = (PHEAP_INFORMATION)(Buf + Buf->SizeOfInfo);
286 HSize = sizeof(HEAP_INFORMATION);
287 if (DebugInfoMask & PDI_HEAP_TAGS)
288 {
289 }
290 if (DebugInfoMask & PDI_HEAP_BLOCKS)
291 {
292 }
293 Buf->HeapInformation = Hp;
294 Buf->SizeOfInfo = Buf->SizeOfInfo + HSize;
295
296 }
297
298 if (DebugInfoMask & PDI_LOCKS)
299 {
300 PLOCK_INFORMATION Lp;
301 ULONG LSize;
302
303 Lp = (PLOCK_INFORMATION)(Buf + Buf->SizeOfInfo);
304 LSize = sizeof(LOCK_INFORMATION);
305 Buf->LockInformation = Lp;
306 Buf->SizeOfInfo = Buf->SizeOfInfo + LSize;
307 }
308
309 DPRINT("QueryProcessDebugInformation end \n");
310 DPRINT("QueryDebugInfo : %d\n", Buf->SizeOfInfo);
311 }
312 else
313 {
314 HANDLE hProcess;
315 CLIENT_ID ClientId;
316 OBJECT_ATTRIBUTES ObjectAttributes;
317
318 Buf->Unknown[0] = (ULONG)NtCurrentProcess();
319
320 ClientId.UniqueThread = 0;
321 ClientId.UniqueProcess = (HANDLE)ProcessId;
322 InitializeObjectAttributes(&ObjectAttributes,
323 NULL,
324 0,
325 NULL,
326 NULL);
327
328 Status = NtOpenProcess( &hProcess,
329 (PROCESS_ALL_ACCESS),
330 &ObjectAttributes,
331 &ClientId );
332 if (!NT_SUCCESS(Status))
333 {
334 return Status;
335 }
336
337 if (DebugInfoMask & PDI_MODULES)
338 {
339 PMODULE_INFORMATION Mp;
340 ULONG ReturnSize = 0;
341 ULONG MSize;
342
343 Mp = (PMODULE_INFORMATION)(Buf + Buf->SizeOfInfo);
344
345 Status = RtlpQueryRemoteProcessModules( hProcess,
346 NULL,
347 0,
348 &ReturnSize);
349
350 Status = RtlpQueryRemoteProcessModules( hProcess,
351 Mp,
352 ReturnSize ,
353 &ReturnSize);
354 if (!NT_SUCCESS(Status))
355 {
356 return Status;
357 }
358
359 MSize = Mp->ModuleCount * (sizeof(MODULE_INFORMATION) + 8);
360 Buf->ModuleInformation = Mp;
361 Buf->SizeOfInfo = Buf->SizeOfInfo + MSize;
362 }
363
364 if (DebugInfoMask & PDI_HEAPS)
365 {
366 PHEAP_INFORMATION Hp;
367 ULONG HSize;
368
369 Hp = (PHEAP_INFORMATION)(Buf + Buf->SizeOfInfo);
370 HSize = sizeof(HEAP_INFORMATION);
371 if (DebugInfoMask & PDI_HEAP_TAGS)
372 {
373 }
374 if (DebugInfoMask & PDI_HEAP_BLOCKS)
375 {
376 }
377 Buf->HeapInformation = Hp;
378 Buf->SizeOfInfo = Buf->SizeOfInfo + HSize;
379
380 }
381
382 if (DebugInfoMask & PDI_LOCKS)
383 {
384 PLOCK_INFORMATION Lp;
385 ULONG LSize;
386
387 Lp = (PLOCK_INFORMATION)(Buf + Buf->SizeOfInfo);
388 LSize = sizeof(LOCK_INFORMATION);
389 Buf->LockInformation = Lp;
390 Buf->SizeOfInfo = Buf->SizeOfInfo + LSize;
391 }
392
393 DPRINT("QueryProcessDebugInformation end \n");
394 DPRINT("QueryDebugInfo : %d\n", Buf->SizeOfInfo);
395 }
396 return Status;
397
398 }
399
400 /* EOL */