process.c 63.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 22
#include "config.h"

Alexandre Julliard's avatar
Alexandre Julliard committed
23
#include <assert.h>
24
#include <errno.h>
25
#include <fcntl.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
26
#include <limits.h>
27
#include <signal.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
28
#include <string.h>
29
#include <stdarg.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
30
#include <stdio.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
31
#include <stdlib.h>
32
#include <sys/types.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
33
#include <sys/time.h>
34
#include <sys/socket.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
35
#include <unistd.h>
36
#include <poll.h>
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
#ifdef HAVE_SYS_QUEUE_H
# include <sys/queue.h>
#endif
#ifdef HAVE_SYS_SYSCTL_H
# include <sys/sysctl.h>
#endif
#ifdef HAVE_SYS_USER_H
# define thread __unix_thread
# include <sys/user.h>
# undef thread
#endif
#ifdef HAVE_LIBPROCSTAT
# include <libprocstat.h>
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
54

55 56
#include "ntstatus.h"
#define WIN32_NO_STATUS
57
#include "winternl.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
58

59
#include "file.h"
60 61 62
#include "handle.h"
#include "process.h"
#include "thread.h"
63
#include "request.h"
64
#include "user.h"
65
#include "security.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
66

67
/* process object */
68

69
static struct list process_list = LIST_INIT(process_list);
70
static int running_processes, user_processes;
71 72
static struct event *shutdown_event;           /* signaled when shutdown starts */
static struct timeout_user *shutdown_timeout;  /* timeout for server shutdown */
73
static int shutdown_stage;  /* current stage in the shutdown process */
Alexandre Julliard's avatar
Alexandre Julliard committed
74

75 76 77 78 79
static const WCHAR process_name[] = {'P','r','o','c','e','s','s'};

struct type_descr process_type =
{
    { process_name, sizeof(process_name) },   /* name */
80 81 82 83 84 85 86 87 88
    PROCESS_ALL_ACCESS,                       /* valid_access */
    {                                         /* mapping */
        STANDARD_RIGHTS_READ | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
        STANDARD_RIGHTS_WRITE | PROCESS_SUSPEND_RESUME | PROCESS_SET_INFORMATION | PROCESS_SET_QUOTA
        | PROCESS_CREATE_PROCESS | PROCESS_DUP_HANDLE | PROCESS_VM_WRITE | PROCESS_VM_OPERATION
        | PROCESS_CREATE_THREAD,
        STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE,
        PROCESS_ALL_ACCESS
    },
89
};
Alexandre Julliard's avatar
Alexandre Julliard committed
90

91
static void process_dump( struct object *obj, int verbose );
92
static int process_signaled( struct object *obj, struct wait_queue_entry *entry );
93
static unsigned int process_map_access( struct object *obj, unsigned int access );
94
static struct security_descriptor *process_get_sd( struct object *obj );
95
static void process_poll_event( struct fd *fd, int event );
96
static struct list *process_get_kernel_obj_list( struct object *obj );
97
static void process_destroy( struct object *obj );
98
static void terminate_process( struct process *process, struct thread *skip, int exit_code );
Alexandre Julliard's avatar
Alexandre Julliard committed
99 100 101

static const struct object_ops process_ops =
{
102
    sizeof(struct process),      /* size */
103
    &process_type,               /* type */
104 105 106 107 108
    process_dump,                /* dump */
    add_queue,                   /* add_queue */
    remove_queue,                /* remove_queue */
    process_signaled,            /* signaled */
    no_satisfied,                /* satisfied */
109
    no_signal,                   /* signal */
110
    no_get_fd,                   /* get_fd */
111
    process_map_access,          /* map_access */
112
    process_get_sd,              /* get_sd */
113
    default_set_sd,              /* set_sd */
114
    no_get_full_name,            /* get_full_name */
115
    no_lookup_name,              /* lookup_name */
116 117
    no_link_name,                /* link_name */
    NULL,                        /* unlink_name */
118
    no_open_file,                /* open_file */
119
    process_get_kernel_obj_list, /* get_kernel_obj_list */
120
    no_close_handle,             /* close_handle */
121 122 123 124 125
    process_destroy              /* destroy */
};

static const struct fd_ops process_fd_ops =
{
126
    NULL,                        /* get_poll_events */
127
    process_poll_event,          /* poll_event */
128 129
    NULL,                        /* flush */
    NULL,                        /* get_fd_type */
130
    NULL,                        /* ioctl */
131
    NULL,                        /* queue_async */
132
    NULL,                        /* reselect_async */
133
    NULL                         /* cancel async */
Alexandre Julliard's avatar
Alexandre Julliard committed
134 135
};

136 137 138
/* process startup info */

struct startup_info
139
{
140 141
    struct object       obj;          /* object header */
    struct process     *process;      /* created process */
142 143 144
    data_size_t         info_size;    /* size of startup info */
    data_size_t         data_size;    /* size of whole startup data */
    startup_info_t     *data;         /* data for startup info */
145
};
Alexandre Julliard's avatar
Alexandre Julliard committed
146

147
static void startup_info_dump( struct object *obj, int verbose );
148
static int startup_info_signaled( struct object *obj, struct wait_queue_entry *entry );
149 150 151
static void startup_info_destroy( struct object *obj );

static const struct object_ops startup_info_ops =
152
{
153
    sizeof(struct startup_info),   /* size */
154
    &no_type,                      /* type */
155 156 157 158 159
    startup_info_dump,             /* dump */
    add_queue,                     /* add_queue */
    remove_queue,                  /* remove_queue */
    startup_info_signaled,         /* signaled */
    no_satisfied,                  /* satisfied */
160
    no_signal,                     /* signal */
161
    no_get_fd,                     /* get_fd */
162
    default_map_access,            /* map_access */
163 164
    default_get_sd,                /* get_sd */
    default_set_sd,                /* set_sd */
165
    no_get_full_name,              /* get_full_name */
166
    no_lookup_name,                /* lookup_name */
167 168
    no_link_name,                  /* link_name */
    NULL,                          /* unlink_name */
169
    no_open_file,                  /* open_file */
170
    no_kernel_obj_list,            /* get_kernel_obj_list */
171
    no_close_handle,               /* close_handle */
172 173 174
    startup_info_destroy           /* destroy */
};

175 176
/* job object */

177 178 179 180 181
static const WCHAR job_name[] = {'J','o','b'};

struct type_descr job_type =
{
    { job_name, sizeof(job_name) },   /* name */
182 183 184 185 186 187 188
    JOB_OBJECT_ALL_ACCESS,            /* valid_access */
    {                                 /* mapping */
        STANDARD_RIGHTS_READ | JOB_OBJECT_QUERY,
        STANDARD_RIGHTS_WRITE | JOB_OBJECT_TERMINATE | JOB_OBJECT_SET_ATTRIBUTES | JOB_OBJECT_ASSIGN_PROCESS,
        STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
        JOB_OBJECT_ALL_ACCESS
    },
189 190
};

191 192
static void job_dump( struct object *obj, int verbose );
static int job_signaled( struct object *obj, struct wait_queue_entry *entry );
193
static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle );
194 195 196 197 198
static void job_destroy( struct object *obj );

struct job
{
    struct object obj;             /* object header */
199
    struct list process_list;      /* list of processes */
200
    int num_processes;             /* count of running processes */
201
    int total_processes;           /* count of processes which have been assigned */
202
    unsigned int limit_flags;      /* limit flags */
203
    int terminating;               /* job is terminating */
204
    int signaled;                  /* job is signaled */
205 206
    struct completion *completion_port; /* associated completion port */
    apc_param_t completion_key;    /* key to send with completion messages */
207 208 209
    struct job *parent;
    struct list parent_job_entry;  /* list entry for parent job */
    struct list child_job_list;    /* list of child jobs */
210 211 212 213 214
};

static const struct object_ops job_ops =
{
    sizeof(struct job),            /* size */
215
    &job_type,                     /* type */
216 217 218 219 220 221 222
    job_dump,                      /* dump */
    add_queue,                     /* add_queue */
    remove_queue,                  /* remove_queue */
    job_signaled,                  /* signaled */
    no_satisfied,                  /* satisfied */
    no_signal,                     /* signal */
    no_get_fd,                     /* get_fd */
223
    default_map_access,            /* map_access */
224 225
    default_get_sd,                /* get_sd */
    default_set_sd,                /* set_sd */
226
    default_get_full_name,         /* get_full_name */
227
    no_lookup_name,                /* lookup_name */
228 229
    directory_link_name,           /* link_name */
    default_unlink_name,           /* unlink_name */
230
    no_open_file,                  /* open_file */
231
    no_kernel_obj_list,            /* get_kernel_obj_list */
232
    job_close_handle,              /* close_handle */
233 234 235
    job_destroy                    /* destroy */
};

236
static struct job *create_job_object( struct object *root, const struct unicode_str *name,
237 238 239 240
                                      unsigned int attr, const struct security_descriptor *sd )
{
    struct job *job;

241
    if ((job = create_named_object( root, &job_ops, name, attr, sd )))
242 243 244 245
    {
        if (get_error() != STATUS_OBJECT_NAME_EXISTS)
        {
            /* initialize it if it didn't already exist */
246
            list_init( &job->process_list );
247
            list_init( &job->child_job_list );
248
            job->num_processes = 0;
249
            job->total_processes = 0;
250
            job->limit_flags = 0;
251
            job->terminating = 0;
252
            job->signaled = 0;
253 254
            job->completion_port = NULL;
            job->completion_key = 0;
255
            job->parent = NULL;
256 257 258 259 260
        }
    }
    return job;
}

261 262 263 264 265
static struct job *get_job_obj( struct process *process, obj_handle_t handle, unsigned int access )
{
    return (struct job *)get_handle_obj( process, handle, access, &job_ops );
}

266 267 268 269 270 271
static void add_job_completion( struct job *job, apc_param_t msg, apc_param_t pid )
{
    if (job->completion_port)
        add_completion( job->completion_port, job->completion_key, pid, STATUS_SUCCESS, msg );
}

272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
static void add_job_completion_existing_processes( struct job *job, struct job *completion_job )
{
    struct process *process;
    struct job *j;

    assert( completion_job->obj.ops == &job_ops );

    LIST_FOR_EACH_ENTRY( j, &job->child_job_list, struct job, parent_job_entry )
    {
        add_job_completion_existing_processes( j, completion_job );
    }

    LIST_FOR_EACH_ENTRY( process, &job->process_list, struct process, job_entry )
    {
        if (process->running_threads)
            add_job_completion( completion_job, JOB_OBJECT_MSG_NEW_PROCESS, get_process_id( process ));
    }
}

291 292 293 294 295 296 297 298 299 300 301 302
static int process_in_job( struct job *job, struct process *process )
{
    struct job *j;

    LIST_FOR_EACH_ENTRY( j, &job->child_job_list, struct job, parent_job_entry )
    {
        assert( j->parent == job );
        if (process_in_job( j, process )) return 1;
    }
    return process->job == job;
}

303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
static process_id_t *get_job_pids( struct job *job, process_id_t *pids, process_id_t *end )
{
    struct process *process;
    struct job *j;

    LIST_FOR_EACH_ENTRY( j, &job->child_job_list, struct job, parent_job_entry )
        pids = get_job_pids( j, pids, end );

    LIST_FOR_EACH_ENTRY( process, &job->process_list, struct process, job_entry )
    {
        if (pids == end) break;
        if (process->end_time) continue;  /* skip processes that ended */
        *pids++ = process->id;
    }

    return pids;
}

321 322
static void add_job_process( struct job *job, struct process *process )
{
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
    struct job *j, *common_parent;
    process_id_t pid;

    if (job == process->job) return;

    if ((common_parent = process->job))
    {
        if (job->parent)
        {
            for (j = job->parent; j; j = j->parent)
                if (j == common_parent) break;

            if (j != common_parent)
            {
                /* Job already has parent and the process is not in the job's chain. */
                set_error( STATUS_ACCESS_DENIED );
                return;
            }
            /* process->job is referenced in the job->parent chain. */
            release_object( process->job );
        }
        else
        {
346 347 348 349 350
            if (job->total_processes)
            {
                set_error( STATUS_ACCESS_DENIED );
                return;
            }
351 352 353 354 355 356
            /* transfer reference. */
            job->parent = process->job;
            list_add_tail( &job->parent->child_job_list, &job->parent_job_entry );
        }
        list_remove( &process->job_entry );
    }
357 358
    process->job = (struct job *)grab_object( job );
    list_add_tail( &job->process_list, &process->job_entry );
359

360 361 362 363 364 365 366
    pid = get_process_id( process );
    for (j = job; j != common_parent; j = j->parent)
    {
        j->num_processes++;
        j->total_processes++;
        add_job_completion( j, JOB_OBJECT_MSG_NEW_PROCESS, pid );
    }
367 368 369 370 371 372 373
}

/* called when a process has terminated, allow one additional process */
static void release_job_process( struct process *process )
{
    struct job *job = process->job;

374 375 376 377
    while (job)
    {
        assert( job->num_processes );
        job->num_processes--;
378

379 380
        if (!job->terminating)
            add_job_completion( job, JOB_OBJECT_MSG_EXIT_PROCESS, get_process_id(process) );
381

382 383
        if (!job->num_processes)
            add_job_completion( job, JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO, 0 );
384

385 386
        job = job->parent;
    }
387 388
}

389 390
static void terminate_job( struct job *job, int exit_code )
{
391 392
    struct process *process, *next_process;
    struct job *j, *next_job;
393

394
    LIST_FOR_EACH_ENTRY_SAFE( j, next_job, &job->child_job_list, struct job, parent_job_entry )
395
    {
396
        assert( j->parent == job );
397

398 399 400
        grab_object( j );
        terminate_job( j, exit_code );
        release_object( j );
401 402
    }

403 404 405 406 407 408
    job->terminating = 1;
    LIST_FOR_EACH_ENTRY_SAFE( process, next_process, &job->process_list, struct process, job_entry )
    {
        assert( process->job == job );
        if (process->running_threads) terminate_process( process, NULL, exit_code );
    }
409
    job->terminating = 0;
410 411
    job->signaled = 1;
    wake_up( &job->obj, 0 );
412 413
}

414 415 416 417 418 419 420 421 422 423 424 425 426
static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
{
    struct job *job = (struct job *)obj;
    assert( obj->ops == &job_ops );

    if (obj->handle_count == 1)  /* last handle */
    {
        if (job->limit_flags & JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE)
            terminate_job( job, 0 );
    }
    return 1;
}

427 428
static void job_destroy( struct object *obj )
{
429
    struct job *job = (struct job *)obj;
430
    assert( obj->ops == &job_ops );
431 432

    assert( !job->num_processes );
433 434
    assert( list_empty( &job->process_list ));
    assert( list_empty( &job->child_job_list ));
435 436

    if (job->completion_port) release_object( job->completion_port );
437 438 439 440 441
    if (job->parent)
    {
        list_remove( &job->parent_job_entry );
        release_object( job->parent );
    }
442 443 444 445
}

static void job_dump( struct object *obj, int verbose )
{
446
    struct job *job = (struct job *)obj;
447
    assert( obj->ops == &job_ops );
448 449
    fprintf( stderr, "Job processes=%d child_jobs=%d parent=%p\n",
             list_count(&job->process_list), list_count(&job->child_job_list), job->parent );
450 451 452 453
}

static int job_signaled( struct object *obj, struct wait_queue_entry *entry )
{
454 455
    struct job *job = (struct job *)obj;
    return job->signaled;
456
}
457

458 459 460 461 462 463 464 465 466 467 468
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 */
469
static unsigned int num_free_ptids;         /* number of free ptids */
470

471 472
static void kill_all_processes(void);

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

475 476 477
static unsigned int index_from_ptid(unsigned int id) { return id / 4; }
static unsigned int ptid_from_index(unsigned int index) { return index * 4; }

478 479 480 481
/* allocate a new process or thread id */
unsigned int alloc_ptid( void *ptr )
{
    struct ptid_entry *entry;
482
    unsigned int index;
483 484 485

    if (used_ptid_entries < alloc_ptid_entries)
    {
486
        index = used_ptid_entries + PTID_OFFSET;
487 488
        entry = &ptid_entries[used_ptid_entries++];
    }
489
    else if (next_free_ptid && num_free_ptids >= 256)
490
    {
491 492
        index = next_free_ptid;
        entry = &ptid_entries[index - PTID_OFFSET];
493
        if (!(next_free_ptid = entry->next)) last_free_ptid = 0;
494
        num_free_ptids--;
495 496 497 498
    }
    else  /* need to grow the array */
    {
        unsigned int count = alloc_ptid_entries + (alloc_ptid_entries / 2);
499
        if (!count) count = 512;
500 501 502 503 504 505 506
        if (!(entry = realloc( ptid_entries, count * sizeof(*entry) )))
        {
            set_error( STATUS_NO_MEMORY );
            return 0;
        }
        ptid_entries = entry;
        alloc_ptid_entries = count;
507
        index = used_ptid_entries + PTID_OFFSET;
508 509 510 511
        entry = &ptid_entries[used_ptid_entries++];
    }

    entry->ptr = ptr;
512
    return ptid_from_index( index );
513 514 515 516 517
}

