macdrv_main.c 23.6 KB
Newer Older
1
/*
2
 * MACDRV initialization code
3 4 5
 *
 * Copyright 1998 Patrik Stridvall
 * Copyright 2000 Alexandre Julliard
6
 * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * 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
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */
22 23 24 25 26

#if 0
#pragma makedep unix
#endif

27 28
#include "config.h"

29
#include <Security/AuthSession.h>
30
#include <IOKit/pwr_mgt/IOPMLib.h>
31

32 33
#include "ntstatus.h"
#define WIN32_NO_STATUS
34
#include "macdrv.h"
35
#include "shellapi.h"
36
#include "wine/server.h"
37 38

WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
39

40 41 42
#define IS_OPTION_TRUE(ch) \
    ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')

43 44
C_ASSERT(NUM_EVENT_TYPES <= sizeof(macdrv_event_mask) * 8);

45
int topmost_float_inactive = TOPMOST_FLOAT_INACTIVE_NONFULLSCREEN;
46
int capture_displays_for_fullscreen = 0;
47
BOOL skip_single_buffer_flushes = FALSE;
48
BOOL allow_vsync = TRUE;
49
BOOL allow_set_gamma = TRUE;
50 51
int left_option_is_alt = 0;
int right_option_is_alt = 0;
52 53
int left_command_is_ctrl = 0;
int right_command_is_ctrl = 0;
54
BOOL allow_software_rendering = FALSE;
55
BOOL disable_window_decorations = FALSE;
56
int allow_immovable_windows = TRUE;
57
int use_confinement_cursor_clipping = TRUE;
58
int cursor_clipping_locks_windows = TRUE;
59
int use_precise_scrolling = TRUE;
60
int gl_surface_mode = GL_SURFACE_IN_FRONT_OPAQUE;
61
int retina_enabled = FALSE;
62
int enable_app_nap = FALSE;
63

64 65
CFDictionaryRef localized_strings;

66

67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
/**************************************************************************
 *              debugstr_cf
 */
const char* debugstr_cf(CFTypeRef t)
{
    CFStringRef s;
    const char* ret;

    if (!t) return "(null)";

    if (CFGetTypeID(t) == CFStringGetTypeID())
        s = t;
    else
        s = CFCopyDescription(t);
    ret = CFStringGetCStringPtr(s, kCFStringEncodingUTF8);
    if (ret) ret = debugstr_a(ret);
    if (!ret)
    {
        const UniChar* u = CFStringGetCharactersPtr(s);
        if (u)
            ret = debugstr_wn((const WCHAR*)u, CFStringGetLength(s));
    }
    if (!ret)
    {
        UniChar buf[200];
92
        int len = min(CFStringGetLength(s), ARRAY_SIZE(buf));
93 94 95 96 97 98 99 100
        CFStringGetCharacters(s, CFRangeMake(0, len), buf);
        ret = debugstr_wn(buf, len);
    }
    if (s != t) CFRelease(s);
    return ret;
}


101
HKEY reg_open_key(HKEY root, const WCHAR *name, ULONG name_len)
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
{
    UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name };
    OBJECT_ATTRIBUTES attr;
    HANDLE ret;

    attr.Length = sizeof(attr);
    attr.RootDirectory = root;
    attr.ObjectName = &nameW;
    attr.Attributes = 0;
    attr.SecurityDescriptor = NULL;
    attr.SecurityQualityOfService = NULL;

    return NtOpenKeyEx(&ret, MAXIMUM_ALLOWED, &attr, 0) ? 0 : ret;
}


