thread.c 43.8 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4
/*
 * Server-side thread management
 *
 * Copyright (C) 1998 Alexandre Julliard
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Alexandre Julliard's avatar
Alexandre Julliard committed
19 20
 */

21
#include "config.h"
22
#include "wine/port.h"
23

Alexandre Julliard's avatar
Alexandre Julliard committed
24
#include <assert.h>
25
#include <errno.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
26
#include <fcntl.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
27
#include <signal.h>
28
#include <stdarg.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
29 30 31
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
32
#include <sys/types.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
33
#include <unistd.h>
34
#include <time.h>
35 36 37
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
38

39 40
#include "ntstatus.h"
#define WIN32_NO_STATUS
41
#include "windef.h"
42
#include "winternl.h"
43

44
#include "file.h"
45 46 47
#include "handle.h"
#include "process.h"
#include "thread.h"
48
#include "request.h"
49
#include "user.h"
50
#include "security.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
51 52


Alexandre Julliard's avatar
Alexandre Julliard committed
53 54 55 56
/* thread queues */

struct thread_wait
{
57 58
    struct thread_wait     *next;       /* next wait structure for this thread */
    struct thread          *thread;     /* owner thread */
Alexandre Julliard's avatar
Alexandre Julliard committed
59 60
    int                     count;      /* count of objects */
    int                     flags;
61
    void                   *cookie;     /* magic cookie to return to client */
62
    timeout_t               timeout;
63
    struct timeout_user    *user;
Alexandre Julliard's avatar
Alexandre Julliard committed
64 65 66
    struct wait_queue_entry queues[1];
};

67 68 69 70
/* asynchronous procedure calls */

struct thread_apc
{
71
    struct object       obj;      /* object header */
72
    struct list         entry;    /* queue linked list */
73
    struct thread      *caller;   /* thread that queued this apc */
74
    struct object      *owner;    /* object that queued this apc */
75
    int                 executed; /* has it been executed by the client? */
76 77
    apc_call_t          call;     /* call arguments */
    apc_result_t        result;   /* call results once executed */
78 79
};

80 81
static void dump_thread_apc( struct object *obj, int verbose );
static int thread_apc_signaled( struct object *obj, struct thread *thread );
82
static void thread_apc_destroy( struct object *obj );
83
static void clear_apc_queue( struct list *queue );
84 85 86 87 88

static const struct object_ops thread_apc_ops =
{
    sizeof(struct thread_apc),  /* size */
    dump_thread_apc,            /* dump */
89
    no_get_type,                /* get_type */
90 91 92 93 94 95 96
    add_queue,                  /* add_queue */
    remove_queue,               /* remove_queue */
    thread_apc_signaled,        /* signaled */
    no_satisfied,               /* satisfied */
    no_signal,                  /* signal */
    no_get_fd,                  /* get_fd */
    no_map_access,              /* map_access */
97 98
    default_get_sd,             /* get_sd */
    default_set_sd,             /* set_sd */
99
    no_lookup_name,             /* lookup_name */
100
    no_open_file,               /* open_file */
101
    no_close_handle,            /* close_handle */
102
    thread_apc_destroy          /* destroy */
103 104
};

Alexandre Julliard's avatar
Alexandre Julliard committed
105

Alexandre Julliard's avatar
Alexandre Julliard committed
106 107
/* thread operations */

Alexandre Julliard's avatar
Alexandre Julliard committed
108
static void dump_thread( struct object *obj, int verbose );
Alexandre Julliard's avatar
Alexandre Julliard committed
109
static int thread_signaled( struct object *obj, struct thread *thread );
110
static unsigned int thread_map_access( struct object *obj, unsigned int access );
111
static void thread_poll_event( struct fd *fd, int event );
Alexandre Julliard's avatar
Alexandre Julliard committed
112 113 114 115
static void destroy_thread( struct object *obj );

static const struct object_ops thread_ops =
{
116 117
    sizeof(struct thread),      /* size */
    dump_thread,                /* dump */
118
    no_get_type,                /* get_type */
119 120 121 122
    add_queue,                  /* add_queue */
    remove_queue,               /* remove_queue */
    thread_signaled,            /* signaled */
    no_satisfied,               /* satisfied */
123
    no_signal,                  /* signal */
124
    no_get_fd,                  /* get_fd */
125
    thread_map_access,          /* map_access */
126 127
    default_get_sd,             /* get_sd */
    default_set_sd,             /* set_sd */
128
    no_lookup_name,             /* lookup_name */
129
    no_open_file,               /* open_file */
130
    no_close_handle,            /* close_handle */
131 132 133 134 135
    destroy_thread              /* destroy */
};

static const struct fd_ops thread_fd_ops =
{
136 137
    NULL,                       /* get_poll_events */
    thread_poll_event,          /* poll_event */
138 139
    NULL,                       /* flush */
    NULL,                       /* get_fd_type */
140
    NULL,                       /* ioctl */
141
    NULL,                       /* queue_async */
142
    NULL,                       /* reselect_async */
143
    NULL                        /* cancel_async */
Alexandre Julliard's avatar
Alexandre Julliard committed
144 145
};

146
static struct list thread_list = LIST_INIT(thread_list);
Alexandre Julliard's avatar
Alexandre Julliard committed
147

148
/* initialize the structure for a newly allocated thread */
149
static inline void init_thread_structure( struct thread *thread )
150 151 152
{
    int i;

153
    thread->unix_pid        = -1;  /* not known yet */
154
    thread->unix_tid        = -1;  /* not known yet */
155
    thread->context         = NULL;
156
    thread->suspend_context = NULL;
157 158 159
    thread->teb             = NULL;
    thread->debug_ctx       = NULL;
    thread->debug_event     = NULL;
160
    thread->debug_break     = 0;
161 162 163
    thread->queue           = NULL;
    thread->wait            = NULL;
    thread->error           = 0;
164 165 166 167
    thread->req_data        = NULL;
    thread->req_toread      = 0;
    thread->reply_data      = NULL;
    thread->reply_towrite   = 0;
168 169 170
    thread->request_fd      = NULL;
    thread->reply_fd        = NULL;
    thread->wait_fd         = NULL;
171 172
    thread->state           = RUNNING;
    thread->exit_code       = 0;
173
    thread->priority        = 0;
174
    thread->affinity        = ~0;
175
    thread->suspend         = 0;
176
    thread->desktop_users   = 0;
177
    thread->token           = NULL;
178

179
    thread->creation_time = current_time;
180
    thread->exit_time     = 0;
181

182
    list_init( &thread->mutex_list );
183 184 185
    list_init( &thread->system_apc );
    list_init( &thread->user_apc );

186 187 188 189
    for (i = 0; i < MAX_INFLIGHT_FDS; i++)
        thread->inflight[i].server = thread->inflight[i].client = -1;
}

