ReactOS 0.4.15-dev-8241-g63935f8
debugger.c File Reference
#include <k32.h>
#include <ndk/dbgkfuncs.h>
#include <debug.h>
Include dependency graph for debugger.c:

Go to the source code of this file.

Classes

struct  _DBGSS_THREAD_DATA
 

Macros

#define NDEBUG
 
#define DbgSsSetThreadData(d)    NtCurrentTeb()->DbgSsReserved[0] = d
 
#define DbgSsGetThreadData()    ((PDBGSS_THREAD_DATA)NtCurrentTeb()->DbgSsReserved[0])
 

Typedefs

typedef struct _DBGSS_THREAD_DATA DBGSS_THREAD_DATA
 
typedef struct _DBGSS_THREAD_DATAPDBGSS_THREAD_DATA
 

Functions

static HANDLE K32CreateDBMonMutex (VOID)
 
VOID WINAPI SaveThreadHandle (IN DWORD dwProcessId, IN DWORD dwThreadId, IN HANDLE hThread)
 
VOID WINAPI SaveProcessHandle (IN DWORD dwProcessId, IN HANDLE hProcess)
 
VOID WINAPI MarkThreadHandle (IN DWORD dwThreadId)
 
VOID WINAPI MarkProcessHandle (IN DWORD dwProcessId)
 
VOID WINAPI RemoveHandles (IN DWORD dwProcessId, IN DWORD dwThreadId)
 
VOID WINAPI CloseAllProcessHandles (IN DWORD dwProcessId)
 
HANDLE WINAPI ProcessIdToHandle (IN DWORD dwProcessId)
 
BOOL WINAPI CheckRemoteDebuggerPresent (IN HANDLE hProcess, OUT PBOOL pbDebuggerPresent)
 
BOOL WINAPI ContinueDebugEvent (IN DWORD dwProcessId, IN DWORD dwThreadId, IN DWORD dwContinueStatus)
 
BOOL WINAPI DebugActiveProcess (IN DWORD dwProcessId)
 
BOOL WINAPI DebugActiveProcessStop (IN DWORD dwProcessId)
 
BOOL WINAPI DebugBreakProcess (IN HANDLE Process)
 
BOOL WINAPI DebugSetProcessKillOnExit (IN BOOL KillOnExit)
 
BOOL WINAPI IsDebuggerPresent (VOID)
 
BOOL WINAPI WaitForDebugEvent (IN LPDEBUG_EVENT lpDebugEvent, IN DWORD dwMilliseconds)
 
VOID WINAPI OutputDebugStringA (IN LPCSTR _OutputString)
 
VOID WINAPI OutputDebugStringW (IN LPCWSTR OutputString)
 

Macro Definition Documentation

◆ DbgSsGetThreadData

#define DbgSsGetThreadData ( )     ((PDBGSS_THREAD_DATA)NtCurrentTeb()->DbgSsReserved[0])

Definition at line 31 of file debugger.c.

◆ DbgSsSetThreadData

#define DbgSsSetThreadData (   d)     NtCurrentTeb()->DbgSsReserved[0] = d

Definition at line 28 of file debugger.c.

◆ NDEBUG

#define NDEBUG

Definition at line 15 of file debugger.c.

Typedef Documentation

◆ DBGSS_THREAD_DATA

◆ PDBGSS_THREAD_DATA

Function Documentation

◆ CheckRemoteDebuggerPresent()

BOOL WINAPI CheckRemoteDebuggerPresent ( IN HANDLE  hProcess,
OUT PBOOL  pbDebuggerPresent 
)

Definition at line 376 of file debugger.c.

378{
379 HANDLE DebugPort;
381
382 /* Make sure we have an output and process*/
383 if (!(pbDebuggerPresent) || !(hProcess))
384 {
385 /* Fail */
387 return FALSE;
388 }
389
390 /* Check if the process has a debug object/port */
393 &DebugPort,
394 sizeof(DebugPort),
395 NULL);
396 if (NT_SUCCESS(Status))
397 {
398 /* Return the current state */
399 *pbDebuggerPresent = DebugPort != NULL;
400 return TRUE;
401 }
402
403 /* Otherwise, fail */
405 return FALSE;
406}
LONG NTSTATUS
Definition: precomp.h:26
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
Status
Definition: gdiplustypes.h:25
@ ProcessDebugPort
Definition: winternl.h:395
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:71
NTSTATUS NTAPI NtQueryInformationProcess(_In_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASS ProcessInformationClass, _Out_ PVOID ProcessInformation, _In_ ULONG ProcessInformationLength, _Out_opt_ PULONG ReturnLength)
Definition: query.c:59
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166

◆ CloseAllProcessHandles()

VOID WINAPI CloseAllProcessHandles ( IN DWORD  dwProcessId)

Definition at line 304 of file debugger.c.