118
HKEY open_hkcu_key(const char *name)
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
{
    WCHAR bufferW[256];
    static HKEY hkcu;

    if (!hkcu)
    {
        char buffer[256];
        DWORD_PTR sid_data[(sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE) / sizeof(DWORD_PTR)];
        DWORD i, len = sizeof(sid_data);
        SID *sid;

        if (NtQueryInformationToken(GetCurrentThreadEffectiveToken(), TokenUser, sid_data, len, &len))
            return 0;

        sid = ((TOKEN_USER *)sid_data)->User.Sid;
        len = sprintf(buffer, "\\Registry\\User\\S-%u-%u", sid->Revision,
135 136 137 138
                      (unsigned int)MAKELONG(MAKEWORD(sid->IdentifierAuthority.Value[5],
                                                      sid->IdentifierAuthority.Value[4]),
                                             MAKEWORD(sid->IdentifierAuthority.Value[3],
                                                      sid->IdentifierAuthority.Value[2])));
139
        for (i = 0; i < sid->SubAuthorityCount; i++)
140
            len += sprintf(buffer + len, "-%u", (unsigned int)sid->SubAuthority[i]);
141 142 143 144 145 146 147 148 149

        ascii_to_unicode(bufferW, buffer, len);
        hkcu = reg_open_key(NULL, bufferW, len * sizeof(WCHAR));
    }

    return reg_open_key(hkcu, bufferW, asciiz_to_unicode(bufferW, name) - sizeof(WCHAR));
}


150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
/* wrapper for NtCreateKey that creates the key recursively if necessary */
HKEY reg_create_key(HKEY root, const WCHAR *name, ULONG name_len,
                    DWORD options, DWORD *disposition)
{
    UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name };
    OBJECT_ATTRIBUTES attr;
    NTSTATUS status;
    HANDLE ret;

    attr.Length = sizeof(attr);
    attr.RootDirectory = root;
    attr.ObjectName = &nameW;
    attr.Attributes = 0;
    attr.SecurityDescriptor = NULL;
    attr.SecurityQualityOfService = NULL;

    status = NtCreateKey(&ret, MAXIMUM_ALLOWED, &attr, 0, NULL, options, disposition);
    if (status == STATUS_OBJECT_NAME_NOT_FOUND)
    {
        static const WCHAR registry_rootW[] = { '\\','R','e','g','i','s','t','r','y','\\' };
        DWORD pos = 0, i = 0, len = name_len / sizeof(WCHAR);

        /* don't try to create registry root */
        if (!root && len > ARRAY_SIZE(registry_rootW) &&
            !memcmp(name, registry_rootW, sizeof(registry_rootW)))
            i += ARRAY_SIZE(registry_rootW);

        while (i < len && name[i] != '\\') i++;
        if (i == len) return 0;
        for (;;)
        {
            unsigned int subkey_options = options;
            if (i < len) subkey_options &= ~(REG_OPTION_CREATE_LINK | REG_OPTION_OPEN_LINK);
            nameW.Buffer = (WCHAR *)name + pos;
            nameW.Length = (i - pos) * sizeof(WCHAR);
            status = NtCreateKey(&ret, MAXIMUM_ALLOWED, &attr, 0, NULL, subkey_options, disposition);

            if (attr.RootDirectory != root) NtClose(attr.RootDirectory);
            if (!NT_SUCCESS(status)) return 0;
            if (i == len) break;
            attr.RootDirectory = ret;
            while (i < len && name[i] == '\\') i++;
            pos = i;
            while (i < len && name[i] != '\\') i++;
        }
    }
    return ret;
}


HKEY reg_create_ascii_key(HKEY root, const char *name, DWORD options, DWORD *disposition)
{
    WCHAR buf[256];
    return reg_create_key(root, buf, asciiz_to_unicode(buf, name) - sizeof(WCHAR),
                          options, disposition);
}


BOOL reg_delete_tree(HKEY parent, const WCHAR *name, ULONG name_len)
{
    char buffer[4096];
    KEY_NODE_INFORMATION *key_info = (KEY_NODE_INFORMATION *)buffer;
    DWORD size;
    HKEY key;
    BOOL ret = TRUE;

    if (!(key = reg_open_key(parent, name, name_len))) return FALSE;

    while (ret && !NtEnumerateKey(key, 0, KeyNodeInformation, key_info, sizeof(buffer), &size))
        ret = reg_delete_tree(key, key_info->Name, key_info->NameLength);

    if (ret) ret = !NtDeleteKey(key);
    NtClose(key);
    return ret;
}


