2 * Copyright (c) 2000 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
50 UNDServerRef gUNDServer
= UND_SERVER_NULL
;
54 decl_mutex_data(,lock
) /* UNDReply lock */
55 int userLandNotificationKey
;
56 KUNCUserNotificationCallBack callback
;
58 ipc_port_t self_port
; /* Our port */
61 #define UNDReply_lock(reply) mutex_lock(&reply->lock)
62 #define UNDReply_lock_try(reply) mutex_lock_try(&(reply)->lock)
63 #define UNDReply_unlock(reply) mutex_unlock(&(reply)->lock)
71 port
= reply
->self_port
;
72 ipc_kobject_set(port
, IKO_NULL
, IKOT_NONE
);
73 reply
->self_port
= IP_NULL
;
74 UNDReply_unlock(reply
);
76 ipc_port_dealloc_kernel(port
);
77 kfree((vm_offset_t
)reply
, sizeof(struct UNDReply
));
86 UNDAlertCompletedWithResult_rpc (
89 xmlData_t keyRef
, /* raw XML bytes */
90 mach_msg_type_number_t keyLen
)
93 CFStringRef xmlError
= NULL
;
94 CFDictionaryRef dict
= NULL
;
96 void *dict
= (void *)keyRef
;
99 if (reply
== UND_REPLY_NULL
|| !reply
->inprogress
)
100 return KERN_INVALID_ARGUMENT
;
103 * JMM - No C vesion of the Unserialize code in-kernel
104 * and no C type for a CFDictionary either. For now,
105 * just pass the raw keyRef through.
108 if (keyRef
&& keyLen
) {
109 dict
= IOCFUnserialize(keyRef
, NULL
, NULL
, &xmlError
);
116 #endif /* KERNEL_CF */
118 if (reply
->callback
) {
119 (reply
->callback
)((KUNCUserNotificationID
) reply
, result
, dict
);
122 UNDReply_lock(reply
);
123 reply
->inprogress
= FALSE
;
124 reply
->userLandNotificationKey
= -1;
125 UNDReply_unlock(reply
);
126 UNDReply_deallocate(reply
);
131 * Routine: UNDNotificationCreated_rpc
133 * Intermediate routine. Allows the kernel mechanism
134 * to be informed that the notification request IS
135 * being processed by the user-level daemon, and how
136 * to identify that request.
139 UNDNotificationCreated_rpc (
141 int userLandNotificationKey
)
143 if (reply
== UND_REPLY_NULL
)
144 return KERN_INVALID_ARGUMENT
;
146 UNDReply_lock(reply
);
147 if (reply
->inprogress
|| reply
->userLandNotificationKey
!= -1) {
148 UNDReply_unlock(reply
);
149 return KERN_INVALID_ARGUMENT
;
151 reply
->userLandNotificationKey
= userLandNotificationKey
;
152 UNDReply_unlock(reply
);
161 KUNCUserNotificationID
162 KUNCGetNotificationID()
166 reply
= (UNDReplyRef
) kalloc(sizeof(struct UNDReply
));
167 if (reply
!= UND_REPLY_NULL
) {
168 reply
->self_port
= ipc_port_alloc_kernel();
169 if (reply
->self_port
== IP_NULL
) {
170 kfree((vm_offset_t
)reply
, sizeof(struct UNDReply
));
171 reply
= UND_REPLY_NULL
;
173 mutex_init(&reply
->lock
, ETAP_IO_UNDREPLY
);
174 reply
->userLandNotificationKey
= -1;
175 reply
->inprogress
= FALSE
;
176 ipc_kobject_set(reply
->self_port
,
177 (ipc_kobject_t
)reply
,
181 return (KUNCUserNotificationID
) reply
;
185 kern_return_t
KUNCExecute(char executionPath
[1024], int uid
, int gid
)
187 return UNDExecute_rpc(gUNDServer
, executionPath
, uid
, gid
);
190 kern_return_t
KUNCUserNotificationCancel(
191 KUNCUserNotificationID id
)
193 UNDReplyRef reply
= (UNDReplyRef
)id
;
197 if (reply
== UND_REPLY_NULL
)
198 return KERN_INVALID_ARGUMENT
;
200 UNDReply_lock(reply
);
201 if (!reply
->inprogress
) {
202 UNDReply_unlock(reply
);
203 return KERN_INVALID_ARGUMENT
;
206 reply
->inprogress
= FALSE
;
207 if (ulkey
= reply
->userLandNotificationKey
) {
208 reply
->userLandNotificationKey
= 0;
209 UNDReply_unlock(reply
);
210 kr
= UNDCancelNotification_rpc(gUNDServer
,ulkey
);
212 UNDReply_unlock(reply
);
215 UNDReply_deallocate(reply
);
220 KUNCUserNotificationDisplayNotice(
225 char *localizationPath
,
228 char *defaultButtonTitle
)
231 kr
= UNDDisplayNoticeSimple_rpc(gUNDServer
,
244 KUNCUserNotificationDisplayAlert(
249 char *localizationPath
,
252 char *defaultButtonTitle
,
253 char *alternateButtonTitle
,
254 char *otherButtonTitle
,
255 unsigned *responseFlags
)
259 kr
= UNDDisplayAlertSimple_rpc(gUNDServer
,
268 alternateButtonTitle
,
275 KUNCUserNotificationDisplayFromBundle(
276 KUNCUserNotificationID id
,
282 KUNCUserNotificationCallBack callback
,
285 UNDReplyRef reply
= (UNDReplyRef
)id
;
286 ipc_port_t reply_port
;
289 if (reply
== UND_REPLY_NULL
)
290 return KERN_INVALID_ARGUMENT
;
291 UNDReply_lock(reply
);
292 if (reply
->inprogress
== TRUE
|| reply
->userLandNotificationKey
!= -1) {
293 UNDReply_unlock(reply
);
294 return KERN_INVALID_ARGUMENT
;
296 reply
->inprogress
== TRUE
;
297 reply
->callback
= callback
;
298 reply_port
= ipc_port_make_send(reply
->self_port
);
299 UNDReply_unlock(reply
);
301 kr
= UNDDisplayCustomFromBundle_rpc(gUNDServer
,
312 * Routine: convert_port_to_UNDReply
314 * MIG helper routine to convert from a mach port to a
321 convert_port_to_UNDReply(
324 if (IP_VALID(port
)) {
328 if (!ip_active(port
) || (ip_kotype(port
) != IKOT_UND_REPLY
)) {
330 return UND_REPLY_NULL
;
332 reply
= (UNDReplyRef
) port
->ip_kobject
;
333 assert(reply
!= UND_REPLY_NULL
);
336 return UND_REPLY_NULL
;
340 * User interface for setting the host UserNotification Daemon port.
345 host_priv_t host_priv
,
349 if (host_priv
== HOST_PRIV_NULL
|| server
== UND_SERVER_NULL
)
350 return KERN_INVALID_ARGUMENT
;
351 if (gUNDServer
!= UND_SERVER_NULL
)
352 ipc_port_dealloc_kernel(gUNDServer
);
358 * User interface for retrieving the UserNotification Daemon port.
363 host_priv_t host_priv
,
364 UNDServerRef
*server
)
366 if (host_priv
== HOST_PRIV_NULL
)
367 return KERN_INVALID_ARGUMENT
;
368 *server
= gUNDServer
;