305{
307 PDBGSS_THREAD_DATA ThisData;
308
309 /* Loop all thread data events */
310 ThreadData = (PDBGSS_THREAD_DATA*)NtCurrentTeb()->DbgSsReserved;
311 ThisData = *ThreadData;
312 while(ThisData)
313 {
314 /* Check if this one matches */
315 if (ThisData->ProcessId == dwProcessId)
316 {
317 /* Close open handles */
318 if (ThisData->ThreadHandle) CloseHandle(ThisData->ThreadHandle);
319 if (ThisData->ProcessHandle) CloseHandle(ThisData->ProcessHandle);
320
321 /* Unlink the thread data */
322 *ThreadData = ThisData->Next;
323
324 /* Free it*/
325 RtlFreeHeap(RtlGetProcessHeap(), 0, ThisData);
326 }
327 else
328 {
329 /* Move to the next one */
330 ThreadData = &ThisData->Next;
331 }
332 ThisData = *ThreadData;
333 }
334}
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
#define CloseHandle
Definition: compat.h:739
#define NtCurrentTeb
HANDLE ProcessHandle
Definition: debugger.c:22
struct _DBGSS_THREAD_DATA * Next
Definition: debugger.c:20
HANDLE ThreadHandle
Definition: debugger.c:21

Referenced by DebugActiveProcessStop().

◆ ContinueDebugEvent()

BOOL WINAPI ContinueDebugEvent ( IN DWORD  dwProcessId,
IN DWORD  dwThreadId,
IN DWORD  dwContinueStatus 
)

Definition at line 413 of file debugger.c.

416{
419
420 /* Set the Client ID */
421 ClientId.UniqueProcess = UlongToHandle(dwProcessId);
423
424 /* Continue debugging */
425 Status = DbgUiContinue(&ClientId, dwContinueStatus);
426 if (!NT_SUCCESS(Status))
427 {
428 /* Fail */
430 return FALSE;
431 }
432
433 /* Remove the process/thread handles */
434 RemoveHandles(dwProcessId, dwThreadId);
435
436 /* Success */
437 return TRUE;
438}
#define UlongToHandle(ul)
Definition: basetsd.h:97
NTSTATUS NTAPI DbgUiContinue(IN PCLIENT_ID ClientId, IN NTSTATUS ContinueStatus)
Definition: dbgui.c:47
VOID WINAPI RemoveHandles(IN DWORD dwProcessId, IN DWORD dwThreadId)
Definition: debugger.c:268
DWORD dwThreadId
Definition: fdebug.c:31
HANDLE UniqueThread
Definition: compat.h:826
HANDLE UniqueProcess
Definition: compat.h:825
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1151

Referenced by Main(), test_debug_children(), test_debug_loop(), test_DebuggingFlag(), test_NtSuspendProcess(), test_query_process_debug_flags(), test_query_process_debug_object_handle(), test_query_process_debug_port(), and wWinMain().

◆ DebugActiveProcess()

BOOL WINAPI DebugActiveProcess ( IN DWORD  dwProcessId)

Definition at line 445 of file debugger.c.

446{
447 NTSTATUS Status, Status1;
449
450 /* Connect to the debugger */
452 if (!NT_SUCCESS(Status))
453 {
455 return FALSE;
456 }
457
458 /* Get the process handle */
459 Handle = ProcessIdToHandle(dwProcessId);
460 if (!Handle) return FALSE;
461
462 /* Now debug the process */
464
465 /* Close the handle since we're done */
466 Status1 = NtClose(Handle);
467 ASSERT(NT_SUCCESS(Status1));
468
469 /* Check if debugging worked */
470 if (!NT_SUCCESS(Status))
471 {
472 /* Fail */
474 return FALSE;
475 }
476
477 /* Success */
478 return TRUE;
479}
NTSTATUS NTAPI DbgUiDebugActiveProcess(IN HANDLE Process)
Definition: dbgui.c:355
NTSTATUS NTAPI DbgUiConnectToDbg(VOID)
Definition: dbgui.c:25
HANDLE WINAPI ProcessIdToHandle(IN DWORD dwProcessId)
Definition: debugger.c:338
ULONG Handle
Definition: gdb_input.c:15
#define ASSERT(a)
Definition: mode.c:44
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402

Referenced by dll_entry_point(), doChild(), doDebugger(), Main(), test_debug_children(), test_debug_loop(), test_ExitProcess(), test_NtSuspendProcess(), test_query_process_debug_flags(), and wWinMain().

◆ DebugActiveProcessStop()

BOOL WINAPI DebugActiveProcessStop ( IN DWORD  dwProcessId)

Definition at line 486 of file debugger.c.

487{
488 NTSTATUS Status, Status1;
490
491 /* Get the process handle */
492 Handle = ProcessIdToHandle(dwProcessId);
493 if (!Handle) return FALSE;
494
495 /* Close all the process handles */
496 CloseAllProcessHandles(dwProcessId);
497
498 /* Now stop debugging the process */
500 Status1 = NtClose(Handle);
501 ASSERT(NT_SUCCESS(Status1));
502
503 /* Check for failure */
504 if (!NT_SUCCESS(Status))
505 {
506 /* Fail */
508 return FALSE;
509 }
510
511 /* Success */
512 return TRUE;
513}
NTSTATUS NTAPI DbgUiStopDebugging(IN HANDLE Process)
Definition: dbgui.c:381
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
VOID WINAPI CloseAllProcessHandles(IN DWORD dwProcessId)
Definition: debugger.c:304

