strmbase: Fixed user-after-free (Coverity).
[wine] / dlls / winemac.drv / macdrv_main.c
1 /*
2  * MACDRV initialization code
3  *
4  * Copyright 1998 Patrik Stridvall
5  * Copyright 2000 Alexandre Julliard
6  * Copyright 2011, 2012, 2013 Ken Thomases for CodeWeavers Inc.
7  *
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.
12  *
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.
17  *
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
21  */
22 #include "config.h"
23
24 #include <Security/AuthSession.h>
25
26 #include "macdrv.h"
27 #include "wine/server.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
30
31
32 DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
33
34
35 /**************************************************************************
36  *              debugstr_cf
37  */
38 const char* debugstr_cf(CFTypeRef t)
39 {
40     CFStringRef s;
41     const char* ret;
42
43     if (!t) return "(null)";
44
45     if (CFGetTypeID(t) == CFStringGetTypeID())
46         s = t;
47     else
48         s = CFCopyDescription(t);
49     ret = CFStringGetCStringPtr(s, kCFStringEncodingUTF8);
50     if (ret) ret = debugstr_a(ret);
51     if (!ret)
52     {
53         const UniChar* u = CFStringGetCharactersPtr(s);
54         if (u)
55             ret = debugstr_wn((const WCHAR*)u, CFStringGetLength(s));
56     }
57     if (!ret)
58     {
59         UniChar buf[200];
60         int len = min(CFStringGetLength(s), sizeof(buf)/sizeof(buf[0]));
61         CFStringGetCharacters(s, CFRangeMake(0, len), buf);
62         ret = debugstr_wn(buf, len);
63     }
64     if (s != t) CFRelease(s);
65     return ret;
66 }
67
68
69 /***********************************************************************
70  *              set_app_icon
71  */
72 static void set_app_icon(void)
73 {
74     CFArrayRef images = create_app_icon_images();
75     if (images)
76     {
77         macdrv_set_application_icon(images);
78         CFRelease(images);
79     }
80 }
81
82
83 /***********************************************************************
84  *              process_attach
85  */
86 static BOOL process_attach(void)
87 {
88     SessionAttributeBits attributes;
89     OSStatus status;
90
91     assert(NUM_EVENT_TYPES <= sizeof(macdrv_event_mask) * 8);
92
93     status = SessionGetInfo(callerSecuritySession, NULL, &attributes);
94     if (status != noErr || !(attributes & sessionHasGraphicAccess))
95         return FALSE;
96
97     if ((thread_data_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE;
98
99     macdrv_err_on = ERR_ON(macdrv);
100     if (macdrv_start_cocoa_app(GetTickCount64()))
101     {
102         ERR("Failed to start Cocoa app main loop\n");
103         return FALSE;
104     }
105
106     set_app_icon();
107     macdrv_clipboard_process_attach();
108
109     return TRUE;
110 }
111
112
113 /***********************************************************************
114  *              thread_detach
115  */
116 static void thread_detach(void)
117 {
118     struct macdrv_thread_data *data = macdrv_thread_data();
119
120     if (data)
121     {
122         macdrv_destroy_event_queue(data->queue);
123         if (data->keyboard_layout_uchr)
124             CFRelease(data->keyboard_layout_uchr);
125         HeapFree(GetProcessHeap(), 0, data);
126     }
127 }
128
129
130 /***********************************************************************
131  *              set_queue_display_fd
132  *
133  * Store the event queue fd into the message queue
134  */
135 static void set_queue_display_fd(int fd)
136 {
137     HANDLE handle;
138     int ret;
139
140     if (wine_server_fd_to_handle(fd, GENERIC_READ | SYNCHRONIZE, 0, &handle))
141     {
142         MESSAGE("macdrv: Can't allocate handle for event queue fd\n");
143         ExitProcess(1);
144     }
145     SERVER_START_REQ(set_queue_fd)
146     {
147         req->handle = wine_server_obj_handle(handle);
148         ret = wine_server_call(req);
149     }
150     SERVER_END_REQ;
151     if (ret)
152     {
153         MESSAGE("macdrv: Can't store handle for event queue fd\n");
154         ExitProcess(1);
155     }
156     CloseHandle(handle);
157 }
158
159
160 /***********************************************************************
161  *              macdrv_init_thread_data
162  */
163 struct macdrv_thread_data *macdrv_init_thread_data(void)
164 {
165     struct macdrv_thread_data *data = macdrv_thread_data();
166
167     if (data) return data;
168
169     if (!(data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data))))
170     {
171         ERR("could not create data\n");
172         ExitProcess(1);
173     }
174
175     if (!(data->queue = macdrv_create_event_queue(macdrv_handle_event)))
176     {
177         ERR("macdrv: Can't create event queue.\n");
178         ExitProcess(1);
179     }
180
181     data->keyboard_layout_uchr = macdrv_copy_keyboard_layout(&data->keyboard_type, &data->iso_keyboard);
182     macdrv_compute_keyboard_layout(data);
183
184     set_queue_display_fd(macdrv_get_event_queue_fd(data->queue));
185     TlsSetValue(thread_data_tls_index, data);
186
187     return data;
188 }
189
190
191 /***********************************************************************
192  *              DllMain
193  */
194 BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
195 {
196     BOOL ret = TRUE;
197
198     switch(reason)
199     {
200     case DLL_PROCESS_ATTACH:
201         ret = process_attach();
202         break;
203     case DLL_THREAD_DETACH:
204         thread_detach();
205         break;
206     }
207     return ret;
208 }