Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

dbgkproc.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 dbgkproc.c 00008 00009 Abstract: 00010 00011 This module implements process control primitives for the 00012 Dbg component of NT 00013 00014 Author: 00015 00016 Mark Lucovsky (markl) 19-Jan-1990 00017 00018 Revision History: 00019 00020 --*/ 00021 00022 #include "dbgkp.h" 00023 00024 #ifdef ALLOC_PRAGMA 00025 #pragma alloc_text(PAGE, DbgkpSuspendProcess) 00026 #pragma alloc_text(PAGE, DbgkpResumeProcess) 00027 #pragma alloc_text(PAGE, DbgkpSectionHandleToFileHandle) 00028 #pragma alloc_text(PAGE, DbgkCreateThread) 00029 #pragma alloc_text(PAGE, DbgkExitThread) 00030 #pragma alloc_text(PAGE, DbgkExitProcess) 00031 #pragma alloc_text(PAGE, DbgkMapViewOfSection) 00032 #pragma alloc_text(PAGE, DbgkUnMapViewOfSection) 00033 #endif 00034 00035 VOID 00036 DbgkpSuspendProcess( 00037 IN BOOLEAN CreateDeleteLockHeld 00038 ) 00039 00040 /*++ 00041 00042 Routine Description: 00043 00044 This function causes all threads in the calling process except for 00045 the calling thread to suspend. 00046 00047 Arguments: 00048 00049 CreateDeleteLockHeld - Supplies a flag that specifies whether or not 00050 the caller is holding the process create delete lock. If the 00051 caller holds the lock, than this function will not aquire the 00052 lock before suspending the process. 00053 00054 Return Value: 00055 00056 None. 00057 00058 --*/ 00059 00060 { 00061 PEPROCESS Process; 00062 00063 PAGED_CODE(); 00064 00065 Process = PsGetCurrentProcess(); 00066 00067 // 00068 // Freeze the execution of all threads in the current process, but 00069 // the calling thread. 00070 // 00071 if ( !CreateDeleteLockHeld ) { 00072 PsLockProcess(Process,KernelMode,PsLockWaitForever); 00073 } 00074 00075 KeFreezeAllThreads(); 00076 00077 if ( !CreateDeleteLockHeld ) { 00078 PsUnlockProcess(Process); 00079 } 00080 00081 00082 return; 00083 } 00084 00085 VOID 00086 DbgkpResumeProcess( 00087 IN BOOLEAN CreateDeleteLockHeld 00088 ) 00089 00090 /*++ 00091 00092 Routine Description: 00093 00094 This function causes all threads in the calling process except for 00095 the calling thread to resume. 00096 00097 Arguments: 00098 00099 CreateDeleteLockHeld - Supplies a flag that specifies whether or not 00100 the caller is holding the process create delete lock. If the 00101 caller holds the lock, than this function will not aquire the 00102 lock before suspending the process. 00103 00104 Return Value: 00105 00106 None. 00107 00108 --*/ 00109 00110 { 00111 00112 PEPROCESS Process; 00113 00114 PAGED_CODE(); 00115 00116 Process = PsGetCurrentProcess(); 00117 // 00118 // Thaw the execution of all threads in the current process, but 00119 // the calling thread. 00120 // 00121 00122 if ( !CreateDeleteLockHeld ) { 00123 PsLockProcess(Process,KernelMode,PsLockWaitForever); 00124 } 00125 00126 KeThawAllThreads(); 00127 00128 if ( !CreateDeleteLockHeld ) { 00129 PsUnlockProcess(Process); 00130 } 00131 00132 return; 00133 } 00134 00135 HANDLE 00136 DbgkpSectionHandleToFileHandle( 00137 IN HANDLE SectionHandle 00138 ) 00139 00140 /*++ 00141 00142 Routine Description: 00143 00144 This function Opens a handle to the file associated with the processes 00145 section. The file is opened such that it can be dupped all the way to 00146 the UI where the UI can either map the file or read the file to get 00147 the debug info. 00148 00149 Arguments: 00150 00151 SectionHandle - Supplies a handle to the section whose associated file 00152 is to be opened. 00153 00154 Return Value: 00155 00156 NULL - The file could not be opened. 00157 00158 NON-NULL - Returns a handle to the file associated with the specified 00159 section. 00160 00161 --*/ 00162 00163 { 00164 NTSTATUS Status; 00165 ANSI_STRING FileName; 00166 UNICODE_STRING UnicodeFileName; 00167 OBJECT_ATTRIBUTES Obja; 00168 IO_STATUS_BLOCK IoStatusBlock; 00169 HANDLE Handle; 00170 00171 PAGED_CODE(); 00172 00173 Status = MmGetFileNameForSection(SectionHandle, (PSTRING)&FileName); 00174 if ( !NT_SUCCESS(Status) ) { 00175 return NULL; 00176 } 00177 00178 Status = RtlAnsiStringToUnicodeString(&UnicodeFileName,&FileName,TRUE); 00179 ExFreePool(FileName.Buffer); 00180 if ( !NT_SUCCESS(Status) ) { 00181 return NULL; 00182 } 00183 00184 InitializeObjectAttributes( 00185 &Obja, 00186 &UnicodeFileName, 00187 OBJ_CASE_INSENSITIVE, 00188 NULL, 00189 NULL 00190 ); 00191 00192 Status = ZwOpenFile( 00193 &Handle, 00194 (ACCESS_MASK)(GENERIC_READ | SYNCHRONIZE), 00195 &Obja, 00196 &IoStatusBlock, 00197 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 00198 FILE_SYNCHRONOUS_IO_NONALERT 00199 ); 00200 RtlFreeUnicodeString(&UnicodeFileName); 00201 if ( !NT_SUCCESS(Status) ) { 00202 return NULL; 00203 } 00204 else { 00205 return Handle; 00206 } 00207 } 00208 00209 00210 VOID 00211 DbgkCreateThread( 00212 PVOID StartAddress 00213 ) 00214 00215 /*++ 00216 00217 Routine Description: 00218 00219 This function is called when a new thread begins to execute. If the 00220 thread has an associated DebugPort, then a message is sent thru the 00221 port. 00222 00223 If this thread is the first thread in the process, then this event 00224 is translated into a CreateProcessInfo message. 00225 00226 If a message is sent, then while the thread is awaiting a reply, 00227 all other threads in the process are suspended. 00228 00229 Arguments: 00230 00231 StartAddress - Supplies the start address for the thread that is 00232 starting. 00233 00234 Return Value: 00235 00236 None. 00237 00238 --*/ 00239 00240 { 00241 PVOID Port; 00242 DBGKM_APIMSG m; 00243 PDBGKM_CREATE_THREAD CreateThreadArgs; 00244 PDBGKM_CREATE_PROCESS CreateProcessArgs; 00245 PETHREAD Thread; 00246 PEPROCESS Process; 00247 PDBGKM_LOAD_DLL LoadDllArgs; 00248 NTSTATUS Status; 00249 OBJECT_ATTRIBUTES Obja; 00250 IO_STATUS_BLOCK IoStatusBlock; 00251 PIMAGE_NT_HEADERS NtHeaders; 00252 00253 PAGED_CODE(); 00254 00255 Process = PsGetCurrentProcess(); 00256 00257 Port = PsGetCurrentThread()->HideFromDebugger ? NULL : Process->DebugPort; 00258 00259 if ( PsImageNotifyEnabled && !Process->Pcb.UserTime) { 00260 IMAGE_INFO ImageInfo; 00261 PIMAGE_NT_HEADERS NtHeaders; 00262 ANSI_STRING FileName; 00263 UNICODE_STRING UnicodeFileName; 00264 PUNICODE_STRING pUnicodeFileName; 00265 00266 // 00267 // notification of main .exe 00268 // 00269 ImageInfo.Properties = 0; 00270 ImageInfo.ImageAddressingMode = IMAGE_ADDRESSING_MODE_32BIT; 00271 ImageInfo.ImageBase = Process->SectionBaseAddress; 00272 ImageInfo.ImageSize = 0; 00273 00274 try { 00275 NtHeaders = RtlImageNtHeader(Process->SectionBaseAddress); 00276 00277 if ( NtHeaders ) { 00278 ImageInfo.ImageSize = NtHeaders->OptionalHeader.SizeOfImage; 00279 } 00280 } 00281 except(EXCEPTION_EXECUTE_HANDLER) { 00282 ImageInfo.ImageSize = 0; 00283 } 00284 ImageInfo.ImageSelector = 0; 00285 ImageInfo.ImageSectionNumber = 0; 00286 00287 pUnicodeFileName = NULL; 00288 Status = MmGetFileNameForSection(Process->SectionHandle, (PSTRING)&FileName); 00289 if ( NT_SUCCESS(Status) ) { 00290 Status = RtlAnsiStringToUnicodeString(&UnicodeFileName,&FileName,TRUE); 00291 ExFreePool(FileName.Buffer); 00292 if ( NT_SUCCESS(Status) ) { 00293 pUnicodeFileName = &UnicodeFileName; 00294 } 00295 } 00296 PsCallImageNotifyRoutines( 00297 pUnicodeFileName, 00298 Process->UniqueProcessId, 00299 &ImageInfo 00300 ); 00301 if ( pUnicodeFileName ) { 00302 RtlFreeUnicodeString(pUnicodeFileName); 00303 } 00304 00305 // 00306 // and of ntdll.dll 00307 // 00308 ImageInfo.Properties = 0; 00309 ImageInfo.ImageAddressingMode = IMAGE_ADDRESSING_MODE_32BIT; 00310 ImageInfo.ImageBase = PsSystemDllBase; 00311 ImageInfo.ImageSize = 0; 00312 00313 try { 00314 NtHeaders = RtlImageNtHeader(PsSystemDllBase); 00315 if ( NtHeaders ) { 00316 ImageInfo.ImageSize = NtHeaders->OptionalHeader.SizeOfImage; 00317 } 00318 } 00319 except(EXCEPTION_EXECUTE_HANDLER) { 00320 ImageInfo.ImageSize = 0; 00321 } 00322 00323 ImageInfo.ImageSelector = 0; 00324 ImageInfo.ImageSectionNumber = 0; 00325 00326 RtlInitUnicodeString(&UnicodeFileName,L"\\SystemRoot\\System32\\ntdll.dll"); 00327 PsCallImageNotifyRoutines( 00328 &UnicodeFileName, 00329 Process->UniqueProcessId, 00330 &ImageInfo 00331 ); 00332 } 00333 00334 00335 if ( !Port ) { 00336 00337 return; 00338 } 00339 00340 Thread = PsGetCurrentThread(); 00341 00342 if ( Thread->DeadThread ) { 00343 return; 00344 } 00345 00346 // 00347 // To determine if this should be turned into a create process, 00348 // all threads in the process are suspended. The process list 00349 // is then examined to see if the curent thread is the only thread 00350 // on the list. If so, this becomes a create process message 00351 // 00352 00353 PsLockProcess(Process,KernelMode,PsLockWaitForever); 00354 00355 // 00356 // If we are doing a debug attach, then the create process has 00357 // already occured. If this is the case, then the process has 00358 // accumulated some time, so set reported to true 00359 // 00360 00361 if ( Process->Pcb.UserTime ) { 00362 Process->CreateProcessReported = TRUE; 00363 } 00364 00365 if ( Process->CreateProcessReported == FALSE ) { 00366 00367 // 00368 // This is a create process 00369 // 00370 00371 Process->CreateProcessReported = TRUE; 00372 00373 CreateThreadArgs = &m.u.CreateProcessInfo.InitialThread; 00374 CreateThreadArgs->SubSystemKey = 0; 00375 00376 CreateProcessArgs = &m.u.CreateProcessInfo; 00377 CreateProcessArgs->SubSystemKey = 0; 00378 CreateProcessArgs->FileHandle = DbgkpSectionHandleToFileHandle( 00379 Process->SectionHandle 00380 ); 00381 CreateProcessArgs->BaseOfImage = Process->SectionBaseAddress; 00382 CreateThreadArgs->StartAddress = NULL; 00383 CreateProcessArgs->DebugInfoFileOffset = 0; 00384 CreateProcessArgs->DebugInfoSize = 0; 00385 00386 try { 00387 NtHeaders = RtlImageNtHeader(Process->SectionBaseAddress); 00388 if ( NtHeaders ) { 00389 CreateThreadArgs->StartAddress = (PVOID)( 00390 NtHeaders->OptionalHeader.ImageBase + 00391 NtHeaders->OptionalHeader.AddressOfEntryPoint); 00392 00393 CreateProcessArgs->DebugInfoFileOffset = NtHeaders->FileHeader.PointerToSymbolTable; 00394 CreateProcessArgs->DebugInfoSize = NtHeaders->FileHeader.NumberOfSymbols; 00395 } 00396 } 00397 except(EXCEPTION_EXECUTE_HANDLER) { 00398 CreateThreadArgs->StartAddress = NULL; 00399 CreateProcessArgs->DebugInfoFileOffset = 0; 00400 CreateProcessArgs->DebugInfoSize = 0; 00401 } 00402 00403 DBGKM_FORMAT_API_MSG(m,DbgKmCreateProcessApi,sizeof(*CreateProcessArgs)); 00404 00405 PsUnlockProcess(Process); 00406 00407 DbgkpSendApiMessage(&m,Port,FALSE); 00408 ZwClose(CreateProcessArgs->FileHandle); 00409 00410 LoadDllArgs = &m.u.LoadDll; 00411 LoadDllArgs->BaseOfDll = PsSystemDllBase; 00412 LoadDllArgs->DebugInfoFileOffset = 0; 00413 LoadDllArgs->DebugInfoSize = 0; 00414 00415 try { 00416 NtHeaders = RtlImageNtHeader(PsSystemDllBase); 00417 if ( NtHeaders ) { 00418 LoadDllArgs->DebugInfoFileOffset = NtHeaders->FileHeader.PointerToSymbolTable; 00419 LoadDllArgs->DebugInfoSize = NtHeaders->FileHeader.NumberOfSymbols; 00420 } 00421 } 00422 except(EXCEPTION_EXECUTE_HANDLER) { 00423 LoadDllArgs->DebugInfoFileOffset = 0; 00424 LoadDllArgs->DebugInfoSize = 0; 00425 } 00426 00427 // 00428 // Send load dll section for NT dll ! 00429 // 00430 00431 InitializeObjectAttributes( 00432 &Obja, 00433 &PsNtDllPathName, 00434 OBJ_CASE_INSENSITIVE, 00435 NULL, 00436 NULL 00437 ); 00438 00439 Status = ZwOpenFile( 00440 &LoadDllArgs->FileHandle, 00441 (ACCESS_MASK)(GENERIC_READ | SYNCHRONIZE), 00442 &Obja, 00443 &IoStatusBlock, 00444 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 00445 FILE_SYNCHRONOUS_IO_NONALERT 00446 ); 00447 00448 if ( NT_SUCCESS(Status) ) { 00449 DBGKM_FORMAT_API_MSG(m,DbgKmLoadDllApi,sizeof(*LoadDllArgs)); 00450 DbgkpSendApiMessage(&m,Port,TRUE); 00451 } 00452 ZwClose(LoadDllArgs->FileHandle); 00453 00454 } else { 00455 00456 CreateThreadArgs = &m.u.CreateThread; 00457 CreateThreadArgs->SubSystemKey = 0; 00458 CreateThreadArgs->StartAddress = StartAddress; 00459 00460 DBGKM_FORMAT_API_MSG(m,DbgKmCreateThreadApi,sizeof(*CreateThreadArgs)); 00461 00462 PsUnlockProcess(Process); 00463 00464 DbgkpSendApiMessage(&m,Port,TRUE); 00465 } 00466 00467 00468 } 00469 00470 VOID 00471 DbgkExitThread( 00472 NTSTATUS ExitStatus 00473 ) 00474 00475 /*++ 00476 00477 Routine Description: 00478 00479 This function is called when a new thread terminates. At this 00480 point, the thread will no longer execute in user-mode. No other 00481 exit processing has occured. 00482 00483 If a message is sent, then while the thread is awaiting a reply, 00484 all other threads in the process are suspended. 00485 00486 Arguments: 00487 00488 ExitStatus - Supplies the ExitStatus of the exiting thread. 00489 00490 Return Value: 00491 00492 None. 00493 00494 --*/ 00495 00496 { 00497 PVOID Port; 00498 DBGKM_APIMSG m; 00499 PDBGKM_EXIT_THREAD args; 00500 PEPROCESS Process; 00501 00502 PAGED_CODE(); 00503 00504 Process = PsGetCurrentProcess(); 00505 Port = PsGetCurrentThread()->HideFromDebugger ? NULL : Process->DebugPort; 00506 00507 if ( !Port ) { 00508 return; 00509 } 00510 00511 if ( PsGetCurrentThread()->DeadThread ) { 00512 return; 00513 } 00514 00515 args = &m.u.ExitThread; 00516 args->ExitStatus = ExitStatus; 00517 00518 DBGKM_FORMAT_API_MSG(m,DbgKmExitThreadApi,sizeof(*args)); 00519 00520 DbgkpSuspendProcess(TRUE); 00521 00522 DbgkpSendApiMessage(&m,Port,FALSE); 00523 00524 DbgkpResumeProcess(TRUE); 00525 } 00526 00527 VOID 00528 DbgkExitProcess( 00529 NTSTATUS ExitStatus 00530 ) 00531 00532 /*++ 00533 00534 Routine Description: 00535 00536 This function is called when a process terminates. The address 00537 space of the process is still intact, but no threads exist in 00538 the process. 00539 00540 Arguments: 00541 00542 ExitStatus - Supplies the ExitStatus of the exiting process. 00543 00544 Return Value: 00545 00546 None. 00547 00548 --*/ 00549 00550 { 00551 PVOID Port; 00552 DBGKM_APIMSG m; 00553 PDBGKM_EXIT_PROCESS args; 00554 PEPROCESS Process; 00555 00556 PAGED_CODE(); 00557 00558 Process = PsGetCurrentProcess(); 00559 Port = PsGetCurrentThread()->HideFromDebugger ? NULL : Process->DebugPort; 00560 00561 if ( !Port ) { 00562 return; 00563 } 00564 00565 if ( PsGetCurrentThread()->DeadThread ) { 00566 return; 00567 } 00568 00569 // 00570 // this ensures that other timed lockers of the process will bail 00571 // since this call is done while holding the process lock, and lock duration 00572 // is controlled by debugger 00573 // 00574 KeQuerySystemTime(&PsGetCurrentProcess()->ExitTime); 00575 00576 args = &m.u.ExitProcess; 00577 args->ExitStatus = ExitStatus; 00578 00579 DBGKM_FORMAT_API_MSG(m,DbgKmExitProcessApi,sizeof(*args)); 00580 00581 DbgkpSendApiMessage(&m,Port,FALSE); 00582 00583 } 00584 00585 VOID 00586 DbgkMapViewOfSection( 00587 IN HANDLE SectionHandle, 00588 IN PVOID BaseAddress, 00589 IN ULONG SectionOffset, 00590 IN ULONG_PTR ViewSize 00591 ) 00592 00593 /*++ 00594 00595 Routine Description: 00596 00597 This function is called when the current process successfully 00598 maps a view of an image section. If the process has an associated 00599 debug port, then a load dll message is sent. 00600 00601 Arguments: 00602 00603 SectionHandle - Supplies a handle to the section mapped by the 00604 process. 00605 00606 BaseAddress - Supplies the base address of where the section is 00607 mapped in the current process address space. 00608 00609 SectionOffset - Supplies the offset in the section where the 00610 processes mapped view begins. 00611 00612 ViewSize - Supplies the size of the mapped view. 00613 00614 Return Value: 00615 00616 None. 00617 00618 --*/ 00619 00620 { 00621 00622 PVOID Port; 00623 DBGKM_APIMSG m; 00624 PDBGKM_LOAD_DLL LoadDllArgs; 00625 PEPROCESS Process; 00626 PIMAGE_NT_HEADERS NtHeaders; 00627 00628 PAGED_CODE(); 00629 00630 Process = PsGetCurrentProcess(); 00631 00632 Port = PsGetCurrentThread()->HideFromDebugger ? NULL : Process->DebugPort; 00633 00634 if ( !Port || KeGetPreviousMode() == KernelMode ) { 00635 return; 00636 } 00637 00638 LoadDllArgs = &m.u.LoadDll; 00639 LoadDllArgs->FileHandle = DbgkpSectionHandleToFileHandle(SectionHandle); 00640 LoadDllArgs->BaseOfDll = BaseAddress; 00641 LoadDllArgs->DebugInfoFileOffset = 0; 00642 LoadDllArgs->DebugInfoSize = 0; 00643 00644 try { 00645 NtHeaders = RtlImageNtHeader(BaseAddress); 00646 if ( NtHeaders ) { 00647 LoadDllArgs->DebugInfoFileOffset = NtHeaders->FileHeader.PointerToSymbolTable; 00648 LoadDllArgs->DebugInfoSize = NtHeaders->FileHeader.NumberOfSymbols; 00649 } 00650 } 00651 except(EXCEPTION_EXECUTE_HANDLER) { 00652 LoadDllArgs->DebugInfoFileOffset = 0; 00653 LoadDllArgs->DebugInfoSize = 0; 00654 } 00655 00656 DBGKM_FORMAT_API_MSG(m,DbgKmLoadDllApi,sizeof(*LoadDllArgs)); 00657 00658 DbgkpSendApiMessage(&m,Port,TRUE); 00659 ZwClose(LoadDllArgs->FileHandle); 00660 00661 } 00662 00663 VOID 00664 DbgkUnMapViewOfSection( 00665 IN PVOID BaseAddress 00666 ) 00667 00668 /*++ 00669 00670 Routine Description: 00671 00672 This function is called when the current process successfully 00673 un maps a view of an image section. If the process has an associated 00674 debug port, then an "unmap view of section" message is sent. 00675 00676 Arguments: 00677 00678 BaseAddress - Supplies the base address of the section being 00679 unmapped. 00680 00681 Return Value: 00682 00683 None. 00684 00685 --*/ 00686 00687 { 00688 00689 PVOID Port; 00690 DBGKM_APIMSG m; 00691 PDBGKM_UNLOAD_DLL UnloadDllArgs; 00692 PEPROCESS Process; 00693 00694 PAGED_CODE(); 00695 00696 Process = PsGetCurrentProcess(); 00697 00698 Port = PsGetCurrentThread()->HideFromDebugger ? NULL : Process->DebugPort; 00699 00700 if ( !Port || KeGetPreviousMode() == KernelMode ) { 00701 return; 00702 } 00703 00704 UnloadDllArgs = &m.u.UnloadDll; 00705 UnloadDllArgs->BaseAddress = BaseAddress; 00706 00707 DBGKM_FORMAT_API_MSG(m,DbgKmUnloadDllApi,sizeof(*UnloadDllArgs)); 00708 00709 DbgkpSendApiMessage(&m,Port,TRUE); 00710 00711 }

Generated on Sat May 15 19:39:39 2004 for test by doxygen 1.3.7