227
ULONG query_reg_value(HKEY hkey, const WCHAR *name, KEY_VALUE_PARTIAL_INFORMATION *info, ULONG size)
228 229 230 231 232 233 234 235 236 237 238
{
    UNICODE_STRING str;

    RtlInitUnicodeString(&str, name);
    if (NtQueryValueKey(hkey, &str, KeyValuePartialInformation, info, size, &size))
        return 0;

    return size - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
}


239 240 241 242 243 244
/***********************************************************************
 *              get_config_key
 *
 * Get a config key from either the app-specific or the default config
 */
static inline DWORD get_config_key(HKEY defkey, HKEY appkey, const char *name,
245
                                   WCHAR *buffer, DWORD size)
246
{
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
    WCHAR nameW[128];
    char buf[2048];
    KEY_VALUE_PARTIAL_INFORMATION *info = (void *)buf;

    asciiz_to_unicode(nameW, name);

    if (appkey && query_reg_value(appkey, nameW, info, sizeof(buf)))
    {
        size = min(info->DataLength, size - sizeof(WCHAR));
        memcpy(buffer, info->Data, size);
        buffer[size / sizeof(WCHAR)] = 0;
        return 0;
    }

    if (defkey && query_reg_value(defkey, nameW, info, sizeof(buf)))
    {
        size = min(info->DataLength, size - sizeof(WCHAR));
        memcpy(buffer, info->Data, size);
        buffer[size / sizeof(WCHAR)] = 0;
        return 0;
    }

269 270 271 272 273 274 275 276 277 278 279
    return ERROR_FILE_NOT_FOUND;
}


/***********************************************************************
 *              setup_options
 *
 * Set up the Mac driver options.
 */
