maintainers: Update the Direct3D section.
[wine.git] / dlls / ntdll / process.c
blob7b36c988e81f51413ee8dae6bb00887776eaec79
1 /*
2 * NT process handling
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
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include <sys/types.h>
31 #include "ntstatus.h"
32 #define WIN32_NO_STATUS
33 #include "wine/debug.h"
34 #include "windef.h"
35 #include "winternl.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 * RtlWow64EnableFsRedirection (NTDLL.@)
55 NTSTATUS WINAPI RtlWow64EnableFsRedirection( BOOLEAN enable )
57 if (!NtCurrentTeb64()) return STATUS_NOT_IMPLEMENTED;
58 NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR] = !enable;
59 return STATUS_SUCCESS;
63 /******************************************************************
64 * RtlWow64EnableFsRedirectionEx (NTDLL.@)
66 NTSTATUS WINAPI RtlWow64EnableFsRedirectionEx( ULONG disable, ULONG *old_value )
68 if (!NtCurrentTeb64()) return STATUS_NOT_IMPLEMENTED;
70 __TRY
72 *old_value = NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR];
74 __EXCEPT_PAGE_FAULT
76 return STATUS_ACCESS_VIOLATION;
78 __ENDTRY
80 NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR] = disable;
81 return STATUS_SUCCESS;
85 /**********************************************************************
86 * RtlWow64GetCurrentMachine (NTDLL.@)
88 USHORT WINAPI RtlWow64GetCurrentMachine(void)
90 USHORT current, native;
92 RtlWow64GetProcessMachines( GetCurrentProcess(), &current, &native );
93 return current ? current : native;
97 /**********************************************************************
98 * RtlWow64GetProcessMachines (NTDLL.@)
100 NTSTATUS WINAPI RtlWow64GetProcessMachines( HANDLE process, USHORT *current_ret, USHORT *native_ret )
102 ULONG i, machines[8];
103 USHORT current = 0, native = 0;
104 NTSTATUS status;
106 status = NtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, sizeof(process),
107 machines, sizeof(machines), NULL );
108 if (status) return status;
109 for (i = 0; machines[i]; i++)
111 USHORT flags = HIWORD(machines[i]);
112 USHORT machine = LOWORD(machines[i]);
113 if (flags & 4 /* native machine */) native = machine;
114 else if (flags & 8 /* current machine */) current = machine;
116 if (current_ret) *current_ret = current;
117 if (native_ret) *native_ret = native;
118 return status;
122 /**********************************************************************
123 * RtlWow64IsWowGuestMachineSupported (NTDLL.@)
125 NTSTATUS WINAPI RtlWow64IsWowGuestMachineSupported( USHORT machine, BOOLEAN *supported )
127 ULONG i, machines[8];
128 HANDLE process = 0;
129 NTSTATUS status;
131 status = NtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, sizeof(process),
132 machines, sizeof(machines), NULL );
133 if (status) return status;
134 *supported = FALSE;
135 for (i = 0; machines[i]; i++)
137 if (HIWORD(machines[i]) & 4 /* native machine */) continue;
138 if (machine == LOWORD(machines[i])) *supported = TRUE;
140 return status;
144 #ifdef _WIN64
146 /**********************************************************************
147 * RtlWow64GetCpuAreaInfo (NTDLL.@)
149 NTSTATUS WINAPI RtlWow64GetCpuAreaInfo( WOW64_CPURESERVED *cpu, ULONG reserved, WOW64_CPU_AREA_INFO *info )
151 static const struct { ULONG machine, align, size, offset, flag; } data[] =
153 #define ENTRY(machine,type,flag) { machine, TYPE_ALIGNMENT(type), sizeof(type), offsetof(type,ContextFlags), flag },
154 ENTRY( IMAGE_FILE_MACHINE_I386, I386_CONTEXT, CONTEXT_i386 )
155 ENTRY( IMAGE_FILE_MACHINE_AMD64, AMD64_CONTEXT, CONTEXT_AMD64 )
156 ENTRY( IMAGE_FILE_MACHINE_ARMNT, ARM_CONTEXT, CONTEXT_ARM )
157 ENTRY( IMAGE_FILE_MACHINE_ARM64, ARM64_NT_CONTEXT, CONTEXT_ARM64 )
158 #undef ENTRY
160 unsigned int i;
162 for (i = 0; i < ARRAY_SIZE(data); i++)
164 #define ALIGN(ptr,align) ((void *)(((ULONG_PTR)(ptr) + (align) - 1) & ~((align) - 1)))
165 if (data[i].machine != cpu->Machine) continue;
166 info->Context = ALIGN( cpu + 1, data[i].align );
167 info->ContextEx = ALIGN( (char *)info->Context + data[i].size, sizeof(void *) );
168 info->ContextFlagsLocation = (char *)info->Context + data[i].offset;
169 info->ContextFlag = data[i].flag;
170 info->CpuReserved = cpu;
171 info->Machine = data[i].machine;
172 return STATUS_SUCCESS;
173 #undef ALIGN
175 return STATUS_INVALID_PARAMETER;
179 /**********************************************************************
180 * RtlWow64GetCurrentCpuArea (NTDLL.@)
182 NTSTATUS WINAPI RtlWow64GetCurrentCpuArea( USHORT *machine, void **context, void **context_ex )
184 WOW64_CPU_AREA_INFO info;
185 NTSTATUS status;
187 if (!(status = RtlWow64GetCpuAreaInfo( NtCurrentTeb()->TlsSlots[WOW64_TLS_CPURESERVED], 0, &info )))
189 if (machine) *machine = info.Machine;
190 if (context) *context = info.Context;
191 if (context_ex) *context_ex = *(void **)info.ContextEx;
193 return status;
197 /******************************************************************************
198 * RtlWow64GetThreadContext (NTDLL.@)
200 NTSTATUS WINAPI RtlWow64GetThreadContext( HANDLE handle, WOW64_CONTEXT *context )
202 return NtQueryInformationThread( handle, ThreadWow64Context, context, sizeof(*context), NULL );
206 /******************************************************************************
207 * RtlWow64SetThreadContext (NTDLL.@)
209 NTSTATUS WINAPI RtlWow64SetThreadContext( HANDLE handle, const WOW64_CONTEXT *context )
211 return NtSetInformationThread( handle, ThreadWow64Context, context, sizeof(*context) );
214 /******************************************************************************
215 * RtlWow64GetThreadSelectorEntry (NTDLL.@)
217 NTSTATUS WINAPI RtlWow64GetThreadSelectorEntry( HANDLE handle, THREAD_DESCRIPTOR_INFORMATION *info,
218 ULONG size, ULONG *retlen )
220 DWORD sel;
221 WOW64_CONTEXT context = { WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_SEGMENTS };
222 LDT_ENTRY entry = { 0 };
224 if (size != sizeof(*info)) return STATUS_INFO_LENGTH_MISMATCH;
225 if (RtlWow64GetThreadContext( handle, &context ))
227 /* hardcoded values */
228 context.SegCs = 0x23;
229 #ifdef __x86_64__
230 __asm__( "movw %%fs,%0" : "=m" (context.SegFs) );
231 __asm__( "movw %%ss,%0" : "=m" (context.SegSs) );
232 #else
233 context.SegSs = 0x2b;
234 context.SegFs = 0x53;
235 #endif
238 sel = info->Selector | 3;
239 if (sel == 0x03) goto done; /* null selector */
241 /* set common data */
242 entry.HighWord.Bits.Dpl = 3;
243 entry.HighWord.Bits.Pres = 1;
244 entry.HighWord.Bits.Default_Big = 1;
245 if (sel == context.SegCs) /* code selector */
247 entry.LimitLow = 0xffff;
248 entry.HighWord.Bits.LimitHi = 0xf;
249 entry.HighWord.Bits.Type = 0x1b; /* code */
250 entry.HighWord.Bits.Granularity = 1;
252 else if (sel == context.SegSs) /* data selector */
254 entry.LimitLow = 0xffff;
255 entry.HighWord.Bits.LimitHi = 0xf;
256 entry.HighWord.Bits.Type = 0x13; /* data */
257 entry.HighWord.Bits.Granularity = 1;
259 else if (sel == context.SegFs) /* TEB selector */
261 THREAD_BASIC_INFORMATION tbi;
263 entry.LimitLow = 0xfff;
264 entry.HighWord.Bits.Type = 0x13; /* data */
265 if (!NtQueryInformationThread( handle, ThreadBasicInformation, &tbi, sizeof(tbi), NULL ))
267 ULONG addr = (ULONG_PTR)tbi.TebBaseAddress + 0x2000; /* 32-bit teb offset */
268 entry.BaseLow = addr;
269 entry.HighWord.Bytes.BaseMid = addr >> 16;
270 entry.HighWord.Bytes.BaseHi = addr >> 24;
273 else return STATUS_UNSUCCESSFUL;
275 done:
276 info->Entry = entry;
277 if (retlen) *retlen = sizeof(entry);
278 return STATUS_SUCCESS;
281 #endif
283 /**********************************************************************
284 * RtlCreateUserProcess (NTDLL.@)
286 NTSTATUS WINAPI RtlCreateUserProcess( UNICODE_STRING *path, ULONG attributes,
287 RTL_USER_PROCESS_PARAMETERS *params,
288 SECURITY_DESCRIPTOR *process_descr,
289 SECURITY_DESCRIPTOR *thread_descr,
290 HANDLE parent, BOOLEAN inherit, HANDLE debug, HANDLE token,
291 RTL_USER_PROCESS_INFORMATION *info )
293 OBJECT_ATTRIBUTES process_attr, thread_attr;
294 PS_CREATE_INFO create_info;
295 ULONG_PTR buffer[offsetof( PS_ATTRIBUTE_LIST, Attributes[6] ) / sizeof(ULONG_PTR)];
296 PS_ATTRIBUTE_LIST *attr = (PS_ATTRIBUTE_LIST *)buffer;
297 UINT pos = 0;
299 RtlNormalizeProcessParams( params );
301 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_IMAGE_NAME;
302 attr->Attributes[pos].Size = path->Length;
303 attr->Attributes[pos].ValuePtr = path->Buffer;
304 attr->Attributes[pos].ReturnLength = NULL;
305 pos++;
306 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_CLIENT_ID;
307 attr->Attributes[pos].Size = sizeof(info->ClientId);
308 attr->Attributes[pos].ValuePtr = &info->ClientId;
309 attr->Attributes[pos].ReturnLength = NULL;
310 pos++;
311 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_IMAGE_INFO;
312 attr->Attributes[pos].Size = sizeof(info->ImageInformation);
313 attr->Attributes[pos].ValuePtr = &info->ImageInformation;
314 attr->Attributes[pos].ReturnLength = NULL;
315 pos++;
316 if (parent)
318 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_PARENT_PROCESS;
319 attr->Attributes[pos].Size = sizeof(parent);
320 attr->Attributes[pos].ValuePtr = parent;
321 attr->Attributes[pos].ReturnLength = NULL;
322 pos++;
324 if (debug)
326 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_DEBUG_PORT;
327 attr->Attributes[pos].Size = sizeof(debug);
328 attr->Attributes[pos].ValuePtr = debug;
329 attr->Attributes[pos].ReturnLength = NULL;
330 pos++;
332 if (token)
334 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_TOKEN;
335 attr->Attributes[pos].Size = sizeof(token);
336 attr->Attributes[pos].ValuePtr = token;
337 attr->Attributes[pos].ReturnLength = NULL;
338 pos++;
340 attr->TotalLength = offsetof( PS_ATTRIBUTE_LIST, Attributes[pos] );
342 InitializeObjectAttributes( &process_attr, NULL, 0, NULL, process_descr );
343 InitializeObjectAttributes( &thread_attr, NULL, 0, NULL, thread_descr );
345 return NtCreateUserProcess( &info->Process, &info->Thread, PROCESS_ALL_ACCESS, THREAD_ALL_ACCESS,
346 &process_attr, &thread_attr,
347 inherit ? PROCESS_CREATE_FLAGS_INHERIT_HANDLES : 0,
348 THREAD_CREATE_FLAGS_CREATE_SUSPENDED, params,
349 &create_info, attr );
352 /***********************************************************************
353 * DbgUiGetThreadDebugObject (NTDLL.@)
355 HANDLE WINAPI DbgUiGetThreadDebugObject(void)
357 return NtCurrentTeb()->DbgSsReserved[1];
360 /***********************************************************************
361 * DbgUiSetThreadDebugObject (NTDLL.@)
363 void WINAPI DbgUiSetThreadDebugObject( HANDLE handle )
365 NtCurrentTeb()->DbgSsReserved[1] = handle;
368 /***********************************************************************
369 * DbgUiConnectToDbg (NTDLL.@)
371 NTSTATUS WINAPI DbgUiConnectToDbg(void)
373 HANDLE handle;
374 NTSTATUS status;
375 OBJECT_ATTRIBUTES attr = { sizeof(attr) };
377 if (DbgUiGetThreadDebugObject()) return STATUS_SUCCESS; /* already connected */
379 status = NtCreateDebugObject( &handle, DEBUG_ALL_ACCESS, &attr, DEBUG_KILL_ON_CLOSE );
380 if (!status) DbgUiSetThreadDebugObject( handle );
381 return status;
384 /***********************************************************************
385 * DbgUiDebugActiveProcess (NTDLL.@)
387 NTSTATUS WINAPI DbgUiDebugActiveProcess( HANDLE process )
389 NTSTATUS status;
391 if ((status = NtDebugActiveProcess( process, DbgUiGetThreadDebugObject() ))) return status;
392 if ((status = DbgUiIssueRemoteBreakin( process ))) DbgUiStopDebugging( process );
393 return status;
396 /***********************************************************************
397 * DbgUiStopDebugging (NTDLL.@)
399 NTSTATUS WINAPI DbgUiStopDebugging( HANDLE process )
401 return NtRemoveProcessDebug( process, DbgUiGetThreadDebugObject() );
404 /***********************************************************************
405 * DbgUiContinue (NTDLL.@)
407 NTSTATUS WINAPI DbgUiContinue( CLIENT_ID *client, NTSTATUS status )
409 return NtDebugContinue( DbgUiGetThreadDebugObject(), client, status );
412 /***********************************************************************
413 * DbgUiWaitStateChange (NTDLL.@)
415 NTSTATUS WINAPI DbgUiWaitStateChange( DBGUI_WAIT_STATE_CHANGE *state, LARGE_INTEGER *timeout )
417 return NtWaitForDebugEvent( DbgUiGetThreadDebugObject(), TRUE, timeout, state );
420 /* helper for DbgUiConvertStateChangeStructure */
421 static inline void *get_thread_teb( HANDLE thread )
423 THREAD_BASIC_INFORMATION info;
425 if (NtQueryInformationThread( thread, ThreadBasicInformation, &info, sizeof(info), NULL )) return NULL;
426 return info.TebBaseAddress;
429 /***********************************************************************
430 * DbgUiConvertStateChangeStructure (NTDLL.@)
432 NTSTATUS WINAPI DbgUiConvertStateChangeStructure( DBGUI_WAIT_STATE_CHANGE *state, DEBUG_EVENT *event )
434 event->dwProcessId = HandleToULong( state->AppClientId.UniqueProcess );
435 event->dwThreadId = HandleToULong( state->AppClientId.UniqueThread );
436 switch (state->NewState)
438 case DbgCreateThreadStateChange:
440 DBGUI_CREATE_THREAD *info = &state->StateInfo.CreateThread;
441 event->dwDebugEventCode = CREATE_THREAD_DEBUG_EVENT;
442 event->u.CreateThread.hThread = info->HandleToThread;
443 event->u.CreateThread.lpThreadLocalBase = get_thread_teb( info->HandleToThread );
444 event->u.CreateThread.lpStartAddress = info->NewThread.StartAddress;
445 break;
447 case DbgCreateProcessStateChange:
449 DBGUI_CREATE_PROCESS *info = &state->StateInfo.CreateProcessInfo;
450 event->dwDebugEventCode = CREATE_PROCESS_DEBUG_EVENT;
451 event->u.CreateProcessInfo.hFile = info->NewProcess.FileHandle;
452 event->u.CreateProcessInfo.hProcess = info->HandleToProcess;
453 event->u.CreateProcessInfo.hThread = info->HandleToThread;
454 event->u.CreateProcessInfo.lpBaseOfImage = info->NewProcess.BaseOfImage;
455 event->u.CreateProcessInfo.dwDebugInfoFileOffset = info->NewProcess.DebugInfoFileOffset;
456 event->u.CreateProcessInfo.nDebugInfoSize = info->NewProcess.DebugInfoSize;
457 event->u.CreateProcessInfo.lpThreadLocalBase = get_thread_teb( info->HandleToThread );
458 event->u.CreateProcessInfo.lpStartAddress = info->NewProcess.InitialThread.StartAddress;
459 event->u.CreateProcessInfo.lpImageName = NULL;
460 event->u.CreateProcessInfo.fUnicode = TRUE;
461 break;
463 case DbgExitThreadStateChange:
465 DBGKM_EXIT_THREAD *info = &state->StateInfo.ExitThread;
466 event->dwDebugEventCode = EXIT_THREAD_DEBUG_EVENT;
467 event->u.ExitThread.dwExitCode = info->ExitStatus;
468 break;
470 case DbgExitProcessStateChange:
472 DBGKM_EXIT_PROCESS *info = &state->StateInfo.ExitProcess;
473 event->dwDebugEventCode = EXIT_PROCESS_DEBUG_EVENT;
474 event->u.ExitProcess.dwExitCode = info->ExitStatus;
475 break;
477 case DbgExceptionStateChange:
478 case DbgBreakpointStateChange:
479 case DbgSingleStepStateChange:
481 DBGKM_EXCEPTION *info = &state->StateInfo.Exception;
482 DWORD code = info->ExceptionRecord.ExceptionCode;
483 if (code == DBG_PRINTEXCEPTION_C && info->ExceptionRecord.NumberParameters >= 2)
485 event->dwDebugEventCode = OUTPUT_DEBUG_STRING_EVENT;
486 event->u.DebugString.lpDebugStringData = (void *)info->ExceptionRecord.ExceptionInformation[1];
487 event->u.DebugString.fUnicode = FALSE;
488 event->u.DebugString.nDebugStringLength = info->ExceptionRecord.ExceptionInformation[0];
490 else if (code == DBG_RIPEXCEPTION && info->ExceptionRecord.NumberParameters >= 2)
492 event->dwDebugEventCode = RIP_EVENT;
493 event->u.RipInfo.dwError = info->ExceptionRecord.ExceptionInformation[0];
494 event->u.RipInfo.dwType = info->ExceptionRecord.ExceptionInformation[1];
496 else
498 event->dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
499 event->u.Exception.ExceptionRecord = info->ExceptionRecord;
500 event->u.Exception.dwFirstChance = info->FirstChance;
502 break;
504 case DbgLoadDllStateChange:
506 DBGKM_LOAD_DLL *info = &state->StateInfo.LoadDll;
507 event->dwDebugEventCode = LOAD_DLL_DEBUG_EVENT;
508 event->u.LoadDll.hFile = info->FileHandle;
509 event->u.LoadDll.lpBaseOfDll = info->BaseOfDll;
510 event->u.LoadDll.dwDebugInfoFileOffset = info->DebugInfoFileOffset;
511 event->u.LoadDll.nDebugInfoSize = info->DebugInfoSize;
512 event->u.LoadDll.lpImageName = info->NamePointer;
513 event->u.LoadDll.fUnicode = TRUE;
514 break;
516 case DbgUnloadDllStateChange:
518 DBGKM_UNLOAD_DLL *info = &state->StateInfo.UnloadDll;
519 event->dwDebugEventCode = UNLOAD_DLL_DEBUG_EVENT;
520 event->u.UnloadDll.lpBaseOfDll = info->BaseAddress;
521 break;
523 default:
524 return STATUS_UNSUCCESSFUL;
526 return STATUS_SUCCESS;
529 /***********************************************************************
530 * DbgUiRemoteBreakin (NTDLL.@)
532 void WINAPI DbgUiRemoteBreakin( void *arg )
534 TRACE( "\n" );
535 if (NtCurrentTeb()->Peb->BeingDebugged)
537 __TRY
539 DbgBreakPoint();
541 __EXCEPT_ALL
543 /* do nothing */
545 __ENDTRY
547 RtlExitUserThread( STATUS_SUCCESS );
550 /***********************************************************************
551 * DbgUiIssueRemoteBreakin (NTDLL.@)
553 NTSTATUS WINAPI DbgUiIssueRemoteBreakin( HANDLE process )
555 HANDLE handle;
556 NTSTATUS status;
557 OBJECT_ATTRIBUTES attr = { sizeof(attr) };
559 status = NtCreateThreadEx( &handle, THREAD_ALL_ACCESS, &attr, process,
560 DbgUiRemoteBreakin, NULL, 0, 0, 0, 0, NULL );
561 #ifdef _WIN64
562 /* FIXME: hack for debugging 32-bit wow64 process without a 64-bit ntdll */
563 if (status == STATUS_INVALID_PARAMETER)
565 ULONG_PTR wow;
566 if (!NtQueryInformationProcess( process, ProcessWow64Information, &wow, sizeof(wow), NULL ) && wow)
567 status = NtCreateThreadEx( &handle, THREAD_ALL_ACCESS, &attr, process,
568 (void *)0x7ffe1000, NULL, 0, 0, 0, 0, NULL );
570 #endif
571 if (!status) NtClose( handle );
572 return status;