process.c 33.5 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4
/*
 * Server-side process 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>
Alexandre Julliard's avatar
Alexandre Julliard committed
25
#include <limits.h>
26
#include <signal.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
27
#include <string.h>
28
#include <stdarg.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
29
#include <stdio.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
30
#include <stdlib.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
31
#include <sys/time.h>
32 33 34
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
35
#include <unistd.h>
36 37 38
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
39

40 41
#include "ntstatus.h"
#define WIN32_NO_STATUS
42
#include "winternl.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
43

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

53
/* process structure */
54

55
static struct list process_list = LIST_INIT(process_list);
56
static int running_processes;
Alexandre Julliard's avatar
Alexandre Julliard committed
57 58 59

/* process operations */

60
static void process_dump( struct object *obj, int verbose );
Alexandre Julliard's avatar
Alexandre Julliard committed
61
static int process_signaled( struct object *obj, struct thread *thread );
62
static unsigned int process_map_access( struct object *obj, unsigned int access );
63
static void process_poll_event( struct fd *fd, int event );
64
static void process_destroy( struct object *obj );
Alexandre Julliard's avatar
Alexandre Julliard committed
65 66 67

static const struct object_ops process_ops =
{
68 69 70 71 72 73
    sizeof(struct process),      /* size */
    process_dump,                /* dump */
    add_queue,                   /* add_queue */
    remove_queue,                /* remove_queue */
    process_signaled,            /* signaled */
    no_satisfied,                /* satisfied */
74
    no_signal,                   /* signal */
75
    no_get_fd,                   /* get_fd */
76
    process_map_access,          /* map_access */
77
    no_lookup_name,              /* lookup_name */
78
    no_close_handle,             /* close_handle */
79 80 81 82 83
    process_destroy              /* destroy */
};

static const struct fd_ops process_fd_ops =
{
84
    NULL,                        /* get_poll_events */
85
    process_poll_event,          /* poll_event */
86 87
    no_flush,                    /* flush */
    no_get_file_info,            /* get_file_info */
88 89
    no_queue_async,              /* queue_async */
    no_cancel_async              /* cancel async */
Alexandre Julliard's avatar
Alexandre Julliard committed
90 91
};

92 93 94
/* process startup info */

struct startup_info
95
{
96
    struct object       obj;          /* object header */
97 98 99
    obj_handle_t        hstdin;       /* handle for stdin */
    obj_handle_t        hstdout;      /* handle for stdout */
    obj_handle_t        hstderr;      /* handle for stderr */
100
    struct file        *exe_file;     /* file handle for main exe */
101
    struct process     *process;      /* created process */
102
    data_size_t         data_size;    /* size of startup data */
103
    void               *data;         /* data for startup info */
104
};
Alexandre Julliard's avatar
Alexandre Julliard committed
105

106 107 108 109 110
static void startup_info_dump( struct object *obj, int verbose );
static int startup_info_signaled( struct object *obj, struct thread *thread );
static void startup_info_destroy( struct object *obj );

static const struct object_ops startup_info_ops =
111
{
112 113 114 115 116 117
    sizeof(struct startup_info),   /* size */
    startup_info_dump,             /* dump */
    add_queue,                     /* add_queue */
    remove_queue,                  /* remove_queue */
    startup_info_signaled,         /* signaled */
    no_satisfied,                  /* satisfied */
118
    no_signal,                     /* signal */
119
    no_get_fd,                     /* get_fd */
120
    no_map_access,                 /* map_access */
121
    no_lookup_name,                /* lookup_name */
122
    no_close_handle,               /* close_handle */
123 124 125
    startup_info_destroy           /* destroy */
};

126

127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
struct ptid_entry
{
    void        *ptr;   /* entry ptr */
    unsigned int next;  /* next free entry */
};

static struct ptid_entry *ptid_entries;     /* array of ptid entries */
static unsigned int used_ptid_entries;      /* number of entries in use */
static unsigned int alloc_ptid_entries;     /* number of allocated entries */
static unsigned int next_free_ptid;         /* next free entry */
static unsigned int last_free_ptid;         /* last free entry */

#define PTID_OFFSET 8  /* offset for first ptid value */

/* allocate a new process or thread id */
unsigned int alloc_ptid( void *ptr )
{
    struct ptid_entry *entry;
    unsigned int id;

    if (used_ptid_entries < alloc_ptid_entries)
    {
        id = used_ptid_entries + PTID_OFFSET;
        entry = &ptid_entries[used_ptid_entries++];
    }
    else if (next_free_ptid)
    {
        id = next_free_ptid;
        entry = &ptid_entries[id - PTID_OFFSET];
        if (!(next_free_ptid = entry->next)) last_free_ptid = 0;
    }
    else  /* need to grow the array */
    {
        unsigned int count = alloc_ptid_entries + (alloc_ptid_entries / 2);
        if (!count) count = 64;
        if (!(entry = realloc( ptid_entries, count * sizeof(*entry) )))
        {
            set_error( STATUS_NO_MEMORY );
            return 0;
        }
        ptid_entries = entry;
        alloc_ptid_entries = count;
        id = used_ptid_entries + PTID_OFFSET;
        entry = &ptid_entries[used_ptid_entries++];
    }

    entry->ptr = ptr;
    return id;
}

/* free a process or thread id */
void free_ptid( unsigned int id )
{
    struct ptid_entry *entry = &ptid_entries[id - PTID_OFFSET];

    entry->ptr  = NULL;
    entry->next = 0;

    /* append to end of free list so that we don't reuse it too early */
    if (last_free_ptid) ptid_entries[last_free_ptid - PTID_OFFSET].next = id;
    else next_free_ptid = id;

    last_free_ptid = id;
}

/* retrieve the pointer corresponding to a process or thread id */
void *get_ptid_entry( unsigned int id )
{
    if (id < PTID_OFFSET) return NULL;
    if (id - PTID_OFFSET >= used_ptid_entries) return NULL;
    return ptid_entries[id - PTID_OFFSET].ptr;
}

200 201 202 203 204 205 206 207
/* return the main thread of the process */
struct thread *get_process_first_thread( struct process *process )
{
    struct list *ptr = list_head( &process->thread_list );
    if (!ptr) return NULL;
    return LIST_ENTRY( ptr, struct thread, proc_entry );
}

208 209 210
/* set the state of the process startup info */
static void set_process_startup_state( struct process *process, enum startup_state state )
{
211 212 213 214 215 216 217
    if (process->startup_state == STARTUP_IN_PROGRESS) process->startup_state = state;
    if (process->startup_info)
    {
        wake_up( &process->startup_info->obj, 0 );
        release_object( process->startup_info );
        process->startup_info = NULL;
    }
218 219
}

220
/* create a new process and its main thread */
221 222
/* if the function fails the fd is closed */
struct thread *create_process( int fd, struct thread *parent_thread, int inherit_all )
223
{
224
    struct process *process;
225
    struct thread *thread = NULL;
226
    int request_pipe[2];
227

228 229 230 231 232
    if (!(process = alloc_object( &process_ops )))
    {
        close( fd );
        goto error;
    }
233
    process->parent          = NULL;
234
    process->debugger        = NULL;
235
    process->handles         = NULL;
236
    process->msg_fd          = NULL;
237
    process->exit_code       = STILL_ACTIVE;
Alexandre Julliard's avatar
Alexandre Julliard committed
238
    process->running_threads = 0;
239
    process->priority        = PROCESS_PRIOCLASS_NORMAL;
240
    process->affinity        = 1;
241
    process->suspend         = 0;
242
    process->create_flags    = 0;
243
    process->console         = NULL;
244
    process->startup_state   = STARTUP_IN_PROGRESS;
245
    process->startup_info    = NULL;
246 247
    process->idle_event      = NULL;
    process->queue           = NULL;
248
    process->peb             = NULL;
249
    process->ldt_copy        = NULL;
250
    process->winstation      = 0;
251
    process->desktop         = 0;
252
    process->token           = token_create_admin();
253
    list_init( &process->thread_list );
254
    list_init( &process->locks );
255
    list_init( &process->classes );
256
    list_init( &process->dlls );
257

258
    gettimeofday( &process->start_time, NULL );
259
    process->end_time.tv_sec = process->end_time.tv_usec = 0;
260
    list_add_head( &process_list, &process->entry );
261

262 263 264 265 266
    if (!(process->id = process->group_id = alloc_ptid( process )))
    {
        close( fd );
        goto error;
    }
267
    if (!(process->msg_fd = create_anonymous_fd( &process_fd_ops, fd, &process->obj ))) goto error;
268

269 270 271 272 273 274 275 276 277 278 279
    /* create the handle table */
    if (!parent_thread) process->handles = alloc_handle_table( process, 0 );
    else
    {
        struct process *parent = parent_thread->process;
        process->parent = (struct process *)grab_object( parent );
        process->handles = inherit_all ? copy_handle_table( process, parent )
                                       : alloc_handle_table( process, 0 );
    }
    if (!process->handles) goto error;

280
    /* create the main thread */
281 282 283 284 285
    if (pipe( request_pipe ) == -1)
    {
        file_set_error();
        goto error;
    }
286 287 288 289 290 291
    if (send_client_fd( process, request_pipe[1], 0 ) == -1)
    {
        close( request_pipe[0] );
        close( request_pipe[1] );
        goto error;
    }
292 293
    close( request_pipe[1] );
    if (!(thread = create_thread( request_pipe[0], process ))) goto error;
294

295
    set_fd_events( process->msg_fd, POLLIN );  /* start listening to events */
296 297 298 299
    release_object( process );
    return thread;

 error:
300 301 302
    if (process) release_object( process );
    /* if we failed to start our first process, close everything down */
    if (!running_processes) close_master_socket();
303 304 305 306
    return NULL;
}

