Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
e9e5c950
Commit
e9e5c950
authored
Jun 16, 2020
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ntdll: Move the process information functions to the Unix library.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
c4c3b06e
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
614 additions
and
633 deletions
+614
-633
loader.c
dlls/ntdll/loader.c
+1
-2
ntdll_misc.h
dlls/ntdll/ntdll_misc.h
+0
-7
process.c
dlls/ntdll/process.c
+6
-617
loader.c
dlls/ntdll/unix/loader.c
+3
-1
process.c
dlls/ntdll/unix/process.c
+583
-0
thread.c
dlls/ntdll/unix/thread.c
+10
-1
unix_private.h
dlls/ntdll/unix/unix_private.h
+3
-1
virtual.c
dlls/ntdll/unix/virtual.c
+2
-2
unixlib.h
dlls/ntdll/unixlib.h
+6
-2
No files found.
dlls/ntdll/loader.c
View file @
e9e5c950
...
...
@@ -3592,8 +3592,7 @@ void WINAPI RtlExitUserProcess( DWORD status )
RtlAcquirePebLock
();
NtTerminateProcess
(
0
,
status
);
LdrShutdownProcess
();
NtTerminateProcess
(
GetCurrentProcess
(),
status
);
exit
(
get_unix_exit_code
(
status
));
for
(;;)
NtTerminateProcess
(
GetCurrentProcess
(),
status
);
}
/******************************************************************
...
...
dlls/ntdll/ntdll_misc.h
View file @
e9e5c950
...
...
@@ -196,13 +196,6 @@ static inline struct ntdll_thread_data *ntdll_get_thread_data(void)
return
(
struct
ntdll_thread_data
*
)
&
NtCurrentTeb
()
->
GdiTebBatch
;
}
static
inline
int
get_unix_exit_code
(
NTSTATUS
status
)
{
/* prevent a nonzero exit code to end up truncated to zero in unix */
if
(
status
&&
!
(
status
&
0xff
))
return
1
;
return
status
;
}
extern
SYSTEM_CPU_INFORMATION
cpu_info
DECLSPEC_HIDDEN
;
#define HASH_STRING_ALGORITHM_DEFAULT 0
...
...
dlls/ntdll/process.c
View file @
e9e5c950
...
...
@@ -65,10 +65,6 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
process
);
static
ULONG
execute_flags
=
MEM_EXECUTE_OPTION_DISABLE
|
(
sizeof
(
void
*
)
>
sizeof
(
int
)
?
MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
|
MEM_EXECUTE_OPTION_PERMANENT
:
0
);
static
const
BOOL
is_win64
=
(
sizeof
(
void
*
)
>
sizeof
(
int
));
...
...
@@ -83,18 +79,7 @@ static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
*/
NTSTATUS
WINAPI
NtTerminateProcess
(
HANDLE
handle
,
LONG
exit_code
)
{
NTSTATUS
ret
;
BOOL
self
;
SERVER_START_REQ
(
terminate_process
)
{
req
->
handle
=
wine_server_obj_handle
(
handle
);
req
->
exit_code
=
exit_code
;
ret
=
wine_server_call
(
req
);
self
=
!
ret
&&
reply
->
self
;
}
SERVER_END_REQ
;
if
(
self
&&
handle
)
_exit
(
get_unix_exit_code
(
exit_code
));
return
ret
;
return
unix_funcs
->
NtTerminateProcess
(
handle
,
exit_code
);
}
/******************************************************************************
...
...
@@ -123,14 +108,6 @@ HANDLE CDECL __wine_make_process_system(void)
return
ret
;
}
static
UINT
process_error_mode
;
#define UNIMPLEMENTED_INFO_CLASS(c) \
case c: \
FIXME("(process=%p) Unimplemented information class: " #c "\n", ProcessHandle); \
ret = STATUS_INVALID_INFO_CLASS; \
break
ULONG_PTR
get_system_affinity_mask
(
void
)
{
ULONG
num_cpus
=
NtCurrentTeb
()
->
Peb
->
NumberOfProcessors
;
...
...
@@ -138,612 +115,24 @@ ULONG_PTR get_system_affinity_mask(void)
return
((
ULONG_PTR
)
1
<<
num_cpus
)
-
1
;
}
#if defined(HAVE_MACH_MACH_H)
static
void
fill_VM_COUNTERS
(
VM_COUNTERS
*
pvmi
)
{
#if defined(MACH_TASK_BASIC_INFO)
struct
mach_task_basic_info
info
;
mach_msg_type_number_t
infoCount
=
MACH_TASK_BASIC_INFO_COUNT
;
if
(
task_info
(
mach_task_self
(),
MACH_TASK_BASIC_INFO
,
(
task_info_t
)
&
info
,
&
infoCount
)
==
KERN_SUCCESS
)
{
pvmi
->
VirtualSize
=
info
.
resident_size
+
info
.
virtual_size
;
pvmi
->
PagefileUsage
=
info
.
virtual_size
;
pvmi
->
WorkingSetSize
=
info
.
resident_size
;
pvmi
->
PeakWorkingSetSize
=
info
.
resident_size_max
;
}
#endif
}
#elif defined(linux)
static
void
fill_VM_COUNTERS
(
VM_COUNTERS
*
pvmi
)
{
FILE
*
f
;
char
line
[
256
];
unsigned
long
value
;
f
=
fopen
(
"/proc/self/status"
,
"r"
);
if
(
!
f
)
return
;
while
(
fgets
(
line
,
sizeof
(
line
),
f
))
{
if
(
sscanf
(
line
,
"VmPeak: %lu"
,
&
value
))
pvmi
->
PeakVirtualSize
=
(
ULONG64
)
value
*
1024
;
else
if
(
sscanf
(
line
,
"VmSize: %lu"
,
&
value
))
pvmi
->
VirtualSize
=
(
ULONG64
)
value
*
1024
;
else
if
(
sscanf
(
line
,
"VmHWM: %lu"
,
&
value
))
pvmi
->
PeakWorkingSetSize
=
(
ULONG64
)
value
*
1024
;
else
if
(
sscanf
(
line
,
"VmRSS: %lu"
,
&
value
))
pvmi
->
WorkingSetSize
=
(
ULONG64
)
value
*
1024
;
else
if
(
sscanf
(
line
,
"RssAnon: %lu"
,
&
value
))
pvmi
->
PagefileUsage
+=
(
ULONG64
)
value
*
1024
;
else
if
(
sscanf
(
line
,
"VmSwap: %lu"
,
&
value
))
pvmi
->
PagefileUsage
+=
(
ULONG64
)
value
*
1024
;
}
pvmi
->
PeakPagefileUsage
=
pvmi
->
PagefileUsage
;
fclose
(
f
);
}
#else
static
void
fill_VM_COUNTERS
(
VM_COUNTERS
*
pvmi
)
{
/* FIXME : real data */
}
#endif
/******************************************************************************
* NtQueryInformationProcess [NTDLL.@]
* ZwQueryInformationProcess [NTDLL.@]
*
*/
NTSTATUS
WINAPI
NtQueryInformationProcess
(
IN
HANDLE
ProcessHandle
,
IN
PROCESSINFOCLASS
ProcessInformationClass
,
OUT
PVOID
ProcessInformation
,
IN
ULONG
ProcessInformationLength
,
OUT
PULONG
ReturnLength
)
NTSTATUS
WINAPI
NtQueryInformationProcess
(
HANDLE
handle
,
PROCESSINFOCLASS
class
,
void
*
info
,
ULONG
size
,
ULONG
*
ret_len
)
{
NTSTATUS
ret
=
STATUS_SUCCESS
;
ULONG
len
=
0
;
TRACE
(
"(%p,0x%08x,%p,0x%08x,%p)
\n
"
,
ProcessHandle
,
ProcessInformationClass
,
ProcessInformation
,
ProcessInformationLength
,
ReturnLength
);
switch
(
ProcessInformationClass
)
{
UNIMPLEMENTED_INFO_CLASS
(
ProcessQuotaLimits
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessBasePriority
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessRaisePriority
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessExceptionPort
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessAccessToken
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessLdtInformation
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessLdtSize
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessIoPortHandlers
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessPooledUsageAndLimits
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessWorkingSetWatch
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessUserModeIOPL
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessEnableAlignmentFaultFixup
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessWx86Information
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessPriorityBoost
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessDeviceMap
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessSessionInformation
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessForegroundInformation
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessLUIDDeviceMapsEnabled
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessBreakOnTermination
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessHandleTracing
);
case
ProcessBasicInformation
:
{
PROCESS_BASIC_INFORMATION
pbi
;
const
ULONG_PTR
affinity_mask
=
get_system_affinity_mask
();
if
(
ProcessInformationLength
>=
sizeof
(
PROCESS_BASIC_INFORMATION
))
{
if
(
!
ProcessInformation
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
if
(
!
ProcessHandle
)
ret
=
STATUS_INVALID_HANDLE
;
else
{
SERVER_START_REQ
(
get_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
ProcessHandle
);
if
((
ret
=
wine_server_call
(
req
))
==
STATUS_SUCCESS
)
{
pbi
.
ExitStatus
=
reply
->
exit_code
;
pbi
.
PebBaseAddress
=
wine_server_get_ptr
(
reply
->
peb
);
pbi
.
AffinityMask
=
reply
->
affinity
&
affinity_mask
;
pbi
.
BasePriority
=
reply
->
priority
;
pbi
.
UniqueProcessId
=
reply
->
pid
;
pbi
.
InheritedFromUniqueProcessId
=
reply
->
ppid
;
}
}
SERVER_END_REQ
;
memcpy
(
ProcessInformation
,
&
pbi
,
sizeof
(
PROCESS_BASIC_INFORMATION
));
len
=
sizeof
(
PROCESS_BASIC_INFORMATION
);
}
if
(
ProcessInformationLength
>
sizeof
(
PROCESS_BASIC_INFORMATION
))
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
else
{
len
=
sizeof
(
PROCESS_BASIC_INFORMATION
);
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
}
break
;
case
ProcessIoCounters
:
{
IO_COUNTERS
pii
;
if
(
ProcessInformationLength
>=
sizeof
(
IO_COUNTERS
))
{
if
(
!
ProcessInformation
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
if
(
!
ProcessHandle
)
ret
=
STATUS_INVALID_HANDLE
;
else
{
/* FIXME : real data */
memset
(
&
pii
,
0
,
sizeof
(
IO_COUNTERS
));
memcpy
(
ProcessInformation
,
&
pii
,
sizeof
(
IO_COUNTERS
));
len
=
sizeof
(
IO_COUNTERS
);
}
if
(
ProcessInformationLength
>
sizeof
(
IO_COUNTERS
))
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
else
{
len
=
sizeof
(
IO_COUNTERS
);
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
}
break
;
case
ProcessVmCounters
:
{
VM_COUNTERS
pvmi
;
/* older Windows versions don't have the PrivatePageCount field */
if
(
ProcessInformationLength
>=
FIELD_OFFSET
(
VM_COUNTERS
,
PrivatePageCount
))
{
if
(
!
ProcessInformation
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
{
memset
(
&
pvmi
,
0
,
sizeof
(
VM_COUNTERS
));
if
(
ProcessHandle
==
GetCurrentProcess
())
fill_VM_COUNTERS
(
&
pvmi
);
else
{
SERVER_START_REQ
(
get_process_vm_counters
)
{
req
->
handle
=
wine_server_obj_handle
(
ProcessHandle
);
if
(
!
(
ret
=
wine_server_call
(
req
)))
{
pvmi
.
PeakVirtualSize
=
reply
->
peak_virtual_size
;
pvmi
.
VirtualSize
=
reply
->
virtual_size
;
pvmi
.
PeakWorkingSetSize
=
reply
->
peak_working_set_size
;
pvmi
.
WorkingSetSize
=
reply
->
working_set_size
;
pvmi
.
PagefileUsage
=
reply
->
pagefile_usage
;
pvmi
.
PeakPagefileUsage
=
reply
->
peak_pagefile_usage
;
}
}
SERVER_END_REQ
;
if
(
ret
)
break
;
}
len
=
ProcessInformationLength
;
if
(
len
!=
FIELD_OFFSET
(
VM_COUNTERS
,
PrivatePageCount
))
len
=
sizeof
(
VM_COUNTERS
);
memcpy
(
ProcessInformation
,
&
pvmi
,
min
(
ProcessInformationLength
,
sizeof
(
VM_COUNTERS
)));
}
if
(
ProcessInformationLength
!=
FIELD_OFFSET
(
VM_COUNTERS
,
PrivatePageCount
)
&&
ProcessInformationLength
!=
sizeof
(
VM_COUNTERS
))
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
else
{
len
=
sizeof
(
pvmi
);
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
}
break
;
case
ProcessTimes
:
{
KERNEL_USER_TIMES
pti
=
{{{
0
}}};
if
(
ProcessInformationLength
>=
sizeof
(
KERNEL_USER_TIMES
))
{
if
(
!
ProcessInformation
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
if
(
!
ProcessHandle
)
ret
=
STATUS_INVALID_HANDLE
;
else
{
long
ticks
=
sysconf
(
_SC_CLK_TCK
);
struct
tms
tms
;
/* FIXME: user/kernel times only work for current process */
if
(
ticks
&&
times
(
&
tms
)
!=
-
1
)
{
pti
.
UserTime
.
QuadPart
=
(
ULONGLONG
)
tms
.
tms_utime
*
10000000
/
ticks
;
pti
.
KernelTime
.
QuadPart
=
(
ULONGLONG
)
tms
.
tms_stime
*
10000000
/
ticks
;
}
SERVER_START_REQ
(
get_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
ProcessHandle
);
if
((
ret
=
wine_server_call
(
req
))
==
STATUS_SUCCESS
)
{
pti
.
CreateTime
.
QuadPart
=
reply
->
start_time
;
pti
.
ExitTime
.
QuadPart
=
reply
->
end_time
;
}
}
SERVER_END_REQ
;
memcpy
(
ProcessInformation
,
&
pti
,
sizeof
(
KERNEL_USER_TIMES
));
len
=
sizeof
(
KERNEL_USER_TIMES
);
}
if
(
ProcessInformationLength
>
sizeof
(
KERNEL_USER_TIMES
))
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
else
{
len
=
sizeof
(
KERNEL_USER_TIMES
);
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
}
break
;
case
ProcessDebugPort
:
len
=
sizeof
(
DWORD_PTR
);
if
(
ProcessInformationLength
==
len
)
{
if
(
!
ProcessInformation
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
if
(
!
ProcessHandle
)
ret
=
STATUS_INVALID_HANDLE
;
else
{
SERVER_START_REQ
(
get_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
ProcessHandle
);
if
((
ret
=
wine_server_call
(
req
))
==
STATUS_SUCCESS
)
{
*
(
DWORD_PTR
*
)
ProcessInformation
=
reply
->
debugger_present
?
~
(
DWORD_PTR
)
0
:
0
;
}
}
SERVER_END_REQ
;
}
}
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
break
;
case
ProcessDebugFlags
:
len
=
sizeof
(
DWORD
);
if
(
ProcessInformationLength
==
len
)
{
if
(
!
ProcessInformation
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
if
(
!
ProcessHandle
)
ret
=
STATUS_INVALID_HANDLE
;
else
{
SERVER_START_REQ
(
get_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
ProcessHandle
);
if
((
ret
=
wine_server_call
(
req
))
==
STATUS_SUCCESS
)
{
*
(
DWORD
*
)
ProcessInformation
=
reply
->
debug_children
;
}
}
SERVER_END_REQ
;
}
}
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
break
;
case
ProcessDefaultHardErrorMode
:
len
=
sizeof
(
process_error_mode
);
if
(
ProcessInformationLength
==
len
)
memcpy
(
ProcessInformation
,
&
process_error_mode
,
len
);
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
break
;
case
ProcessDebugObjectHandle
:
/* "These are not the debuggers you are looking for." *
* set it to 0 aka "no debugger" to satisfy copy protections */
len
=
sizeof
(
HANDLE
);
if
(
ProcessInformationLength
==
len
)
{
if
(
!
ProcessInformation
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
if
(
!
ProcessHandle
)
ret
=
STATUS_INVALID_HANDLE
;
else
{
memset
(
ProcessInformation
,
0
,
ProcessInformationLength
);
ret
=
STATUS_PORT_NOT_SET
;
}
}
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
break
;
case
ProcessHandleCount
:
if
(
ProcessInformationLength
>=
4
)
{
if
(
!
ProcessInformation
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
if
(
!
ProcessHandle
)
ret
=
STATUS_INVALID_HANDLE
;
else
{
memset
(
ProcessInformation
,
0
,
4
);
len
=
4
;
}
if
(
ProcessInformationLength
>
4
)
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
else
{
len
=
4
;
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
break
;
case
ProcessAffinityMask
:
len
=
sizeof
(
ULONG_PTR
);
if
(
ProcessInformationLength
==
len
)
{
const
ULONG_PTR
system_mask
=
get_system_affinity_mask
();
SERVER_START_REQ
(
get_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
ProcessHandle
);
if
(
!
(
ret
=
wine_server_call
(
req
)))
*
(
ULONG_PTR
*
)
ProcessInformation
=
reply
->
affinity
&
system_mask
;
}
SERVER_END_REQ
;
}
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
break
;
case
ProcessWow64Information
:
len
=
sizeof
(
ULONG_PTR
);
if
(
ProcessInformationLength
!=
len
)
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
else
if
(
!
ProcessInformation
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
if
(
!
ProcessHandle
)
ret
=
STATUS_INVALID_HANDLE
;
else
{
ULONG_PTR
val
=
0
;
if
(
ProcessHandle
==
GetCurrentProcess
())
val
=
is_wow64
;
else
if
(
server_cpus
&
((
1
<<
CPU_x86_64
)
|
(
1
<<
CPU_ARM64
)))
{
SERVER_START_REQ
(
get_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
ProcessHandle
);
if
(
!
(
ret
=
wine_server_call
(
req
)))
val
=
(
reply
->
cpu
!=
CPU_x86_64
&&
reply
->
cpu
!=
CPU_ARM64
);
}
SERVER_END_REQ
;
}
*
(
ULONG_PTR
*
)
ProcessInformation
=
val
;
}
break
;
case
ProcessImageFileName
:
/* FIXME: Should return a device path */
case
ProcessImageFileNameWin32
:
SERVER_START_REQ
(
get_dll_info
)
{
UNICODE_STRING
*
image_file_name_str
=
ProcessInformation
;
req
->
handle
=
wine_server_obj_handle
(
ProcessHandle
);
req
->
base_address
=
0
;
/* main module */
wine_server_set_reply
(
req
,
image_file_name_str
?
image_file_name_str
+
1
:
NULL
,
ProcessInformationLength
>
sizeof
(
UNICODE_STRING
)
?
ProcessInformationLength
-
sizeof
(
UNICODE_STRING
)
:
0
);
ret
=
wine_server_call
(
req
);
if
(
ret
==
STATUS_BUFFER_TOO_SMALL
)
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
len
=
sizeof
(
UNICODE_STRING
)
+
reply
->
filename_len
;
if
(
ret
==
STATUS_SUCCESS
)
{
image_file_name_str
->
MaximumLength
=
image_file_name_str
->
Length
=
reply
->
filename_len
;
image_file_name_str
->
Buffer
=
(
PWSTR
)(
image_file_name_str
+
1
);
}
}
SERVER_END_REQ
;
break
;
case
ProcessExecuteFlags
:
len
=
sizeof
(
ULONG
);
if
(
ProcessInformationLength
==
len
)
*
(
ULONG
*
)
ProcessInformation
=
execute_flags
;
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
break
;
case
ProcessPriorityClass
:
len
=
sizeof
(
PROCESS_PRIORITY_CLASS
);
if
(
ProcessInformationLength
==
len
)
{
if
(
!
ProcessInformation
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
if
(
!
ProcessHandle
)
ret
=
STATUS_INVALID_HANDLE
;
else
{
PROCESS_PRIORITY_CLASS
*
priority
=
ProcessInformation
;
SERVER_START_REQ
(
get_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
ProcessHandle
);
if
((
ret
=
wine_server_call
(
req
))
==
STATUS_SUCCESS
)
{
priority
->
PriorityClass
=
reply
->
priority
;
/* FIXME: Not yet supported by the wineserver */
priority
->
Foreground
=
FALSE
;
}
}
SERVER_END_REQ
;
}
}
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
break
;
case
ProcessCookie
:
FIXME
(
"ProcessCookie (%p,%p,0x%08x,%p) stub
\n
"
,
ProcessHandle
,
ProcessInformation
,
ProcessInformationLength
,
ReturnLength
);
if
(
ProcessHandle
==
NtCurrentProcess
())
{
len
=
sizeof
(
ULONG
);
if
(
ProcessInformationLength
==
len
)
*
(
ULONG
*
)
ProcessInformation
=
0
;
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
else
ret
=
STATUS_INVALID_PARAMETER
;
break
;
case
ProcessImageInformation
:
len
=
sizeof
(
SECTION_IMAGE_INFORMATION
);
if
(
ProcessInformationLength
==
len
)
{
if
(
ProcessInformation
)
{
pe_image_info_t
pe_info
;
SERVER_START_REQ
(
get_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
ProcessHandle
);
wine_server_set_reply
(
req
,
&
pe_info
,
sizeof
(
pe_info
)
);
if
((
ret
=
wine_server_call
(
req
))
==
STATUS_SUCCESS
)
virtual_fill_image_information
(
&
pe_info
,
ProcessInformation
);
}
SERVER_END_REQ
;
}
else
ret
=
STATUS_ACCESS_VIOLATION
;
}
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
break
;
default:
FIXME
(
"(%p,info_class=%d,%p,0x%08x,%p) Unknown information class
\n
"
,
ProcessHandle
,
ProcessInformationClass
,
ProcessInformation
,
ProcessInformationLength
,
ReturnLength
);
ret
=
STATUS_INVALID_INFO_CLASS
;
break
;
}
if
(
ReturnLength
)
*
ReturnLength
=
len
;
return
ret
;
return
unix_funcs
->
NtQueryInformationProcess
(
handle
,
class
,
info
,
size
,
ret_len
);
}
/******************************************************************************
* NtSetInformationProcess [NTDLL.@]
* ZwSetInformationProcess [NTDLL.@]
*/
NTSTATUS
WINAPI
NtSetInformationProcess
(
IN
HANDLE
ProcessHandle
,
IN
PROCESSINFOCLASS
ProcessInformationClass
,
IN
PVOID
ProcessInformation
,
IN
ULONG
ProcessInformationLength
)
NTSTATUS
WINAPI
NtSetInformationProcess
(
HANDLE
handle
,
PROCESSINFOCLASS
class
,
void
*
info
,
ULONG
size
)
{
NTSTATUS
ret
=
STATUS_SUCCESS
;
switch
(
ProcessInformationClass
)
{
case
ProcessDefaultHardErrorMode
:
if
(
ProcessInformationLength
!=
sizeof
(
UINT
))
return
STATUS_INVALID_PARAMETER
;
process_error_mode
=
*
(
UINT
*
)
ProcessInformation
;
break
;
case
ProcessAffinityMask
:
{
const
ULONG_PTR
system_mask
=
get_system_affinity_mask
();
if
(
ProcessInformationLength
!=
sizeof
(
DWORD_PTR
))
return
STATUS_INVALID_PARAMETER
;
if
(
*
(
PDWORD_PTR
)
ProcessInformation
&
~
system_mask
)
return
STATUS_INVALID_PARAMETER
;
if
(
!*
(
PDWORD_PTR
)
ProcessInformation
)
return
STATUS_INVALID_PARAMETER
;
SERVER_START_REQ
(
set_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
ProcessHandle
);
req
->
affinity
=
*
(
PDWORD_PTR
)
ProcessInformation
;
req
->
mask
=
SET_PROCESS_INFO_AFFINITY
;
ret
=
wine_server_call
(
req
);
}
SERVER_END_REQ
;
break
;
}
case
ProcessPriorityClass
:
if
(
ProcessInformationLength
!=
sizeof
(
PROCESS_PRIORITY_CLASS
))
return
STATUS_INVALID_PARAMETER
;
else
{
PROCESS_PRIORITY_CLASS
*
ppc
=
ProcessInformation
;
SERVER_START_REQ
(
set_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
ProcessHandle
);
/* FIXME Foreground isn't used */
req
->
priority
=
ppc
->
PriorityClass
;
req
->
mask
=
SET_PROCESS_INFO_PRIORITY
;
ret
=
wine_server_call
(
req
);
}
SERVER_END_REQ
;
}
break
;
case
ProcessExecuteFlags
:
if
(
is_win64
||
ProcessInformationLength
!=
sizeof
(
ULONG
))
return
STATUS_INVALID_PARAMETER
;
else
if
(
execute_flags
&
MEM_EXECUTE_OPTION_PERMANENT
)
return
STATUS_ACCESS_DENIED
;
else
{
BOOL
enable
;
switch
(
*
(
ULONG
*
)
ProcessInformation
&
(
MEM_EXECUTE_OPTION_ENABLE
|
MEM_EXECUTE_OPTION_DISABLE
))
{
case
MEM_EXECUTE_OPTION_ENABLE
:
enable
=
TRUE
;
break
;
case
MEM_EXECUTE_OPTION_DISABLE
:
enable
=
FALSE
;
break
;
default:
return
STATUS_INVALID_PARAMETER
;
}
execute_flags
=
*
(
ULONG
*
)
ProcessInformation
;
unix_funcs
->
virtual_set_force_exec
(
enable
);
}
break
;
default:
FIXME
(
"(%p,0x%08x,%p,0x%08x) stub
\n
"
,
ProcessHandle
,
ProcessInformationClass
,
ProcessInformation
,
ProcessInformationLength
);
ret
=
STATUS_NOT_IMPLEMENTED
;
break
;
}
return
ret
;
return
unix_funcs
->
NtSetInformationProcess
(
handle
,
class
,
info
,
size
);
}
/******************************************************************************
...
...
dlls/ntdll/unix/loader.c
View file @
e9e5c950
...
...
@@ -867,6 +867,7 @@ static struct unix_funcs unix_funcs =
NtQueryFullAttributesFile
,
NtQueryInformationFile
,
NtQueryInformationJobObject
,
NtQueryInformationProcess
,
NtQueryIoCompletion
,
NtQueryMutant
,
NtQueryPerformanceCounter
,
...
...
@@ -890,6 +891,7 @@ static struct unix_funcs unix_funcs =
NtSetEvent
,
NtSetInformationFile
,
NtSetInformationJobObject
,
NtSetInformationProcess
,
NtSetIoCompletion
,
NtSetLdtEntries
,
NtSetSystemTime
,
...
...
@@ -897,6 +899,7 @@ static struct unix_funcs unix_funcs =
NtSignalAndWaitForSingleObject
,
NtSuspendThread
,
NtTerminateJobObject
,
NtTerminateProcess
,
NtTerminateThread
,
NtUnlockVirtualMemory
,
NtUnmapViewOfSection
,
...
...
@@ -941,7 +944,6 @@ static struct unix_funcs unix_funcs =
virtual_locked_recvmsg
,
virtual_check_buffer_for_read
,
virtual_check_buffer_for_write
,
virtual_set_force_exec
,
virtual_release_address_space
,
virtual_set_large_address_space
,
init_threading
,
...
...
dlls/ntdll/unix/process.c
View file @
e9e5c950
...
...
@@ -70,10 +70,16 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
process
);
static
ULONG
execute_flags
=
MEM_EXECUTE_OPTION_DISABLE
|
(
sizeof
(
void
*
)
>
sizeof
(
int
)
?
MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
|
MEM_EXECUTE_OPTION_PERMANENT
:
0
);
static
const
BOOL
is_win64
=
(
sizeof
(
void
*
)
>
sizeof
(
int
));
static
const
char
*
const
cpu_names
[]
=
{
"x86"
,
"x86_64"
,
"PowerPC"
,
"ARM"
,
"ARM64"
};
static
UINT
process_error_mode
;
static
char
**
build_argv
(
const
UNICODE_STRING
*
cmdline
,
int
reserved
)
{
char
**
argv
,
*
arg
,
*
src
,
*
dst
;
...
...
@@ -942,3 +948,580 @@ done:
RtlFreeHeap
(
GetProcessHeap
(),
0
,
unixdir
);
return
status
;
}
/******************************************************************************
* NtTerminateProcess (NTDLL.@)
*/
NTSTATUS
WINAPI
NtTerminateProcess
(
HANDLE
handle
,
LONG
exit_code
)
{
NTSTATUS
ret
;
BOOL
self
;
SERVER_START_REQ
(
terminate_process
)
{
req
->
handle
=
wine_server_obj_handle
(
handle
);
req
->
exit_code
=
exit_code
;
ret
=
wine_server_call
(
req
);
self
=
reply
->
self
;
}
SERVER_END_REQ
;
if
(
self
&&
handle
)
abort_process
(
exit_code
);
return
ret
;
}
#if defined(HAVE_MACH_MACH_H)
static
void
fill_VM_COUNTERS
(
VM_COUNTERS
*
pvmi
)
{
#if defined(MACH_TASK_BASIC_INFO)
struct
mach_task_basic_info
info
;
mach_msg_type_number_t
infoCount
=
MACH_TASK_BASIC_INFO_COUNT
;
if
(
task_info
(
mach_task_self
(),
MACH_TASK_BASIC_INFO
,
(
task_info_t
)
&
info
,
&
infoCount
)
==
KERN_SUCCESS
)
{
pvmi
->
VirtualSize
=
info
.
resident_size
+
info
.
virtual_size
;
pvmi
->
PagefileUsage
=
info
.
virtual_size
;
pvmi
->
WorkingSetSize
=
info
.
resident_size
;
pvmi
->
PeakWorkingSetSize
=
info
.
resident_size_max
;
}
#endif
}
#elif defined(linux)
static
void
fill_VM_COUNTERS
(
VM_COUNTERS
*
pvmi
)
{
FILE
*
f
;
char
line
[
256
];
unsigned
long
value
;
f
=
fopen
(
"/proc/self/status"
,
"r"
);
if
(
!
f
)
return
;
while
(
fgets
(
line
,
sizeof
(
line
),
f
))
{
if
(
sscanf
(
line
,
"VmPeak: %lu"
,
&
value
))
pvmi
->
PeakVirtualSize
=
(
ULONG64
)
value
*
1024
;
else
if
(
sscanf
(
line
,
"VmSize: %lu"
,
&
value
))
pvmi
->
VirtualSize
=
(
ULONG64
)
value
*
1024
;
else
if
(
sscanf
(
line
,
"VmHWM: %lu"
,
&
value
))
pvmi
->
PeakWorkingSetSize
=
(
ULONG64
)
value
*
1024
;
else
if
(
sscanf
(
line
,
"VmRSS: %lu"
,
&
value
))
pvmi
->
WorkingSetSize
=
(
ULONG64
)
value
*
1024
;
else
if
(
sscanf
(
line
,
"RssAnon: %lu"
,
&
value
))
pvmi
->
PagefileUsage
+=
(
ULONG64
)
value
*
1024
;
else
if
(
sscanf
(
line
,
"VmSwap: %lu"
,
&
value
))
pvmi
->
PagefileUsage
+=
(
ULONG64
)
value
*
1024
;
}
pvmi
->
PeakPagefileUsage
=
pvmi
->
PagefileUsage
;
fclose
(
f
);
}
#else
static
void
fill_VM_COUNTERS
(
VM_COUNTERS
*
pvmi
)
{
/* FIXME : real data */
}
#endif
#define UNIMPLEMENTED_INFO_CLASS(c) \
case c: \
FIXME( "(process=%p) Unimplemented information class: " #c "\n", handle); \
ret = STATUS_INVALID_INFO_CLASS; \
break
/**********************************************************************
* NtQueryInformationProcess (NTDLL.@)
*/
NTSTATUS
WINAPI
NtQueryInformationProcess
(
HANDLE
handle
,
PROCESSINFOCLASS
class
,
void
*
info
,
ULONG
size
,
ULONG
*
ret_len
)
{
NTSTATUS
ret
=
STATUS_SUCCESS
;
ULONG
len
=
0
;
TRACE
(
"(%p,0x%08x,%p,0x%08x,%p)
\n
"
,
handle
,
class
,
info
,
size
,
ret_len
);
switch
(
class
)
{
UNIMPLEMENTED_INFO_CLASS
(
ProcessQuotaLimits
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessBasePriority
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessRaisePriority
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessExceptionPort
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessAccessToken
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessLdtInformation
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessLdtSize
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessIoPortHandlers
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessPooledUsageAndLimits
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessWorkingSetWatch
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessUserModeIOPL
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessEnableAlignmentFaultFixup
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessWx86Information
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessPriorityBoost
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessDeviceMap
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessSessionInformation
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessForegroundInformation
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessLUIDDeviceMapsEnabled
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessBreakOnTermination
);
UNIMPLEMENTED_INFO_CLASS
(
ProcessHandleTracing
);
case
ProcessBasicInformation
:
{
PROCESS_BASIC_INFORMATION
pbi
;
const
ULONG_PTR
affinity_mask
=
get_system_affinity_mask
();
if
(
size
>=
sizeof
(
PROCESS_BASIC_INFORMATION
))
{
if
(
!
info
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
{
SERVER_START_REQ
(
get_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
handle
);
if
((
ret
=
wine_server_call
(
req
))
==
STATUS_SUCCESS
)
{
pbi
.
ExitStatus
=
reply
->
exit_code
;
pbi
.
PebBaseAddress
=
wine_server_get_ptr
(
reply
->
peb
);
pbi
.
AffinityMask
=
reply
->
affinity
&
affinity_mask
;
pbi
.
BasePriority
=
reply
->
priority
;
pbi
.
UniqueProcessId
=
reply
->
pid
;
pbi
.
InheritedFromUniqueProcessId
=
reply
->
ppid
;
}
}
SERVER_END_REQ
;
memcpy
(
info
,
&
pbi
,
sizeof
(
PROCESS_BASIC_INFORMATION
)
);
len
=
sizeof
(
PROCESS_BASIC_INFORMATION
);
}
if
(
size
>
sizeof
(
PROCESS_BASIC_INFORMATION
))
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
else
{
len
=
sizeof
(
PROCESS_BASIC_INFORMATION
);
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
}
break
;
case
ProcessIoCounters
:
{
IO_COUNTERS
pii
;
if
(
size
>=
sizeof
(
IO_COUNTERS
))
{
if
(
!
info
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
if
(
!
handle
)
ret
=
STATUS_INVALID_HANDLE
;
else
{
/* FIXME : real data */
memset
(
&
pii
,
0
,
sizeof
(
IO_COUNTERS
));
memcpy
(
info
,
&
pii
,
sizeof
(
IO_COUNTERS
));
len
=
sizeof
(
IO_COUNTERS
);
}
if
(
size
>
sizeof
(
IO_COUNTERS
))
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
else
{
len
=
sizeof
(
IO_COUNTERS
);
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
}
break
;
case
ProcessVmCounters
:
{
VM_COUNTERS
pvmi
;
/* older Windows versions don't have the PrivatePageCount field */
if
(
size
>=
FIELD_OFFSET
(
VM_COUNTERS
,
PrivatePageCount
))
{
if
(
!
info
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
{
memset
(
&
pvmi
,
0
,
sizeof
(
VM_COUNTERS
));
if
(
handle
==
GetCurrentProcess
())
fill_VM_COUNTERS
(
&
pvmi
);
else
{
SERVER_START_REQ
(
get_process_vm_counters
)
{
req
->
handle
=
wine_server_obj_handle
(
handle
);
if
(
!
(
ret
=
wine_server_call
(
req
)))
{
pvmi
.
PeakVirtualSize
=
reply
->
peak_virtual_size
;
pvmi
.
VirtualSize
=
reply
->
virtual_size
;
pvmi
.
PeakWorkingSetSize
=
reply
->
peak_working_set_size
;
pvmi
.
WorkingSetSize
=
reply
->
working_set_size
;
pvmi
.
PagefileUsage
=
reply
->
pagefile_usage
;
pvmi
.
PeakPagefileUsage
=
reply
->
peak_pagefile_usage
;
}
}
SERVER_END_REQ
;
if
(
ret
)
break
;
}
len
=
size
;
if
(
len
!=
FIELD_OFFSET
(
VM_COUNTERS
,
PrivatePageCount
))
len
=
sizeof
(
VM_COUNTERS
);
memcpy
(
info
,
&
pvmi
,
min
(
size
,
sizeof
(
VM_COUNTERS
)));
}
if
(
size
!=
FIELD_OFFSET
(
VM_COUNTERS
,
PrivatePageCount
)
&&
size
!=
sizeof
(
VM_COUNTERS
))
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
else
{
len
=
sizeof
(
pvmi
);
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
}
break
;
case
ProcessTimes
:
{
KERNEL_USER_TIMES
pti
=
{{{
0
}}};
if
(
size
>=
sizeof
(
KERNEL_USER_TIMES
))
{
if
(
!
info
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
if
(
!
handle
)
ret
=
STATUS_INVALID_HANDLE
;
else
{
long
ticks
=
sysconf
(
_SC_CLK_TCK
);
struct
tms
tms
;
/* FIXME: user/kernel times only work for current process */
if
(
ticks
&&
times
(
&
tms
)
!=
-
1
)
{
pti
.
UserTime
.
QuadPart
=
(
ULONGLONG
)
tms
.
tms_utime
*
10000000
/
ticks
;
pti
.
KernelTime
.
QuadPart
=
(
ULONGLONG
)
tms
.
tms_stime
*
10000000
/
ticks
;
}
SERVER_START_REQ
(
get_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
handle
);
if
((
ret
=
wine_server_call
(
req
))
==
STATUS_SUCCESS
)
{
pti
.
CreateTime
.
QuadPart
=
reply
->
start_time
;
pti
.
ExitTime
.
QuadPart
=
reply
->
end_time
;
}
}
SERVER_END_REQ
;
memcpy
(
info
,
&
pti
,
sizeof
(
KERNEL_USER_TIMES
));
len
=
sizeof
(
KERNEL_USER_TIMES
);
}
if
(
size
>
sizeof
(
KERNEL_USER_TIMES
))
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
else
{
len
=
sizeof
(
KERNEL_USER_TIMES
);
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
}
break
;
case
ProcessDebugPort
:
len
=
sizeof
(
DWORD_PTR
);
if
(
size
==
len
)
{
if
(
!
info
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
{
SERVER_START_REQ
(
get_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
handle
);
if
((
ret
=
wine_server_call
(
req
))
==
STATUS_SUCCESS
)
{
*
(
DWORD_PTR
*
)
info
=
reply
->
debugger_present
?
~
(
DWORD_PTR
)
0
:
0
;
}
}
SERVER_END_REQ
;
}
}
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
break
;
case
ProcessDebugFlags
:
len
=
sizeof
(
DWORD
);
if
(
size
==
len
)
{
if
(
!
info
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
{
SERVER_START_REQ
(
get_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
handle
);
if
((
ret
=
wine_server_call
(
req
))
==
STATUS_SUCCESS
)
{
*
(
DWORD
*
)
info
=
reply
->
debug_children
;
}
}
SERVER_END_REQ
;
}
}
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
break
;
case
ProcessDefaultHardErrorMode
:
len
=
sizeof
(
process_error_mode
);
if
(
size
==
len
)
memcpy
(
info
,
&
process_error_mode
,
len
);
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
break
;
case
ProcessDebugObjectHandle
:
/* "These are not the debuggers you are looking for." *
* set it to 0 aka "no debugger" to satisfy copy protections */
len
=
sizeof
(
HANDLE
);
if
(
size
==
len
)
{
if
(
!
info
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
if
(
!
handle
)
ret
=
STATUS_INVALID_HANDLE
;
else
{
memset
(
info
,
0
,
size
);
ret
=
STATUS_PORT_NOT_SET
;
}
}
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
break
;
case
ProcessHandleCount
:
if
(
size
>=
4
)
{
if
(
!
info
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
if
(
!
handle
)
ret
=
STATUS_INVALID_HANDLE
;
else
{
memset
(
info
,
0
,
4
);
len
=
4
;
}
if
(
size
>
4
)
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
else
{
len
=
4
;
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
break
;
case
ProcessAffinityMask
:
len
=
sizeof
(
ULONG_PTR
);
if
(
size
==
len
)
{
const
ULONG_PTR
system_mask
=
get_system_affinity_mask
();
SERVER_START_REQ
(
get_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
handle
);
if
(
!
(
ret
=
wine_server_call
(
req
)))
*
(
ULONG_PTR
*
)
info
=
reply
->
affinity
&
system_mask
;
}
SERVER_END_REQ
;
}
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
break
;
case
ProcessWow64Information
:
len
=
sizeof
(
ULONG_PTR
);
if
(
size
!=
len
)
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
else
if
(
!
info
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
if
(
!
handle
)
ret
=
STATUS_INVALID_HANDLE
;
else
{
ULONG_PTR
val
=
0
;
if
(
handle
==
GetCurrentProcess
())
val
=
is_wow64
;
else
if
(
server_cpus
&
((
1
<<
CPU_x86_64
)
|
(
1
<<
CPU_ARM64
)))
{
SERVER_START_REQ
(
get_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
handle
);
if
(
!
(
ret
=
wine_server_call
(
req
)))
val
=
(
reply
->
cpu
!=
CPU_x86_64
&&
reply
->
cpu
!=
CPU_ARM64
);
}
SERVER_END_REQ
;
}
*
(
ULONG_PTR
*
)
info
=
val
;
}
break
;
case
ProcessImageFileName
:
/* FIXME: Should return a device path */
case
ProcessImageFileNameWin32
:
SERVER_START_REQ
(
get_dll_info
)
{
UNICODE_STRING
*
image_file_name_str
=
info
;
req
->
handle
=
wine_server_obj_handle
(
handle
);
req
->
base_address
=
0
;
/* main module */
wine_server_set_reply
(
req
,
image_file_name_str
?
image_file_name_str
+
1
:
NULL
,
size
>
sizeof
(
UNICODE_STRING
)
?
size
-
sizeof
(
UNICODE_STRING
)
:
0
);
ret
=
wine_server_call
(
req
);
if
(
ret
==
STATUS_BUFFER_TOO_SMALL
)
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
len
=
sizeof
(
UNICODE_STRING
)
+
reply
->
filename_len
;
if
(
ret
==
STATUS_SUCCESS
)
{
image_file_name_str
->
MaximumLength
=
image_file_name_str
->
Length
=
reply
->
filename_len
;
image_file_name_str
->
Buffer
=
(
PWSTR
)(
image_file_name_str
+
1
);
}
}
SERVER_END_REQ
;
break
;
case
ProcessExecuteFlags
:
len
=
sizeof
(
ULONG
);
if
(
size
==
len
)
*
(
ULONG
*
)
info
=
execute_flags
;
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
break
;
case
ProcessPriorityClass
:
len
=
sizeof
(
PROCESS_PRIORITY_CLASS
);
if
(
size
==
len
)
{
if
(
!
info
)
ret
=
STATUS_ACCESS_VIOLATION
;
else
{
PROCESS_PRIORITY_CLASS
*
priority
=
info
;
SERVER_START_REQ
(
get_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
handle
);
if
((
ret
=
wine_server_call
(
req
))
==
STATUS_SUCCESS
)
{
priority
->
PriorityClass
=
reply
->
priority
;
/* FIXME: Not yet supported by the wineserver */
priority
->
Foreground
=
FALSE
;
}
}
SERVER_END_REQ
;
}
}
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
break
;
case
ProcessCookie
:
FIXME
(
"ProcessCookie (%p,%p,0x%08x,%p) stub
\n
"
,
handle
,
info
,
size
,
ret_len
);
if
(
handle
==
NtCurrentProcess
())
{
len
=
sizeof
(
ULONG
);
if
(
size
==
len
)
*
(
ULONG
*
)
info
=
0
;
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
}
else
ret
=
STATUS_INVALID_PARAMETER
;
break
;
case
ProcessImageInformation
:
len
=
sizeof
(
SECTION_IMAGE_INFORMATION
);
if
(
size
==
len
)
{
if
(
info
)
{
pe_image_info_t
pe_info
;
SERVER_START_REQ
(
get_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
handle
);
wine_server_set_reply
(
req
,
&
pe_info
,
sizeof
(
pe_info
)
);
if
((
ret
=
wine_server_call
(
req
))
==
STATUS_SUCCESS
)
virtual_fill_image_information
(
&
pe_info
,
info
);
}
SERVER_END_REQ
;
}
else
ret
=
STATUS_ACCESS_VIOLATION
;
}
else
ret
=
STATUS_INFO_LENGTH_MISMATCH
;
break
;
default:
FIXME
(
"(%p,info_class=%d,%p,0x%08x,%p) Unknown information class
\n
"
,
handle
,
class
,
info
,
size
,
ret_len
);
ret
=
STATUS_INVALID_INFO_CLASS
;
break
;
}
if
(
ret_len
)
*
ret_len
=
len
;
return
ret
;
}
/**********************************************************************
* NtSetInformationProcess (NTDLL.@)
*/
NTSTATUS
WINAPI
NtSetInformationProcess
(
HANDLE
handle
,
PROCESSINFOCLASS
class
,
void
*
info
,
ULONG
size
)
{
NTSTATUS
ret
=
STATUS_SUCCESS
;
switch
(
class
)
{
case
ProcessDefaultHardErrorMode
:
if
(
size
!=
sizeof
(
UINT
))
return
STATUS_INVALID_PARAMETER
;
process_error_mode
=
*
(
UINT
*
)
info
;
break
;
case
ProcessAffinityMask
:
{
const
ULONG_PTR
system_mask
=
get_system_affinity_mask
();
if
(
size
!=
sizeof
(
DWORD_PTR
))
return
STATUS_INVALID_PARAMETER
;
if
(
*
(
PDWORD_PTR
)
info
&
~
system_mask
)
return
STATUS_INVALID_PARAMETER
;
if
(
!*
(
PDWORD_PTR
)
info
)
return
STATUS_INVALID_PARAMETER
;
SERVER_START_REQ
(
set_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
handle
);
req
->
affinity
=
*
(
PDWORD_PTR
)
info
;
req
->
mask
=
SET_PROCESS_INFO_AFFINITY
;
ret
=
wine_server_call
(
req
);
}
SERVER_END_REQ
;
break
;
}
case
ProcessPriorityClass
:
if
(
size
!=
sizeof
(
PROCESS_PRIORITY_CLASS
))
return
STATUS_INVALID_PARAMETER
;
else
{
PROCESS_PRIORITY_CLASS
*
ppc
=
info
;
SERVER_START_REQ
(
set_process_info
)
{
req
->
handle
=
wine_server_obj_handle
(
handle
);
/* FIXME Foreground isn't used */
req
->
priority
=
ppc
->
PriorityClass
;
req
->
mask
=
SET_PROCESS_INFO_PRIORITY
;
ret
=
wine_server_call
(
req
);
}
SERVER_END_REQ
;
}
break
;
case
ProcessExecuteFlags
:
if
(
is_win64
||
size
!=
sizeof
(
ULONG
))
return
STATUS_INVALID_PARAMETER
;
if
(
execute_flags
&
MEM_EXECUTE_OPTION_PERMANENT
)
return
STATUS_ACCESS_DENIED
;
else
{
BOOL
enable
;
switch
(
*
(
ULONG
*
)
info
&
(
MEM_EXECUTE_OPTION_ENABLE
|
MEM_EXECUTE_OPTION_DISABLE
))
{
case
MEM_EXECUTE_OPTION_ENABLE
:
enable
=
TRUE
;
break
;
case
MEM_EXECUTE_OPTION_DISABLE
:
enable
=
FALSE
;
break
;
default:
return
STATUS_INVALID_PARAMETER
;
}
execute_flags
=
*
(
ULONG
*
)
info
;
virtual_set_force_exec
(
enable
);
}
break
;
default:
FIXME
(
"(%p,0x%08x,%p,0x%08x) stub
\n
"
,
handle
,
class
,
info
,
size
);
ret
=
STATUS_NOT_IMPLEMENTED
;
break
;
}
return
ret
;
}
dlls/ntdll/unix/thread.c
View file @
e9e5c950
...
...
@@ -327,12 +327,21 @@ done:
void
abort_thread
(
int
status
)
{
pthread_sigmask
(
SIG_BLOCK
,
&
server_block_set
,
NULL
);
if
(
InterlockedDecrement
(
nb_threads
)
<=
0
)
_exit
(
get_unix_exit_code
(
status
)
);
if
(
InterlockedDecrement
(
nb_threads
)
<=
0
)
abort_process
(
status
);
signal_exit_thread
(
status
,
pthread_exit_wrapper
);
}
/***********************************************************************
* abort_process
*/
void
abort_process
(
int
status
)
{
_exit
(
get_unix_exit_code
(
status
));
}
/***********************************************************************
* exit_thread
*/
void
CDECL
exit_thread
(
int
status
)
...
...
dlls/ntdll/unix/unix_private.h
View file @
e9e5c950
...
...
@@ -94,7 +94,6 @@ extern ssize_t CDECL virtual_locked_pread( int fd, void *addr, size_t size, off_
extern
ssize_t
CDECL
virtual_locked_recvmsg
(
int
fd
,
struct
msghdr
*
hdr
,
int
flags
)
DECLSPEC_HIDDEN
;
extern
BOOL
CDECL
virtual_check_buffer_for_read
(
const
void
*
ptr
,
SIZE_T
size
)
DECLSPEC_HIDDEN
;
extern
BOOL
CDECL
virtual_check_buffer_for_write
(
void
*
ptr
,
SIZE_T
size
)
DECLSPEC_HIDDEN
;
extern
void
CDECL
virtual_set_force_exec
(
BOOL
enable
)
DECLSPEC_HIDDEN
;
extern
void
CDECL
virtual_release_address_space
(
void
)
DECLSPEC_HIDDEN
;
extern
void
CDECL
virtual_set_large_address_space
(
void
)
DECLSPEC_HIDDEN
;
...
...
@@ -160,6 +159,7 @@ extern int server_pipe( int fd[2] ) DECLSPEC_HIDDEN;
extern
NTSTATUS
context_to_server
(
context_t
*
to
,
const
CONTEXT
*
from
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
context_from_server
(
CONTEXT
*
to
,
const
context_t
*
from
)
DECLSPEC_HIDDEN
;
extern
void
DECLSPEC_NORETURN
abort_thread
(
int
status
)
DECLSPEC_HIDDEN
;
extern
void
DECLSPEC_NORETURN
abort_process
(
int
status
)
DECLSPEC_HIDDEN
;
extern
void
wait_suspend
(
CONTEXT
*
context
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
send_debug_event
(
EXCEPTION_RECORD
*
rec
,
CONTEXT
*
context
,
BOOL
first_chance
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
set_thread_context
(
HANDLE
handle
,
const
context_t
*
context
,
BOOL
*
self
)
DECLSPEC_HIDDEN
;
...
...
@@ -168,6 +168,7 @@ extern NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct o
data_size_t
*
ret_len
)
DECLSPEC_HIDDEN
;
extern
void
virtual_init
(
void
)
DECLSPEC_HIDDEN
;
extern
ULONG_PTR
get_system_affinity_mask
(
void
)
DECLSPEC_HIDDEN
;
extern
TEB
*
virtual_alloc_first_teb
(
void
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
virtual_alloc_teb
(
TEB
**
ret_teb
)
DECLSPEC_HIDDEN
;
extern
void
virtual_free_teb
(
TEB
*
teb
)
DECLSPEC_HIDDEN
;
...
...
@@ -177,6 +178,7 @@ extern BOOL virtual_is_valid_code_address( const void *addr, SIZE_T size ) DECLS
extern
int
virtual_handle_stack_fault
(
void
*
addr
)
DECLSPEC_HIDDEN
;
extern
SIZE_T
virtual_uninterrupted_read_memory
(
const
void
*
addr
,
void
*
buffer
,
SIZE_T
size
)
DECLSPEC_HIDDEN
;
extern
NTSTATUS
virtual_uninterrupted_write_memory
(
void
*
addr
,
const
void
*
buffer
,
SIZE_T
size
)
DECLSPEC_HIDDEN
;
extern
void
virtual_set_force_exec
(
BOOL
enable
)
DECLSPEC_HIDDEN
;
extern
void
virtual_fill_image_information
(
const
pe_image_info_t
*
pe_info
,
SECTION_IMAGE_INFORMATION
*
info
)
DECLSPEC_HIDDEN
;
...
...
dlls/ntdll/unix/virtual.c
View file @
e9e5c950
...
...
@@ -2458,7 +2458,7 @@ void virtual_init(void)
}
static
ULONG_PTR
get_system_affinity_mask
(
void
)
ULONG_PTR
get_system_affinity_mask
(
void
)
{
ULONG
num_cpus
=
NtCurrentTeb
()
->
Peb
->
NumberOfProcessors
;
if
(
num_cpus
>=
sizeof
(
ULONG_PTR
)
*
8
)
return
~
(
ULONG_PTR
)
0
;
...
...
@@ -3180,7 +3180,7 @@ NTSTATUS virtual_uninterrupted_write_memory( void *addr, const void *buffer, SIZ
*
* Whether to force exec prot on all views.
*/
void
CDECL
virtual_set_force_exec
(
BOOL
enable
)
void
virtual_set_force_exec
(
BOOL
enable
)
{
struct
file_view
*
view
;
sigset_t
sigset
;
...
...
dlls/ntdll/unixlib.h
View file @
e9e5c950
...
...
@@ -28,7 +28,7 @@ struct ldt_copy;
struct
msghdr
;
/* increment this when you change the function table */
#define NTDLL_UNIXLIB_VERSION 4
7
#define NTDLL_UNIXLIB_VERSION 4
8
struct
unix_funcs
{
...
...
@@ -139,6 +139,8 @@ struct unix_funcs
void
*
ptr
,
LONG
len
,
FILE_INFORMATION_CLASS
class
);
NTSTATUS
(
WINAPI
*
NtQueryInformationJobObject
)(
HANDLE
handle
,
JOBOBJECTINFOCLASS
class
,
void
*
info
,
ULONG
len
,
ULONG
*
ret_len
);
NTSTATUS
(
WINAPI
*
NtQueryInformationProcess
)(
HANDLE
handle
,
PROCESSINFOCLASS
class
,
void
*
info
,
ULONG
size
,
ULONG
*
ret_len
);
NTSTATUS
(
WINAPI
*
NtQueryIoCompletion
)(
HANDLE
handle
,
IO_COMPLETION_INFORMATION_CLASS
class
,
void
*
buffer
,
ULONG
len
,
ULONG
*
ret_len
);
NTSTATUS
(
WINAPI
*
NtQueryMutant
)(
HANDLE
handle
,
MUTANT_INFORMATION_CLASS
class
,
...
...
@@ -177,6 +179,8 @@ struct unix_funcs
void
*
ptr
,
ULONG
len
,
FILE_INFORMATION_CLASS
class
);
NTSTATUS
(
WINAPI
*
NtSetInformationJobObject
)(
HANDLE
handle
,
JOBOBJECTINFOCLASS
class
,
void
*
info
,
ULONG
len
);
NTSTATUS
(
WINAPI
*
NtSetInformationProcess
)(
HANDLE
handle
,
PROCESSINFOCLASS
class
,
void
*
info
,
ULONG
size
);
NTSTATUS
(
WINAPI
*
NtSetIoCompletion
)(
HANDLE
handle
,
ULONG_PTR
key
,
ULONG_PTR
value
,
NTSTATUS
status
,
SIZE_T
count
);
NTSTATUS
(
WINAPI
*
NtSetLdtEntries
)(
ULONG
sel1
,
LDT_ENTRY
entry1
,
ULONG
sel2
,
LDT_ENTRY
entry2
);
...
...
@@ -188,6 +192,7 @@ struct unix_funcs
BOOLEAN
alertable
,
const
LARGE_INTEGER
*
timeout
);
NTSTATUS
(
WINAPI
*
NtSuspendThread
)(
HANDLE
handle
,
ULONG
*
count
);
NTSTATUS
(
WINAPI
*
NtTerminateJobObject
)(
HANDLE
handle
,
NTSTATUS
status
);
NTSTATUS
(
WINAPI
*
NtTerminateProcess
)(
HANDLE
handle
,
LONG
exit_code
);
NTSTATUS
(
WINAPI
*
NtTerminateThread
)(
HANDLE
handle
,
LONG
exit_code
);
NTSTATUS
(
WINAPI
*
NtUnlockVirtualMemory
)(
HANDLE
process
,
PVOID
*
addr
,
SIZE_T
*
size
,
ULONG
unknown
);
...
...
@@ -253,7 +258,6 @@ struct unix_funcs
ssize_t
(
CDECL
*
virtual_locked_recvmsg
)(
int
fd
,
struct
msghdr
*
hdr
,
int
flags
);
BOOL
(
CDECL
*
virtual_check_buffer_for_read
)(
const
void
*
ptr
,
SIZE_T
size
);
BOOL
(
CDECL
*
virtual_check_buffer_for_write
)(
void
*
ptr
,
SIZE_T
size
);
void
(
CDECL
*
virtual_set_force_exec
)(
BOOL
enable
);
void
(
CDECL
*
virtual_release_address_space
)(
void
);
void
(
CDECL
*
virtual_set_large_address_space
)(
void
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment