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

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

Alexandre Julliard's avatar
Alexandre Julliard committed
24
#include <assert.h>
25
#include <ctype.h>
26 27 28
#ifdef HAVE_DIRENT_H
# include <dirent.h>
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
29
#include <errno.h>
30
#include <fcntl.h>
31 32 33
#ifdef HAVE_LWP_H
#include <lwp.h>
#endif
34 35 36
#ifdef HAVE_PTHREAD_NP_H
# include <pthread_np.h>
#endif
37
#include <signal.h>
38
#include <stdarg.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
39 40
#include <stdio.h>
#include <string.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
41
#include <sys/types.h>
42 43 44
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
45 46 47
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
Steven Edwards's avatar
Steven Edwards committed
48
#ifdef HAVE_SYS_UN_H
49
#include <sys/un.h>
Steven Edwards's avatar
Steven Edwards committed
50
#endif
51
#ifdef HAVE_SYS_MMAN_H
52
#include <sys/mman.h>
53
#endif
54 55 56
#ifdef HAVE_SYS_PRCTL_H
# include <sys/prctl.h>
#endif
57 58 59
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
60 61 62
#ifdef HAVE_SYS_SYSCALL_H
# include <sys/syscall.h>
#endif
Steven Edwards's avatar
Steven Edwards committed
63
#ifdef HAVE_SYS_UIO_H
Alexandre Julliard's avatar
Alexandre Julliard committed
64
#include <sys/uio.h>
Steven Edwards's avatar
Steven Edwards committed
65
#endif
66 67 68
#ifdef HAVE_SYS_UCONTEXT_H
# include <sys/ucontext.h>
#endif
69 70 71
#ifdef HAVE_SYS_THR_H
#include <sys/thr.h>
#endif
72 73 74
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
75

76
#include "ntstatus.h"
77
#define WIN32_NO_STATUS
78 79
#include "windef.h"
#include "winnt.h"
80
#include "wine/library.h"
81
#include "wine/server.h"
82
#include "wine/debug.h"
83
#include "ntdll_misc.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
84

85 86
WINE_DEFAULT_DEBUG_CHANNEL(server);

Alexandre Julliard's avatar
Alexandre Julliard committed
87 88 89 90
/* Some versions of glibc don't define this */
#ifndef SCM_RIGHTS
#define SCM_RIGHTS 1
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
91

92 93 94 95
#ifndef MSG_CMSG_CLOEXEC
#define MSG_CMSG_CLOEXEC 0
#endif

96
#define SOCKETNAME "socket"        /* name of the socket file */
97
#define LOCKNAME   "lock"          /* name of the lock file */
98

99 100 101 102 103 104
#ifdef __i386__
static const enum cpu_type client_cpu = CPU_x86;
#elif defined(__x86_64__)
static const enum cpu_type client_cpu = CPU_x86_64;
#elif defined(__powerpc__)
static const enum cpu_type client_cpu = CPU_POWERPC;
105 106
#elif defined(__arm__)
static const enum cpu_type client_cpu = CPU_ARM;
107 108
#elif defined(__aarch64__)
static const enum cpu_type client_cpu = CPU_ARM64;
109 110 111 112
#else
#error Unsupported CPU
#endif

113
unsigned int server_cpus = 0;
114
BOOL is_wow64 = FALSE;
115

116
timeout_t server_start_time = 0;  /* time of server startup */
117

118
sigset_t server_block_set;  /* signals to block during server calls */
119
static int fd_socket = -1;  /* socket to exchange file descriptors with the server */
120
static pid_t server_pid;
121

122 123 124 125 126 127 128 129 130
static RTL_CRITICAL_SECTION fd_cache_section;
static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
{
    0, 0, &fd_cache_section,
    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
      0, 0, { (DWORD_PTR)(__FILE__ ": fd_cache_section") }
};
static RTL_CRITICAL_SECTION fd_cache_section = { &critsect_debug, -1, 0, 0, 0, 0 };

131 132 133 134 135 136 137 138 139 140 141
/* atomically exchange a 64-bit value */
static inline LONG64 interlocked_xchg64( LONG64 *dest, LONG64 val )
{
#ifdef _WIN64
    return (LONG64)interlocked_xchg_ptr( (void **)dest, (void *)val );
#else
    LONG64 tmp = *dest;
    while (interlocked_cmpxchg64( dest, val, tmp ) != tmp) tmp = *dest;
    return tmp;
#endif
}
142

143 144 145 146 147 148
#ifdef __GNUC__
static void fatal_error( const char *err, ... ) __attribute__((noreturn, format(printf,1,2)));
static void fatal_perror( const char *err, ... ) __attribute__((noreturn, format(printf,1,2)));
static void server_connect_error( const char *serverdir ) __attribute__((noreturn));
#endif

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
/* die on a fatal error; use only during initialization */
static void fatal_error( const char *err, ... )
{
    va_list args;

    va_start( args, err );
    fprintf( stderr, "wine: " );
    vfprintf( stderr, err, args );
    va_end( args );
    exit(1);
}

/* die on a fatal error; use only during initialization */
static void fatal_perror( const char *err, ... )
{
    va_list args;

    va_start( args, err );
    fprintf( stderr, "wine: " );
    vfprintf( stderr, err, args );
    perror( " " );
    va_end( args );
    exit(1);
}

174

Alexandre Julliard's avatar
Alexandre Julliard committed
175
/***********************************************************************
176
 *           server_protocol_error
Alexandre Julliard's avatar
Alexandre Julliard committed
177
 */
178
static DECLSPEC_NORETURN void server_protocol_error( const char *err, ... )
Alexandre Julliard's avatar
Alexandre Julliard committed
179 180 181 182
{
    va_list args;

    va_start( args, err );
183
    fprintf( stderr, "wine client error:%x: ", GetCurrentThreadId() );
Alexandre Julliard's avatar
Alexandre Julliard committed
184 185
    vfprintf( stderr, err, args );
    va_end( args );
186
    abort_thread(1);
Alexandre Julliard's avatar
Alexandre Julliard committed
187 188 189
}


Alexandre Julliard's avatar
Alexandre Julliard committed
190
/***********************************************************************
191
 *           server_protocol_perror
192
 */
193
static DECLSPEC_NORETURN void server_protocol_perror( const char *err )
194
{
195
    fprintf( stderr, "wine client error:%x: ", GetCurrentThreadId() );
196
    perror( err );
197
    abort_thread(1);
198 199 200 201 202
}


/***********************************************************************
 *           send_request
Alexandre Julliard's avatar
Alexandre Julliard committed
203 204 205
 *
 * Send a request to the server.
 */
206
static unsigned int send_request( const struct __server_request_info *req )
207
{
208 209
    unsigned int i;
    int ret;
210 211 212

    if (!req->u.req.request_header.request_size)
    {
213
        if ((ret = write( ntdll_get_thread_data()->request_fd, &req->u.req,
214
                          sizeof(req->u.req) )) == sizeof(req->u.req)) return STATUS_SUCCESS;
215 216 217 218 219 220 221 222 223 224 225 226 227

    }
    else
    {
        struct iovec vec[__SERVER_MAX_DATA+1];

        vec[0].iov_base = (void *)&req->u.req;
        vec[0].iov_len = sizeof(req->u.req);
        for (i = 0; i < req->data_count; i++)
        {
            vec[i+1].iov_base = (void *)req->data[i].ptr;
            vec[i+1].iov_len = req->data[i].size;
        }
228
        if ((ret = writev( ntdll_get_thread_data()->request_fd, vec, i+1 )) ==
229
            req->u.req.request_header.request_size + sizeof(req->u.req)) return STATUS_SUCCESS;
230
    }
231 232

    if (ret >= 0) server_protocol_error( "partial write %d\n", ret );
233
    if (errno == EPIPE) abort_thread(0);
234
    if (errno == EFAULT) return STATUS_ACCESS_VIOLATION;
235
    server_protocol_perror( "write" );
236 237
}