/* initialize the current process and fill in the request */
307
data_size_t init_process( struct thread *thread )
308
{
309
    struct process *process = thread->process;
310
    struct startup_info *info = process->startup_info;
311

312 313
    if (!info) return 0;
    return info->data_size;
Alexandre Julliard's avatar
Alexandre Julliard committed
314 315 316
}

/* destroy a process when its refcount is 0 */
317
static void process_destroy( struct object *obj )
Alexandre Julliard's avatar
Alexandre Julliard committed
318 319 320 321
{
    struct process *process = (struct process *)obj;
    assert( obj->ops == &process_ops );

Alexandre Julliard's avatar
Alexandre Julliard committed
322
    /* we can't have a thread remaining */
323
    assert( list_empty( &process->thread_list ));
324 325

    set_process_startup_state( process, STARTUP_ABORTED );
326 327
    if (process->console) release_object( process->console );
    if (process->parent) release_object( process->parent );
328
    if (process->msg_fd) release_object( process->msg_fd );
329
    list_remove( &process->entry );
330 331
    if (process->idle_event) release_object( process->idle_event );
    if (process->queue) release_object( process->queue );
332
    if (process->id) free_ptid( process->id );
333
    if (process->token) release_object( process->token );
Alexandre Julliard's avatar
Alexandre Julliard committed
334 335
}

Alexandre Julliard's avatar
Alexandre Julliard committed
336
/* dump a process on stdout for debugging purposes */
337
static void process_dump( struct object *obj, int verbose )
Alexandre Julliard's avatar
Alexandre Julliard committed
338 339 340 341
{
    struct process *process = (struct process *)obj;
    assert( obj->ops == &process_ops );

342
    fprintf( stderr, "Process id=%04x handles=%p\n", process->id, process->handles );
Alexandre Julliard's avatar
Alexandre Julliard committed
343 344
}

Alexandre Julliard's avatar
Alexandre Julliard committed
345 346 347
static int process_signaled( struct object *obj, struct thread *thread )
{
    struct process *process = (struct process *)obj;
348
    return !process->running_threads;
Alexandre Julliard's avatar
Alexandre Julliard committed
349 350
}

351 352 353 354 355 356 357 358 359
static unsigned int process_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 |= PROCESS_ALL_ACCESS;
    return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
}

360
static void process_poll_event( struct fd *fd, int event )
361
{
362 363
    struct process *process = get_fd_user( fd );
    assert( process->obj.ops == &process_ops );
364

365
    if (event & (POLLERR | POLLHUP)) set_fd_events( fd, -1 );
366 367 368
    else if (event & POLLIN) receive_fd( process );
}

369 370 371 372
static void startup_info_destroy( struct object *obj )
{
    struct startup_info *info = (struct startup_info *)obj;
    assert( obj->ops == &startup_info_ops );
373
    if (info->data) free( info->data );
374
    if (info->exe_file) release_object( info->exe_file );
375 376 377 378 379 380 381 382
    if (info->process) release_object( info->process );
}

static void startup_info_dump( struct object *obj, int verbose )
{
    struct startup_info *info = (struct startup_info *)obj;
    assert( obj->ops == &startup_info_ops );

383 384
    fprintf( stderr, "Startup info in=%p out=%p err=%p\n",
             info->hstdin, info->hstdout, info->hstderr );
385 386 387 388 389
}

static int startup_info_signaled( struct object *obj, struct thread *thread )
{
    struct startup_info *info = (struct startup_info *)obj;
390
    return info->process && info->process->startup_state != STARTUP_IN_PROGRESS;
391 392
}

Alexandre Julliard's avatar
Alexandre Julliard committed
393
/* get a process from an id (and increment the refcount) */
394
struct process *get_process_from_id( process_id_t id )
Alexandre Julliard's avatar
Alexandre Julliard committed
395
{
396 397 398 399 400
    struct object *obj = get_ptid_entry( id );

    if (obj && obj->ops == &process_ops) return (struct process *)grab_object( obj );
    set_error( STATUS_INVALID_PARAMETER );
    return NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
401
}
Alexandre Julliard's avatar
Alexandre Julliard committed
402 403

