2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 #include <mach/port.h>
27 #include <mach/message.h>
28 #include <mach/kern_return.h>
29 #include <mach/etap_events.h>
31 #include <kern/host.h>
32 #include <ipc/ipc_port.h>
33 #include <kern/ipc_kobject.h>
35 #include <UserNotification/UNDTypes.h>
36 #include <UserNotification/UNDRequest.h>
37 #include <UserNotification/UNDReplyServer.h>
38 #include <UserNotification/KUNCUserNotifications.h>
42 #include <IOKit/IOCFSerialize.h>
43 #include <IOKit/IOCFUnserialize.h>
47 * DEFINES AND STRUCTURES
51 decl_mutex_data(,lock
) /* UNDReply lock */
52 int userLandNotificationKey
;
53 KUNCUserNotificationCallBack callback
;
55 ipc_port_t self_port
; /* Our port */
58 #define UNDReply_lock(reply) mutex_lock(&reply->lock)
59 #define UNDReply_lock_try(reply) mutex_lock_try(&(reply)->lock)
60 #define UNDReply_unlock(reply) mutex_unlock(&(reply)->lock)
69 port
= reply
->self_port
;
70 assert(IP_VALID(port
));
71 ipc_kobject_set(port
, IKO_NULL
, IKOT_NONE
);
72 reply
->self_port
= IP_NULL
;
73 UNDReply_unlock(reply
);
75 ipc_port_dealloc_kernel(port
);
76 kfree((vm_offset_t
)reply
, sizeof(struct UNDReply
));
81 UNDServer_reference(void)
83 UNDServerRef UNDServer
;
86 kr
= host_get_user_notification_port(host_priv_self(), &UNDServer
);
87 assert(kr
== KERN_SUCCESS
);
93 UNDServerRef UNDServer
)
95 if (IP_VALID(UNDServer
))
96 ipc_port_release_send(UNDServer
);
104 UNDAlertCompletedWithResult_rpc (
107 xmlData_t keyRef
, /* raw XML bytes */
108 mach_msg_type_number_t keyLen
)
111 CFStringRef xmlError
= NULL
;
112 CFDictionaryRef dict
= NULL
;
114 void *dict
= (void *)keyRef
;
117 if (reply
== UND_REPLY_NULL
|| !reply
->inprogress
)
118 return KERN_INVALID_ARGUMENT
;
121 * JMM - No C vesion of the Unserialize code in-kernel
122 * and no C type for a CFDictionary either. For now,
123 * just pass the raw keyRef through.
126 if (keyRef
&& keyLen
) {
127 dict
= IOCFUnserialize(keyRef
, NULL
, NULL
, &xmlError
);
134 #endif /* KERNEL_CF */
136 if (reply
->callback
) {
137 (reply
->callback
)((KUNCUserNotificationID
) reply
, result
, dict
);
140 UNDReply_lock(reply
);
141 reply
->inprogress
= FALSE
;
142 reply
->userLandNotificationKey
= -1;
143 UNDReply_unlock(reply
);
144 UNDReply_deallocate(reply
);
149 * Routine: UNDNotificationCreated_rpc
151 * Intermediate routine. Allows the kernel mechanism
152 * to be informed that the notification request IS
153 * being processed by the user-level daemon, and how
154 * to identify that request.
157 UNDNotificationCreated_rpc (
159 int userLandNotificationKey
)
161 if (reply
== UND_REPLY_NULL
)
162 return KERN_INVALID_ARGUMENT
;
164 UNDReply_lock(reply
);
165 if (reply
->inprogress
|| reply
->userLandNotificationKey
!= -1) {
166 UNDReply_unlock(reply
);
167 return KERN_INVALID_ARGUMENT
;
169 reply
->userLandNotificationKey
= userLandNotificationKey
;
170 UNDReply_unlock(reply
);
179 KUNCUserNotificationID
180 KUNCGetNotificationID()
184 reply
= (UNDReplyRef
) kalloc(sizeof(struct UNDReply
));
185 if (reply
!= UND_REPLY_NULL
) {
186 reply
->self_port
= ipc_port_alloc_kernel();
187 if (reply
->self_port
== IP_NULL
) {
188 kfree((vm_offset_t
)reply
, sizeof(struct UNDReply
));
189 reply
= UND_REPLY_NULL
;
191 mutex_init(&reply
->lock
, ETAP_IO_UNDREPLY
);
192 reply
->userLandNotificationKey
= -1;
193 reply
->inprogress
= FALSE
;
194 ipc_kobject_set(reply
->self_port
,
195 (ipc_kobject_t
)reply
,
199 return (KUNCUserNotificationID
) reply
;
203 kern_return_t
KUNCExecute(char executionPath
[1024], int uid
, int gid
)
206 UNDServerRef UNDServer
;
208 UNDServer
= UNDServer_reference();
209 if (IP_VALID(UNDServer
)) {
211 kr
= UNDExecute_rpc(UNDServer
, executionPath
, uid
, gid
);
212 UNDServer_deallocate(UNDServer
);
215 return MACH_SEND_INVALID_DEST
;
218 kern_return_t
KUNCUserNotificationCancel(
219 KUNCUserNotificationID id
)
221 UNDReplyRef reply
= (UNDReplyRef
)id
;
225 if (reply
== UND_REPLY_NULL
)
226 return KERN_INVALID_ARGUMENT
;
228 UNDReply_lock(reply
);
229 if (!reply
->inprogress
) {
230 UNDReply_unlock(reply
);
231 return KERN_INVALID_ARGUMENT
;
234 reply
->inprogress
= FALSE
;
235 if (ulkey
= reply
->userLandNotificationKey
) {
236 UNDServerRef UNDServer
;
238 reply
->userLandNotificationKey
= 0;
239 UNDReply_unlock(reply
);
241 UNDServer
= UNDServer_reference();
242 if (IP_VALID(UNDServer
)) {
243 kr
= UNDCancelNotification_rpc(UNDServer
,ulkey
);
244 UNDServer_deallocate(UNDServer
);
246 kr
= MACH_SEND_INVALID_DEST
;
248 UNDReply_unlock(reply
);
251 UNDReply_deallocate(reply
);
256 KUNCUserNotificationDisplayNotice(
261 char *localizationPath
,
264 char *defaultButtonTitle
)
266 UNDServerRef UNDServer
;
268 UNDServer
= UNDServer_reference();
269 if (IP_VALID(UNDServer
)) {
271 kr
= UNDDisplayNoticeSimple_rpc(UNDServer
,
280 UNDServer_deallocate(UNDServer
);
283 return MACH_SEND_INVALID_DEST
;
287 KUNCUserNotificationDisplayAlert(
292 char *localizationPath
,
295 char *defaultButtonTitle
,
296 char *alternateButtonTitle
,
297 char *otherButtonTitle
,
298 unsigned *responseFlags
)
300 UNDServerRef UNDServer
;
302 UNDServer
= UNDServer_reference();
303 if (IP_VALID(UNDServer
)) {
305 kr
= UNDDisplayAlertSimple_rpc(UNDServer
,
314 alternateButtonTitle
,
317 UNDServer_deallocate(UNDServer
);
320 return MACH_SEND_INVALID_DEST
;
324 KUNCUserNotificationDisplayFromBundle(
325 KUNCUserNotificationID id
,
331 KUNCUserNotificationCallBack callback
,
334 UNDReplyRef reply
= (UNDReplyRef
)id
;
335 UNDServerRef UNDServer
;
336 ipc_port_t reply_port
;
338 if (reply
== UND_REPLY_NULL
)
339 return KERN_INVALID_ARGUMENT
;
340 UNDReply_lock(reply
);
341 if (reply
->inprogress
== TRUE
|| reply
->userLandNotificationKey
!= -1) {
342 UNDReply_unlock(reply
);
343 return KERN_INVALID_ARGUMENT
;
345 reply
->inprogress
== TRUE
;
346 reply
->callback
= callback
;
347 reply_port
= ipc_port_make_send(reply
->self_port
);
348 UNDReply_unlock(reply
);
350 UNDServer
= UNDServer_reference();
351 if (IP_VALID(UNDServer
)) {
354 kr
= UNDDisplayCustomFromBundle_rpc(UNDServer
,
361 UNDServer_deallocate(UNDServer
);
364 return MACH_SEND_INVALID_DEST
;
368 * Routine: convert_port_to_UNDReply
370 * MIG helper routine to convert from a mach port to a
377 convert_port_to_UNDReply(
380 if (IP_VALID(port
)) {
384 if (!ip_active(port
) || (ip_kotype(port
) != IKOT_UND_REPLY
)) {
386 return UND_REPLY_NULL
;
388 reply
= (UNDReplyRef
) port
->ip_kobject
;
389 assert(reply
!= UND_REPLY_NULL
);
393 return UND_REPLY_NULL
;
397 * User interface for setting the host UserNotification Daemon port.
402 host_priv_t host_priv
,
405 return (host_set_user_notification_port(host_priv
, server
));
409 * User interface for retrieving the UserNotification Daemon port.
414 host_priv_t host_priv
,
415 UNDServerRef
*serverp
)
417 return (host_get_user_notification_port(host_priv
, serverp
));