Referenced by test_query_process_debug_flags().

◆ DebugBreakProcess()

BOOL WINAPI DebugBreakProcess ( IN HANDLE  Process)

Definition at line 520 of file debugger.c.

521{
523
524 /* Send the breakin request */
526 if (!NT_SUCCESS(Status))
527 {
528 /* Failure */
530 return FALSE;
531 }
532
533 /* Success */
534 return TRUE;
535}
NTSTATUS NTAPI DbgUiIssueRemoteBreakin(IN HANDLE Process)
Definition: dbgui.c:303
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223

◆ DebugSetProcessKillOnExit()

BOOL WINAPI DebugSetProcessKillOnExit ( IN BOOL  KillOnExit)

Definition at line 542 of file debugger.c.

543{
546 ULONG State;
547
548 /* Get the debug object */
550 if (!Handle)
551 {
552 /* Fail */
554 return FALSE;
555 }
556
557 /* Now set the kill-on-exit state */
558 State = KillOnExit != 0;
561 &State,
562 sizeof(State),
563 NULL);
564 if (!NT_SUCCESS(Status))
565 {
566 /* Fail */
568 return FALSE;
569 }
570
571 /* Success */
572 return TRUE;
573}
NTSTATUS NTAPI NtSetInformationDebugObject(IN HANDLE DebugHandle, IN DEBUGOBJECTINFOCLASS DebugObjectInformationClass, IN PVOID DebugInformation, IN ULONG DebugInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: dbgkobj.c:1921
@ DebugObjectKillProcessOnExitInformation
Definition: dbgktypes.h:58
HANDLE NTAPI DbgUiGetThreadDebugObject(VOID)
Definition: dbgui.c:333
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:245
uint32_t ULONG
Definition: typedefs.h:59

Referenced by wWinMain().

◆ IsDebuggerPresent()

BOOL WINAPI IsDebuggerPresent ( VOID  )

Definition at line 580 of file debugger.c.

581{
582 return (BOOL)NtCurrentPeb()->BeingDebugged;
583}
#define NtCurrentPeb()
Definition: FLS.c:22
unsigned int BOOL
Definition: ntddk_ex.h:94

Referenced by _CrtDbgReportWindow(), ConsoleControlDispatcher(), init_funcs(), InitThreads(), and wmain().

◆ K32CreateDBMonMutex()

static HANDLE K32CreateDBMonMutex ( VOID  )
static

Definition at line 37 of file debugger.c.

38{
43
44 /* SIDs to be used in the DACL */
45 PSID psidSystem = NULL;
46 PSID psidAdministrators = NULL;
47 PSID psidEveryone = NULL;
48
49 /* Buffer for the DACL */
50 PVOID pDaclBuf = NULL;
51
52 /* Minimum size of the DACL: an ACL descriptor and three ACCESS_ALLOWED_ACE
53 * headers. We will add the size of SIDs when they are known. */
54 SIZE_T nDaclBufSize =
55 sizeof(ACL) + 3 * FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart);
56
57 /* Security descriptor and attributes of the mutex */
58 SECURITY_DESCRIPTOR sdMutexSecurity;
59 SECURITY_ATTRIBUTES saMutexAttribs = {sizeof(saMutexAttribs),
60 &sdMutexSecurity,
61 TRUE};
62
63 /* Try to open the mutex */
65 TRUE,
66 L"DBWinMutex");
67 if (hMutex != NULL)
68 {
69 /* Success */
70 return hMutex;
71 }
72 /* Error other than the mutex not being found */
74 {
75 /* Failure */
76 return NULL;
77 }
78
79 /* If the mutex does not exist, set up its security, then create it */
80
81 /* Allocate the NT AUTHORITY\SYSTEM SID */
83 1,
85 0, 0, 0, 0, 0, 0, 0,
86 &psidSystem);
87 if (!NT_SUCCESS(Status))
88 goto Cleanup;
89
90 /* Allocate the BUILTIN\Administrators SID */
92 2,
95 0, 0, 0, 0, 0, 0,
96 &psidAdministrators);
97 if (!NT_SUCCESS(Status))
98 goto Cleanup;
99
100 /* Allocate the Everyone SID */
101 Status = RtlAllocateAndInitializeSid(&siaWorldAuth,
102 1,
104 0, 0, 0, 0, 0, 0, 0,
105 &psidEveryone);
106 if (!NT_SUCCESS(Status))
107 goto Cleanup;
108
109 /* Allocate space for the SIDs too */
110 nDaclBufSize += RtlLengthSid(psidSystem);
111 nDaclBufSize += RtlLengthSid(psidAdministrators);
112 nDaclBufSize += RtlLengthSid(psidEveryone);
113
114 /* Allocate the buffer for the DACL */
115 pDaclBuf = GlobalAlloc(GMEM_FIXED, nDaclBufSize);
116 if (pDaclBuf == NULL)
117 goto Cleanup;
118
119 /* Create the DACL */
120 Status = RtlCreateAcl(pDaclBuf, nDaclBufSize, ACL_REVISION);
121 if (!NT_SUCCESS(Status))
122 goto Cleanup;
123
124 /* Grant the minimum required access to Everyone */
130 psidEveryone);
131 if (!NT_SUCCESS(Status))
132 goto Cleanup;
133
134 /* Grant full access to BUILTIN\Administrators */
138 psidAdministrators);
139 if (!NT_SUCCESS(Status))
140 goto Cleanup;
141
142 /* Grant full access to NT AUTHORITY\SYSTEM */
146 psidSystem);
147 if (!NT_SUCCESS(Status))
148 goto Cleanup;
149
150 /* Create the security descriptor */
151 Status = RtlCreateSecurityDescriptor(&sdMutexSecurity,
153 if (!NT_SUCCESS(Status))
154 goto Cleanup;
155
156 /* Set the descriptor's DACL to the created ACL */
157 Status = RtlSetDaclSecurityDescriptor(&sdMutexSecurity,
158 TRUE,
159 pDaclBuf,
160 FALSE);
161 if (!NT_SUCCESS(Status))
162 goto Cleanup;
163
164 /* Create the mutex */
165 hMutex = CreateMutexW(&saMutexAttribs, FALSE, L"DBWinMutex");
166
167Cleanup:
168 /* Free the buffers */
169 if (pDaclBuf) GlobalFree(pDaclBuf);
170 if (psidEveryone) RtlFreeSid(psidEveryone);
171 if (psidAdministrators) RtlFreeSid(psidAdministrators);
172 if (psidSystem) RtlFreeSid(psidSystem);
173
174 return hMutex;
175}
static const WCHAR Cleanup[]
Definition: register.c:80
HGLOBAL NTAPI GlobalFree(HGLOBAL hMem)
Definition: heapmem.c:611
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
NTSYSAPI NTSTATUS WINAPI RtlAddAccessAllowedAce(PACL, DWORD, DWORD, PSID)
NTSYSAPI NTSTATUS WINAPI RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR, BOOLEAN, PACL, BOOLEAN)
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
HANDLE hMutex
Definition: mutex.c:11
struct _ACL ACL
#define MUTANT_ALL_ACCESS
Definition: extypes.h:110
#define MUTANT_QUERY_STATE
Definition: extypes.h:109
NTSYSAPI NTSTATUS NTAPI RtlCreateAcl(PACL Acl, ULONG AclSize, ULONG AclRevision)
NTSYSAPI ULONG NTAPI RtlLengthSid(IN PSID Sid)
Definition: sid.c:150
NTSYSAPI NTSTATUS NTAPI RtlCreateSecurityDescriptor(_Out_ PSECURITY_DESCRIPTOR SecurityDescriptor, _In_ ULONG Revision)
NTSYSAPI PVOID NTAPI RtlFreeSid(_In_ _Post_invalid_ PSID Sid)
#define SYNCHRONIZE
Definition: nt_native.h:61
#define READ_CONTROL
Definition: nt_native.h:58
NTSYSAPI NTSTATUS NTAPI RtlAllocateAndInitializeSid(IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority, IN UCHAR SubAuthorityCount, IN ULONG SubAuthority0, IN ULONG SubAuthority1, IN ULONG SubAuthority2, IN ULONG SubAuthority3, IN ULONG SubAuthority4, IN ULONG SubAuthority5, IN ULONG SubAuthority6, IN ULONG SubAuthority7, OUT PSID *Sid)
Definition: sid.c:290
#define L(x)
Definition: ntvdm.h:50
HANDLE WINAPI DECLSPEC_HOTPATCH CreateMutexW(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL, IN BOOL bInitialOwner, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:576
HANDLE WINAPI DECLSPEC_HOTPATCH OpenMutexW(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCWSTR lpName)
Definition: synch.c:605
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
ULONG_PTR SIZE_T
Definition: typedefs.h:80
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define GMEM_FIXED
Definition: winbase.h:293
#define SECURITY_BUILTIN_DOMAIN_RID
Definition: setypes.h:581
#define SECURITY_WORLD_SID_AUTHORITY
Definition: setypes.h:527
#define SECURITY_WORLD_RID
Definition: setypes.h:541
#define SECURITY_LOCAL_SYSTEM_RID
Definition: setypes.h:574
#define SECURITY_NT_AUTHORITY
Definition: setypes.h:554
#define SECURITY_DESCRIPTOR_REVISION
Definition: setypes.h:58
#define ACL_REVISION
Definition: setypes.h:39
#define DOMAIN_ALIAS_RID_ADMINS
Definition: setypes.h:652

Referenced by OutputDebugStringA().

◆ MarkProcessHandle()

VOID WINAPI MarkProcessHandle ( IN DWORD  dwProcessId)

Definition at line 249 of file debugger.c.

250{
252
253 /* Loop all thread data events */
255 {
256 /* Check if this one matches */
257 if ((ThreadData->ProcessId == dwProcessId) && !(ThreadData->ThreadId))
258 {
259 /* Mark the structure and break out */
260 ThreadData->HandleMarked = TRUE;
261 break;
262 }
263 }
264}
#define DbgSsGetThreadData()
Definition: debugger.c:31

Referenced by WaitForDebugEvent().

◆ MarkThreadHandle()

VOID WINAPI MarkThreadHandle ( IN DWORD  dwThreadId)

Definition at line 230 of file debugger.c.

231{
233
234 /* Loop all thread data events */
236 {
237 /* Check if this one matches */
238 if (ThreadData->ThreadId == dwThreadId)
239 {
240 /* Mark the structure and break out */
241 ThreadData->HandleMarked = TRUE;
242 break;
243 }
244 }
245}

Referenced by WaitForDebugEvent().

◆ OutputDebugStringA()

VOID WINAPI OutputDebugStringA ( IN LPCSTR  _OutputString)

Definition at line 693 of file debugger.c.

694{
696 {
697 ULONG_PTR a_nArgs[2];
698
699 a_nArgs[0] = (ULONG_PTR)(strlen(_OutputString) + 1);
700 a_nArgs[1] = (ULONG_PTR)_OutputString;
701
702 /* send the string to the user-mode debugger */
703 RaiseException(DBG_PRINTEXCEPTION_C, 0, 2, a_nArgs);
704 }
706 {
707 /* no user-mode debugger: try the systemwide debug message monitor, or the
708 kernel debugger as a last resort */
709
710 /* mutex used to synchronize invocations of OutputDebugString */
711 static HANDLE s_hDBMonMutex = NULL;
712 /* true if we already attempted to open/create the mutex */
713 static BOOL s_bDBMonMutexTriedOpen = FALSE;
714
715 /* local copy of the mutex handle */
716 volatile HANDLE hDBMonMutex = s_hDBMonMutex;
717 /* handle to the Section of the shared buffer */
718 volatile HANDLE hDBMonBuffer = NULL;
719
720 /* pointer to the mapped view of the shared buffer. It consist of the current
721 process id followed by the message string */
722 struct { DWORD ProcessId; CHAR Buffer[1]; } * pDBMonBuffer = NULL;
723
724 /* event: signaled by the debug message monitor when OutputDebugString can write
725 to the shared buffer */
726 volatile HANDLE hDBMonBufferReady = NULL;
727
728 /* event: to be signaled by OutputDebugString when it's done writing to the
729 shared buffer */
730 volatile HANDLE hDBMonDataReady = NULL;
731
732 /* mutex not opened, and no previous attempts to open/create it */
733 if (hDBMonMutex == NULL && !s_bDBMonMutexTriedOpen)
734 {
735 /* open/create the mutex */
736 hDBMonMutex = K32CreateDBMonMutex();
737 /* store the handle */
738 s_hDBMonMutex = hDBMonMutex;
739 }
740
742 {
743 volatile PCHAR a_cBuffer = NULL;
744
745 /* opening the mutex failed */
746 if (hDBMonMutex == NULL)
747 {
748 /* remember next time */
749 s_bDBMonMutexTriedOpen = TRUE;
750 }
751 /* opening the mutex succeeded */
752 else
753 {
754 do
755 {
756 /* synchronize with other invocations of OutputDebugString */
757 WaitForSingleObject(hDBMonMutex, INFINITE);
758
759 /* buffer of the system-wide debug message monitor */
760 hDBMonBuffer = OpenFileMappingW(SECTION_MAP_WRITE, FALSE, L"DBWIN_BUFFER");
761
762 /* couldn't open the buffer: send the string to the kernel debugger */
763 if (hDBMonBuffer == NULL) break;
764
765 /* map the buffer */
766 pDBMonBuffer = MapViewOfFile(hDBMonBuffer,
768 0,
769 0,
770 0);
771
772 /* couldn't map the buffer: send the string to the kernel debugger */
773 if (pDBMonBuffer == NULL) break;
774
775 /* open the event signaling that the buffer can be accessed */
776 hDBMonBufferReady = OpenEventW(SYNCHRONIZE, FALSE, L"DBWIN_BUFFER_READY");
777
778 /* couldn't open the event: send the string to the kernel debugger */
779 if (hDBMonBufferReady == NULL) break;
780
781 /* open the event to be signaled when the buffer has been filled */
782 hDBMonDataReady = OpenEventW(EVENT_MODIFY_STATE, FALSE, L"DBWIN_DATA_READY");
783 }
784 while(0);
785
786 /* we couldn't connect to the system-wide debug message monitor: send the
787 string to the kernel debugger */
788 if (hDBMonDataReady == NULL) ReleaseMutex(hDBMonMutex);
789 }
790
792 {
793 /* size of the current output block */
794 volatile SIZE_T nRoundLen;
795
796 /* size of the remainder of the string */
797 volatile SIZE_T nOutputStringLen;
798
799 /* output the whole string */
800 nOutputStringLen = strlen(_OutputString);
801
802 do
803 {
804 /* we're connected to the debug monitor:
805 write the current block to the shared buffer */
806 if (hDBMonDataReady)
807 {
808 /* wait a maximum of 10 seconds for the debug monitor
809 to finish processing the shared buffer */
810 if (WaitForSingleObject(hDBMonBufferReady, 10000) != WAIT_OBJECT_0)
811 {
812 /* timeout or failure: give up */
813 break;
814 }
815
816 /* write the process id into the buffer */
817 pDBMonBuffer->ProcessId = GetCurrentProcessId();
818
819 /* write only as many bytes as they fit in the buffer */
820 if (nOutputStringLen > (PAGE_SIZE - sizeof(DWORD) - 1))
821 nRoundLen = PAGE_SIZE - sizeof(DWORD) - 1;
822 else
823 nRoundLen = nOutputStringLen;
824
825 /* copy the current block into the buffer */
826 memcpy(pDBMonBuffer->Buffer, _OutputString, nRoundLen);
827
828 /* null-terminate the current block */
829 pDBMonBuffer->Buffer[nRoundLen] = 0;
830
831 /* signal that the data contains meaningful data and can be read */
832 SetEvent(hDBMonDataReady);
833 }
834 /* else, send the current block to the kernel debugger */
835 else
836 {
837 /* output in blocks of 512 characters */
838 a_cBuffer = (CHAR*)HeapAlloc(GetProcessHeap(), 0, 512);
839
840 if (!a_cBuffer)
841 {
842 DbgPrint("OutputDebugStringA: Failed\n");
843 break;
844 }
845
846 /* write a maximum of 511 bytes */
847 if (nOutputStringLen > 510)
848 nRoundLen = 510;
849 else
850 nRoundLen = nOutputStringLen;
851
852 /* copy the current block */
853 memcpy(a_cBuffer, _OutputString, nRoundLen);
854
855 /* null-terminate the current block */
856 a_cBuffer[nRoundLen] = 0;
857
858 /* send the current block to the kernel debugger */
859 DbgPrint("%s", a_cBuffer);
860
861 if (a_cBuffer)
862 {
863 HeapFree(GetProcessHeap(), 0, a_cBuffer);
864 a_cBuffer = NULL;
865 }
866 }
867
868 /* move to the next block */
869 _OutputString += nRoundLen;
870 nOutputStringLen -= nRoundLen;
871 }
872 /* repeat until the string has been fully output */
873 while (nOutputStringLen > 0);
874 }
875 /* ignore access violations and let other exceptions fall through */
877 {
878 if (a_cBuffer)
879 HeapFree(GetProcessHeap(), 0, a_cBuffer);
880
881 /* string copied verbatim from Microsoft's kernel32.dll */
882 DbgPrint("\nOutputDebugString faulted during output\n");
883 }
884 _SEH2_END;
885 }
887 {
888 /* close all the still open resources */
889 if (hDBMonBufferReady) CloseHandle(hDBMonBufferReady);
890 if (pDBMonBuffer) UnmapViewOfFile(pDBMonBuffer);
891 if (hDBMonBuffer) CloseHandle(hDBMonBuffer);
892 if (hDBMonDataReady) CloseHandle(hDBMonDataReady);
893
894 /* leave the critical section */
895 if (hDBMonDataReady != NULL)
896 ReleaseMutex(hDBMonMutex);
897 }
898 _SEH2_END;
899 }
900 _SEH2_END;
901}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
Definition: bufpool.h:45
#define GetProcessHeap()
Definition: compat.h:736
#define SECTION_MAP_READ
Definition: compat.h:139
#define UnmapViewOfFile
Definition: compat.h:746
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define MapViewOfFile
Definition: compat.h:745
static HANDLE K32CreateDBMonMutex(VOID)
Definition: debugger.c:37
VOID WINAPI RaiseException(_In_ DWORD dwExceptionCode, _In_ DWORD dwExceptionFlags, _In_ DWORD nNumberOfArguments, _In_opt_ const ULONG_PTR *lpArguments)
Definition: except.c:700
#define INFINITE
Definition: serial.h:102
#define ULONG_PTR
Definition: config.h:101
#define PAGE_SIZE
Definition: env_spec_w32.h:49
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ProcessId
Definition: fatprocs.h:2711
HANDLE NTAPI OpenFileMappingW(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCWSTR lpName)
Definition: filemap.c:297
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
unsigned long DWORD
Definition: ntddk_ex.h:95
#define DbgPrint
Definition: hal.h:12
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:86
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define SECTION_MAP_WRITE
Definition: nt_native.h:1288
#define DWORD
Definition: nt_native.h:44
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define DBG_PRINTEXCEPTION_C
Definition: ntstatus.h:53
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
HANDLE WINAPI DECLSPEC_HOTPATCH OpenEventW(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCWSTR lpName)
Definition: synch.c:682
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
BOOL WINAPI DECLSPEC_HOTPATCH ReleaseMutex(IN HANDLE hMutex)
Definition: synch.c:618
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
uint32_t ULONG_PTR
Definition: typedefs.h:65
char * PCHAR
Definition: typedefs.h:51
#define EVENT_MODIFY_STATE
Definition: winbase.h:163
DWORD WINAPI GetCurrentProcessId(void)
Definition: proc.c:1158
#define WAIT_OBJECT_0
Definition: winbase.h:406
char CHAR
Definition: xmlstorage.h:175

Referenced by OutputDebugStringW().

◆ OutputDebugStringW()

VOID WINAPI OutputDebugStringW ( IN LPCWSTR  OutputString)

Definition at line 908 of file debugger.c.

909{
913
914 /* convert the string in ANSI */
915 RtlInitUnicodeString(&UnicodeString, OutputString);
917
918 /* OutputDebugStringW always prints something, even if conversion fails */
919 if (!NT_SUCCESS(Status)) AnsiString.Buffer = "";
920
921 /* Output the converted string */
923
924 /* free the converted string */
926}
VOID WINAPI OutputDebugStringA(IN LPCSTR _OutputString)
Definition: debugger.c:693
@ AnsiString
Definition: dnslib.h:19
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
NTSYSAPI VOID NTAPI RtlFreeAnsiString(PANSI_STRING AnsiString)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)