238

Alexandre Julliard's avatar
Alexandre Julliard committed
239
/***********************************************************************
240
 *           read_reply_data
Alexandre Julliard's avatar
Alexandre Julliard committed
241
 *
242
 * Read data from the reply buffer; helper for wait_reply.
Alexandre Julliard's avatar
Alexandre Julliard committed
243
 */
244
static void read_reply_data( void *buffer, size_t size )
Alexandre Julliard's avatar
Alexandre Julliard committed
245
{
246
    int ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
247

248
    for (;;)
Alexandre Julliard's avatar
Alexandre Julliard committed
249
    {
250
        if ((ret = read( ntdll_get_thread_data()->reply_fd, buffer, size )) > 0)
251 252 253 254 255
        {
            if (!(size -= ret)) return;
            buffer = (char *)buffer + ret;
            continue;
        }
256
        if (!ret) break;
257 258
        if (errno == EINTR) continue;
        if (errno == EPIPE) break;
259
        server_protocol_perror("read");
Alexandre Julliard's avatar
Alexandre Julliard committed
260
    }
261
    /* the server closed the connection; time to die... */
262
    abort_thread(0);
Alexandre Julliard's avatar
Alexandre Julliard committed
263 264 265
}


266 267 268 269 270
/***********************************************************************
 *           wait_reply
 *
 * Wait for a reply from the server.
 */
271
static inline unsigned int wait_reply( struct __server_request_info *req )
272 273 274 275
{
    read_reply_data( &req->u.reply, sizeof(req->u.reply) );
    if (req->u.reply.reply_header.reply_size)
        read_reply_data( req->reply_data, req->u.reply.reply_header.reply_size );
276
    return req->u.reply.reply_header.error;
277 278 279
}


280 281 282 283 284 285 286 287 288 289 290 291 292
/***********************************************************************
 *           server_call_unlocked
 */
unsigned int server_call_unlocked( void *req_ptr )
{
    struct __server_request_info * const req = req_ptr;
    unsigned int ret;

    if ((ret = send_request( req ))) return ret;
    return wait_reply( req );
}


Alexandre Julliard's avatar
Alexandre Julliard committed
293
/***********************************************************************
294
 *           wine_server_call (NTDLL.@)
295 296
 *
 * Perform a server call.
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
 *
 * PARAMS
 *     req_ptr [I/O] Function dependent data
 *
 * RETURNS
 *     Depends on server function being called, but usually an NTSTATUS code.
 *
 * NOTES
 *     Use the SERVER_START_REQ and SERVER_END_REQ to help you fill out the
 *     server request structure for the particular call. E.g:
 *|     SERVER_START_REQ( event_op )
 *|     {
 *|         req->handle = handle;
 *|         req->op     = SET_EVENT;
 *|         ret = wine_server_call( req );
 *|     }
 *|     SERVER_END_REQ;
314
 */
315
unsigned int wine_server_call( void *req_ptr )
316
{
317
    sigset_t old_set;
318
    unsigned int ret;
319

320
    pthread_sigmask( SIG_BLOCK, &server_block_set, &old_set );
321
    ret = server_call_unlocked( req_ptr );
322
    pthread_sigmask( SIG_SETMASK, &old_set, NULL );
323
    return ret;
324 325 326
}


327 328 329 330 331
/***********************************************************************
 *           server_enter_uninterrupted_section
 */
void server_enter_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset )
{
332
    pthread_sigmask( SIG_BLOCK, &server_block_set, sigset );
333 334 335 336 337 338 339 340 341 342
    RtlEnterCriticalSection( cs );
}


/***********************************************************************
 *           server_leave_uninterrupted_section
 */
void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset )
{
    RtlLeaveCriticalSection( cs );
343
    pthread_sigmask( SIG_SETMASK, sigset, NULL );
344 345 346
}


347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
/***********************************************************************
 *              wait_select_reply
 *
 * Wait for a reply on the waiting pipe of the current thread.
 */
static int wait_select_reply( void *cookie )
{
    int signaled;
    struct wake_up_reply reply;
    for (;;)
    {
        int ret;
        ret = read( ntdll_get_thread_data()->wait_fd[0], &reply, sizeof(reply) );
        if (ret == sizeof(reply))
        {
            if (!reply.cookie) abort_thread( reply.signaled );  /* thread got killed */
            if (wine_server_get_ptr(reply.cookie) == cookie) return reply.signaled;
            /* we stole another reply, wait for the real one */
            signaled = wait_select_reply( cookie );
            /* and now put the wrong one back in the pipe */
            for (;;)
            {
                ret = write( ntdll_get_thread_data()->wait_fd[1], &reply, sizeof(reply) );
                if (ret == sizeof(reply)) break;
                if (ret >= 0) server_protocol_error( "partial wakeup write %d\n", ret );
                if (errno == EINTR) continue;
                server_protocol_perror("wakeup write");
            }
            return signaled;
        }
        if (ret >= 0) server_protocol_error( "partial wakeup read %d\n", ret );
        if (errno == EINTR) continue;
        server_protocol_perror("wakeup read");
    }
}


/***********************************************************************
 *              invoke_apc
 *
 * Invoke a single APC. Return TRUE if a user APC has been run.
 */
