- NDK 0.98, now with versionned headers. Too many changes to list, see the TinyKRNL...
[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 NTAPI
20 RtlCreateQueryDebugBuffer(IN ULONG Size,
21 IN BOOLEAN EventPair)
22 {
23 NTSTATUS Status;
24 PRTL_DEBUG_INFORMATION Buf = NULL;
25 SIZE_T ViewSize = 100 * PAGE_SIZE;
26
27 Status = NtAllocateVirtualMemory( NtCurrentProcess(),
28 (PVOID*)&Buf,
29 0,
30 &ViewSize,
31 MEM_COMMIT,
32 PAGE_READWRITE);
33 if (!NT_SUCCESS(Status))
34 {
35 return NULL;
36 }
37
38 Buf->ViewBaseClient = Buf;
39 Buf->ViewSize = ViewSize;
40
41 DPRINT("RtlCQDB: BA: %p BS: 0x%lx\n", Buf->ViewBaseClient, Buf->ViewSize);
42
43 return Buf;
44 }
45
46 /*
47 * @unimplemented
48 */
49 NTSTATUS NTAPI
50 RtlDestroyQueryDebugBuffer(IN PRTL_DEBUG_INFORMATION Buf)
51 {
52 NTSTATUS Status = STATUS_SUCCESS;
53
54 if (NULL != Buf)
55 {
56 Status = NtFreeVirtualMemory( NtCurrentProcess(),
57 (PVOID)&Buf,
58 &Buf->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 NTAPI
73 RtlpQueryRemoteProcessModules(HANDLE ProcessHandle,
74 IN PRTL_PROCESS_MODULES Modules 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 PRTL_PROCESS_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 0x%lx \n", Status);
103 return Status;
104 }
105
106 if (Modules == NULL || Size == 0)
107 {
108 Status = STATUS_INFO_LENGTH_MISMATCH;
109 }
110 else
111 {
112 Modules->NumberOfModules = 0;
113 ModulePtr = &Modules->Modules[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 0x%lx \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 0x%lx \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, 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 = 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 NTAPI
232 RtlQueryProcessDebugInformation(IN ULONG ProcessId,
233 IN ULONG DebugInfoMask,
234 IN OUT PRTL_DEBUG_INFORMATION Buf)
235 {
236 NTSTATUS Status = STATUS_SUCCESS;
237 ULONG Pid = (ULONG) NtCurrentTeb()->Cid.UniqueProcess;
238
239 Buf->Flags = DebugInfoMask;
240 Buf->OffsetFree = sizeof(RTL_DEBUG_INFORMATION);
241
242 DPRINT("QueryProcessDebugInformation Start\n");
243
244 /*
245 Currently ROS can not read-only from kenrel space, and doesn't
246 check for boundaries inside kernel space that are page protected
247 from every one but the kernel. aka page 0 - 2
248 */
249 if (ProcessId <= 1)
250 {
251 Status = STATUS_ACCESS_VIOLATION;
252 }
253 else
254 if (Pid == ProcessId)
255 {
256 if (DebugInfoMask & RTL_DEBUG_QUERY_MODULES)
257 {
258 PRTL_PROCESS_MODULES Mp;
259 ULONG ReturnSize = 0;
260 ULONG MSize;
261
262 Mp = (PRTL_PROCESS_MODULES)(Buf + Buf->OffsetFree);
263
264 /* I like this better than the do & while loop. */
265 Status = LdrQueryProcessModuleInformation( NULL,
266 0 ,
267 &ReturnSize);
268 Status = LdrQueryProcessModuleInformation( Mp,
269 ReturnSize ,
270 &ReturnSize);
271 if (!NT_SUCCESS(Status))
272 {
273 return Status;
274 }
275
276 MSize = Mp->NumberOfModules * (sizeof(RTL_PROCESS_MODULES) + 8);
277 Buf->Modules = Mp;
278 Buf->OffsetFree = Buf->OffsetFree + MSize;
279 }
280
281 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAPS)
282 {
283 PRTL_PROCESS_HEAPS Hp;
284 ULONG HSize;
285
286 Hp = (PRTL_PROCESS_HEAPS)(Buf + Buf->OffsetFree);
287 HSize = sizeof(RTL_PROCESS_HEAPS);
288 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAP_TAGS)
289 {
290 }
291 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAP_BLOCKS)
292 {
293 }
294 Buf->Heaps = Hp;
295 Buf->OffsetFree = Buf->OffsetFree + HSize;
296
297 }
298
299 if (DebugInfoMask & RTL_DEBUG_QUERY_LOCKS)
300 {
301 PRTL_PROCESS_LOCKS Lp;
302 ULONG LSize;
303
304 Lp = (PRTL_PROCESS_LOCKS)(Buf + Buf->OffsetFree);
305 LSize = sizeof(RTL_PROCESS_LOCKS);
306 Buf->Locks = Lp;
307 Buf->OffsetFree = Buf->OffsetFree + LSize;
308 }
309
310 DPRINT("QueryProcessDebugInformation end \n");
311 DPRINT("QueryDebugInfo : 0x%lx\n", Buf->OffsetFree);
312 }
313 else
314 {
315 HANDLE hProcess;
316 CLIENT_ID ClientId;
317 OBJECT_ATTRIBUTES ObjectAttributes;
318
319 Buf->TargetProcessHandle = NtCurrentProcess();
320
321 ClientId.UniqueThread = 0;
322 ClientId.UniqueProcess = (HANDLE)ProcessId;
323 InitializeObjectAttributes(&ObjectAttributes,
324 NULL,
325 0,
326 NULL,
327 NULL);
328
329 Status = NtOpenProcess( &hProcess,
330 (PROCESS_ALL_ACCESS),
331 &ObjectAttributes,
332 &ClientId );
333 if (!NT_SUCCESS(Status))
334 {
335 return Status;
336 }
337
338 if (DebugInfoMask & RTL_DEBUG_QUERY_MODULES)
339 {
340 PRTL_PROCESS_MODULES Mp;
341 ULONG ReturnSize = 0;
342 ULONG MSize;
343
344 Mp = (PRTL_PROCESS_MODULES)(Buf + Buf->OffsetFree);
345
346 Status = RtlpQueryRemoteProcessModules( hProcess,
347 NULL,
348 0,
349 &ReturnSize);
350
351 Status = RtlpQueryRemoteProcessModules( hProcess,
352 Mp,
353 ReturnSize ,
354 &ReturnSize);
355 if (!NT_SUCCESS(Status))
356 {
357 return Status;
358 }
359
360 MSize = Mp->NumberOfModules * (sizeof(RTL_PROCESS_MODULES) + 8);
361 Buf->Modules = Mp;
362 Buf->OffsetFree = Buf->OffsetFree + MSize;
363 }
364
365 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAPS)
366 {
367 PRTL_PROCESS_HEAPS Hp;
368 ULONG HSize;
369
370 Hp = (PRTL_PROCESS_HEAPS)(Buf + Buf->OffsetFree);
371 HSize = sizeof(RTL_PROCESS_HEAPS);
372 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAP_TAGS)
373 {
374 }
375 if (DebugInfoMask & RTL_DEBUG_QUERY_HEAP_BLOCKS)
376 {
377 }
378 Buf->Heaps = Hp;
379 Buf->OffsetFree = Buf->OffsetFree + HSize;
380
381 }
382
383 if (DebugInfoMask & RTL_DEBUG_QUERY_LOCKS)
384 {
385 PRTL_PROCESS_LOCKS Lp;
386 ULONG LSize;
387
388 Lp = (PRTL_PROCESS_LOCKS)(Buf + Buf->OffsetFree);
389 LSize = sizeof(RTL_PROCESS_LOCKS);
390 Buf->Locks = Lp;
391 Buf->OffsetFree = Buf->OffsetFree + LSize;
392 }
393
394 DPRINT("QueryProcessDebugInformation end \n");
395 DPRINT("QueryDebugInfo : 0x%lx\n", Buf->OffsetFree);
396 }
397 return Status;
398
399 }
400
401 /* EOL */