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 */
253 context
.SegCs
= 0x23;
254 __asm__( "movw %%fs,%0" : "=m" (context
.SegFs
) );
255 __asm__( "movw %%ss,%0" : "=m" (context
.SegSs
) );
257 context
.SegCs
= 0x1b;
258 context
.SegSs
= 0x23;
259 context
.SegFs
= 0x3b;
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
;
302 if (retlen
) *retlen
= sizeof(entry
);
303 return STATUS_SUCCESS
;
307 /**********************************************************************
308 * RtlOpenCrossProcessEmulatorWorkConnection (NTDLL.@)
310 void WINAPI
RtlOpenCrossProcessEmulatorWorkConnection( HANDLE process
, HANDLE
*section
, void **addr
)
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
))
327 if (!NtMapViewOfSection( *section
, GetCurrentProcess(), addr
, 0, 0, NULL
,
328 &size
, ViewShare
, 0, PAGE_READWRITE
)) return;
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;
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 */
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
;
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
);
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
);
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;
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
);
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
);
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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)
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
);
549 /***********************************************************************
550 * DbgUiDebugActiveProcess (NTDLL.@)
552 NTSTATUS WINAPI
DbgUiDebugActiveProcess( HANDLE process
)
556 if ((status
= NtDebugActiveProcess( process
, DbgUiGetThreadDebugObject() ))) return status
;
557 if ((status
= DbgUiIssueRemoteBreakin( process
))) DbgUiStopDebugging( process
);
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
;
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
;
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
;
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
;
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];
670 event
->dwDebugEventCode
= EXCEPTION_DEBUG_EVENT
;
671 event
->u
.Exception
.ExceptionRecord
= info
->ExceptionRecord
;
672 event
->u
.Exception
.dwFirstChance
= info
->FirstChance
;
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
;
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
;
696 return STATUS_UNSUCCESSFUL
;
698 return STATUS_SUCCESS
;
701 /***********************************************************************
702 * DbgUiRemoteBreakin (NTDLL.@)
704 void WINAPI
DbgUiRemoteBreakin( void *arg
)
707 if (NtCurrentTeb()->Peb
->BeingDebugged
)
719 RtlExitUserThread( STATUS_SUCCESS
);
722 /***********************************************************************
723 * DbgUiIssueRemoteBreakin (NTDLL.@)
725 NTSTATUS WINAPI
DbgUiIssueRemoteBreakin( HANDLE process
)
729 OBJECT_ATTRIBUTES attr
= { sizeof(attr
) };
731 status
= NtCreateThreadEx( &handle
, THREAD_ALL_ACCESS
, &attr
, process
,
732 DbgUiRemoteBreakin
, NULL
, 0, 0, 0, 0, NULL
);
734 /* FIXME: hack for debugging 32-bit wow64 process without a 64-bit ntdll */
735 if (status
== STATUS_INVALID_PARAMETER
)
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
);
743 if (!status
) NtClose( handle
);