/* free a process or thread id */
void free_ptid( unsigned int id )
{
518 519
    unsigned int index = index_from_ptid( id );
    struct ptid_entry *entry = &ptid_entries[index - PTID_OFFSET];
520 521 522 523 524

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

    /* append to end of free list so that we don't reuse it too early */
525 526 527
    if (last_free_ptid) ptid_entries[last_free_ptid - PTID_OFFSET].next = index;
    else next_free_ptid = index;
    last_free_ptid = index;
528
    num_free_ptids++;
529 530 531 532 533
}

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

540 541 542 543 544 545 546 547
/* 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 );
}

548 549 550
/* set the state of the process startup info */
static void set_process_startup_state( struct process *process, enum startup_state state )
{
551 552 553 554 555 556 557
    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;
    }
558 559
}

560 561 562 563
/* callback for server shutdown */
static void server_shutdown_timeout( void *arg )
{
    shutdown_timeout = NULL;
564
    if (!running_processes)
565
    {
566 567 568 569 570 571
        close_master_socket( 0 );
        return;
    }
    switch(++shutdown_stage)
    {
    case 1:  /* signal system processes to exit */
572 573
        if (debug_level) fprintf( stderr, "wineserver: shutting down\n" );
        if (shutdown_event) set_event( shutdown_event );
574 575 576 577 578 579
        shutdown_timeout = add_timeout_user( 2 * -TICKS_PER_SEC, server_shutdown_timeout, NULL );
        close_master_socket( 4 * -TICKS_PER_SEC );
        break;
    case 2:  /* now forcibly kill all processes (but still wait for SIGKILL timeouts) */
        kill_all_processes();
        break;
580 581 582
    }
}

583 584 585 586 587 588 589 590 591 592 593 594 595
/* forced shutdown, used for wineserver -k */
void shutdown_master_socket(void)
{
    kill_all_processes();
    shutdown_stage = 2;
    if (shutdown_timeout)
    {
        remove_timeout_user( shutdown_timeout );
        shutdown_timeout = NULL;
    }
    close_master_socket( 2 * -TICKS_PER_SEC );  /* for SIGKILL timeouts */
}

596 597 598 599
/* final cleanup once we are sure a process is really dead */
static void process_died( struct process *process )
{
    if (debug_level) fprintf( stderr, "%04x: *process killed*\n", process->id );
600 601
    if (!process->is_system)
    {
602
        if (!--user_processes && !shutdown_stage && master_socket_timeout != TIMEOUT_INFINITE)
603
            shutdown_timeout = add_timeout_user( master_socket_timeout, server_shutdown_timeout, NULL );
604
    }
605
    release_object( process );
606
    if (!--running_processes && shutdown_stage) close_master_socket( 0 );
607 608 609 610 611 612
}

/* callback for process sigkill timeout */
static void process_sigkill( void *private )
{
    struct process *process = private;
613
    int signal = 0;
614

615 616 617 618 619 620 621 622 623 624 625 626
    process->sigkill_delay *= 2;
    if (process->sigkill_delay >= TICKS_PER_SEC / 2)
        signal = SIGKILL;

    if (!kill( process->unix_pid, signal ) && !signal)
        process->sigkill_timeout = add_timeout_user( -process->sigkill_delay, process_sigkill, process );
    else
    {
        process->sigkill_delay = TICKS_PER_SEC / 64;
        process->sigkill_timeout = NULL;
        process_died( process );
    }
627 628 629 630 631 632
}

/* start the sigkill timer for a process upon exit */
static void start_sigkill_timer( struct process *process )
{
    grab_object( process );
633
    if (process->unix_pid != -1)
634
        process->sigkill_timeout = add_timeout_user( -process->sigkill_delay, process_sigkill, process );
635 636
    else
        process_died( process );
637 638
}

639
/* create a new process */
640
/* if the function fails the fd is closed */
641
struct process *create_process( int fd, struct process *parent, unsigned int flags, const startup_info_t *info,
642
                                const struct security_descriptor *sd, const obj_handle_t *handles,
643
                                unsigned int handle_count, struct token *token )
644
{
645 646
    struct process *process;

647 648 649 650 651
    if (!(process = alloc_object( &process_ops )))
    {
        close( fd );
        goto error;
    }
652
    process->parent_id       = 0;
653
    process->debug_obj       = NULL;
654
    process->debug_event     = NULL;
655
    process->handles         = NULL;
656
    process->msg_fd          = NULL;
657
    process->sigkill_timeout = NULL;
658
    process->sigkill_delay   = TICKS_PER_SEC / 64;
659
    process->unix_pid        = -1;
660
    process->exit_code       = STILL_ACTIVE;
Alexandre Julliard's avatar
Alexandre Julliard committed
661
    process->running_threads = 0;
662
    process->priority        = PROCESS_PRIOCLASS_NORMAL;
663
    process->suspend         = 0;
664
    process->is_system       = 0;
665
    process->debug_children  = 1;
666
    process->is_terminating  = 0;
667 668
    process->imagelen        = 0;
    process->image           = NULL;
669
    process->job             = NULL;
670
    process->console         = NULL;
671
    process->startup_state   = STARTUP_IN_PROGRESS;
672
    process->startup_info    = NULL;
673
    process->idle_event      = NULL;
674
    process->peb             = 0;
675
    process->ldt_copy        = 0;
676
    process->dir_cache       = NULL;
677
    process->winstation      = 0;
678
    process->desktop         = 0;
679
    process->token           = NULL;
680
    process->trace_data      = 0;
681 682
    process->rawinput_devices = NULL;
    process->rawinput_device_count = 0;
683
    process->rawinput_mouse  = NULL;
684
    process->rawinput_kbd    = NULL;
685
    memset( &process->image_info, 0, sizeof(process->image_info) );
686
    list_init( &process->kernel_object );
687
    list_init( &process->thread_list );
688
    list_init( &process->locks );
689
    list_init( &process->asyncs );
690
    list_init( &process->classes );
691
    list_init( &process->views );
692

693
    process->end_time = 0;
694

695 696 697 698 699 700
    if (sd && !default_set_sd( &process->obj, sd, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
                               DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION ))
    {
        close( fd );
        goto error;
    }
701 702 703 704 705
    if (!(process->id = process->group_id = alloc_ptid( process )))
    {
        close( fd );
        goto error;
    }
706
    if (!(process->msg_fd = create_anonymous_fd( &process_fd_ops, fd, &process->obj, 0 ))) goto error;
707

708
    /* create the handle table */
709
    if (!parent)
710 711
    {
        process->handles = alloc_handle_table( process, 0 );
712
        process->token = token_create_admin( TRUE, -1, TokenElevationTypeFull, default_session_id );
713
        process->affinity = ~0;
714
    }
715 716
    else
    {
717 718 719 720 721 722
        obj_handle_t std_handles[3];

        std_handles[0] = info->hstdin;
        std_handles[1] = info->hstdout;
        std_handles[2] = info->hstderr;

723
        process->parent_id = parent->id;
724 725 726 727
        if (flags & PROCESS_CREATE_FLAGS_INHERIT_HANDLES)
            process->handles = copy_handle_table( process, parent, handles, handle_count, std_handles );
        else
            process->handles = alloc_handle_table( process, 0 );
728 729
        /* Note: for security reasons, starting a new process does not attempt
         * to use the current impersonation token for the new process */
730
        process->token = token_duplicate( token ? token : parent->token, TRUE, 0, NULL, NULL, 0, NULL, 0 );
731
        process->affinity = parent->affinity;
732
    }
733
    if (!process->handles || !process->token) goto error;
734
    process->session_id = token_get_session_id( process->token );
735

736 737 738
    /* Assign a high security label to the token. The default would be medium
     * but Wine provides admin access to all applications right now so high
     * makes more sense for the time being. */
739
    if (!token_assign_label( process->token, &high_label_sid ))
740 741
        goto error;

742
    set_fd_events( process->msg_fd, POLLIN );  /* start listening to events */
743
    return process;
744 745

 error:
746 747
    if (process) release_object( process );
    /* if we failed to start our first process, close everything down */
748
    if (!running_processes && master_socket_timeout != TIMEOUT_INFINITE) close_master_socket( 0 );
749 750 751
    return NULL;
}

752 753
/* get the process data size */
data_size_t get_process_startup_info_size( struct process *process )
754
{
755
    struct startup_info *info = process->startup_info;
756

757 758
    if (!info) return 0;
    return info->data_size;
Alexandre Julliard's avatar
Alexandre Julliard committed
759 760 761
}