static BOOL invoke_apc( const apc_call_t *call, apc_result_t *result )
{
    BOOL user_apc = FALSE;
    SIZE_T size;
    void *addr;

    memset( result, 0, sizeof(*result) );

    switch (call->type)
    {
    case APC_NONE:
        break;
    case APC_USER:
    {
        void (WINAPI *func)(ULONG_PTR,ULONG_PTR,ULONG_PTR) = wine_server_get_ptr( call->user.func );
        func( call->user.args[0], call->user.args[1], call->user.args[2] );
        user_apc = TRUE;
        break;
    }
    case APC_TIMER:
    {
        void (WINAPI *func)(void*, unsigned int, unsigned int) = wine_server_get_ptr( call->timer.func );
        func( wine_server_get_ptr( call->timer.arg ),
              (DWORD)call->timer.time, (DWORD)(call->timer.time >> 32) );
        user_apc = TRUE;
        break;
    }
    case APC_ASYNC_IO:
    {
        IO_STATUS_BLOCK *iosb = wine_server_get_ptr( call->async_io.sb );
419
        NTSTATUS (**user)(void *, IO_STATUS_BLOCK *, NTSTATUS) = wine_server_get_ptr( call->async_io.user );
420
        result->type = call->type;
421
        result->async_io.status = (*user)( user, iosb, call->async_io.status );
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621
        if (result->async_io.status != STATUS_PENDING)
            result->async_io.total = iosb->Information;
        break;
    }
    case APC_VIRTUAL_ALLOC:
        result->type = call->type;
        addr = wine_server_get_ptr( call->virtual_alloc.addr );
        size = call->virtual_alloc.size;
        if ((ULONG_PTR)addr == call->virtual_alloc.addr && size == call->virtual_alloc.size)
        {
            result->virtual_alloc.status = NtAllocateVirtualMemory( NtCurrentProcess(), &addr,
                                                                    call->virtual_alloc.zero_bits, &size,
                                                                    call->virtual_alloc.op_type,
                                                                    call->virtual_alloc.prot );
            result->virtual_alloc.addr = wine_server_client_ptr( addr );
            result->virtual_alloc.size = size;
        }
        else result->virtual_alloc.status = STATUS_WORKING_SET_LIMIT_RANGE;
        break;
    case APC_VIRTUAL_FREE:
        result->type = call->type;
        addr = wine_server_get_ptr( call->virtual_free.addr );
        size = call->virtual_free.size;
        if ((ULONG_PTR)addr == call->virtual_free.addr && size == call->virtual_free.size)
        {
            result->virtual_free.status = NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size,
                                                               call->virtual_free.op_type );
            result->virtual_free.addr = wine_server_client_ptr( addr );
            result->virtual_free.size = size;
        }
        else result->virtual_free.status = STATUS_INVALID_PARAMETER;
        break;
    case APC_VIRTUAL_QUERY:
    {
        MEMORY_BASIC_INFORMATION info;
        result->type = call->type;
        addr = wine_server_get_ptr( call->virtual_query.addr );
        if ((ULONG_PTR)addr == call->virtual_query.addr)
            result->virtual_query.status = NtQueryVirtualMemory( NtCurrentProcess(),
                                                                 addr, MemoryBasicInformation, &info,
                                                                 sizeof(info), NULL );
        else
            result->virtual_query.status = STATUS_WORKING_SET_LIMIT_RANGE;

        if (result->virtual_query.status == STATUS_SUCCESS)
        {
            result->virtual_query.base       = wine_server_client_ptr( info.BaseAddress );
            result->virtual_query.alloc_base = wine_server_client_ptr( info.AllocationBase );
            result->virtual_query.size       = info.RegionSize;
            result->virtual_query.prot       = info.Protect;
            result->virtual_query.alloc_prot = info.AllocationProtect;
            result->virtual_query.state      = info.State >> 12;
            result->virtual_query.alloc_type = info.Type >> 16;
        }
        break;
    }
    case APC_VIRTUAL_PROTECT:
        result->type = call->type;
        addr = wine_server_get_ptr( call->virtual_protect.addr );
        size = call->virtual_protect.size;
        if ((ULONG_PTR)addr == call->virtual_protect.addr && size == call->virtual_protect.size)
        {
            result->virtual_protect.status = NtProtectVirtualMemory( NtCurrentProcess(), &addr, &size,
                                                                     call->virtual_protect.prot,
                                                                     &result->virtual_protect.prot );
            result->virtual_protect.addr = wine_server_client_ptr( addr );
            result->virtual_protect.size = size;
        }
        else result->virtual_protect.status = STATUS_INVALID_PARAMETER;
        break;
    case APC_VIRTUAL_FLUSH:
        result->type = call->type;
        addr = wine_server_get_ptr( call->virtual_flush.addr );
        size = call->virtual_flush.size;
        if ((ULONG_PTR)addr == call->virtual_flush.addr && size == call->virtual_flush.size)
        {
            result->virtual_flush.status = NtFlushVirtualMemory( NtCurrentProcess(),
                                                                 (const void **)&addr, &size, 0 );
            result->virtual_flush.addr = wine_server_client_ptr( addr );
            result->virtual_flush.size = size;
        }
        else result->virtual_flush.status = STATUS_INVALID_PARAMETER;
        break;
    case APC_VIRTUAL_LOCK:
        result->type = call->type;
        addr = wine_server_get_ptr( call->virtual_lock.addr );
        size = call->virtual_lock.size;
        if ((ULONG_PTR)addr == call->virtual_lock.addr && size == call->virtual_lock.size)
        {
            result->virtual_lock.status = NtLockVirtualMemory( NtCurrentProcess(), &addr, &size, 0 );
            result->virtual_lock.addr = wine_server_client_ptr( addr );
            result->virtual_lock.size = size;
        }
        else result->virtual_lock.status = STATUS_INVALID_PARAMETER;
        break;
    case APC_VIRTUAL_UNLOCK:
        result->type = call->type;
        addr = wine_server_get_ptr( call->virtual_unlock.addr );
        size = call->virtual_unlock.size;
        if ((ULONG_PTR)addr == call->virtual_unlock.addr && size == call->virtual_unlock.size)
        {
            result->virtual_unlock.status = NtUnlockVirtualMemory( NtCurrentProcess(), &addr, &size, 0 );
            result->virtual_unlock.addr = wine_server_client_ptr( addr );
            result->virtual_unlock.size = size;
        }
        else result->virtual_unlock.status = STATUS_INVALID_PARAMETER;
        break;
    case APC_MAP_VIEW:
        result->type = call->type;
        addr = wine_server_get_ptr( call->map_view.addr );
        size = call->map_view.size;
        if ((ULONG_PTR)addr == call->map_view.addr && size == call->map_view.size)
        {
            LARGE_INTEGER offset;
            offset.QuadPart = call->map_view.offset;
            result->map_view.status = NtMapViewOfSection( wine_server_ptr_handle(call->map_view.handle),
                                                          NtCurrentProcess(), &addr,
                                                          call->map_view.zero_bits, 0,
                                                          &offset, &size, ViewShare,
                                                          call->map_view.alloc_type, call->map_view.prot );
            result->map_view.addr = wine_server_client_ptr( addr );
            result->map_view.size = size;
        }
        else result->map_view.status = STATUS_INVALID_PARAMETER;
        NtClose( wine_server_ptr_handle(call->map_view.handle) );
        break;
    case APC_UNMAP_VIEW:
        result->type = call->type;
        addr = wine_server_get_ptr( call->unmap_view.addr );
        if ((ULONG_PTR)addr == call->unmap_view.addr)
            result->unmap_view.status = NtUnmapViewOfSection( NtCurrentProcess(), addr );
        else
            result->unmap_view.status = STATUS_INVALID_PARAMETER;
        break;
    case APC_CREATE_THREAD:
    {
        CLIENT_ID id;
        HANDLE handle;
        SIZE_T reserve = call->create_thread.reserve;
        SIZE_T commit = call->create_thread.commit;
        void *func = wine_server_get_ptr( call->create_thread.func );
        void *arg  = wine_server_get_ptr( call->create_thread.arg );

        result->type = call->type;
        if (reserve == call->create_thread.reserve && commit == call->create_thread.commit &&
            (ULONG_PTR)func == call->create_thread.func && (ULONG_PTR)arg == call->create_thread.arg)
        {
            result->create_thread.status = RtlCreateUserThread( NtCurrentProcess(), NULL,
                                                                call->create_thread.suspend, NULL,
                                                                reserve, commit, func, arg, &handle, &id );
            result->create_thread.handle = wine_server_obj_handle( handle );
            result->create_thread.tid = HandleToULong(id.UniqueThread);
        }
        else result->create_thread.status = STATUS_INVALID_PARAMETER;
        break;
    }
    default:
        server_protocol_error( "get_apc_request: bad type %d\n", call->type );
        break;
    }
    return user_apc;
}


/***********************************************************************
 *              server_select
 */
unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT flags,
                            const LARGE_INTEGER *timeout )
{
    unsigned int ret;
    int cookie;
    BOOL user_apc = FALSE;
    obj_handle_t apc_handle = 0;
    apc_call_t call;
    apc_result_t result;
    timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;

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

    for (;;)
    {
        SERVER_START_REQ( select )
        {
            req->flags    = flags;
            req->cookie   = wine_server_client_ptr( &cookie );
            req->prev_apc = apc_handle;
            req->timeout  = abs_timeout;
            wine_server_add_data( req, &result, sizeof(result) );
            wine_server_add_data( req, select_op, size );
            ret = wine_server_call( req );
            abs_timeout = reply->timeout;
            apc_handle  = reply->apc_handle;
            call        = reply->call;
        }
        SERVER_END_REQ;
        if (ret == STATUS_PENDING) ret = wait_select_reply( &cookie );
        if (ret != STATUS_USER_APC) break;
        if (invoke_apc( &call, &result ))
        {
622
            /* if we ran a user apc we have to check once more if additional apcs are queued,
623 624 625
             * but we don't want to wait */
            abs_timeout = 0;
            user_apc = TRUE;
626
            size = 0;
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
        }

        /* don't signal multiple times */
        if (size >= sizeof(select_op->signal_and_wait) && select_op->op == SELECT_SIGNAL_AND_WAIT)
            size = offsetof( select_op_t, signal_and_wait.signal );
    }

    if (ret == STATUS_TIMEOUT && user_apc) ret = STATUS_USER_APC;

    /* A test on Windows 2000 shows that Windows always yields during
       a wait, but a wait that is hit by an event gets a priority
       boost as well.  This seems to model that behavior the closest.  */
    if (ret == STATUS_TIMEOUT) NtYieldExecution();

    return ret;
}


/***********************************************************************
 *           server_queue_process_apc
 */
unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call, apc_result_t *result )
{
    for (;;)
    {
        unsigned int ret;
        HANDLE handle = 0;
        BOOL self = FALSE;

        SERVER_START_REQ( queue_apc )
        {
            req->handle = wine_server_obj_handle( process );
            req->call = *call;
            if (!(ret = wine_server_call( req )))
            {
                handle = wine_server_ptr_handle( reply->handle );
                self = reply->self;
            }
        }
        SERVER_END_REQ;
        if (ret != STATUS_SUCCESS) return ret;

        if (self)
        {
            invoke_apc( call, result );
        }
        else
        {
            NtWaitForSingleObject( handle, FALSE, NULL );

            SERVER_START_REQ( get_apc_result )
            {
                req->handle = wine_server_obj_handle( handle );
                if (!(ret = wine_server_call( req ))) *result = reply->result;
            }
            SERVER_END_REQ;

            if (!ret && result->type == APC_NONE) continue;  /* APC didn't run, try again */
        }
        return ret;
    }
}


691
/***********************************************************************
692
 *           wine_server_send_fd   (NTDLL.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
693
 *
694
 * Send a file descriptor to the server.
695 696 697 698 699 700
 *
 * PARAMS
 *     fd [I] file descriptor to send
 *
 * RETURNS
 *     nothing
Alexandre Julliard's avatar
Alexandre Julliard committed
701
 */
702
void CDECL wine_server_send_fd( int fd )
703
{
704 705 706 707 708
    struct send_fd data;
    struct msghdr msghdr;
    struct iovec vec;
    int ret;

709
#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
710 711
    msghdr.msg_accrights    = (void *)&fd;
    msghdr.msg_accrightslen = sizeof(fd);
712
#else  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
713 714 715 716
    char cmsg_buffer[256];
    struct cmsghdr *cmsg;
    msghdr.msg_control    = cmsg_buffer;
    msghdr.msg_controllen = sizeof(cmsg_buffer);
717
    msghdr.msg_flags      = 0;
718 719 720 721 722 723
    cmsg = CMSG_FIRSTHDR( &msghdr );
    cmsg->cmsg_len   = CMSG_LEN( sizeof(fd) );
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type  = SCM_RIGHTS;
    *(int *)CMSG_DATA(cmsg) = fd;
    msghdr.msg_controllen = cmsg->cmsg_len;
724
#endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
725

726 727 728 729 730 731 732 733
    msghdr.msg_name    = NULL;
    msghdr.msg_namelen = 0;
    msghdr.msg_iov     = &vec;
    msghdr.msg_iovlen  = 1;

    vec.iov_base = (void *)&data;
    vec.iov_len  = sizeof(data);

734
    data.tid = GetCurrentThreadId();
735 736 737 738 739 740 741
    data.fd  = fd;

    for (;;)
    {
        if ((ret = sendmsg( fd_socket, &msghdr, 0 )) == sizeof(data)) return;
        if (ret >= 0) server_protocol_error( "partial write %d\n", ret );
        if (errno == EINTR) continue;
742
        if (errno == EPIPE) abort_thread(0);
743 744
        server_protocol_perror( "sendmsg" );
    }
745 746 747 748
}


/***********************************************************************
749
 *           receive_fd
750 751 752
 *
 * Receive a file descriptor passed from the server.
 */
753
static int receive_fd( obj_handle_t *handle )
Alexandre Julliard's avatar
Alexandre Julliard committed
754
{
755
    struct iovec vec;
Patrik Stridvall's avatar
Patrik Stridvall committed
756
    struct msghdr msghdr;
757
    int ret, fd = -1;
Patrik Stridvall's avatar
Patrik Stridvall committed
758

759
#ifdef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
760 761
    msghdr.msg_accrights    = (void *)&fd;
    msghdr.msg_accrightslen = sizeof(fd);
762
#else  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
763 764 765
    char cmsg_buffer[256];
    msghdr.msg_control    = cmsg_buffer;
    msghdr.msg_controllen = sizeof(cmsg_buffer);
Patrik Stridvall's avatar
Patrik Stridvall committed
766
    msghdr.msg_flags      = 0;
767
#endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
Patrik Stridvall's avatar
Patrik Stridvall committed
768 769 770

    msghdr.msg_name    = NULL;
    msghdr.msg_namelen = 0;
771 772
    msghdr.msg_iov     = &vec;
    msghdr.msg_iovlen  = 1;
773 774
    vec.iov_base = (void *)handle;
    vec.iov_len  = sizeof(*handle);
Patrik Stridvall's avatar
Patrik Stridvall committed
775

776
    for (;;)
Alexandre Julliard's avatar
Alexandre Julliard committed
777
    {
778
        if ((ret = recvmsg( fd_socket, &msghdr, MSG_CMSG_CLOEXEC )) > 0)
779
        {
780
#ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS
781 782 783 784 785
            struct cmsghdr *cmsg;
            for (cmsg = CMSG_FIRSTHDR( &msghdr ); cmsg; cmsg = CMSG_NXTHDR( &msghdr, cmsg ))
            {
                if (cmsg->cmsg_level != SOL_SOCKET) continue;
                if (cmsg->cmsg_type == SCM_RIGHTS) fd = *(int *)CMSG_DATA(cmsg);
786 787 788 789 790 791 792
#ifdef SCM_CREDENTIALS
                else if (cmsg->cmsg_type == SCM_CREDENTIALS)
                {
                    struct ucred *ucred = (struct ucred *)CMSG_DATA(cmsg);
                    server_pid = ucred->pid;
                }
#endif
793 794
            }
#endif  /* HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
795
            if (fd != -1) fcntl( fd, F_SETFD, FD_CLOEXEC ); /* in case MSG_CMSG_CLOEXEC is not supported */
796
            return fd;
797
        }
798
        if (!ret) break;
799 800
        if (errno == EINTR) continue;
        if (errno == EPIPE) break;
801
        server_protocol_perror("recvmsg");
Alexandre Julliard's avatar
Alexandre Julliard committed
802
    }
803
    /* the server closed the connection; time to die... */
804
    abort_thread(0);
805
}
Alexandre Julliard's avatar
Alexandre Julliard committed
806 807