◆ ProcessIdToHandle()

HANDLE WINAPI ProcessIdToHandle ( IN DWORD  dwProcessId)

Definition at line 338 of file debugger.c.

339{
344
345 /* If we don't have a PID, look it up */
346 if (dwProcessId == MAXDWORD) dwProcessId = (DWORD_PTR)CsrGetProcessId();
347
348 /* Open a handle to the process */
350 ClientId.UniqueProcess = UlongToHandle(dwProcessId);
357 &ClientId);
358 if (!NT_SUCCESS(Status))
359 {
360 /* Fail */
362 return 0;
363 }
364
365 /* Return the handle */
366 return Handle;
367}
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define PROCESS_SUSPEND_RESUME
Definition: pstypes.h:167
#define PROCESS_VM_READ
Definition: pstypes.h:161
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:166
#define PROCESS_VM_WRITE
Definition: pstypes.h:162
#define PROCESS_CREATE_THREAD
Definition: pstypes.h:158
#define PROCESS_VM_OPERATION
Definition: pstypes.h:160
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define MAXDWORD
NTSTATUS NTAPI NtOpenProcess(OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PCLIENT_ID ClientId)
Definition: process.c:1440
HANDLE NTAPI CsrGetProcessId(VOID)
Definition: connect.c:507
#define DWORD_PTR
Definition: treelist.c:76