/* destroy a process when its refcount is 0 */
762
static void process_destroy( struct object *obj )
Alexandre Julliard's avatar
Alexandre Julliard committed
763 764 765 766
{
    struct process *process = (struct process *)obj;
    assert( obj->ops == &process_ops );

Alexandre Julliard's avatar
Alexandre Julliard committed
767
    /* we can't have a thread remaining */
768
    assert( list_empty( &process->thread_list ));
769
    assert( list_empty( &process->asyncs ));
770

771 772
    assert( !process->sigkill_timeout );  /* timeout should hold a reference to the process */

773
    close_process_handles( process );
774
    set_process_startup_state( process, STARTUP_ABORTED );
775 776 777 778 779 780

    if (process->job)
    {
        list_remove( &process->job_entry );
        release_object( process->job );
    }
781
    if (process->console) release_object( process->console );
782
    if (process->msg_fd) release_object( process->msg_fd );
783
    if (process->idle_event) release_object( process->idle_event );
784
    if (process->id) free_ptid( process->id );
785
    if (process->token) release_object( process->token );
786
    free( process->rawinput_devices );
787
    free( process->dir_cache );
788
    free( process->image );
Alexandre Julliard's avatar
Alexandre Julliard committed
789 790
}

Alexandre Julliard's avatar
Alexandre Julliard committed
791
/* dump a process on stdout for debugging purposes */
792
static void process_dump( struct object *obj, int verbose )
Alexandre Julliard's avatar
Alexandre Julliard committed
793 794 795 796
{
    struct process *process = (struct process *)obj;
    assert( obj->ops == &process_ops );

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

800
static int process_signaled( struct object *obj, struct wait_queue_entry *entry )
Alexandre Julliard's avatar
Alexandre Julliard committed
801 802
{
    struct process *process = (struct process *)obj;
803
    return !process->running_threads;
Alexandre Julliard's avatar
Alexandre Julliard committed
804 805
}

806 807
static unsigned int process_map_access( struct object *obj, unsigned int access )
{
808
    access = default_map_access( obj, access );
809 810
    if (access & PROCESS_QUERY_INFORMATION) access |= PROCESS_QUERY_LIMITED_INFORMATION;
    if (access & PROCESS_SET_INFORMATION) access |= PROCESS_SET_LIMITED_INFORMATION;
811
    return access;
812 813
}

814 815 816 817 818 819
static struct list *process_get_kernel_obj_list( struct object *obj )
{
    struct process *process = (struct process *)obj;
    return &process->kernel_object;
}

820 821 822 823 824 825 826 827
static struct security_descriptor *process_get_sd( struct object *obj )
{
    static struct security_descriptor *process_default_sd;

    if (obj->sd) return obj->sd;

    if (!process_default_sd)
    {
828 829
        struct ace *ace;
        struct acl *dacl;
830 831 832
        struct sid *sid;
        size_t users_sid_len = sid_len( &domain_users_sid );
        size_t admins_sid_len = sid_len( &builtin_admins_sid );
833
        size_t dacl_len = sizeof(*dacl) + 2 * sizeof(*ace) + users_sid_len + admins_sid_len;
834

835 836
        process_default_sd = mem_alloc( sizeof(*process_default_sd) + admins_sid_len + users_sid_len
                                    + dacl_len );
837 838 839 840
        process_default_sd->control   = SE_DACL_PRESENT;
        process_default_sd->owner_len = admins_sid_len;
        process_default_sd->group_len = users_sid_len;
        process_default_sd->sacl_len  = 0;
841
        process_default_sd->dacl_len  = dacl_len;
842 843 844
        sid = (struct sid *)(process_default_sd + 1);
        sid = copy_sid( sid, &builtin_admins_sid );
        sid = copy_sid( sid, &domain_users_sid );
845

846 847 848 849 850 851
        dacl = (struct acl *)((char *)(process_default_sd + 1) + admins_sid_len + users_sid_len);
        dacl->revision = ACL_REVISION;
        dacl->pad1     = 0;
        dacl->size     = dacl_len;
        dacl->count    = 2;
        dacl->pad2     = 0;
852
        ace = set_ace( ace_first( dacl ), &domain_users_sid, ACCESS_ALLOWED_ACE_TYPE,
853
                       INHERIT_ONLY_ACE | CONTAINER_INHERIT_ACE, GENERIC_READ );
854
        set_ace( ace_next( ace ), &builtin_admins_sid, ACCESS_ALLOWED_ACE_TYPE, 0, PROCESS_ALL_ACCESS );
855 856 857 858
    }
    return process_default_sd;
}

859
static void process_poll_event( struct fd *fd, int event )
860
{
861 862
    struct process *process = get_fd_user( fd );
    assert( process->obj.ops == &process_ops );
863

864
    if (event & (POLLERR | POLLHUP)) kill_process( process, 0 );
865 866 867
    else if (event & POLLIN) receive_fd( process );
}

868 869 870 871
static void startup_info_destroy( struct object *obj )
{
    struct startup_info *info = (struct startup_info *)obj;
    assert( obj->ops == &startup_info_ops );
872
    free( info->data );
873 874 875 876 877 878 879 880
    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 );

881 882 883 884 885
    fputs( "Startup info", stderr );
    if (info->data)
        fprintf( stderr, " in=%04x out=%04x err=%04x",
                 info->data->hstdin, info->data->hstdout, info->data->hstderr );
    fputc( '\n', stderr );
886 887
}

888
static int startup_info_signaled( struct object *obj, struct wait_queue_entry *entry )
889 890
{
    struct startup_info *info = (struct startup_info *)obj;
891
    return info->process && info->process->startup_state != STARTUP_IN_PROGRESS;
892 893
}

Alexandre Julliard's avatar
Alexandre Julliard committed
894
/* get a process from an id (and increment the refcount) */
895
struct process *get_process_from_id( process_id_t id )
Alexandre Julliard's avatar
Alexandre Julliard committed
896
{
897 898 899
    struct object *obj = get_ptid_entry( id );

    if (obj && obj->ops == &process_ops) return (struct process *)grab_object( obj );
900
    set_error( STATUS_INVALID_CID );
901
    return NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
902
}
Alexandre Julliard's avatar
Alexandre Julliard committed
903 904

/* get a process from a handle (and increment the refcount) */
905
struct process *get_process_from_handle( obj_handle_t handle, unsigned int access )
Alexandre Julliard's avatar
Alexandre Julliard committed
906 907 908 909 910
{
    return (struct process *)get_handle_obj( current->process, handle,
                                             access, &process_ops );
}

911 912 913
/* terminate a process with the given exit code */
static void terminate_process( struct process *process, struct thread *skip, int exit_code )
{
914
    struct thread *thread;
915

916
    grab_object( process );  /* make sure it doesn't get freed when threads die */
917 918
    process->is_terminating = 1;

919 920
restart:
    LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry )
921 922
    {
        if (exit_code) thread->exit_code = exit_code;
923 924
        if (thread == skip) continue;
        if (thread->state == TERMINATED) continue;
925
        kill_thread( thread, 1 );
926
        goto restart;
927
    }
928
    release_object( process );
929 930
}

931
/* kill all processes */
932
static void kill_all_processes(void)
933
{
934
    struct list *ptr;
935

936 937 938
    while ((ptr = list_head( &process_list )))
    {
        struct process *process = LIST_ENTRY( ptr, struct process, entry );
939
        terminate_process( process, NULL, 1 );
940 941 942
    }
}

943
/* kill all processes being attached to a console renderer */
944
void kill_console_processes( struct thread *renderer, int exit_code )
945 946 947
{
    for (;;)  /* restart from the beginning of the list every time */
    {
948
        struct process *process;
949 950

        /* find the first process being attached to 'renderer' and still running */
951
        LIST_FOR_EACH_ENTRY( process, &process_list, struct process, entry )
952
        {
953
            if (process == renderer->process) continue;
954
            if (process->console && console_get_renderer( process->console ) == renderer) break;
955
        }
956
        if (&process->entry == &process_list) break;  /* no process found */
957
        terminate_process( process, NULL, exit_code );
958 959 960
    }
}

Alexandre Julliard's avatar
Alexandre Julliard committed
961
/* a process has been killed (i.e. its last thread died) */
962
static void process_killed( struct process *process )
Alexandre Julliard's avatar
Alexandre Julliard committed
963
{
964
    assert( list_empty( &process->thread_list ));
965
    process->end_time = current_time;
966
    close_process_desktop( process );
967 968
    process->winstation = 0;
    process->desktop = 0;
969
    cancel_process_asyncs( process );
970
    close_process_handles( process );
971 972
    if (process->idle_event) release_object( process->idle_event );
    process->idle_event = NULL;
973
    assert( !process->console );
974

975
    destroy_process_classes( process );
976
    free_mapped_views( process );
977
    free_process_user_handles( process );
978
    remove_process_locks( process );
979
    set_process_startup_state( process, STARTUP_ABORTED );
980
    finish_process_tracing( process );
981
    release_job_process( process );
982
    start_sigkill_timer( process );
Alexandre Julliard's avatar
Alexandre Julliard committed
983
    wake_up( &process->obj, 0 );
Alexandre Julliard's avatar
Alexandre Julliard committed
984 985 986 987 988
}