808 809
/***********************************************************************/
/* fd cache support */
810

811
union fd_cache_entry
812
{
813 814 815 816 817 818 819 820
    LONG64 data;
    struct
    {
        int fd;
        enum server_fd_type type : 5;
        unsigned int        access : 3;
        unsigned int        options : 24;
    } s;
821
};
822 823

C_ASSERT( sizeof(union fd_cache_entry) == sizeof(LONG64) );
824

825
#define FD_CACHE_BLOCK_SIZE  (65536 / sizeof(union fd_cache_entry))
826 827
#define FD_CACHE_ENTRIES     128

828 829
static union fd_cache_entry *fd_cache[FD_CACHE_ENTRIES];
static union fd_cache_entry fd_cache_initial_block[FD_CACHE_BLOCK_SIZE];
830

831
static inline unsigned int handle_to_index( HANDLE handle, unsigned int *entry )
832
{
833
    unsigned int idx = (wine_server_obj_handle(handle) >> 2) - 1;
834 835 836 837
    *entry = idx / FD_CACHE_BLOCK_SIZE;
    return idx % FD_CACHE_BLOCK_SIZE;
}

838 839 840 841 842 843

/***********************************************************************
 *           add_fd_to_cache
 *
 * Caller must hold fd_cache_section.
 */
844
static BOOL add_fd_to_cache( HANDLE handle, int fd, enum server_fd_type type,
845
                            unsigned int access, unsigned int options )
846
{
847
    unsigned int entry, idx = handle_to_index( handle, &entry );
848
    union fd_cache_entry cache;
849

850
    if (entry >= FD_CACHE_ENTRIES)
851
    {
852
        FIXME( "too many allocated handles, not caching %p\n", handle );
853
        return FALSE;
854
    }
855

856 857 858
    if (!fd_cache[entry])  /* do we need to allocate a new block of entries? */
    {
        if (!entry) fd_cache[0] = fd_cache_initial_block;
859 860
        else
        {
861
            void *ptr = wine_anon_mmap( NULL, FD_CACHE_BLOCK_SIZE * sizeof(union fd_cache_entry),
862
                                        PROT_READ | PROT_WRITE, 0 );
863
            if (ptr == MAP_FAILED) return FALSE;
864
            fd_cache[entry] = ptr;
865 866
        }
    }
867

868
    /* store fd+1 so that 0 can be used as the unset value */
869 870 871 872 873 874
    cache.s.fd = fd + 1;
    cache.s.type = type;
    cache.s.access = access;
    cache.s.options = options;
    cache.data = interlocked_xchg64( &fd_cache[entry][idx].data, cache.data );
    assert( !cache.s.fd );
875
    return TRUE;
876 877 878 879 880 881
}


/***********************************************************************
 *           get_cached_fd
 */
882 883
static inline NTSTATUS get_cached_fd( HANDLE handle, int *fd, enum server_fd_type *type,
                                      unsigned int *access, unsigned int *options )
884
{
885
    unsigned int entry, idx = handle_to_index( handle, &entry );
886
    union fd_cache_entry cache;
887

888 889 890 891 892 893 894 895 896 897 898 899 900
    if (entry >= FD_CACHE_ENTRIES || !fd_cache[entry]) return STATUS_INVALID_HANDLE;

    cache.data = interlocked_cmpxchg64( &fd_cache[entry][idx].data, 0, 0 );
    if (!cache.data) return STATUS_INVALID_HANDLE;

    /* if fd type is invalid, fd stores an error value */
    if (cache.s.type == FD_TYPE_INVALID) return cache.s.fd - 1;

    *fd = cache.s.fd - 1;
    if (type) *type = cache.s.type;
    if (access) *access = cache.s.access;
    if (options) *options = cache.s.options;
    return STATUS_SUCCESS;
901 902 903 904 905 906
}


/***********************************************************************
 *           server_remove_fd_from_cache
 */
907
int server_remove_fd_from_cache( HANDLE handle )
908
{
909
    unsigned int entry, idx = handle_to_index( handle, &entry );
910 911
    int fd = -1;

912
    if (entry < FD_CACHE_ENTRIES && fd_cache[entry])
913 914 915
    {
        union fd_cache_entry cache;
        cache.data = interlocked_xchg64( &fd_cache[entry][idx].data, 0 );
916
        if (cache.s.type != FD_TYPE_INVALID) fd = cache.s.fd - 1;
917
    }
918 919 920 921 922

    return fd;
}


923 924 925 926 927
/***********************************************************************
 *           server_get_unix_fd
 *
 * The returned unix_fd should be closed iff needs_close is non-zero.
 */
928
int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
929
                        int *needs_close, enum server_fd_type *type, unsigned int *options )
930
{
931
    sigset_t sigset;
932
    obj_handle_t fd_handle;
933
    int ret, fd = -1;
934
    unsigned int access = 0;
935 936 937

    *unix_fd = -1;
    *needs_close = 0;
938
    wanted_access &= FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA;
939

940 941
    ret = get_cached_fd( handle, &fd, type, &access, options );
    if (ret != STATUS_INVALID_HANDLE) goto done;
942

943
    server_enter_uninterrupted_section( &fd_cache_section, &sigset );
944 945
    ret = get_cached_fd( handle, &fd, type, &access, options );
    if (ret == STATUS_INVALID_HANDLE)
946
    {
947
        SERVER_START_REQ( get_handle_fd )
948
        {
949 950
            req->handle = wine_server_obj_handle( handle );
            if (!(ret = wine_server_call( req )))
951
            {
952 953 954 955 956 957 958 959 960 961 962
                if (type) *type = reply->type;
                if (options) *options = reply->options;
                access = reply->access;
                if ((fd = receive_fd( &fd_handle )) != -1)
                {
                    assert( wine_server_ptr_handle(fd_handle) == handle );
                    *needs_close = (!reply->cacheable ||
                                    !add_fd_to_cache( handle, fd, reply->type,
                                                      reply->access, reply->options ));
                }
                else ret = STATUS_TOO_MANY_OPENED_FILES;
963
            }
964 965 966 967
            else if (reply->cacheable)
            {
                add_fd_to_cache( handle, ret, FD_TYPE_INVALID, 0, 0 );
            }
968
        }
969
        SERVER_END_REQ;
970
    }
971
    server_leave_uninterrupted_section( &fd_cache_section, &sigset );
972 973

done:
974 975 976 977 978
    if (!ret && ((access & wanted_access) != wanted_access))
    {
        ret = STATUS_ACCESS_DENIED;
        if (*needs_close) close( fd );
    }
979 980 981 982 983
    if (!ret) *unix_fd = fd;
    return ret;
}


984 985 986
/***********************************************************************
 *           wine_server_fd_to_handle   (NTDLL.@)
 *
987 988 989 990 991
 * Allocate a file handle for a Unix file descriptor.
 *
 * PARAMS
 *     fd      [I] Unix file descriptor.
 *     access  [I] Win32 access flags.
992
 *     attributes [I] Object attributes.
993 994 995 996
 *     handle  [O] Address where Wine file handle will be stored.
 *
 * RETURNS
 *     NTSTATUS code
997
 */