/* get a process from a handle (and increment the refcount) */
404
struct process *get_process_from_handle( obj_handle_t handle, unsigned int access )
Alexandre Julliard's avatar
Alexandre Julliard committed
405 406 407 408 409
{
    return (struct process *)get_handle_obj( current->process, handle,
                                             access, &process_ops );
}

410 411 412 413 414 415 416 417 418 419 420 421
/* find a dll from its base address */
static inline struct process_dll *find_process_dll( struct process *process, void *base )
{
    struct process_dll *dll;

    LIST_FOR_EACH_ENTRY( dll, &process->dlls, struct process_dll, entry )
    {
        if (dll->base == base) return dll;
    }
    return NULL;
}

422 423
/* add a dll to a process list */
static struct process_dll *process_load_dll( struct process *process, struct file *file,
424
                                             void *base, const WCHAR *filename, data_size_t name_len )
425 426 427 428
{
    struct process_dll *dll;

    /* make sure we don't already have one with the same base address */
429
    if (find_process_dll( process, base ))
430 431 432 433 434 435 436 437 438
    {
        set_error( STATUS_INVALID_PARAMETER );
        return NULL;
    }

    if ((dll = mem_alloc( sizeof(*dll) )))
    {
        dll->file = NULL;
        dll->base = base;
439 440 441 442 443 444 445
        dll->filename = NULL;
        dll->namelen  = name_len;
        if (name_len && !(dll->filename = memdup( filename, name_len )))
        {
            free( dll );
            return NULL;
        }
446
        if (file) dll->file = (struct file *)grab_object( file );
447
        list_add_tail( &process->dlls, &dll->entry );
448 449 450 451 452 453 454
    }
    return dll;
}

/* remove a dll from a process list */
static void process_unload_dll( struct process *process, void *base )
{
455
    struct process_dll *dll = find_process_dll( process, base );
456

457
    if (dll && (&dll->entry != list_head( &process->dlls )))  /* main exe can't be unloaded */
458
    {
459 460 461 462 463
        if (dll->file) release_object( dll->file );
        if (dll->filename) free( dll->filename );
        list_remove( &dll->entry );
        free( dll );
        generate_debug_event( current, UNLOAD_DLL_DEBUG_EVENT, base );
464
    }
465
    else set_error( STATUS_INVALID_PARAMETER );
466 467
}

468 469 470 471 472
/* kill all processes */
void kill_all_processes( struct process *skip, int exit_code )
{
    for (;;)
    {
473
        struct process *process;
474

475 476 477 478 479 480
        LIST_FOR_EACH_ENTRY( process, &process_list, struct process, entry )
        {
            if (process == skip) continue;
            if (process->running_threads) break;
        }
        if (&process->entry == &process_list) break;  /* no process found */
481 482 483 484
        kill_process( process, NULL, exit_code );
    }
}

485
/* kill all processes being attached to a console renderer */
486
void kill_console_processes( struct thread *renderer, int exit_code )
487 488 489
{
    for (;;)  /* restart from the beginning of the list every time */
    {
490
        struct process *process;
491 492

        /* find the first process being attached to 'renderer' and still running */
493
        LIST_FOR_EACH_ENTRY( process, &process_list, struct process, entry )
494
        {
495 496 497
            if (process == renderer->process) continue;
            if (!process->running_threads) continue;
            if (process->console && process->console->renderer == renderer) break;
498
        }
499
        if (&process->entry == &process_list) break;  /* no process found */
500 501 502 503
        kill_process( process, NULL, exit_code );
    }
}

Alexandre Julliard's avatar
Alexandre Julliard committed
504
/* a process has been killed (i.e. its last thread died) */
505
static void process_killed( struct process *process )
Alexandre Julliard's avatar
Alexandre Julliard committed
506
{
507
    struct handle_table *handles;
508 509
    struct list *ptr;

510
    assert( list_empty( &process->thread_list ));
Alexandre Julliard's avatar
Alexandre Julliard committed
511
    gettimeofday( &process->end_time, NULL );
512
    close_process_desktop( process );
513
    handles = process->handles;
514
    process->handles = NULL;
515
    if (handles) release_object( handles );
516 517

    /* close the console attached to this process, if any */
518
    free_console( process );
519

520
    while ((ptr = list_head( &process->dlls )))
521
    {
522
        struct process_dll *dll = LIST_ENTRY( ptr, struct process_dll, entry );
523
        if (dll->file) release_object( dll->file );
524
        if (dll->filename) free( dll->filename );
525
        list_remove( &dll->entry );
526 527
        free( dll );
    }
528
    destroy_process_classes( process );
529
    remove_process_locks( process );
530
    set_process_startup_state( process, STARTUP_ABORTED );
Alexandre Julliard's avatar
Alexandre Julliard committed
531
    wake_up( &process->obj, 0 );
532
    if (!--running_processes) close_master_socket();
Alexandre Julliard's avatar
Alexandre Julliard committed
533 534 535 536 537
}