/* add a thread to a process running threads list */
void add_process_thread( struct process *process, struct thread *thread )
{
989
    list_add_tail( &process->thread_list, &thread->proc_entry );
990 991
    if (!process->running_threads++)
    {
992
        list_add_tail( &process_list, &process->entry );
993 994 995
        running_processes++;
        if (!process->is_system)
        {
996 997 998 999 1000
            if (!user_processes++ && shutdown_timeout)
            {
                remove_timeout_user( shutdown_timeout );
                shutdown_timeout = NULL;
            }
1001 1002
        }
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
1003 1004 1005 1006 1007 1008 1009
    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 );
1010
    assert( !list_empty( &process->thread_list ));
Alexandre Julliard's avatar
Alexandre Julliard committed
1011

1012
    list_remove( &thread->proc_entry );
Alexandre Julliard's avatar
Alexandre Julliard committed
1013 1014 1015 1016

    if (!--process->running_threads)
    {
        /* we have removed the last running thread, exit the process */
1017
        process->exit_code = thread->exit_code;
1018
        generate_debug_event( thread, DbgExitProcessStateChange, process );
1019
        list_remove( &process->entry );
1020
        process_killed( process );
Alexandre Julliard's avatar
Alexandre Julliard committed
1021
    }
1022
    else generate_debug_event( thread, DbgExitThreadStateChange, thread );
Alexandre Julliard's avatar
Alexandre Julliard committed
1023 1024 1025
    release_object( thread );
}

1026 1027 1028 1029 1030
/* suspend all the threads of a process */
void suspend_process( struct process *process )
{
    if (!process->suspend++)
    {
1031 1032 1033
        struct list *ptr, *next;

        LIST_FOR_EACH_SAFE( ptr, next, &process->thread_list )
1034
        {
1035
            struct thread *thread = LIST_ENTRY( ptr, struct thread, proc_entry );
1036
            if (!thread->suspend) stop_thread( thread );
1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
        }
    }
}

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

        LIST_FOR_EACH_SAFE( ptr, next, &process->thread_list )
1050
        {
1051
            struct thread *thread = LIST_ENTRY( ptr, struct thread, proc_entry );
1052
            if (!thread->suspend) wake_thread( thread );
1053 1054 1055 1056
        }
    }
}