998
int CDECL wine_server_fd_to_handle( int fd, unsigned int access, unsigned int attributes, HANDLE *handle )
999 1000 1001 1002 1003 1004 1005 1006
{
    int ret;

    *handle = 0;
    wine_server_send_fd( fd );

    SERVER_START_REQ( alloc_file_handle )
    {
1007
        req->access     = access;
1008
        req->attributes = attributes;
1009
        req->fd         = fd;
1010
        if (!(ret = wine_server_call( req ))) *handle = wine_server_ptr_handle( reply->handle );
1011 1012 1013 1014 1015 1016
    }
    SERVER_END_REQ;
    return ret;
}


1017 1018 1019
/***********************************************************************
 *           wine_server_handle_to_fd   (NTDLL.@)
 *
1020 1021 1022 1023 1024 1025
 * Retrieve the file descriptor corresponding to a file handle.
 *
 * PARAMS
 *     handle  [I] Wine file handle.
 *     access  [I] Win32 file access rights requested.
 *     unix_fd [O] Address where Unix file descriptor will be stored.
1026
 *     options [O] Address where the file open options will be stored. Optional.
1027 1028 1029
 *
 * RETURNS
 *     NTSTATUS code
1030
 */
1031
int CDECL wine_server_handle_to_fd( HANDLE handle, unsigned int access, int *unix_fd,
1032
                              unsigned int *options )
1033
{
1034
    int needs_close, ret = server_get_unix_fd( handle, access, unix_fd, &needs_close, NULL, options );
1035

1036
    if (!ret && !needs_close)
1037
    {
1038
        if ((*unix_fd = dup(*unix_fd)) == -1) ret = FILE_GetNtStatus();
1039
    }
1040
    return ret;
1041 1042 1043
}


1044 1045 1046
/***********************************************************************
 *           wine_server_release_fd   (NTDLL.@)
 *
1047 1048 1049 1050 1051 1052 1053 1054
 * Release the Unix file descriptor returned by wine_server_handle_to_fd.
 *
 * PARAMS
 *     handle  [I] Wine file handle.
 *     unix_fd [I] Unix file descriptor to release.
 *
 * RETURNS
 *     nothing
1055
 */
1056
void CDECL wine_server_release_fd( HANDLE handle, int unix_fd )
1057 1058 1059 1060 1061
{
    close( unix_fd );
}


1062 1063 1064 1065 1066 1067 1068 1069 1070
/***********************************************************************
 *           server_pipe
 *
 * Create a pipe for communicating with the server.
 */
int server_pipe( int fd[2] )
{
    int ret;
#ifdef HAVE_PIPE2
1071
    static BOOL have_pipe2 = TRUE;
1072 1073 1074 1075

    if (have_pipe2)
    {
        if (!(ret = pipe2( fd, O_CLOEXEC ))) return ret;
1076
        if (errno == ENOSYS || errno == EINVAL) have_pipe2 = FALSE;  /* don't try again */
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
    }
#endif
    if (!(ret = pipe( fd )))
    {
        fcntl( fd[0], F_SETFD, FD_CLOEXEC );
        fcntl( fd[1], F_SETFD, FD_CLOEXEC );
    }
    return ret;
}


1088 1089 1090 1091 1092
/***********************************************************************
 *           start_server
 *
 * Start a new wine server.
 */
1093
static void start_server(void)
1094
{
1095
    static BOOL started;  /* we only try once */
1096
    char *argv[3];
1097 1098
    static char wineserver[] = "server/wineserver";
    static char debug[] = "-d";
1099

1100 1101
    if (!started)
    {
1102
        int status;
1103 1104 1105 1106
        int pid = fork();
        if (pid == -1) fatal_perror( "fork" );
        if (!pid)
        {
1107 1108
            argv[0] = wineserver;
            argv[1] = TRACE_ON(server) ? debug : NULL;
1109
            argv[2] = NULL;
1110
            wine_exec_wine_binary( argv[0], argv, getenv("WINESERVER") );
1111 1112
            fatal_error( "could not exec wineserver\n" );
        }
1113 1114
        waitpid( pid, &status, 0 );
        status = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
1115
        if (status == 2) return;  /* server lock held by someone else, will retry later */
1116
        if (status) exit(status);  /* server failed */
1117
        started = TRUE;
1118 1119 1120 1121
    }
}


1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150
/***********************************************************************
 *           setup_config_dir
 *
 * Setup the wine configuration dir.
 */
static void setup_config_dir(void)
{
    const char *p, *config_dir = wine_get_config_dir();

    if (chdir( config_dir ) == -1)
    {
        if (errno != ENOENT) fatal_perror( "chdir to %s\n", config_dir );

        if ((p = strrchr( config_dir, '/' )) && p != config_dir)
        {
            struct stat st;
            char *tmp_dir;

            if (!(tmp_dir = malloc( p + 1 - config_dir ))) fatal_error( "out of memory\n" );
            memcpy( tmp_dir, config_dir, p - config_dir );
            tmp_dir[p - config_dir] = 0;
            if (!stat( tmp_dir, &st ) && st.st_uid != getuid())
                fatal_error( "'%s' is not owned by you, refusing to create a configuration directory there\n",
                             tmp_dir );
            free( tmp_dir );
        }

        mkdir( config_dir, 0777 );
        if (chdir( config_dir ) == -1) fatal_perror( "chdir to %s\n", config_dir );
1151

1152
        MESSAGE( "wine: created the configuration directory '%s'\n", config_dir );
1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168
    }

    if (mkdir( "dosdevices", 0777 ) == -1)
    {
        if (errno == EEXIST) return;
        fatal_perror( "cannot create %s/dosdevices\n", config_dir );
    }

    /* create the drive symlinks */

    mkdir( "drive_c", 0777 );
    symlink( "../drive_c", "dosdevices/c:" );
    symlink( "/", "dosdevices/z:" );
}


1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
/***********************************************************************
 *           server_connect_error
 *
 * Try to display a meaningful explanation of why we couldn't connect
 * to the server.
 */
static void server_connect_error( const char *serverdir )
{
    int fd;
    struct flock fl;

    if ((fd = open( LOCKNAME, O_WRONLY )) == -1)
        fatal_error( "for some mysterious reason, the wine server never started.\n" );

    fl.l_type   = F_WRLCK;
    fl.l_whence = SEEK_SET;
    fl.l_start  = 0;
    fl.l_len    = 1;
    if (fcntl( fd, F_GETLK, &fl ) != -1)
    {
        if (fl.l_type == F_WRLCK)  /* the file is locked */
            fatal_error( "a wine server seems to be running, but I cannot connect to it.\n"
                         "   You probably need to kill that process (it might be pid %d).\n",
                         (int)fl.l_pid );
        fatal_error( "for some mysterious reason, the wine server failed to run.\n" );
1194
    }
1195 1196 1197 1198
    fatal_error( "the file system of '%s' doesn't support locks,\n"
          "   and there is a 'socket' file in that directory that prevents wine from starting.\n"
          "   You should make sure no wine server is running, remove that file and try again.\n",
                 serverdir );
1199 1200
}

1201

1202 1203 1204 1205 1206 1207
/***********************************************************************
 *           server_connect
 *
 * Attempt to connect to an existing server socket.
 * We need to be in the server directory already.
 */
