gdi32: Fix leak in GdiDeleteSpoolFileHandle.
[wine.git] / dlls / winemac.drv / macdrv_main.c
blob54c5ee6c93a0c0243fc2ebfeeb6f03985547d5fd
1 /*
2 * MACDRV initialization code
4 * Copyright 1998 Patrik Stridvall
5 * Copyright 2000 Alexandre Julliard
6 * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #if 0
24 #pragma makedep unix
25 #endif
27 #include "config.h"
29 #include <Security/AuthSession.h>
30 #include <IOKit/pwr_mgt/IOPMLib.h>
32 #include "ntstatus.h"
33 #define WIN32_NO_STATUS
34 #include "macdrv.h"
35 #include "shellapi.h"
36 #include "wine/server.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
40 #define IS_OPTION_TRUE(ch) \
41 ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
43 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 int left_option_is_alt = 0;
51 int right_option_is_alt = 0;
52 int left_command_is_ctrl = 0;
53 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;
64 CFDictionaryRef localized_strings;
67 /**************************************************************************
68 * debugstr_cf
70 const char* debugstr_cf(CFTypeRef t)
72 CFStringRef s;
73 const char* ret;
75 if (!t) return "(null)";
77 if (CFGetTypeID(t) == CFStringGetTypeID())
78 s = t;
79 else
80 s = CFCopyDescription(t);
81 ret = CFStringGetCStringPtr(s, kCFStringEncodingUTF8);
82 if (ret) ret = debugstr_a(ret);
83 if (!ret)
85 const UniChar* u = CFStringGetCharactersPtr(s);
86 if (u)
87 ret = debugstr_wn((const WCHAR*)u, CFStringGetLength(s));
89 if (!ret)
91 UniChar buf[200];
92 int len = min(CFStringGetLength(s), ARRAY_SIZE(buf));
93 CFStringGetCharacters(s, CFRangeMake(0, len), buf);
94 ret = debugstr_wn(buf, len);
96 if (s != t) CFRelease(s);
97 return ret;
101 HKEY reg_open_key(HKEY root, const WCHAR *name, ULONG name_len)
103 UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name };
104 OBJECT_ATTRIBUTES attr;
105 HANDLE ret;
107 attr.Length = sizeof(attr);
108 attr.RootDirectory = root;
109 attr.ObjectName = &nameW;
110 attr.Attributes = 0;
111 attr.SecurityDescriptor = NULL;
112 attr.SecurityQualityOfService = NULL;
114 return NtOpenKeyEx(&ret, MAXIMUM_ALLOWED, &attr, 0) ? 0 : ret;
118 HKEY open_hkcu_key(const char *name)
120 WCHAR bufferW[256];
121 static HKEY hkcu;
123 if (!hkcu)
125 char buffer[256];
126 DWORD_PTR sid_data[(sizeof(TOKEN_USER) + SECURITY_MAX_SID_SIZE) / sizeof(DWORD_PTR)];
127 DWORD i, len = sizeof(sid_data);
128 SID *sid;
130 if (NtQueryInformationToken(GetCurrentThreadEffectiveToken(), TokenUser, sid_data, len, &len))
131 return 0;
133 sid = ((TOKEN_USER *)sid_data)->User.Sid;
134 len = sprintf(buffer, "\\Registry\\User\\S-%u-%u", sid->Revision,
135 (unsigned int)MAKELONG(MAKEWORD(sid->IdentifierAuthority.Value[5],
136 sid->IdentifierAuthority.Value[4]),
137 MAKEWORD(sid->IdentifierAuthority.Value[3],
138 sid->IdentifierAuthority.Value[2])));
139 for (i = 0; i < sid->SubAuthorityCount; i++)
140 len += sprintf(buffer + len, "-%u", (unsigned int)sid->SubAuthority[i]);
142 ascii_to_unicode(bufferW, buffer, len);
143 hkcu = reg_open_key(NULL, bufferW, len * sizeof(WCHAR));
146 return reg_open_key(hkcu, bufferW, asciiz_to_unicode(bufferW, name) - sizeof(WCHAR));
150 /* wrapper for NtCreateKey that creates the key recursively if necessary */
151 HKEY reg_create_key(HKEY root, const WCHAR *name, ULONG name_len,
152 DWORD options, DWORD *disposition)
154 UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name };
155 OBJECT_ATTRIBUTES attr;
156 NTSTATUS status;
157 HANDLE ret;
159 attr.Length = sizeof(attr);
160 attr.RootDirectory = root;
161 attr.ObjectName = &nameW;
162 attr.Attributes = 0;
163 attr.SecurityDescriptor = NULL;
164 attr.SecurityQualityOfService = NULL;
166 status = NtCreateKey(&ret, MAXIMUM_ALLOWED, &attr, 0, NULL, options, disposition);
167 if (status == STATUS_OBJECT_NAME_NOT_FOUND)
169 static const WCHAR registry_rootW[] = { '\\','R','e','g','i','s','t','r','y','\\' };
170 DWORD pos = 0, i = 0, len = name_len / sizeof(WCHAR);
172 /* don't try to create registry root */
173 if (!root && len > ARRAY_SIZE(registry_rootW) &&
174 !memcmp(name, registry_rootW, sizeof(registry_rootW)))
175 i += ARRAY_SIZE(registry_rootW);
177 while (i < len && name[i] != '\\') i++;
178 if (i == len) return 0;
179 for (;;)
181 unsigned int subkey_options = options;
182 if (i < len) subkey_options &= ~(REG_OPTION_CREATE_LINK | REG_OPTION_OPEN_LINK);
183 nameW.Buffer = (WCHAR *)name + pos;
184 nameW.Length = (i - pos) * sizeof(WCHAR);
185 status = NtCreateKey(&ret, MAXIMUM_ALLOWED, &attr, 0, NULL, subkey_options, disposition);
187 if (attr.RootDirectory != root) NtClose(attr.RootDirectory);
188 if (!NT_SUCCESS(status)) return 0;
189 if (i == len) break;
190 attr.RootDirectory = ret;
191 while (i < len && name[i] == '\\') i++;
192 pos = i;
193 while (i < len && name[i] != '\\') i++;
196 return ret;
200 HKEY reg_create_ascii_key(HKEY root, const char *name, DWORD options, DWORD *disposition)
202 WCHAR buf[256];
203 return reg_create_key(root, buf, asciiz_to_unicode(buf, name) - sizeof(WCHAR),
204 options, disposition);
208 BOOL reg_delete_tree(HKEY parent, const WCHAR *name, ULONG name_len)
210 char buffer[4096];
211 KEY_NODE_INFORMATION *key_info = (KEY_NODE_INFORMATION *)buffer;
212 DWORD size;
213 HKEY key;
214 BOOL ret = TRUE;
216 if (!(key = reg_open_key(parent, name, name_len))) return FALSE;
218 while (ret && !NtEnumerateKey(key, 0, KeyNodeInformation, key_info, sizeof(buffer), &size))
219 ret = reg_delete_tree(key, key_info->Name, key_info->NameLength);
221 if (ret) ret = !NtDeleteKey(key);
222 NtClose(key);
223 return ret;
227 ULONG query_reg_value(HKEY hkey, const WCHAR *name, KEY_VALUE_PARTIAL_INFORMATION *info, ULONG size)
229 UNICODE_STRING str;
231 RtlInitUnicodeString(&str, name);
232 if (NtQueryValueKey(hkey, &str, KeyValuePartialInformation, info, size, &size))
233 return 0;
235 return size - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
239 /***********************************************************************
240 * get_config_key
242 * Get a config key from either the app-specific or the default config
244 static inline DWORD get_config_key(HKEY defkey, HKEY appkey, const char *name,
245 WCHAR *buffer, DWORD size)
247 WCHAR nameW[128];
248 char buf[2048];
249 KEY_VALUE_PARTIAL_INFORMATION *info = (void *)buf;
251 asciiz_to_unicode(nameW, name);
253 if (appkey && query_reg_value(appkey, nameW, info, sizeof(buf)))
255 size = min(info->DataLength, size - sizeof(WCHAR));
256 memcpy(buffer, info->Data, size);
257 buffer[size / sizeof(WCHAR)] = 0;
258 return 0;
261 if (defkey && query_reg_value(defkey, nameW, info, sizeof(buf)))
263 size = min(info->DataLength, size - sizeof(WCHAR));
264 memcpy(buffer, info->Data, size);
265 buffer[size / sizeof(WCHAR)] = 0;
266 return 0;
269 return ERROR_FILE_NOT_FOUND;
273 /***********************************************************************
274 * setup_options
276 * Set up the Mac driver options.
278 static void setup_options(void)
280 static const WCHAR macdriverW[] = {'\\','M','a','c',' ','D','r','i','v','e','r',0};
281 WCHAR buffer[MAX_PATH + 16], *p, *appname;
282 HKEY hkey, appkey = 0;
283 DWORD len;
285 /* @@ Wine registry key: HKCU\Software\Wine\Mac Driver */
286 hkey = open_hkcu_key("Software\\Wine\\Mac Driver");
288 /* open the app-specific key */
290 appname = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
291 if ((p = wcsrchr(appname, '/'))) appname = p + 1;
292 if ((p = wcsrchr(appname, '\\'))) appname = p + 1;
293 len = lstrlenW(appname);
295 if (len && len < MAX_PATH)
297 HKEY tmpkey;
298 memcpy(buffer, appname, len * sizeof(WCHAR));
299 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")))
303 appkey = reg_open_key(tmpkey, buffer, lstrlenW(buffer) * sizeof(WCHAR));
304 NtClose(tmpkey);
308 if (!get_config_key(hkey, appkey, "WindowsFloatWhenInactive", buffer, sizeof(buffer)))
310 static const WCHAR noneW[] = {'n','o','n','e',0};
311 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 topmost_float_inactive = TOPMOST_FLOAT_INACTIVE_ALL;
316 else
317 topmost_float_inactive = TOPMOST_FLOAT_INACTIVE_NONFULLSCREEN;
320 if (!get_config_key(hkey, appkey, "CaptureDisplaysForFullscreen", buffer, sizeof(buffer)))
321 capture_displays_for_fullscreen = IS_OPTION_TRUE(buffer[0]);
323 if (!get_config_key(hkey, appkey, "SkipSingleBufferFlushes", buffer, sizeof(buffer)))
324 skip_single_buffer_flushes = IS_OPTION_TRUE(buffer[0]);
326 if (!get_config_key(hkey, appkey, "AllowVerticalSync", buffer, sizeof(buffer)))
327 allow_vsync = IS_OPTION_TRUE(buffer[0]);
329 if (!get_config_key(hkey, appkey, "AllowSetGamma", buffer, sizeof(buffer)))
330 allow_set_gamma = IS_OPTION_TRUE(buffer[0]);
332 if (!get_config_key(hkey, appkey, "LeftOptionIsAlt", buffer, sizeof(buffer)))
333 left_option_is_alt = IS_OPTION_TRUE(buffer[0]);
334 if (!get_config_key(hkey, appkey, "RightOptionIsAlt", buffer, sizeof(buffer)))
335 right_option_is_alt = IS_OPTION_TRUE(buffer[0]);
337 if (!get_config_key(hkey, appkey, "LeftCommandIsCtrl", buffer, sizeof(buffer)))
338 left_command_is_ctrl = IS_OPTION_TRUE(buffer[0]);
339 if (!get_config_key(hkey, appkey, "RightCommandIsCtrl", buffer, sizeof(buffer)))
340 right_command_is_ctrl = IS_OPTION_TRUE(buffer[0]);
342 if (left_command_is_ctrl && right_command_is_ctrl && !left_option_is_alt && !right_option_is_alt)
343 WARN("Both Command keys have been mapped to Control. There is no way to "
344 "send an Alt key to Windows applications. Consider enabling "
345 "LeftOptionIsAlt or RightOptionIsAlt.\n");
347 if (!get_config_key(hkey, appkey, "AllowSoftwareRendering", buffer, sizeof(buffer)))
348 allow_software_rendering = IS_OPTION_TRUE(buffer[0]);
350 /* Value name chosen to match what's used in the X11 driver. */
351 if (!get_config_key(hkey, appkey, "Decorated", buffer, sizeof(buffer)))
352 disable_window_decorations = !IS_OPTION_TRUE(buffer[0]);
354 if (!get_config_key(hkey, appkey, "AllowImmovableWindows", buffer, sizeof(buffer)))
355 allow_immovable_windows = IS_OPTION_TRUE(buffer[0]);
357 if (!get_config_key(hkey, appkey, "UseConfinementCursorClipping", buffer, sizeof(buffer)))
358 use_confinement_cursor_clipping = IS_OPTION_TRUE(buffer[0]);
360 if (!get_config_key(hkey, appkey, "CursorClippingLocksWindows", buffer, sizeof(buffer)))
361 cursor_clipping_locks_windows = IS_OPTION_TRUE(buffer[0]);
363 if (!get_config_key(hkey, appkey, "UsePreciseScrolling", buffer, sizeof(buffer)))
364 use_precise_scrolling = IS_OPTION_TRUE(buffer[0]);
366 if (!get_config_key(hkey, appkey, "OpenGLSurfaceMode", buffer, sizeof(buffer)))
368 static const WCHAR transparentW[] = {'t','r','a','n','s','p','a','r','e','n','t',0};
369 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 gl_surface_mode = GL_SURFACE_BEHIND;
374 else
375 gl_surface_mode = GL_SURFACE_IN_FRONT_OPAQUE;
378 if (!get_config_key(hkey, appkey, "EnableAppNap", buffer, sizeof(buffer)))
379 enable_app_nap = IS_OPTION_TRUE(buffer[0]);
381 /* Don't use appkey. The DPI and monitor sizes should be consistent for all
382 processes in the prefix. */
383 if (!get_config_key(hkey, NULL, "RetinaMode", buffer, sizeof(buffer)))
384 retina_enabled = IS_OPTION_TRUE(buffer[0]);
386 retina_on = retina_enabled;
388 if (appkey) NtClose(appkey);
389 if (hkey) NtClose(hkey);
393 /***********************************************************************
394 * load_strings
396 static void load_strings(struct localized_string *str)
398 CFMutableDictionaryRef dict;
400 dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks,
401 &kCFTypeDictionaryValueCallBacks);
402 if (!dict)
404 ERR("Failed to create localized strings dictionary\n");
405 return;
408 while (str->id)
410 if (str->str && str->len)
412 const UniChar *ptr = param_ptr(str->str);
413 CFNumberRef key = CFNumberCreate(NULL, kCFNumberIntType, &str->id);
414 CFStringRef value = CFStringCreateWithCharacters(NULL, ptr, str->len);
415 if (key && value)
416 CFDictionarySetValue(dict, key, value);
417 else
418 ERR("Failed to add string ID 0x%04x %s\n", str->id, debugstr_wn(ptr, str->len));
420 else
421 ERR("Failed to load string ID 0x%04x\n", str->id);
422 str++;
425 localized_strings = dict;
429 /***********************************************************************
430 * macdrv_init
432 static NTSTATUS macdrv_init(void *arg)
434 struct init_params *params = arg;
435 SessionAttributeBits attributes;
436 OSStatus status;
438 status = SessionGetInfo(callerSecuritySession, NULL, &attributes);
439 if (status != noErr || !(attributes & sessionHasGraphicAccess))
440 return STATUS_UNSUCCESSFUL;
442 init_win_context();
443 setup_options();
444 load_strings(params->strings);
446 macdrv_err_on = ERR_ON(macdrv);
447 if (macdrv_start_cocoa_app(NtGetTickCount()))
449 ERR("Failed to start Cocoa app main loop\n");
450 return STATUS_UNSUCCESSFUL;
453 init_user_driver();
454 macdrv_init_display_devices(FALSE);
455 return STATUS_SUCCESS;
459 /***********************************************************************
460 * ThreadDetach (MACDRV.@)
462 void macdrv_ThreadDetach(void)
464 struct macdrv_thread_data *data = macdrv_thread_data();
466 if (data)
468 macdrv_destroy_event_queue(data->queue);
469 if (data->keyboard_layout_uchr)
470 CFRelease(data->keyboard_layout_uchr);
471 free(data);
472 /* clear data in case we get re-entered from user32 before the thread is truly dead */
473 NtUserGetThreadInfo()->driver_data = 0;
478 /***********************************************************************
479 * set_queue_display_fd
481 * Store the event queue fd into the message queue
483 static void set_queue_display_fd(int fd)
485 HANDLE handle;
486 int ret;
488 if (wine_server_fd_to_handle(fd, GENERIC_READ | SYNCHRONIZE, 0, &handle))
490 MESSAGE("macdrv: Can't allocate handle for event queue fd\n");
491 NtTerminateProcess(0, 1);
493 SERVER_START_REQ(set_queue_fd)
495 req->handle = wine_server_obj_handle(handle);
496 ret = wine_server_call(req);
498 SERVER_END_REQ;
499 if (ret)
501 MESSAGE("macdrv: Can't store handle for event queue fd\n");
502 NtTerminateProcess(0, 1);
504 NtClose(handle);
508 /***********************************************************************
509 * macdrv_init_thread_data
511 struct macdrv_thread_data *macdrv_init_thread_data(void)
513 struct macdrv_thread_data *data = macdrv_thread_data();
514 TISInputSourceRef input_source;
516 if (data) return data;
518 if (!(data = calloc(1, sizeof(*data))))
520 ERR("could not create data\n");
521 NtTerminateProcess(0, 1);
524 if (!(data->queue = macdrv_create_event_queue(macdrv_handle_event)))
526 ERR("macdrv: Can't create event queue.\n");
527 NtTerminateProcess(0, 1);
530 macdrv_get_input_source_info(&data->keyboard_layout_uchr, &data->keyboard_type, &data->iso_keyboard, &input_source);
531 data->active_keyboard_layout = macdrv_get_hkl_from_source(input_source);
532 CFRelease(input_source);
533 macdrv_compute_keyboard_layout(data);
535 set_queue_display_fd(macdrv_get_event_queue_fd(data->queue));
536 NtUserGetThreadInfo()->driver_data = (UINT_PTR)data;
538 NtUserActivateKeyboardLayout(data->active_keyboard_layout, 0);
539 return data;
543 /***********************************************************************
544 * SystemParametersInfo (MACDRV.@)
546 BOOL macdrv_SystemParametersInfo( UINT action, UINT int_param, void *ptr_param, UINT flags )
548 switch (action)
550 case SPI_GETSCREENSAVEACTIVE:
551 if (ptr_param)
553 CFDictionaryRef assertionStates;
554 IOReturn status = IOPMCopyAssertionsStatus(&assertionStates);
555 if (status == kIOReturnSuccess)
557 CFNumberRef count = CFDictionaryGetValue(assertionStates, kIOPMAssertionTypeNoDisplaySleep);
558 CFNumberRef count2 = CFDictionaryGetValue(assertionStates, kIOPMAssertionTypePreventUserIdleDisplaySleep);
559 long longCount = 0, longCount2 = 0;
561 if (count)
562 CFNumberGetValue(count, kCFNumberLongType, &longCount);
563 if (count2)
564 CFNumberGetValue(count2, kCFNumberLongType, &longCount2);
566 *(BOOL *)ptr_param = !longCount && !longCount2;
567 CFRelease(assertionStates);
569 else
571 WARN("Could not determine screen saver state, error code %d\n", status);
572 *(BOOL *)ptr_param = TRUE;
574 return TRUE;
576 break;
578 case SPI_SETSCREENSAVEACTIVE:
580 static IOPMAssertionID powerAssertion = kIOPMNullAssertionID;
581 if (int_param)
583 if (powerAssertion != kIOPMNullAssertionID)
585 IOPMAssertionRelease(powerAssertion);
586 powerAssertion = kIOPMNullAssertionID;
589 else if (powerAssertion == kIOPMNullAssertionID)
591 IOPMAssertionCreateWithName( kIOPMAssertionTypePreventUserIdleDisplaySleep, kIOPMAssertionLevelOn,
592 CFSTR("Wine Process requesting no screen saver"),
593 &powerAssertion);
596 break;
598 return FALSE;
602 NTSTATUS macdrv_client_func(enum macdrv_client_funcs id, const void *params, ULONG size)
604 void *ret_ptr;
605 ULONG ret_len;
606 return KeUserModeCallback(id, params, size, &ret_ptr, &ret_len);
610 static NTSTATUS macdrv_quit_result(void *arg)
612 struct quit_result_params *params = arg;
613 macdrv_quit_reply(params->result);
614 return 0;
618 const unixlib_entry_t __wine_unix_call_funcs[] =
620 macdrv_dnd_get_data,
621 macdrv_dnd_get_formats,
622 macdrv_dnd_have_format,
623 macdrv_dnd_release,
624 macdrv_dnd_retain,
625 macdrv_init,
626 macdrv_notify_icon,
627 macdrv_quit_result,
630 C_ASSERT( ARRAYSIZE(__wine_unix_call_funcs) == unix_funcs_count );
632 #ifdef _WIN64
634 static NTSTATUS wow64_dnd_get_data(void *arg)
636 struct
638 UINT64 handle;
639 UINT format;
640 ULONG size;
641 ULONG data;
642 } *params32 = arg;
643 struct dnd_get_data_params params;
645 params.handle = params32->handle;
646 params.format = params32->format;
647 params.size = params32->size;
648 params.data = UlongToPtr(params32->data);
649 return macdrv_dnd_get_data(&params);
652 static NTSTATUS wow64_init(void *arg)
654 struct
656 ULONG strings;
657 } *params32 = arg;
658 struct init_params params;
660 params.strings = UlongToPtr(params32->strings);
661 return macdrv_init(&params);
664 static NTSTATUS wow64_notify_icon(void *arg)
666 struct
668 DWORD msg;
669 ULONG data;
670 } *params32 = arg;
671 struct
673 DWORD cbSize;
674 ULONG hWnd;
675 UINT uID;
676 UINT uFlags;
677 UINT uCallbackMessage;
678 ULONG hIcon;
679 WCHAR szTip[128];
680 DWORD dwState;
681 DWORD dwStateMask;
682 WCHAR szInfo[256];
683 UINT uTimeout;
684 WCHAR szInfoTitle[64];
685 DWORD dwInfoFlags;
686 GUID guidItem;
687 ULONG hBalloonIcon;
688 } *data32 = UlongToPtr(params32->data);
690 struct notify_icon_params params;
691 NOTIFYICONDATAW data;
693 params.msg = params32->msg;
694 params.data = &data;
696 data.cbSize = sizeof(data);
697 data.hWnd = UlongToHandle(data32->hWnd);
698 data.uID = data32->uID;
699 data.uFlags = data32->uFlags;
700 data.uCallbackMessage = data32->uCallbackMessage;
701 data.hIcon = UlongToHandle(data32->hIcon);
702 if (data.uFlags & NIF_TIP)
703 wcscpy(data.szTip, data32->szTip);
704 data.dwState = data32->dwState;
705 data.dwStateMask = data32->dwStateMask;
706 if (data.uFlags & NIF_INFO)
708 wcscpy(data.szInfoTitle, data32->szInfoTitle);
709 wcscpy(data.szInfo, data32->szInfo);
710 data.uTimeout = data32->uTimeout;
711 data.dwInfoFlags = data32->dwInfoFlags;
713 data.guidItem = data32->guidItem;
714 data.hBalloonIcon = UlongToHandle(data32->hBalloonIcon);
716 return macdrv_notify_icon(&params);
719 const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
721 wow64_dnd_get_data,
722 macdrv_dnd_get_formats,
723 macdrv_dnd_have_format,
724 macdrv_dnd_release,
725 macdrv_dnd_retain,
726 wow64_init,
727 wow64_notify_icon,
728 macdrv_quit_result,
731 C_ASSERT( ARRAYSIZE(__wine_unix_call_wow64_funcs) == unix_funcs_count );
733 #endif /* _WIN64 */