Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendbgui.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS NT Layer/System API 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: dll/ntdll/dbg/dbgui.c 00005 * PURPOSE: Native Wrappers for the NT Debug Implementation 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 */ 00008 00009 /* INCLUDES *****************************************************************/ 00010 00011 #include <ntdll.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* FUNCTIONS *****************************************************************/ 00016 00017 /* 00018 * @implemented 00019 */ 00020 NTSTATUS 00021 NTAPI 00022 DbgUiConnectToDbg(VOID) 00023 { 00024 OBJECT_ATTRIBUTES ObjectAttributes; 00025 00026 /* Don't connect twice */ 00027 if (NtCurrentTeb()->DbgSsReserved[1]) return STATUS_SUCCESS; 00028 00029 /* Setup the Attributes */ 00030 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, 0); 00031 00032 /* Create the object */ 00033 return ZwCreateDebugObject(&NtCurrentTeb()->DbgSsReserved[1], 00034 DEBUG_OBJECT_ALL_ACCESS, 00035 &ObjectAttributes, 00036 DBGK_KILL_PROCESS_ON_EXIT); 00037 } 00038 00039 /* 00040 * @implemented 00041 */ 00042 NTSTATUS 00043 NTAPI 00044 DbgUiContinue(IN PCLIENT_ID ClientId, 00045 IN NTSTATUS ContinueStatus) 00046 { 00047 /* Tell the kernel object to continue */ 00048 return ZwDebugContinue(NtCurrentTeb()->DbgSsReserved[1], 00049 ClientId, 00050 ContinueStatus); 00051 } 00052 00053 /* 00054 * @implemented 00055 */ 00056 NTSTATUS 00057 NTAPI 00058 DbgUiConvertStateChangeStructure(IN PDBGUI_WAIT_STATE_CHANGE WaitStateChange, 00059 OUT PVOID Win32DebugEvent) 00060 { 00061 NTSTATUS Status; 00062 OBJECT_ATTRIBUTES ObjectAttributes; 00063 THREAD_BASIC_INFORMATION ThreadBasicInfo; 00064 LPDEBUG_EVENT DebugEvent = Win32DebugEvent; 00065 HANDLE ThreadHandle; 00066 00067 /* Write common data */ 00068 DebugEvent->dwProcessId = (DWORD)WaitStateChange-> 00069 AppClientId.UniqueProcess; 00070 DebugEvent->dwThreadId = (DWORD)WaitStateChange->AppClientId.UniqueThread; 00071 00072 /* Check what kind of even this is */ 00073 switch (WaitStateChange->NewState) 00074 { 00075 /* New thread */ 00076 case DbgCreateThreadStateChange: 00077 00078 /* Setup Win32 code */ 00079 DebugEvent->dwDebugEventCode = CREATE_THREAD_DEBUG_EVENT; 00080 00081 /* Copy data over */ 00082 DebugEvent->u.CreateThread.hThread = 00083 WaitStateChange->StateInfo.CreateThread.HandleToThread; 00084 DebugEvent->u.CreateThread.lpStartAddress = 00085 WaitStateChange->StateInfo.CreateThread.NewThread.StartAddress; 00086 00087 /* Query the TEB */ 00088 Status = NtQueryInformationThread(WaitStateChange->StateInfo. 00089 CreateThread.HandleToThread, 00090 ThreadBasicInformation, 00091 &ThreadBasicInfo, 00092 sizeof(ThreadBasicInfo), 00093 NULL); 00094 if (!NT_SUCCESS(Status)) 00095 { 00096 /* Failed to get PEB address */ 00097 DebugEvent->u.CreateThread.lpThreadLocalBase = NULL; 00098 } 00099 else 00100 { 00101 /* Write PEB Address */ 00102 DebugEvent->u.CreateThread.lpThreadLocalBase = 00103 ThreadBasicInfo.TebBaseAddress; 00104 } 00105 break; 00106 00107 /* New process */ 00108 case DbgCreateProcessStateChange: 00109 00110 /* Write Win32 debug code */ 00111 DebugEvent->dwDebugEventCode = CREATE_PROCESS_DEBUG_EVENT; 00112 00113 /* Copy data over */ 00114 DebugEvent->u.CreateProcessInfo.hProcess = 00115 WaitStateChange->StateInfo.CreateProcessInfo.HandleToProcess; 00116 DebugEvent->u.CreateProcessInfo.hThread = 00117 WaitStateChange->StateInfo.CreateProcessInfo.HandleToThread; 00118 DebugEvent->u.CreateProcessInfo.hFile = 00119 WaitStateChange->StateInfo.CreateProcessInfo.NewProcess. 00120 FileHandle; 00121 DebugEvent->u.CreateProcessInfo.lpBaseOfImage = 00122 WaitStateChange->StateInfo.CreateProcessInfo.NewProcess. 00123 BaseOfImage; 00124 DebugEvent->u.CreateProcessInfo.dwDebugInfoFileOffset = 00125 WaitStateChange->StateInfo.CreateProcessInfo.NewProcess. 00126 DebugInfoFileOffset; 00127 DebugEvent->u.CreateProcessInfo.nDebugInfoSize = 00128 WaitStateChange->StateInfo.CreateProcessInfo.NewProcess. 00129 DebugInfoSize; 00130 DebugEvent->u.CreateProcessInfo.lpStartAddress = 00131 WaitStateChange->StateInfo.CreateProcessInfo.NewProcess. 00132 InitialThread.StartAddress; 00133 00134 /* Query TEB address */ 00135 Status = NtQueryInformationThread(WaitStateChange->StateInfo. 00136 CreateProcessInfo.HandleToThread, 00137 ThreadBasicInformation, 00138 &ThreadBasicInfo, 00139 sizeof(ThreadBasicInfo), 00140 NULL); 00141 if (!NT_SUCCESS(Status)) 00142 { 00143 /* Failed to get PEB address */ 00144 DebugEvent->u.CreateProcessInfo.lpThreadLocalBase = NULL; 00145 } 00146 else 00147 { 00148 /* Write PEB Address */ 00149 DebugEvent->u.CreateProcessInfo.lpThreadLocalBase = 00150 ThreadBasicInfo.TebBaseAddress; 00151 } 00152 00153 /* Clear image name */ 00154 DebugEvent->u.CreateProcessInfo.lpImageName = NULL; 00155 DebugEvent->u.CreateProcessInfo.fUnicode = TRUE; 00156 break; 00157 00158 /* Thread exited */ 00159 case DbgExitThreadStateChange: 00160 00161 /* Write the Win32 debug code and the exit status */ 00162 DebugEvent->dwDebugEventCode = EXIT_THREAD_DEBUG_EVENT; 00163 DebugEvent->u.ExitThread.dwExitCode = 00164 WaitStateChange->StateInfo.ExitThread.ExitStatus; 00165 break; 00166 00167 /* Process exited */ 00168 case DbgExitProcessStateChange: 00169 00170 /* Write the Win32 debug code and the exit status */ 00171 DebugEvent->dwDebugEventCode = EXIT_PROCESS_DEBUG_EVENT; 00172 DebugEvent->u.ExitProcess.dwExitCode = 00173 WaitStateChange->StateInfo.ExitProcess.ExitStatus; 00174 break; 00175 00176 /* Any sort of exception */ 00177 case DbgExceptionStateChange: 00178 case DbgBreakpointStateChange: 00179 case DbgSingleStepStateChange: 00180 00181 /* Check if this was a debug print */ 00182 if (WaitStateChange->StateInfo.Exception.ExceptionRecord. 00183 ExceptionCode == DBG_PRINTEXCEPTION_C) 00184 { 00185 /* Set the Win32 code */ 00186 DebugEvent->dwDebugEventCode = OUTPUT_DEBUG_STRING_EVENT; 00187 00188 /* Copy debug string information */ 00189 DebugEvent->u.DebugString.lpDebugStringData = 00190 (PVOID)WaitStateChange-> 00191 StateInfo.Exception.ExceptionRecord. 00192 ExceptionInformation[1]; 00193 DebugEvent->u.DebugString.nDebugStringLength = 00194 WaitStateChange->StateInfo.Exception.ExceptionRecord. 00195 ExceptionInformation[0]; 00196 DebugEvent->u.DebugString.fUnicode = FALSE; 00197 } 00198 else if (WaitStateChange->StateInfo.Exception.ExceptionRecord. 00199 ExceptionCode == DBG_RIPEXCEPTION) 00200 { 00201 /* Set the Win32 code */ 00202 DebugEvent->dwDebugEventCode = RIP_EVENT; 00203 00204 /* Set exception information */ 00205 DebugEvent->u.RipInfo.dwType = 00206 WaitStateChange->StateInfo.Exception.ExceptionRecord. 00207 ExceptionInformation[1]; 00208 DebugEvent->u.RipInfo.dwError = 00209 WaitStateChange->StateInfo.Exception.ExceptionRecord. 00210 ExceptionInformation[0]; 00211 } 00212 else 00213 { 00214 /* Otherwise, this is a debug event, copy info over */ 00215 DebugEvent->dwDebugEventCode = EXCEPTION_DEBUG_EVENT; 00216 DebugEvent->u.Exception.ExceptionRecord = 00217 WaitStateChange->StateInfo.Exception.ExceptionRecord; 00218 DebugEvent->u.Exception.dwFirstChance = 00219 WaitStateChange->StateInfo.Exception.FirstChance; 00220 } 00221 break; 00222 00223 /* DLL Load */ 00224 case DbgLoadDllStateChange: 00225 00226 /* Set the Win32 debug code */ 00227 DebugEvent->dwDebugEventCode = LOAD_DLL_DEBUG_EVENT; 00228 00229 /* Copy the rest of the data */ 00230 DebugEvent->u.LoadDll.lpBaseOfDll = 00231 WaitStateChange->StateInfo.LoadDll.BaseOfDll; 00232 DebugEvent->u.LoadDll.hFile = 00233 WaitStateChange->StateInfo.LoadDll.FileHandle; 00234 DebugEvent->u.LoadDll.dwDebugInfoFileOffset = 00235 WaitStateChange->StateInfo.LoadDll.DebugInfoFileOffset; 00236 DebugEvent->u.LoadDll.nDebugInfoSize = 00237 WaitStateChange->StateInfo.LoadDll.DebugInfoSize; 00238 00239 /* Open the thread */ 00240 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 00241 Status = NtOpenThread(&ThreadHandle, 00242 THREAD_QUERY_INFORMATION, 00243 &ObjectAttributes, 00244 &WaitStateChange->AppClientId); 00245 if (NT_SUCCESS(Status)) 00246 { 00247 /* Query thread information */ 00248 Status = NtQueryInformationThread(ThreadHandle, 00249 ThreadBasicInformation, 00250 &ThreadBasicInfo, 00251 sizeof(ThreadBasicInfo), 00252 NULL); 00253 NtClose(ThreadHandle); 00254 } 00255 00256 /* Check if we got thread information */ 00257 if (NT_SUCCESS(Status)) 00258 { 00259 /* Save the image name from the TIB */ 00260 DebugEvent->u.LoadDll.lpImageName = 00261 ((PTEB)ThreadBasicInfo.TebBaseAddress)-> 00262 NtTib.ArbitraryUserPointer; 00263 } 00264 else 00265 { 00266 /* Otherwise, no name */ 00267 DebugEvent->u.LoadDll.lpImageName = NULL; 00268 } 00269 00270 /* It's Unicode */ 00271 DebugEvent->u.LoadDll.fUnicode = TRUE; 00272 break; 00273 00274 /* DLL Unload */ 00275 case DbgUnloadDllStateChange: 00276 00277 /* Set Win32 code and DLL Base */ 00278 DebugEvent->dwDebugEventCode = UNLOAD_DLL_DEBUG_EVENT; 00279 DebugEvent->u.UnloadDll.lpBaseOfDll = 00280 WaitStateChange->StateInfo.UnloadDll.BaseAddress; 00281 break; 00282 00283 /* Anything else, fail */ 00284 default: return STATUS_UNSUCCESSFUL; 00285 } 00286 00287 /* Return success */ 00288 return STATUS_SUCCESS; 00289 } 00290 00291 /* 00292 * @implemented 00293 */ 00294 NTSTATUS 00295 NTAPI 00296 DbgUiWaitStateChange(OUT PDBGUI_WAIT_STATE_CHANGE DbgUiWaitStateCange, 00297 IN PLARGE_INTEGER TimeOut OPTIONAL) 00298 { 00299 /* Tell the kernel to wait */ 00300 return NtWaitForDebugEvent(NtCurrentTeb()->DbgSsReserved[1], 00301 TRUE, 00302 TimeOut, 00303 DbgUiWaitStateCange); 00304 } 00305 00306 /* 00307 * @implemented 00308 */ 00309 VOID 00310 NTAPI 00311 DbgUiRemoteBreakin(VOID) 00312 { 00313 /* Make sure a debugger is enabled; if so, breakpoint */ 00314 if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint(); 00315 00316 /* Exit the thread */ 00317 RtlExitUserThread(STATUS_SUCCESS); 00318 } 00319 00320 /* 00321 * @implemented 00322 */ 00323 NTSTATUS 00324 NTAPI 00325 DbgUiIssueRemoteBreakin(IN HANDLE Process) 00326 { 00327 HANDLE hThread; 00328 CLIENT_ID ClientId; 00329 NTSTATUS Status; 00330 00331 /* Create the thread that will do the breakin */ 00332 Status = RtlCreateUserThread(Process, 00333 NULL, 00334 FALSE, 00335 0, 00336 0, 00337 PAGE_SIZE, 00338 (PVOID)DbgUiRemoteBreakin, 00339 NULL, 00340 &hThread, 00341 &ClientId); 00342 00343 /* Close the handle on success */ 00344 if(NT_SUCCESS(Status)) NtClose(hThread); 00345 00346 /* Return status */ 00347 return Status; 00348 } 00349 00350 /* 00351 * @implemented 00352 */ 00353 HANDLE 00354 NTAPI 00355 DbgUiGetThreadDebugObject(VOID) 00356 { 00357 /* Just return the handle from the TEB */ 00358 return NtCurrentTeb()->DbgSsReserved[1]; 00359 } 00360 00361 /* 00362 * @implemented 00363 */ 00364 VOID 00365 NTAPI 00366 DbgUiSetThreadDebugObject(HANDLE DebugObject) 00367 { 00368 /* Just set the handle in the TEB */ 00369 NtCurrentTeb()->DbgSsReserved[1] = DebugObject; 00370 } 00371 00372 /* 00373 * @implemented 00374 */ 00375 NTSTATUS 00376 NTAPI 00377 DbgUiDebugActiveProcess(IN HANDLE Process) 00378 { 00379 NTSTATUS Status; 00380 00381 /* Tell the kernel to start debugging */ 00382 Status = NtDebugActiveProcess(Process, NtCurrentTeb()->DbgSsReserved[1]); 00383 if (NT_SUCCESS(Status)) 00384 { 00385 /* Now break-in the process */ 00386 Status = DbgUiIssueRemoteBreakin(Process); 00387 if (!NT_SUCCESS(Status)) 00388 { 00389 /* We couldn't break-in, cancel debugging */ 00390 DbgUiStopDebugging(Process); 00391 } 00392 } 00393 00394 /* Return status */ 00395 return Status; 00396 } 00397 00398 /* 00399 * @implemented 00400 */ 00401 NTSTATUS 00402 NTAPI 00403 DbgUiStopDebugging(IN HANDLE Process) 00404 { 00405 /* Call the kernel to remove the debug object */ 00406 return NtRemoveProcessDebug(Process, NtCurrentTeb()->DbgSsReserved[1]); 00407 } 00408 00409 /* EOF */ Generated on Sun May 27 2012 04:22:34 for ReactOS by
1.7.6.1
|