Example #1
0
/***********************************************************************
 *           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) );
}
Example #2
0
/***********************************************************************
 *           terminate_thread
 */
void terminate_thread( int status )
{
    pthread_sigmask( SIG_BLOCK, &server_block_set, 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) );
}
Example #3
0
/***********************************************************************
 *           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) );
}
Example #4
0
/***********************************************************************
 *           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) );
}
Example #5
0
/***********************************************************************
 *              RtlCreateUserThread   (NTDLL.@)
 */
NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *descr,
                                     BOOLEAN suspended, PVOID stack_addr,
                                     SIZE_T stack_reserve, SIZE_T stack_commit,
                                     PRTL_THREAD_START_ROUTINE start, void *param,
                                     HANDLE *handle_ptr, CLIENT_ID *id )
{
    sigset_t sigset;
    pthread_t pthread_id;
    pthread_attr_t attr;
    struct ntdll_thread_data *thread_data;
    struct startup_info *info = NULL;
    HANDLE handle = 0, actctx = 0;
    TEB *teb = NULL;
    DWORD tid = 0;
    int request_pipe[2];
    NTSTATUS status;

    if (process != NtCurrentProcess())
    {
        apc_call_t call;
        apc_result_t result;

        memset( &call, 0, sizeof(call) );

        call.create_thread.type    = APC_CREATE_THREAD;
        call.create_thread.func    = wine_server_client_ptr( start );
        call.create_thread.arg     = wine_server_client_ptr( param );
        call.create_thread.reserve = stack_reserve;
        call.create_thread.commit  = stack_commit;
        call.create_thread.suspend = suspended;
        status = server_queue_process_apc( process, &call, &result );
        if (status != STATUS_SUCCESS) return status;

        if (result.create_thread.status == STATUS_SUCCESS)
        {
            if (id) id->UniqueThread = ULongToHandle(result.create_thread.tid);
            if (handle_ptr) *handle_ptr = wine_server_ptr_handle( result.create_thread.handle );
            else NtClose( wine_server_ptr_handle( result.create_thread.handle ));
        }
        return result.create_thread.status;
    }

    if (server_pipe( request_pipe ) == -1) return STATUS_TOO_MANY_OPENED_FILES;
    wine_server_send_fd( request_pipe[0] );

    SERVER_START_REQ( new_thread )
    {
        req->access     = THREAD_ALL_ACCESS;
        req->attributes = 0;  /* FIXME */
        req->suspend    = suspended;
        req->request_fd = request_pipe[0];
        if (!(status = wine_server_call( req )))
        {
            handle = wine_server_ptr_handle( reply->handle );
            tid = reply->tid;
        }
        close( request_pipe[0] );
    }
    SERVER_END_REQ;

    if (status)
    {
        close( request_pipe[1] );
        return status;
    }

    pthread_sigmask( SIG_BLOCK, &server_block_set, &sigset );

    if ((status = signal_alloc_thread( &teb ))) goto error;

    teb->Peb = NtCurrentTeb()->Peb;
    teb->ClientId.UniqueProcess = ULongToHandle(GetCurrentProcessId());
    teb->ClientId.UniqueThread  = ULongToHandle(tid);
    teb->StaticUnicodeString.Buffer        = teb->StaticUnicodeBuffer;
    teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);

    /* create default activation context frame for new thread */
    RtlGetActiveActivationContext(&actctx);
    if (actctx)
    {
        RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;

        frame = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*frame));
        frame->Previous = NULL;
        frame->ActivationContext = actctx;
        frame->Flags = 0;
        teb->ActivationContextStack.ActiveFrame = frame;

        RtlAddRefActivationContext(actctx);
    }

    info = (struct startup_info *)(teb + 1);
    info->teb         = teb;
    info->entry_point = start;
    info->entry_arg   = param;

    thread_data = (struct ntdll_thread_data *)teb->SpareBytes1;
    thread_data->request_fd  = request_pipe[1];
    thread_data->reply_fd    = -1;
    thread_data->wait_fd[0]  = -1;
    thread_data->wait_fd[1]  = -1;

    if ((status = virtual_alloc_thread_stack( teb, stack_reserve, stack_commit ))) goto error;

    pthread_attr_init( &attr );
    pthread_attr_setstack( &attr, teb->DeallocationStack,
                           (char *)teb->Tib.StackBase - (char *)teb->DeallocationStack );
    pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM ); /* force creating a kernel thread */
    interlocked_xchg_add( &nb_threads, 1 );
    if (pthread_create( &pthread_id, &attr, (void * (*)(void *))start_thread, info ))
    {
        interlocked_xchg_add( &nb_threads, -1 );
        pthread_attr_destroy( &attr );
        status = STATUS_NO_MEMORY;
        goto error;
    }
    pthread_attr_destroy( &attr );
    pthread_sigmask( SIG_SETMASK, &sigset, NULL );

    if (id) id->UniqueThread = ULongToHandle(tid);
    if (handle_ptr) *handle_ptr = handle;
    else NtClose( handle );

    return STATUS_SUCCESS;