Alexandre Julliard's avatar
Alexandre Julliard committed
1057
/* kill a process on the spot */
1058
void kill_process( struct process *process, int violent_death )
Alexandre Julliard's avatar
Alexandre Julliard committed
1059
{
1060 1061 1062 1063 1064 1065
    if (!violent_death && process->msg_fd)  /* normal termination on pipe close */
    {
        release_object( process->msg_fd );
        process->msg_fd = NULL;
    }

1066
    if (process->sigkill_timeout) return;  /* already waiting for it to die */
1067

1068 1069
    if (violent_death) terminate_process( process, NULL, 1 );
    else
1070
    {
1071
        struct list *ptr;
1072

1073 1074
        grab_object( process );  /* make sure it doesn't get freed when threads die */
        while ((ptr = list_head( &process->thread_list )))
1075 1076 1077 1078
        {
            struct thread *thread = LIST_ENTRY( ptr, struct thread, proc_entry );
            kill_thread( thread, 0 );
        }
1079
        release_object( process );
1080
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
1081 1082
}

1083 1084
/* detach all processes being debugged by a given thread */
void detach_debugged_processes( struct debug_obj *debug_obj, int exit_code )
1085 1086 1087
{
    for (;;)  /* restart from the beginning of the list every time */
    {
1088 1089
        struct process *process;

1090
        /* find the first process being debugged by 'debugger' and still running */
1091
        LIST_FOR_EACH_ENTRY( process, &process_list, struct process, entry )
1092
            if (process->debug_obj == debug_obj) break;
1093

1094
        if (&process->entry == &process_list) break;  /* no process found */
1095
        if (exit_code)
1096
        {
1097 1098
            process->debug_obj = NULL;
            terminate_process( process, NULL, exit_code );
1099
        }
1100
        else debugger_detach( process, debug_obj );
1101 1102 1103 1104
    }
}


1105 1106
void enum_processes( int (*cb)(struct process*, void*), void *user )
{
1107 1108 1109
    struct list *ptr, *next;

    LIST_FOR_EACH_SAFE( ptr, next, &process_list )
1110
    {
1111
        struct process *process = LIST_ENTRY( ptr, struct process, entry );
1112 1113 1114 1115
        if ((cb)(process, user)) break;
    }
}

1116 1117 1118
/* set the debugged flag in the process PEB */
int set_process_debug_flag( struct process *process, int flag )
{
1119
    char data = (flag != 0);
1120 1121
    client_ptr_t peb32 = 0;

1122
    if (!is_machine_64bit( process->machine ) && is_machine_64bit( native_machine ))
1123
        peb32 = process->peb + 0x1000;
1124 1125

    /* BeingDebugged flag is the byte at offset 2 in the PEB */
1126
    if (peb32 && !write_process_memory( process, peb32 + 2, 1, &data )) return 0;
1127
    return write_process_memory( process, process->peb + 2, 1, &data );
1128 1129
}

1130 1131 1132
/* create a new process */
DECL_HANDLER(new_process)
{
1133
    struct startup_info *info;
1134 1135 1136 1137
    const void *info_ptr;
    struct unicode_str name;
    const struct security_descriptor *sd;
    const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL );
1138
    struct process *process = NULL;
1139
    struct token *token = NULL;
1140
    struct debug_obj *debug_obj = NULL;
1141 1142
    struct process *parent;
    struct thread *parent_thread = current;
1143
    int socket_fd = thread_get_inflight_fd( current, req->socket_fd );
1144
    const obj_handle_t *handles = NULL;
1145 1146
    const obj_handle_t *job_handles = NULL;
    unsigned int i, job_handle_count;
1147
    struct job *job;
1148 1149 1150 1151 1152 1153

    if (socket_fd == -1)
    {
        set_error( STATUS_INVALID_PARAMETER );
        return;
    }
1154 1155 1156 1157 1158 1159
    if (!objattr)
    {
        set_error( STATUS_INVALID_PARAMETER );
        close( socket_fd );
        return;
    }
1160 1161 1162 1163 1164 1165
    if (fcntl( socket_fd, F_SETFL, O_NONBLOCK ) == -1)
    {
        set_error( STATUS_INVALID_HANDLE );
        close( socket_fd );
        return;
    }
1166
    if (shutdown_stage)
1167 1168 1169 1170 1171
    {
        set_error( STATUS_SHUTDOWN_IN_PROGRESS );
        close( socket_fd );
        return;
    }
1172

1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183
    if (req->parent_process)
    {
        if (!(parent = get_process_from_handle( req->parent_process, PROCESS_CREATE_PROCESS)))
        {
            close( socket_fd );
            return;
        }
        parent_thread = NULL;
    }
    else parent = (struct process *)grab_object( current->process );

1184 1185
    /* If a job further in the job chain does not permit breakaway process creation
     * succeeds and the process which is trying to breakaway is assigned to that job. */
1186
    if (parent->job && (req->flags & PROCESS_CREATE_FLAGS_BREAKAWAY) &&
1187 1188 1189 1190
        !(parent->job->limit_flags & (JOB_OBJECT_LIMIT_BREAKAWAY_OK | JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)))
    {
        set_error( STATUS_ACCESS_DENIED );
        close( socket_fd );
1191
        release_object( parent );
1192 1193 1194
        return;
    }

1195
    /* build the startup info for a new process */
1196 1197 1198
    if (!(info = alloc_object( &startup_info_ops )))
    {
        close( socket_fd );
1199
        release_object( parent );
1200 1201
        return;
    }
1202 1203
    info->process  = NULL;
    info->data     = NULL;
1204

1205
    info_ptr = get_req_data_after_objattr( objattr, &info->data_size );
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218

    if ((req->handles_size & 3) || req->handles_size > info->data_size)
    {
        set_error( STATUS_INVALID_PARAMETER );
        close( socket_fd );
        goto done;
    }
    if (req->handles_size)
    {
        handles = info_ptr;
        info_ptr = (const char *)info_ptr + req->handles_size;
        info->data_size -= req->handles_size;
    }
1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243

    if ((req->jobs_size & 3) || req->jobs_size > info->data_size)
    {
        set_error( STATUS_INVALID_PARAMETER );
        close( socket_fd );
        goto done;
    }
    if (req->jobs_size)
    {
        job_handles = info_ptr;
        info_ptr = (const char *)info_ptr + req->jobs_size;
        info->data_size -= req->jobs_size;
    }

    job_handle_count = req->jobs_size / sizeof(*handles);
    for (i = 0; i < job_handle_count; ++i)
    {
        if (!(job = get_job_obj( current->process, job_handles[i], JOB_OBJECT_ASSIGN_PROCESS )))
        {
            close( socket_fd );
            goto done;
        }
        release_object( job );
    }

1244 1245 1246 1247 1248 1249 1250 1251
    info->info_size = min( req->info_size, info->data_size );

    if (req->info_size < sizeof(*info->data))
    {
        /* make sure we have a full startup_info_t structure */
        data_size_t env_size = info->data_size - info->info_size;
        data_size_t info_size = min( req->info_size, FIELD_OFFSET( startup_info_t, curdir_len ));

1252 1253 1254 1255 1256
        if (!(info->data = mem_alloc( sizeof(*info->data) + env_size )))
        {
            close( socket_fd );
            goto done;
        }
1257
        memcpy( info->data, info_ptr, info_size );
1258
        memset( (char *)info->data + info_size, 0, sizeof(*info->data) - info_size );
1259
        memcpy( info->data + 1, (const char *)info_ptr + req->info_size, env_size );
1260 1261 1262 1263 1264 1265 1266
        info->info_size = sizeof(startup_info_t);
        info->data_size = info->info_size + env_size;
    }
    else
    {
        data_size_t pos = sizeof(*info->data);

1267
        if (!(info->data = memdup( info_ptr, info->data_size )))
1268 1269 1270 1271
        {
            close( socket_fd );
            goto done;
        }
1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282
#define FIXUP_LEN(len) do { (len) = min( (len), info->info_size - pos ); pos += (len); } while(0)
        FIXUP_LEN( info->data->curdir_len );
        FIXUP_LEN( info->data->dllpath_len );
        FIXUP_LEN( info->data->imagepath_len );
        FIXUP_LEN( info->data->cmdline_len );
        FIXUP_LEN( info->data->title_len );
        FIXUP_LEN( info->data->desktop_len );
        FIXUP_LEN( info->data->shellinfo_len );
        FIXUP_LEN( info->data->runtime_len );
#undef FIXUP_LEN
    }
1283

1284 1285 1286 1287 1288
    if (req->token && !(token = get_token_obj( current->process, req->token, TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY )))
    {
        close( socket_fd );
        goto done;
    }
1289 1290 1291 1292 1293
    if (req->debug && !(debug_obj = get_debug_obj( current->process, req->debug, DEBUG_PROCESS_ASSIGN )))
    {
        close( socket_fd );
        goto done;
    }
1294

1295
    if (!(process = create_process( socket_fd, parent, req->flags, info->data, sd,
1296
                                    handles, req->handles_size / sizeof(*handles), token )))
1297
        goto done;
1298

1299 1300
    process->startup_info = (struct startup_info *)grab_object( info );

1301 1302
    job = parent->job;
    while (job)
1303
    {
1304 1305 1306 1307 1308 1309 1310 1311 1312
        if (!(job->limit_flags & JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)
                && !(req->flags & PROCESS_CREATE_FLAGS_BREAKAWAY
                && job->limit_flags & JOB_OBJECT_LIMIT_BREAKAWAY_OK))
        {
            add_job_process( job, process );
            assert( !get_error() );
            break;
        }
        job = job->parent;
1313 1314
    }

1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326
    for (i = 0; i < job_handle_count; ++i)
    {
        job = get_job_obj( current->process, job_handles[i], JOB_OBJECT_ASSIGN_PROCESS );
        add_job_process( job, process );
        release_object( job );
        if (get_error())
        {
            release_job_process( process );
            goto done;
        }
    }

1327
    /* connect to the window station */
1328
    connect_process_winstation( process, parent_thread, parent );
1329

1330 1331
    /* inherit the process console, but keep pseudo handles (< 0), and 0 (= not attached to a console) as is */
    if ((int)info->data->console > 0)
1332 1333
        info->data->console = duplicate_handle( parent, info->data->console, process,
                                                0, 0, DUPLICATE_SAME_ACCESS );
1334

1335
    if (!(req->flags & PROCESS_CREATE_FLAGS_INHERIT_HANDLES) && info->data->console != 1)
1336
    {
1337 1338 1339 1340 1341 1342
        info->data->hstdin  = duplicate_handle( parent, info->data->hstdin, process,
                                                0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
        info->data->hstdout = duplicate_handle( parent, info->data->hstdout, process,
                                                0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
        info->data->hstderr = duplicate_handle( parent, info->data->hstderr, process,
                                                0, OBJ_INHERIT, DUPLICATE_SAME_ACCESS );
1343 1344 1345 1346
        /* 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();
    }
1347 1348 1349

    /* attach to the debugger */
    if (debug_obj)
1350
    {
1351
        process->debug_obj = debug_obj;
1352
        process->debug_children = !(req->flags & PROCESS_CREATE_FLAGS_NO_DEBUG_INHERIT);
1353
    }
1354
    else if (parent->debug_children)
1355
    {
1356
        process->debug_obj = parent->debug_obj;
1357
        /* debug_children is set to 1 by default */
1358
    }
1359

1360
    if (!info->data->console_flags) process->group_id = parent->group_id;
1361 1362

    info->process = (struct process *)grab_object( process );
1363
    reply->info = alloc_handle( current->process, info, SYNCHRONIZE, 0 );
1364
    reply->pid = get_process_id( process );
1365
    reply->handle = alloc_handle_no_access_check( current->process, process, req->access, objattr->attributes );
1366 1367

 done:
1368
    if (process) release_object( process );
1369
    if (debug_obj) release_object( debug_obj );
1370
    if (token) release_object( token );
1371
    release_object( parent );
1372
    release_object( info );
1373
}
1374

1375 1376
/* Retrieve information about a newly started process */
DECL_HANDLER(get_new_process_info)
1377
{
1378 1379 1380 1381
    struct startup_info *info;

    if ((info = (struct startup_info *)get_handle_obj( current->process, req->info,
                                                       0, &startup_info_ops )))
1382
    {
1383
        reply->success = is_process_init_done( info->process );
1384
        reply->exit_code = info->process->exit_code;
1385
        release_object( info );
1386
    }
1387 1388
}

1389 1390 1391
/* Retrieve the new process startup info */
DECL_HANDLER(get_startup_info)
{
1392 1393
    struct process *process = current->process;
    struct startup_info *info = process->startup_info;
1394
    data_size_t size;
1395

1396 1397 1398
    if (!info) return;

    /* we return the data directly without making a copy so this can only be called once */
1399
    reply->info_size = info->info_size;
1400 1401 1402 1403 1404
    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;
1405 1406
}

1407 1408 1409 1410
/* signal the end of the process initialization */
DECL_HANDLER(init_process_done)
{
    struct process *process = current->process;
1411 1412 1413
    struct memory_view *view;
    client_ptr_t base;
    const pe_image_info_t *image_info;
1414

1415
    if (is_process_init_done(process))
1416
    {
1417
        set_error( STATUS_INVALID_PARAMETER );
1418 1419
        return;
    }
1420
    if (!(view = get_exe_view( process )))
1421
    {
1422 1423
        set_error( STATUS_DLL_NOT_FOUND );
        return;
1424
    }
1425
    if (!(image_info = get_view_image_info( view, &base ))) return;
1426

1427 1428 1429 1430
    current->teb      = req->teb;
    process->peb      = req->peb;
    process->ldt_copy = req->ldt_copy;

1431
    process->start_time = current_time;
1432
    current->entry_point = base + image_info->entry_point;
1433

1434
    init_process_tracing( process );
1435
    generate_startup_debug_events( process );
1436 1437
    set_process_startup_state( process, STARTUP_DONE );

1438 1439
    if (image_info->subsystem != IMAGE_SUBSYSTEM_WINDOWS_CUI)
        process->idle_event = create_event( NULL, NULL, 0, 1, 0, NULL );
1440
    if (process->debug_obj) set_process_debug_flag( process, 1 );
1441
    reply->entry = current->entry_point;
1442
    reply->suspend = (current->suspend || process->suspend);
1443 1444
}

1445 1446 1447 1448
/* open a handle to a process */
DECL_HANDLER(open_process)
{
    struct process *process = get_process_from_id( req->pid );
1449
    reply->handle = 0;
1450 1451
    if (process)
    {
1452
        reply->handle = alloc_handle( current->process, process, req->access, req->attributes );
1453 1454 1455 1456 1457 1458 1459 1460 1461
        release_object( process );
    }
}

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

1462
    if (req->handle)
1463
    {
1464 1465
        process = get_process_from_handle( req->handle, PROCESS_TERMINATE );
        if (!process) return;
1466
    }
1467 1468 1469 1470 1471
    else process = (struct process *)grab_object( current->process );

    reply->self = (current->process == process);
    terminate_process( process, current, req->exit_code );
    release_object( process );
1472 1473 1474 1475 1476 1477 1478
}

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

1479
    if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_LIMITED_INFORMATION )))