Referenced by DebugActiveProcess(), and DebugActiveProcessStop().

◆ RemoveHandles()

VOID WINAPI RemoveHandles ( IN DWORD  dwProcessId,
IN DWORD  dwThreadId 
)

Definition at line 268 of file debugger.c.

270{
272 PDBGSS_THREAD_DATA ThisData;
273
274 /* Loop all thread data events */
275 ThreadData = (PDBGSS_THREAD_DATA*)NtCurrentTeb()->DbgSsReserved;
276 ThisData = *ThreadData;
277 while(ThisData)
278 {
279 /* Check if this one matches */
280 if ((ThisData->HandleMarked) &&
281 ((ThisData->ProcessId == dwProcessId) || (ThisData->ThreadId == dwThreadId)))
282 {
283 /* Close open handles */
284 if (ThisData->ThreadHandle) CloseHandle(ThisData->ThreadHandle);
285 if (ThisData->ProcessHandle) CloseHandle(ThisData->ProcessHandle);
286
287 /* Unlink the thread data */
288 *ThreadData = ThisData->Next;
289
290 /* Free it*/
291 RtlFreeHeap(RtlGetProcessHeap(), 0, ThisData);
292 }
293 else
294 {
295 /* Move to the next one */
296 ThreadData = &ThisData->Next;
297 }
298 ThisData = *ThreadData;
299 }
300}
BOOLEAN HandleMarked
Definition: debugger.c:25

