Loading...
osfmk/UserNotification/KUNCUserNotifications.c xnu-12377.121.6 xnu-201
--- xnu/xnu-12377.121.6/osfmk/UserNotification/KUNCUserNotifications.c
+++ xnu/xnu-201/osfmk/UserNotification/KUNCUserNotifications.c
@@ -1,42 +1,33 @@
 /*
- * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
+ * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ * 
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
  */
 
 #include <mach/port.h>
 #include <mach/message.h>
 #include <mach/kern_return.h>
-#include <mach/host_priv.h>
-
-#include <kern/kern_types.h>
-#include <kern/kalloc.h>
+#include <mach/etap_events.h>
+
 #include <kern/host.h>
+#include <ipc/ipc_port.h>
 #include <kern/ipc_kobject.h>
-
-#include <ipc/ipc_port.h>
 
 #include <UserNotification/UNDTypes.h>
 #include <UserNotification/UNDRequest.h>
@@ -49,84 +40,68 @@
 #include <IOKit/IOCFUnserialize.h>
 #endif
 
-#if CONFIG_USER_NOTIFICATION
 /*
  * DEFINES AND STRUCTURES
  */
 
+UNDServerRef gUNDServer = UND_SERVER_NULL;
+
+
 struct UNDReply {
-	decl_lck_mtx_data(, lock);                               /* UNDReply lock */
-	int                             userLandNotificationKey;
-	KUNCUserNotificationCallBack    callback;
-	boolean_t                       inprogress;
-	ipc_port_t                      self_port;      /* Our port */
+	decl_mutex_data(,lock)				/* UNDReply lock */
+	int				userLandNotificationKey;
+	KUNCUserNotificationCallBack 	callback;
+	boolean_t			inprogress;
+	ipc_port_t			self_port;	/* Our port */
 };
 
-static void
-UNDReply_no_senders(ipc_port_t port, mach_port_mscount_t mscount);
-
-IPC_KOBJECT_DEFINE(IKOT_UND_REPLY,
-    .iko_op_movable_send = true,
-    .iko_op_stable     = true,
-    .iko_op_no_senders = UNDReply_no_senders);
-
-#define UNDReply_lock(reply)            lck_mtx_lock(&reply->lock)
-#define UNDReply_unlock(reply)          lck_mtx_unlock(&reply->lock)
-
-LCK_GRP_DECLARE(UNDLckGrp, "UND");
-
-static UNDServerRef
-UNDServer_reference(void)
-{
-	UNDServerRef UNDServer;
-	kern_return_t kr;
-
-	kr = host_get_user_notification_port(host_priv_self(), &UNDServer);
-	assert(kr == KERN_SUCCESS);
-	return UNDServer;
-}
-
-static void
-UNDServer_deallocate(
-	UNDServerRef    UNDServer)
-{
-	if (IP_VALID(UNDServer)) {
-		ipc_port_release_send(UNDServer);
-	}
-}
-
-/*
+#define UNDReply_lock(reply)		mutex_lock(&reply->lock)
+#define UNDReply_lock_try(reply)	mutex_lock_try(&(reply)->lock)
+#define UNDReply_unlock(reply)		mutex_unlock(&(reply)->lock)
+
+void
+UNDReply_deallocate(
+	UNDReplyRef		reply)
+{
+	ipc_port_t port;
+	UNDReply_lock(reply);
+	port = reply->self_port;
+	ipc_kobject_set(port, IKO_NULL, IKOT_NONE);
+	reply->self_port = IP_NULL;
+	UNDReply_unlock(reply);
+
+	ipc_port_dealloc_kernel(port);
+	kfree((vm_offset_t)reply, sizeof(struct UNDReply));
+	return;
+}
+
+/* 
  * UND Mig Callbacks
- */
-
-kern_return_t
-UNDAlertCompletedWithResult_rpc(
-	UNDReplyRef             reply,
-	int                     result,
-	xmlData_t               keyRef,         /* raw XML bytes */
+*/
+
+kern_return_t
+UNDAlertCompletedWithResult_rpc (
+        UNDReplyRef 		reply,
+        int 			result,
+        xmlData_t		keyRef,		/* raw XML bytes */
+        mach_msg_type_number_t	keyLen)
+{
 #ifdef KERNEL_CF
-	mach_msg_type_number_t  keyLen)
+	CFStringRef		xmlError = NULL;
+	CFDictionaryRef 	dict = NULL;
 #else
-	__unused mach_msg_type_number_t keyLen)
+	void *dict = (void *)keyRef;
 #endif