1480
    {
1481
        reply->pid              = get_process_id( process );
1482
        reply->ppid             = process->parent_id;
1483 1484
        reply->exit_code        = process->exit_code;
        reply->priority         = process->priority;
1485
        reply->affinity         = process->affinity;
1486
        reply->peb              = process->peb;
1487 1488
        reply->start_time       = process->start_time;
        reply->end_time         = process->end_time;
1489
        reply->session_id       = process->session_id;
1490
        reply->machine          = process->machine;
1491
        if (get_reply_max_size())
1492 1493 1494 1495
        {
            if (!process->running_threads) set_error( STATUS_PROCESS_IS_TERMINATING );
            else set_reply_data( &process->image_info, min( sizeof(process->image_info), get_reply_max_size() ));
        }
1496 1497 1498 1499
        release_object( process );
    }
}

1500 1501 1502 1503 1504 1505 1506 1507 1508
/* retrieve debug information about a process */
DECL_HANDLER(get_process_debug_info)
{
    struct process *process;

    if (!(process = get_process_from_handle( req->handle, PROCESS_QUERY_LIMITED_INFORMATION ))) return;

    reply->debug_children = process->debug_children;
    if (!process->debug_obj) set_error( STATUS_PORT_NOT_SET );
1509
    else reply->debug = alloc_handle( current->process, process->debug_obj, MAXIMUM_ALLOWED, 0 );
1510 1511 1512
    release_object( process );
}

1513 1514 1515 1516 1517 1518
/* fetch the name of the process image */
DECL_HANDLER(get_process_image_name)
{
    struct process *process = get_process_from_handle( req->handle, PROCESS_QUERY_LIMITED_INFORMATION );

    if (!process) return;
1519
    if (process->image)
1520
    {
1521
        struct unicode_str name = { process->image, process->imagelen };
1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541
        /* skip the \??\ prefix */
        if (req->win32 && name.len > 6 * sizeof(WCHAR) && name.str[5] == ':')
        {
            name.str += 4;
            name.len -= 4 * sizeof(WCHAR);
        }
        /* FIXME: else resolve symlinks in NT path */

        reply->len = name.len;
        if (name.len <= get_reply_max_size())
        {
            WCHAR *ptr = set_reply_data( name.str, name.len );
            /* change \??\ to \\?\ */
            if (req->win32 && name.len > sizeof(WCHAR) && ptr[1] == '?') ptr[1] = '\\';
        }
        else set_error( STATUS_BUFFER_TOO_SMALL );
    }
    release_object( process );
}

1542 1543 1544 1545 1546 1547 1548 1549
/* retrieve information about a process memory usage */
DECL_HANDLER(get_process_vm_counters)
{
    struct process *process = get_process_from_handle( req->handle, PROCESS_QUERY_LIMITED_INFORMATION );

    if (!process) return;
    if (process->unix_pid != -1)
    {
1550
#ifdef linux
1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567
        FILE *f;
        char proc_path[32], line[256];
        unsigned long value;

        sprintf( proc_path, "/proc/%u/status", process->unix_pid );
        if ((f = fopen( proc_path, "r" )))
        {
            while (fgets( line, sizeof(line), f ))
            {
                if (sscanf( line, "VmPeak: %lu", &value ))
                    reply->peak_virtual_size = (mem_size_t)value * 1024;
                else if (sscanf( line, "VmSize: %lu", &value ))
                    reply->virtual_size = (mem_size_t)value * 1024;
                else if (sscanf( line, "VmHWM: %lu", &value ))
                    reply->peak_working_set_size = (mem_size_t)value * 1024;
                else if (sscanf( line, "VmRSS: %lu", &value ))
                    reply->working_set_size = (mem_size_t)value * 1024;
1568 1569
                else if (sscanf( line, "RssAnon: %lu", &value ))
                    reply->pagefile_usage += (mem_size_t)value * 1024;
1570
                else if (sscanf( line, "VmSwap: %lu", &value ))
1571
                    reply->pagefile_usage += (mem_size_t)value * 1024;
1572
            }
1573
            reply->peak_pagefile_usage = reply->pagefile_usage;
1574 1575 1576
            fclose( f );
        }
        else set_error( STATUS_ACCESS_DENIED );
1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596
#elif defined(HAVE_LIBPROCSTAT)
        struct procstat *procstat;
        unsigned int count;

        if ((procstat = procstat_open_sysctl()))
        {
            struct kinfo_proc *kp = procstat_getprocs( procstat, KERN_PROC_PID, process->unix_pid, &count );
            if (kp)
            {
                reply->virtual_size = kp->ki_size;
                reply->peak_virtual_size = reply->virtual_size;
                reply->working_set_size = kp->ki_rssize << PAGE_SHIFT;
                reply->peak_working_set_size = kp->ki_rusage.ru_maxrss * 1024;
                procstat_freeprocs( procstat, kp );
            }
            else set_error( STATUS_ACCESS_DENIED );
            procstat_close( procstat );
        }
        else set_error( STATUS_ACCESS_DENIED );
#endif
1597 1598 1599 1600 1601
    }
    else set_error( STATUS_ACCESS_DENIED );
    release_object( process );
}

1602 1603 1604 1605
static void set_process_affinity( struct process *process, affinity_t affinity )
{
    struct thread *thread;

1606 1607 1608 1609 1610 1611
    if (!process->running_threads)
    {
        set_error( STATUS_PROCESS_IS_TERMINATING );
        return;
    }

1612 1613 1614 1615 1616 1617 1618 1619
    process->affinity = affinity;

    LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry )
    {
        set_thread_affinity( thread, affinity );
    }
}

1620 1621 1622 1623 1624 1625 1626
/* set information about a process */
DECL_HANDLER(set_process_info)
{
    struct process *process;

    if ((process = get_process_from_handle( req->handle, PROCESS_SET_INFORMATION )))
    {
1627
        if (req->mask & SET_PROCESS_INFO_PRIORITY) process->priority = req->priority;
1628
        if (req->mask & SET_PROCESS_INFO_AFFINITY) set_process_affinity( process, req->affinity );
1629 1630 1631
        release_object( process );
    }
}
1632 1633 1634 1635 1636

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

1639 1640 1641
    if (!(process = get_process_from_handle( req->handle, PROCESS_VM_READ ))) return;

    if (len)
1642
    {
1643
        char *buffer = mem_alloc( len );
1644 1645
        if (buffer)
        {
1646
            if (read_process_memory( process, req->addr, len, buffer ))
1647
                set_reply_data_ptr( buffer, len );
1648 1649
            else
                free( buffer );
1650
        }
1651
    }
1652
    release_object( process );
1653
}
1654 1655 1656 1657 1658 1659 1660 1661

/* 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 )))
    {
1662
        data_size_t len = get_req_data_size();
1663 1664
        if (len) write_process_memory( process, req->addr, len, get_req_data() );
        else set_error( STATUS_INVALID_PARAMETER );
1665 1666 1667
        release_object( process );
    }
}
1668

1669 1670
/* retrieve the process idle event */
DECL_HANDLER(get_process_idle_event)
1671 1672 1673
{
    struct process *process;

1674
    reply->event = 0;
1675 1676
    if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
    {
1677
        if (process->idle_event && process != current->process)
1678 1679
            reply->event = alloc_handle( current->process, process->idle_event,
                                         EVENT_ALL_ACCESS, 0 );
1680 1681 1682
        release_object( process );
    }
}
1683 1684 1685 1686