error:
    if (teb) signal_free_thread( teb );
    if (handle) NtClose( handle );
    pthread_sigmask( SIG_SETMASK, &sigset, NULL );
    close( request_pipe[1] );
    return status;
}
Example #6
0
File: hook.c Project: AndreRH/wine
/***********************************************************************
 *		call_hook
 *
 * Call hook either in current thread or send message to the destination
 * thread.
 */
static LRESULT call_hook( struct hook_info *info, INT code, WPARAM wparam, LPARAM lparam )
{
    DWORD_PTR ret = 0;

    if (info->tid)
    {
        struct hook_extra_info h_extra;
        h_extra.handle = info->handle;
        h_extra.lparam = lparam;

        TRACE( "calling hook in thread %04x %s code %x wp %lx lp %lx\n",
               info->tid, hook_names[info->id-WH_MINHOOK], code, wparam, lparam );

        switch(info->id)
        {
        case WH_KEYBOARD_LL:
            MSG_SendInternalMessageTimeout( info->pid, info->tid, WM_WINE_KEYBOARD_LL_HOOK,
                                            wparam, (LPARAM)&h_extra, SMTO_ABORTIFHUNG,
                                            get_ll_hook_timeout(), &ret );
            break;
        case WH_MOUSE_LL:
            MSG_SendInternalMessageTimeout( info->pid, info->tid, WM_WINE_MOUSE_LL_HOOK,
                                            wparam, (LPARAM)&h_extra, SMTO_ABORTIFHUNG,
                                            get_ll_hook_timeout(), &ret );
            break;
        default:
            ERR("Unknown hook id %d\n", info->id);
            assert(0);
            break;
        }
    }
    else if (info->proc)
    {
        struct user_thread_info *thread_info = get_user_thread_info();
        HMODULE free_module = 0;

        /*
         * Windows protects from stack overflow in recursive hook calls. Different Windows
         * allow different depths.
         */
        if (thread_info->hook_call_depth >= 25)
        {
            WARN("Too many hooks called recursively, skipping call.\n");
            return 0;
        }

        TRACE( "calling hook %p %s code %x wp %lx lp %lx module %s\n",
               info->proc, hook_names[info->id-WH_MINHOOK], code, wparam,
               lparam, debugstr_w(info->module) );

        if (!info->module[0] ||
            (info->proc = get_hook_proc( info->proc, info->module, &free_module )) != NULL)
        {
            HHOOK prev = thread_info->hook;
            BOOL prev_unicode = thread_info->hook_unicode;

            thread_info->hook = info->handle;
            thread_info->hook_unicode = info->next_unicode;
            thread_info->hook_call_depth++;
            ret = call_hook_proc( info->proc, info->id, code, wparam, lparam,
                                  info->prev_unicode, info->next_unicode );
            thread_info->hook = prev;
            thread_info->hook_unicode = prev_unicode;
            thread_info->hook_call_depth--;

            if (free_module) FreeLibrary(free_module);
        }
    }

    if (info->id == WH_KEYBOARD_LL || info->id == WH_MOUSE_LL)
        interlocked_xchg_add( &global_key_state_counter, 1 );  /* force refreshing the key state cache */

    return ret;
}
Example #7
0
static inline LONG interlocked_dec( PLONG dest )
{
    return interlocked_xchg_add( dest, -1 ) - 1;
}
Example #8
0
static inline LONG interlocked_inc( PLONG dest )
{
    return interlocked_xchg_add( dest, 1 ) + 1;
}