/* add a thread to a process running threads list */
void add_process_thread( struct process *process, struct thread *thread )
{
538
    list_add_tail( &process->thread_list, &thread->proc_entry );
539
    if (!process->running_threads++) running_processes++;
Alexandre Julliard's avatar
Alexandre Julliard committed
540 541 542 543 544 545 546
    grab_object( thread );
}

/* remove a thread from a process running threads list */
void remove_process_thread( struct process *process, struct thread *thread )
{
    assert( process->running_threads > 0 );
547
    assert( !list_empty( &process->thread_list ));
Alexandre Julliard's avatar
Alexandre Julliard committed
548

549
    list_remove( &thread->proc_entry );
Alexandre Julliard's avatar
Alexandre Julliard committed
550 551 552 553

    if (!--process->running_threads)
    {
        /* we have removed the last running thread, exit the process */
554 555 556
        process->exit_code = thread->exit_code;
        generate_debug_event( thread, EXIT_PROCESS_DEBUG_EVENT, process );
        process_killed( process );
Alexandre Julliard's avatar
Alexandre Julliard committed
557
    }
558
    else generate_debug_event( thread, EXIT_THREAD_DEBUG_EVENT, thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
559 560 561
    release_object( thread );
}

562 563 564 565 566
/* suspend all the threads of a process */
void suspend_process( struct process *process )
{
    if (!process->suspend++)
    {
567 568 569
        struct list *ptr, *next;

        LIST_FOR_EACH_SAFE( ptr, next, &process->thread_list )
570
        {
571
            struct thread *thread = LIST_ENTRY( ptr, struct thread, proc_entry );
572
            if (!thread->suspend) stop_thread( thread );
573 574 575 576 577 578 579 580 581 582
        }
    }
}

/* resume all the threads of a process */
void resume_process( struct process *process )
{
    assert (process->suspend > 0);
    if (!--process->suspend)
    {
583 584 585
        struct list *ptr, *next;

        LIST_FOR_EACH_SAFE( ptr, next, &process->thread_list )
586
        {
587
            struct thread *thread = LIST_ENTRY( ptr, struct thread, proc_entry );
588
            if (!thread->suspend) wake_thread( thread );
589 590 591 592
        }
    }
}

Alexandre Julliard's avatar
Alexandre Julliard committed
593
/* kill a process on the spot */
594
void kill_process( struct process *process, struct thread *skip, int exit_code )
Alexandre Julliard's avatar
Alexandre Julliard committed
595
{
596
    struct list *ptr, *next;
597

598
    LIST_FOR_EACH_SAFE( ptr, next, &process->thread_list )
599
    {
600 601
        struct thread *thread = LIST_ENTRY( ptr, struct thread, proc_entry );

602
        if (exit_code) thread->exit_code = exit_code;
603 604
        if (thread != skip) kill_thread( thread, 1 );
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
605 606
}

607 608 609 610 611
/* kill all processes being debugged by a given thread */
void kill_debugged_processes( struct thread *debugger, int exit_code )
{
    for (;;)  /* restart from the beginning of the list every time */
    {
612 613
        struct process *process;

614
        /* find the first process being debugged by 'debugger' and still running */
615 616 617 618 619 620
        LIST_FOR_EACH_ENTRY( process, &process_list, struct process, entry )
        {
            if (!process->running_threads) continue;
            if (process->debugger == debugger) break;
        }
        if (&process->entry == &process_list) break;  /* no process found */
621
        process->debugger = NULL;
622
        kill_process( process, NULL, exit_code );
623 624 625
    }
}

626

627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
/* trigger a breakpoint event in a given process */
void break_process( struct process *process )
{
    struct thread *thread;

    suspend_process( process );

    LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry )
    {
        if (thread->context)  /* inside an exception event already */
        {
            break_thread( thread );
            goto done;
        }
    }
    if ((thread = get_process_first_thread( process ))) thread->debug_break = 1;
    else set_error( STATUS_ACCESS_DENIED );
done:
    resume_process( process );
}


649 650 651 652
/* detach a debugger from all its debuggees */
void detach_debugged_processes( struct thread *debugger )
{
    struct process *process;
653 654

    LIST_FOR_EACH_ENTRY( process, &process_list, struct process, entry )
655 656 657 658 659 660 661 662 663
    {
        if (process->debugger == debugger && process->running_threads)
        {
            debugger_detach( process, debugger );
        }
    }
}


664 665
void enum_processes( int (*cb)(struct process*, void*), void *user )
{
666 667 668
    struct list *ptr, *next;

    LIST_FOR_EACH_SAFE( ptr, next, &process_list )
669
    {
670
        struct process *process = LIST_ENTRY( ptr, struct process, entry );
671 672 673 674
        if ((cb)(process, user)) break;
    }
}

675 676 677
/* set the debugged flag in the process PEB */
int set_process_debug_flag( struct process *process, int flag )
{
678
    char data = (flag != 0);
679 680

    /* BeingDebugged flag is the byte at offset 2 in the PEB */
681
    return write_process_memory( process, (char *)process->peb + 2, 1, &data );
682 683
}

684 685 686 687 688 689 690 691 692
/* take a snapshot of currently running processes */
struct process_snapshot *process_snap( int *count )
{
    struct process_snapshot *snapshot, *ptr;
    struct process *process;
    if (!running_processes) return NULL;
    if (!(snapshot = mem_alloc( sizeof(*snapshot) * running_processes )))
        return NULL;
    ptr = snapshot;
693
    LIST_FOR_EACH_ENTRY( process, &process_list, struct process, entry )
694 695 696 697
    {
        if (!process->running_threads) continue;
        ptr->process  = process;
        ptr->threads  = process->running_threads;
698
        ptr->count    = process->obj.refcount;
699
        ptr->priority = process->priority;
700
        ptr->handles  = get_handle_table_count(process);
701 702 703 704 705 706
        grab_object( process );
        ptr++;
    }
    *count = running_processes;
    return snapshot;
}
707

708 709 710 711 712
/* take a snapshot of the modules of a process */
struct module_snapshot *module_snap( struct process *process, int *count )
{
    struct module_snapshot *snapshot, *ptr;
    struct process_dll *dll;
713
    int total = 0;
714

715
    LIST_FOR_EACH_ENTRY( dll, &process->dlls, struct process_dll, entry ) total++;
716 717
    if (!(snapshot = mem_alloc( sizeof(*snapshot) * total ))) return NULL;

718
    ptr = snapshot;
719
    LIST_FOR_EACH_ENTRY( dll, &process->dlls, struct process_dll, entry )
720
    {
721 722 723 724
        ptr->base     = dll->base;
        ptr->size     = dll->size;
        ptr->namelen  = dll->namelen;
        ptr->filename = memdup( dll->filename, dll->namelen );
725
        ptr++;
726 727 728 729 730 731
    }
    *count = total;
    return snapshot;
}


732 733 734
/* create a new process */
DECL_HANDLER(new_process)
{
735
    struct startup_info *info;
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751
    struct thread *thread;
    struct process *process;
    struct process *parent = current->process;
    int socket_fd = thread_get_inflight_fd( current, req->socket_fd );

    if (socket_fd == -1)
    {
        set_error( STATUS_INVALID_PARAMETER );
        return;
    }
    if (fcntl( socket_fd, F_SETFL, O_NONBLOCK ) == -1)
    {
        set_error( STATUS_INVALID_HANDLE );
        close( socket_fd );
        return;
    }
752

753
    /* build the startup info for a new process */
754
    if (!(info = alloc_object( &startup_info_ops ))) return;
755 756 757
    info->hstdin       = req->hstdin;
    info->hstdout      = req->hstdout;
    info->hstderr      = req->hstderr;
758
    info->exe_file     = NULL;
759
    info->process      = NULL;
760 761
    info->data_size    = get_req_data_size();
    info->data         = NULL;
762

763
    if (req->exe_file &&
764
        !(info->exe_file = get_file_obj( current->process, req->exe_file, FILE_READ_DATA )))
765 766
        goto done;

767
    if (!(info->data = memdup( get_req_data(), info->data_size ))) goto done;
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812

    if (!(thread = create_process( socket_fd, current, req->inherit_all ))) goto done;
    process = thread->process;
    process->create_flags = req->create_flags;
    process->startup_info = (struct startup_info *)grab_object( info );

    /* connect to the window station */
    connect_process_winstation( process, current );

    /* thread will be actually suspended in init_done */
    if (req->create_flags & CREATE_SUSPENDED) thread->suspend++;

    /* set the process console */
    if (!(req->create_flags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE)))
    {
        /* FIXME: some better error checking should be done...
         * like if hConOut and hConIn are console handles, then they should be on the same
         * physical console
         */
        inherit_console( current, process, req->inherit_all ? req->hstdin : 0 );
    }

    if (!req->inherit_all && !(req->create_flags & CREATE_NEW_CONSOLE))
    {
        info->hstdin  = duplicate_handle( parent, req->hstdin, process,
                                          0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
        info->hstdout = duplicate_handle( parent, req->hstdout, process,
                                          0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
        info->hstderr = duplicate_handle( parent, req->hstderr, process,
                                          0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
        /* some handles above may have been invalid; this is not an error */
        if (get_error() == STATUS_INVALID_HANDLE ||
            get_error() == STATUS_OBJECT_TYPE_MISMATCH) clear_error();
    }

    /* attach to the debugger if requested */
    if (req->create_flags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS))
        set_process_debugger( process, current );
    else if (parent->debugger && !(parent->create_flags & DEBUG_ONLY_THIS_PROCESS))
        set_process_debugger( process, parent->debugger );

    if (!(req->create_flags & CREATE_NEW_PROCESS_GROUP))
        process->group_id = parent->group_id;

    info->process = (struct process *)grab_object( process );
813
    reply->info = alloc_handle( current->process, info, SYNCHRONIZE, 0 );
814 815 816 817
    reply->pid = get_process_id( process );
    reply->tid = get_thread_id( thread );
    reply->phandle = alloc_handle( parent, process, req->process_access, req->process_attr );
    reply->thandle = alloc_handle( parent, thread, req->thread_access, req->thread_attr );
818 819 820

 done:
    release_object( info );
821
}
822

823 824
/* Retrieve information about a newly started process */
DECL_HANDLER(get_new_process_info)
825
{
826 827 828 829
    struct startup_info *info;

    if ((info = (struct startup_info *)get_handle_obj( current->process, req->info,
                                                       0, &startup_info_ops )))
830
    {
831
        reply->success = is_process_init_done( info->process );
832
        reply->exit_code = info->process->exit_code;
833
        release_object( info );
834
    }
835 836
}

837 838 839
/* Retrieve the new process startup info */
DECL_HANDLER(get_startup_info)
{
840 841
    struct process *process = current->process;
    struct startup_info *info = process->startup_info;
842
    data_size_t size;
843

844 845 846 847 848
    if (!info) return;

    if (info->exe_file &&
        !(reply->exe_file = alloc_handle( process, info->exe_file, GENERIC_READ, 0 ))) return;

849 850 851
    reply->hstdin  = info->hstdin;
    reply->hstdout = info->hstdout;
    reply->hstderr = info->hstderr;
852 853 854 855 856 857 858

    /* we return the data directly without making a copy so this can only be called once */
    size = info->data_size;
    if (size > get_reply_max_size()) size = get_reply_max_size();
    set_reply_data_ptr( info->data, size );
    info->data = NULL;
    info->data_size = 0;
859 860
}

861 862 863
/* signal the end of the process initialization */
DECL_HANDLER(init_process_done)
{
864
    struct process_dll *dll;
865
    struct process *process = current->process;
866

867
    if (is_process_init_done(process))
868
    {
869
        set_error( STATUS_INVALID_PARAMETER );
870 871
        return;
    }
872
    if (!(dll = find_process_dll( process, req->module )))
873
    {
874 875
        set_error( STATUS_DLL_NOT_FOUND );
        return;
876
    }
877

878 879 880 881
    /* main exe is the first in the dll list */
    list_remove( &dll->entry );
    list_add_head( &process->dlls, &dll->entry );

882 883 884
    generate_startup_debug_events( process, req->entry );
    set_process_startup_state( process, STARTUP_DONE );

885
    if (req->gui) process->idle_event = create_event( NULL, NULL, 0, 1, 0 );
886
    if (current->suspend + process->suspend > 0) stop_thread( current );
887
    if (process->debugger) set_process_debug_flag( process, 1 );
888 889
}

890 891 892 893
/* open a handle to a process */
DECL_HANDLER(open_process)
{
    struct process *process = get_process_from_id( req->pid );
894
    reply->handle = 0;
895 896
    if (process)
    {
897
        reply->handle = alloc_handle( current->process, process, req->access, req->attributes );
898 899 900 901 902 903 904 905 906 907 908
        release_object( process );
    }
}

/* terminate a process */
DECL_HANDLER(terminate_process)
{
    struct process *process;

    if ((process = get_process_from_handle( req->handle, PROCESS_TERMINATE )))
    {
909
        reply->self = (current->process == process);
910
        kill_process( process, current, req->exit_code );
911 912 913 914 915 916 917 918 919 920 921
        release_object( process );
    }
}

/* fetch information about a process */
DECL_HANDLER(get_process_info)
{
    struct process *process;

    if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
    {
922
        reply->pid              = get_process_id( process );
923
        reply->ppid             = process->parent ? get_process_id( process->parent ) : 0;
924 925
        reply->exit_code        = process->exit_code;
        reply->priority         = process->priority;
926
        reply->affinity         = process->affinity;
927
        reply->peb              = process->peb;
928 929 930 931
        reply->start_time.sec   = process->start_time.tv_sec;
        reply->start_time.usec  = process->start_time.tv_usec;
        reply->end_time.sec     = process->end_time.tv_sec;
        reply->end_time.usec    = process->end_time.tv_usec;
932 933 934 935 936 937 938 939 940 941 942
        release_object( process );
    }
}

/* set information about a process */
DECL_HANDLER(set_process_info)
{
    struct process *process;

    if ((process = get_process_from_handle( req->handle, PROCESS_SET_INFORMATION )))
    {
943 944 945 946 947 948
        if (req->mask & SET_PROCESS_INFO_PRIORITY) process->priority = req->priority;
        if (req->mask & SET_PROCESS_INFO_AFFINITY)
        {
            if (req->affinity != 1) set_error( STATUS_INVALID_PARAMETER );
            else process->affinity = req->affinity;
        }
949 950 951
        release_object( process );
    }
}
952 953 954 955 956

/* read data from a process address space */
DECL_HANDLER(read_process_memory)
{
    struct process *process;
957
    data_size_t len = get_reply_max_size();
958

959 960 961
    if (!(process = get_process_from_handle( req->handle, PROCESS_VM_READ ))) return;

    if (len)
962
    {
963
        char *buffer = mem_alloc( len );
964 965
        if (buffer)
        {
966
            if (read_process_memory( process, req->addr, len, buffer ))
967
                set_reply_data_ptr( buffer, len );
968 969
            else
                free( buffer );
970
        }
971
    }
972
    release_object( process );
973
}
974 975 976 977 978 979 980 981

/* write data to a process address space */
DECL_HANDLER(write_process_memory)
{
    struct process *process;

    if ((process = get_process_from_handle( req->handle, PROCESS_VM_WRITE )))
    {
982
        data_size_t len = get_req_data_size();
983 984
        if (len) write_process_memory( process, req->addr, len, get_req_data() );
        else set_error( STATUS_INVALID_PARAMETER );
985 986 987
        release_object( process );
    }
}
988 989 990 991 992 993 994

/* notify the server that a dll has been loaded */
DECL_HANDLER(load_dll)
{
    struct process_dll *dll;
    struct file *file = NULL;

995
    if (req->handle && !(file = get_file_obj( current->process, req->handle, FILE_READ_DATA )))
996
        return;
997

998 999
    if ((dll = process_load_dll( current->process, file, req->base,
                                 get_req_data(), get_req_data_size() )))
1000
    {
1001
        dll->size       = req->size;
1002 1003 1004 1005
        dll->dbg_offset = req->dbg_offset;
        dll->dbg_size   = req->dbg_size;
        dll->name       = req->name;
        /* only generate event if initialization is done */
1006
        if (is_process_init_done( current->process ))
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016
            generate_debug_event( current, LOAD_DLL_DEBUG_EVENT, dll );
    }
    if (file) release_object( file );
}

/* notify the server that a dll is being unloaded */
DECL_HANDLER(unload_dll)
{
    process_unload_dll( current->process, req->base );
}
1017

1018 1019 1020 1021 1022 1023 1024
/* retrieve information about a module in a process */
DECL_HANDLER(get_dll_info)
{
    struct process *process;

    if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
    {
1025
        struct process_dll *dll = find_process_dll( process, req->base_address );
1026

1027
        if (dll)
1028
        {
1029
            reply->size = dll->size;
1030
            reply->entry_point = NULL; /* FIXME */
1031
            if (dll->filename)
1032
            {
1033
                data_size_t len = min( dll->namelen, get_reply_max_size() );
1034
                set_reply_data( dll->filename, len );
1035 1036
            }
        }
1037 1038 1039
        else
            set_error( STATUS_DLL_NOT_FOUND );

1040 1041 1042 1043
        release_object( process );
    }
}

1044 1045
/* retrieve the process idle event */
DECL_HANDLER(get_process_idle_event)
1046 1047 1048
{
    struct process *process;

1049
    reply->event = 0;
1050 1051
    if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
    {
1052
        if (process->idle_event && process != current->process)
1053 1054
            reply->event = alloc_handle( current->process, process->idle_event,
                                         EVENT_ALL_ACCESS, 0 );
1055 1056 1057
        release_object( process );
    }
}