static void setup_options(void)
{
280 281
    static const WCHAR macdriverW[] = {'\\','M','a','c',' ','D','r','i','v','e','r',0};
    WCHAR buffer[MAX_PATH + 16], *p, *appname;
282 283 284 285
    HKEY hkey, appkey = 0;
    DWORD len;

    /* @@ Wine registry key: HKCU\Software\Wine\Mac Driver */
286
    hkey = open_hkcu_key("Software\\Wine\\Mac Driver");
287 288 289

    /* open the app-specific key */

290 291 292 293 294
    appname = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
    if ((p = wcsrchr(appname, '/'))) appname = p + 1;
    if ((p = wcsrchr(appname, '\\'))) appname = p + 1;
    len = lstrlenW(appname);

295 296 297
    if (len && len < MAX_PATH)
    {
        HKEY tmpkey;
298 299
        memcpy(buffer, appname, len * sizeof(WCHAR));
        memcpy(buffer + len, macdriverW, sizeof(macdriverW));
300
        /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\Mac Driver */
301
        if ((tmpkey = open_hkcu_key("Software\\Wine\\AppDefaults")))
302
        {
303 304
            appkey = reg_open_key(tmpkey, buffer, lstrlenW(buffer) * sizeof(WCHAR));
            NtClose(tmpkey);
305 306 307 308 309
        }
    }

    if (!get_config_key(hkey, appkey, "WindowsFloatWhenInactive", buffer, sizeof(buffer)))
    {
310 311
        static const WCHAR noneW[] = {'n','o','n','e',0};
        static const WCHAR allW[] = {'a','l','l',0};
312
        if (!wcscmp(buffer, noneW))
313
            topmost_float_inactive = TOPMOST_FLOAT_INACTIVE_NONE;
314
        else if (!wcscmp(buffer, allW))
315 316 317 318 319
            topmost_float_inactive = TOPMOST_FLOAT_INACTIVE_ALL;
        else
            topmost_float_inactive = TOPMOST_FLOAT_INACTIVE_NONFULLSCREEN;
    }

320 321 322
    if (!get_config_key(hkey, appkey, "CaptureDisplaysForFullscreen", buffer, sizeof(buffer)))
        capture_displays_for_fullscreen = IS_OPTION_TRUE(buffer[0]);

323 324 325
    if (!get_config_key(hkey, appkey, "SkipSingleBufferFlushes", buffer, sizeof(buffer)))
        skip_single_buffer_flushes = IS_OPTION_TRUE(buffer[0]);

326 327 328
    if (!get_config_key(hkey, appkey, "AllowVerticalSync", buffer, sizeof(buffer)))
        allow_vsync = IS_OPTION_TRUE(buffer[0]);

329 330 331
    if (!get_config_key(hkey, appkey, "AllowSetGamma", buffer, sizeof(buffer)))
        allow_set_gamma = IS_OPTION_TRUE(buffer[0]);

332 333 334 335 336
    if (!get_config_key(hkey, appkey, "LeftOptionIsAlt", buffer, sizeof(buffer)))
        left_option_is_alt = IS_OPTION_TRUE(buffer[0]);
    if (!get_config_key(hkey, appkey, "RightOptionIsAlt", buffer, sizeof(buffer)))
        right_option_is_alt = IS_OPTION_TRUE(buffer[0]);

337 338 339 340 341 342 343 344 345 346
    if (!get_config_key(hkey, appkey, "LeftCommandIsCtrl", buffer, sizeof(buffer)))
        left_command_is_ctrl = IS_OPTION_TRUE(buffer[0]);
    if (!get_config_key(hkey, appkey, "RightCommandIsCtrl", buffer, sizeof(buffer)))
        right_command_is_ctrl = IS_OPTION_TRUE(buffer[0]);

    if (left_command_is_ctrl && right_command_is_ctrl && !left_option_is_alt && !right_option_is_alt)
        WARN("Both Command keys have been mapped to Control. There is no way to "
             "send an Alt key to Windows applications. Consider enabling "
             "LeftOptionIsAlt or RightOptionIsAlt.\n");

347 348 349
    if (!get_config_key(hkey, appkey, "AllowSoftwareRendering", buffer, sizeof(buffer)))
        allow_software_rendering = IS_OPTION_TRUE(buffer[0]);

350 351 352 353
    /* Value name chosen to match what's used in the X11 driver. */
    if (!get_config_key(hkey, appkey, "Decorated", buffer, sizeof(buffer)))
        disable_window_decorations = !IS_OPTION_TRUE(buffer[0]);

354 355 356
    if (!get_config_key(hkey, appkey, "AllowImmovableWindows", buffer, sizeof(buffer)))
        allow_immovable_windows = IS_OPTION_TRUE(buffer[0]);

357 358 359
    if (!get_config_key(hkey, appkey, "UseConfinementCursorClipping", buffer, sizeof(buffer)))
        use_confinement_cursor_clipping = IS_OPTION_TRUE(buffer[0]);

360 361 362
    if (!get_config_key(hkey, appkey, "CursorClippingLocksWindows", buffer, sizeof(buffer)))
        cursor_clipping_locks_windows = IS_OPTION_TRUE(buffer[0]);

363 364 365
    if (!get_config_key(hkey, appkey, "UsePreciseScrolling", buffer, sizeof(buffer)))
        use_precise_scrolling = IS_OPTION_TRUE(buffer[0]);

366 367
    if (!get_config_key(hkey, appkey, "OpenGLSurfaceMode", buffer, sizeof(buffer)))
    {
368 369
        static const WCHAR transparentW[] = {'t','r','a','n','s','p','a','r','e','n','t',0};
        static const WCHAR behindW[] = {'b','e','h','i','n','d',0};
370
        if (!wcscmp(buffer, transparentW))
371
            gl_surface_mode = GL_SURFACE_IN_FRONT_TRANSPARENT;
372
        else if (!wcscmp(buffer, behindW))
373 374 375 376 377
            gl_surface_mode = GL_SURFACE_BEHIND;
        else
            gl_surface_mode = GL_SURFACE_IN_FRONT_OPAQUE;
    }

378 379 380
    if (!get_config_key(hkey, appkey, "EnableAppNap", buffer, sizeof(buffer)))
        enable_app_nap = IS_OPTION_TRUE(buffer[0]);

381 382 383 384 385
    /* Don't use appkey.  The DPI and monitor sizes should be consistent for all
       processes in the prefix. */
    if (!get_config_key(hkey, NULL, "RetinaMode", buffer, sizeof(buffer)))
        retina_enabled = IS_OPTION_TRUE(buffer[0]);

386 387
    if (appkey) NtClose(appkey);
    if (hkey) NtClose(hkey);
388 389 390
}


391 392 393
/***********************************************************************
 *              load_strings
 */
394
static void load_strings(struct localized_string *str)
395 396 397 398 399 400 401 402 403 404 405
{
    CFMutableDictionaryRef dict;

    dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks,
                                     &kCFTypeDictionaryValueCallBacks);
    if (!dict)
    {
        ERR("Failed to create localized strings dictionary\n");
        return;
    }

406
    while (str->id)
407
    {
408
        if (str->str && str->len)
409
        {
410
            const UniChar *ptr = param_ptr(str->str);
411
            CFNumberRef key = CFNumberCreate(NULL, kCFNumberIntType, &str->id);
412
            CFStringRef value = CFStringCreateWithCharacters(NULL, ptr, str->len);
413 414 415
            if (key && value)
                CFDictionarySetValue(dict, key, value);
            else
416
                ERR("Failed to add string ID 0x%04x %s\n", str->id, debugstr_wn(ptr, str->len));
417 418
        }
        else
419 420
            ERR("Failed to load string ID 0x%04x\n", str->id);
        str++;
421 422 423 424 425 426
    }

    localized_strings = dict;
}


427
/***********************************************************************
428
 *              macdrv_init
429
 */
430
static NTSTATUS macdrv_init(void *arg)
431
{
432
    struct init_params *params = arg;
433 434 435 436 437
    SessionAttributeBits attributes;
    OSStatus status;

    status = SessionGetInfo(callerSecuritySession, NULL, &attributes);
    if (status != noErr || !(attributes & sessionHasGraphicAccess))
438
        return STATUS_UNSUCCESSFUL;
439

440
    init_win_context();
441
    setup_options();
442
    load_strings(params->strings);
443

444
    macdrv_err_on = ERR_ON(macdrv);
445
    if (macdrv_start_cocoa_app(NtGetTickCount()))
446 447
    {
        ERR("Failed to start Cocoa app main loop\n");
448
        return STATUS_UNSUCCESSFUL;
449 450
    }

451
    init_user_driver();
452
    macdrv_init_display_devices(FALSE);
453
    return STATUS_SUCCESS;
454 455 456 457
}


/***********************************************************************
458
 *              ThreadDetach   (MACDRV.@)
459
 */
460
void macdrv_ThreadDetach(void)
461 462 463 464 465 466
{
    struct macdrv_thread_data *data = macdrv_thread_data();

    if (data)
    {
        macdrv_destroy_event_queue(data->queue);
467 468
        if (data->keyboard_layout_uchr)
            CFRelease(data->keyboard_layout_uchr);
469
        free(data);
470
        /* clear data in case we get re-entered from user32 before the thread is truly dead */
471
        NtUserGetThreadInfo()->driver_data = 0;
472 473 474 475
    }
}


476
/***********************************************************************
477 478 479
 *              set_queue_display_fd
 *
 * Store the event queue fd into the message queue
480
 */
481 482 483 484 485 486 487 488
static void set_queue_display_fd(int fd)
{
    HANDLE handle;
    int ret;

    if (wine_server_fd_to_handle(fd, GENERIC_READ | SYNCHRONIZE, 0, &handle))
    {
        MESSAGE("macdrv: Can't allocate handle for event queue fd\n");
489
        NtTerminateProcess(0, 1);
490 491 492 493 494 495 496 497 498 499
    }
    SERVER_START_REQ(set_queue_fd)
    {
        req->handle = wine_server_obj_handle(handle);
        ret = wine_server_call(req);
    }
    SERVER_END_REQ;
    if (ret)
    {
        MESSAGE("macdrv: Can't store handle for event queue fd\n");
500
        NtTerminateProcess(0, 1);
501
    }
502
    NtClose(handle);
503 504 505 506 507 508 509 510 511
}


/***********************************************************************
 *              macdrv_init_thread_data
 */
struct macdrv_thread_data *macdrv_init_thread_data(void)
{
    struct macdrv_thread_data *data = macdrv_thread_data();
512
    TISInputSourceRef input_source;
513 514 515

