dmime/tests: Check more notification / dirty messages fields.
[wine.git] / dlls / ntdll / process.c
blob3ca4195ab3d090028c74b0c3370c8e21a57455f1
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 #ifdef __x86_64__
253 context.SegCs = 0x23;
254 __asm__( "movw %%fs,%0" : "=m" (context.SegFs) );
255 __asm__( "movw %%ss,%0" : "=m" (context.SegSs) );
256 #else
257 context.SegCs = 0x1b;
258 context.SegSs = 0x23;
259 context.SegFs = 0x3b;
260 #endif
263 sel = info->Selector | 3;
264 if (sel == 0x03) goto done; /* null selector */
266 /* set common data */
267 entry.HighWord.Bits.Dpl = 3;
268 entry.HighWord.Bits.Pres = 1;
269 entry.HighWord.Bits.Default_Big = 1;
270 if (sel == context.SegCs) /* code selector */
272 entry.LimitLow = 0xffff;
273 entry.HighWord.Bits.LimitHi = 0xf;
274 entry.HighWord.Bits.Type = 0x1b; /* code */
275 entry.HighWord.Bits.Granularity = 1;
277 else if (sel == context.SegSs) /* data selector */
279 entry.LimitLow = 0xffff;
280 entry.HighWord.Bits.LimitHi = 0xf;
281 entry.HighWord.Bits.Type = 0x13; /* data */
282 entry.HighWord.Bits.Granularity = 1;
284 else if (sel == context.SegFs) /* TEB selector */
286 THREAD_BASIC_INFORMATION tbi;
288 entry.LimitLow = 0xfff;
289 entry.HighWord.Bits.Type = 0x13; /* data */
290 if (!NtQueryInformationThread( handle, ThreadBasicInformation, &tbi, sizeof(tbi), NULL ))
292 ULONG addr = (ULONG_PTR)tbi.TebBaseAddress + 0x2000; /* 32-bit teb offset */
293 entry.BaseLow = addr;
294 entry.HighWord.Bytes.BaseMid = addr >> 16;
295 entry.HighWord.Bytes.BaseHi = addr >> 24;
298 else return STATUS_UNSUCCESSFUL;
300 done:
301 info->Entry = entry;
302 if (retlen) *retlen = sizeof(entry);
303 return STATUS_SUCCESS;
307 /**********************************************************************
308 * RtlOpenCrossProcessEmulatorWorkConnection (NTDLL.@)
310 void WINAPI RtlOpenCrossProcessEmulatorWorkConnection( HANDLE process, HANDLE *section, void **addr )
312 WOW64INFO wow64info;
313 BOOLEAN is_wow64;
314 SIZE_T size = 0;
316 *addr = NULL;
317 *section = 0;
319 if (RtlWow64GetSharedInfoProcess( process, &is_wow64, &wow64info )) return;
320 if (!is_wow64) return;
321 if (!wow64info.SectionHandle) return;
323 if (NtDuplicateObject( process, (HANDLE)(ULONG_PTR)wow64info.SectionHandle,
324 GetCurrentProcess(), section, 0, 0, DUPLICATE_SAME_ACCESS ))
325 return;
327 if (!NtMapViewOfSection( *section, GetCurrentProcess(), addr, 0, 0, NULL,
328 &size, ViewShare, 0, PAGE_READWRITE )) return;
330 NtClose( *section );
331 *section = 0;
335 /**********************************************************************
336 * RtlWow64PopAllCrossProcessWorkFromWorkList (NTDLL.@)
338 CROSS_PROCESS_WORK_ENTRY * WINAPI RtlWow64PopAllCrossProcessWorkFromWorkList( CROSS_PROCESS_WORK_HDR *list, BOOLEAN *flush )
340 CROSS_PROCESS_WORK_HDR prev, new;
341 UINT pos, prev_pos = 0;
345 prev.hdr = list->hdr;
346 if (!prev.first) break;
347 new.first = 0;
348 new.counter = prev.counter + 1;
349 } while (InterlockedCompareExchange64( &list->hdr, new.hdr, prev.hdr ) != prev.hdr);
351 *flush = (prev.first & CROSS_PROCESS_LIST_FLUSH) != 0;
352 if (!(pos = prev.first & ~CROSS_PROCESS_LIST_FLUSH)) return NULL;
354 /* reverse the list */
356 for (;;)
358 CROSS_PROCESS_WORK_ENTRY *entry = CROSS_PROCESS_LIST_ENTRY( list, pos );
359 UINT next = entry->next;
360 entry->next = prev_pos;
361 if (!next) return entry;
362 prev_pos = pos;
363 pos = next;
368 /**********************************************************************
369 * RtlWow64PopCrossProcessWorkFromFreeList (NTDLL.@)
371 CROSS_PROCESS_WORK_ENTRY * WINAPI RtlWow64PopCrossProcessWorkFromFreeList( CROSS_PROCESS_WORK_HDR *list )
373 CROSS_PROCESS_WORK_ENTRY *ret;
374 CROSS_PROCESS_WORK_HDR prev, new;
378 prev.hdr = list->hdr;
379 if (!prev.first) return NULL;
380 ret = CROSS_PROCESS_LIST_ENTRY( list, prev.first );
381 new.first = ret->next;
382 new.counter = prev.counter + 1;
383 } while (InterlockedCompareExchange64( &list->hdr, new.hdr, prev.hdr ) != prev.hdr);
385 ret->next = 0;
386 return ret;
390 /**********************************************************************
391 * RtlWow64PushCrossProcessWorkOntoFreeList (NTDLL.@)
393 BOOLEAN WINAPI RtlWow64PushCrossProcessWorkOntoFreeList( CROSS_PROCESS_WORK_HDR *list, CROSS_PROCESS_WORK_ENTRY *entry )
395 CROSS_PROCESS_WORK_HDR prev, new;
399 prev.hdr = list->hdr;
400 entry->next = prev.first;
401 new.first = (char *)entry - (char *)list;
402 new.counter = prev.counter + 1;
403 } while (InterlockedCompareExchange64( &list->hdr, new.hdr, prev.hdr ) != prev.hdr);
405 return TRUE;
409 /**********************************************************************
410 * RtlWow64PushCrossProcessWorkOntoWorkList (NTDLL.@)
412 BOOLEAN WINAPI RtlWow64PushCrossProcessWorkOntoWorkList( CROSS_PROCESS_WORK_HDR *list, CROSS_PROCESS_WORK_ENTRY *entry, void **unknown )
414 CROSS_PROCESS_WORK_HDR prev, new;
416 *unknown = NULL;
419 prev.hdr = list->hdr;
420 entry->next = prev.first;
421 new.first = ((char *)entry - (char *)list) | (prev.first & CROSS_PROCESS_LIST_FLUSH);
422 new.counter = prev.counter + 1;
423 } while (InterlockedCompareExchange64( &list->hdr, new.hdr, prev.hdr ) != prev.hdr);
425 return TRUE;
429 /**********************************************************************
430 * RtlWow64RequestCrossProcessHeavyFlush (NTDLL.@)
432 BOOLEAN WINAPI RtlWow64RequestCrossProcessHeavyFlush( CROSS_PROCESS_WORK_HDR *list )
434 CROSS_PROCESS_WORK_HDR prev, new;
438 prev.hdr = list->hdr;
439 new.first = prev.first | CROSS_PROCESS_LIST_FLUSH;
440 new.counter = prev.counter + 1;
441 } while (InterlockedCompareExchange64( &list->hdr, new.hdr, prev.hdr ) != prev.hdr);
443 return TRUE;
446 #endif /* _WIN64 */
448 /**********************************************************************
449 * RtlCreateUserProcess (NTDLL.@)
451 NTSTATUS WINAPI RtlCreateUserProcess( UNICODE_STRING *path, ULONG attributes,
452 RTL_USER_PROCESS_PARAMETERS *params,
453 SECURITY_DESCRIPTOR *process_descr,
454 SECURITY_DESCRIPTOR *thread_descr,
455 HANDLE parent, BOOLEAN inherit, HANDLE debug, HANDLE token,
456 RTL_USER_PROCESS_INFORMATION *info )
458 OBJECT_ATTRIBUTES process_attr, thread_attr;
459 PS_CREATE_INFO create_info;
460 ULONG_PTR buffer[offsetof( PS_ATTRIBUTE_LIST, Attributes[6] ) / sizeof(ULONG_PTR)];
461 PS_ATTRIBUTE_LIST *attr = (PS_ATTRIBUTE_LIST *)buffer;
462 UINT pos = 0;
464 RtlNormalizeProcessParams( params );
466 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_IMAGE_NAME;
467 attr->Attributes[pos].Size = path->Length;
468 attr->Attributes[pos].ValuePtr = path->Buffer;
469 attr->Attributes[pos].ReturnLength = NULL;
470 pos++;
471 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_CLIENT_ID;
472 attr->Attributes[pos].Size = sizeof(info->ClientId);
473 attr->Attributes[pos].ValuePtr = &info->ClientId;
474 attr->Attributes[pos].ReturnLength = NULL;
475 pos++;
476 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_IMAGE_INFO;
477 attr->Attributes[pos].Size = sizeof(info->ImageInformation);
478 attr->Attributes[pos].ValuePtr = &info->ImageInformation;
479 attr->Attributes[pos].ReturnLength = NULL;
480 pos++;
481 if (parent)
483 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_PARENT_PROCESS;
484 attr->Attributes[pos].Size = sizeof(parent);
485 attr->Attributes[pos].ValuePtr = parent;
486 attr->Attributes[pos].ReturnLength = NULL;
487 pos++;
489 if (debug)
491 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_DEBUG_PORT;
492 attr->Attributes[pos].Size = sizeof(debug);
493 attr->Attributes[pos].ValuePtr = debug;
494 attr->Attributes[pos].ReturnLength = NULL;
495 pos++;
497 if (token)
499 attr->Attributes[pos].Attribute = PS_ATTRIBUTE_TOKEN;
500 attr->Attributes[pos].Size = sizeof(token);
501 attr->Attributes[pos].ValuePtr = token;
502 attr->Attributes[pos].ReturnLength = NULL;
503 pos++;
505 attr->TotalLength = offsetof( PS_ATTRIBUTE_LIST, Attributes[pos] );
507 InitializeObjectAttributes( &process_attr, NULL, 0, NULL, process_descr );
508 InitializeObjectAttributes( &thread_attr, NULL, 0, NULL, thread_descr );
510 return NtCreateUserProcess( &info->Process, &info->Thread, PROCESS_ALL_ACCESS, THREAD_ALL_ACCESS,
511 &process_attr, &thread_attr,
512 inherit ? PROCESS_CREATE_FLAGS_INHERIT_HANDLES : 0,
513 THREAD_CREATE_FLAGS_CREATE_SUSPENDED, params,
514 &create_info, attr );
517 /***********************************************************************
518 * DbgUiGetThreadDebugObject (NTDLL.@)
520 HANDLE WINAPI DbgUiGetThreadDebugObject(void)
522 return NtCurrentTeb()->DbgSsReserved[1];
525 /***********************************************************************
526 * DbgUiSetThreadDebugObject (NTDLL.@)
528 void WINAPI DbgUiSetThreadDebugObject( HANDLE handle )
530 NtCurrentTeb()->DbgSsReserved[1] = handle;
533 /***********************************************************************
534 * DbgUiConnectToDbg (NTDLL.@)
536 NTSTATUS WINAPI DbgUiConnectToDbg(void)
538 HANDLE handle;
539 NTSTATUS status;
540 OBJECT_ATTRIBUTES attr = { sizeof(attr) };
542 if (DbgUiGetThreadDebugObject()) return STATUS_SUCCESS; /* already connected */
544 status = NtCreateDebugObject( &handle, DEBUG_ALL_ACCESS, &attr, DEBUG_KILL_ON_CLOSE );
545 if (!status) DbgUiSetThreadDebugObject( handle );
546 return status;
549 /***********************************************************************
550 * DbgUiDebugActiveProcess (NTDLL.@)
552 NTSTATUS WINAPI DbgUiDebugActiveProcess( HANDLE process )
554 NTSTATUS status;
556 if ((status = NtDebugActiveProcess( process, DbgUiGetThreadDebugObject() ))) return status;
557 if ((status = DbgUiIssueRemoteBreakin( process ))) DbgUiStopDebugging( process );
558 return status;
561 /***********************************************************************
562 * DbgUiStopDebugging (NTDLL.@)
564 NTSTATUS WINAPI DbgUiStopDebugging( HANDLE process )
566 return NtRemoveProcessDebug( process, DbgUiGetThreadDebugObject() );
569 /***********************************************************************
570 * DbgUiContinue (NTDLL.@)
572 NTSTATUS WINAPI DbgUiContinue( CLIENT_ID *client, NTSTATUS status )
574 return NtDebugContinue( DbgUiGetThreadDebugObject(), client, status );
577 /***********************************************************************
578 * DbgUiWaitStateChange (NTDLL.@)
580 NTSTATUS WINAPI DbgUiWaitStateChange( DBGUI_WAIT_STATE_CHANGE *state, LARGE_INTEGER *timeout )
582 return NtWaitForDebugEvent( DbgUiGetThreadDebugObject(), TRUE, timeout, state );
585 /* helper for DbgUiConvertStateChangeStructure */
586 static inline void *get_thread_teb( HANDLE thread )
588 THREAD_BASIC_INFORMATION info;
590 if (NtQueryInformationThread( thread, ThreadBasicInformation, &info, sizeof(info), NULL )) return NULL;
591 return info.TebBaseAddress;
594 /***********************************************************************
595 * DbgUiConvertStateChangeStructure (NTDLL.@)
597 NTSTATUS WINAPI DbgUiConvertStateChangeStructure( DBGUI_WAIT_STATE_CHANGE *state, DEBUG_EVENT *event )
599 event->dwProcessId = HandleToULong( state->AppClientId.UniqueProcess );
600 event->dwThreadId = HandleToULong( state->AppClientId.UniqueThread );
601 switch (state->NewState)
603 case DbgCreateThreadStateChange:
605 DBGUI_CREATE_THREAD *info = &state->StateInfo.CreateThread;
606 event->dwDebugEventCode = CREATE_THREAD_DEBUG_EVENT;
607 event->u.CreateThread.hThread = info->HandleToThread;
608 event->u.CreateThread.lpThreadLocalBase = get_thread_teb( info->HandleToThread );
609 event->u.CreateThread.lpStartAddress = info->NewThread.StartAddress;
610 break;
612 case DbgCreateProcessStateChange:
614 DBGUI_CREATE_PROCESS *info = &state->StateInfo.CreateProcessInfo;
615 event->dwDebugEventCode = CREATE_PROCESS_DEBUG_EVENT;
616 event->u.CreateProcessInfo.hFile = info->NewProcess.FileHandle;
617 event->u.CreateProcessInfo.hProcess = info->HandleToProcess;
618 event->u.CreateProcessInfo.hThread = info->HandleToThread;
619 event->u.CreateProcessInfo.lpBaseOfImage = info->NewProcess.BaseOfImage;
620 event->u.CreateProcessInfo.dwDebugInfoFileOffset = info->NewProcess.DebugInfoFileOffset;
621 event->u.CreateProcessInfo.nDebugInfoSize = info->NewProcess.DebugInfoSize;
622 event->u.CreateProcessInfo.lpThreadLocalBase = get_thread_teb( info->HandleToThread );
623 event->u.CreateProcessInfo.lpStartAddress = info->NewProcess.InitialThread.StartAddress;
624 event->u.CreateProcessInfo.lpImageName = NULL;
625 event->u.CreateProcessInfo.fUnicode = TRUE;
626 break;
628 case DbgExitThreadStateChange:
630 DBGKM_EXIT_THREAD *info = &state->StateInfo.ExitThread;
631 event->dwDebugEventCode = EXIT_THREAD_DEBUG_EVENT;
632 event->u.ExitThread.dwExitCode = info->ExitStatus;
633 break;
635 case DbgExitProcessStateChange:
637 DBGKM_EXIT_PROCESS *info = &state->StateInfo.ExitProcess;
638 event->dwDebugEventCode = EXIT_PROCESS_DEBUG_EVENT;
639 event->u.ExitProcess.dwExitCode = info->ExitStatus;
640 break;
642 case DbgExceptionStateChange:
643 case DbgBreakpointStateChange:
644 case DbgSingleStepStateChange:
646 DBGKM_EXCEPTION *info = &state->StateInfo.Exception;
647 DWORD code = info->ExceptionRecord.ExceptionCode;
648 if (code == DBG_PRINTEXCEPTION_C && info->ExceptionRecord.NumberParameters >= 2)
650 event->dwDebugEventCode = OUTPUT_DEBUG_STRING_EVENT;
651 event->u.DebugString.lpDebugStringData = (void *)info->ExceptionRecord.ExceptionInformation[1];
652 event->u.DebugString.fUnicode = FALSE;
653 event->u.DebugString.nDebugStringLength = info->ExceptionRecord.ExceptionInformation[0];
655 else if (code == DBG_PRINTEXCEPTION_WIDE_C && info->ExceptionRecord.NumberParameters >= 2)
657 event->dwDebugEventCode = OUTPUT_DEBUG_STRING_EVENT;
658 event->u.DebugString.lpDebugStringData = (void *)info->ExceptionRecord.ExceptionInformation[1];
659 event->u.DebugString.fUnicode = TRUE;
660 event->u.DebugString.nDebugStringLength = info->ExceptionRecord.ExceptionInformation[0];
662 else if (code == DBG_RIPEXCEPTION && info->ExceptionRecord.NumberParameters >= 2)
664 event->dwDebugEventCode = RIP_EVENT;
665 event->u.RipInfo.dwError = info->ExceptionRecord.ExceptionInformation[0];
666 event->u.RipInfo.dwType = info->ExceptionRecord.ExceptionInformation[1];
668 else
670 event->dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
671 event->u.Exception.ExceptionRecord = info->ExceptionRecord;
672 event->u.Exception.dwFirstChance = info->FirstChance;
674 break;
676 case DbgLoadDllStateChange:
678 DBGKM_LOAD_DLL *info = &state->StateInfo.LoadDll;
679 event->dwDebugEventCode = LOAD_DLL_DEBUG_EVENT;
680 event->u.LoadDll.hFile = info->FileHandle;
681 event->u.LoadDll.lpBaseOfDll = info->BaseOfDll;
682 event->u.LoadDll.dwDebugInfoFileOffset = info->DebugInfoFileOffset;
683 event->u.LoadDll.nDebugInfoSize = info->DebugInfoSize;
684 event->u.LoadDll.lpImageName = info->NamePointer;
685 event->u.LoadDll.fUnicode = TRUE;
686 break;
688 case DbgUnloadDllStateChange:
690 DBGKM_UNLOAD_DLL *info = &state->StateInfo.UnloadDll;
691 event->dwDebugEventCode = UNLOAD_DLL_DEBUG_EVENT;
692 event->u.UnloadDll.lpBaseOfDll = info->BaseAddress;
693 break;
695 default:
696 return STATUS_UNSUCCESSFUL;
698 return STATUS_SUCCESS;
701 /***********************************************************************
702 * DbgUiRemoteBreakin (NTDLL.@)
704 void WINAPI DbgUiRemoteBreakin( void *arg )
706 TRACE( "\n" );
707 if (NtCurrentTeb()->Peb->BeingDebugged)
709 __TRY
711 DbgBreakPoint();
713 __EXCEPT_ALL
715 /* do nothing */
717 __ENDTRY
719 RtlExitUserThread( STATUS_SUCCESS );
722 /***********************************************************************
723 * DbgUiIssueRemoteBreakin (NTDLL.@)
725 NTSTATUS WINAPI DbgUiIssueRemoteBreakin( HANDLE process )
727 HANDLE handle;
728 NTSTATUS status;
729 OBJECT_ATTRIBUTES attr = { sizeof(attr) };
731 status = NtCreateThreadEx( &handle, THREAD_ALL_ACCESS, &attr, process,
732 DbgUiRemoteBreakin, NULL, 0, 0, 0, 0, NULL );
733 #ifdef _WIN64
734 /* FIXME: hack for debugging 32-bit wow64 process without a 64-bit ntdll */
735 if (status == STATUS_INVALID_PARAMETER)
737 ULONG_PTR wow;
738 if (!NtQueryInformationProcess( process, ProcessWow64Information, &wow, sizeof(wow), NULL ) && wow)
739 status = NtCreateThreadEx( &handle, THREAD_ALL_ACCESS, &attr, process,
740 (void *)0x7ffe1000, NULL, 0, 0, 0, 0, NULL );
742 #endif
743 if (!status) NtClose( handle );
744 return status;