4 * Copyright 1996-1998 Marcus Meissner
5 * Copyright 2018 Alexandre Julliard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include <sys/types.h>
32 #define WIN32_NO_STATUS
33 #include "wine/debug.h"
36 #include "ntdll_misc.h"
37 #include "wine/exception.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(process
);
42 /******************************************************************************
43 * RtlGetCurrentPeb [NTDLL.@]
46 PEB
* WINAPI
RtlGetCurrentPeb(void)
48 return NtCurrentTeb()->Peb
;
52 /**********************************************************************
53 * RtlCreateUserProcess (NTDLL.@)
55 NTSTATUS WINAPI
RtlCreateUserProcess( UNICODE_STRING
*path
, ULONG attributes
,
56 RTL_USER_PROCESS_PARAMETERS
*params
,
57 SECURITY_DESCRIPTOR
*process_descr
,
58 SECURITY_DESCRIPTOR
*thread_descr
,
59 HANDLE parent
, BOOLEAN inherit
, HANDLE debug
, HANDLE token
,
60 RTL_USER_PROCESS_INFORMATION
*info
)
62 OBJECT_ATTRIBUTES process_attr
, thread_attr
;
63 PS_CREATE_INFO create_info
;
64 ULONG_PTR buffer
[offsetof( PS_ATTRIBUTE_LIST
, Attributes
[6] ) / sizeof(ULONG_PTR
)];
65 PS_ATTRIBUTE_LIST
*attr
= (PS_ATTRIBUTE_LIST
*)buffer
;
68 RtlNormalizeProcessParams( params
);
70 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_IMAGE_NAME
;
71 attr
->Attributes
[pos
].Size
= path
->Length
;
72 attr
->Attributes
[pos
].ValuePtr
= path
->Buffer
;
73 attr
->Attributes
[pos
].ReturnLength
= NULL
;
75 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_CLIENT_ID
;
76 attr
->Attributes
[pos
].Size
= sizeof(info
->ClientId
);
77 attr
->Attributes
[pos
].ValuePtr
= &info
->ClientId
;
78 attr
->Attributes
[pos
].ReturnLength
= NULL
;
80 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_IMAGE_INFO
;
81 attr
->Attributes
[pos
].Size
= sizeof(info
->ImageInformation
);
82 attr
->Attributes
[pos
].ValuePtr
= &info
->ImageInformation
;
83 attr
->Attributes
[pos
].ReturnLength
= NULL
;
87 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_PARENT_PROCESS
;
88 attr
->Attributes
[pos
].Size
= sizeof(parent
);
89 attr
->Attributes
[pos
].ValuePtr
= parent
;
90 attr
->Attributes
[pos
].ReturnLength
= NULL
;
95 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_DEBUG_PORT
;
96 attr
->Attributes
[pos
].Size
= sizeof(debug
);
97 attr
->Attributes
[pos
].ValuePtr
= debug
;
98 attr
->Attributes
[pos
].ReturnLength
= NULL
;
103 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_TOKEN
;
104 attr
->Attributes
[pos
].Size
= sizeof(token
);
105 attr
->Attributes
[pos
].ValuePtr
= token
;
106 attr
->Attributes
[pos
].ReturnLength
= NULL
;
109 attr
->TotalLength
= offsetof( PS_ATTRIBUTE_LIST
, Attributes
[pos
] );
111 InitializeObjectAttributes( &process_attr
, NULL
, 0, NULL
, process_descr
);
112 InitializeObjectAttributes( &thread_attr
, NULL
, 0, NULL
, thread_descr
);
114 return NtCreateUserProcess( &info
->Process
, &info
->Thread
, PROCESS_ALL_ACCESS
, THREAD_ALL_ACCESS
,
115 &process_attr
, &thread_attr
,
116 inherit
? PROCESS_CREATE_FLAGS_INHERIT_HANDLES
: 0,
117 THREAD_CREATE_FLAGS_CREATE_SUSPENDED
, params
,
118 &create_info
, attr
);
121 /***********************************************************************
122 * DbgUiGetThreadDebugObject (NTDLL.@)
124 HANDLE WINAPI
DbgUiGetThreadDebugObject(void)
126 return NtCurrentTeb()->DbgSsReserved
[1];
129 /***********************************************************************
130 * DbgUiSetThreadDebugObject (NTDLL.@)
132 void WINAPI
DbgUiSetThreadDebugObject( HANDLE handle
)
134 NtCurrentTeb()->DbgSsReserved
[1] = handle
;
137 /***********************************************************************
138 * DbgUiConnectToDbg (NTDLL.@)
140 NTSTATUS WINAPI
DbgUiConnectToDbg(void)
144 OBJECT_ATTRIBUTES attr
= { sizeof(attr
) };
146 if (DbgUiGetThreadDebugObject()) return STATUS_SUCCESS
; /* already connected */
148 status
= NtCreateDebugObject( &handle
, DEBUG_ALL_ACCESS
, &attr
, DEBUG_KILL_ON_CLOSE
);
149 if (!status
) DbgUiSetThreadDebugObject( handle
);
153 /***********************************************************************
154 * DbgUiDebugActiveProcess (NTDLL.@)
156 NTSTATUS WINAPI
DbgUiDebugActiveProcess( HANDLE process
)
160 if ((status
= NtDebugActiveProcess( process
, DbgUiGetThreadDebugObject() ))) return status
;
161 if ((status
= DbgUiIssueRemoteBreakin( process
))) DbgUiStopDebugging( process
);
165 /***********************************************************************
166 * DbgUiStopDebugging (NTDLL.@)
168 NTSTATUS WINAPI
DbgUiStopDebugging( HANDLE process
)
170 return NtRemoveProcessDebug( process
, DbgUiGetThreadDebugObject() );
173 /***********************************************************************
174 * DbgUiContinue (NTDLL.@)
176 NTSTATUS WINAPI
DbgUiContinue( CLIENT_ID
*client
, NTSTATUS status
)
178 return NtDebugContinue( DbgUiGetThreadDebugObject(), client
, status
);
181 /***********************************************************************
182 * DbgUiWaitStateChange (NTDLL.@)
184 NTSTATUS WINAPI
DbgUiWaitStateChange( DBGUI_WAIT_STATE_CHANGE
*state
, LARGE_INTEGER
*timeout
)
186 return NtWaitForDebugEvent( DbgUiGetThreadDebugObject(), TRUE
, timeout
, state
);
189 /* helper for DbgUiConvertStateChangeStructure */
190 static inline void *get_thread_teb( HANDLE thread
)
192 THREAD_BASIC_INFORMATION info
;
194 if (NtQueryInformationThread( thread
, ThreadBasicInformation
, &info
, sizeof(info
), NULL
)) return NULL
;
195 return info
.TebBaseAddress
;
198 /***********************************************************************
199 * DbgUiConvertStateChangeStructure (NTDLL.@)
201 NTSTATUS WINAPI
DbgUiConvertStateChangeStructure( DBGUI_WAIT_STATE_CHANGE
*state
, DEBUG_EVENT
*event
)
203 event
->dwProcessId
= HandleToULong( state
->AppClientId
.UniqueProcess
);
204 event
->dwThreadId
= HandleToULong( state
->AppClientId
.UniqueThread
);
205 switch (state
->NewState
)
207 case DbgCreateThreadStateChange
:
209 DBGUI_CREATE_THREAD
*info
= &state
->StateInfo
.CreateThread
;
210 event
->dwDebugEventCode
= CREATE_THREAD_DEBUG_EVENT
;
211 event
->u
.CreateThread
.hThread
= info
->HandleToThread
;
212 event
->u
.CreateThread
.lpThreadLocalBase
= get_thread_teb( info
->HandleToThread
);
213 event
->u
.CreateThread
.lpStartAddress
= info
->NewThread
.StartAddress
;
216 case DbgCreateProcessStateChange
:
218 DBGUI_CREATE_PROCESS
*info
= &state
->StateInfo
.CreateProcessInfo
;
219 event
->dwDebugEventCode
= CREATE_PROCESS_DEBUG_EVENT
;
220 event
->u
.CreateProcessInfo
.hFile
= info
->NewProcess
.FileHandle
;
221 event
->u
.CreateProcessInfo
.hProcess
= info
->HandleToProcess
;
222 event
->u
.CreateProcessInfo
.hThread
= info
->HandleToThread
;
223 event
->u
.CreateProcessInfo
.lpBaseOfImage
= info
->NewProcess
.BaseOfImage
;
224 event
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
= info
->NewProcess
.DebugInfoFileOffset
;
225 event
->u
.CreateProcessInfo
.nDebugInfoSize
= info
->NewProcess
.DebugInfoSize
;
226 event
->u
.CreateProcessInfo
.lpThreadLocalBase
= get_thread_teb( info
->HandleToThread
);
227 event
->u
.CreateProcessInfo
.lpStartAddress
= info
->NewProcess
.InitialThread
.StartAddress
;
228 event
->u
.CreateProcessInfo
.lpImageName
= NULL
;
229 event
->u
.CreateProcessInfo
.fUnicode
= TRUE
;
232 case DbgExitThreadStateChange
:
234 DBGKM_EXIT_THREAD
*info
= &state
->StateInfo
.ExitThread
;
235 event
->dwDebugEventCode
= EXIT_THREAD_DEBUG_EVENT
;
236 event
->u
.ExitThread
.dwExitCode
= info
->ExitStatus
;
239 case DbgExitProcessStateChange
:
241 DBGKM_EXIT_PROCESS
*info
= &state
->StateInfo
.ExitProcess
;
242 event
->dwDebugEventCode
= EXIT_PROCESS_DEBUG_EVENT
;
243 event
->u
.ExitProcess
.dwExitCode
= info
->ExitStatus
;
246 case DbgExceptionStateChange
:
247 case DbgBreakpointStateChange
:
248 case DbgSingleStepStateChange
:
250 DBGKM_EXCEPTION
*info
= &state
->StateInfo
.Exception
;
251 DWORD code
= info
->ExceptionRecord
.ExceptionCode
;
252 if (code
== DBG_PRINTEXCEPTION_C
&& info
->ExceptionRecord
.NumberParameters
>= 2)
254 event
->dwDebugEventCode
= OUTPUT_DEBUG_STRING_EVENT
;
255 event
->u
.DebugString
.lpDebugStringData
= (void *)info
->ExceptionRecord
.ExceptionInformation
[1];
256 event
->u
.DebugString
.fUnicode
= FALSE
;
257 event
->u
.DebugString
.nDebugStringLength
= info
->ExceptionRecord
.ExceptionInformation
[0];
259 else if (code
== DBG_RIPEXCEPTION
&& info
->ExceptionRecord
.NumberParameters
>= 2)
261 event
->dwDebugEventCode
= RIP_EVENT
;
262 event
->u
.RipInfo
.dwError
= info
->ExceptionRecord
.ExceptionInformation
[0];
263 event
->u
.RipInfo
.dwType
= info
->ExceptionRecord
.ExceptionInformation
[1];
267 event
->dwDebugEventCode
= EXCEPTION_DEBUG_EVENT
;
268 event
->u
.Exception
.ExceptionRecord
= info
->ExceptionRecord
;
269 event
->u
.Exception
.dwFirstChance
= info
->FirstChance
;
273 case DbgLoadDllStateChange
:
275 DBGKM_LOAD_DLL
*info
= &state
->StateInfo
.LoadDll
;
276 event
->dwDebugEventCode
= LOAD_DLL_DEBUG_EVENT
;
277 event
->u
.LoadDll
.hFile
= info
->FileHandle
;
278 event
->u
.LoadDll
.lpBaseOfDll
= info
->BaseOfDll
;
279 event
->u
.LoadDll
.dwDebugInfoFileOffset
= info
->DebugInfoFileOffset
;
280 event
->u
.LoadDll
.nDebugInfoSize
= info
->DebugInfoSize
;
281 event
->u
.LoadDll
.lpImageName
= info
->NamePointer
;
282 event
->u
.LoadDll
.fUnicode
= TRUE
;
285 case DbgUnloadDllStateChange
:
287 DBGKM_UNLOAD_DLL
*info
= &state
->StateInfo
.UnloadDll
;
288 event
->dwDebugEventCode
= UNLOAD_DLL_DEBUG_EVENT
;
289 event
->u
.UnloadDll
.lpBaseOfDll
= info
->BaseAddress
;
293 return STATUS_UNSUCCESSFUL
;
295 return STATUS_SUCCESS
;
298 /***********************************************************************
299 * DbgUiRemoteBreakin (NTDLL.@)
301 void WINAPI
DbgUiRemoteBreakin( void *arg
)
304 if (NtCurrentTeb()->Peb
->BeingDebugged
)
316 RtlExitUserThread( STATUS_SUCCESS
);
319 /***********************************************************************
320 * DbgUiIssueRemoteBreakin (NTDLL.@)
322 NTSTATUS WINAPI
DbgUiIssueRemoteBreakin( HANDLE process
)
324 return unix_funcs
->DbgUiIssueRemoteBreakin( process
);