190 191 192
/* check if address looks valid for a client-side data structure (TEB etc.) */
static inline int is_valid_address( void *addr )
{
193
    return addr && !((unsigned long)addr % sizeof(int));
194 195
}

196
/* create a new thread */
197
struct thread *create_thread( int fd, struct process *process )
198 199 200
{
    struct thread *thread;

201
    if (!(thread = alloc_object( &thread_ops ))) return NULL;
202

203
    init_thread_structure( thread );
204

205
    thread->process = (struct process *)grab_object( process );
206
    thread->desktop = process->desktop;
207 208
    if (!current) current = thread;

209
    list_add_head( &thread_list, &thread->entry );
Alexandre Julliard's avatar
Alexandre Julliard committed
210

211 212 213 214 215
    if (!(thread->id = alloc_ptid( thread )))
    {
        release_object( thread );
        return NULL;
    }
216
    if (!(thread->request_fd = create_anonymous_fd( &thread_fd_ops, fd, &thread->obj, 0 )))
217 218 219 220
    {
        release_object( thread );
        return NULL;
    }
221

222
    set_fd_events( thread->request_fd, POLLIN );  /* start listening to events */
223
    add_process_thread( thread->process, thread );
224
    return thread;
Alexandre Julliard's avatar
Alexandre Julliard committed
225 226
}

227
/* handle a client event */
228
static void thread_poll_event( struct fd *fd, int event )
229
{
230 231
    struct thread *thread = get_fd_user( fd );
    assert( thread->obj.ops == &thread_ops );
232

233
    if (event & (POLLERR | POLLHUP)) kill_thread( thread, 0 );
234
    else if (event & POLLIN) read_request( thread );
235
    else if (event & POLLOUT) write_reply( thread );
236 237 238 239 240 241 242 243
}

/* cleanup everything that is no longer needed by a dead thread */
/* used by destroy_thread and kill_thread */
static void cleanup_thread( struct thread *thread )
{
    int i;

244 245
    clear_apc_queue( &thread->system_apc );
    clear_apc_queue( &thread->user_apc );
246 247
    free( thread->req_data );
    free( thread->reply_data );
248 249 250
    if (thread->request_fd) release_object( thread->request_fd );
    if (thread->reply_fd) release_object( thread->reply_fd );
    if (thread->wait_fd) release_object( thread->wait_fd );
251
    free( thread->suspend_context );
252
    free_msg_queue( thread );
253
    cleanup_clipboard_thread(thread);
254
    destroy_thread_windows( thread );
255
    close_thread_desktop( thread );
256 257 258 259 260 261 262 263
    for (i = 0; i < MAX_INFLIGHT_FDS; i++)
    {
        if (thread->inflight[i].client != -1)
        {
            close( thread->inflight[i].server );
            thread->inflight[i].client = thread->inflight[i].server = -1;
        }
    }
264 265
    thread->req_data = NULL;
    thread->reply_data = NULL;
266 267 268
    thread->request_fd = NULL;
    thread->reply_fd = NULL;
    thread->wait_fd = NULL;
269 270
    thread->context = NULL;
    thread->suspend_context = NULL;
271
    thread->desktop = 0;
272 273
}

Alexandre Julliard's avatar
Alexandre Julliard committed
274 275 276 277 278 279
/* destroy a thread when its refcount is 0 */
static void destroy_thread( struct object *obj )
{
    struct thread *thread = (struct thread *)obj;
    assert( obj->ops == &thread_ops );

280
    assert( !thread->debug_ctx );  /* cannot still be debugging something */
281
    list_remove( &thread->entry );
282
    cleanup_thread( thread );
283
    release_object( thread->process );
284
    if (thread->id) free_ptid( thread->id );
285
    if (thread->token) release_object( thread->token );
Alexandre Julliard's avatar
Alexandre Julliard committed
286 287
}

Alexandre Julliard's avatar
Alexandre Julliard committed
288 289 290 291 292 293
/* dump a thread on stdout for debugging purposes */
static void dump_thread( struct object *obj, int verbose )
{
    struct thread *thread = (struct thread *)obj;
    assert( obj->ops == &thread_ops );

294 295
    fprintf( stderr, "Thread id=%04x unix pid=%d unix tid=%d teb=%p state=%d\n",
             thread->id, thread->unix_pid, thread->unix_tid, thread->teb, thread->state );
Alexandre Julliard's avatar
Alexandre Julliard committed
296 297
}

Alexandre Julliard's avatar
Alexandre Julliard committed
298 299 300 301 302 303
static int thread_signaled( struct object *obj, struct thread *thread )
{
    struct thread *mythread = (struct thread *)obj;
    return (mythread->state == TERMINATED);
}

304 305 306 307 308 309 310 311 312
static unsigned int thread_map_access( struct object *obj, unsigned int access )
{
    if (access & GENERIC_READ)    access |= STANDARD_RIGHTS_READ | SYNCHRONIZE;
    if (access & GENERIC_WRITE)   access |= STANDARD_RIGHTS_WRITE | SYNCHRONIZE;
    if (access & GENERIC_EXECUTE) access |= STANDARD_RIGHTS_EXECUTE;
    if (access & GENERIC_ALL)     access |= THREAD_ALL_ACCESS;
    return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
}

313 314 315 316 317
static void dump_thread_apc( struct object *obj, int verbose )
{
    struct thread_apc *apc = (struct thread_apc *)obj;
    assert( obj->ops == &thread_apc_ops );

318
    fprintf( stderr, "APC owner=%p type=%u\n", apc->owner, apc->call.type );
319 320 321 322
}

static int thread_apc_signaled( struct object *obj, struct thread *thread )
{
323 324
    struct thread_apc *apc = (struct thread_apc *)obj;
    return apc->executed;
325 326
}

327 328 329 330
static void thread_apc_destroy( struct object *obj )
{
    struct thread_apc *apc = (struct thread_apc *)obj;
    if (apc->caller) release_object( apc->caller );
331
    if (apc->owner) release_object( apc->owner );
332 333
}

334 335 336 337 338 339 340 341
/* queue an async procedure call */
static struct thread_apc *create_apc( struct object *owner, const apc_call_t *call_data )
{
    struct thread_apc *apc;