/* make the current process a system process */
DECL_HANDLER(make_process_system)
{
1687
    struct process *process;
1688
    struct thread *thread;
1689

1690
    if (!shutdown_event)
1691
    {
1692 1693
        if (!(shutdown_event = create_event( NULL, NULL, OBJ_PERMANENT, 1, 0, NULL ))) return;
        release_object( shutdown_event );
1694 1695
    }

1696 1697
    if (!(process = get_process_from_handle( req->handle, PROCESS_SET_INFORMATION ))) return;

1698
    if (!(reply->event = alloc_handle( current->process, shutdown_event, SYNCHRONIZE, 0 )))
1699 1700
    {
        release_object( process );
1701
        return;
1702
    }
1703 1704 1705

    if (!process->is_system)
    {
1706 1707
        LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry )
            release_thread_desktop( thread, 0 );
1708
        process->is_system = 1;
1709
        if (!--user_processes && !shutdown_stage && master_socket_timeout != TIMEOUT_INFINITE)
1710
            shutdown_timeout = add_timeout_user( master_socket_timeout, server_shutdown_timeout, NULL );
1711
    }
1712
    release_object( process );
1713
}
1714 1715 1716 1717 1718 1719

/* create a new job object */
DECL_HANDLER(create_job)
{
    struct job *job;
    struct unicode_str name;
1720
    struct object *root;
1721
    const struct security_descriptor *sd;
1722
    const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, &root );
1723

1724
    if (!objattr) return;
1725

1726
    if ((job = create_job_object( root, &name, objattr->attributes, sd )))
1727 1728
    {
        if (get_error() == STATUS_OBJECT_NAME_EXISTS)
1729
            reply->handle = alloc_handle( current->process, job, req->access, objattr->attributes );
1730
        else
1731 1732
            reply->handle = alloc_handle_no_access_check( current->process, job,
                                                          req->access, objattr->attributes );
1733 1734 1735
        release_object( job );
    }
    if (root) release_object( root );
1736 1737 1738 1739 1740
}

/* open a job object */
DECL_HANDLER(open_job)
{
1741
    struct unicode_str name = get_req_unicode_str();
1742

1743 1744
    reply->handle = open_object( current->process, req->rootdir, req->access,
                                 &job_ops, &name, req->attributes );
1745
}
1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756

/* assign a job object to a process */
DECL_HANDLER(assign_job)
{
    struct process *process;
    struct job *job = get_job_obj( current->process, req->job, JOB_OBJECT_ASSIGN_PROCESS );

    if (!job) return;

    if ((process = get_process_from_handle( req->process, PROCESS_SET_QUOTA | PROCESS_TERMINATE )))
    {
1757 1758
        if (!process->running_threads) set_error( STATUS_PROCESS_IS_TERMINATING );
        else add_job_process( job, process );
1759 1760 1761 1762
        release_object( process );
    }
    release_object( job );
}
1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779


/* check if a process is associated with a job */
DECL_HANDLER(process_in_job)
{
    struct process *process;
    struct job *job;

    if (!(process = get_process_from_handle( req->process, PROCESS_QUERY_INFORMATION )))
        return;

    if (!req->job)
    {
        set_error( process->job ? STATUS_PROCESS_IN_JOB : STATUS_PROCESS_NOT_IN_JOB );
    }
    else if ((job = get_job_obj( current->process, req->job, JOB_OBJECT_QUERY )))
    {
1780
        set_error( process_in_job( job, process ) ? STATUS_PROCESS_IN_JOB : STATUS_PROCESS_NOT_IN_JOB );
1781 1782 1783 1784
        release_object( job );
    }
    release_object( process );
}
1785

1786 1787 1788 1789
/* retrieve information about a job */
DECL_HANDLER(get_job_info)
{
    struct job *job = get_job_obj( current->process, req->handle, JOB_OBJECT_QUERY );
1790 1791
    process_id_t *pids;
    data_size_t len;
1792 1793 1794 1795 1796

    if (!job) return;

    reply->total_processes = job->total_processes;
    reply->active_processes = job->num_processes;
1797 1798 1799 1800 1801

    len = min( get_reply_max_size(), reply->active_processes * sizeof(*pids) );
    if (len && ((pids = set_reply_data_size( len ))))
        get_job_pids( job, pids, pids + len / sizeof(*pids) );

1802 1803 1804
    release_object( job );
}

1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815
/* terminate all processes associated with the job */
DECL_HANDLER(terminate_job)
{
    struct job *job = get_job_obj( current->process, req->handle, JOB_OBJECT_TERMINATE );

    if (!job) return;

    terminate_job( job, req->status );
    release_object( job );
}

1816 1817 1818 1819 1820 1821 1822 1823 1824 1825
/* update limits of the job object */
DECL_HANDLER(set_job_limits)
{
    struct job *job = get_job_obj( current->process, req->handle, JOB_OBJECT_SET_ATTRIBUTES );

    if (!job) return;

    job->limit_flags = req->limit_flags;
    release_object( job );
}
1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837

/* set the jobs completion port */
DECL_HANDLER(set_job_completion_port)
{
    struct job *job = get_job_obj( current->process, req->job, JOB_OBJECT_SET_ATTRIBUTES );

    if (!job) return;

    if (!job->completion_port)
    {
        job->completion_port = get_completion_obj( current->process, req->port, IO_COMPLETION_MODIFY_STATE );
        job->completion_key = req->key;
1838 1839

        add_job_completion_existing_processes( job, job );
1840 1841 1842 1843 1844 1845
    }
    else
        set_error( STATUS_INVALID_PARAMETER );

    release_object( job );
}
1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883

/* Suspend a process */
DECL_HANDLER(suspend_process)
{
    struct process *process;

    if ((process = get_process_from_handle( req->handle, PROCESS_SUSPEND_RESUME )))
    {
        struct list *ptr, *next;

        LIST_FOR_EACH_SAFE( ptr, next, &process->thread_list )
        {
            struct thread *thread = LIST_ENTRY( ptr, struct thread, proc_entry );
            suspend_thread( thread );
        }

        release_object( process );
    }
}

/* Resume a process */
DECL_HANDLER(resume_process)
{
    struct process *process;

    if ((process = get_process_from_handle( req->handle, PROCESS_SUSPEND_RESUME )))
    {
        struct list *ptr, *next;

        LIST_FOR_EACH_SAFE( ptr, next, &process->thread_list )
        {
            struct thread *thread = LIST_ENTRY( ptr, struct thread, proc_entry );
            resume_thread( thread );
        }

        release_object( process );
    }
}
1884 1885 1886 1887 1888 1889 1890 1891 1892 1893

/* Get a list of processes and threads currently running */
DECL_HANDLER(list_processes)
{
    struct process *process;
    struct thread *thread;
    unsigned int pos = 0;
    char *buffer;

    reply->process_count = 0;
1894 1895
    reply->total_thread_count = 0;
    reply->total_name_len = 0;
1896 1897 1898 1899 1900
    reply->info_size = 0;

    LIST_FOR_EACH_ENTRY( process, &process_list, struct process, entry )
    {
        reply->info_size = (reply->info_size + 7) & ~7;
1901
        reply->info_size += sizeof(struct process_info) + process->imagelen;
1902 1903 1904
        reply->info_size = (reply->info_size + 7) & ~7;
        reply->info_size += process->running_threads * sizeof(struct thread_info);
        reply->process_count++;
1905 1906
        reply->total_thread_count += process->running_threads;
        reply->total_name_len += process->imagelen;
1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923
    }

    if (reply->info_size > get_reply_max_size())
    {
        set_error( STATUS_INFO_LENGTH_MISMATCH );
        return;
    }

    if (!(buffer = set_reply_data_size( reply->info_size ))) return;

    memset( buffer, 0, reply->info_size );
    LIST_FOR_EACH_ENTRY( process, &process_list, struct process, entry )
    {
        struct process_info *process_info;

        pos = (pos + 7) & ~7;
        process_info = (struct process_info *)(buffer + pos);
1924
        process_info->start_time = process->start_time;
1925
        process_info->name_len = process->imagelen;
1926 1927 1928 1929
        process_info->thread_count = process->running_threads;
        process_info->priority = process->priority;
        process_info->pid = process->id;
        process_info->parent_pid = process->parent_id;
1930
        process_info->session_id = process->session_id;
1931 1932 1933
        process_info->handle_count = get_handle_table_count(process);
        process_info->unix_pid = process->unix_pid;
        pos += sizeof(*process_info);
1934 1935
        memcpy( buffer + pos, process->image, process->imagelen );
        pos += process->imagelen;
1936 1937 1938 1939 1940
        pos = (pos + 7) & ~7;
        LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry )
        {
            struct thread_info *thread_info = (struct thread_info *)(buffer + pos);

1941
            thread_info->start_time = thread->creation_time;
1942 1943 1944 1945
            thread_info->tid = thread->id;
            thread_info->base_priority = thread->priority;
            thread_info->current_priority = thread->priority; /* FIXME */
            thread_info->unix_tid = thread->unix_tid;
1946 1947
            thread_info->entry_point = thread->entry_point;
            thread_info->teb = thread->teb;
1948 1949 1950 1951
            pos += sizeof(*thread_info);
        }
    }
}