-{
-#ifdef KERNEL_CF
-	CFStringRef             xmlError = NULL;
-	CFDictionaryRef         dict = NULL;
-#else
-	const void *dict = (const void *)keyRef;
-#endif
-
-	if (reply == UND_REPLY_NULL || !reply->inprogress) {
-		return KERN_INVALID_ARGUMENT;
-	}
+
+	if (reply == UND_REPLY_NULL || !reply->inprogress)
+		return KERN_INVALID_ARGUMENT;
 
 	/*
 	 * JMM - No C vesion of the Unserialize code in-kernel
 	 * and no C type for a CFDictionary either.  For now,
 	 * just pass the raw keyRef through.
 	 */
-#ifdef KERNEL_CF
+#ifdef KERNEL_CF 
 	if (keyRef && keyLen) {
 		dict = IOCFUnserialize(keyRef, NULL, NULL, &xmlError);
 	}
@@ -138,14 +113,14 @@
 #endif /* KERNEL_CF */
 
 	if (reply->callback) {
-		(reply->callback)((int)(KUNCUserNotificationID)reply, result, dict);
+		(reply->callback)((KUNCUserNotificationID) reply, result, dict);
 	}
 
 	UNDReply_lock(reply);
 	reply->inprogress = FALSE;
 	reply->userLandNotificationKey = -1;
 	UNDReply_unlock(reply);
-
+	UNDReply_deallocate(reply);
 	return KERN_SUCCESS;
 }
 
@@ -158,13 +133,12 @@
  *		to identify that request.
  */
 kern_return_t