    if ((apc = alloc_object( &thread_apc_ops )))
    {
        apc->call        = *call_data;
342
        apc->caller      = NULL;
343 344 345
        apc->owner       = owner;
        apc->executed    = 0;
        apc->result.type = APC_NONE;
346
        if (owner) grab_object( owner );
347 348 349 350
    }
    return apc;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
351
/* get a thread pointer from a thread id (and increment the refcount) */
352
struct thread *get_thread_from_id( thread_id_t id )
Alexandre Julliard's avatar
Alexandre Julliard committed
353
{
354 355 356
    struct object *obj = get_ptid_entry( id );

    if (obj && obj->ops == &thread_ops) return (struct thread *)grab_object( obj );
357
    set_error( STATUS_INVALID_CID );
358
    return NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
359 360
}

Alexandre Julliard's avatar
Alexandre Julliard committed
361
/* get a thread from a handle (and increment the refcount) */
362
struct thread *get_thread_from_handle( obj_handle_t handle, unsigned int access )
Alexandre Julliard's avatar
Alexandre Julliard committed
363
{
Alexandre Julliard's avatar
Alexandre Julliard committed
364 365
    return (struct thread *)get_handle_obj( current->process, handle,
                                            access, &thread_ops );
Alexandre Julliard's avatar
Alexandre Julliard committed
366 367
}

368 369
/* find a thread from a Unix tid */
struct thread *get_thread_from_tid( int tid )
370
{
371
    struct thread *thread;
372

373 374
    LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry )
    {
375
        if (thread->unix_tid == tid) return thread;
376
    }
377 378 379 380 381 382 383 384
    return NULL;
}

/* find a thread from a Unix pid */
struct thread *get_thread_from_pid( int pid )
{
    struct thread *thread;

385 386 387 388
    LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry )
    {
        if (thread->unix_pid == pid) return thread;
    }
389
    return NULL;
390 391
}

392 393 394
#define THREAD_PRIORITY_REALTIME_HIGHEST 6
#define THREAD_PRIORITY_REALTIME_LOWEST -7

395
/* set all information about a thread */
396
static void set_thread_info( struct thread *thread,
397
                             const struct set_thread_info_request *req )
398 399
{
    if (req->mask & SET_THREAD_INFO_PRIORITY)
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
    {
        int max = THREAD_PRIORITY_HIGHEST;
        int min = THREAD_PRIORITY_LOWEST;
        if (thread->process->priority == PROCESS_PRIOCLASS_REALTIME)
        {
            max = THREAD_PRIORITY_REALTIME_HIGHEST;
            min = THREAD_PRIORITY_REALTIME_LOWEST;
        }
        if ((req->priority >= min && req->priority <= max) ||
            req->priority == THREAD_PRIORITY_IDLE ||
            req->priority == THREAD_PRIORITY_TIME_CRITICAL)
            thread->priority = req->priority;
        else
            set_error( STATUS_INVALID_PARAMETER );
    }
415
    if (req->mask & SET_THREAD_INFO_AFFINITY)
416
        thread->affinity = req->affinity;
417 418
    if (req->mask & SET_THREAD_INFO_TOKEN)
        security_set_thread_token( thread, req->token );
419 420
}

421 422 423
/* stop a thread (at the Unix level) */
void stop_thread( struct thread *thread )
{
424
    if (thread->context) return;  /* already inside a debug event, no need for a signal */
425 426 427 428
    /* can't stop a thread while initialisation is in progress */
    if (is_process_init_done(thread->process)) send_thread_signal( thread, SIGUSR1 );
}

429
/* suspend a thread */
430
static int suspend_thread( struct thread *thread )
431 432
{
    int old_count = thread->suspend;
433
    if (thread->suspend < MAXIMUM_SUSPEND_COUNT)
434
    {
435
        if (!(thread->process->suspend + thread->suspend++)) stop_thread( thread );
436
    }
437
    else set_error( STATUS_SUSPEND_COUNT_EXCEEDED );
438 439 440 441
    return old_count;
}

/* resume a thread */
442
static int resume_thread( struct thread *thread )
443 444 445 446
{
    int old_count = thread->suspend;
    if (thread->suspend > 0)
    {
447
        if (!(--thread->suspend + thread->process->suspend)) wake_thread( thread );
448 449
    }
    return old_count;
Alexandre Julliard's avatar
Alexandre Julliard committed
450 451 452
}

/* add a thread to an object wait queue; return 1 if OK, 0 on error */
453
int add_queue( struct object *obj, struct wait_queue_entry *entry )
Alexandre Julliard's avatar
Alexandre Julliard committed
454
{
455
    grab_object( obj );
456 457
    entry->obj = obj;
    list_add_tail( &obj->wait_queue, &entry->entry );
458
    return 1;
Alexandre Julliard's avatar
Alexandre Julliard committed
459 460 461
}

/* remove a thread from an object wait queue */
462
void remove_queue( struct object *obj, struct wait_queue_entry *entry )
Alexandre Julliard's avatar
Alexandre Julliard committed
463
{
464
    list_remove( &entry->entry );
Alexandre Julliard's avatar
Alexandre Julliard committed
465 466 467 468 469 470 471 472 473 474 475
    release_object( obj );
}

/* finish waiting */
static void end_wait( struct thread *thread )
{
    struct thread_wait *wait = thread->wait;
    struct wait_queue_entry *entry;
    int i;

    assert( wait );
476
    thread->wait = wait->next;
477 478
    for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
        entry->obj->ops->remove_queue( entry->obj, entry );
479
    if (wait->user) remove_timeout_user( wait->user );
Alexandre Julliard's avatar
Alexandre Julliard committed
480 481 482 483
    free( wait );
}