1208
static int server_connect(void)
1209
{
1210
    const char *serverdir;
1211 1212
    struct sockaddr_un addr;
    struct stat st;
1213 1214 1215 1216
    int s, slen, retry, fd_cwd;

    /* retrieve the current directory */
    fd_cwd = open( ".", O_RDONLY );
1217
    if (fd_cwd != -1) fcntl( fd_cwd, F_SETFD, FD_CLOEXEC );
1218

1219 1220 1221
    setup_config_dir();
    serverdir = wine_get_server_dir();

1222
    /* chdir to the server directory */
1223 1224 1225
    if (chdir( serverdir ) == -1)
    {
        if (errno != ENOENT) fatal_perror( "chdir to %s", serverdir );
1226
        start_server();
1227
        if (chdir( serverdir ) == -1) fatal_perror( "chdir to %s", serverdir );
1228
    }
1229 1230

    /* make sure we are at the right place */
1231 1232 1233 1234
    if (stat( ".", &st ) == -1) fatal_perror( "stat %s", serverdir );
    if (st.st_uid != getuid()) fatal_error( "'%s' is not owned by you\n", serverdir );
    if (st.st_mode & 077) fatal_error( "'%s' must not be accessible by other users\n", serverdir );

1235
    for (retry = 0; retry < 6; retry++)
1236
    {
1237 1238 1239 1240
        /* if not the first try, wait a bit to leave the previous server time to exit */
        if (retry)
        {
            usleep( 100000 * retry * retry );
1241
            start_server();
1242 1243 1244
            if (lstat( SOCKETNAME, &st ) == -1) continue;  /* still no socket, wait a bit more */
        }
        else if (lstat( SOCKETNAME, &st ) == -1) /* check for an already existing socket */
1245 1246
        {
            if (errno != ENOENT) fatal_perror( "lstat %s/%s", serverdir, SOCKETNAME );
1247
            start_server();
1248
            if (lstat( SOCKETNAME, &st ) == -1) continue;  /* still no socket, wait a bit more */
1249
        }
1250

1251 1252
        /* make sure the socket is sane (ISFIFO needed for Solaris) */
        if (!S_ISSOCK(st.st_mode) && !S_ISFIFO(st.st_mode))
1253 1254 1255
            fatal_error( "'%s/%s' is not a socket\n", serverdir, SOCKETNAME );
        if (st.st_uid != getuid())
            fatal_error( "'%s/%s' is not owned by you\n", serverdir, SOCKETNAME );
1256

1257 1258 1259 1260
        /* try to connect to it */
        addr.sun_family = AF_UNIX;
        strcpy( addr.sun_path, SOCKETNAME );
        slen = sizeof(addr) - sizeof(addr.sun_path) + strlen(addr.sun_path) + 1;
1261
#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
1262
        addr.sun_len = slen;
1263
#endif
1264
        if ((s = socket( AF_UNIX, SOCK_STREAM, 0 )) == -1) fatal_perror( "socket" );
1265 1266 1267 1268 1269 1270 1271
#ifdef SO_PASSCRED
        else
        {
            int enable = 1;
            setsockopt( s, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable) );
        }
#endif
1272 1273
        if (connect( s, (struct sockaddr *)&addr, slen ) != -1)
        {
1274 1275 1276 1277 1278 1279
            /* switch back to the starting directory */
            if (fd_cwd != -1)
            {
                fchdir( fd_cwd );
                close( fd_cwd );
            }
1280
            fcntl( s, F_SETFD, FD_CLOEXEC );
1281 1282 1283
            return s;
        }
        close( s );
1284
    }
1285
    server_connect_error( serverdir );
1286 1287 1288
}


1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331
#ifdef __APPLE__
#include <mach/mach.h>
#include <mach/mach_error.h>
#include <servers/bootstrap.h>

/* send our task port to the server */
static void send_server_task_port(void)
{
    mach_port_t bootstrap_port, wineserver_port;
    kern_return_t kret;

    struct {
        mach_msg_header_t           header;
        mach_msg_body_t             body;
        mach_msg_port_descriptor_t  task_port;
    } msg;

    if (task_get_bootstrap_port(mach_task_self(), &bootstrap_port) != KERN_SUCCESS) return;

    kret = bootstrap_look_up(bootstrap_port, (char*)wine_get_server_dir(), &wineserver_port);
    if (kret != KERN_SUCCESS)
        fatal_error( "cannot find the server port: 0x%08x\n", kret );

    mach_port_deallocate(mach_task_self(), bootstrap_port);

    msg.header.msgh_bits        = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0) | MACH_MSGH_BITS_COMPLEX;
    msg.header.msgh_size        = sizeof(msg);
    msg.header.msgh_remote_port = wineserver_port;
    msg.header.msgh_local_port  = MACH_PORT_NULL;

    msg.body.msgh_descriptor_count  = 1;
    msg.task_port.name              = mach_task_self();
    msg.task_port.disposition       = MACH_MSG_TYPE_COPY_SEND;
    msg.task_port.type              = MACH_MSG_PORT_DESCRIPTOR;

    kret = mach_msg_send(&msg.header);
    if (kret != KERN_SUCCESS)
        server_protocol_error( "mach_msg_send failed: 0x%08x\n", kret );

    mach_port_deallocate(mach_task_self(), wineserver_port);
}
#endif  /* __APPLE__ */

1332 1333 1334 1335 1336 1337 1338 1339 1340

/***********************************************************************
 *           get_unix_tid
 *
 * Retrieve the Unix tid to use on the server side for the current thread.
 */
static int get_unix_tid(void)
{
    int ret = -1;
1341 1342 1343
#ifdef HAVE_PTHREAD_GETTHREADID_NP
    ret = pthread_getthreadid_np();
#elif defined(linux)
1344
    ret = syscall( __NR_gettid );
1345 1346 1347 1348
#elif defined(__sun)
    ret = pthread_self();
#elif defined(__APPLE__)
    ret = mach_thread_self();
1349
    mach_port_deallocate(mach_task_self(), ret);
1350 1351
#elif defined(__NetBSD__)
    ret = _lwp_self();
1352 1353 1354 1355
#elif defined(__FreeBSD__)
    long lwpid;
    thr_self( &lwpid );
    ret = lwpid;
1356 1357
#elif defined(__DragonFly__)
    ret = lwp_gettid();
1358 1359 1360 1361 1362
#endif
    return ret;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
1363
/***********************************************************************
1364
 *           server_init_process
Alexandre Julliard's avatar
Alexandre Julliard committed
1365
 *
1366
 * Start the server and create the initial socket pair.
Alexandre Julliard's avatar
Alexandre Julliard committed
1367
 */
1368
void server_init_process(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
1369
{
1370
    obj_handle_t version;
1371
    const char *env_socket = getenv( "WINESERVERSOCKET" );
1372

1373
    server_pid = -1;
1374
    if (env_socket)
1375
    {
1376
        fd_socket = atoi( env_socket );
1377
        if (fcntl( fd_socket, F_SETFD, FD_CLOEXEC ) == -1)
1378
            fatal_perror( "Bad server socket %d", fd_socket );
1379
        unsetenv( "WINESERVERSOCKET" );
1380
    }
1381 1382 1383 1384 1385 1386 1387 1388 1389
    else
    {
        const char *arch = getenv( "WINEARCH" );

        if (arch && strcmp( arch, "win32" ) && strcmp( arch, "win64" ))
            fatal_error( "WINEARCH set to invalid value '%s', it must be either win32 or win64.\n", arch );

        fd_socket = server_connect();
    }
1390 1391

    /* setup the signal mask */
1392 1393 1394 1395 1396 1397 1398 1399
    sigemptyset( &server_block_set );
    sigaddset( &server_block_set, SIGALRM );
    sigaddset( &server_block_set, SIGIO );
    sigaddset( &server_block_set, SIGINT );
    sigaddset( &server_block_set, SIGHUP );
    sigaddset( &server_block_set, SIGUSR1 );
    sigaddset( &server_block_set, SIGUSR2 );
    sigaddset( &server_block_set, SIGCHLD );
1400
    pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );
1401

1402
    /* receive the first thread request fd on the main socket */
1403 1404
    ntdll_get_thread_data()->request_fd = receive_fd( &version );

1405
#ifdef SO_PASSCRED
1406
    /* now that we hopefully received the server_pid, disable SO_PASSCRED */
1407
    {
1408
        int enable = 0;
1409 1410 1411
        setsockopt( fd_socket, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable) );
    }
#endif
1412

1413 1414 1415 1416 1417 1418 1419
    if (version != SERVER_PROTOCOL_VERSION)
        server_protocol_error( "version mismatch %d/%d.\n"
                               "Your %s binary was not upgraded correctly,\n"
                               "or you have an older one somewhere in your PATH.\n"
                               "Or maybe the wrong wineserver is still running?\n",
                               version, SERVER_PROTOCOL_VERSION,
                               (version > SERVER_PROTOCOL_VERSION) ? "wine" : "wineserver" );
1420 1421 1422
#ifdef __APPLE__
    send_server_task_port();
#endif
1423 1424 1425 1426
#if defined(__linux__) && defined(HAVE_PRCTL)
    /* work around Ubuntu's ptrace breakage */
    if (server_pid != -1) prctl( 0x59616d61 /* PR_SET_PTRACER */, server_pid );
#endif
Alexandre Julliard's avatar
Alexandre Julliard committed
1427 1428 1429
}


