static inline BOOL find_next_hook(DWORD event, HWND hwnd, LONG object_id, LONG child_id, struct hook_info *info) { BOOL ret; SERVER_START_REQ( get_hook_info ) { req->handle = wine_server_user_handle( info->handle ); req->get_next = 1; req->event = event; req->window = wine_server_user_handle( hwnd ); req->object_id = object_id; req->child_id = child_id; wine_server_set_reply( req, info->module, sizeof(info->module)-sizeof(WCHAR) ); ret = !wine_server_call( req ); if (ret) { info->module[wine_server_reply_size(req) / sizeof(WCHAR)] = 0; info->handle = wine_server_ptr_handle( reply->handle ); info->proc = wine_server_get_ptr( reply->proc ); info->tid = reply->tid; } } 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; }
/*********************************************************************** * server_init_process_done */ NTSTATUS server_init_process_done(void) { PEB *peb = NtCurrentTeb()->Peb; IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress ); NTSTATUS status; /* Install signal handlers; this cannot be done earlier, since we cannot * send exceptions to the debugger before the create process event that * is sent by REQ_INIT_PROCESS_DONE. * We do need the handlers in place by the time the request is over, so * we set them up here. If we segfault between here and the server call * something is very wrong... */ if (!SIGNAL_Init()) exit(1); /* Signal the parent process to continue */ SERVER_START_REQ( init_process_done ) { req->module = peb->ImageBaseAddress; req->entry = (char *)peb->ImageBaseAddress + nt->OptionalHeader.AddressOfEntryPoint; req->gui = (nt->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_CUI); status = wine_server_call( req ); } SERVER_END_REQ; return status; }
/***************************************************************** * CARET_Callback */ static void CALLBACK CARET_Callback( HWND hwnd, UINT msg, UINT_PTR id, DWORD ctime) { BOOL ret; RECT r; int old_state = 0; int hidden = 0; SERVER_START_REQ( set_caret_info ) { req->flags = SET_CARET_STATE; req->handle = hwnd; req->x = 0; req->y = 0; req->hide = 0; req->state = -1; /* toggle current state */ if ((ret = !wine_server_call( req ))) { hwnd = reply->full_handle; r.left = reply->old_rect.left; r.top = reply->old_rect.top; r.right = reply->old_rect.right; r.bottom = reply->old_rect.bottom; old_state = reply->old_state; hidden = reply->old_hide; } } SERVER_END_REQ; if (ret && !hidden) CARET_DisplayCaret( hwnd, &r ); }
/****************************************************************************** * NtDuplicateToken [NTDLL.@] * ZwDuplicateToken [NTDLL.@] */ NTSTATUS WINAPI NtDuplicateToken( IN HANDLE ExistingToken, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, IN TOKEN_TYPE TokenType, OUT PHANDLE NewToken) { NTSTATUS status; TRACE("(%p,0x%08lx,%p,0x%08x,0x%08x,%p)\n", ExistingToken, DesiredAccess, ObjectAttributes, ImpersonationLevel, TokenType, NewToken); dump_ObjectAttributes(ObjectAttributes); SERVER_START_REQ( duplicate_token ) { req->handle = ExistingToken; req->access = DesiredAccess; req->attributes = ObjectAttributes ? ObjectAttributes->Attributes : 0; req->primary = (TokenType == TokenPrimary); req->impersonation_level = ImpersonationLevel; status = wine_server_call( req ); if (!status) *NewToken = reply->new_handle; } SERVER_END_REQ; return status; }
/*********************************************************************** * send_mouse_input * * Update the various window states on a mouse event. */ static void send_mouse_input(HWND hwnd, UINT flags, int x, int y, DWORD mouse_data, unsigned long time) { INPUT input; HWND top_level_hwnd; top_level_hwnd = GetAncestor(hwnd, GA_ROOT); if ((flags & MOUSEEVENTF_MOVE) && (flags & MOUSEEVENTF_ABSOLUTE)) { RECT rect; /* update the wine server Z-order */ SetRect(&rect, x, y, x + 1, y + 1); MapWindowPoints(0, top_level_hwnd, (POINT *)&rect, 2); SERVER_START_REQ(update_window_zorder) { req->window = wine_server_user_handle(top_level_hwnd); req->rect.left = rect.left; req->rect.top = rect.top; req->rect.right = rect.right; req->rect.bottom = rect.bottom; wine_server_call(req); } SERVER_END_REQ; }
/****************************************************************************** * EnumWindowStationsW (USER32.@) */ BOOL WINAPI EnumWindowStationsW( WINSTAENUMPROCW func, LPARAM lparam ) { unsigned int index = 0; WCHAR name[MAX_PATH]; BOOL ret = TRUE; NTSTATUS status; while (ret) { SERVER_START_REQ( enum_winstation ) { 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; }
/*********************************************************************** * CreateDesktopW (USER32.@) */ HDESK WINAPI CreateDesktopW( LPCWSTR name, LPCWSTR device, LPDEVMODEW devmode, DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa ) { HANDLE ret; DWORD len = name ? strlenW(name) : 0; if (device || devmode) { SetLastError( ERROR_INVALID_PARAMETER ); return 0; } if (len >= MAX_PATH) { SetLastError( ERROR_FILENAME_EXCED_RANGE ); return 0; } SERVER_START_REQ( create_desktop ) { req->flags = flags; req->access = access; req->attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF | ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0); wine_server_add_data( req, name, len * sizeof(WCHAR) ); /* it doesn't seem to set last error */ wine_server_call( req ); ret = wine_server_ptr_handle( reply->handle ); } SERVER_END_REQ; return ret; }
/****************************************************************************** * NtOpenThreadToken [NTDLL.@] * ZwOpenThreadToken [NTDLL.@] */ NTSTATUS WINAPI NtOpenThreadToken( HANDLE ThreadHandle, DWORD DesiredAccess, BOOLEAN OpenAsSelf, HANDLE *TokenHandle) { NTSTATUS ret; TRACE("(%p,0x%08lx,0x%08x,%p)\n", ThreadHandle,DesiredAccess, OpenAsSelf, TokenHandle); SERVER_START_REQ( open_token ) { req->handle = ThreadHandle; req->access = DesiredAccess; req->attributes = 0; req->flags = OPEN_TOKEN_THREAD; if (OpenAsSelf) req->flags |= OPEN_TOKEN_AS_SELF; ret = wine_server_call( req ); if (!ret) *TokenHandle = reply->token; } SERVER_END_REQ; return ret; }
/*********************************************************************** * CreateWindowStationW (USER32.@) */ HWINSTA WINAPI CreateWindowStationW( LPCWSTR name, DWORD reserved, 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 | OBJ_OPENIF | ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0); wine_server_add_data( req, name, len * sizeof(WCHAR) ); /* it doesn't seem to set last error */ wine_server_call( req ); ret = wine_server_ptr_handle( reply->handle ); } SERVER_END_REQ; return ret; }
static inline BOOL find_first_hook(DWORD id, DWORD event, HWND hwnd, LONG object_id, LONG child_id, struct hook_info *info) { struct user_thread_info *thread_info = get_user_thread_info(); BOOL ret; if (!HOOK_IsHooked( id )) { TRACE( "skipping hook %s mask %x\n", hook_names[id-WH_MINHOOK], thread_info->active_hooks ); return FALSE; } SERVER_START_REQ( start_hook_chain ) { req->id = id; req->event = event; req->window = wine_server_user_handle( hwnd ); req->object_id = object_id; req->child_id = child_id; wine_server_set_reply( req, info->module, sizeof(info->module)-sizeof(WCHAR) ); ret = !wine_server_call( req ); if (ret) { info->module[wine_server_reply_size(req) / sizeof(WCHAR)] = 0; info->handle = wine_server_ptr_handle( reply->handle ); info->proc = wine_server_get_ptr( reply->proc ); info->tid = reply->tid; thread_info->active_hooks = reply->active_hooks; } } SERVER_END_REQ; return ret && (info->tid || info->proc); }
/*********************************************************************** * HOOK_CallHooks */ LRESULT HOOK_CallHooks( INT id, INT code, WPARAM wparam, LPARAM lparam, BOOL unicode ) { struct user_thread_info *thread_info = get_user_thread_info(); struct hook_info info; DWORD_PTR ret = 0; USER_CheckNotLock(); if (!HOOK_IsHooked( id )) { TRACE( "skipping hook %s mask %x\n", hook_names[id-WH_MINHOOK], thread_info->active_hooks ); return 0; } ZeroMemory( &info, sizeof(info) - sizeof(info.module) ); info.prev_unicode = unicode; info.id = id; SERVER_START_REQ( start_hook_chain ) { req->id = info.id; req->event = EVENT_MIN; wine_server_set_reply( req, info.module, sizeof(info.module)-sizeof(WCHAR) ); if (!wine_server_call( req )) { info.module[wine_server_reply_size(req) / sizeof(WCHAR)] = 0; info.handle = wine_server_ptr_handle( reply->handle ); info.pid = reply->pid; info.tid = reply->tid; info.proc = wine_server_get_ptr( reply->proc ); info.next_unicode = reply->unicode; thread_info->active_hooks = reply->active_hooks; } } SERVER_END_REQ; if (!info.tid && !info.proc) return 0; ret = call_hook( &info, code, wparam, lparam ); SERVER_START_REQ( finish_hook_chain ) { req->id = id; wine_server_call( req ); } SERVER_END_REQ; return ret; }
/*********************************************************************** * send_mouse_input * * Update the various window states on a mouse event. */ static void send_mouse_input( HWND hwnd, UINT flags, Window window, int x, int y, unsigned int state, DWORD mouse_data, Time time ) { struct x11drv_win_data *data = X11DRV_get_win_data( hwnd ); POINT pt; INPUT input; if (!data) return; if (window == data->whole_window) { x += data->whole_rect.left - data->client_rect.left; y += data->whole_rect.top - data->client_rect.top; } if (window == root_window) { x += virtual_screen_rect.left; y += virtual_screen_rect.top; } pt.x = x; pt.y = y; if (GetWindowLongW( data->hwnd, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL) pt.x = data->client_rect.right - data->client_rect.left - 1 - pt.x; MapWindowPoints( hwnd, 0, &pt, 1 ); if (InterlockedExchangePointer( (void **)&cursor_window, hwnd ) != hwnd || GetTickCount() - last_time_modified > 100) { cursor_window = hwnd; sync_window_cursor( data ); } last_time_modified = GetTickCount(); if (hwnd != GetDesktopWindow()) hwnd = GetAncestor( hwnd, GA_ROOT ); /* update the wine server Z-order */ if (window != x11drv_thread_data()->grab_window && /* ignore event if a button is pressed, since the mouse is then grabbed too */ !(state & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask|Button6Mask|Button7Mask))) { RECT rect; SetRect( &rect, pt.x, pt.y, pt.x + 1, pt.y + 1 ); MapWindowPoints( 0, hwnd, (POINT *)&rect, 2 ); SERVER_START_REQ( update_window_zorder ) { req->window = wine_server_user_handle( hwnd ); req->rect.left = rect.left; req->rect.top = rect.top; req->rect.right = rect.right; req->rect.bottom = rect.bottom; wine_server_call( req ); } SERVER_END_REQ; }
/*********************************************************************** * __wine_make_process_system (NTDLL.@) * * Mark the current process as a system process. * Returns the event that is signaled when all non-system processes have exited. */ HANDLE CDECL __wine_make_process_system(void) { HANDLE ret = 0; SERVER_START_REQ( make_process_system ) { if (!wine_server_call( req )) ret = wine_server_ptr_handle( reply->event ); } 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) ); }
static DWORD DEVICE_GetClientID( HANDLE handle ) { DWORD ret = 0; SERVER_START_REQ( get_file_info ) { req->handle = handle; if (!wine_server_call( req ) && (reply->type == FILE_TYPE_UNKNOWN)) ret = reply->attr; } SERVER_END_REQ; return ret; }
/************************************************************************** * NtClose [NTDLL.@] * FUNCTION: Closes a handle reference to an object * ARGUMENTS: * Handle handle to close */ NTSTATUS WINAPI NtClose( HANDLE Handle ) { NTSTATUS ret; SERVER_START_REQ( close_handle ) { req->handle = Handle; ret = wine_server_call( req ); if (!ret && reply->fd != -1) close( reply->fd ); } 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; }
/*********************************************************************** * server_init_thread * * Send an init thread request. Return 0 if OK. */ size_t server_init_thread( int unix_pid, int unix_tid, void *entry_point ) { int ret; int reply_pipe[2]; struct sigaction sig_act; size_t info_size; sig_act.sa_handler = SIG_IGN; sig_act.sa_flags = 0; sigemptyset( &sig_act.sa_mask ); /* ignore SIGPIPE so that we get an EPIPE error instead */ sigaction( SIGPIPE, &sig_act, NULL ); /* automatic child reaping to avoid zombies */ #ifdef SA_NOCLDWAIT sig_act.sa_flags |= SA_NOCLDWAIT; #endif sigaction( SIGCHLD, &sig_act, NULL ); /* create the server->client communication pipes */ if (pipe( reply_pipe ) == -1) server_protocol_perror( "pipe" ); if (pipe( ntdll_get_thread_data()->wait_fd ) == -1) server_protocol_perror( "pipe" ); wine_server_send_fd( reply_pipe[1] ); wine_server_send_fd( ntdll_get_thread_data()->wait_fd[1] ); ntdll_get_thread_data()->reply_fd = reply_pipe[0]; close( reply_pipe[1] ); /* set close on exec flag */ fcntl( ntdll_get_thread_data()->reply_fd, F_SETFD, 1 ); fcntl( ntdll_get_thread_data()->wait_fd[0], F_SETFD, 1 ); fcntl( ntdll_get_thread_data()->wait_fd[1], F_SETFD, 1 ); SERVER_START_REQ( init_thread ) { req->unix_pid = unix_pid; req->unix_tid = unix_tid; req->teb = wine_server_client_ptr( NtCurrentTeb() ); req->peb = wine_server_client_ptr( NtCurrentTeb()->Peb ); req->entry = wine_server_client_ptr( entry_point ); req->reply_fd = reply_pipe[1]; req->wait_fd = ntdll_get_thread_data()->wait_fd[1]; req->debug_level = (TRACE_ON(server) != 0); ret = wine_server_call( req ); NtCurrentTeb()->ClientId.UniqueProcess = ULongToHandle(reply->pid); NtCurrentTeb()->ClientId.UniqueThread = ULongToHandle(reply->tid); info_size = reply->info_size; server_start_time = reply->server_start; } SERVER_END_REQ; if (ret) server_protocol_error( "init_thread failed with status %x\n", ret ); return info_size; }
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 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 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; }
/********************************************************************** * GetKeyState (USER32.@) * * An application calls the GetKeyState function in response to a * keyboard-input message. This function retrieves the state of the key * at the time the input message was generated. */ SHORT WINAPI DECLSPEC_HOTPATCH GetKeyState(INT vkey) { SHORT retval = 0; SERVER_START_REQ( get_key_state ) { req->tid = GetCurrentThreadId(); req->key = vkey; if (!wine_server_call( req )) retval = (signed char)reply->state; } SERVER_END_REQ; TRACE("key (0x%x) -> %x\n", vkey, retval); return retval; }
/************************************************************************** * CLIPBOARD_OpenClipboard */ static BOOL CLIPBOARD_OpenClipboard(HWND hWnd) { BOOL bRet; SERVER_START_REQ( set_clipboard_info ) { req->flags = SET_CB_OPEN; req->clipboard = wine_server_user_handle( hWnd ); bRet = !wine_server_call( req ); } SERVER_END_REQ; return bRet; }
/*********************************************************************** * sync_window_cursor */ void sync_window_cursor( struct x11drv_win_data *data ) { HCURSOR cursor; SERVER_START_REQ( set_cursor ) { req->flags = 0; wine_server_call( req ); cursor = reply->prev_count >= 0 ? wine_server_ptr_handle( reply->prev_handle ) : 0; } SERVER_END_REQ; if (data->cursor != cursor) set_window_cursor( data, cursor ); }
/*********************************************************************** * 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) ); }
/*********************************************************************** * GetInputState (USER32.@) */ BOOL WINAPI GetInputState(void) { DWORD ret = 0; /* check for pending X events */ USER_Driver->pMsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_INPUT, 0 ); SERVER_START_REQ( get_queue_status ) { req->clear = 0; wine_server_call( req ); ret = reply->wake_bits & (QS_KEY | QS_MOUSEBUTTON); } SERVER_END_REQ; return ret; }
/*********************************************************************** * NtOpenThread (NTDLL.@) * ZwOpenThread (NTDLL.@) */ NTSTATUS WINAPI NtOpenThread( HANDLE *handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, const CLIENT_ID *id ) { NTSTATUS ret; SERVER_START_REQ( open_thread ) { req->tid = HandleToULong(id->UniqueThread); req->access = access; req->attributes = attr ? attr->Attributes : 0; ret = wine_server_call( req ); *handle = wine_server_ptr_handle( reply->handle ); } SERVER_END_REQ; return ret; }