    if (data) return data;

516
    if (!(data = calloc(1, sizeof(*data))))
517 518
    {
        ERR("could not create data\n");
519
        NtTerminateProcess(0, 1);
520 521
    }

522
    if (!(data->queue = macdrv_create_event_queue(macdrv_handle_event)))
523 524
    {
        ERR("macdrv: Can't create event queue.\n");
525
        NtTerminateProcess(0, 1);
526 527
    }

528 529 530
    macdrv_get_input_source_info(&data->keyboard_layout_uchr, &data->keyboard_type, &data->iso_keyboard, &input_source);
    data->active_keyboard_layout = macdrv_get_hkl_from_source(input_source);
    CFRelease(input_source);
531 532
    macdrv_compute_keyboard_layout(data);

533
    set_queue_display_fd(macdrv_get_event_queue_fd(data->queue));
534
    NtUserGetThreadInfo()->driver_data = (UINT_PTR)data;
535

536
    NtUserActivateKeyboardLayout(data->active_keyboard_layout, 0);
537 538 539 540
    return data;
}


541 542 543
/***********************************************************************
 *              SystemParametersInfo (MACDRV.@)
 */
544
BOOL macdrv_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param, UINT flags )
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
{
    switch (action)
    {
    case SPI_GETSCREENSAVEACTIVE:
        if (ptr_param)
        {
            CFDictionaryRef assertionStates;
            IOReturn status = IOPMCopyAssertionsStatus(&assertionStates);
            if (status == kIOReturnSuccess)
            {
                CFNumberRef count = CFDictionaryGetValue(assertionStates, kIOPMAssertionTypeNoDisplaySleep);
                CFNumberRef count2 = CFDictionaryGetValue(assertionStates, kIOPMAssertionTypePreventUserIdleDisplaySleep);
                long longCount = 0, longCount2 = 0;

                if (count)
                    CFNumberGetValue(count, kCFNumberLongType, &longCount);
                if (count2)
                    CFNumberGetValue(count2, kCFNumberLongType, &longCount2);

                *(BOOL *)ptr_param = !longCount && !longCount2;
                CFRelease(assertionStates);
            }
            else
            {
                WARN("Could not determine screen saver state, error code %d\n", status);
                *(BOOL *)ptr_param = TRUE;
            }
            return TRUE;
        }
        break;

    case SPI_SETSCREENSAVEACTIVE:
        {
            static IOPMAssertionID powerAssertion = kIOPMNullAssertionID;
            if (int_param)
            {
                if (powerAssertion != kIOPMNullAssertionID)
                {
                    IOPMAssertionRelease(powerAssertion);
                    powerAssertion = kIOPMNullAssertionID;
                }
            }
            else if (powerAssertion == kIOPMNullAssertionID)
            {
589
                IOPMAssertionCreateWithName( kIOPMAssertionTypePreventUserIdleDisplaySleep, kIOPMAssertionLevelOn,
590 591 592 593 594 595 596 597
                                             CFSTR("Wine Process requesting no screen saver"),
                                             &powerAssertion);
            }
        }
        break;
    }
    return FALSE;
}
598 599


600 601
NTSTATUS macdrv_client_func(enum macdrv_client_funcs id, const void *params, ULONG size)
{
602 603 604
    void *ret_ptr;
    ULONG ret_len;
    return KeUserModeCallback(id, params, size, &ret_ptr, &ret_len);
605 606 607
}


608 609 610 611 612 613 614
static NTSTATUS macdrv_ime_clear(void *arg)
{
    macdrv_clear_ime_text();
    return 0;
}


615 616 617 618 619 620
static NTSTATUS macdrv_ime_using_input_method(void *arg)
{
    return macdrv_using_input_method();
}


621 622 623 624 625 626 627 628
static NTSTATUS macdrv_quit_result(void *arg)
{
    struct quit_result_params *params = arg;
    macdrv_quit_reply(params->result);
    return 0;
}


629 630
const unixlib_entry_t __wine_unix_call_funcs[] =
{
631
    macdrv_dnd_get_data,
632 633 634 635
    macdrv_dnd_get_formats,
    macdrv_dnd_have_format,
    macdrv_dnd_release,
    macdrv_dnd_retain,
636
    macdrv_ime_clear,
637 638
    macdrv_ime_process_text_input,
    macdrv_ime_using_input_method,
639
    macdrv_init,
640
    macdrv_notify_icon,
641
    macdrv_quit_result,
642 643 644
};

C_ASSERT( ARRAYSIZE(__wine_unix_call_funcs) == unix_funcs_count );
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

#ifdef _WIN64

static NTSTATUS wow64_dnd_get_data(void *arg)
{
    struct
    {
        UINT64 handle;
        UINT format;
        ULONG size;
        ULONG data;
    } *params32 = arg;
    struct dnd_get_data_params params;

    params.handle = params32->handle;
    params.format = params32->format;
    params.size = params32->size;
    params.data = UlongToPtr(params32->data);
    return macdrv_dnd_get_data(&params);
}

static NTSTATUS wow64_ime_process_text_input(void *arg)
{
    struct
    {
670
        UINT himc;
671 672 673 674 675 676 677 678
        UINT vkey;
        UINT scan;
        UINT repeat;
        ULONG key_state;
        ULONG done;
    } *params32 = arg;
    struct process_text_input_params params;

679
    params.himc = params32->himc;
680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772
    params.vkey = params32->vkey;
    params.scan = params32->scan;
    params.repeat = params32->repeat;
    params.key_state = UlongToPtr(params32->key_state);
    params.done = UlongToPtr(params32->done);
    return macdrv_ime_process_text_input(&params);
}

static NTSTATUS wow64_init(void *arg)
{
    struct
    {
        ULONG strings;
    } *params32 = arg;
    struct init_params params;

    params.strings = UlongToPtr(params32->strings);
    return macdrv_init(&params);
}

static NTSTATUS wow64_notify_icon(void *arg)
{
    struct
    {
        DWORD msg;
        ULONG data;
    } *params32 = arg;
    struct
    {
        DWORD cbSize;
        ULONG hWnd;
        UINT uID;
        UINT uFlags;
        UINT uCallbackMessage;
        ULONG hIcon;
        WCHAR szTip[128];
        DWORD dwState;
        DWORD dwStateMask;
        WCHAR szInfo[256];
        UINT uTimeout;
        WCHAR szInfoTitle[64];
        DWORD dwInfoFlags;
        GUID guidItem;
        ULONG hBalloonIcon;
    } *data32 = UlongToPtr(params32->data);

    struct notify_icon_params params;
    NOTIFYICONDATAW data;

    params.msg = params32->msg;
    params.data = &data;

    data.cbSize = sizeof(data);
    data.hWnd = UlongToHandle(data32->hWnd);
    data.uID = data32->uID;
    data.uFlags = data32->uFlags;
    data.uCallbackMessage = data32->uCallbackMessage;
    data.hIcon = UlongToHandle(data32->hIcon);
    if (data.uFlags & NIF_TIP)
        wcscpy(data.szTip, data32->szTip);
    data.dwState = data32->dwState;
    data.dwStateMask = data32->dwStateMask;
    if (data.uFlags & NIF_INFO)
    {
        wcscpy(data.szInfoTitle, data32->szInfoTitle);
        wcscpy(data.szInfo, data32->szInfo);
        data.uTimeout = data32->uTimeout;
        data.dwInfoFlags = data32->dwInfoFlags;
    }
    data.guidItem = data32->guidItem;
    data.hBalloonIcon = UlongToHandle(data32->hBalloonIcon);

    return macdrv_notify_icon(&params);
}

const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
{
    wow64_dnd_get_data,
    macdrv_dnd_get_formats,
    macdrv_dnd_have_format,
    macdrv_dnd_release,
    macdrv_dnd_retain,
    macdrv_ime_clear,
    wow64_ime_process_text_input,
    macdrv_ime_using_input_method,
    wow64_init,
    wow64_notify_icon,
    macdrv_quit_result,
};

C_ASSERT( ARRAYSIZE(__wine_unix_call_wow64_funcs) == unix_funcs_count );

#endif /* _WIN64 */