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
29 #include <Security/AuthSession.h>
30 #include <IOKit/pwr_mgt/IOPMLib.h>
33 #define WIN32_NO_STATUS
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 /**************************************************************************
70 const char* debugstr_cf(CFTypeRef t
)
75 if (!t
) return "(null)";
77 if (CFGetTypeID(t
) == CFStringGetTypeID())
80 s
= CFCopyDescription(t
);
81 ret
= CFStringGetCStringPtr(s
, kCFStringEncodingUTF8
);
82 if (ret
) ret
= debugstr_a(ret
);
85 const UniChar
* u
= CFStringGetCharactersPtr(s
);
87 ret
= debugstr_wn((const WCHAR
*)u
, CFStringGetLength(s
));
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
);
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
;
107 attr
.Length
= sizeof(attr
);
108 attr
.RootDirectory
= root
;
109 attr
.ObjectName
= &nameW
;
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
)
126 DWORD_PTR sid_data
[(sizeof(TOKEN_USER
) + SECURITY_MAX_SID_SIZE
) / sizeof(DWORD_PTR
)];
127 DWORD i
, len
= sizeof(sid_data
);
130 if (NtQueryInformationToken(GetCurrentThreadEffectiveToken(), TokenUser
, sid_data
, len
, &len
))
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
;
159 attr
.Length
= sizeof(attr
);
160 attr
.RootDirectory
= root
;
161 attr
.ObjectName
= &nameW
;
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;
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;
190 attr
.RootDirectory
= ret
;
191 while (i
< len
&& name
[i
] == '\\') i
++;
193 while (i
< len
&& name
[i
] != '\\') i
++;
200 HKEY
reg_create_ascii_key(HKEY root
, const char *name
, DWORD options
, DWORD
*disposition
)
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
)
211 KEY_NODE_INFORMATION
*key_info
= (KEY_NODE_INFORMATION
*)buffer
;
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
);
227 ULONG
query_reg_value(HKEY hkey
, const WCHAR
*name
, KEY_VALUE_PARTIAL_INFORMATION
*info
, ULONG size
)
231 RtlInitUnicodeString(&str
, name
);
232 if (NtQueryValueKey(hkey
, &str
, KeyValuePartialInformation
, info
, size
, &size
))
235 return size
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
);
239 /***********************************************************************
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
)
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;
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;
269 return ERROR_FILE_NOT_FOUND
;
273 /***********************************************************************
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;
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
)
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
));
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
;
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
;
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 /***********************************************************************
396 static void load_strings(struct localized_string
*str
)
398 CFMutableDictionaryRef dict
;
400 dict
= CFDictionaryCreateMutable(NULL
, 0, &kCFTypeDictionaryKeyCallBacks
,
401 &kCFTypeDictionaryValueCallBacks
);
404 ERR("Failed to create localized strings dictionary\n");
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
);
416 CFDictionarySetValue(dict
, key
, value
);
418 ERR("Failed to add string ID 0x%04x %s\n", str
->id
, debugstr_wn(ptr
, str
->len
));
421 ERR("Failed to load string ID 0x%04x\n", str
->id
);
425 localized_strings
= dict
;
429 /***********************************************************************
432 static NTSTATUS
macdrv_init(void *arg
)
434 struct init_params
*params
= arg
;
435 SessionAttributeBits attributes
;
438 status
= SessionGetInfo(callerSecuritySession
, NULL
, &attributes
);
439 if (status
!= noErr
|| !(attributes
& sessionHasGraphicAccess
))
440 return STATUS_UNSUCCESSFUL
;
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
;
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();
468 macdrv_destroy_event_queue(data
->queue
);
469 if (data
->keyboard_layout_uchr
)
470 CFRelease(data
->keyboard_layout_uchr
);
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
)
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
);
501 MESSAGE("macdrv: Can't store handle for event queue fd\n");
502 NtTerminateProcess(0, 1);
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);
543 /***********************************************************************
544 * SystemParametersInfo (MACDRV.@)
546 BOOL
macdrv_SystemParametersInfo( UINT action
, UINT int_param
, void *ptr_param
, UINT flags
)
550 case SPI_GETSCREENSAVEACTIVE
:
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;
562 CFNumberGetValue(count
, kCFNumberLongType
, &longCount
);
564 CFNumberGetValue(count2
, kCFNumberLongType
, &longCount2
);
566 *(BOOL
*)ptr_param
= !longCount
&& !longCount2
;
567 CFRelease(assertionStates
);
571 WARN("Could not determine screen saver state, error code %d\n", status
);
572 *(BOOL
*)ptr_param
= TRUE
;
578 case SPI_SETSCREENSAVEACTIVE
:
580 static IOPMAssertionID powerAssertion
= kIOPMNullAssertionID
;
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"),
602 NTSTATUS
macdrv_client_func(enum macdrv_client_funcs id
, const void *params
, ULONG size
)
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
);
618 const unixlib_entry_t __wine_unix_call_funcs
[] =
621 macdrv_dnd_get_formats
,
622 macdrv_dnd_have_format
,
630 C_ASSERT( ARRAYSIZE(__wine_unix_call_funcs
) == unix_funcs_count
);
634 static NTSTATUS
wow64_dnd_get_data(void *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(¶ms
);
652 static NTSTATUS
wow64_init(void *arg
)
658 struct init_params params
;
660 params
.strings
= UlongToPtr(params32
->strings
);
661 return macdrv_init(¶ms
);
664 static NTSTATUS
wow64_notify_icon(void *arg
)
677 UINT uCallbackMessage
;
684 WCHAR szInfoTitle
[64];
688 } *data32
= UlongToPtr(params32
->data
);
690 struct notify_icon_params params
;
691 NOTIFYICONDATAW data
;
693 params
.msg
= params32
->msg
;
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(¶ms
);
719 const unixlib_entry_t __wine_unix_call_wow64_funcs
[] =
722 macdrv_dnd_get_formats
,
723 macdrv_dnd_have_format
,
731 C_ASSERT( ARRAYSIZE(__wine_unix_call_wow64_funcs
) == unix_funcs_count
);