/****************************************************************************** * EnumDesktopsW (USER32.@) */ BOOL WINAPI EnumDesktopsW( HWINSTA winsta, DESKTOPENUMPROCW func, LPARAM lparam ) { unsigned int index = 0; WCHAR name[MAX_PATH]; BOOL ret = TRUE; NTSTATUS status; if (!winsta) winsta = GetProcessWindowStation(); while (ret) { SERVER_START_REQ( enum_desktop ) { req->winstation = wine_server_obj_handle( winsta ); req->index = index; wine_server_set_reply( req, name, sizeof(name) - sizeof(WCHAR) ); status = wine_server_call( req ); name[wine_server_reply_size(reply)/sizeof(WCHAR)] = 0; index = reply->next; } SERVER_END_REQ; if (status == STATUS_NO_MORE_ENTRIES) break; if (status) { SetLastError( RtlNtStatusToDosError( status ) ); return FALSE; } ret = func(name, lparam); } return ret; }
/*********************************************************************** * CreateWindowStationW (USER32.@) */ HWINSTA WINAPI CreateWindowStationW( LPCWSTR name, DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa ) { HANDLE ret; DWORD len = name ? strlenW(name) : 0; if (len >= MAX_PATH) { SetLastError( ERROR_FILENAME_EXCED_RANGE ); return 0; } SERVER_START_REQ( create_winstation ) { req->flags = 0; req->access = access; req->attributes = OBJ_CASE_INSENSITIVE | ((flags & CWF_CREATE_ONLY) ? 0 : OBJ_OPENIF) | ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0); req->rootdir = wine_server_obj_handle( get_winstations_dir_handle() ); wine_server_add_data( req, name, len * sizeof(WCHAR) ); wine_server_call_err( req ); ret = wine_server_ptr_handle( reply->handle ); } SERVER_END_REQ; return ret; }
/****************************************************************************** * NtTerminateThread (NTDLL.@) * ZwTerminateThread (NTDLL.@) */ NTSTATUS WINAPI NtTerminateThread( HANDLE handle, LONG exit_code ) { NTSTATUS ret; BOOL self; SERVER_START_REQ( terminate_thread ) { req->handle = wine_server_obj_handle( handle ); req->exit_code = exit_code; ret = wine_server_call( req ); self = !ret && reply->self; } SERVER_END_REQ; #ifdef CONFIG_UNIFIED_KERNEL if (self) { server_kill_thread( exit_code ); abort_thread( exit_code ); } #else if (self) abort_thread( exit_code ); #endif return ret; }
/*********************************************************************** * CloseWindowStation (USER32.@) */ BOOL WINAPI CloseWindowStation( HWINSTA handle ) { BOOL ret; SERVER_START_REQ( close_winstation ) { req->handle = wine_server_obj_handle( handle ); ret = !wine_server_call_err( req ); } SERVER_END_REQ; return ret; }
/*********************************************************************** * exit_thread */ void exit_thread( int status ) { static void *prev_teb; shmlocal_t *shmlocal; sigset_t sigset; TEB *teb; if (status) /* send the exit code to the server (0 is already the default) */ { SERVER_START_REQ( terminate_thread ) { req->handle = wine_server_obj_handle( GetCurrentThread() ); req->exit_code = status; wine_server_call( req ); } SERVER_END_REQ; } if (interlocked_xchg_add( &nb_threads, 0 ) <= 1) { LdrShutdownProcess(); exit( status ); } LdrShutdownThread(); RtlFreeThreadActivationContextStack(); shmlocal = interlocked_xchg_ptr( &NtCurrentTeb()->Reserved5[2], NULL ); if (shmlocal) NtUnmapViewOfSection( NtCurrentProcess(), shmlocal ); pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() ))) { struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; if (thread_data->pthread_id) { pthread_join( thread_data->pthread_id, NULL ); signal_free_thread( teb ); } } sigemptyset( &sigset ); sigaddset( &sigset, SIGQUIT ); pthread_sigmask( SIG_BLOCK, &sigset, NULL ); if (interlocked_xchg_add( &nb_threads, -1 ) <= 1) _exit( status ); close( ntdll_get_thread_data()->wait_fd[0] ); close( ntdll_get_thread_data()->wait_fd[1] ); close( ntdll_get_thread_data()->reply_fd ); close( ntdll_get_thread_data()->request_fd ); pthread_exit( UIntToPtr(status) ); }
/*********************************************************************** * CloseDesktop (USER32.@) */ BOOL WINAPI CloseDesktop( HDESK handle ) { BOOL ret; SERVER_START_REQ( close_desktop ) { req->handle = wine_server_obj_handle( handle ); ret = !wine_server_call_err( req ); } SERVER_END_REQ; return ret; }
/****************************************************************************** * NtResumeThread (NTDLL.@) * ZwResumeThread (NTDLL.@) */ NTSTATUS WINAPI NtResumeThread( HANDLE handle, PULONG count ) { NTSTATUS ret; SERVER_START_REQ( resume_thread ) { req->handle = wine_server_obj_handle( handle ); if (!(ret = wine_server_call( req ))) *count = reply->count; } SERVER_END_REQ; return ret; }
/*********************************************************************** * SetProcessWindowStation (USER32.@) */ BOOL WINAPI SetProcessWindowStation( HWINSTA handle ) { BOOL ret; SERVER_START_REQ( set_process_winstation ) { req->handle = wine_server_obj_handle( handle ); ret = !wine_server_call_err( req ); } SERVER_END_REQ; return ret; }
static void stop_waiting( HANDLE handle ) { NTSTATUS status; SERVER_START_REQ( set_serial_info ) { req->handle = wine_server_obj_handle( handle ); req->flags = SERIALINFO_PENDING_WAIT; if ((status = wine_server_call( req ))) ERR("failed to clear waiting state: %#x\n", status); } SERVER_END_REQ; }
static NTSTATUS get_wait_mask(HANDLE hDevice, DWORD* mask) { NTSTATUS status; SERVER_START_REQ( get_serial_info ) { req->handle = wine_server_obj_handle( hDevice ); if (!(status = wine_server_call( req ))) *mask = reply->eventmask; } SERVER_END_REQ; return status; }
static NTSTATUS set_wait_mask(HANDLE hDevice, DWORD mask) { NTSTATUS status; SERVER_START_REQ( set_serial_info ) { req->handle = wine_server_obj_handle( hDevice ); req->flags = SERIALINFO_SET_MASK; req->eventmask = mask; status = wine_server_call( req ); } SERVER_END_REQ; return status; }
/*********************************************************************** * exit_thread */ void exit_thread( int status ) { static void *prev_teb; TEB *teb; if (status) /* send the exit code to the server (0 is already the default) */ { SERVER_START_REQ( terminate_thread ) { req->handle = wine_server_obj_handle( GetCurrentThread() ); req->exit_code = status; wine_server_call( req ); } SERVER_END_REQ; } if (interlocked_xchg_add( &nb_threads, -1 ) <= 1) { LdrShutdownProcess(); #ifdef CONFIG_UNIFIED_KERNEL server_kill_thread( status ); #endif exit( status ); } LdrShutdownThread(); pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() ))) { struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; if (thread_data->pthread_id) { pthread_join( thread_data->pthread_id, NULL ); signal_free_thread( teb ); } } close( ntdll_get_thread_data()->wait_fd[0] ); close( ntdll_get_thread_data()->wait_fd[1] ); close( ntdll_get_thread_data()->reply_fd ); close( ntdll_get_thread_data()->request_fd ); #ifdef CONFIG_UNIFIED_KERNEL server_kill_thread( status ); #endif pthread_exit( UIntToPtr(status) ); }
/****************************************************************************** * NtTerminateProcess [NTDLL.@] * * Native applications must kill themselves when done */ 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( exit_code ); return ret; }
/*********************************************************************** * exit_thread */ void exit_thread( int status ) { static void *prev_teb; TEB *teb; if (status) /* send the exit code to the server (0 is already the default) */ { SERVER_START_REQ( terminate_thread ) { req->handle = wine_server_obj_handle( GetCurrentThread() ); req->exit_code = status; wine_server_call( req ); } SERVER_END_REQ; } if (interlocked_xchg_add( &nb_threads, -1 ) <= 1) { LdrShutdownProcess(); exit( status ); } LdrShutdownThread(); RtlAcquirePebLock(); RemoveEntryList( &NtCurrentTeb()->TlsLinks ); RtlReleasePebLock(); RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->FlsSlots ); RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->TlsExpansionSlots ); pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() ))) { struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; if (thread_data->pthread_id) { pthread_join( thread_data->pthread_id, NULL ); signal_free_thread( teb ); } } close( ntdll_get_thread_data()->wait_fd[0] ); close( ntdll_get_thread_data()->wait_fd[1] ); close( ntdll_get_thread_data()->reply_fd ); close( ntdll_get_thread_data()->request_fd ); pthread_exit( UIntToPtr(status) ); }
/*********************************************************************** * DebugBreakProcess (KERNEL32.@) * * Raises an exception so that a debugger (if attached) * can take some action. Same as DebugBreak, but applies to any process. * * PARAMS * hProc [I] Process to break into. * * RETURNS * * True if successful. */ BOOL WINAPI DebugBreakProcess(HANDLE hProc) { BOOL ret, self; TRACE("(%p)\n", hProc); SERVER_START_REQ( debug_break ) { req->handle = wine_server_obj_handle( hProc ); ret = !wine_server_call_err( req ); self = ret && reply->self; } SERVER_END_REQ; if (self) DbgBreakPoint(); return ret; }
/*********************************************************************** * server_get_unix_fd * * The returned unix_fd should be closed iff needs_close is non-zero. */ int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, int *needs_close, enum server_fd_type *type, unsigned int *options ) { sigset_t sigset; obj_handle_t fd_handle; int ret = 0, fd; unsigned int access = 0; *unix_fd = -1; *needs_close = 0; wanted_access &= FILE_READ_DATA | FILE_WRITE_DATA; server_enter_uninterrupted_section( &fd_cache_section, &sigset ); fd = get_cached_fd( handle, type, &access, options ); if (fd != -1) goto done; SERVER_START_REQ( get_handle_fd ) { req->handle = wine_server_obj_handle( handle ); if (!(ret = wine_server_call( req ))) { if (type) *type = reply->type; if (options) *options = reply->options; access = reply->access; if ((fd = receive_fd( &fd_handle )) != -1) { assert( wine_server_ptr_handle(fd_handle) == handle ); *needs_close = (reply->removable || !add_fd_to_cache( handle, fd, reply->type, reply->access, reply->options )); } else ret = STATUS_TOO_MANY_OPENED_FILES; } } SERVER_END_REQ; done: server_leave_uninterrupted_section( &fd_cache_section, &sigset ); if (!ret && ((access & wanted_access) != wanted_access)) { ret = STATUS_ACCESS_DENIED; if (*needs_close) close( fd ); } if (!ret) *unix_fd = fd; return ret; }
/****************************************************************************** * NtTerminateThread (NTDLL.@) * ZwTerminateThread (NTDLL.@) */ NTSTATUS WINAPI NtTerminateThread( HANDLE handle, LONG exit_code ) { NTSTATUS ret; BOOL self; SERVER_START_REQ( terminate_thread ) { 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) abort_thread( exit_code ); return ret; }
static NTSTATUS get_timeouts(HANDLE handle, SERIAL_TIMEOUTS* st) { NTSTATUS status; SERVER_START_REQ( get_serial_info ) { req->handle = wine_server_obj_handle( handle ); if (!(status = wine_server_call( req ))) { st->ReadIntervalTimeout = reply->readinterval; st->ReadTotalTimeoutMultiplier = reply->readmult; st->ReadTotalTimeoutConstant = reply->readconst; st->WriteTotalTimeoutMultiplier = reply->writemult; st->WriteTotalTimeoutConstant = reply->writeconst; } } SERVER_END_REQ; return status; }
static NTSTATUS set_timeouts(HANDLE handle, const SERIAL_TIMEOUTS* st) { NTSTATUS status; SERVER_START_REQ( set_serial_info ) { req->handle = wine_server_obj_handle( handle ); req->flags = SERIALINFO_SET_TIMEOUTS; req->readinterval = st->ReadIntervalTimeout ; req->readmult = st->ReadTotalTimeoutMultiplier ; req->readconst = st->ReadTotalTimeoutConstant ; req->writemult = st->WriteTotalTimeoutMultiplier ; req->writeconst = st->WriteTotalTimeoutConstant ; status = wine_server_call( req ); } SERVER_END_REQ; return status; }
/****************************************************************************** * SetThreadDesktop (USER32.@) */ BOOL WINAPI SetThreadDesktop( HDESK handle ) { BOOL ret; SERVER_START_REQ( set_thread_desktop ) { req->handle = wine_server_obj_handle( handle ); ret = !wine_server_call_err( req ); } SERVER_END_REQ; if (ret) /* reset the desktop windows */ { struct user_thread_info *thread_info = get_user_thread_info(); thread_info->top_window = 0; thread_info->msg_window = 0; } return ret; }
static NTSTATUS get_wait_mask(HANDLE hDevice, DWORD *mask, DWORD *cookie, DWORD *pending_write, BOOL start_wait) { NTSTATUS status; SERVER_START_REQ( get_serial_info ) { req->handle = wine_server_obj_handle( hDevice ); req->flags = pending_write ? SERIALINFO_PENDING_WRITE : 0; if (start_wait) req->flags |= SERIALINFO_PENDING_WAIT; if (!(status = wine_server_call( req ))) { *mask = reply->eventmask; if (cookie) *cookie = reply->cookie; if (pending_write) *pending_write = reply->pending_write; } } SERVER_END_REQ; return status; }
/****************************************************************************** * OpenWindowStationW (USER32.@) */ HWINSTA WINAPI OpenWindowStationW( LPCWSTR name, BOOL inherit, ACCESS_MASK access ) { HANDLE ret = 0; DWORD len = name ? strlenW(name) : 0; if (len >= MAX_PATH) { SetLastError( ERROR_FILENAME_EXCED_RANGE ); return 0; } SERVER_START_REQ( open_winstation ) { req->access = access; req->attributes = OBJ_CASE_INSENSITIVE | (inherit ? OBJ_INHERIT : 0); req->rootdir = wine_server_obj_handle( get_winstations_dir_handle() ); wine_server_add_data( req, name, len * sizeof(WCHAR) ); if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->handle ); } SERVER_END_REQ; return ret; }
/****************************************************************************** * SetUserObjectInformationW (USER32.@) */ BOOL WINAPI SetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DWORD len ) { BOOL ret; const USEROBJECTFLAGS *obj_flags = info; if (index != UOI_FLAGS || !info || len < sizeof(*obj_flags)) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } /* FIXME: inherit flag */ SERVER_START_REQ( set_user_object_info ) { req->handle = wine_server_obj_handle( handle ); req->flags = SET_USER_OBJECT_FLAGS; req->obj_flags = obj_flags->dwFlags; ret = !wine_server_call_err( req ); } SERVER_END_REQ; return ret; }
/****************************************************************************** * NtQueueApcThread (NTDLL.@) */ NTSTATUS WINAPI NtQueueApcThread( HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3 ) { NTSTATUS ret; SERVER_START_REQ( queue_apc ) { req->handle = wine_server_obj_handle( handle ); if (func) { req->call.type = APC_USER; req->call.user.func = wine_server_client_ptr( func ); req->call.user.args[0] = arg1; req->call.user.args[1] = arg2; req->call.user.args[2] = arg3; } else req->call.type = APC_NONE; /* wake up only */ ret = wine_server_call( req ); } SERVER_END_REQ; return ret; }
HDESK open_winstation_desktop( HWINSTA hwinsta, LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access ) { HANDLE ret = 0; DWORD len = name ? strlenW(name) : 0; if (len >= MAX_PATH) { SetLastError( ERROR_FILENAME_EXCED_RANGE ); return 0; } SERVER_START_REQ( open_desktop ) { req->winsta = wine_server_obj_handle( hwinsta ); req->flags = flags; req->access = access; req->attributes = OBJ_CASE_INSENSITIVE | (inherit ? OBJ_INHERIT : 0); wine_server_add_data( req, name, len * sizeof(WCHAR) ); if (!wine_server_call( req )) ret = wine_server_ptr_handle( reply->handle ); } SERVER_END_REQ; return ret; }
/*********************************************************************** * set_queue_display_fd * * Store the event queue fd into the message queue */ static void set_queue_display_fd(int fd) { HANDLE handle; int ret; if (wine_server_fd_to_handle(fd, GENERIC_READ | SYNCHRONIZE, 0, &handle)) { MESSAGE("macdrv: Can't allocate handle for event queue fd\n"); ExitProcess(1); } SERVER_START_REQ(set_queue_fd) { req->handle = wine_server_obj_handle(handle); ret = wine_server_call(req); } SERVER_END_REQ; if (ret) { MESSAGE("macdrv: Can't store handle for event queue fd\n"); ExitProcess(1); } CloseHandle(handle); }
/****************************************************************************** * NtQueryInformationProcess [NTDLL.@] * ZwQueryInformationProcess [NTDLL.@] * */ NTSTATUS WINAPI NtQueryInformationProcess( IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength) { 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; } }
/****************************************************************************** * NtQueryInformationProcess [NTDLL.@] * ZwQueryInformationProcess [NTDLL.@] * */ NTSTATUS WINAPI NtQueryInformationProcess( IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength) { 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(ProcessPriorityClass); 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 = ((ULONG_PTR)1 << NtCurrentTeb()->Peb->NumberOfProcessors) - 1; 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 if (!ProcessHandle) ret = STATUS_INVALID_HANDLE; else { /* FIXME : real data */ memset(&pvmi, 0 , sizeof(VM_COUNTERS)); 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; if (ProcessInformationLength >= sizeof(KERNEL_USER_TIMES)) { if (!ProcessInformation) ret = STATUS_ACCESS_VIOLATION; else if (!ProcessHandle) ret = STATUS_INVALID_HANDLE; else { /* FIXME : User- and KernelTime have to be implemented */ memset(&pti, 0, sizeof(KERNEL_USER_TIMES)); 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; } }
/*********************************************************************** * NtSetContextThread (NTDLL.@) * ZwSetContextThread (NTDLL.@) */ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context ) { NTSTATUS ret; DWORD dummy, i; BOOL self = FALSE; #ifdef __i386__ /* on i386 debug registers always require a server call */ self = (handle == GetCurrentThread()); if (self && (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386))) { self = (ntdll_get_thread_data()->dr0 == context->Dr0 && ntdll_get_thread_data()->dr1 == context->Dr1 && ntdll_get_thread_data()->dr2 == context->Dr2 && ntdll_get_thread_data()->dr3 == context->Dr3 && ntdll_get_thread_data()->dr6 == context->Dr6 && ntdll_get_thread_data()->dr7 == context->Dr7); } #endif if (!self) { context_t server_context; context_to_server( &server_context, context ); SERVER_START_REQ( set_thread_context ) { req->handle = wine_server_obj_handle( handle ); req->suspend = 1; wine_server_add_data( req, &server_context, sizeof(server_context) ); ret = wine_server_call( req ); self = reply->self; } SERVER_END_REQ; if (ret == STATUS_PENDING) { for (i = 0; i < 100; i++) { SERVER_START_REQ( set_thread_context ) { req->handle = wine_server_obj_handle( handle ); req->suspend = 0; wine_server_add_data( req, &server_context, sizeof(server_context) ); ret = wine_server_call( req ); } SERVER_END_REQ; if (ret == STATUS_PENDING) { LARGE_INTEGER timeout; timeout.QuadPart = -10000; NtDelayExecution( FALSE, &timeout ); } else break; } NtResumeThread( handle, &dummy ); if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED; } if (ret) return ret; }
/*********************************************************************** * GetUserObjectInformationW (USER32.@) */ BOOL WINAPI GetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed ) { static const WCHAR desktopW[] = { 'D','e','s','k','t','o','p',0 }; static const WCHAR winstationW[] = { 'W','i','n','d','o','w','S','t','a','t','i','o','n',0 }; BOOL ret; switch(index) { case UOI_FLAGS: { USEROBJECTFLAGS *obj_flags = info; if (needed) *needed = sizeof(*obj_flags); if (len < sizeof(*obj_flags)) { SetLastError( ERROR_BUFFER_OVERFLOW ); return FALSE; } SERVER_START_REQ( set_user_object_info ) { req->handle = wine_server_obj_handle( handle ); req->flags = 0; ret = !wine_server_call_err( req ); if (ret) { /* FIXME: inherit flag */ obj_flags->dwFlags = reply->old_obj_flags; } } SERVER_END_REQ; } return ret; case UOI_TYPE: SERVER_START_REQ( set_user_object_info ) { req->handle = wine_server_obj_handle( handle ); req->flags = 0; ret = !wine_server_call_err( req ); if (ret) { size_t size = reply->is_desktop ? sizeof(desktopW) : sizeof(winstationW); if (needed) *needed = size; if (len < size) { SetLastError( ERROR_INSUFFICIENT_BUFFER ); ret = FALSE; } else memcpy( info, reply->is_desktop ? desktopW : winstationW, size ); } } SERVER_END_REQ; return ret; case UOI_NAME: { WCHAR buffer[MAX_PATH]; SERVER_START_REQ( set_user_object_info ) { req->handle = wine_server_obj_handle( handle ); req->flags = 0; wine_server_set_reply( req, buffer, sizeof(buffer) - sizeof(WCHAR) ); ret = !wine_server_call_err( req ); if (ret) { size_t size = wine_server_reply_size( reply ); buffer[size / sizeof(WCHAR)] = 0; size += sizeof(WCHAR); if (needed) *needed = size; if (len < size) { SetLastError( ERROR_INSUFFICIENT_BUFFER ); ret = FALSE; } else memcpy( info, buffer, size ); } } SERVER_END_REQ; } return ret; case UOI_USER_SID: FIXME( "not supported index %d\n", index ); /* fall through */ default: SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } }