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 * 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
;
81 *old_value
= NtCurrentTeb64()->TlsSlots
[WOW64_TLS_FILESYSREDIR
];
85 return STATUS_ACCESS_VIOLATION
;
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(), ¤t
, &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;
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
;
131 /**********************************************************************
132 * RtlWow64GetSharedInfoProcess (NTDLL.@)
134 NTSTATUS WINAPI
RtlWow64GetSharedInfoProcess( HANDLE process
, BOOLEAN
*is_wow64
, WOW64INFO
*info
)
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
);
146 /**********************************************************************
147 * RtlWow64IsWowGuestMachineSupported (NTDLL.@)
149 NTSTATUS WINAPI
RtlWow64IsWowGuestMachineSupported( USHORT machine
, BOOLEAN
*supported
)
151 ULONG i
, machines
[8];
155 status
= NtQuerySystemInformationEx( SystemSupportedProcessorArchitectures
, &process
, sizeof(process
),
156 machines
, sizeof(machines
), NULL
);
157 if (status
) return status
;
159 for (i
= 0; machines
[i
]; i
++)
161 if (HIWORD(machines
[i
]) & 4 /* native machine */) continue;
162 if (machine
== LOWORD(machines
[i
])) *supported
= TRUE
;
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
)
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
;
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
;
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
;
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
)
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;
254 __asm__( "movw %%fs,%0" : "=m" (context
.SegFs
) );
255 __asm__( "movw %%ss,%0" : "=m" (context
.SegSs
) );
257 context
.SegSs
= 0x2b;
258 context
.SegFs
= 0x53;
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
;
301 if (retlen
) *retlen
= sizeof(entry
);
302 return STATUS_SUCCESS
;
306 /**********************************************************************
307 * RtlOpenCrossProcessEmulatorWorkConnection (NTDLL.@)
309 void WINAPI
RtlOpenCrossProcessEmulatorWorkConnection( HANDLE process
, HANDLE
*section
, void **addr
)
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
))
326 if (!NtMapViewOfSection( *section
, GetCurrentProcess(), addr
, 0, 0, NULL
,
327 &size
, ViewShare
, 0, PAGE_READWRITE
)) return;
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;
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 */
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
;
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
);
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
);
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;
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
);
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
);
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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)
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
);
548 /***********************************************************************
549 * DbgUiDebugActiveProcess (NTDLL.@)
551 NTSTATUS WINAPI
DbgUiDebugActiveProcess( HANDLE process
)
555 if ((status
= NtDebugActiveProcess( process
, DbgUiGetThreadDebugObject() ))) return status
;
556 if ((status
= DbgUiIssueRemoteBreakin( process
))) DbgUiStopDebugging( process
);
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
;
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
;
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
;
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
;
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];
669 event
->dwDebugEventCode
= EXCEPTION_DEBUG_EVENT
;
670 event
->u
.Exception
.ExceptionRecord
= info
->ExceptionRecord
;
671 event
->u
.Exception
.dwFirstChance
= info
->FirstChance
;
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
;
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
;
695 return STATUS_UNSUCCESSFUL
;
697 return STATUS_SUCCESS
;
700 /***********************************************************************
701 * DbgUiRemoteBreakin (NTDLL.@)
703 void WINAPI
DbgUiRemoteBreakin( void *arg
)
706 if (NtCurrentTeb()->Peb
->BeingDebugged
)
718 RtlExitUserThread( STATUS_SUCCESS
);
721 /***********************************************************************
722 * DbgUiIssueRemoteBreakin (NTDLL.@)
724 NTSTATUS WINAPI
DbgUiIssueRemoteBreakin( HANDLE process
)
728 OBJECT_ATTRIBUTES attr
= { sizeof(attr
) };
730 status
= NtCreateThreadEx( &handle
, THREAD_ALL_ACCESS
, &attr
, process
,
731 DbgUiRemoteBreakin
, NULL
, 0, 0, 0, 0, NULL
);
733 /* FIXME: hack for debugging 32-bit wow64 process without a 64-bit ntdll */
734 if (status
== STATUS_INVALID_PARAMETER
)
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
);
742 if (!status
) NtClose( handle
);