Referenced by ContinueDebugEvent().

◆ SaveProcessHandle()

VOID WINAPI SaveProcessHandle ( IN DWORD  dwProcessId,
IN HANDLE  hProcess 
)

Definition at line 205 of file debugger.c.

207{
209
210 /* Allocate a thread structure */
211 ThreadData = RtlAllocateHeap(RtlGetProcessHeap(),
212 0,
213 sizeof(DBGSS_THREAD_DATA));
214 if (!ThreadData) return;
215
216 /* Fill it out */
217 ThreadData->ProcessHandle = hProcess;
218 ThreadData->ProcessId = dwProcessId;
219 ThreadData->ThreadId = 0;
220 ThreadData->ThreadHandle = NULL;
221 ThreadData->HandleMarked = FALSE;
222
223 /* Link it */
226}
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
#define DbgSsSetThreadData(d)
Definition: debugger.c:28

Referenced by WaitForDebugEvent().

◆ SaveThreadHandle()

VOID WINAPI SaveThreadHandle ( IN DWORD  dwProcessId,
IN DWORD  dwThreadId,
IN HANDLE  hThread 
)

Definition at line 179 of file debugger.c.

182{
184
185 /* Allocate a thread structure */
186 ThreadData = RtlAllocateHeap(RtlGetProcessHeap(),
187 0,
188 sizeof(DBGSS_THREAD_DATA));
189 if (!ThreadData) return;
190
191 /* Fill it out */
192 ThreadData->ThreadHandle = hThread;
193 ThreadData->ProcessId = dwProcessId;
194 ThreadData->ThreadId = dwThreadId;
195 ThreadData->ProcessHandle = NULL;
196 ThreadData->HandleMarked = FALSE;
197
198 /* Link it */
201}
HANDLE hThread
Definition: wizard.c:28