-UNDNotificationCreated_rpc(
-	UNDReplyRef     reply,
-	int             userLandNotificationKey)
-{
-	if (reply == UND_REPLY_NULL) {
-		return KERN_INVALID_ARGUMENT;
-	}
+UNDNotificationCreated_rpc (
+        UNDReplyRef	reply,
+        int		userLandNotificationKey)
+{
+	if (reply == UND_REPLY_NULL)
+		return KERN_INVALID_ARGUMENT;
 
 	UNDReply_lock(reply);
 	if (reply->inprogress || reply->userLandNotificationKey != -1) {
@@ -178,160 +152,157 @@
 
 /*
  * KUNC Functions
- */
+*/
 
 
 KUNCUserNotificationID
-KUNCGetNotificationID(void)
+KUNCGetNotificationID()
 {
 	UNDReplyRef reply;
 
-	reply = kalloc_type(struct UNDReply, Z_WAITOK | Z_ZERO | Z_NOFAIL);
-	reply->self_port = ipc_kobject_alloc_port((ipc_kobject_t)reply,
-	    IKOT_UND_REPLY, IPC_KOBJECT_ALLOC_NONE);
-	lck_mtx_init(&reply->lock, &UNDLckGrp, LCK_ATTR_NULL);
-	reply->userLandNotificationKey = -1;
+	reply = (UNDReplyRef) kalloc(sizeof(struct UNDReply));
+	if (reply != UND_REPLY_NULL) {
+		reply->self_port = ipc_port_alloc_kernel();
+		if (reply->self_port == IP_NULL) {
+			kfree((vm_offset_t)reply, sizeof(struct UNDReply));
+			reply = UND_REPLY_NULL;
+		} else {
+			mutex_init(&reply->lock, ETAP_IO_UNDREPLY);
+			reply->userLandNotificationKey = -1;
+			reply->inprogress = FALSE;
+			ipc_kobject_set(reply->self_port,
+					(ipc_kobject_t)reply,
+					IKOT_UND_REPLY);
+		}
+	}
+	return (KUNCUserNotificationID) reply;
+}
+
+
+kern_return_t KUNCExecute(char executionPath[1024], int uid, int gid)
+{
+    return UNDExecute_rpc(gUNDServer, executionPath, uid, gid);
+}
+
+kern_return_t KUNCUserNotificationCancel(
+	KUNCUserNotificationID id)
+{
+	UNDReplyRef reply = (UNDReplyRef)id;
+	kern_return_t kr;
+	int ulkey;
+
+	if (reply == UND_REPLY_NULL)
+		return KERN_INVALID_ARGUMENT;
+
+	UNDReply_lock(reply);
+	if (!reply->inprogress) {
+		UNDReply_unlock(reply);
+		return KERN_INVALID_ARGUMENT;
+	}
+
 	reply->inprogress = FALSE;
-
-	return (KUNCUserNotificationID) reply;
-}
-
-static void
-UNDReply_no_senders(ipc_port_t port, mach_port_mscount_t mscount)
-{
-	UNDReplyRef reply;
-
-	reply = ipc_kobject_dealloc_port(port, mscount, IKOT_UND_REPLY);
-	lck_mtx_destroy(&reply->lock, &UNDLckGrp);
-	kfree_type(struct UNDReply, reply);
-}
-
-kern_return_t
-KUNCExecute(char executionPath[1024], int uid, int gid)
-{
-	UNDServerRef UNDServer;
-
-	UNDServer = UNDServer_reference();
-	if (IP_VALID(UNDServer)) {
-		kern_return_t kr;
-		kr = UNDExecute_rpc(UNDServer, executionPath, uid, gid);
-		UNDServer_deallocate(UNDServer);
-		return kr;
-	}
-	return MACH_SEND_INVALID_DEST;
+	if (ulkey = reply->userLandNotificationKey) {
+		reply->userLandNotificationKey = 0;
+		UNDReply_unlock(reply);
+		kr = UNDCancelNotification_rpc(gUNDServer,ulkey);
+	} else {
+		UNDReply_unlock(reply);
+		kr = KERN_SUCCESS;
+	}
+	UNDReply_deallocate(reply);
+	return kr;
 }
 
 kern_return_t
 KUNCUserNotificationDisplayNotice(
-	int             noticeTimeout,
-	unsigned        flags,
-	char            *iconPath,
-	char            *soundPath,
-	char            *localizationPath,
-	char            *alertHeader,
-	char            *alertMessage,
-	char            *defaultButtonTitle)
-{
-	UNDServerRef UNDServer;
-
-	UNDServer = UNDServer_reference();
-	if (IP_VALID(UNDServer)) {
-		kern_return_t kr;
-		kr = UNDDisplayNoticeSimple_rpc(UNDServer,
-		    noticeTimeout,
-		    flags,
-		    iconPath,
-		    soundPath,
-		    localizationPath,
-		    alertHeader,
-		    alertMessage,
-		    defaultButtonTitle);
-		UNDServer_deallocate(UNDServer);
-		return kr;
-	}
-	return MACH_SEND_INVALID_DEST;
+	int		timeout,
+	unsigned	flags,
+	char		*iconPath,
+	char		*soundPath,
+	char		*localizationPath,
+	char		*alertHeader,
+	char		*alertMessage,
+	char		*defaultButtonTitle)
+{
+	kern_return_t kr;
+	kr = UNDDisplayNoticeSimple_rpc(gUNDServer,
+					timeout,
+					flags,
+					iconPath,
+					soundPath,
+					localizationPath,
+					alertHeader,
+					alertMessage,
+					defaultButtonTitle);
+	return kr;
 }
 
 kern_return_t
 KUNCUserNotificationDisplayAlert(
-	int             alertTimeout,
-	unsigned        flags,
-	char            *iconPath,
-	char            *soundPath,
-	char            *localizationPath,
-	char            *alertHeader,
-	char            *alertMessage,
-	char            *defaultButtonTitle,
-	char            *alternateButtonTitle,
-	char            *otherButtonTitle,
-	unsigned        *responseFlags)
-{
-	UNDServerRef    UNDServer;
-
-	UNDServer = UNDServer_reference();
-	if (IP_VALID(UNDServer)) {
-		kern_return_t   kr;
-		kr = UNDDisplayAlertSimple_rpc(UNDServer,
-		    alertTimeout,
-		    flags,
-		    iconPath,
-		    soundPath,
-		    localizationPath,
-		    alertHeader,
-		    alertMessage,
-		    defaultButtonTitle,
-		    alternateButtonTitle,
-		    otherButtonTitle,
-		    responseFlags);
-		UNDServer_deallocate(UNDServer);
-		return kr;
-	}
-	return MACH_SEND_INVALID_DEST;
+	int		timeout,
+	unsigned	flags,
+	char		*iconPath,
+	char		*soundPath,
+	char		*localizationPath,
+	char		*alertHeader,
+	char		*alertMessage,
+	char		*defaultButtonTitle,
+	char		*alternateButtonTitle,
+	char		*otherButtonTitle,
+	unsigned	*responseFlags)
+{
+	kern_return_t	kr;
+	
+	kr = UNDDisplayAlertSimple_rpc(gUNDServer,
+				       timeout,
+				       flags,
+				       iconPath,
+				       soundPath,
+				       localizationPath,
+				       alertHeader,
+				       alertMessage,
+				       defaultButtonTitle,
+				       alternateButtonTitle,
+				       otherButtonTitle,
+				       responseFlags);
+	return kr;
 }
 
 kern_return_t
 KUNCUserNotificationDisplayFromBundle(
-	KUNCUserNotificationID       id,
-	char                         *bundlePath,
-	char                         *fileName,
-	char                         *fileExtension,
-	char                         *messageKey,
-	char                         *tokenString,
+	KUNCUserNotificationID	     id,
+	char 			     *bundlePath,
+	char			     *fileName,
+	char			     *fileExtension,
+	char			     *messageKey,
+	char			     *tokenString,
 	KUNCUserNotificationCallBack callback,
-	__unused int                    contextKey)
+	int			     contextKey)
 {
 	UNDReplyRef reply = (UNDReplyRef)id;
-	UNDServerRef UNDServer;
 	ipc_port_t reply_port;
-
-	if (reply == UND_REPLY_NULL) {
-		return KERN_INVALID_ARGUMENT;
-	}
+	kern_return_t kr;
+
+	if (reply == UND_REPLY_NULL)
+		return KERN_INVALID_ARGUMENT;
 	UNDReply_lock(reply);
 	if (reply->inprogress == TRUE || reply->userLandNotificationKey != -1) {
 		UNDReply_unlock(reply);
 		return KERN_INVALID_ARGUMENT;
 	}
-	reply->inprogress = TRUE;
+	reply->inprogress == TRUE;
 	reply->callback = callback;
-	reply_port = ipc_kobject_make_send(reply->self_port, reply, IKOT_UND_REPLY);
+	reply_port = ipc_port_make_send(reply->self_port);
 	UNDReply_unlock(reply);
 
-	UNDServer = UNDServer_reference();
-	if (IP_VALID(UNDServer)) {
-		kern_return_t kr;
-
-		kr = UNDDisplayCustomFromBundle_rpc(UNDServer,
-		    reply_port,
-		    bundlePath,
-		    fileName,
-		    fileExtension,
-		    messageKey,
-		    tokenString);
-		UNDServer_deallocate(UNDServer);
-		return kr;
-	}
-	return MACH_SEND_INVALID_DEST;
+	kr = UNDDisplayCustomFromBundle_rpc(gUNDServer,
+					    reply_port,
+					    bundlePath,
+					    fileName,
+					    fileExtension,
+					    messageKey,
+					    tokenString);
+	return kr;
 }
 
 /*
@@ -347,14 +318,20 @@
 convert_port_to_UNDReply(
 	ipc_port_t port)
 {
-	UNDReplyRef reply = NULL;
 	if (IP_VALID(port)) {
-		reply = ipc_kobject_get_stable(port, IKOT_UND_REPLY);
-	}
-
-	return reply;
-}
-#endif
+		UNDReplyRef reply;
+
+		ip_lock(port);
+		if (!ip_active(port) || (ip_kotype(port) != IKOT_UND_REPLY)) {
+			ip_unlock(port);
+			return UND_REPLY_NULL;
+		}
+		reply = (UNDReplyRef) port->ip_kobject;
+		assert(reply != UND_REPLY_NULL);
+		ip_unlock(port);
+	}
+	return UND_REPLY_NULL;
+}
 
 /*
  *      User interface for setting the host UserNotification Daemon port.
@@ -362,15 +339,16 @@
 
 kern_return_t
 host_set_UNDServer(
-	host_priv_t     host_priv,
-	UNDServerRef    server)
-{
-#if CONFIG_USER_NOTIFICATION
-	return host_set_user_notification_port(host_priv, server);
-#else
-#pragma unused(host_priv, server)
-	return KERN_NOT_SUPPORTED;
-#endif
+        host_priv_t     host_priv,
+        UNDServerRef    server)
+{
+
+	if (host_priv == HOST_PRIV_NULL || server == UND_SERVER_NULL)
+		return KERN_INVALID_ARGUMENT;
+	if (gUNDServer != UND_SERVER_NULL)
+		ipc_port_dealloc_kernel(gUNDServer);
+	gUNDServer = server;
+	return KERN_SUCCESS;
 }
 
 /*
@@ -380,12 +358,11 @@
 kern_return_t
 host_get_UNDServer(
 	host_priv_t     host_priv,
-	UNDServerRef    *serverp)
-{
-#if CONFIG_USER_NOTIFICATION
-	return host_get_user_notification_port(host_priv, serverp);
-#else
-#pragma unused(host_priv, serverp)
-	return KERN_NOT_SUPPORTED;
-#endif
-}
+	UNDServerRef	*server)
+{
+	if (host_priv == HOST_PRIV_NULL)
+		return KERN_INVALID_ARGUMENT;
+	 *server = gUNDServer;
+	 return KERN_SUCCESS;
+}
+