gdiplus: In GdipImageSelectActiveFrame rely on codec->select_func() to fail.
[wine.git] / dlls / ntdll / process.c
blob4ddf3ad59bd5f57a672d42ee47493cc7931c462e
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 * RtlIsCurrentProcess (NTDLL.@)
55 BOOLEAN WINAPI RtlIsCurrentProcess( HANDLE handle )
57 return handle == NtCurrentProcess() || !NtCompareObjects( handle, NtCurrentProcess() );
61 /******************************************************************
62 * RtlWow64EnableFsRedirection (NTDLL.@)
64 NTSTATUS WINAPI RtlWow64EnableFsRedirection( BOOLEAN enable )
66 if (!NtCurrentTeb64()) return STATUS_NOT_IMPLEMENTED;
67 NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR] = !enable;
68 return STATUS_SUCCESS;
72 /******************************************************************
73 * RtlWow64EnableFsRedirectionEx (NTDLL.@)
75 NTSTATUS WINAPI RtlWow64EnableFsRedirectionEx( ULONG disable, ULONG *old_value )
77 if (!NtCurrentTeb64()) return STATUS_NOT_IMPLEMENTED;
79 __TRY
81 *old_value = NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR];
83 __EXCEPT_PAGE_FAULT
85 return STATUS_ACCESS_VIOLATION;
87 __ENDTRY
89 NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR] = disable;
90 return STATUS_SUCCESS;
94 /**********************************************************************
95 * RtlWow64GetCurrentMachine (NTDLL.@)
97 USHORT WINAPI RtlWow64GetCurrentMachine(void)
99 USHORT current, native;
101 RtlWow64GetProcessMachines( GetCurrentProcess(), &current, &native );
102 return current ? current : native;
106 /**********************************************************************
107 * RtlWow64GetProcessMachines (NTDLL.@)
109 NTSTATUS WINAPI RtlWow64GetProcessMachines( HANDLE process, USHORT *current_ret, USHORT *native_ret )
111 ULONG i, machines[8];
112 USHORT current = 0, native = 0;
113 NTSTATUS status;
115 status = NtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, sizeof(process),
116 machines, sizeof(machines), NULL );
117 if (status) return status;
118 for (i = 0; machines[i]; i++)
120 USHORT flags = HIWORD(machines[i]);
121 USHORT machine = LOWORD(machines[i]);
122 if (flags & 4 /* native machine */) native = machine;
123 else if (flags & 8 /* current machine */) current = machine;
125 if (current_ret) *current_ret = current;
126 if (native_ret) *native_ret = native;
127 return status;
131 /**********************************************************************
132 * RtlWow64GetSharedInfoProcess (NTDLL.@)
134 NTSTATUS WINAPI RtlWow64GetSharedInfoProcess( HANDLE process, BOOLEAN *is_wow64, WOW64INFO *info )
136 PEB32 *peb32;
137 NTSTATUS status = NtQueryInformationProcess( process, ProcessWow64Information,
138 &peb32, sizeof(peb32), NULL );
139 if (status) return status;
140 if (peb32) status = NtReadVirtualMemory( process, peb32 + 1, info, sizeof(*info), NULL );
141 *is_wow64 = !!peb32;
142 return status;
146 /**********************************************************************
147 * RtlWow64IsWowGuestMachineSupported (NTDLL.@)
149 NTSTATUS WINAPI RtlWow64IsWowGuestMachineSupported( USHORT machine, BOOLEAN *supported )
151 ULONG i, machines[8];
152 HANDLE process = 0;
153 NTSTATUS status;
155 status = NtQuerySystemInformationEx( SystemSupportedProcessorArchitectures, &process, sizeof(process),
156 machines, sizeof(machines), NULL );
157 if (status) return status;
158 *supported = FALSE;
159 for (i = 0; machines[i]; i++)
161 if (HIWORD(machines[i]) & 4 /* native machine */) continue;
162 if (machine == LOWORD(machines[i])) *supported = TRUE;
164 return status;
168 #ifdef _WIN64
170 /**********************************************************************
171 * RtlWow64GetCpuAreaInfo (NTDLL.@)
173 NTSTATUS WINAPI RtlWow64GetCpuAreaInfo( WOW64_CPURESERVED *cpu, ULONG reserved, WOW64_CPU_AREA_INFO *info )
175 static const struct { ULONG machine, align, size, offset, flag; } data[] =
177 #define ENTRY(machine,type,flag) { machine, TYPE_ALIGNMENT(type), sizeof(type), offsetof(type,ContextFlags), flag },
178 ENTRY( IMAGE_FILE_MACHINE_I386, I386_CONTEXT, CONTEXT_i386 )
179 ENTRY( IMAGE_FILE_MACHINE_AMD64, AMD64_CONTEXT, CONTEXT_AMD64 )
180 ENTRY( IMAGE_FILE_MACHINE_ARMNT, ARM_CONTEXT, CONTEXT_ARM )
181 ENTRY( IMAGE_FILE_MACHINE_ARM64, ARM64_NT_CONTEXT, CONTEXT_ARM64 )
182 #undef ENTRY
184 unsigned int i;
186 for (i = 0; i < ARRAY_SIZE(data); i++)
188 #define ALIGN(ptr,align) ((void *)(((ULONG_PTR)(ptr) + (align) - 1) & ~((ULONG_PTR)(align) - 1)))
189 if (data[i].machine != cpu->Machine) continue;
190 info->Context = ALIGN( cpu + 1, data[i].align );
191 info->ContextEx = ALIGN( (char *)info->Context + data[i].size, sizeof(void *) );
192 info->ContextFlagsLocation = (char *)info->Context + data[i].offset;
193 info->ContextFlag = data[i].flag;
194 info->CpuReserved = cpu;
195 info->Machine = data[i].machine;
196 return STATUS_SUCCESS;
197 #undef ALIGN
199 return STATUS_INVALID_PARAMETER;
203 /**********************************************************************
204 * RtlWow64GetCurrentCpuArea (NTDLL.@)
206 NTSTATUS WINAPI RtlWow64GetCurrentCpuArea( USHORT *machine, void **context, void **context_ex )
208 WOW64_CPU_AREA_INFO info;
209 NTSTATUS status;
211 if (!(status = RtlWow64GetCpuAreaInfo( NtCurrentTeb()->TlsSlots[WOW64_TLS_CPURESERVED], 0, &info )))
213 if (machine) *machine = info.Machine;
214 if (context) *context = info.Context;
215 if (context_ex) *context_ex = *(void **)info.ContextEx;
217 return status;
221 /******************************************************************************
222 * RtlWow64GetThreadContext (NTDLL.@)
224 NTSTATUS WINAPI RtlWow64GetThreadContext( HANDLE handle, WOW64_CONTEXT *context )
226 return NtQueryInformationThread( handle, ThreadWow64Context, context, sizeof(*context), NULL );
230 /******************************************************************************
231 * RtlWow64SetThreadContext (NTDLL.@)
233 NTSTATUS WINAPI RtlWow64SetThreadContext( HANDLE handle, const WOW64_CONTEXT *context )
235 return NtSetInformationThread( handle, ThreadWow64Context, context, sizeof(*context) );
238 /******************************************************************************
239 * RtlWow64GetThreadSelectorEntry (NTDLL.@)
241 NTSTATUS WINAPI RtlWow64GetThreadSelectorEntry( HANDLE handle, THREAD_DESCRIPTOR_INFORMATION *info,
242 ULONG size, ULONG *retlen )
244 DWORD sel;
245 WOW64_CONTEXT context = { WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_SEGMENTS };
246 LDT_ENTRY entry = { 0 };
248 if (size != sizeof(*info)) return STATUS_INFO_LENGTH_MISMATCH;
249 if (RtlWow64GetThreadContext( handle, &context ))
251 /* hardcoded values */
252 context.SegCs = 0x23;
253 #ifdef __x86_64__
254 __asm__( "movw %%fs,%0" : "=m" (context.SegFs) );
255 __asm__( "movw %%ss,%0" : "=m" (context.SegSs) );
256 #else
257 context.SegSs = 0x2b;
258 context.SegFs = 0x53;
259 #endif
262 sel = info->Selector | 3;
263 if (sel == 0x03) goto done; /* null selector */
265 /* set common data */
266 entry.HighWord.Bits.Dpl = 3;
267 entry.HighWord.Bits.Pres = 1;
268 entry.HighWord.Bits.Default_Big = 1;
269 if (sel == context.SegCs) /* code selector */
271 entry.LimitLow = 0xffff;
272 entry.HighWord.Bits.LimitHi = 0xf;
273 entry.HighWord.Bits.Type = 0x1b; /* code */
274 entry.HighWord.Bits.Granularity = 1;
276 else if (sel == context.SegSs) /* data selector */
278 entry.LimitLow = 0xffff;
279 entry.HighWord.Bits.LimitHi = 0xf;
280 entry.HighWord.Bits.Type = 0x13; /* data */
281 entry.HighWord.Bits.Granularity = 1;
283 else if (sel == context.SegFs) /* TEB selector */
285 THREAD_BASIC_INFORMATION tbi;
287 entry.LimitLow = 0xfff;
288 entry.HighWord.Bits.Type = 0x13; /* data */
289 if (!NtQueryInformationThread( handle, ThreadBasicInformation, &tbi, sizeof(tbi), NULL ))
291 ULONG addr = (ULONG_PTR)tbi.TebBaseAddress + 0x2000; /* 32-bit teb offset */
292 entry.BaseLow = addr;
293 entry.HighWord.Bytes.BaseMid = addr >> 16;
294 entry.HighWord.Bytes.BaseHi = addr >> 24;
297 else return STATUS_UNSUCCESSFUL;
299 done:
300 info->Entry = entry;
301 if (retlen) *retlen = sizeof(entry);
302 return STATUS_SUCCESS;
306 /**********************************************************************
307 * RtlOpenCrossProcessEmulatorWorkConnection (NTDLL.@)
309 void WINAPI RtlOpenCrossProcessEmulatorWorkConnection( HANDLE process, HANDLE *section, void **addr )
311 WOW64INFO wow64info;
312 BOOLEAN is_wow64;
313 SIZE_T size = 0;
315 *addr = NULL;
316 *section = 0;
318 if (RtlWow64GetSharedInfoProcess( process, &is_wow64, &wow64info )) return;
319 if (!is_wow64) return;
320 if (!wow64info.SectionHandle) return;
322 if (NtDuplicateObject( process, (HANDLE)(ULONG_PTR)wow64info.SectionHandle,
323 GetCurrentProcess(), section, 0, 0, DUPLICATE_SAME_ACCESS ))
324 return;
326 if (!NtMapViewOfSection( *section, GetCurrentProcess(), addr, 0, 0, NULL,
327 &size, ViewShare, 0, PAGE_READWRITE )) return;
329 NtClose( *section );
330 *section = 0;
334 /**********************************************************************
335 * RtlWow64PopAllCrossProcessWorkFromWorkList (NTDLL.@)
337 CROSS_PROCESS_WORK_ENTRY * WINAPI RtlWow64PopAllCrossProcessWorkFromWorkList( CROSS_PROCESS_WORK_HDR *list, BOOLEAN *flush )
339 CROSS_PROCESS_WORK_HDR prev, new;
340 UINT pos, prev_pos = 0;
344 prev.hdr = list->hdr;
345 if (!prev.first) break;
346 new.first = 0;
347 new.counter = prev.counter + 1;
348 } while (InterlockedCompareExchange64( &list->hdr, new.hdr, prev.hdr ) != prev.hdr);
350 *flush = (prev.first & CROSS_PROCESS_LIST_FLUSH) != 0;
351 if (!(pos = prev.first & ~CROSS_PROCESS_LIST_FLUSH)) return NULL;
353 /* reverse the list */
355 for (;;)
357 CROSS_PROCESS_WORK_ENTRY *entry = CROSS_PROCESS_LIST_ENTRY( list, pos );
358 UINT next = entry->next;
359 entry->next = prev_pos;
360 if (!next) return entry;
361 prev_pos = pos;
362 pos = next;
367 /**********************************************************************
368 * RtlWow64PopCrossProcessWorkFromFreeList (NTDLL.@)
370 CROSS_PROCESS_WORK_ENTRY * WINAPI RtlWow64PopCrossProcessWorkFromFreeList( CROSS_PROCESS_WORK_HDR *list )
372 CROSS_PROCESS_WORK_ENTRY *ret;
373 CROSS_PROCESS_WORK_HDR prev, new;
377 prev.hdr = list->hdr;
378 if (!prev.first) return NULL;
379 ret = CROSS_PROCESS_LIST_ENTRY( list, prev.first );
380 new.first = ret->next;
381 new.counter = prev.counter + 1;
382 } while (InterlockedCompareExchange64( &list->hdr, new.hdr, prev.hdr ) != prev.hdr);
384 ret->next = 0;
385 return ret;
389 /**********************************************************************
390 * RtlWow64PushCrossProcessWorkOntoFreeList (NTDLL.@)
392 BOOLEAN WINAPI RtlWow64PushCrossProcessWorkOntoFreeList( CROSS_PROCESS_WORK_HDR *list, CROSS_PROCESS_WORK_ENTRY *entry )
394 CROSS_PROCESS_WORK_HDR prev, new;
398 prev.hdr = list->hdr;
399 entry->next = prev.first;
400 new.first = (char *)entry - (char *)list;
401 new.counter = prev.counter + 1;
402 } while (InterlockedCompareExchange64( &list->hdr, new.hdr, prev.hdr ) != prev.hdr);
404 return TRUE;
408 /**********************************************************************
409 * RtlWow64PushCrossProcessWorkOntoWorkList (NTDLL.@)
411 BOOLEAN WINAPI RtlWow64PushCrossProcessWorkOntoWorkList( CROSS_PROCESS_WORK_HDR *list, CROSS_PROCESS_WORK_ENTRY *entry, void **unknown )
413 CROSS_PROCESS_WORK_HDR prev, new;
415 *unknown = NULL;
418 prev.hdr = list->hdr;
419 entry->next = prev.first;
420 new.first = ((char *)entry - (char *)list) | (prev.first & CROSS_PROCESS_LIST_FLUSH);
421 new.counter = prev.counter + 1;
422 } while (InterlockedCompareExchange64( &list->hdr, new.hdr, prev.hdr ) != prev.hdr);
424 return TRUE;
428 /**********************************************************************
429 * RtlWow64RequestCrossProcessHeavyFlush (NTDLL.@)
431 BOOLEAN WINAPI RtlWow64RequestCrossProcessHeavyFlush( CROSS_PROCESS_WORK_HDR *list )
433 CROSS_PROCESS_WORK_HDR prev, new;
437 prev.hdr = list->hdr;
438 new.first = prev.first | CROSS_PROCESS_LIST_FLUSH;
439 new.counter = prev.counter + 1;
440 } while (InterlockedCompareExchange64( &list->hdr, new.hdr, prev.hdr ) != prev.hdr);
442 return TRUE;
445 #endif /* _WIN64 */
447 /**********************************************************************
448 * RtlCreateUserProcess (NTDLL.@)
450 NTSTATUS WINAPI RtlCreateUserProcess( UNICODE_STRING *path, ULONG attributes,
451 RTL_USER_PROCESS_PARAMETERS *params,
452 SECURITY_DESCRIPTOR *process_descr,
453 SECURITY_DESCRIPTOR *thread_descr,
454 HANDLE parent, BOOLEAN inherit, HANDLE debug, HANDLE token,
455 RTL_USER_PROCESS_INFORMATION *info )
457 OBJECT_ATTRIBUTES process_attr, thread_attr;
458 PS_CREATE_INFO create_info;
459 ULONG_PTR buffer[offsetof( PS_ATTRIBUTE_LIST, Attributes[6] ) / sizeof(ULONG_PTR)];
460 PS_ATTRIBUTE_LIST *attr = (PS_ATTRIBUTE_LIST *)buffer;
461 UINT pos = 0;
463 RtlNormalizeProcessParams( params );
465 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_IMAGE_NAME;
466 attr->Attributes[pos].Size = path->Length;
467 attr->Attributes[pos].ValuePtr = path->Buffer;
468 attr->Attributes[pos].ReturnLength = NULL;
469 pos++;
470 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_CLIENT_ID;
471 attr->Attributes[pos].Size = sizeof(info->ClientId);
472 attr->Attributes[pos].ValuePtr = &info->ClientId;
473 attr->Attributes[pos].ReturnLength = NULL;
474 pos++;
475 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_IMAGE_INFO;
476 attr->Attributes[pos].Size = sizeof(info->ImageInformation);
477 attr->Attributes[pos].ValuePtr = &info->ImageInformation;
478 attr->Attributes[pos].ReturnLength = NULL;
479 pos++;
480 if (parent)
482 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_PARENT_PROCESS;
483 attr->Attributes[pos].Size = sizeof(parent);
484 attr->Attributes[pos].ValuePtr = parent;
485 attr->Attributes[pos].ReturnLength = NULL;
486 pos++;
488 if (debug)
490 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_DEBUG_PORT;
491 attr->Attributes[pos].Size = sizeof(debug);
492 attr->Attributes[pos].ValuePtr = debug;
493 attr->Attributes[pos].ReturnLength = NULL;
494 pos++;
496 if (token)
498 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_TOKEN;
499 attr->Attributes[pos].Size = sizeof(token);
500 attr->Attributes[pos].ValuePtr = token;
501 attr->Attributes[pos].ReturnLength = NULL;
502 pos++;
504 attr->TotalLength = offsetof( PS_ATTRIBUTE_LIST, Attributes[pos] );
506 InitializeObjectAttributes( &process_attr, NULL, 0, NULL, process_descr );
507 InitializeObjectAttributes( &thread_attr, NULL, 0, NULL, thread_descr );
509 return NtCreateUserProcess( &info->Process, &info->Thread, PROCESS_ALL_ACCESS, THREAD_ALL_ACCESS,
510 &process_attr, &thread_attr,
511 inherit ? PROCESS_CREATE_FLAGS_INHERIT_HANDLES : 0,
512 THREAD_CREATE_FLAGS_CREATE_SUSPENDED, params,
513 &create_info, attr );
516 /***********************************************************************
517 * DbgUiGetThreadDebugObject (NTDLL.@)
519 HANDLE WINAPI DbgUiGetThreadDebugObject(void)
521 return NtCurrentTeb()->DbgSsReserved[1];
524 /***********************************************************************
525 * DbgUiSetThreadDebugObject (NTDLL.@)
527 void WINAPI DbgUiSetThreadDebugObject( HANDLE handle )
529 NtCurrentTeb()->DbgSsReserved[1] = handle;
532 /***********************************************************************
533 * DbgUiConnectToDbg (NTDLL.@)
535 NTSTATUS WINAPI DbgUiConnectToDbg(void)
537 HANDLE handle;
538 NTSTATUS status;
539 OBJECT_ATTRIBUTES attr = { sizeof(attr) };
541 if (DbgUiGetThreadDebugObject()) return STATUS_SUCCESS; /* already connected */
543 status = NtCreateDebugObject( &handle, DEBUG_ALL_ACCESS, &attr, DEBUG_KILL_ON_CLOSE );
544 if (!status) DbgUiSetThreadDebugObject( handle );
545 return status;
548 /***********************************************************************
549 * DbgUiDebugActiveProcess (NTDLL.@)
551 NTSTATUS WINAPI DbgUiDebugActiveProcess( HANDLE process )
553 NTSTATUS status;
555 if ((status = NtDebugActiveProcess( process, DbgUiGetThreadDebugObject() ))) return status;
556 if ((status = DbgUiIssueRemoteBreakin( process ))) DbgUiStopDebugging( process );
557 return status;
560 /***********************************************************************
561 * DbgUiStopDebugging (NTDLL.@)
563 NTSTATUS WINAPI DbgUiStopDebugging( HANDLE process )
565 return NtRemoveProcessDebug( process, DbgUiGetThreadDebugObject() );
568 /***********************************************************************
569 * DbgUiContinue (NTDLL.@)
571 NTSTATUS WINAPI DbgUiContinue( CLIENT_ID *client, NTSTATUS status )
573 return NtDebugContinue( DbgUiGetThreadDebugObject(), client, status );
576 /***********************************************************************
577 * DbgUiWaitStateChange (NTDLL.@)
579 NTSTATUS WINAPI DbgUiWaitStateChange( DBGUI_WAIT_STATE_CHANGE *state, LARGE_INTEGER *timeout )
581 return NtWaitForDebugEvent( DbgUiGetThreadDebugObject(), TRUE, timeout, state );
584 /* helper for DbgUiConvertStateChangeStructure */
585 static inline void *get_thread_teb( HANDLE thread )
587 THREAD_BASIC_INFORMATION info;
589 if (NtQueryInformationThread( thread, ThreadBasicInformation, &info, sizeof(info), NULL )) return NULL;
590 return info.TebBaseAddress;
593 /***********************************************************************
594 * DbgUiConvertStateChangeStructure (NTDLL.@)
596 NTSTATUS WINAPI DbgUiConvertStateChangeStructure( DBGUI_WAIT_STATE_CHANGE *state, DEBUG_EVENT *event )
598 event->dwProcessId = HandleToULong( state->AppClientId.UniqueProcess );
599 event->dwThreadId = HandleToULong( state->AppClientId.UniqueThread );
600 switch (state->NewState)
602 case DbgCreateThreadStateChange:
604 DBGUI_CREATE_THREAD *info = &state->StateInfo.CreateThread;
605 event->dwDebugEventCode = CREATE_THREAD_DEBUG_EVENT;
606 event->u.CreateThread.hThread = info->HandleToThread;
607 event->u.CreateThread.lpThreadLocalBase = get_thread_teb( info->HandleToThread );
608 event->u.CreateThread.lpStartAddress = info->NewThread.StartAddress;
609 break;
611 case DbgCreateProcessStateChange:
613 DBGUI_CREATE_PROCESS *info = &state->StateInfo.CreateProcessInfo;
614 event->dwDebugEventCode = CREATE_PROCESS_DEBUG_EVENT;
615 event->u.CreateProcessInfo.hFile = info->NewProcess.FileHandle;
616 event->u.CreateProcessInfo.hProcess = info->HandleToProcess;
617 event->u.CreateProcessInfo.hThread = info->HandleToThread;
618 event->u.CreateProcessInfo.lpBaseOfImage = info->NewProcess.BaseOfImage;
619 event->u.CreateProcessInfo.dwDebugInfoFileOffset = info->NewProcess.DebugInfoFileOffset;
620 event->u.CreateProcessInfo.nDebugInfoSize = info->NewProcess.DebugInfoSize;
621 event->u.CreateProcessInfo.lpThreadLocalBase = get_thread_teb( info->HandleToThread );
622 event->u.CreateProcessInfo.lpStartAddress = info->NewProcess.InitialThread.StartAddress;
623 event->u.CreateProcessInfo.lpImageName = NULL;
624 event->u.CreateProcessInfo.fUnicode = TRUE;
625 break;
627 case DbgExitThreadStateChange:
629 DBGKM_EXIT_THREAD *info = &state->StateInfo.ExitThread;
630 event->dwDebugEventCode = EXIT_THREAD_DEBUG_EVENT;
631 event->u.ExitThread.dwExitCode = info->ExitStatus;
632 break;
634 case DbgExitProcessStateChange:
636 DBGKM_EXIT_PROCESS *info = &state->StateInfo.ExitProcess;
637 event->dwDebugEventCode = EXIT_PROCESS_DEBUG_EVENT;
638 event->u.ExitProcess.dwExitCode = info->ExitStatus;
639 break;
641 case DbgExceptionStateChange:
642 case DbgBreakpointStateChange:
643 case DbgSingleStepStateChange:
645 DBGKM_EXCEPTION *info = &state->StateInfo.Exception;
646 DWORD code = info->ExceptionRecord.ExceptionCode;
647 if (code == DBG_PRINTEXCEPTION_C && info->ExceptionRecord.NumberParameters >= 2)
649 event->dwDebugEventCode = OUTPUT_DEBUG_STRING_EVENT;
650 event->u.DebugString.lpDebugStringData = (void *)info->ExceptionRecord.ExceptionInformation[1];
651 event->u.DebugString.fUnicode = FALSE;
652 event->u.DebugString.nDebugStringLength = info->ExceptionRecord.ExceptionInformation[0];
654 else if (code == DBG_PRINTEXCEPTION_WIDE_C && info->ExceptionRecord.NumberParameters >= 2)
656 event->dwDebugEventCode = OUTPUT_DEBUG_STRING_EVENT;
657 event->u.DebugString.lpDebugStringData = (void *)info->ExceptionRecord.ExceptionInformation[1];
658 event->u.DebugString.fUnicode = TRUE;
659 event->u.DebugString.nDebugStringLength = info->ExceptionRecord.ExceptionInformation[0];
661 else if (code == DBG_RIPEXCEPTION && info->ExceptionRecord.NumberParameters >= 2)
663 event->dwDebugEventCode = RIP_EVENT;
664 event->u.RipInfo.dwError = info->ExceptionRecord.ExceptionInformation[0];
665 event->u.RipInfo.dwType = info->ExceptionRecord.ExceptionInformation[1];
667 else
669 event->dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
670 event->u.Exception.ExceptionRecord = info->ExceptionRecord;
671 event->u.Exception.dwFirstChance = info->FirstChance;
673 break;
675 case DbgLoadDllStateChange:
677 DBGKM_LOAD_DLL *info = &state->StateInfo.LoadDll;
678 event->dwDebugEventCode = LOAD_DLL_DEBUG_EVENT;
679 event->u.LoadDll.hFile = info->FileHandle;
680 event->u.LoadDll.lpBaseOfDll = info->BaseOfDll;
681 event->u.LoadDll.dwDebugInfoFileOffset = info->DebugInfoFileOffset;
682 event->u.LoadDll.nDebugInfoSize = info->DebugInfoSize;
683 event->u.LoadDll.lpImageName = info->NamePointer;
684 event->u.LoadDll.fUnicode = TRUE;
685 break;
687 case DbgUnloadDllStateChange:
689 DBGKM_UNLOAD_DLL *info = &state->StateInfo.UnloadDll;
690 event->dwDebugEventCode = UNLOAD_DLL_DEBUG_EVENT;
691 event->u.UnloadDll.lpBaseOfDll = info->BaseAddress;
692 break;
694 default:
695 return STATUS_UNSUCCESSFUL;
697 return STATUS_SUCCESS;
700 /***********************************************************************
701 * DbgUiRemoteBreakin (NTDLL.@)
703 void WINAPI DbgUiRemoteBreakin( void *arg )
705 TRACE( "\n" );
706 if (NtCurrentTeb()->Peb->BeingDebugged)
708 __TRY
710 DbgBreakPoint();
712 __EXCEPT_ALL
714 /* do nothing */
716 __ENDTRY
718 RtlExitUserThread( STATUS_SUCCESS );
721 /***********************************************************************
722 * DbgUiIssueRemoteBreakin (NTDLL.@)
724 NTSTATUS WINAPI DbgUiIssueRemoteBreakin( HANDLE process )
726 HANDLE handle;
727 NTSTATUS status;
728 OBJECT_ATTRIBUTES attr = { sizeof(attr) };
730 status = NtCreateThreadEx( &handle, THREAD_ALL_ACCESS, &attr, process,
731 DbgUiRemoteBreakin, NULL, 0, 0, 0, 0, NULL );
732 #ifdef _WIN64
733 /* FIXME: hack for debugging 32-bit wow64 process without a 64-bit ntdll */
734 if (status == STATUS_INVALID_PARAMETER)
736 ULONG_PTR wow;
737 if (!NtQueryInformationProcess( process, ProcessWow64Information, &wow, sizeof(wow), NULL ) && wow)
738 status = NtCreateThreadEx( &handle, THREAD_ALL_ACCESS, &attr, process,
739 (void *)0x7ffe1000, NULL, 0, 0, 0, 0, NULL );
741 #endif
742 if (!status) NtClose( handle );
743 return status;