2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 #include <mach/port.h>
24 #include <mach/message.h>
25 #include <mach/kern_return.h>
26 #include <mach/etap_events.h>
28 #include <kern/host.h>
29 #include <ipc/ipc_port.h>
30 #include <kern/ipc_kobject.h>
32 #include <UserNotification/UNDTypes.h>
33 #include <UserNotification/UNDRequest.h>
34 #include <UserNotification/UNDReplyServer.h>
35 #include <UserNotification/KUNCUserNotifications.h>
39 #include <IOKit/IOCFSerialize.h>
40 #include <IOKit/IOCFUnserialize.h>
44 * DEFINES AND STRUCTURES
48 decl_mutex_data(,lock
) /* UNDReply lock */
49 int userLandNotificationKey
;
50 KUNCUserNotificationCallBack callback
;
52 ipc_port_t self_port
; /* Our port */
55 #define UNDReply_lock(reply) mutex_lock(&reply->lock)
56 #define UNDReply_lock_try(reply) mutex_lock_try(&(reply)->lock)
57 #define UNDReply_unlock(reply) mutex_unlock(&(reply)->lock)
66 port
= reply
->self_port
;
67 assert(IP_VALID(port
));
68 ipc_kobject_set(port
, IKO_NULL
, IKOT_NONE
);
69 reply
->self_port
= IP_NULL
;
70 UNDReply_unlock(reply
);
72 ipc_port_dealloc_kernel(port
);
73 kfree((vm_offset_t
)reply
, sizeof(struct UNDReply
));
78 UNDServer_reference(void)
80 UNDServerRef UNDServer
;
83 kr
= host_get_user_notification_port(host_priv_self(), &UNDServer
);
84 assert(kr
== KERN_SUCCESS
);
90 UNDServerRef UNDServer
)
92 if (IP_VALID(UNDServer
))
93 ipc_port_release_send(UNDServer
);
101 UNDAlertCompletedWithResult_rpc (
104 xmlData_t keyRef
, /* raw XML bytes */
105 mach_msg_type_number_t keyLen
)
108 CFStringRef xmlError
= NULL
;
109 CFDictionaryRef dict
= NULL
;
111 void *dict
= (void *)keyRef
;
114 if (reply
== UND_REPLY_NULL
|| !reply
->inprogress
)
115 return KERN_INVALID_ARGUMENT
;
118 * JMM - No C vesion of the Unserialize code in-kernel
119 * and no C type for a CFDictionary either. For now,
120 * just pass the raw keyRef through.
123 if (keyRef
&& keyLen
) {
124 dict
= IOCFUnserialize(keyRef
, NULL
, NULL
, &xmlError
);
131 #endif /* KERNEL_CF */
133 if (reply
->callback
) {
134 (reply
->callback
)((KUNCUserNotificationID
) reply
, result
, dict
);
137 UNDReply_lock(reply
);
138 reply
->inprogress
= FALSE
;
139 reply
->userLandNotificationKey
= -1;
140 UNDReply_unlock(reply
);
141 UNDReply_deallocate(reply
);
146 * Routine: UNDNotificationCreated_rpc
148 * Intermediate routine. Allows the kernel mechanism
149 * to be informed that the notification request IS
150 * being processed by the user-level daemon, and how
151 * to identify that request.
154 UNDNotificationCreated_rpc (
156 int userLandNotificationKey
)
158 if (reply
== UND_REPLY_NULL
)
159 return KERN_INVALID_ARGUMENT
;
161 UNDReply_lock(reply
);
162 if (reply
->inprogress
|| reply
->userLandNotificationKey
!= -1) {
163 UNDReply_unlock(reply
);
164 return KERN_INVALID_ARGUMENT
;
166 reply
->userLandNotificationKey
= userLandNotificationKey
;
167 UNDReply_unlock(reply
);
176 KUNCUserNotificationID
177 KUNCGetNotificationID()
181 reply
= (UNDReplyRef
) kalloc(sizeof(struct UNDReply
));
182 if (reply
!= UND_REPLY_NULL
) {
183 reply
->self_port
= ipc_port_alloc_kernel();
184 if (reply
->self_port
== IP_NULL
) {
185 kfree((vm_offset_t
)reply
, sizeof(struct UNDReply
));
186 reply
= UND_REPLY_NULL
;
188 mutex_init(&reply
->lock
, ETAP_IO_UNDREPLY
);
189 reply
->userLandNotificationKey
= -1;
190 reply
->inprogress
= FALSE
;
191 ipc_kobject_set(reply
->self_port
,
192 (ipc_kobject_t
)reply
,
196 return (KUNCUserNotificationID
) reply
;
200 kern_return_t
KUNCExecute(char executionPath
[1024], int uid
, int gid
)
203 UNDServerRef UNDServer
;
205 UNDServer
= UNDServer_reference();
206 if (IP_VALID(UNDServer
)) {
208 kr
= UNDExecute_rpc(UNDServer
, executionPath
, uid
, gid
);
209 UNDServer_deallocate(UNDServer
);
212 return MACH_SEND_INVALID_DEST
;
215 kern_return_t
KUNCUserNotificationCancel(
216 KUNCUserNotificationID id
)
218 UNDReplyRef reply
= (UNDReplyRef
)id
;
222 if (reply
== UND_REPLY_NULL
)
223 return KERN_INVALID_ARGUMENT
;
225 UNDReply_lock(reply
);
226 if (!reply
->inprogress
) {
227 UNDReply_unlock(reply
);
228 return KERN_INVALID_ARGUMENT
;
231 reply
->inprogress
= FALSE
;
232 if (ulkey
= reply
->userLandNotificationKey
) {
233 UNDServerRef UNDServer
;
235 reply
->userLandNotificationKey
= 0;
236 UNDReply_unlock(reply
);
238 UNDServer
= UNDServer_reference();
239 if (IP_VALID(UNDServer
)) {
240 kr
= UNDCancelNotification_rpc(UNDServer
,ulkey
);
241 UNDServer_deallocate(UNDServer
);
243 kr
= MACH_SEND_INVALID_DEST
;
245 UNDReply_unlock(reply
);
248 UNDReply_deallocate(reply
);
253 KUNCUserNotificationDisplayNotice(
258 char *localizationPath
,
261 char *defaultButtonTitle
)
263 UNDServerRef UNDServer
;
265 UNDServer
= UNDServer_reference();
266 if (IP_VALID(UNDServer
)) {
268 kr
= UNDDisplayNoticeSimple_rpc(UNDServer
,
277 UNDServer_deallocate(UNDServer
);
280 return MACH_SEND_INVALID_DEST
;
284 KUNCUserNotificationDisplayAlert(
289 char *localizationPath
,
292 char *defaultButtonTitle
,
293 char *alternateButtonTitle
,
294 char *otherButtonTitle
,
295 unsigned *responseFlags
)
297 UNDServerRef UNDServer
;
299 UNDServer
= UNDServer_reference();
300 if (IP_VALID(UNDServer
)) {
302 kr
= UNDDisplayAlertSimple_rpc(UNDServer
,
311 alternateButtonTitle
,
314 UNDServer_deallocate(UNDServer
);
317 return MACH_SEND_INVALID_DEST
;
321 KUNCUserNotificationDisplayFromBundle(
322 KUNCUserNotificationID id
,
328 KUNCUserNotificationCallBack callback
,
331 UNDReplyRef reply
= (UNDReplyRef
)id
;
332 UNDServerRef UNDServer
;
333 ipc_port_t reply_port
;
335 if (reply
== UND_REPLY_NULL
)
336 return KERN_INVALID_ARGUMENT
;
337 UNDReply_lock(reply
);
338 if (reply
->inprogress
== TRUE
|| reply
->userLandNotificationKey
!= -1) {
339 UNDReply_unlock(reply
);
340 return KERN_INVALID_ARGUMENT
;
342 reply
->inprogress
== TRUE
;
343 reply
->callback
= callback
;
344 reply_port
= ipc_port_make_send(reply
->self_port
);
345 UNDReply_unlock(reply
);
347 UNDServer
= UNDServer_reference();
348 if (IP_VALID(UNDServer
)) {
351 kr
= UNDDisplayCustomFromBundle_rpc(UNDServer
,
358 UNDServer_deallocate(UNDServer
);
361 return MACH_SEND_INVALID_DEST
;
365 * Routine: convert_port_to_UNDReply
367 * MIG helper routine to convert from a mach port to a
374 convert_port_to_UNDReply(
377 if (IP_VALID(port
)) {
381 if (!ip_active(port
) || (ip_kotype(port
) != IKOT_UND_REPLY
)) {
383 return UND_REPLY_NULL
;
385 reply
= (UNDReplyRef
) port
->ip_kobject
;
386 assert(reply
!= UND_REPLY_NULL
);
390 return UND_REPLY_NULL
;
394 * User interface for setting the host UserNotification Daemon port.
399 host_priv_t host_priv
,
402 return (host_set_user_notification_port(host_priv
, server
));
406 * User interface for retrieving the UserNotification Daemon port.
411 host_priv_t host_priv
,
412 UNDServerRef
*serverp
)
414 return (host_get_user_notification_port(host_priv
, serverp
));