Referenced by WaitForDebugEvent().

◆ WaitForDebugEvent()

BOOL WINAPI WaitForDebugEvent ( IN LPDEBUG_EVENT  lpDebugEvent,
IN DWORD  dwMilliseconds 
)

Definition at line 590 of file debugger.c.

592{
593 LARGE_INTEGER WaitTime;
595 DBGUI_WAIT_STATE_CHANGE WaitStateChange;
597
598 /* Convert to NT Timeout */
599 Timeout = BaseFormatTimeOut(&WaitTime, dwMilliseconds);
600
601 /* Loop while we keep getting interrupted */
602 do
603 {
604 /* Call the native API */
605 Status = DbgUiWaitStateChange(&WaitStateChange, Timeout);
606 } while ((Status == STATUS_ALERTED) || (Status == STATUS_USER_APC));
607
608 /* Check if the wait failed */
610 {
611 /* Set the error code and quit */
613 return FALSE;
614 }
615
616 /* Check if we timed out */
617 if (Status == STATUS_TIMEOUT)
618 {
619 /* Fail with a timeout error */
621 return FALSE;
622 }
623
624 /* Convert the structure */
625 Status = DbgUiConvertStateChangeStructure(&WaitStateChange, lpDebugEvent);
626 if (!NT_SUCCESS(Status))
627 {
628 /* Set the error code and quit */
630 return FALSE;
631 }
632
633 /* Check what kind of event this was */
634 switch (lpDebugEvent->dwDebugEventCode)
635 {
636 /* New thread was created */
638
639 /* Setup the thread data */
640 SaveThreadHandle(lpDebugEvent->dwProcessId,
641 lpDebugEvent->dwThreadId,
642 lpDebugEvent->u.CreateThread.hThread);
643 break;
644
645 /* New process was created */
647
648 /* Setup the process data */
649 SaveProcessHandle(lpDebugEvent->dwProcessId,
650 lpDebugEvent->u.CreateProcessInfo.hProcess);
651
652 /* Setup the thread data */
653 SaveThreadHandle(lpDebugEvent->dwProcessId,
654 lpDebugEvent->dwThreadId,
655 lpDebugEvent->u.CreateProcessInfo.hThread);
656 break;
657
658 /* Process was exited */
660
661 /* Mark the thread data as such and fall through */
662 MarkProcessHandle(lpDebugEvent->dwProcessId);
663
664 /* Thread was exited */
666
667 /* Mark the thread data */
668 MarkThreadHandle(lpDebugEvent->dwThreadId);
669 break;
670
671 /* Nothing to do */
676 case RIP_EVENT:
677 break;
678
679 /* Fail anything else */
680 default:
681 return FALSE;
682 }
683
684 /* Return success */
685 return TRUE;
686}
NTSTATUS NTAPI DbgUiConvertStateChangeStructure(IN PDBGUI_WAIT_STATE_CHANGE WaitStateChange, OUT PVOID Win32DebugEvent)
Definition: dbgui.c:61
NTSTATUS NTAPI DbgUiWaitStateChange(OUT PDBGUI_WAIT_STATE_CHANGE WaitStateChange, IN PLARGE_INTEGER TimeOut OPTIONAL)
Definition: dbgui.c:274
VOID WINAPI MarkProcessHandle(IN DWORD dwProcessId)
Definition: debugger.c:249
VOID WINAPI SaveThreadHandle(IN DWORD dwProcessId, IN DWORD dwThreadId, IN HANDLE hThread)
Definition: debugger.c:179
VOID WINAPI SaveProcessHandle(IN DWORD dwProcessId, IN HANDLE hProcess)
Definition: debugger.c:205
VOID WINAPI MarkThreadHandle(IN DWORD dwThreadId)
Definition: debugger.c:230
PLARGE_INTEGER WINAPI BaseFormatTimeOut(OUT PLARGE_INTEGER Timeout, IN DWORD dwMilliseconds)
Definition: utils.c:288
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define STATUS_ALERTED
Definition: ntstatus.h:80
#define STATUS_USER_APC
Definition: ntstatus.h:78
#define DBG_UNABLE_TO_PROVIDE_HANDLE
Definition: ntstatus.h:49
static ULONG Timeout
Definition: ping.c:61
#define RIP_EVENT
Definition: winbase.h:110
#define CREATE_PROCESS_DEBUG_EVENT
Definition: winbase.h:104
#define LOAD_DLL_DEBUG_EVENT
Definition: winbase.h:107
#define EXIT_PROCESS_DEBUG_EVENT
Definition: winbase.h:106
#define OUTPUT_DEBUG_STRING_EVENT
Definition: winbase.h:109
#define EXCEPTION_DEBUG_EVENT
Definition: winbase.h:102
#define CREATE_THREAD_DEBUG_EVENT
Definition: winbase.h:103
#define UNLOAD_DLL_DEBUG_EVENT
Definition: winbase.h:108
#define EXIT_THREAD_DEBUG_EVENT
Definition: winbase.h:105
#define ERROR_SEM_TIMEOUT
Definition: winerror.h:193

Referenced by dll_entry_point(), Main(), test_debug_children(), test_debug_loop(), test_DebuggingFlag(), test_NtSuspendProcess(), test_query_process_debug_flags(), test_query_process_debug_object_handle(), test_query_process_debug_port(), and wWinMain().