diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index a09c17e3b50..bdd343324da 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -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 ); } /****************************************************************** diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 54bb8357e11..bfb291374d0 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -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 diff --git a/dlls/ntdll/process.c b/dlls/ntdll/process.c index 814d6973ba1..a14b24219fc 100644 --- a/dlls/ntdll/process.c +++ b/dlls/ntdll/process.c @@ -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 ); } /****************************************************************************** diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 697f16d945f..178f8e18d1b 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -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, diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c index 2b64bb86a3c..cca6c2747bf 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c @@ -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; +} diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 0470f5eaa8a..d6fb12d7f47 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -327,11 +327,20 @@ 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 */ diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index f8f34a0211b..6eab6052bf9 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -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; diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index a89d760e69d..22cf724b819 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -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; diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h index 1b917183c67..15b44b6735e 100644 --- a/dlls/ntdll/unixlib.h +++ b/dlls/ntdll/unixlib.h @@ -28,7 +28,7 @@ struct ldt_copy; struct msghdr; /* increment this when you change the function table */ -#define NTDLL_UNIXLIB_VERSION 47 +#define NTDLL_UNIXLIB_VERSION 48 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);