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 */ 414