/* build the thread wait structure */
484
static int wait_on( unsigned int count, struct object *objects[], int flags, timeout_t timeout )
Alexandre Julliard's avatar
Alexandre Julliard committed
485 486 487
{
    struct thread_wait *wait;
    struct wait_queue_entry *entry;
488
    unsigned int i;
Alexandre Julliard's avatar
Alexandre Julliard committed
489

490
    if (!(wait = mem_alloc( FIELD_OFFSET(struct thread_wait, queues[count]) ))) return 0;
491 492
    wait->next    = current->wait;
    wait->thread  = current;
Alexandre Julliard's avatar
Alexandre Julliard committed
493 494
    wait->count   = count;
    wait->flags   = flags;
495
    wait->user    = NULL;
496
    wait->timeout = timeout;
497
    current->wait = wait;
Alexandre Julliard's avatar
Alexandre Julliard committed
498 499 500

    for (i = 0, entry = wait->queues; i < count; i++, entry++)
    {
501 502
        struct object *obj = objects[i];
        entry->thread = current;
503 504
        if (!obj->ops->add_queue( obj, entry ))
        {
505 506
            wait->count = i;
            end_wait( current );
507 508
            return 0;
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
509 510 511 512 513
    }
    return 1;
}

/* check if the thread waiting condition is satisfied */
514
static int check_wait( struct thread *thread )
Alexandre Julliard's avatar
Alexandre Julliard committed
515
{
516
    int i, signaled;
Alexandre Julliard's avatar
Alexandre Julliard committed
517 518 519
    struct thread_wait *wait = thread->wait;
    struct wait_queue_entry *entry = wait->queues;

520 521 522 523 524
    assert( wait );

    if ((wait->flags & SELECT_INTERRUPTIBLE) && !list_empty( &thread->system_apc ))
        return STATUS_USER_APC;

525
    /* Suspended threads may not acquire locks, but they can run system APCs */
526
    if (thread->process->suspend + thread->suspend > 0) return -1;
527

Alexandre Julliard's avatar
Alexandre Julliard committed
528 529
    if (wait->flags & SELECT_ALL)
    {
530 531 532
        int not_ok = 0;
        /* Note: we must check them all anyway, as some objects may
         * want to do something when signaled, even if others are not */
Alexandre Julliard's avatar
Alexandre Julliard committed
533
        for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
534 535
            not_ok |= !entry->obj->ops->signaled( entry->obj, thread );
        if (not_ok) goto other_checks;
Alexandre Julliard's avatar
Alexandre Julliard committed
536
        /* Wait satisfied: tell it to all objects */
537
        signaled = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
538 539
        for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
            if (entry->obj->ops->satisfied( entry->obj, thread ))
540 541
                signaled = STATUS_ABANDONED_WAIT_0;
        return signaled;
Alexandre Julliard's avatar
Alexandre Julliard committed
542 543 544 545 546 547 548
    }
    else
    {
        for (i = 0, entry = wait->queues; i < wait->count; i++, entry++)
        {
            if (!entry->obj->ops->signaled( entry->obj, thread )) continue;
            /* Wait satisfied: tell it to the object */
549
            signaled = i;
Alexandre Julliard's avatar
Alexandre Julliard committed
550
            if (entry->obj->ops->satisfied( entry->obj, thread ))
551 552
                signaled = i + STATUS_ABANDONED_WAIT_0;
            return signaled;
Alexandre Julliard's avatar
Alexandre Julliard committed
553 554
        }
    }
555 556

 other_checks:
557
    if ((wait->flags & SELECT_ALERTABLE) && !list_empty(&thread->user_apc)) return STATUS_USER_APC;
558
    if (wait->timeout <= current_time) return STATUS_TIMEOUT;
559 560 561
    return -1;
}

562 563 564 565 566 567 568 569
/* send the wakeup signal to a thread */
static int send_thread_wakeup( struct thread *thread, void *cookie, int signaled )
{
    struct wake_up_reply reply;
    int ret;

    reply.cookie   = cookie;
    reply.signaled = signaled;
570 571
    if ((ret = write( get_unix_fd( thread->wait_fd ), &reply, sizeof(reply) )) == sizeof(reply))
        return 0;
572 573 574 575 576 577 578 579 580
    if (ret >= 0)
        fatal_protocol_error( thread, "partial wakeup write %d\n", ret );
    else if (errno == EPIPE)
        kill_thread( thread, 0 );  /* normal death */
    else
        fatal_protocol_perror( thread, "write" );
    return -1;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
581
/* attempt to wake up a thread */
582
/* return >0 if OK, 0 if the wait condition is still not satisfied */
583
int wake_thread( struct thread *thread )
Alexandre Julliard's avatar
Alexandre Julliard committed
584
{
585 586
    int signaled, count;
    void *cookie;
587

588 589 590 591 592
    for (count = 0; thread->wait; count++)
    {
        if ((signaled = check_wait( thread )) == -1) break;

        cookie = thread->wait->cookie;
593 594
        if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d cookie=%p\n",
                                  thread->id, signaled, cookie );
595
        end_wait( thread );
596 597
        if (send_thread_wakeup( thread, cookie, signaled ) == -1) /* error */
	    break;
598 599
    }
    return count;
Alexandre Julliard's avatar
Alexandre Julliard committed
600 601
}

602 603 604
/* thread wait timeout */
static void thread_timeout( void *ptr )
{
605 606 607
    struct thread_wait *wait = ptr;
    struct thread *thread = wait->thread;
    void *cookie = wait->cookie;
608

609 610
    wait->user = NULL;
    if (thread->wait != wait) return; /* not the top-level wait, ignore it */
611
    if (thread->suspend + thread->process->suspend > 0) return;  /* suspended, ignore it */
612

613
    if (debug_level) fprintf( stderr, "%04x: *wakeup* signaled=%d cookie=%p\n",
614
                              thread->id, (int)STATUS_TIMEOUT, cookie );
615
    end_wait( thread );
616
    if (send_thread_wakeup( thread, cookie, STATUS_TIMEOUT ) == -1) return;
617 618
    /* check if other objects have become signaled in the meantime */
    wake_thread( thread );
619 620
}

621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
/* try signaling an event flag, a semaphore or a mutex */
static int signal_object( obj_handle_t handle )
{
    struct object *obj;
    int ret = 0;

    obj = get_handle_obj( current->process, handle, 0, NULL );
    if (obj)
    {
        ret = obj->ops->signal( obj, get_handle_access( current->process, handle ));
        release_object( obj );
    }
    return ret;
}

636
/* select on a list of handles */
637 638
static timeout_t select_on( unsigned int count, void *cookie, const obj_handle_t *handles,
                            int flags, timeout_t timeout, obj_handle_t signal_obj )
Alexandre Julliard's avatar
Alexandre Julliard committed
639
{
640 641
    int ret;
    unsigned int i;
642
    struct object *objects[MAXIMUM_WAIT_OBJECTS];
643

644 645 646
    if (timeout <= 0) timeout = current_time - timeout;

    if (count > MAXIMUM_WAIT_OBJECTS)
647
    {
648
        set_error( STATUS_INVALID_PARAMETER );
649
        return 0;
650 651 652 653 654 655
    }
    for (i = 0; i < count; i++)
    {
        if (!(objects[i] = get_handle_obj( current->process, handles[i], SYNCHRONIZE, NULL )))
            break;
    }
656 657

    if (i < count) goto done;
658
    if (!wait_on( count, objects, flags, timeout )) goto done;
659

660 661 662 663 664 665 666 667 668 669 670 671
    /* signal the object */
    if (signal_obj)
    {
        if (!signal_object( signal_obj ))
        {
            end_wait( current );
            goto done;
        }
        /* check if we woke ourselves up */
        if (!current->wait) goto done;
    }

672 673 674 675 676 677 678 679 680
    if ((ret = check_wait( current )) != -1)
    {
        /* condition is already satisfied */
        end_wait( current );
        set_error( ret );
        goto done;
    }

    /* now we need to wait */
681
    if (current->wait->timeout != TIMEOUT_INFINITE)
682
    {
683
        if (!(current->wait->user = add_timeout_user( current->wait->timeout,
684
                                                      thread_timeout, current->wait )))
685 686 687 688 689
        {
            end_wait( current );
            goto done;
        }
    }
690
    current->wait->cookie = cookie;
691 692 693
    set_error( STATUS_PENDING );

done:
694 695
    while (i > 0) release_object( objects[--i] );
    return timeout;
Alexandre Julliard's avatar
Alexandre Julliard committed
696 697 698 699 700
}

/* attempt to wake threads sleeping on the object wait queue */
void wake_up( struct object *obj, int max )
{
701
    struct list *ptr, *next;
Alexandre Julliard's avatar
Alexandre Julliard committed
702

703
    LIST_FOR_EACH_SAFE( ptr, next, &obj->wait_queue )
Alexandre Julliard's avatar
Alexandre Julliard committed
704
    {
705 706
        struct wait_queue_entry *entry = LIST_ENTRY( ptr, struct wait_queue_entry, entry );
        if (wake_thread( entry->thread ))
Alexandre Julliard's avatar
Alexandre Julliard committed
707 708 709 710 711 712
        {
            if (max && !--max) break;
        }
    }
}

713 714 715 716 717 718 719 720 721 722 723 724 725 726
/* return the apc queue to use for a given apc type */
static inline struct list *get_apc_queue( struct thread *thread, enum apc_type type )
{
    switch(type)
    {
    case APC_NONE:
    case APC_USER:
    case APC_TIMER:
        return &thread->user_apc;
    default:
        return &thread->system_apc;
    }
}

727 728 729 730 731 732 733
/* check if thread is currently waiting for a (system) apc */
static inline int is_in_apc_wait( struct thread *thread )
{
    return (thread->process->suspend || thread->suspend ||
            (thread->wait && (thread->wait->flags & SELECT_INTERRUPTIBLE)));
}

734 735
/* queue an existing APC to a given thread */
static int queue_apc( struct process *process, struct thread *thread, struct thread_apc *apc )
736
{
737 738 739 740 741
    struct list *queue;

    if (!thread)  /* find a suitable thread inside the process */
    {
        struct thread *candidate;
742

743 744 745 746
        /* first try to find a waiting thread */
        LIST_FOR_EACH_ENTRY( candidate, &process->thread_list, struct thread, proc_entry )
        {
            if (candidate->state == TERMINATED) continue;
747
            if (is_in_apc_wait( candidate ))
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
            {
                thread = candidate;
                break;
            }
        }
        if (!thread)
        {
            /* then use the first one that accepts a signal */
            LIST_FOR_EACH_ENTRY( candidate, &process->thread_list, struct thread, proc_entry )
            {
                if (send_thread_signal( candidate, SIGUSR1 ))
                {
                    thread = candidate;
                    break;
                }
            }
        }
        if (!thread) return 0;  /* nothing found */
766
        queue = get_apc_queue( thread, apc->call.type );
767 768 769 770
    }
    else
    {
        if (thread->state == TERMINATED) return 0;
771 772 773 774 775 776
        queue = get_apc_queue( thread, apc->call.type );
        /* send signal for system APCs if needed */
        if (queue == &thread->system_apc && list_empty( queue ) && !is_in_apc_wait( thread ))
        {
            if (!send_thread_signal( thread, SIGUSR1 )) return 0;
        }
777 778 779
        /* cancel a possible previous APC with the same owner */
        if (apc->owner) thread_cancel_apc( thread, apc->owner, apc->call.type );
    }
780

781
    grab_object( apc );
782 783
    list_add_tail( queue, &apc->entry );
    if (!list_prev( queue, &apc->entry ))  /* first one */
784
        wake_thread( thread );
785

786 787 788
    return 1;
}

789 790 791 792 793 794 795 796 797 798 799 800 801 802
/* queue an async procedure call */
int thread_queue_apc( struct thread *thread, struct object *owner, const apc_call_t *call_data )
{
    struct thread_apc *apc;
    int ret = 0;

    if ((apc = create_apc( owner, call_data )))
    {
        ret = queue_apc( NULL, thread, apc );
        release_object( apc );
    }
    return ret;
}

803
/* cancel the async procedure call owned by a specific object */
804
void thread_cancel_apc( struct thread *thread, struct object *owner, enum apc_type type )
805 806
{
    struct thread_apc *apc;
807 808
    struct list *queue = get_apc_queue( thread, type );

809
    LIST_FOR_EACH_ENTRY( apc, queue, struct thread_apc, entry )
810 811
    {
        if (apc->owner != owner) continue;
812
        list_remove( &apc->entry );
813 814
        apc->executed = 1;
        wake_up( &apc->obj, 0 );
815
        release_object( apc );
816 817 818 819
        return;
    }
}

820
/* remove the head apc from the queue; the returned object must be released by the caller */
821
static struct thread_apc *thread_dequeue_apc( struct thread *thread, int system_only )
822
{
823 824
    struct thread_apc *apc = NULL;
    struct list *ptr = list_head( &thread->system_apc );
825

826 827
    if (!ptr && !system_only) ptr = list_head( &thread->user_apc );
    if (ptr)
828
    {
829 830
        apc = LIST_ENTRY( ptr, struct thread_apc, entry );
        list_remove( ptr );
831 832 833 834
    }
    return apc;
}

835 836 837 838 839 840 841 842 843 844 845 846 847 848 849
/* clear an APC queue, cancelling all the APCs on it */
static void clear_apc_queue( struct list *queue )
{
    struct list *ptr;

    while ((ptr = list_head( queue )))
    {
        struct thread_apc *apc = LIST_ENTRY( ptr, struct thread_apc, entry );
        list_remove( &apc->entry );
        apc->executed = 1;
        wake_up( &apc->obj, 0 );
        release_object( apc );
    }
}

850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905
/* add an fd to the inflight list */
/* return list index, or -1 on error */
int thread_add_inflight_fd( struct thread *thread, int client, int server )
{
    int i;

    if (server == -1) return -1;
    if (client == -1)
    {
        close( server );
        return -1;
    }

    /* first check if we already have an entry for this fd */
    for (i = 0; i < MAX_INFLIGHT_FDS; i++)
        if (thread->inflight[i].client == client)
        {
            close( thread->inflight[i].server );
            thread->inflight[i].server = server;
            return i;
        }

    /* now find a free spot to store it */
    for (i = 0; i < MAX_INFLIGHT_FDS; i++)
        if (thread->inflight[i].client == -1)
        {
            thread->inflight[i].client = client;
            thread->inflight[i].server = server;
            return i;
        }
    return -1;
}

/* get an inflight fd and purge it from the list */
/* the fd must be closed when no longer used */
int thread_get_inflight_fd( struct thread *thread, int client )
{
    int i, ret;

    if (client == -1) return -1;

    do
    {
        for (i = 0; i < MAX_INFLIGHT_FDS; i++)
        {
            if (thread->inflight[i].client == client)
            {
                ret = thread->inflight[i].server;
                thread->inflight[i].server = thread->inflight[i].client = -1;
                return ret;
            }
        }
    } while (!receive_fd( thread->process ));  /* in case it is still in the socket buffer */
    return -1;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
906
/* kill a thread on the spot */
907
void kill_thread( struct thread *thread, int violent_death )
Alexandre Julliard's avatar
Alexandre Julliard committed
908
{
Alexandre Julliard's avatar
Alexandre Julliard committed
909
    if (thread->state == TERMINATED) return;  /* already killed */
Alexandre Julliard's avatar
Alexandre Julliard committed
910
    thread->state = TERMINATED;
911
    thread->exit_time = current_time;
912
    if (current == thread) current = NULL;
913
    if (debug_level)
914 915
        fprintf( stderr,"%04x: *killed* exit_code=%d\n",
                 thread->id, thread->exit_code );
916 917
    if (thread->wait)
    {
918 919
        while (thread->wait) end_wait( thread );
        send_thread_wakeup( thread, NULL, STATUS_PENDING );
920
        /* if it is waiting on the socket, we don't need to send a SIGQUIT */
921 922
        violent_death = 0;
    }
923
    kill_console_processes( thread, 0 );
924
    debug_exit_thread( thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
925
    abandon_mutexes( thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
926
    wake_up( &thread->obj, 0 );
927
    if (violent_death) send_thread_signal( thread, SIGQUIT );
928
    cleanup_thread( thread );
929
    remove_process_thread( thread->process, thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
930
    release_object( thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
931
}
932

933 934 935 936 937 938 939
/* trigger a breakpoint event in a given thread */
void break_thread( struct thread *thread )
{
    struct debug_event_exception data;

    assert( thread->context );

940
    data.record.ExceptionCode    = STATUS_BREAKPOINT;
941 942 943 944 945 946 947 948 949
    data.record.ExceptionFlags   = EXCEPTION_CONTINUABLE;
    data.record.ExceptionRecord  = NULL;
    data.record.ExceptionAddress = get_context_ip( thread->context );
    data.record.NumberParameters = 0;
    data.first = 1;
    generate_debug_event( thread, EXCEPTION_DEBUG_EVENT, &data );
    thread->debug_break = 0;
}

950 951 952 953 954 955 956
/* take a snapshot of currently running threads */
struct thread_snapshot *thread_snap( int *count )
{
    struct thread_snapshot *snapshot, *ptr;
    struct thread *thread;
    int total = 0;

957
    LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry )
958 959 960
        if (thread->state != TERMINATED) total++;
    if (!total || !(snapshot = mem_alloc( sizeof(*snapshot) * total ))) return NULL;
    ptr = snapshot;
961
    LIST_FOR_EACH_ENTRY( thread, &thread_list, struct thread, entry )
962 963 964 965 966 967 968 969 970 971 972 973
    {
        if (thread->state == TERMINATED) continue;
        ptr->thread   = thread;
        ptr->count    = thread->obj.refcount;
        ptr->priority = thread->priority;
        grab_object( thread );
        ptr++;
    }
    *count = total;
    return snapshot;
}

974 975 976 977 978 979 980 981 982
/* gets the current impersonation token */
struct token *thread_get_impersonation_token( struct thread *thread )
{
    if (thread->token)
        return thread->token;
    else
        return thread->process->token;
}

983 984 985
/* create a new thread */
DECL_HANDLER(new_thread)
{
986
    struct thread *thread;
987
    int request_fd = thread_get_inflight_fd( current, req->request_fd );
988

989
    if (request_fd == -1 || fcntl( request_fd, F_SETFL, O_NONBLOCK ) == -1)
990
    {
991
        if (request_fd != -1) close( request_fd );
992 993 994 995 996 997 998
        set_error( STATUS_INVALID_HANDLE );
        return;
    }

    if ((thread = create_thread( request_fd, current->process )))
    {
        if (req->suspend) thread->suspend++;
999
        reply->tid = get_thread_id( thread );
1000
        if ((reply->handle = alloc_handle( current->process, thread, req->access, req->attributes )))
1001
        {
1002 1003
            /* thread object will be released when the thread gets killed */
            return;
1004
        }
1005
        kill_thread( thread, 1 );
1006 1007 1008 1009 1010 1011
    }
}

/* initialize a new thread */
DECL_HANDLER(init_thread)
{
1012
    struct process *process = current->process;
1013 1014 1015
    int reply_fd = thread_get_inflight_fd( current, req->reply_fd );
    int wait_fd = thread_get_inflight_fd( current, req->wait_fd );

1016
    if (current->reply_fd)  /* already initialised */
1017
    {
1018
        set_error( STATUS_INVALID_PARAMETER );
1019 1020
        goto error;
    }
1021 1022 1023

    if (reply_fd == -1 || fcntl( reply_fd, F_SETFL, O_NONBLOCK ) == -1) goto error;

1024
    current->reply_fd = create_anonymous_fd( &thread_fd_ops, reply_fd, &current->obj, 0 );
1025 1026 1027
    reply_fd = -1;
    if (!current->reply_fd) goto error;

1028 1029
    if (wait_fd == -1)
    {
1030 1031
        set_error( STATUS_TOO_MANY_OPENED_FILES );  /* most likely reason */
        return;
1032
    }
1033
    if (!(current->wait_fd  = create_anonymous_fd( &thread_fd_ops, wait_fd, &current->obj, 0 )))
1034
        return;
1035

1036 1037 1038 1039 1040 1041
    if (!is_valid_address(req->teb) || !is_valid_address(req->peb) || !is_valid_address(req->ldt_copy))
    {
        set_error( STATUS_INVALID_PARAMETER );
        return;
    }

1042
    current->unix_pid = req->unix_pid;
1043
    current->unix_tid = req->unix_tid;
1044
    current->teb      = req->teb;
1045

1046 1047
    if (!process->peb)  /* first thread, initialize the process too */
    {
1048
        process->unix_pid = current->unix_pid;
1049 1050
        process->peb      = req->peb;
        process->ldt_copy = req->ldt_copy;
1051
        reply->info_size  = init_process( current );
1052 1053 1054
    }
    else
    {
1055 1056
        if (process->unix_pid != current->unix_pid)
            process->unix_pid = -1;  /* can happen with linuxthreads */
1057
        if (current->suspend + process->suspend > 0) stop_thread( current );
1058
        generate_debug_event( current, CREATE_THREAD_DEBUG_EVENT, req->entry );
1059 1060
    }
    debug_level = max( debug_level, req->debug_level );
1061

1062
    reply->pid     = get_process_id( process );
1063 1064
    reply->tid     = get_thread_id( current );
    reply->version = SERVER_PROTOCOL_VERSION;
1065
    reply->server_start = server_start_time;
1066 1067 1068 1069 1070 1071 1072
    return;

 error:
    if (reply_fd != -1) close( reply_fd );
    if (wait_fd != -1) close( wait_fd );
}

1073 1074 1075 1076 1077
/* terminate a thread */
DECL_HANDLER(terminate_thread)
{
    struct thread *thread;

1078 1079
    reply->self = 0;
    reply->last = 0;
1080 1081
    if ((thread = get_thread_from_handle( req->handle, THREAD_TERMINATE )))
    {
1082 1083 1084 1085
        thread->exit_code = req->exit_code;
        if (thread != current) kill_thread( thread, 1 );
        else
        {
1086 1087
            reply->self = 1;
            reply->last = (thread->process->running_threads == 1);
1088
        }
1089 1090 1091 1092
        release_object( thread );
    }
}

1093 1094 1095 1096 1097 1098 1099 1100
/* open a handle to a thread */
DECL_HANDLER(open_thread)
{
    struct thread *thread = get_thread_from_id( req->tid );

    reply->handle = 0;
    if (thread)
    {
1101
        reply->handle = alloc_handle( current->process, thread, req->access, req->attributes );
1102 1103 1104 1105
        release_object( thread );
    }
}

1106 1107 1108 1109
/* fetch information about a thread */
DECL_HANDLER(get_thread_info)
{
    struct thread *thread;
1110
    obj_handle_t handle = req->handle;
1111

1112
    if (!handle) thread = get_thread_from_id( req->tid_in );
1113 1114 1115
    else thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION );

    if (thread)
1116
    {
1117
        reply->pid            = get_process_id( thread->process );
1118 1119
        reply->tid            = get_thread_id( thread );
        reply->teb            = thread->teb;
1120
        reply->exit_code      = (thread->state == TERMINATED) ? thread->exit_code : STATUS_PENDING;
1121
        reply->priority       = thread->priority;
1122
        reply->affinity       = thread->affinity;
1123 1124
        reply->creation_time  = thread->creation_time;
        reply->exit_time      = thread->exit_time;
1125
        reply->last           = thread->process->running_threads == 1;
1126

1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
        release_object( thread );
    }
}

/* set information about a thread */
DECL_HANDLER(set_thread_info)
{
    struct thread *thread;

    if ((thread = get_thread_from_handle( req->handle, THREAD_SET_INFORMATION )))
    {
        set_thread_info( thread, req );
        release_object( thread );
    }
}

/* suspend a thread */
DECL_HANDLER(suspend_thread)
{
    struct thread *thread;
1147

1148 1149
    if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
    {
1150
        if (thread->state == TERMINATED) set_error( STATUS_ACCESS_DENIED );
1151
        else reply->count = suspend_thread( thread );
1152 1153 1154 1155 1156 1157 1158 1159
        release_object( thread );
    }
}

/* resume a thread */
DECL_HANDLER(resume_thread)
{
    struct thread *thread;
1160

1161 1162
    if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME )))
    {
1163
        reply->count = resume_thread( thread );
1164 1165 1166 1167 1168 1169 1170
        release_object( thread );
    }
}

/* select on a handle list */
DECL_HANDLER(select)
{
1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199
    struct thread_apc *apc;
    unsigned int count;
    const apc_result_t *result = get_req_data();
    const obj_handle_t *handles = (const obj_handle_t *)(result + 1);

    if (get_req_data_size() < sizeof(*result))
    {
        set_error( STATUS_INVALID_PARAMETER );
        return;
    }
    count = (get_req_data_size() - sizeof(*result)) / sizeof(obj_handle_t);

    /* first store results of previous apc */
    if (req->prev_apc)
    {
        if (!(apc = (struct thread_apc *)get_handle_obj( current->process, req->prev_apc,
                                                         0, &thread_apc_ops ))) return;
        apc->result = *result;
        apc->executed = 1;
        if (apc->result.type == APC_CREATE_THREAD)  /* transfer the handle to the caller process */
        {
            obj_handle_t handle = duplicate_handle( current->process, apc->result.create_thread.handle,
                                                    apc->caller->process, 0, 0, DUP_HANDLE_SAME_ACCESS );
            close_handle( current->process, apc->result.create_thread.handle );
            apc->result.create_thread.handle = handle;
            clear_error();  /* ignore errors from the above calls */
        }
        else if (apc->result.type == APC_ASYNC_IO)
        {
1200
            if (apc->owner) async_set_result( apc->owner, apc->result.async_io.status, apc->result.async_io.total );
1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229
        }
        wake_up( &apc->obj, 0 );
        close_handle( current->process, req->prev_apc );
        release_object( apc );
    }

    reply->timeout = select_on( count, req->cookie, handles, req->flags, req->timeout, req->signal );

    if (get_error() == STATUS_USER_APC)
    {
        for (;;)
        {
            if (!(apc = thread_dequeue_apc( current, !(req->flags & SELECT_ALERTABLE) )))
                break;
            /* Optimization: ignore APC_NONE calls, they are only used to
             * wake up a thread, but since we got here the thread woke up already.
             */
            if (apc->call.type != APC_NONE)
            {
                if ((reply->apc_handle = alloc_handle( current->process, apc, SYNCHRONIZE, 0 )))
                    reply->call = apc->call;
                release_object( apc );
                break;
            }
            apc->executed = 1;
            wake_up( &apc->obj, 0 );
            release_object( apc );
        }
    }
1230 1231
}

1232
/* queue an APC for a thread or process */
1233 1234
DECL_HANDLER(queue_apc)
{
1235 1236
    struct thread *thread = NULL;
    struct process *process = NULL;
1237 1238 1239 1240 1241
    struct thread_apc *apc;

    if (!(apc = create_apc( NULL, &req->call ))) return;

    switch (apc->call.type)
1242
    {
1243 1244
    case APC_NONE:
    case APC_USER:
1245
        thread = get_thread_from_handle( req->thread, THREAD_SET_CONTEXT );
1246 1247 1248
        break;
    case APC_VIRTUAL_ALLOC:
    case APC_VIRTUAL_FREE:
1249
    case APC_VIRTUAL_PROTECT:
1250
    case APC_VIRTUAL_FLUSH:
1251 1252
    case APC_VIRTUAL_LOCK:
    case APC_VIRTUAL_UNLOCK:
1253
    case APC_UNMAP_VIEW:
1254 1255 1256 1257 1258
        process = get_process_from_handle( req->process, PROCESS_VM_OPERATION );
        break;
    case APC_VIRTUAL_QUERY:
        process = get_process_from_handle( req->process, PROCESS_QUERY_INFORMATION );
        break;
1259 1260
    case APC_MAP_VIEW:
        process = get_process_from_handle( req->process, PROCESS_VM_OPERATION );
1261
        if (process && process != current->process)
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273
        {
            /* duplicate the handle into the target process */
            obj_handle_t handle = duplicate_handle( current->process, apc->call.map_view.handle,
                                                    process, 0, 0, DUP_HANDLE_SAME_ACCESS );
            if (handle) apc->call.map_view.handle = handle;
            else
            {
                release_object( process );
                process = NULL;
            }
        }
        break;
1274 1275
    case APC_CREATE_THREAD:
        process = get_process_from_handle( req->process, PROCESS_CREATE_THREAD );
1276 1277 1278 1279
        break;
    default:
        set_error( STATUS_INVALID_PARAMETER );
        break;
1280
    }
1281 1282 1283 1284 1285 1286 1287 1288

    if (thread)
    {
        if (!queue_apc( NULL, thread, apc )) set_error( STATUS_THREAD_IS_TERMINATING );
        release_object( thread );
    }
    else if (process)
    {
1289 1290
        reply->self = (process == current->process);
        if (!reply->self)
1291
        {
1292 1293
            obj_handle_t handle = alloc_handle( current->process, apc, SYNCHRONIZE, 0 );
            if (handle)
1294
            {
1295 1296 1297 1298 1299 1300 1301 1302 1303 1304
                if (queue_apc( process, NULL, apc ))
                {
                    apc->caller = (struct thread *)grab_object( current );
                    reply->handle = handle;
                }
                else
                {
                    close_handle( current->process, handle );
                    set_error( STATUS_PROCESS_IS_TERMINATING );
                }
1305 1306 1307 1308 1309
            }
        }
        release_object( process );
    }

1310
    release_object( apc );
1311
}
1312

1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329
/* Get the result of an APC call */
DECL_HANDLER(get_apc_result)
{
    struct thread_apc *apc;

    if (!(apc = (struct thread_apc *)get_handle_obj( current->process, req->handle,
                                                     0, &thread_apc_ops ))) return;
    if (!apc->executed) set_error( STATUS_PENDING );
    else
    {
        reply->result = apc->result;
        /* close the handle directly to avoid an extra round-trip */
        close_handle( current->process, req->handle );
    }
    release_object( apc );
}

1330 1331 1332 1333
/* retrieve the current context of a thread */
DECL_HANDLER(get_thread_context)
{
    struct thread *thread;
1334
    CONTEXT *context;
1335 1336 1337 1338 1339 1340 1341 1342

    if (get_reply_max_size() < sizeof(CONTEXT))
    {
        set_error( STATUS_INVALID_PARAMETER );
        return;
    }
    if (!(thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT ))) return;

1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362
    if (req->suspend)
    {
        if (thread != current || !thread->suspend_context)
        {
            /* not suspended, shouldn't happen */
            set_error( STATUS_INVALID_PARAMETER );
        }
        else
        {
            if (thread->context == thread->suspend_context) thread->context = NULL;
            set_reply_data_ptr( thread->suspend_context, sizeof(CONTEXT) );
            thread->suspend_context = NULL;
        }
    }
    else if (thread != current && !thread->context)
    {
        /* thread is not suspended, retry (if it's still running) */
        if (thread->state != RUNNING) set_error( STATUS_ACCESS_DENIED );
        else set_error( STATUS_PENDING );
    }
1363
    else if ((context = set_reply_data_size( sizeof(CONTEXT) )))
1364
    {
1365 1366 1367 1368 1369 1370
        unsigned int flags = get_context_system_regs( req->flags );

        memset( context, 0, sizeof(CONTEXT) );
        context->ContextFlags = get_context_cpu_flag();
        if (thread->context) copy_context( context, thread->context, req->flags & ~flags );
        if (flags) get_thread_context( thread, context, flags );
1371
    }
1372
    reply->self = (thread == current);
1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385
    release_object( thread );
}

