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 * RtlWow64GetCurrentMachine (NTDLL.@)
55 USHORT WINAPI
RtlWow64GetCurrentMachine(void)
57 USHORT current
, native
;
59 RtlWow64GetProcessMachines( GetCurrentProcess(), ¤t
, &native
);
60 return current
? current
: native
;
64 /**********************************************************************
65 * RtlWow64GetProcessMachines (NTDLL.@)
67 NTSTATUS WINAPI
RtlWow64GetProcessMachines( HANDLE process
, USHORT
*current_ret
, USHORT
*native_ret
)
70 USHORT current
= 0, native
= 0;
73 status
= NtQuerySystemInformationEx( SystemSupportedProcessorArchitectures
, &process
, sizeof(process
),
74 machines
, sizeof(machines
), NULL
);
75 if (status
) return status
;
76 for (i
= 0; machines
[i
]; i
++)
78 USHORT flags
= HIWORD(machines
[i
]);
79 USHORT machine
= LOWORD(machines
[i
]);
80 if (flags
& 4 /* native machine */) native
= machine
;
81 else if (flags
& 8 /* current machine */) current
= machine
;
83 if (current_ret
) *current_ret
= current
;
84 if (native_ret
) *native_ret
= native
;
89 /**********************************************************************
90 * RtlWow64IsWowGuestMachineSupported (NTDLL.@)
92 NTSTATUS WINAPI
RtlWow64IsWowGuestMachineSupported( USHORT machine
, BOOLEAN
*supported
)
98 status
= NtQuerySystemInformationEx( SystemSupportedProcessorArchitectures
, &process
, sizeof(process
),
99 machines
, sizeof(machines
), NULL
);
100 if (status
) return status
;
102 for (i
= 0; machines
[i
]; i
++)
104 if (HIWORD(machines
[i
]) & 4 /* native machine */) continue;
105 if (machine
== LOWORD(machines
[i
])) *supported
= TRUE
;
113 /**********************************************************************
114 * RtlWow64GetCpuAreaInfo (NTDLL.@)
116 NTSTATUS WINAPI
RtlWow64GetCpuAreaInfo( WOW64_CPURESERVED
*cpu
, ULONG reserved
, WOW64_CPU_AREA_INFO
*info
)
118 static const struct { ULONG machine
, align
, size
, offset
, flag
; } data
[] =
120 #define ENTRY(machine,type,flag) { machine, TYPE_ALIGNMENT(type), sizeof(type), offsetof(type,ContextFlags), flag },
121 ENTRY( IMAGE_FILE_MACHINE_I386
, I386_CONTEXT
, CONTEXT_i386
)
122 ENTRY( IMAGE_FILE_MACHINE_AMD64
, AMD64_CONTEXT
, CONTEXT_AMD64
)
123 ENTRY( IMAGE_FILE_MACHINE_ARMNT
, ARM_CONTEXT
, CONTEXT_ARM
)
124 ENTRY( IMAGE_FILE_MACHINE_ARM64
, ARM64_NT_CONTEXT
, CONTEXT_ARM64
)
129 for (i
= 0; i
< ARRAY_SIZE(data
); i
++)
131 #define ALIGN(ptr,align) ((void *)(((ULONG_PTR)(ptr) + (align) - 1) & ~((align) - 1)))
132 if (data
[i
].machine
!= cpu
->Machine
) continue;
133 info
->Context
= ALIGN( cpu
+ 1, data
[i
].align
);
134 info
->ContextEx
= ALIGN( (char *)info
->Context
+ data
[i
].size
, sizeof(void *) );
135 info
->ContextFlagsLocation
= (char *)info
->Context
+ data
[i
].offset
;
136 info
->ContextFlag
= data
[i
].flag
;
137 info
->CpuReserved
= cpu
;
138 info
->Machine
= data
[i
].machine
;
139 return STATUS_SUCCESS
;
142 return STATUS_INVALID_PARAMETER
;
146 /******************************************************************************
147 * RtlWow64GetThreadContext (NTDLL.@)
149 NTSTATUS WINAPI
RtlWow64GetThreadContext( HANDLE handle
, WOW64_CONTEXT
*context
)
151 return NtQueryInformationThread( handle
, ThreadWow64Context
, context
, sizeof(*context
), NULL
);
155 /******************************************************************************
156 * RtlWow64SetThreadContext (NTDLL.@)
158 NTSTATUS WINAPI
RtlWow64SetThreadContext( HANDLE handle
, const WOW64_CONTEXT
*context
)
160 return NtSetInformationThread( handle
, ThreadWow64Context
, context
, sizeof(*context
) );
165 /**********************************************************************
166 * RtlCreateUserProcess (NTDLL.@)
168 NTSTATUS WINAPI
RtlCreateUserProcess( UNICODE_STRING
*path
, ULONG attributes
,
169 RTL_USER_PROCESS_PARAMETERS
*params
,
170 SECURITY_DESCRIPTOR
*process_descr
,
171 SECURITY_DESCRIPTOR
*thread_descr
,
172 HANDLE parent
, BOOLEAN inherit
, HANDLE debug
, HANDLE token
,
173 RTL_USER_PROCESS_INFORMATION
*info
)
175 OBJECT_ATTRIBUTES process_attr
, thread_attr
;
176 PS_CREATE_INFO create_info
;
177 ULONG_PTR buffer
[offsetof( PS_ATTRIBUTE_LIST
, Attributes
[6] ) / sizeof(ULONG_PTR
)];
178 PS_ATTRIBUTE_LIST
*attr
= (PS_ATTRIBUTE_LIST
*)buffer
;
181 RtlNormalizeProcessParams( params
);
183 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_IMAGE_NAME
;
184 attr
->Attributes
[pos
].Size
= path
->Length
;
185 attr
->Attributes
[pos
].ValuePtr
= path
->Buffer
;
186 attr
->Attributes
[pos
].ReturnLength
= NULL
;
188 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_CLIENT_ID
;
189 attr
->Attributes
[pos
].Size
= sizeof(info
->ClientId
);
190 attr
->Attributes
[pos
].ValuePtr
= &info
->ClientId
;
191 attr
->Attributes
[pos
].ReturnLength
= NULL
;
193 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_IMAGE_INFO
;
194 attr
->Attributes
[pos
].Size
= sizeof(info
->ImageInformation
);
195 attr
->Attributes
[pos
].ValuePtr
= &info
->ImageInformation
;
196 attr
->Attributes
[pos
].ReturnLength
= NULL
;
200 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_PARENT_PROCESS
;
201 attr
->Attributes
[pos
].Size
= sizeof(parent
);
202 attr
->Attributes
[pos
].ValuePtr
= parent
;
203 attr
->Attributes
[pos
].ReturnLength
= NULL
;
208 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_DEBUG_PORT
;
209 attr
->Attributes
[pos
].Size
= sizeof(debug
);
210 attr
->Attributes
[pos
].ValuePtr
= debug
;
211 attr
->Attributes
[pos
].ReturnLength
= NULL
;
216 attr
->Attributes
[pos
].Attribute
= PS_ATTRIBUTE_TOKEN
;
217 attr
->Attributes
[pos
].Size
= sizeof(token
);
218 attr
->Attributes
[pos
].ValuePtr
= token
;
219 attr
->Attributes
[pos
].ReturnLength
= NULL
;
222 attr
->TotalLength
= offsetof( PS_ATTRIBUTE_LIST
, Attributes
[pos
] );
224 InitializeObjectAttributes( &process_attr
, NULL
, 0, NULL
, process_descr
);
225 InitializeObjectAttributes( &thread_attr
, NULL
, 0, NULL
, thread_descr
);
227 return NtCreateUserProcess( &info
->Process
, &info
->Thread
, PROCESS_ALL_ACCESS
, THREAD_ALL_ACCESS
,
228 &process_attr
, &thread_attr
,
229 inherit
? PROCESS_CREATE_FLAGS_INHERIT_HANDLES
: 0,
230 THREAD_CREATE_FLAGS_CREATE_SUSPENDED
, params
,
231 &create_info
, attr
);
234 /***********************************************************************
235 * DbgUiGetThreadDebugObject (NTDLL.@)
237 HANDLE WINAPI
DbgUiGetThreadDebugObject(void)
239 return NtCurrentTeb()->DbgSsReserved
[1];
242 /***********************************************************************
243 * DbgUiSetThreadDebugObject (NTDLL.@)
245 void WINAPI
DbgUiSetThreadDebugObject( HANDLE handle
)
247 NtCurrentTeb()->DbgSsReserved
[1] = handle
;
250 /***********************************************************************
251 * DbgUiConnectToDbg (NTDLL.@)
253 NTSTATUS WINAPI
DbgUiConnectToDbg(void)
257 OBJECT_ATTRIBUTES attr
= { sizeof(attr
) };
259 if (DbgUiGetThreadDebugObject()) return STATUS_SUCCESS
; /* already connected */
261 status
= NtCreateDebugObject( &handle
, DEBUG_ALL_ACCESS
, &attr
, DEBUG_KILL_ON_CLOSE
);
262 if (!status
) DbgUiSetThreadDebugObject( handle
);
266 /***********************************************************************
267 * DbgUiDebugActiveProcess (NTDLL.@)
269 NTSTATUS WINAPI
DbgUiDebugActiveProcess( HANDLE process
)
273 if ((status
= NtDebugActiveProcess( process
, DbgUiGetThreadDebugObject() ))) return status
;
274 if ((status
= DbgUiIssueRemoteBreakin( process
))) DbgUiStopDebugging( process
);
278 /***********************************************************************
279 * DbgUiStopDebugging (NTDLL.@)
281 NTSTATUS WINAPI
DbgUiStopDebugging( HANDLE process
)
283 return NtRemoveProcessDebug( process
, DbgUiGetThreadDebugObject() );
286 /***********************************************************************
287 * DbgUiContinue (NTDLL.@)
289 NTSTATUS WINAPI
DbgUiContinue( CLIENT_ID
*client
, NTSTATUS status
)
291 return NtDebugContinue( DbgUiGetThreadDebugObject(), client
, status
);
294 /***********************************************************************
295 * DbgUiWaitStateChange (NTDLL.@)
297 NTSTATUS WINAPI
DbgUiWaitStateChange( DBGUI_WAIT_STATE_CHANGE
*state
, LARGE_INTEGER
*timeout
)
299 return NtWaitForDebugEvent( DbgUiGetThreadDebugObject(), TRUE
, timeout
, state
);
302 /* helper for DbgUiConvertStateChangeStructure */
303 static inline void *get_thread_teb( HANDLE thread
)
305 THREAD_BASIC_INFORMATION info
;
307 if (NtQueryInformationThread( thread
, ThreadBasicInformation
, &info
, sizeof(info
), NULL
)) return NULL
;
308 return info
.TebBaseAddress
;
311 /***********************************************************************
312 * DbgUiConvertStateChangeStructure (NTDLL.@)
314 NTSTATUS WINAPI
DbgUiConvertStateChangeStructure( DBGUI_WAIT_STATE_CHANGE
*state
, DEBUG_EVENT
*event
)
316 event
->dwProcessId
= HandleToULong( state
->AppClientId
.UniqueProcess
);
317 event
->dwThreadId
= HandleToULong( state
->AppClientId
.UniqueThread
);
318 switch (state
->NewState
)
320 case DbgCreateThreadStateChange
:
322 DBGUI_CREATE_THREAD
*info
= &state
->StateInfo
.CreateThread
;
323 event
->dwDebugEventCode
= CREATE_THREAD_DEBUG_EVENT
;
324 event
->u
.CreateThread
.hThread
= info
->HandleToThread
;
325 event
->u
.CreateThread
.lpThreadLocalBase
= get_thread_teb( info
->HandleToThread
);
326 event
->u
.CreateThread
.lpStartAddress
= info
->NewThread
.StartAddress
;
329 case DbgCreateProcessStateChange
:
331 DBGUI_CREATE_PROCESS
*info
= &state
->StateInfo
.CreateProcessInfo
;
332 event
->dwDebugEventCode
= CREATE_PROCESS_DEBUG_EVENT
;
333 event
->u
.CreateProcessInfo
.hFile
= info
->NewProcess
.FileHandle
;
334 event
->u
.CreateProcessInfo
.hProcess
= info
->HandleToProcess
;
335 event
->u
.CreateProcessInfo
.hThread
= info
->HandleToThread
;
336 event
->u
.CreateProcessInfo
.lpBaseOfImage
= info
->NewProcess
.BaseOfImage
;
337 event
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
= info
->NewProcess
.DebugInfoFileOffset
;
338 event
->u
.CreateProcessInfo
.nDebugInfoSize
= info
->NewProcess
.DebugInfoSize
;
339 event
->u
.CreateProcessInfo
.lpThreadLocalBase
= get_thread_teb( info
->HandleToThread
);
340 event
->u
.CreateProcessInfo
.lpStartAddress
= info
->NewProcess
.InitialThread
.StartAddress
;
341 event
->u
.CreateProcessInfo
.lpImageName
= NULL
;
342 event
->u
.CreateProcessInfo
.fUnicode
= TRUE
;
345 case DbgExitThreadStateChange
:
347 DBGKM_EXIT_THREAD
*info
= &state
->StateInfo
.ExitThread
;
348 event
->dwDebugEventCode
= EXIT_THREAD_DEBUG_EVENT
;
349 event
->u
.ExitThread
.dwExitCode
= info
->ExitStatus
;
352 case DbgExitProcessStateChange
:
354 DBGKM_EXIT_PROCESS
*info
= &state
->StateInfo
.ExitProcess
;
355 event
->dwDebugEventCode
= EXIT_PROCESS_DEBUG_EVENT
;
356 event
->u
.ExitProcess
.dwExitCode
= info
->ExitStatus
;
359 case DbgExceptionStateChange
:
360 case DbgBreakpointStateChange
:
361 case DbgSingleStepStateChange
:
363 DBGKM_EXCEPTION
*info
= &state
->StateInfo
.Exception
;
364 DWORD code
= info
->ExceptionRecord
.ExceptionCode
;
365 if (code
== DBG_PRINTEXCEPTION_C
&& info
->ExceptionRecord
.NumberParameters
>= 2)
367 event
->dwDebugEventCode
= OUTPUT_DEBUG_STRING_EVENT
;
368 event
->u
.DebugString
.lpDebugStringData
= (void *)info
->ExceptionRecord
.ExceptionInformation
[1];
369 event
->u
.DebugString
.fUnicode
= FALSE
;
370 event
->u
.DebugString
.nDebugStringLength
= info
->ExceptionRecord
.ExceptionInformation
[0];
372 else if (code
== DBG_RIPEXCEPTION
&& info
->ExceptionRecord
.NumberParameters
>= 2)
374 event
->dwDebugEventCode
= RIP_EVENT
;
375 event
->u
.RipInfo
.dwError
= info
->ExceptionRecord
.ExceptionInformation
[0];
376 event
->u
.RipInfo
.dwType
= info
->ExceptionRecord
.ExceptionInformation
[1];
380 event
->dwDebugEventCode
= EXCEPTION_DEBUG_EVENT
;
381 event
->u
.Exception
.ExceptionRecord
= info
->ExceptionRecord
;
382 event
->u
.Exception
.dwFirstChance
= info
->FirstChance
;
386 case DbgLoadDllStateChange
:
388 DBGKM_LOAD_DLL
*info
= &state
->StateInfo
.LoadDll
;
389 event
->dwDebugEventCode
= LOAD_DLL_DEBUG_EVENT
;
390 event
->u
.LoadDll
.hFile
= info
->FileHandle
;
391 event
->u
.LoadDll
.lpBaseOfDll
= info
->BaseOfDll
;
392 event
->u
.LoadDll
.dwDebugInfoFileOffset
= info
->DebugInfoFileOffset
;
393 event
->u
.LoadDll
.nDebugInfoSize
= info
->DebugInfoSize
;
394 event
->u
.LoadDll
.lpImageName
= info
->NamePointer
;
395 event
->u
.LoadDll
.fUnicode
= TRUE
;
398 case DbgUnloadDllStateChange
:
400 DBGKM_UNLOAD_DLL
*info
= &state
->StateInfo
.UnloadDll
;
401 event
->dwDebugEventCode
= UNLOAD_DLL_DEBUG_EVENT
;
402 event
->u
.UnloadDll
.lpBaseOfDll
= info
->BaseAddress
;
406 return STATUS_UNSUCCESSFUL
;
408 return STATUS_SUCCESS
;
411 /***********************************************************************
412 * DbgUiRemoteBreakin (NTDLL.@)
414 void WINAPI
DbgUiRemoteBreakin( void *arg
)
417 if (NtCurrentTeb()->Peb
->BeingDebugged
)
429 RtlExitUserThread( STATUS_SUCCESS
);
432 /***********************************************************************
433 * DbgUiIssueRemoteBreakin (NTDLL.@)
435 NTSTATUS WINAPI
DbgUiIssueRemoteBreakin( HANDLE process
)
437 return unix_funcs
->DbgUiIssueRemoteBreakin( process
);