1430 1431 1432
/***********************************************************************
 *           server_init_process_done
 */
1433
void server_init_process_done(void)
1434 1435 1436
{
    PEB *peb = NtCurrentTeb()->Peb;
    IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress );
1437
    void *entry = (char *)peb->ImageBaseAddress + nt->OptionalHeader.AddressOfEntryPoint;
1438
    NTSTATUS status;
1439
    int suspend;
1440 1441 1442 1443 1444 1445 1446

    /* Install signal handlers; this cannot be done earlier, since we cannot
     * send exceptions to the debugger before the create process event that
     * is sent by REQ_INIT_PROCESS_DONE.
     * We do need the handlers in place by the time the request is over, so
     * we set them up here. If we segfault between here and the server call
     * something is very wrong... */
1447
    signal_init_process();
1448 1449 1450 1451

    /* Signal the parent process to continue */
    SERVER_START_REQ( init_process_done )
    {
1452 1453 1454 1455
        req->module   = wine_server_client_ptr( peb->ImageBaseAddress );
#ifdef __i386__
        req->ldt_copy = wine_server_client_ptr( &wine_ldt_copy );
#endif
1456
        req->entry    = wine_server_client_ptr( entry );
1457
        req->gui      = (nt->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_CUI);
1458
        status = wine_server_call( req );
1459
        suspend = reply->suspend;
1460 1461 1462
    }
    SERVER_END_REQ;

1463 1464
    assert( !status );
    signal_start_process( entry, suspend );
1465 1466 1467
}


1468
/***********************************************************************
1469
 *           server_init_thread
1470 1471 1472
 *
 * Send an init thread request. Return 0 if OK.
 */
1473
size_t server_init_thread( void *entry_point, BOOL *suspend )
1474
{
1475
    static const char *cpu_names[] = { "x86", "x86_64", "PowerPC", "ARM", "ARM64" };
1476
    static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
1477
    const char *arch = getenv( "WINEARCH" );
1478
    int ret;
1479
    int reply_pipe[2];
1480
    struct sigaction sig_act;
1481
    size_t info_size;
1482 1483 1484 1485

    sig_act.sa_handler = SIG_IGN;
    sig_act.sa_flags   = 0;
    sigemptyset( &sig_act.sa_mask );
1486

1487
    /* ignore SIGPIPE so that we get an EPIPE error instead  */
1488
    sigaction( SIGPIPE, &sig_act, NULL );
1489 1490

    /* create the server->client communication pipes */
1491 1492
    if (server_pipe( reply_pipe ) == -1) server_protocol_perror( "pipe" );
    if (server_pipe( ntdll_get_thread_data()->wait_fd ) == -1) server_protocol_perror( "pipe" );
1493
    wine_server_send_fd( reply_pipe[1] );
1494 1495
    wine_server_send_fd( ntdll_get_thread_data()->wait_fd[1] );
    ntdll_get_thread_data()->reply_fd = reply_pipe[0];
1496
    close( reply_pipe[1] );
1497

1498
    SERVER_START_REQ( init_thread )
1499
    {
1500 1501
        req->unix_pid    = getpid();
        req->unix_tid    = get_unix_tid();
1502
        req->teb         = wine_server_client_ptr( NtCurrentTeb() );
1503
        req->entry       = wine_server_client_ptr( entry_point );
1504
        req->reply_fd    = reply_pipe[1];
1505
        req->wait_fd     = ntdll_get_thread_data()->wait_fd[1];
1506
        req->debug_level = (TRACE_ON(server) != 0);
1507
        req->cpu         = client_cpu;
1508
        ret = wine_server_call( req );
1509 1510
        NtCurrentTeb()->ClientId.UniqueProcess = ULongToHandle(reply->pid);
        NtCurrentTeb()->ClientId.UniqueThread  = ULongToHandle(reply->tid);
1511 1512
        info_size         = reply->info_size;
        server_start_time = reply->server_start;
1513
        server_cpus       = reply->all_cpus;
1514
        *suspend          = reply->suspend;
1515 1516
    }
    SERVER_END_REQ;
1517

1518
    is_wow64 = !is_win64 && (server_cpus & ((1 << CPU_x86_64) | (1 << CPU_ARM64))) != 0;
1519 1520
    ntdll_get_thread_data()->wow64_redir = is_wow64;

1521
    switch (ret)
1522
    {
1523
    case STATUS_SUCCESS:
1524 1525 1526 1527 1528
        if (arch)
        {
            if (!strcmp( arch, "win32" ) && (is_win64 || is_wow64))
                fatal_error( "WINEARCH set to win32 but '%s' is a 64-bit installation.\n",
                             wine_get_config_dir() );
1529
            if (!strcmp( arch, "win64" ) && !is_win64 && !is_wow64)
1530 1531 1532
                fatal_error( "WINEARCH set to win64 but '%s' is a 32-bit installation.\n",
                             wine_get_config_dir() );
        }
1533
        return info_size;
1534
    case STATUS_INVALID_IMAGE_WIN_64:
1535 1536 1537
        fatal_error( "'%s' is a 32-bit installation, it cannot support 64-bit applications.\n",
                     wine_get_config_dir() );
    case STATUS_NOT_SUPPORTED:
1538 1539 1540 1541
        fatal_error( "'%s' is a 64-bit installation, it cannot be used with a 32-bit wineserver.\n",
                     wine_get_config_dir() );
    case STATUS_INVALID_IMAGE_FORMAT:
        fatal_error( "wineserver doesn't support the %s architecture\n", cpu_names[client_cpu] );
1542 1543
    default:
        server_protocol_error( "init_thread failed with status %x\n", ret );
1544
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
1545
}