/* set the current context of a thread */
DECL_HANDLER(set_thread_context)
{
    struct thread *thread;

    if (get_req_data_size() < sizeof(CONTEXT))
    {
        set_error( STATUS_INVALID_PARAMETER );
        return;
    }
1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398
    if (!(thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT ))) return;

    if (req->suspend)
    {
        if (thread != current || thread->context)
        {
            /* nested suspend or exception, shouldn't happen */
            set_error( STATUS_INVALID_PARAMETER );
        }
        else if ((thread->suspend_context = mem_alloc( sizeof(CONTEXT) )))
        {
            memcpy( thread->suspend_context, get_req_data(), sizeof(CONTEXT) );
            thread->context = thread->suspend_context;
1399
            if (thread->debug_break) break_thread( thread );
1400 1401 1402 1403 1404 1405 1406 1407 1408
        }
    }
    else if (thread != current && !thread->context)
    {
        /* thread is not suspended, retry (if it's still running) */
        if (thread->state != RUNNING) set_error( STATUS_ACCESS_DENIED );
        else set_error( STATUS_PENDING );
    }
    else
1409
    {
1410 1411 1412 1413 1414 1415
        const CONTEXT *context = get_req_data();
        unsigned int flags = get_context_system_regs( req->flags );

        if (flags) set_thread_context( thread, context, flags );
        if (thread->context && !get_error())
            copy_context( thread->context, context, req->flags & ~flags );
1416
    }
1417
    reply->self = (thread == current);
1418
    release_object( thread );
1419 1420
}

1421 1422 1423 1424 1425 1426
/* fetch a selector entry for a thread */
DECL_HANDLER(get_selector_entry)
{
    struct thread *thread;
    if ((thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION )))
    {
1427
        get_selector_entry( thread, req->entry, &reply->base, &reply->limit, &reply->flags );
1428 1429 1430
        release_object( thread );
    }
}