Loading...
iokit/Kernel/IOUserServer.cpp xnu-12377.121.6 xnu-6153.41.3
--- xnu/xnu-12377.121.6/iokit/Kernel/IOUserServer.cpp
+++ xnu/xnu-6153.41.3/iokit/Kernel/IOUserServer.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998-2021 Apple Inc. All rights reserved.
+ * Copyright (c) 1998-2014 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -29,44 +29,26 @@
 #include <IOKit/IORPC.h>
 #include <IOKit/IOKitServer.h>
 #include <IOKit/IOKitKeysPrivate.h>
-#include <IOKit/IOKernelReportStructs.h>
 #include <IOKit/IOUserClient.h>
 #include <IOKit/IOService.h>
 #include <IOKit/IORegistryEntry.h>
 #include <IOKit/IOCatalogue.h>
 #include <IOKit/IOMemoryDescriptor.h>
 #include <IOKit/IOBufferMemoryDescriptor.h>
-#include <IOKit/IOSubMemoryDescriptor.h>
-#include <IOKit/IOMultiMemoryDescriptor.h>
-#include <IOKit/IOMapper.h>
 #include <IOKit/IOLib.h>
-#include <IOKit/IOHibernatePrivate.h>
 #include <IOKit/IOBSD.h>
 #include <IOKit/system.h>
-#include "IOServicePrivate.h"
 #include <IOKit/IOUserServer.h>
 #include <IOKit/IOInterruptEventSource.h>
 #include <IOKit/IOTimerEventSource.h>
-#include <IOKit/IODeviceTreeSupport.h>
 #include <IOKit/pwr_mgt/RootDomain.h>
-#include <IOKit/pwr_mgt/IOPowerConnection.h>
-#include <libkern/c++/OSAllocation.h>
 #include <libkern/c++/OSKext.h>
-#include <libkern/c++/OSSharedPtr.h>
 #include <libkern/OSDebug.h>
 #include <libkern/Block.h>
-#include <kern/cs_blobs.h>
-#include <kern/thread_call.h>
-#include <os/atomic_private.h>
 #include <sys/proc.h>
-#include <sys/reboot.h>
-#include <sys/codesign.h>
-#include <vm/vm_iokit.h>
-#include <mach_debug/mach_debug_types.h>
 #include "IOKitKernelInternal.h"
-#include "IOServicePMPrivate.h"
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
 
 #include <DriverKit/IODispatchQueue.h>
 #include <DriverKit/OSObject.h>
@@ -78,55 +60,17 @@
 #include <DriverKit/IOBufferMemoryDescriptor.h>
 #include <DriverKit/IOMemoryMap.h>
 #include <DriverKit/IODataQueueDispatchSource.h>
-#include <DriverKit/IOServiceNotificationDispatchSource.h>
-#include <DriverKit/IOServiceStateNotificationDispatchSource.h>
-#include <DriverKit/IOEventLink.h>
-#include <DriverKit/IOWorkGroup.h>
 #include <DriverKit/IOUserServer.h>
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
 
 #include <System/IODataQueueDispatchSourceShared.h>
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-enum{
-	kIOUserServerCheckInTimeoutMSecs = 120000ULL,
-	kIOUserServerCheckInMaxRetry     = 3,
-};
-
-TUNABLE(SInt64, gIODKDebug, "dk", kIODKEnable);
-
-#if DEBUG || DEVELOPMENT
-uint64_t driverkit_checkin_timed_out = 0;
-TUNABLE(bool, disable_dext_crash_reboot, "disable_dext_crash_reboot", 0);
-extern "C" kern_return_t kern_register_userspace_coredump(task_t task, const char * name, boolean_t emergency);
-#endif /* DEBUG || DEVELOPMENT */
-
-extern bool restore_boot;
-
-static OSString       * gIOSystemStateSleepDescriptionKey;
-static const OSSymbol * gIOSystemStateSleepDescriptionReasonKey;
-static const OSSymbol * gIOSystemStateSleepDescriptionHibernateStateKey;
-
-static OSString       * gIOSystemStateWakeDescriptionKey;
-static const OSSymbol * gIOSystemStateWakeDescriptionWakeReasonKey;
-static const OSSymbol * gIOSystemStateWakeDescriptionContinuousTimeOffsetKey;
-
-static OSString       * gIOSystemStateHaltDescriptionKey;
-static const OSSymbol * gIOSystemStateHaltDescriptionHaltStateKey;
-
-static OSString       * gIOSystemStatePowerSourceDescriptionKey;
-static const OSSymbol * gIOSystemStatePowerSourceDescriptionACAttachedKey;
-
-extern bool gInUserspaceReboot;
-
-extern void iokit_clear_registered_ports(task_t task);
-
-static IORPCMessage *
-IORPCMessageFromMachReply(IORPCMessageMach * msg);
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
+
+SInt64    gIODKDebug = kIODKEnable;
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
 
 struct IOPStrings;
 
@@ -160,14 +104,31 @@
 
 	virtual bool
 	start(IOService * provider) APPLE_KEXT_OVERRIDE;
+	virtual IOReturn
+	setProperties(OSObject * props) APPLE_KEXT_OVERRIDE;
 };
 
 OSDefineMetaClassAndStructors(IOUserService, IOService)
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-OSDefineMetaClassAndStructors(IOUserServerCheckInToken, OSObject);
-OSDefineMetaClassAndStructors(_IOUserServerCheckInCancellationHandler, OSObject);
+class IOUserUserClient : public IOUserClient
+{
+	OSDeclareDefaultStructors(IOUserUserClient);
+public:
+	task_t          fTask;
+
+	IOReturn                   setTask(task_t task);
+	virtual void           stop(IOService * provider) APPLE_KEXT_OVERRIDE;
+	virtual IOReturn       clientClose(void) APPLE_KEXT_OVERRIDE;
+	virtual IOReturn       setProperties(OSObject * properties) APPLE_KEXT_OVERRIDE;
+	virtual IOReturn       externalMethod(uint32_t selector, IOExternalMethodArguments * args,
+	    IOExternalMethodDispatch * dispatch, OSObject * target, void * reference) APPLE_KEXT_OVERRIDE;
+	virtual IOReturn           clientMemoryForType(UInt32 type,
+	    IOOptionBits * options,
+	    IOMemoryDescriptor ** memory) APPLE_KEXT_OVERRIDE;
+};
+
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
@@ -186,11 +147,18 @@
 	return ok;
 }
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+IOReturn
+IOUserService::setProperties(OSObject * properties)
+{
+	setProperty("USER", properties);
+	return kIOReturnSuccess;
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
 
 #undef super
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
 
 struct IODispatchQueue_IVars {
 	IOUserServer * userServer;
@@ -205,31 +173,15 @@
 	OSObject             * target;
 	uint64_t               targetmsgid;
 	uint64_t               msgid;
-	IOUserServer         * userServer;
 	OSActionAbortedHandler abortedHandler;
-	OSString             * typeName;
-	void                 * reference;
 	size_t                 referenceSize;
-	bool                   aborted;
+	void                 * reference[0];
 };
 
-struct IOWorkGroup_IVars {
-	IOUserServer * userServer;
-	OSString * name;
-	IOUserUserClient * userClient;
-};
-
-struct IOEventLink_IVars {
-	IOUserServer * userServer;
-	OSString * name;
-	IOUserUserClient * userClient;
-};
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-kern_return_t
-IOService::GetRegistryEntryID_Impl(
-	uint64_t * registryEntryID)
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
+
+kern_return_t
+IMPL(IOService, GetRegistryEntryID)
 {
 	IOReturn ret = kIOReturnSuccess;
 
@@ -239,8 +191,7 @@
 }
 
 kern_return_t
-IOService::SetName_Impl(
-	const char * name)
+IMPL(IOService, SetName)
 {
 	IOReturn ret = kIOReturnSuccess;
 
@@ -250,162 +201,29 @@
 }
 
 kern_return_t
-IOService::CopyName_Impl(
-	OSString ** name)
-{
-	const OSString * str = copyName();
-	*name = __DECONST(OSString *, str);
-	return str ? kIOReturnSuccess : kIOReturnError;
-}
-
-
-kern_return_t
-IOService::Start_Impl(
-	IOService * provider)
+IMPL(IOService, Start)
 {
 	IOReturn ret = kIOReturnSuccess;
 	return ret;
 }
 
-
-IOReturn
-IOService::UpdateReport_Impl(OSData *channels, uint32_t action,
-    uint32_t *outElementCount,
-    uint64_t offset, uint64_t capacity,
-    IOMemoryDescriptor *buffer)
-{
-	return kIOReturnUnsupported;
-}
-
-IOReturn
-IOService::ConfigureReport_Impl(OSData *channels, uint32_t action, uint32_t *outCount)
-{
-	return kIOReturnUnsupported;
-}
-
-// adapt old signature of configureReport to the iig-friendly signature of ConfigureReport
-IOReturn
-IOService::_ConfigureReport(IOReportChannelList    *channelList,
-    IOReportConfigureAction action,
-    void                   *result,
-    void                   *destination)
-{
-	if (action != kIOReportEnable && action != kIOReportGetDimensions && action != kIOReportDisable) {
-		return kIOReturnUnsupported;
-	}
-	static_assert(sizeof(IOReportChannelList) == 8);
-	static_assert(sizeof(IOReportChannel) == 16);
-	unsigned int size_of_channels;
-	bool overflow = os_mul_and_add_overflow(channelList->nchannels, sizeof(IOReportChannel), sizeof(IOReportChannelList), &size_of_channels);
-	if (overflow) {
-		return kIOReturnOverrun;
-	}
-	OSSharedPtr<OSData> sp_channels(OSData::withBytesNoCopy(channelList, size_of_channels), libkern::no_retain);
-	if (!sp_channels) {
-		return kIOReturnNoMemory;
-	}
-	int *resultp = (int*) result;
-	uint32_t count = 0;
-	IOReturn r = ConfigureReport(sp_channels.get(), action, &count);
-	int new_result;
-	overflow = os_add_overflow(*resultp, count, &new_result);
-	if (overflow) {
-		return kIOReturnOverrun;
-	}
-	*resultp = new_result;
-	return r;
-}
-
-// adapt old signature of updateReport to the iig-friendly signature of UpdateReport
-IOReturn
-IOService::_UpdateReport(IOReportChannelList      *channelList,
-    IOReportUpdateAction      action,
-    void                     *result,
-    void                     *destination)
-{
-	if (action != kIOReportCopyChannelData) {
-		return kIOReturnUnsupported;
-	}
-	unsigned int size_of_channels;
-	bool overflow = os_mul_and_add_overflow(channelList->nchannels, sizeof(IOReportChannel), sizeof(IOReportChannelList), &size_of_channels);
-	if (overflow) {
-		return kIOReturnOverrun;
-	}
-	OSSharedPtr<OSData> sp_channels(OSData::withBytesNoCopy(channelList, size_of_channels), libkern::no_retain);
-	if (!sp_channels) {
-		return kIOReturnNoMemory;
-	}
-	int *resultp = (int*) result;
-	uint32_t count = 0;
-	auto buffer = (IOBufferMemoryDescriptor*) destination;
-	uint64_t length = buffer->getLength();
-	buffer->setLength(buffer->getCapacity());
-	IOReturn r = UpdateReport(sp_channels.get(), action, &count, length, buffer->getCapacity() - length, buffer);
-	int new_result;
-	overflow = os_add_overflow(*resultp, count, &new_result);
-	size_t new_length;
-	overflow = overflow || os_mul_and_add_overflow(count, sizeof(IOReportElement), length, &new_length);
-	if (overflow || new_length > buffer->getCapacity()) {
-		buffer->setLength(length);
-		return kIOReturnOverrun;
-	}
-	*resultp = new_result;
-	buffer->setLength(new_length);
-	return r;
-}
-
-
-IOReturn
-IOService::SetLegend_Impl(OSArray *legend, bool is_public)
-{
-	bool ok = setProperty(kIOReportLegendKey, legend);
-	ok = ok && setProperty(kIOReportLegendPublicKey, is_public);
-	return ok ? kIOReturnSuccess : kIOReturnError;
-}
-
-
-kern_return_t
-IOService::RegisterService_Impl()
+kern_return_t
+IMPL(IOService, RegisterService)
 {
 	IOReturn ret = kIOReturnSuccess;
-	bool started;
-
-	IOUserServer *us = (typeof(us))thread_iokit_tls_get(0);
-	if (reserved != NULL && reserved->uvars != NULL && reserved->uvars->userServer == us) {
-		started = reserved->uvars->started;
-	} else {
-		// assume started
-		started = true;
-	}
-
-	if (OSDynamicCast(IOUserServer, this) != NULL || started) {
-		registerService(kIOServiceAsynchronous);
-	} else {
-		assert(reserved != NULL && reserved->uvars != NULL);
-		reserved->uvars->deferredRegisterService = true;
-	}
+
+	registerService();
 
 	return ret;
 }
 
 kern_return_t
-IOService::CopyDispatchQueue_Impl(
-	const char * name,
-	IODispatchQueue ** queue)
+IMPL(IOService, CopyDispatchQueue)
 {
 	IODispatchQueue * result;
 	IOService  * service;
 	IOReturn     ret;
 	uint32_t index;
-
-	if (!reserved->uvars) {
-		return kIOReturnError;
-	}
-
-	if (!reserved->uvars->queueArray) {
-		// CopyDispatchQueue should not be called after the service has stopped
-		return kIOReturnError;
-	}
 
 	ret = kIOReturnNotFound;
 	index = -1U;
@@ -435,41 +253,10 @@
 }
 
 kern_return_t
-IOService::CreateDefaultDispatchQueue_Impl(
-	IODispatchQueue ** queue)
-{
-	return kIOReturnError;
-}
-
-kern_return_t
-IOService::CoreAnalyticsSendEvent_Impl(
-	uint64_t       options,
-	OSString     * eventName,
-	OSDictionary * eventPayload)
-{
-	kern_return_t ret;
-
-	if (NULL == gIOCoreAnalyticsSendEventProc) {
-		// perhaps save for later?
-		return kIOReturnNotReady;
-	}
-
-	ret = (*gIOCoreAnalyticsSendEventProc)(options, eventName, eventPayload);
-
-	return ret;
-}
-
-kern_return_t
-IOService::SetDispatchQueue_Impl(
-	const char * name,
-	IODispatchQueue * queue)
+IMPL(IOService, SetDispatchQueue)
 {
 	IOReturn ret = kIOReturnSuccess;
 	uint32_t index;
-
-	if (!reserved->uvars) {
-		return kIOReturnError;
-	}
 
 	if (kIODKLogSetup & gIODKDebug) {
 		DKLOG(DKS "::SetDispatchQueue(%s)\n", DKN(this), name);
@@ -495,162 +282,28 @@
 	return ret;
 }
 
-IOService *
-IOService::GetProvider() const
-{
-	return getProvider();
-}
-
-kern_return_t
-IOService::SetProperties_Impl(
-	OSDictionary * properties)
-{
-	IOUserServer   * us;
-	OSDictionary   * dict;
-	IOReturn         ret;
-
-	us = (typeof(us))thread_iokit_tls_get(0);
-	dict = OSDynamicCast(OSDictionary, properties);
-	if (NULL == us) {
-		if (!dict) {
-			return kIOReturnBadArgument;
-		}
-		bool ok __block = true;
-		dict->iterateObjects(^bool (const OSSymbol * key, OSObject * value) {
-			ok = setProperty(key, value);
-			return !ok;
-		});
-		ret = ok ? kIOReturnSuccess : kIOReturnNotWritable;
-		return ret;
-	}
+kern_return_t
+IMPL(IOService, SetProperties)
+{
+	IOReturn ret = kIOReturnUnsupported;
 
 	ret = setProperties(properties);
 
-	if (kIOReturnUnsupported == ret) {
-		if (dict && reserved->uvars && (reserved->uvars->userServer == us)) {
-			ret = runPropertyActionBlock(^IOReturn (void) {
-				OSDictionary   * userProps;
-				IOReturn         ret;
-
-				userProps = OSDynamicCast(OSDictionary, getProperty(gIOUserServicePropertiesKey));
-				if (userProps) {
-				        userProps = (typeof(userProps))userProps->copyCollection();
-				} else {
-				        userProps = OSDictionary::withCapacity(4);
-				}
-				if (!userProps) {
-				        ret = kIOReturnNoMemory;
-				} else {
-				        bool ok = userProps->merge(dict);
-				        if (ok) {
-				                ok = setProperty(gIOUserServicePropertiesKey, userProps);
-					}
-				        OSSafeReleaseNULL(userProps);
-				        ret = ok ? kIOReturnSuccess : kIOReturnNotWritable;
-				}
-				return ret;
-			});
-		}
-	}
-
 	return ret;
 }
 
 kern_return_t
-IOService::RemoveProperty_Impl(OSString * propertyName)
-{
-	IOUserServer * us  = (IOUserServer *)thread_iokit_tls_get(0);
-	IOReturn       ret = kIOReturnUnsupported;
-
-	if (NULL == propertyName) {
-		return kIOReturnUnsupported;
-	}
-	if (NULL == us) {
-		removeProperty(propertyName);
-		return kIOReturnSuccess;
-	}
-	if (reserved && reserved->uvars && reserved->uvars->userServer == us) {
-		ret = runPropertyActionBlock(^IOReturn (void) {
-			OSDictionary * userProps;
-			userProps = OSDynamicCast(OSDictionary, getProperty(gIOUserServicePropertiesKey));
-			if (userProps) {
-			        userProps = (OSDictionary *)userProps->copyCollection();
-			        if (!userProps) {
-			                return kIOReturnNoMemory;
-				}
-			        userProps->removeObject(propertyName);
-			        bool ok = setProperty(gIOUserServicePropertiesKey, userProps);
-			        OSSafeReleaseNULL(userProps);
-			        return ok ? kIOReturnSuccess : kIOReturnNotWritable;
-			} else {
-			        return kIOReturnNotFound;
-			}
-		});
-	}
+IMPL(IOService, CopyProperties)
+{
+	IOReturn ret = kIOReturnSuccess;
+	*properties = dictionaryWithProperties();
 	return ret;
 }
 
-kern_return_t
-IOService::CopyProperties_Local(
-	OSDictionary ** properties)
-{
-	OSDictionary * props;
-	OSDictionary * userProps;
-
-	props = dictionaryWithProperties();
-	userProps = OSDynamicCast(OSDictionary, props->getObject(gIOUserServicePropertiesKey));
-	if (userProps) {
-		props->merge(userProps);
-		props->removeObject(gIOUserServicePropertiesKey);
-	}
-
-	*properties = props;
-
-	return props ? kIOReturnSuccess : kIOReturnNoMemory;
-}
-
-kern_return_t
-IOService::CopyProperties_Impl(
-	OSDictionary ** properties)
-{
-	return CopyProperties_Local(properties);
-}
-
-kern_return_t
-IOService::RequireMaxBusStall_Impl(
-	uint64_t u64ns)
-{
-	IOReturn ret;
-	UInt32   ns;
-
-	if (os_convert_overflow(u64ns, &ns)) {
-		return kIOReturnBadArgument;
-	}
-	ret = requireMaxBusStall(ns);
-
-	return ret;
-}
-
-#if PRIVATE_WIFI_ONLY
-kern_return_t
-IOService::UserSetProperties_Impl(
-	OSContainer * properties)
-{
-	return kIOReturnUnsupported;
-}
-
-kern_return_t
-IOService::SendIOMessageServicePropertyChange_Impl(void)
-{
-	return messageClients(kIOMessageServicePropertyChange);
-}
-#endif /* PRIVATE_WIFI_ONLY */
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-kern_return_t
-IOMemoryDescriptor::_CopyState_Impl(
-	_IOMDPrivateState * state)
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
+
+kern_return_t
+IMPL(IOMemoryDescriptor, _CopyState)
 {
 	IOReturn ret;
 
@@ -671,13 +324,7 @@
 }
 
 kern_return_t
-IOMemoryDescriptor::CreateMapping_Impl(
-	uint64_t options,
-	uint64_t address,
-	uint64_t offset,
-	uint64_t length,
-	uint64_t alignment,
-	IOMemoryMap ** map)
+IMPL(IOMemoryDescriptor, CreateMapping)
 {
 	IOReturn          ret;
 	IOMemoryMap     * resultMap;
@@ -692,25 +339,11 @@
 		atAddress   = address;
 		koptions    = 0;
 	} else {
-		switch (kIOMemoryMapGuardedMask & options) {
-		default:
-		case kIOMemoryMapGuardedDefault:
-			koptions |= kIOMapGuardedSmall;
-			break;
-		case kIOMemoryMapGuardedNone:
-			break;
-		case kIOMemoryMapGuardedSmall:
-			koptions |= kIOMapGuardedSmall;
-			break;
-		case kIOMemoryMapGuardedLarge:
-			koptions |= kIOMapGuardedLarge;
-			break;
-		}
 		atAddress   = 0;
 		koptions   |= kIOMapAnywhere;
 	}
 
-	if ((kIOMemoryMapReadOnly & options) || (kIODirectionOut == getDirection())) {
+	if (kIOMemoryMapReadOnly & options || (kIODirectionOut == getDirection())) {
 		if (!reserved || (current_task() != reserved->creator)) {
 			koptions   |= kIOMapReadOnly;
 		}
@@ -729,9 +362,6 @@
 	case kIOMemoryMapCacheModeWriteThrough:
 		koptions |= kIOMapWriteThruCache;
 		break;
-	case kIOMemoryMapCacheModeRealTime:
-		koptions |= kIOMapRealTimeCache;
-		break;
 	default:
 		ret = kIOReturnBadArgument;
 	}
@@ -749,151 +379,53 @@
 }
 
 kern_return_t
-IOMemoryDescriptor::CreateSubMemoryDescriptor_Impl(
-	uint64_t memoryDescriptorCreateOptions,
-	uint64_t offset,
-	uint64_t length,
-	IOMemoryDescriptor * ofDescriptor,
-	IOMemoryDescriptor ** memory)
-{
-	IOReturn             ret;
-	IOMemoryDescriptor * iomd;
-	IOByteCount          mdOffset;
-	IOByteCount          mdLength;
-	IOByteCount          mdEnd;
-
-	if (!ofDescriptor) {
+IMPL(IOMemoryDescriptor, PrepareForDMA)
+{
+	IOReturn    ret;
+	uint32_t    idx, count;
+	uint64_t    sumLength;
+	uint64_t    lflags;
+
+	if (!device) {
 		return kIOReturnBadArgument;
 	}
-	if (memoryDescriptorCreateOptions & ~kIOMemoryDirectionOutIn) {
-		return kIOReturnBadArgument;
-	}
-	if (os_convert_overflow(offset, &mdOffset)) {
-		return kIOReturnBadArgument;
-	}
-	if (os_convert_overflow(length, &mdLength)) {
-		return kIOReturnBadArgument;
-	}
-	if (os_add_overflow(mdOffset, mdLength, &mdEnd)) {
-		return kIOReturnBadArgument;
-	}
-	if (mdEnd > ofDescriptor->getLength()) {
-		return kIOReturnBadArgument;
-	}
-
-	iomd = IOSubMemoryDescriptor::withSubRange(
-		ofDescriptor, mdOffset, mdLength, (IOOptionBits) memoryDescriptorCreateOptions);
-
-	if (iomd) {
-		ret = kIOReturnSuccess;
-		*memory = iomd;
-	} else {
-		ret = kIOReturnNoMemory;
-		*memory = NULL;
-	}
+
+	count = *segmentsCount;
+	sumLength = 0;
+	for (idx = 0; idx < count; idx++) {
+#ifdef __LP64__
+		segments[idx].address = getPhysicalSegment(offset, &segments[idx].length);
+#else
+		segments[idx].address = 0;
+#endif
+		if (!segments[idx].address) {
+			break;
+		}
+		sumLength += segments[idx].length;
+		offset += segments[idx].length;
+	}
+	*returnLength = sumLength;
+	*segmentsCount = idx;
+
+	// !!translate flags
+	lflags = 0;
+	if (kIODirectionOut & _flags) {
+		lflags |= kIOMemoryDirectionOut;
+	}
+	if (kIODirectionIn  & _flags) {
+		lflags |= kIOMemoryDirectionIn;
+	}
+
+	*flags = lflags;
+	ret = kIOReturnSuccess;
 
 	return ret;
 }
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-kern_return_t
-IOMemoryDescriptor::CreateWithMemoryDescriptors_Impl(
-	uint64_t memoryDescriptorCreateOptions,
-	uint32_t withDescriptorsCount,
-	IOMemoryDescriptor ** const withDescriptors,
-	IOMemoryDescriptor ** memory)
-{
-	IOReturn             ret;
-	IOMemoryDescriptor * iomd;
-
-	if (!withDescriptors) {
-		return kIOReturnBadArgument;
-	}
-	if (!withDescriptorsCount) {
-		return kIOReturnBadArgument;
-	}
-	if (memoryDescriptorCreateOptions & ~kIOMemoryDirectionOutIn) {
-		return kIOReturnBadArgument;
-	}
-
-	for (unsigned int idx = 0; idx < withDescriptorsCount; idx++) {
-		if (NULL == withDescriptors[idx]) {
-			return kIOReturnBadArgument;
-		}
-	}
-
-	iomd = IOMultiMemoryDescriptor::withDescriptors(withDescriptors, withDescriptorsCount,
-	    (IODirection) memoryDescriptorCreateOptions, false);
-
-	if (iomd) {
-		ret = kIOReturnSuccess;
-		*memory = iomd;
-	} else {
-		ret = kIOReturnNoMemory;
-		*memory = NULL;
-	}
-
-	return ret;
-}
-
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
 
 kern_return_t
-IOUserClient::CreateMemoryDescriptorFromClient_Impl(
-	uint64_t memoryDescriptorCreateOptions,
-	uint32_t segmentsCount,
-	const IOAddressSegment segments[32],
-	IOMemoryDescriptor ** memory)
-{
-	IOReturn             ret;
-	IOMemoryDescriptor * iomd;
-	IOOptionBits         mdOptions;
-	IOUserUserClient   * me;
-	IOAddressRange     * ranges;
-
-	me = OSDynamicCast(IOUserUserClient, this);
-	if (!me) {
-		return kIOReturnBadArgument;
-	}
-	if (!me->fTask) {
-		return kIOReturnNotReady;
-	}
-
-	mdOptions = kIOMemoryThreadSafe;
-	if (kIOMemoryDirectionOut & memoryDescriptorCreateOptions) {
-		mdOptions |= kIODirectionOut;
-	}
-	if (kIOMemoryDirectionIn & memoryDescriptorCreateOptions) {
-		mdOptions |= kIODirectionIn;
-	}
-	if (!(kIOMemoryDisableCopyOnWrite & memoryDescriptorCreateOptions)) {
-		mdOptions |= kIOMemoryMapCopyOnWrite;
-	}
-
-	static_assert(sizeof(IOAddressRange) == sizeof(IOAddressSegment));
-	ranges = __DECONST(IOAddressRange *, &segments[0]);
-
-	iomd = IOMemoryDescriptor::withAddressRanges(
-		ranges, segmentsCount,
-		mdOptions, me->fTask);
-
-	if (iomd) {
-		ret = kIOReturnSuccess;
-		*memory = iomd;
-	} else {
-		ret = kIOReturnNoMemory;
-		*memory = NULL;
-	}
-
-	return ret;
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-kern_return_t
-IOMemoryMap::_CopyState_Impl(
-	_IOMemoryMapPrivateState * state)
+IMPL(IOMemoryMap, _CopyState)
 {
 	IOReturn ret;
 
@@ -907,17 +439,12 @@
 	return ret;
 }
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-kern_return_t
-IOBufferMemoryDescriptor::Create_Impl(
-	uint64_t options,
-	uint64_t capacity,
-	uint64_t alignment,
-	IOBufferMemoryDescriptor ** memory)
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
+
+kern_return_t
+IMPL(IOBufferMemoryDescriptor, Create)
 {
 	IOReturn ret;
-	IOOptionBits                 bmdOptions;
 	IOBufferMemoryDescriptor   * bmd;
 	IOMemoryDescriptorReserved * reserved;
 
@@ -925,9 +452,10 @@
 		// no other options currently defined
 		return kIOReturnBadArgument;
 	}
-	bmdOptions = (options & kIOMemoryDirectionOutIn) | kIOMemoryKernelUserShared | kIOMemoryThreadSafe;
+	options &= kIOMemoryDirectionOutIn;
+	options |= kIOMemoryKernelUserShared;
 	bmd = IOBufferMemoryDescriptor::inTaskWithOptions(
-		kernel_task, bmdOptions, capacity, alignment);
+		kernel_task, options, capacity, alignment);
 
 	*memory = bmd;
 
@@ -945,427 +473,49 @@
 }
 
 kern_return_t
-IOBufferMemoryDescriptor::SetLength_Impl(
-	uint64_t length)
+IMPL(IOBufferMemoryDescriptor, SetLength)
 {
 	setLength(length);
 	return kIOReturnSuccess;
 }
 
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-kern_return_t
-IODMACommand::Create_Impl(
-	IOService * device,
-	uint64_t options,
-	const IODMACommandSpecification * specification,
-	IODMACommand ** command)
-{
-	IOReturn ret;
-	IODMACommand   * dma;
-	IODMACommand::SegmentOptions segmentOptions;
-	IOMapper             * mapper;
-
-	if (options & ~((uint64_t) kIODMACommandCreateNoOptions)) {
-		// no other options currently defined
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
+
+kern_return_t
+OSAction::Create(OSAction_Create_Args)
+{
+	kern_return_t ret;
+	ret = OSAction::Create_Call(target, targetmsgid, msgid, referenceSize, action);
+	return ret;
+}
+
+kern_return_t
+IMPL(OSAction, Create)
+{
+	OSAction * inst;
+	vm_size_t  allocsize;
+
+	if (os_add_overflow(referenceSize, sizeof(OSAction_IVars), &allocsize)) {
 		return kIOReturnBadArgument;
 	}
-
-	if (os_convert_overflow(specification->maxAddressBits, &segmentOptions.fNumAddressBits)) {
-		return kIOReturnBadArgument;
-	}
-	segmentOptions.fMaxSegmentSize            = 0;
-	segmentOptions.fMaxTransferSize           = 0;
-	segmentOptions.fAlignment                 = 1;
-	segmentOptions.fAlignmentLength           = 1;
-	segmentOptions.fAlignmentInternalSegments = 1;
-	segmentOptions.fStructSize                = sizeof(segmentOptions);
-
-	mapper = IOMapper::copyMapperForDevice(device);
-
-	dma = IODMACommand::withSpecification(
-		kIODMACommandOutputHost64,
-		&segmentOptions,
-		kIODMAMapOptionDextOwner |
-		kIODMAMapOptionMapped,
-		mapper,
-		NULL);
-
-	OSSafeReleaseNULL(mapper);
-	*command = dma;
-
-	if (!dma) {
+	inst = OSTypeAlloc(OSAction);
+	if (!inst) {
 		return kIOReturnNoMemory;
 	}
-	ret = kIOReturnSuccess;
-
-	return ret;
-}
-
-#define fInternalState reserved
-
-kern_return_t
-IODMACommand::PrepareForDMA_Impl(
-	uint64_t options,
-	IOMemoryDescriptor * memory,
-	uint64_t offset,
-	uint64_t length,
-	uint64_t * flags,
-	uint32_t * segmentsCount,
-	IOAddressSegment * segments)
-{
-	IOReturn ret;
-	uint64_t lflags, mdFlags;
-	UInt32   numSegments;
-	UInt64   genOffset;
-
-	if (options & ~((uint64_t) kIODMACommandPrepareForDMANoOptions)) {
-		// no other options currently defined
-		return kIOReturnBadArgument;
-	}
-
-	if (memory == NULL) {
-		return kIOReturnBadArgument;
-	}
-
-	assert(fInternalState->fDextLock);
-	IOLockLock(fInternalState->fDextLock);
-
-	// uses IOMD direction
-	ret = memory->prepare();
-	if (kIOReturnSuccess != ret) {
-		goto exit;
-	}
-
-	ret = setMemoryDescriptor(memory, false);
-	if (kIOReturnSuccess != ret) {
-		memory->complete();
-		goto exit;
-	}
-
-	ret = prepare(offset, length);
-	if (kIOReturnSuccess != ret) {
-		clearMemoryDescriptor(false);
-		memory->complete();
-		goto exit;
-	}
-
-	static_assert(sizeof(IODMACommand::Segment64) == sizeof(IOAddressSegment));
-
-	numSegments = *segmentsCount;
-	genOffset   = 0;
-	ret = genIOVMSegments(&genOffset, segments, &numSegments);
-
-	if (kIOReturnSuccess != ret) {
-		clearMemoryDescriptor(true);
-		memory->complete();
-		goto exit;
-	}
-
-	mdFlags = fMemory->getFlags();
-	lflags  = 0;
-	if (kIODirectionOut & mdFlags) {
-		lflags |= kIOMemoryDirectionOut;
-	}
-	if (kIODirectionIn & mdFlags) {
-		lflags |= kIOMemoryDirectionIn;
-	}
-	*flags = lflags;
-	*segmentsCount = numSegments;
-
-exit:
-	IOLockUnlock(fInternalState->fDextLock);
-
-	return ret;
-}
-
-kern_return_t
-IODMACommand::CompleteDMA_Impl(
-	uint64_t options)
-{
-	IOReturn ret, completeRet;
-	IOMemoryDescriptor * md;
-
-	if (options & ~((uint64_t) kIODMACommandCompleteDMANoOptions)) {
-		// no other options currently defined
-		return kIOReturnBadArgument;
-	}
-
-	assert(fInternalState->fDextLock);
-	IOLockLock(fInternalState->fDextLock);
-
-	if (!fInternalState->fPrepared) {
-		ret = kIOReturnNotReady;
-		goto exit;
-	}
-
-	md = __DECONST(IOMemoryDescriptor *, fMemory);
-	if (md) {
-		md->retain();
-	}
-
-	ret = clearMemoryDescriptor(true);
-
-	if (md) {
-		completeRet = md->complete();
-		OSSafeReleaseNULL(md);
-		if (kIOReturnSuccess == ret) {
-			ret = completeRet;
-		}
-	}
-exit:
-	IOLockUnlock(fInternalState->fDextLock);
-
-	return ret;
-}
-
-kern_return_t
-IODMACommand::GetPreparation_Impl(
-	uint64_t * offset,
-	uint64_t * length,
-	IOMemoryDescriptor ** memory)
-{
-	IOReturn ret;
-	IOMemoryDescriptor * md;
-
-	if (!fActive) {
-		return kIOReturnNotReady;
-	}
-
-	ret = getPreparedOffsetAndLength(offset, length);
-	if (kIOReturnSuccess != ret) {
-		return ret;
-	}
-
-	if (memory) {
-		md = __DECONST(IOMemoryDescriptor *, fMemory);
-		*memory = md;
-		if (!md) {
-			ret = kIOReturnNotReady;
-		} else {
-			md->retain();
-		}
-	}
-	return ret;
-}
-
-kern_return_t
-IODMACommand::PerformOperation_Impl(
-	uint64_t options,
-	uint64_t dmaOffset,
-	uint64_t length,
-	uint64_t dataOffset,
-	IOMemoryDescriptor * data)
-{
-	IOReturn ret;
-	OSDataAllocation<uint8_t> buffer;
-	UInt64 copiedDMA;
-	IOByteCount mdOffset, mdLength, copied;
-
-	if (options & ~((uint64_t)
-	    (kIODMACommandPerformOperationOptionRead
-	    | kIODMACommandPerformOperationOptionWrite
-	    | kIODMACommandPerformOperationOptionZero))) {
-		// no other options currently defined
-		return kIOReturnBadArgument;
-	}
-
-	if (!fActive) {
-		return kIOReturnNotReady;
-	}
-	if (os_convert_overflow(dataOffset, &mdOffset)) {
-		return kIOReturnBadArgument;
-	}
-	if (os_convert_overflow(length, &mdLength)) {
-		return kIOReturnBadArgument;
-	}
-	if (length > fMemory->getLength()) {
-		return kIOReturnBadArgument;
-	}
-	buffer = OSDataAllocation<uint8_t>(length, OSAllocateMemory);
-	if (!buffer) {
+	inst->ivars = (typeof(inst->ivars))(uintptr_t) IONewZero(uint8_t, allocsize);
+	if (!inst->ivars) {
+		inst->release();
 		return kIOReturnNoMemory;
 	}
-
-	switch (options) {
-	case kIODMACommandPerformOperationOptionZero:
-		bzero(buffer.data(), length);
-		copiedDMA = writeBytes(dmaOffset, buffer.data(), length);
-		if (copiedDMA != length) {
-			ret = kIOReturnUnderrun;
-			break;
-		}
-		ret = kIOReturnSuccess;
-		break;
-
-	case kIODMACommandPerformOperationOptionRead:
-	case kIODMACommandPerformOperationOptionWrite:
-
-		if (!data) {
-			ret = kIOReturnBadArgument;
-			break;
-		}
-		if (length > data->getLength()) {
-			ret = kIOReturnBadArgument;
-			break;
-		}
-		if (kIODMACommandPerformOperationOptionWrite == options) {
-			copied = data->readBytes(mdOffset, buffer.data(), mdLength);
-			if (copied != mdLength) {
-				ret = kIOReturnUnderrun;
-				break;
-			}
-			copiedDMA = writeBytes(dmaOffset, buffer.data(), length);
-			if (copiedDMA != length) {
-				ret = kIOReturnUnderrun;
-				break;
-			}
-		} else {       /* kIODMACommandPerformOperationOptionRead */
-			copiedDMA = readBytes(dmaOffset, buffer.data(), length);
-			if (copiedDMA != length) {
-				ret = kIOReturnUnderrun;
-				break;
-			}
-			copied = data->writeBytes(mdOffset, buffer.data(), mdLength);
-			if (copied != mdLength) {
-				ret = kIOReturnUnderrun;
-				break;
-			}
-		}
-		ret = kIOReturnSuccess;
-		break;
-	default:
-		ret = kIOReturnBadArgument;
-		break;
-	}
-
-	return ret;
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-static kern_return_t
-OSActionCreateWithTypeNameInternal(OSObject * target, uint64_t targetmsgid, uint64_t msgid, size_t referenceSize, OSString * typeName, bool fromKernel, OSAction ** action)
-{
-	OSAction * inst = NULL;
-	void * reference = NULL; // must release
-	const OSSymbol *sym = NULL; // must release
-	OSObject *obj = NULL; // must release
-	const OSMetaClass *actionMetaClass = NULL; // do not release
-	kern_return_t ret;
-
-	if (fromKernel && typeName) {
-		/* The action is being constructed in the kernel with a type name */
-		sym = OSSymbol::withString(typeName);
-		actionMetaClass = OSMetaClass::getMetaClassWithName(sym);
-		if (actionMetaClass && actionMetaClass->getSuperClass() == OSTypeID(OSAction)) {
-			obj = actionMetaClass->alloc();
-			if (!obj) {
-				ret = kIOReturnNoMemory;
-				goto finish;
-			}
-			inst = OSDynamicCast(OSAction, obj);
-			obj = NULL; // prevent release
-			assert(inst); // obj is a subclass of OSAction so the dynamic cast should always work
-		} else {
-			DKLOG("Attempted to create action object with type \"%s\" which does not inherit from OSAction\n", typeName->getCStringNoCopy());
-			ret = kIOReturnBadArgument;
-			goto finish;
-		}
-	} else {
-		inst = OSTypeAlloc(OSAction);
-		if (!inst) {
-			ret = kIOReturnNoMemory;
-			goto finish;
-		}
-	}
-
-	if (referenceSize != 0) {
-		reference = IONewZeroData(uint8_t, referenceSize);
-		if (reference == NULL) {
-			ret = kIOReturnNoMemory;
-			goto finish;
-		}
-	}
-
-	inst->ivars = IONewZero(OSAction_IVars, 1);
-	if (!inst->ivars) {
-		ret = kIOReturnNoMemory;
-		goto finish;
-	}
-	if (target) {
-		target->retain();
-		if (!fromKernel && !OSDynamicCast(IOService, target)) {
-			IOUserServer * us;
-			us = (typeof(us))thread_iokit_tls_get(0);
-			inst->ivars->userServer = OSDynamicCast(IOUserServer, us);
-			assert(inst->ivars->userServer);
-			inst->ivars->userServer->retain();
-		}
-	}
+	target->retain();
 	inst->ivars->target        = target;
 	inst->ivars->targetmsgid   = targetmsgid;
 	inst->ivars->msgid         = msgid;
-
-	inst->ivars->reference     = reference;
 	inst->ivars->referenceSize = referenceSize;
-	reference = NULL; // prevent release
-
-	if (typeName) {
-		typeName->retain();
-	}
-	inst->ivars->typeName      = typeName;
 
 	*action = inst;
-	inst = NULL; // prevent release
-	ret = kIOReturnSuccess;
-
-finish:
-	OSSafeReleaseNULL(obj);
-	OSSafeReleaseNULL(sym);
-	OSSafeReleaseNULL(inst);
-	if (reference) {
-		IODeleteData(reference, uint8_t, referenceSize);
-	}
-
-	return ret;
-}
-
-kern_return_t
-OSAction::Create(OSAction_Create_Args)
-{
-	return OSAction::CreateWithTypeName(target, targetmsgid, msgid, referenceSize, NULL, action);
-}
-
-kern_return_t
-OSAction::CreateWithTypeName(OSAction_CreateWithTypeName_Args)
-{
-	return OSActionCreateWithTypeNameInternal(target, targetmsgid, msgid, referenceSize, typeName, true, action);
-}
-
-kern_return_t
-OSAction::Create_Impl(
-	OSObject * target,
-	uint64_t targetmsgid,
-	uint64_t msgid,
-	size_t referenceSize,
-	OSAction ** action)
-{
-	return OSAction::CreateWithTypeName_Impl(target, targetmsgid, msgid, referenceSize, NULL, action);
-}
-
-kern_return_t
-OSAction::CreateWithTypeName_Impl(
-	OSObject * target,
-	uint64_t targetmsgid,
-	uint64_t msgid,
-	size_t referenceSize,
-	OSString * typeName,
-	OSAction ** action)
-{
-	return OSActionCreateWithTypeNameInternal(target, targetmsgid, msgid, referenceSize, typeName, false, action);
+
+	return kIOReturnSuccess;
 }
 
 void
@@ -1377,13 +527,7 @@
 			ivars->abortedHandler = NULL;
 		}
 		OSSafeReleaseNULL(ivars->target);
-		OSSafeReleaseNULL(ivars->typeName);
-		OSSafeReleaseNULL(ivars->userServer);
-		if (ivars->reference) {
-			assert(ivars->referenceSize > 0);
-			IODeleteData(ivars->reference, uint8_t, ivars->referenceSize);
-		}
-		IOSafeDeleteNULL(ivars, OSAction_IVars, 1);
+		IOSafeDeleteNULL(ivars, uint8_t, ivars->referenceSize + sizeof(OSAction_IVars));
 	}
 	return super::free();
 }
@@ -1391,8 +535,8 @@
 void *
 OSAction::GetReference()
 {
-	assert(ivars && ivars->referenceSize && ivars->reference);
-	return ivars->reference;
+	assert(ivars && ivars->referenceSize);
+	return &ivars->reference[0];
 }
 
 kern_return_t
@@ -1405,16 +549,12 @@
 void
 OSAction::Aborted_Impl(void)
 {
-	if (!os_atomic_cmpxchg(&ivars->aborted, false, true, relaxed)) {
-		// already aborted
-		return;
-	}
 	if (ivars->abortedHandler) {
 		ivars->abortedHandler();
 	}
 }
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
 
 struct IODispatchSource_IVars {
 	queue_chain_t           link;
@@ -1431,7 +571,7 @@
 		return false;
 	}
 
-	ivars = IOMallocType(IODispatchSource_IVars);
+	ivars = IONewZero(IODispatchSource_IVars, 1);
 
 	ivars->source = this;
 
@@ -1441,38 +581,24 @@
 void
 IODispatchSource::free()
 {
-	IOFreeType(ivars, IODispatchSource_IVars);
+	IOSafeDeleteNULL(ivars, IODispatchSource_IVars, 1);
 	super::free();
 }
 
-kern_return_t
-IODispatchSource::SetEnable_Impl(
-	bool enable)
-{
-	return SetEnableWithCompletion(enable, NULL);
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
 
 struct IOInterruptDispatchSource_IVars {
 	IOService    * provider;
 	uint32_t       intIndex;
-	uint32_t       flags;
-	int            interruptType;
 	IOSimpleLock * lock;
 	thread_t       waiter;
 	uint64_t       count;
 	uint64_t       time;
 	OSAction     * action;
 	bool           enable;
-	bool           canceled;
 };
 
-void
-IOInterruptDispatchSourceInterrupt(OSObject * target, void * refCon,
-    IOService * nub, int source );
-
-void
+static void
 IOInterruptDispatchSourceInterrupt(OSObject * target, void * refCon,
     IOService * nub, int source )
 {
@@ -1481,32 +607,19 @@
 
 	is = IOSimpleLockLockDisableInterrupt(ivars->lock);
 	ivars->count++;
-	ivars->time = (kIOInterruptSourceContinuousTime & ivars->flags)
-	    ? mach_continuous_time() : mach_absolute_time();
 	if (ivars->waiter) {
+		ivars->time = mach_absolute_time();
 		thread_wakeup_thread((event_t) ivars, ivars->waiter);
 		ivars->waiter = NULL;
 	}
-	if (kIOInterruptTypeLevel & ivars->interruptType) {
-		ivars->provider->disableInterrupt(ivars->intIndex);
-	}
 	IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
 }
 
 kern_return_t
-IOInterruptDispatchSource::Create_Impl(
-	IOService * provider,
-	uint32_t indexAndFlags,
-	IODispatchQueue * queue,
-	IOInterruptDispatchSource ** source)
+IMPL(IOInterruptDispatchSource, Create)
 {
 	IOReturn ret;
 	IOInterruptDispatchSource * inst;
-	uint32_t index;
-	uint32_t flags;
-
-	index = indexAndFlags & kIOInterruptSourceIndexMask;
-	flags = indexAndFlags & ~kIOInterruptSourceIndexMask;
 
 	inst = OSTypeAlloc(IOInterruptDispatchSource);
 	if (!inst->init()) {
@@ -1516,37 +629,12 @@
 
 	inst->ivars->lock = IOSimpleLockAlloc();
 
-	ret = provider->getInterruptType(index, &inst->ivars->interruptType);
-	if (kIOReturnSuccess != ret) {
-		OSSafeReleaseNULL(inst);
-		return ret;
-	}
 	ret = provider->registerInterrupt(index, inst, IOInterruptDispatchSourceInterrupt, inst->ivars);
 	if (kIOReturnSuccess == ret) {
 		inst->ivars->intIndex = index;
-		inst->ivars->flags    = flags;
 		inst->ivars->provider = provider;
-		inst->ivars->provider->retain();
 		*source = inst;
 	}
-	return ret;
-}
-
-kern_return_t
-IOInterruptDispatchSource::GetInterruptType_Impl(
-	IOService * provider,
-	uint32_t index,
-	uint64_t * interruptType)
-{
-	IOReturn ret;
-	int      type;
-
-	*interruptType = 0;
-	ret = provider->getInterruptType(index, &type);
-	if (kIOReturnSuccess == ret) {
-		*interruptType = type;
-	}
-
 	return ret;
 }
 
@@ -1556,7 +644,10 @@
 	if (!super::init()) {
 		return false;
 	}
-	ivars = IOMallocType(IOInterruptDispatchSource_IVars);
+	ivars = IONewZero(IOInterruptDispatchSource_IVars, 1);
+	if (!ivars) {
+		return false;
+	}
 
 	return true;
 }
@@ -1564,23 +655,20 @@
 void
 IOInterruptDispatchSource::free()
 {
+	IOReturn ret;
+
 	if (ivars && ivars->provider) {
-		(void) ivars->provider->unregisterInterrupt(ivars->intIndex);
-		ivars->provider->release();
-	}
-
-	if (ivars && ivars->lock) {
-		IOSimpleLockFree(ivars->lock);
-	}
-
-	IOFreeType(ivars, IOInterruptDispatchSource_IVars);
+		ret = ivars->provider->unregisterInterrupt(ivars->intIndex);
+		assert(kIOReturnSuccess == ret);
+	}
+
+	IOSafeDeleteNULL(ivars, IOInterruptDispatchSource_IVars, 1);
 
 	super::free();
 }
 
 kern_return_t
-IOInterruptDispatchSource::SetHandler_Impl(
-	OSAction * action)
+IMPL(IOInterruptDispatchSource, SetHandler)
 {
 	IOReturn ret;
 	OSAction * oldAction;
@@ -1598,9 +686,7 @@
 }
 
 kern_return_t
-IOInterruptDispatchSource::SetEnableWithCompletion_Impl(
-	bool enable,
-	IODispatchSourceCancelHandler handler)
+IMPL(IOInterruptDispatchSource, SetEnableWithCompletion)
 {
 	IOReturn ret;
 	IOInterruptState is;
@@ -1608,11 +694,6 @@
 	if (enable == ivars->enable) {
 		return kIOReturnSuccess;
 	}
-
-	if (ivars->canceled) {
-		return kIOReturnUnsupported;
-	}
-	assert(ivars->provider != NULL);
 
 	if (enable) {
 		is = IOSimpleLockLockDisableInterrupt(ivars->lock);
@@ -1630,41 +711,16 @@
 }
 
 kern_return_t
-IOInterruptDispatchSource::Cancel_Impl(
-	IODispatchSourceCancelHandler handler)
-{
-	IOInterruptState is;
-	IOService * provider;
-
-	is = IOSimpleLockLockDisableInterrupt(ivars->lock);
-	ivars->canceled = true;
-	if (ivars->waiter) {
-		thread_wakeup_thread((event_t) ivars, ivars->waiter);
-		ivars->waiter = NULL;
-	}
-	provider = ivars->provider;
-	if (provider) {
-		ivars->provider = NULL;
-	}
-	IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
-
-	if (provider) {
-		(void) provider->unregisterInterrupt(ivars->intIndex);
-		provider->release();
-	}
-
-	return kIOReturnSuccess;
-}
-
-kern_return_t
-IOInterruptDispatchSource::CheckForWork_Impl(
-	const IORPC rpc,
-	bool synchronous)
+IMPL(IODispatchSource, SetEnable)
+{
+	return SetEnableWithCompletion(enable, NULL);
+}
+
+kern_return_t
+IMPL(IOInterruptDispatchSource, CheckForWork)
 {
 	IOReturn         ret = kIOReturnNotReady;
 	IOInterruptState is;
-	bool             willWait;
-	bool             canceled;
 	wait_result_t    waitResult;
 	uint64_t         icount;
 	uint64_t         itime;
@@ -1673,40 +729,24 @@
 	self = current_thread();
 	icount = 0;
 	do {
-		willWait = false;
 		is = IOSimpleLockLockDisableInterrupt(ivars->lock);
-		canceled = ivars->canceled;
-		if (!canceled) {
-			if ((icount = ivars->count)) {
-				itime = ivars->time;
-				ivars->count = 0;
-				waitResult = THREAD_AWAKENED;
-			} else if (synchronous) {
-				assert(NULL == ivars->waiter);
-				ivars->waiter = self;
-				waitResult = assert_wait((event_t) ivars, THREAD_INTERRUPTIBLE);
-			}
-			willWait = (synchronous && (waitResult == THREAD_WAITING));
-			if (willWait && (kIOInterruptTypeLevel & ivars->interruptType) && ivars->enable) {
-				IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
-				ivars->provider->enableInterrupt(ivars->intIndex);
-			} else {
-				IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
-			}
-		} else {
-			IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
-		}
-		if (willWait) {
+		if ((icount = ivars->count)) {
+			itime = ivars->time;
+			ivars->count = 0;
+			waitResult = THREAD_AWAKENED;
+		} else if (synchronous) {
+			assert(NULL == ivars->waiter);
+			ivars->waiter = self;
+			waitResult = assert_wait((event_t) ivars, THREAD_INTERRUPTIBLE);
+		}
+		IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
+		if (synchronous && (waitResult == THREAD_WAITING)) {
 			waitResult = thread_block(THREAD_CONTINUE_NULL);
 			if (THREAD_INTERRUPTED == waitResult) {
-				is = IOSimpleLockLockDisableInterrupt(ivars->lock);
-				ivars->waiter = NULL;
-				IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
-				canceled = true;
 				break;
 			}
 		}
-	} while (synchronous && !icount && !canceled);
+	} while (synchronous && !icount);
 
 	if (icount && ivars->action) {
 		ret = InterruptOccurred(rpc, ivars->action, icount, itime);
@@ -1716,461 +756,11 @@
 }
 
 void
-IOInterruptDispatchSource::InterruptOccurred_Impl(
-	OSAction * action,
-	uint64_t count,
-	uint64_t time)
-{
-}
-
-kern_return_t
-IOInterruptDispatchSource::GetLastInterrupt_Impl(
-	uint64_t  * pCount,
-	uint64_t  * pTime)
-{
-	IOInterruptState is;
-	uint64_t count, time;
-
-	is = IOSimpleLockLockDisableInterrupt(ivars->lock);
-	count = ivars->count;
-	time  = ivars->time;
-	IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
-
-	if (pCount) {
-		*pCount = count;
-	}
-	if (pTime) {
-		*pTime = time;
-	}
-	return kIOReturnSuccess;
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-enum {
-	kIOServiceNotificationTypeCount = kIOServiceNotificationTypeLast + 1,
-};
-
-struct IOServiceNotificationDispatchSource_IVars {
-	OSObject     * serverName;
-	OSAction     * action;
-	IOLock       * lock;
-	IONotifier   * notifier;
-	OSDictionary * interestNotifiers;
-	OSBoundedArray<OSArray *, kIOServiceNotificationTypeCount> pending;
-	bool           enable;
-};
-
-kern_return_t
-IOServiceNotificationDispatchSource::Create_Impl(
-	OSDictionary * matching,
-	uint64_t options,
-	IODispatchQueue * queue,
-	IOServiceNotificationDispatchSource ** notification)
-{
-	IOUserServer * us;
-	IOReturn       ret;
-	IOServiceNotificationDispatchSource * inst;
-
-	inst = OSTypeAlloc(IOServiceNotificationDispatchSource);
-	if (!inst->init()) {
-		OSSafeReleaseNULL(inst);
-		return kIOReturnNoMemory;
-	}
-
-	us = (typeof(us))thread_iokit_tls_get(0);
-	assert(OSDynamicCast(IOUserServer, us));
-	if (!us) {
-		OSSafeReleaseNULL(inst);
-		return kIOReturnError;
-	}
-	inst->ivars->serverName = us->copyProperty(gIOUserServerNameKey);
-	if (!inst->ivars->serverName) {
-		OSSafeReleaseNULL(inst);
-		return kIOReturnNoMemory;
-	}
-
-	inst->ivars->lock    = IOLockAlloc();
-	if (!inst->ivars->lock) {
-		OSSafeReleaseNULL(inst);
-		return kIOReturnNoMemory;
-	}
-	for (uint32_t idx = 0; idx < kIOServiceNotificationTypeCount; idx++) {
-		inst->ivars->pending[idx] = OSArray::withCapacity(4);
-		if (!inst->ivars->pending[idx]) {
-			OSSafeReleaseNULL(inst);
-			return kIOReturnNoMemory;
-		}
-	}
-	inst->ivars->interestNotifiers = OSDictionary::withCapacity(4);
-	if (!inst->ivars->interestNotifiers) {
-		OSSafeReleaseNULL(inst);
-		return kIOReturnNoMemory;
-	}
-
-	inst->ivars->notifier = IOService::addMatchingNotification(gIOMatchedNotification, matching, 0 /*priority*/,
-	    ^bool (IOService * newService, IONotifier * notifier) {
-		bool         notifyReady = false;
-		IONotifier * interest = NULL;
-		OSObject   * serverName;
-		bool         okToUse;
-
-		serverName = newService->copyProperty(gIOUserServerNameKey);
-		okToUse = (serverName && inst->ivars->serverName->isEqualTo(serverName));
-		OSSafeReleaseNULL(serverName);
-		if (!okToUse) {
-		        OSObject * prop;
-		        OSObject * str;
-
-		        if (!newService->reserved->uvars || !newService->reserved->uvars->userServer) {
-		                return false;
-			}
-		        str = OSString::withCStringNoCopy(kIODriverKitAllowsPublishEntitlementsKey);
-		        if (!str) {
-		                return false;
-			}
-		        okToUse = newService->reserved->uvars->userServer->checkEntitlements(str, NULL, NULL);
-		        if (!okToUse) {
-		                if (kIODKLogSetup & gIODKDebug) {
-		                        DKLOG(DKS ": publisher entitlements check failed\n", DKN(newService));
-				}
-		                return false;
-			}
-		        prop = newService->copyProperty(kIODriverKitPublishEntitlementsKey);
-		        if (!prop) {
-		                return false;
-			}
-		        okToUse = us->checkEntitlements(prop, NULL, NULL);
-		        if (!okToUse) {
-		                if (kIODKLogSetup & gIODKDebug) {
-		                        DKLOG(DKS ": subscriber entitlements check failed\n", DKN(newService));
-				}
-		                return false;
-			}
-		}
-
-		IOLockLock(inst->ivars->lock);
-		notifyReady = (0 == inst->ivars->pending[kIOServiceNotificationTypeMatched]->getCount());
-		inst->ivars->pending[kIOServiceNotificationTypeMatched]->setObject(newService);
-		bool needInterest = (NULL == inst->ivars->interestNotifiers->getObject((const OSSymbol *) newService));
-		IOLockUnlock(inst->ivars->lock);
-
-		if (needInterest) {
-		        interest = newService->registerInterest(gIOGeneralInterest,
-		        ^IOReturn (uint32_t messageType, IOService * provider,
-		        void * messageArgument, size_t argSize) {
-				IONotifier * interest;
-				bool         notifyReady = false;
-
-				// after the notifier remove, IOServiceNotificationDispatchSource::free
-				// will not wait for this code to complete
-				if (!inst->taggedTryRetain(NULL)) {
-				        return kIOReturnSuccess;
-				}
-
-				switch (messageType) {
-				case kIOMessageServiceIsTerminated:
-					IOLockLock(inst->ivars->lock);
-					notifyReady = (0 == inst->ivars->pending[kIOServiceNotificationTypeTerminated]->getCount());
-					inst->ivars->pending[kIOServiceNotificationTypeTerminated]->setObject(provider);
-					if (inst->ivars->interestNotifiers != NULL) {
-					        interest = (typeof(interest))inst->ivars->interestNotifiers->getObject((const OSSymbol *) newService);
-					        assert(interest);
-					        interest->remove();
-					        inst->ivars->interestNotifiers->removeObject((const OSSymbol *) newService);
-					}
-					IOLockUnlock(inst->ivars->lock);
-					break;
-				default:
-					break;
-				}
-				if (notifyReady && inst->ivars->action) {
-				        inst->ServiceNotificationReady(inst->ivars->action);
-				}
-				inst->release();
-				return kIOReturnSuccess;
-			});
-		}
-		if (interest) {
-		        IOLockLock(inst->ivars->lock);
-		        inst->ivars->interestNotifiers->setObject((const OSSymbol *) newService, interest);
-		        IOLockUnlock(inst->ivars->lock);
-		}
-		if (notifyReady) {
-		        if (inst->ivars->action) {
-		                inst->ServiceNotificationReady(inst->ivars->action);
-			}
-		}
-		return false;
-	});
-
-	if (!inst->ivars->notifier) {
-		OSSafeReleaseNULL(inst);
-		ret = kIOReturnError;
-	}
-
-	*notification = inst;
-	ret = kIOReturnSuccess;
-
-	return ret;
-}
-
-kern_return_t
-IOServiceNotificationDispatchSource::CopyNextNotification_Impl(
-	uint64_t * type,
-	IOService ** service,
-	uint64_t * options)
-{
-	IOService * next;
-	uint32_t    idx;
-
-	IOLockLock(ivars->lock);
-	for (idx = 0; idx < kIOServiceNotificationTypeCount; idx++) {
-		next = (IOService *) ivars->pending[idx]->getObject(0);
-		if (next) {
-			next->retain();
-			ivars->pending[idx]->removeObject(0);
-			break;
-		}
-	}
-	IOLockUnlock(ivars->lock);
-
-	if (idx == kIOServiceNotificationTypeCount) {
-		idx = kIOServiceNotificationTypeNone;
-	}
-	*type    = idx;
-	*service = next;
-	*options = 0;
-
-	return kIOReturnSuccess;
-}
-
-bool
-IOServiceNotificationDispatchSource::init()
-{
-	if (!super::init()) {
-		return false;
-	}
-	ivars = IOMallocType(IOServiceNotificationDispatchSource_IVars);
-
-	return true;
-}
-
-void
-IOServiceNotificationDispatchSource::free()
-{
-	if (ivars) {
-		if (ivars->notifier) {
-			ivars->notifier->remove();
-			ivars->notifier = NULL;
-		}
-		if (ivars->interestNotifiers) {
-			OSDictionary * savedInterestNotifiers = NULL;
-
-			// the lock is always initialized first, so it should exist
-			assert(ivars->lock);
-
-			// Prevent additional changes to interestNotifiers
-			IOLockLock(ivars->lock);
-			savedInterestNotifiers = ivars->interestNotifiers;
-			ivars->interestNotifiers = NULL;
-			IOLockUnlock(ivars->lock);
-
-			// Remove all interest notifiers
-			savedInterestNotifiers->iterateObjects(^bool (const OSSymbol * key, OSObject * object) {
-				IONotifier * interest = (typeof(interest))object;
-				interest->remove();
-				return false;
-			});
-			OSSafeReleaseNULL(savedInterestNotifiers);
-		}
-		for (uint32_t idx = 0; idx < kIOServiceNotificationTypeCount; idx++) {
-			OSSafeReleaseNULL(ivars->pending[idx]);
-		}
-		OSSafeReleaseNULL(ivars->action);
-		if (ivars->lock) {
-			IOLockFree(ivars->lock);
-			ivars->lock = NULL;
-		}
-		OSSafeReleaseNULL(ivars->serverName);
-		IOFreeType(ivars, IOServiceNotificationDispatchSource_IVars);
-	}
-
-	super::free();
-}
-
-kern_return_t
-IOServiceNotificationDispatchSource::SetHandler_Impl(
-	OSAction * action)
-{
-	IOReturn ret;
-	bool     notifyReady;
-
-	notifyReady = false;
-
-	IOLockLock(ivars->lock);
-	OSSafeReleaseNULL(ivars->action);
-	action->retain();
-	ivars->action = action;
-	if (action) {
-		for (uint32_t idx = 0; idx < kIOServiceNotificationTypeCount; idx++) {
-			notifyReady = (ivars->pending[idx]->getCount());
-			if (notifyReady) {
-				break;
-			}
-		}
-	}
-	IOLockUnlock(ivars->lock);
-
-	if (notifyReady) {
-		ServiceNotificationReady(action);
-	}
-	ret = kIOReturnSuccess;
-
-	return ret;
-}
-
-kern_return_t
-IOServiceNotificationDispatchSource::SetEnableWithCompletion_Impl(
-	bool enable,
-	IODispatchSourceCancelHandler handler)
-{
-	if (enable == ivars->enable) {
-		return kIOReturnSuccess;
-	}
-
-	IOLockLock(ivars->lock);
-	ivars->enable = enable;
-	IOLockUnlock(ivars->lock);
-
-	return kIOReturnSuccess;
-}
-
-kern_return_t
-IOServiceNotificationDispatchSource::Cancel_Impl(
-	IODispatchSourceCancelHandler handler)
-{
-	return kIOReturnUnsupported;
-}
-
-kern_return_t
-IOServiceNotificationDispatchSource::CheckForWork_Impl(
-	const IORPC rpc,
-	bool synchronous)
-{
-	return kIOReturnNotReady;
-}
-
-kern_return_t
-IOServiceNotificationDispatchSource::DeliverNotifications(IOServiceNotificationBlock block)
-{
-	return kIOReturnUnsupported;
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-OSDictionary *
-IOService::CreatePropertyMatchingDictionary(const char * key, OSObjectPtr value, OSDictionary * matching)
-{
-	OSDictionary   * result;
-	const OSSymbol * keySym;
-
-	keySym = OSSymbol::withCString(key);
-	result = propertyMatching(keySym, (const OSObject *) value, matching);
-	OSSafeReleaseNULL(keySym);
-
-	return result;
-}
-
-OSDictionary *
-IOService::CreatePropertyMatchingDictionary(const char * key, const char * stringValue, OSDictionary * matching)
-{
-	OSDictionary * result;
-	OSString     * value;
-
-	value = OSString::withCString(stringValue);
-	result = CreatePropertyMatchingDictionary(key, value, matching);
-	OSSafeReleaseNULL(value);
-
-	return result;
-}
-
-OSDictionary *
-IOService::CreateKernelClassMatchingDictionary(OSString * className, OSDictionary * matching)
-{
-	if (!className) {
-		return NULL;
-	}
-	if (!matching) {
-		matching = OSDictionary::withCapacity(2);
-		if (!matching) {
-			return NULL;
-		}
-	}
-	matching->setObject(kIOProviderClassKey, className);
-
-	return matching;
-}
-
-OSDictionary *
-IOService::CreateKernelClassMatchingDictionary(const char * className, OSDictionary * matching)
-{
-	OSDictionary * result;
-	OSString     * string;
-
-	string = OSString::withCString(className);
-	result = CreateKernelClassMatchingDictionary(string, matching);
-	OSSafeReleaseNULL(string);
-
-	return result;
-}
-
-OSDictionary *
-IOService::CreateUserClassMatchingDictionary(OSString * className, OSDictionary * matching)
-{
-	return CreatePropertyMatchingDictionary(kIOUserClassKey, className, matching);
-}
-
-OSDictionary *
-IOService::CreateUserClassMatchingDictionary(const char * className, OSDictionary * matching)
-{
-	return CreatePropertyMatchingDictionary(kIOUserClassKey, className, matching);
-}
-
-OSDictionary *
-IOService::CreateNameMatchingDictionary(OSString * serviceName, OSDictionary * matching)
-{
-	if (!serviceName) {
-		return NULL;
-	}
-	if (!matching) {
-		matching = OSDictionary::withCapacity(2);
-		if (!matching) {
-			return NULL;
-		}
-	}
-	matching->setObject(kIONameMatchKey, serviceName);
-
-	return matching;
-}
-
-OSDictionary *
-IOService::CreateNameMatchingDictionary(const char * serviceName, OSDictionary * matching)
-{
-	OSDictionary * result;
-	OSString     * string;
-
-	string = OSString::withCString(serviceName);
-	result = CreateNameMatchingDictionary(string, matching);
-	OSSafeReleaseNULL(string);
-
-	return result;
-}
-
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+IMPL(IOInterruptDispatchSource, InterruptOccurred)
+{
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
 
 kern_return_t
 IOUserServer::waitInterruptTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6)
@@ -2181,8 +771,6 @@
 	IOInterruptDispatchSource_IVars * ivars;
 	IOInterruptDispatchSourcePayload payload;
 
-	bool             willWait;
-	bool             canceled;
 	wait_result_t    waitResult;
 	thread_t         self;
 
@@ -2200,40 +788,24 @@
 		ivars = interrupt->ivars;
 		payload.count = 0;
 		do {
-			willWait = false;
 			is = IOSimpleLockLockDisableInterrupt(ivars->lock);
-			canceled = ivars->canceled;
-			if (!canceled) {
-				if ((payload.count = ivars->count)) {
-					payload.time = ivars->time;
-					ivars->count = 0;
-					waitResult = THREAD_AWAKENED;
-				} else {
-					assert(NULL == ivars->waiter);
-					ivars->waiter = self;
-					waitResult = assert_wait((event_t) ivars, THREAD_INTERRUPTIBLE);
-				}
-				willWait = (waitResult == THREAD_WAITING);
-				if (willWait && (kIOInterruptTypeLevel & ivars->interruptType) && ivars->enable) {
-					IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
-					ivars->provider->enableInterrupt(ivars->intIndex);
-				} else {
-					IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
-				}
+			if ((payload.count = ivars->count)) {
+				payload.time = ivars->time;
+				ivars->count = 0;
+				waitResult = THREAD_AWAKENED;
 			} else {
-				IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
-			}
-			if (willWait) {
+				assert(NULL == ivars->waiter);
+				ivars->waiter = self;
+				waitResult = assert_wait((event_t) ivars, THREAD_INTERRUPTIBLE);
+			}
+			IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
+			if (waitResult == THREAD_WAITING) {
 				waitResult = thread_block(THREAD_CONTINUE_NULL);
 				if (THREAD_INTERRUPTED == waitResult) {
-					is = IOSimpleLockLockDisableInterrupt(ivars->lock);
-					ivars->waiter = NULL;
-					IOSimpleLockUnlockEnableInterrupt(ivars->lock, is);
-					canceled = true;
 					break;
 				}
 			}
-		} while (!payload.count && !canceled);
+		} while (!payload.count);
 		ret = (payload.count ? kIOReturnSuccess : kIOReturnAborted);
 	}
 
@@ -2249,22 +821,16 @@
 	return ret;
 }
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-kern_return_t
-IOUserServer::Create_Impl(
-	const char * name,
-	uint64_t tag,
-	uint64_t options,
-	OSString * bundleID,
-	IOUserServer ** server)
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
+
+kern_return_t
+IMPL(IOUserServer, Create)
 {
 	IOReturn          ret;
 	IOUserServer    * us;
 	const OSSymbol  * sym;
 	OSNumber        * serverTag;
 	io_name_t         rname;
-	OSKext          * kext;
 
 	us = (typeof(us))thread_iokit_tls_get(0);
 	assert(OSDynamicCast(IOUserServer, us));
@@ -2275,22 +841,6 @@
 		return kIOReturnError;
 	}
 
-	if (bundleID) {
-		kext = OSKext::lookupKextWithIdentifier(bundleID->getCStringNoCopy());
-		if (kext) {
-			us->setTaskLoadTag(kext);
-			us->setDriverKitUUID(kext);
-			us->setDriverKitStatistics(kext);
-			OSKext::OSKextLogDriverKitInfoLoad(kext);
-			OSSafeReleaseNULL(kext);
-		} else {
-			DKLOG(DKS "::Create(" DKS "): could not find OSKext for %s\n", DKN(us), name, tag, bundleID->getCStringNoCopy());
-		}
-
-		us->fAllocationName = kern_allocation_name_allocate(bundleID->getCStringNoCopy(), 0);
-		assert(us->fAllocationName);
-	}
-
 	sym       = OSSymbol::withCString(name);
 	serverTag = OSNumber::withNumber(tag, 64);
 
@@ -2311,51 +861,22 @@
 }
 
 kern_return_t
-IOUserServer::Panic_Impl(const char * reason)
-{
-	if (isPlatformDriver()) {
-		if (strnlen(reason, kIOUserServrMaxPanicReasonLength) == kIOUserServrMaxPanicReasonLength) {
-			// Invalid panic message, panic anyways
-			panic("%s: dext requested panic", getName());
-		} else {
-			panic("%s: dext requested panic: \"%s\"", getName(), reason);
-		}
-		return kIOReturnSuccess;
-	}
-	return kIOReturnNotPermitted;
-}
-
-kern_return_t
-IOUserServer::RegisterService_Impl()
-{
-	kern_return_t ret = IOService::RegisterService_Impl();
-
-	return ret;
-}
-
-kern_return_t
-IOUserServer::Exit_Impl(
-	const char * reason)
+IMPL(IOUserServer, Exit)
 {
 	return kIOReturnUnsupported;
 }
 
 kern_return_t
-IOUserServer::LoadModule_Impl(
-	const char * path)
+IMPL(IOUserServer, LoadModule)
 {
 	return kIOReturnUnsupported;
 }
 
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-kern_return_t
-IODispatchQueue::Create_Impl(
-	const char * name,
-	uint64_t options,
-	uint64_t priority,
-	IODispatchQueue ** queue)
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
+
+kern_return_t
+IMPL(IODispatchQueue, Create)
 {
 	IODispatchQueue * result;
 	IOUserServer    * us;
@@ -2365,7 +886,6 @@
 		return kIOReturnNoMemory;
 	}
 	if (!result->init()) {
-		OSSafeReleaseNULL(result);
 		return kIOReturnNoMemory;
 	}
 
@@ -2385,23 +905,19 @@
 }
 
 kern_return_t
-IODispatchQueue::SetPort_Impl(
-	mach_port_t port)
-{
-	if (MACH_PORT_NULL != ivars->serverPort) {
-		return kIOReturnNotReady;
-	}
-	ivars->serverPort = ipc_port_copy_send_mqueue(port);
-	if (ivars->serverPort == MACH_PORT_NULL) {
-		return kIOReturnBadArgument;
-	}
+IMPL(IODispatchQueue, SetPort)
+{
+	ivars->serverPort = port;
 	return kIOReturnSuccess;
 }
 
 bool
 IODispatchQueue::init()
 {
-	ivars = IOMallocType(IODispatchQueue_IVars);
+	ivars = IONewZero(IODispatchQueue_IVars, 1);
+	if (!ivars) {
+		return false;
+	}
 	ivars->queue = this;
 
 	return true;
@@ -2410,11 +926,7 @@
 void
 IODispatchQueue::free()
 {
-	if (ivars && ivars->serverPort) {
-		ipc_port_release_send(ivars->serverPort);
-		ivars->serverPort = MACH_PORT_NULL;
-	}
-	IOFreeType(ivars, IODispatchQueue_IVars);
+	IOSafeDeleteNULL(ivars, IODispatchQueue_IVars, 1);
 	super::free();
 }
 
@@ -2444,7 +956,7 @@
 	IORPCMessage    * message;
 
 	assert(rpc.sendSize >= (sizeof(IORPCMessageMach) + sizeof(IORPCMessage)));
-	message = rpc.kernelContent;
+	message = IORPCMessageFromMach(rpc.message, false);
 	if (!message) {
 		return kIOReturnIPCError;
 	}
@@ -2454,9 +966,6 @@
 	if (!(kIORPCMessageLocalHost & message->flags)) {
 		us = OSDynamicCast(IOUserServer, this);
 		if (!us) {
-			IOEventLink * eventLink = NULL;
-			IOWorkGroup * workgroup = NULL;
-
 			if ((action = OSDynamicCast(OSAction, this))) {
 				object = IOUserServer::target(action, message);
 			} else {
@@ -2466,12 +975,6 @@
 			    && service->reserved->uvars) {
 				// xxx other classes
 				us = service->reserved->uvars->userServer;
-			} else if (action) {
-				us = action->ivars->userServer;
-			} else if ((eventLink = OSDynamicCast(IOEventLink, object))) {
-				us = eventLink->ivars->userServer;
-			} else if ((workgroup = OSDynamicCast(IOWorkGroup, object))) {
-				us = workgroup->ivars->userServer;
 			}
 		}
 	}
@@ -2487,10 +990,7 @@
 		if (kIODKLogIPC & gIODKDebug) {
 			DKLOG("OSMetaClassBase::Invoke kernel %s 0x%qx\n", getMetaClass()->getClassName(), message->msgid);
 		}
-		void * prior = thread_iokit_tls_get(0);
-		thread_iokit_tls_set(0, NULL);
 		ret = Dispatch(rpc);
-		thread_iokit_tls_set(0, prior);
 	}
 
 	return ret;
@@ -2507,25 +1007,21 @@
 kern_return_t
 OSUserMetaClass::Dispatch(IORPC rpc)
 {
-	if (meta) {
-		return const_cast<OSMetaClass *>(meta)->Dispatch(rpc);
-	} else {
-		return kIOReturnUnsupported;
-	}
+	return const_cast<OSMetaClass *>(meta)->Dispatch(rpc);
 }
 
 void
 OSUserMetaClass::free()
 {
 	if (queueNames) {
-		IOFreeData(queueNames, sizeof(IOPStrings) + queueNames->dataSize * sizeof(char));
+		IOFree(queueNames, sizeof(IOPStrings) + queueNames->dataSize * sizeof(char));
 		queueNames = NULL;
 	}
 	if (description) {
-		IOFreeData(description, description->descriptionSize);
+		IOFree(description, description->descriptionSize);
 		description = NULL;
 	}
-	IODeleteData(methods, uint64_t, 2 * methodCount);
+	IOSafeDeleteNULL(methods, uint64_t, 2 * methodCount);
 	if (meta) {
 		meta->releaseMetaClass();
 	}
@@ -2600,53 +1096,74 @@
 	}
 
 	uuid_unparse(p_uuid, uuid_string);
-	new_uuid = OSData::withValue(p_uuid);
+	new_uuid = OSData::withBytes(p_uuid, sizeof(p_uuid));
 	kext->setDriverKitUUID(new_uuid);
 }
 
-void
-IOUserServer::setDriverKitStatistics(OSKext *kext)
-{
-	OSDextStatistics * statistics = kext->copyDextStatistics();
-	if (statistics == NULL) {
-		panic("Kext %s was not a DriverKit OSKext", kext->getIdentifierCString());
-	}
-	fStatistics = statistics;
-}
-
-IOReturn
-IOUserServer::setCheckInToken(IOUserServerCheckInToken *token)
-{
-	IOReturn ret = kIOReturnError;
-	if (token != NULL && fCheckInToken == NULL) {
-		token->retain();
-		fCheckInToken = token;
-		ret = fCheckInToken->complete();
-		iokit_clear_registered_ports(fOwningTask);
-	} else {
-		printf("%s: failed to set check in token. token=%p, fCheckInToken=%p\n", __FUNCTION__, token, fCheckInToken);
-	}
-	return ret;
-}
-
 bool
-IOUserServer::serviceMatchesCheckInToken(IOUserServerCheckInToken *token)
-{
-	if (token != NULL) {
-		bool result = token == fCheckInToken;
-		return result;
-	} else {
-		printf("%s: null check in token\n", __FUNCTION__);
-		return false;
-	}
-}
-
-// entitlements - dict of entitlements to check
-// prop - string - if present return true
-//      - array of strings - if any present return true
-//      - array of arrays of strings - in each leaf array all must be present
-//                                   - if any top level array succeeds return true
-// consumes one reference of prop
+IOUserServer::serviceMatchesCDHash(IOService *service)
+{
+	OSObject   *obj               = NULL;
+	bool        result            = false;
+	OSString   *requiredCDHashStr = NULL;
+	const char *requiredCDHash    = NULL;
+	char        taskCDHash[CS_CDHASH_LEN];
+
+	task_t owningTask = this->fOwningTask;
+	if (!owningTask) {
+		printf("%s: fOwningTask not found\n", __FUNCTION__);
+		goto out;
+	}
+
+	obj = service->copyProperty(gIOUserServerCDHashKey);
+	requiredCDHashStr = OSDynamicCast(OSString, obj);
+	if (!requiredCDHashStr) {
+		printf("%s: required cdhash not found as property of personality\n", __FUNCTION__);
+		goto out;
+	}
+
+	requiredCDHash = requiredCDHashStr->getCStringNoCopy();
+	if (!requiredCDHash) {
+		printf("%s: required cdhash unable to be read as string\n", __FUNCTION__);
+		goto out;
+	}
+
+	if (strlen(requiredCDHash) != CS_CDHASH_LEN * 2) {
+		printf("%s: required cdhash string has incorrect length\n", __FUNCTION__);
+		goto out;
+	}
+
+	get_task_cdhash(owningTask, taskCDHash);
+	for (int i = 0; i < (int)CS_CDHASH_LEN * 2; i++) {
+		uint8_t which  = (i + 1) & 0x1; /* 1 for upper nibble, 0 for lower */
+		uint8_t nibble = requiredCDHash[i];
+		uint8_t byte   = taskCDHash[i / 2];
+		if ('0' <= nibble && nibble <= '9') {
+			nibble -= '0';
+		} else if ('a' <= nibble && nibble <= 'f') {
+			nibble -= 'a' - 10;
+		} else if ('A' <= nibble && nibble <= 'F') {
+			nibble -= 'A' - 10;
+		} else {
+			printf("%s: required cdhash contains invalid token '%c'\n", __FUNCTION__, nibble);
+			goto out;
+		}
+
+		/*
+		 * Decide which half of the byte to compare
+		 */
+		if (nibble != (which ? (byte >> 4) : (byte & 0x0f))) {
+			printf("%s: required cdhash %s in personality does not match service\n", __FUNCTION__, requiredCDHash);
+			goto out;
+		}
+	}
+
+	result = true;
+out:
+	OSSafeReleaseNULL(obj);
+	return result;
+}
+
 bool
 IOUserServer::checkEntitlements(
 	OSDictionary * entitlements, OSObject * prop,
@@ -2658,7 +1175,6 @@
 		return true;
 	}
 	if (!entitlements) {
-		OSSafeReleaseNULL(prop);
 		return false;
 	}
 
@@ -2666,12 +1182,11 @@
 	if (dext) {
 		matching = dext->dictionaryWithProperties();
 		if (!matching) {
-			OSSafeReleaseNULL(prop);
 			return false;
 		}
 	}
 
-	bool allPresent __block = false;
+	bool allPresent __block;
 	prop->iterateObjects(^bool (OSObject * object) {
 		allPresent = false;
 		object->iterateObjects(^bool (OSObject * object) {
@@ -2683,10 +1198,8 @@
 			        matching->setObject(string, value);
 			}
 			allPresent = (NULL != value);
-			// early terminate if not found
 			return !allPresent;
 		});
-		// early terminate if found
 		return allPresent;
 	});
 
@@ -2698,12 +1211,6 @@
 	OSSafeReleaseNULL(prop);
 
 	return allPresent;
-}
-
-bool
-IOUserServer::checkEntitlements(OSObject * prop, IOService * provider, IOService * dext)
-{
-	return checkEntitlements(fEntitlements, prop, provider, dext);
 }
 
 bool
@@ -2735,40 +1242,9 @@
 IOReturn
 IOUserServer::exit(const char * reason)
 {
-	DKLOG(DKS "::exit(%s)\n", DKN(this), reason);
+	DKLOG("%s::exit(%s)\n", getName(), reason);
 	Exit(reason);
 	return kIOReturnSuccess;
-}
-
-IOReturn
-IOUserServer::kill(const char * reason)
-{
-	IOReturn ret = kIOReturnError;
-	if (fOwningTask != NULL) {
-		DKLOG(DKS"::kill(%s)\n", DKN(this), reason);
-		proc_t unsafe_proc = (proc_t)get_bsdtask_info(fOwningTask);
-		proc_t p = proc_ref_nowait(unsafe_proc);
-		if (p) {
-			taskbsd_kill_and_release(p);
-		}
-		ret = kIOReturnSuccess;
-	}
-	return ret;
-}
-
-void
-IOUserServer::emergencyPanicCoreDumpEnable()
-{
-#if DEVELOPMENT || DEBUG
-	if (isPlatformDriver()) {
-		// Enable coredump for the first party dext that is causing an imminent panic
-		// This is enabled on non-release without requiring an entitlement,
-		// so this coredump has only a generic name
-		char core_name[MACH_CORE_FILEHEADER_NAMELEN];
-		snprintf(core_name, sizeof(core_name), "dext-%d", pid_from_task(fOwningTask));
-		kern_register_userspace_coredump(fOwningTask, core_name, TRUE);
-	}
-#endif /* DEVELOPMENT || DEBUG */
 }
 
 OSObjectUserVars *
@@ -2789,8 +1265,8 @@
 	IOPStrings * array;
 	vm_size_t    alloc;
 	size_t       len;
+	const char * cstr;
 	const char * end;
-	OSBoundedPtr<const char> cstr;
 
 	if (userSize <= 1) {
 		return NULL;
@@ -2804,7 +1280,7 @@
 		assert(false);
 		return NULL;
 	}
-	array = (typeof(array))IOMallocData(alloc);
+	array = (typeof(array))IOMalloc(alloc);
 	if (!array) {
 		return NULL;
 	}
@@ -2812,9 +1288,9 @@
 	bcopy(string, (void *) &array->strings[0], userSize);
 
 	array->count = 0;
+	cstr = &array->strings[0];
 	end =  &array->strings[array->dataSize];
-	cstr = OSBoundedPtr<const char>(&array->strings[0], &array->strings[0], end);
-	while ((len = (unsigned char)cstr[0])) {
+	while ((len = cstr[0])) {
 		cstr++;
 		if ((cstr + len) >= end) {
 			break;
@@ -2823,7 +1299,7 @@
 		array->count++;
 	}
 	if (len) {
-		IOFreeData(array, alloc);
+		IOFree(array, alloc);
 		array = NULL;
 	}
 
@@ -2835,20 +1311,19 @@
 {
 	uint32_t     idx;
 	size_t       len, llen;
-	OSBoundedPtr<const char> cstr;
+	const char * cstr;
 	const char * end;
 
 	idx  = 0;
+	cstr = &array->strings[0];
 	end  =  &array->strings[array->dataSize];
-	cstr = OSBoundedPtr<const char>(&array->strings[0], &array->strings[0], end);
-
 	llen = strlen(look);
-	while ((len = (unsigned char)cstr[0])) {
+	while ((len = cstr[0])) {
 		cstr++;
 		if ((cstr + len) >= end) {
 			break;
 		}
-		if ((len == llen) && !strncmp(cstr.discard_bounds(), look, len)) {
+		if ((len == llen) && !strncmp(cstr, look, len)) {
 			return idx;
 		}
 		cstr += len;
@@ -2917,7 +1392,7 @@
 	const char     * resultClassName;
 	uint64_t         resultFlags;
 
-	mach_msg_size_t    replySize;
+	size_t             replySize;
 	uint32_t           methodCount;
 	const uint64_t   * methods;
 	IODispatchQueue  * queue;
@@ -2925,10 +1400,9 @@
 	OSObjectUserVars * uvars;
 	uint32_t           idx;
 	ipc_port_t         sendPort;
-	bool               serviceInactive;
 
 	OSObject_Instantiate_Rpl_Content * reply;
-	IODispatchQueue ** unboundedQueueArray = NULL;
+
 	queueCount      = 0;
 	methodCount     = 0;
 	methods         = NULL;
@@ -2940,20 +1414,12 @@
 	ret = kIOReturnUnsupportedMode;
 
 	service = OSDynamicCast(IOService, obj);
-	action = OSDynamicCast(OSAction, obj);
 	if (!service) {
 		// xxx other classes hosted
 		resultFlags |= kOSObjectRPCKernel;
 		resultFlags |= kOSObjectRPCRemote;
 	} else {
-		serviceInactive = false;
-		if (service->lockForArbitration()) {
-			if (service->isInactive() && (service->__state[1] & kIOServiceStartState) == 0) {
-				serviceInactive = true;
-			}
-			service->unlockForArbitration();
-		}
-		if (serviceInactive) {
+		if (service->isInactive()) {
 			DKLOG(DKS "::instantiate inactive\n", DKN(service));
 			return kIOReturnOffline;
 		}
@@ -2967,27 +1433,12 @@
 			resultFlags |= kOSObjectRPCRemote;
 		}
 		if (service->reserved->uvars && service->reserved->uvars->userServer) {
-			if (!str) {
-				DKLOG("no IOUserClass defined for " DKS "\n", DKN(service));
-				OSSafeReleaseNULL(prop);
-				return kIOReturnError;
-			}
-			IOLockLock(service->reserved->uvars->userServer->fLock);
-			service->reserved->uvars->instantiated = true;
 			userMeta = (typeof(userMeta))service->reserved->uvars->userServer->fClasses->getObject(str);
-			IOLockUnlock(service->reserved->uvars->userServer->fLock);
 		}
 	}
 	if (!str && !userMeta) {
 		const OSMetaClass * meta;
 		meta = obj->getMetaClass();
-		IOLockLock(fLock);
-		if (action) {
-			str = action->ivars->typeName;
-			if (str) {
-				userMeta = (typeof(userMeta))fClasses->getObject(str);
-			}
-		}
 		while (meta && !userMeta) {
 			str = (OSString *) meta->getClassNameSymbol();
 			userMeta = (typeof(userMeta))fClasses->getObject(str);
@@ -2995,24 +1446,18 @@
 				meta = meta->getSuperClass();
 			}
 		}
-		IOLockUnlock(fLock);
 	}
 	if (str) {
 		if (!userMeta) {
-			IOLockLock(fLock);
 			userMeta = (typeof(userMeta))fClasses->getObject(str);
-			IOLockUnlock(fLock);
 		}
 		if (kIODKLogSetup & gIODKDebug) {
 			DKLOG("userMeta %s %p\n", str->getCStringNoCopy(), userMeta);
 		}
 		if (userMeta) {
 			if (kOSObjectRPCRemote & resultFlags) {
-				if (!action) {
-					/* Special case: For OSAction subclasses, do not use the superclass */
-					while (userMeta && !(kOSClassCanRemote & userMeta->description->flags)) {
-						userMeta = userMeta->superMeta;
-					}
+				while (userMeta && !(kOSClassCanRemote & userMeta->description->flags)) {
+					userMeta = userMeta->superMeta;
 				}
 				if (userMeta) {
 					resultClassName = userMeta->description->name;
@@ -3024,20 +1469,11 @@
 				if (userMeta->queueNames) {
 					queueAlloc += userMeta->queueNames->count;
 				}
-				unboundedQueueArray = IONewZero(IODispatchQueue *, queueAlloc);
 				service->reserved->uvars->queueArray =
-				    OSBoundedArrayRef<IODispatchQueue *>(unboundedQueueArray, queueAlloc);
+				    IONewZero(IODispatchQueue *, queueAlloc);
 				resultClassName = str->getCStringNoCopy();
 				ret = kIOReturnSuccess;
 			}
-		} else if (kIODKLogSetup & gIODKDebug) {
-			DKLOG("userMeta %s was not found in fClasses\n", str->getCStringNoCopy());
-			IOLockLock(fLock);
-			fClasses->iterateObjects(^bool (const OSSymbol * key, OSObject * val) {
-				DKLOG(" fClasses[\"%s\"] => %p\n", key->getCStringNoCopy(), val);
-				return false;
-			});
-			IOLockUnlock(fLock);
 		}
 	}
 	OSSafeReleaseNULL(prop);
@@ -3047,36 +1483,32 @@
 
 	if ((kIOReturnSuccess == ret) && (kOSObjectRPCRemote & resultFlags)) {
 		target = obj;
-		if (action) {
+		if ((action = OSDynamicCast(OSAction, obj))) {
 			if (action->ivars->referenceSize) {
 				resultFlags |= kOSObjectRPCKernel;
 			} else {
 				resultFlags &= ~kOSObjectRPCKernel;
-				if (action->ivars->target) {
-					target = action->ivars->target;
-					queueCount = 1;
-					queue = queueForObject(target, action->ivars->targetmsgid);
-					if (!queue && action->ivars->userServer) {
-						queue = action->ivars->userServer->fRootQueue;
-					}
-					idx = 0;
-					sendPort = NULL;
-					if (queue && (kIODispatchQueueStopped != queue)) {
-						sendPort = ipc_port_copy_send_mqueue(queue->ivars->serverPort);
-					}
-					replySize = sizeof(OSObject_Instantiate_Rpl)
-					    + queueCount * sizeof(machReply->objects[0])
-					    + 2 * methodCount * sizeof(reply->methods[0]);
-					if (replySize > rpc.replySize) {
-						assert(false);
-						return kIOReturnIPCError;
-					}
-					machReply->objects[idx].type        = MACH_MSG_PORT_DESCRIPTOR;
-					machReply->objects[idx].disposition = MACH_MSG_TYPE_MOVE_SEND;
-					machReply->objects[idx].name        = sendPort;
-					machReply->objects[idx].pad2        = 0;
-					machReply->objects[idx].pad_end     = 0;
+				target = action->ivars->target;
+
+				queueCount = 1;
+				queue = queueForObject(target, action->ivars->targetmsgid);
+				idx = 0;
+				sendPort = NULL;
+				if (queue && (kIODispatchQueueStopped != queue)) {
+					sendPort = ipc_port_make_send(queue->ivars->serverPort);
 				}
+				replySize = sizeof(OSObject_Instantiate_Rpl)
+				    + queueCount * sizeof(machReply->objects[0])
+				    + 2 * methodCount * sizeof(reply->methods[0]);
+				if (replySize > rpc.replySize) {
+					assert(false);
+					return kIOReturnIPCError;
+				}
+				machReply->objects[idx].type        = MACH_MSG_PORT_DESCRIPTOR;
+				machReply->objects[idx].disposition = MACH_MSG_TYPE_MOVE_SEND;
+				machReply->objects[idx].name        = sendPort;
+				machReply->objects[idx].pad2        = 0;
+				machReply->objects[idx].pad_end     = 0;
 			}
 		} else {
 			uvars = varsForObject(target);
@@ -3098,7 +1530,7 @@
 					queue = uvars->queueArray[idx];
 					sendPort = NULL;
 					if (queue) {
-						sendPort = ipc_port_copy_send_mqueue(queue->ivars->serverPort);
+						sendPort = ipc_port_make_send(queue->ivars->serverPort);
 					}
 					machReply->objects[idx].type        = MACH_MSG_PORT_DESCRIPTOR;
 					machReply->objects[idx].disposition = MACH_MSG_TYPE_MOVE_SEND;
@@ -3111,7 +1543,7 @@
 	}
 
 	if (kIODKLogIPC & gIODKDebug) {
-		DKLOG("instantiate object %s with user class %s\n", obj->getMetaClass()->getClassName(), str ? str->getCStringNoCopy() : "(null)");
+		DKLOG("instantiate %s\n", obj->getMetaClass()->getClassName());
 	}
 
 	if (kIOReturnSuccess != ret) {
@@ -3123,7 +1555,7 @@
 	machReply->msgh.msgh_size                  = replySize;
 	machReply->msgh_body.msgh_descriptor_count = queueCount;
 
-	reply = (typeof(reply))IORPCMessageFromMachReply(machReply);
+	reply = (typeof(reply))IORPCMessageFromMach(machReply, true);
 	if (!reply) {
 		return kIOReturnIPCError;
 	}
@@ -3143,7 +1575,7 @@
 	return ret;
 }
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
 
 IOReturn
 IOUserServer::kernelDispatch(OSObject * obj, IORPC rpc)
@@ -3151,7 +1583,7 @@
 	IOReturn       ret;
 	IORPCMessage * message;
 
-	message = rpc.kernelContent;
+	message = IORPCMessageFromMach(rpc.message, false);
 	if (!message) {
 		return kIOReturnIPCError;
 	}
@@ -3159,15 +1591,15 @@
 	if (OSObject_Instantiate_ID == message->msgid) {
 		ret = objectInstantiate(obj, rpc, message);
 		if (kIOReturnSuccess != ret) {
-			DKLOG(DKS ": %s: instantiate failed 0x%x\n", DKN(this), obj->getMetaClass()->getClassName(), ret);
+			DKLOG("%s: instantiate failed 0x%x\n", obj->getMetaClass()->getClassName(), ret);
 		}
 	} else {
 		if (kIODKLogIPC & gIODKDebug) {
-			DKLOG(DKS ": %s::Dispatch kernel 0x%qx\n", DKN(this), obj->getMetaClass()->getClassName(), message->msgid);
+			DKLOG("%s::Dispatch kernel 0x%qx\n", obj->getMetaClass()->getClassName(), message->msgid);
 		}
 		ret = obj->Dispatch(rpc);
 		if (kIODKLogIPC & gIODKDebug) {
-			DKLOG(DKS ": %s::Dispatch kernel 0x%qx result 0x%x\n", DKN(this), obj->getMetaClass()->getClassName(), message->msgid, ret);
+			DKLOG("%s::Dispatch kernel 0x%qx result 0x%x\n", obj->getMetaClass()->getClassName(), message->msgid, ret);
 		}
 	}
 
@@ -3175,7 +1607,7 @@
 }
 
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
 
 OSObject *
 IOUserServer::target(OSAction * action, IORPCMessage * message)
@@ -3185,21 +1617,12 @@
 	if (message->msgid != action->ivars->msgid) {
 		return action;
 	}
-	object = action->ivars->target;
-	if (!object) {
-		return action;
-	}
+	object              = action->ivars->target;
 	message->msgid      = action->ivars->targetmsgid;
 	message->objects[0] = (OSObjectRef) object;
 	if (kIORPCMessageRemote & message->flags) {
 		object->retain();
-#ifndef __clang_analyzer__
-		// Hide the release of 'action' from the clang static analyzer to suppress
-		// an overrelease diagnostic. The analyzer doesn't have a way to express the
-		// non-standard contract of this method, which is that it releases 'action' when
-		// the message flags have kIORPCMessageRemote set.
 		action->release();
-#endif
 	}
 	if (kIODKLogIPC & gIODKDebug) {
 		DKLOG("TARGET %s msg 0x%qx from 0x%qx\n", object->getMetaClass()->getClassName(), message->msgid, action->ivars->msgid);
@@ -3208,44 +1631,40 @@
 	return object;
 }
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-kern_return_t
-uext_server(ipc_port_t receiver, ipc_kmsg_t requestkmsg, ipc_kmsg_t * pReply)
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
+
+kern_return_t
+uext_server(ipc_kmsg_t requestkmsg, ipc_kmsg_t * pReply)
 {
 	kern_return_t      ret;
+	IORPCMessageMach * msgin;
 	OSObject         * object;
 	IOUserServer     * server;
 
-	object = IOUserServer::copyObjectForSendRight(receiver, IKOT_UEXT_OBJECT);
+	msgin   = (typeof(msgin))ipc_kmsg_msg_header(requestkmsg);
+
+	object = IOUserServer::copyObjectForSendRight(msgin->msgh.msgh_remote_port, IKOT_UEXT_OBJECT);
 	server = OSDynamicCast(IOUserServer, object);
 	if (!server) {
 		OSSafeReleaseNULL(object);
 		return KERN_INVALID_NAME;
 	}
-
-	IORPCMessage * message = (typeof(message))ikm_udata_from_header(requestkmsg);
-
-	ret = server->server(requestkmsg, message, pReply);
+	ret = server->server(requestkmsg, pReply);
 	object->release();
 
 	return ret;
 }
 
-/*
- * Chosen to hit kalloc zones (as opposed to the VM).
- * doesn't include the trailer size which ipc_kmsg_alloc() will add
- */
 #define MAX_UEXT_REPLY_SIZE     0x17c0
-static_assert(MAX_UEXT_REPLY_SIZE + MAX_TRAILER_SIZE <= KALLOC_SAFE_ALLOC_SIZE);
-
-kern_return_t
-IOUserServer::server(ipc_kmsg_t requestkmsg, IORPCMessage * message, ipc_kmsg_t * pReply)
+
+kern_return_t
+IOUserServer::server(ipc_kmsg_t requestkmsg, ipc_kmsg_t * pReply)
 {
 	kern_return_t      ret;
 	mach_msg_size_t    replyAlloc;
 	ipc_kmsg_t         replykmsg;
 	IORPCMessageMach * msgin;
+	IORPCMessage     * message;
 	IORPCMessageMach * msgout;
 	IORPCMessage     * reply;
 	uint32_t           replySize;
@@ -3254,7 +1673,7 @@
 	bool               oneway;
 	uint64_t           msgid;
 
-	msgin   = (typeof(msgin))ikm_header(requestkmsg);
+	msgin   = (typeof(msgin))ipc_kmsg_msg_header(requestkmsg);
 	replyAlloc = 0;
 	msgout = NULL;
 	replykmsg = NULL;
@@ -3269,10 +1688,8 @@
 	if (!(MACH_MSGH_BITS_COMPLEX & msgin->msgh.msgh_bits)) {
 		msgin->msgh_body.msgh_descriptor_count = 0;
 	}
+	message = IORPCMessageFromMach(msgin, false);
 	if (!message) {
-		return kIOReturnIPCError;
-	}
-	if (message->objectRefs == 0) {
 		return kIOReturnIPCError;
 	}
 	ret = copyInObjects(msgin, message, msgin->msgh.msgh_size, true, false);
@@ -3280,9 +1697,6 @@
 		if (kIODKLogIPC & gIODKDebug) {
 			DKLOG("UEXT copyin(0x%x) %x\n", ret, msgin->msgh.msgh_id);
 		}
-		// release objects and ports
-		consumeObjects(msgin, message, msgin->msgh.msgh_size);
-		copyInObjects(msgin, message, msgin->msgh.msgh_size, false, true);
 		return KERN_NOT_SUPPORTED;
 	}
 
@@ -3302,44 +1716,39 @@
 	oneway = (0 != (kIORPCMessageOneway & message->flags));
 	assert(oneway || (MACH_PORT_NULL != msgin->msgh.msgh_local_port));
 
+	// includes trailer size
 	replyAlloc = oneway ? 0 : MAX_UEXT_REPLY_SIZE;
-
-
-
-
 	if (replyAlloc) {
+		replykmsg = ipc_kmsg_alloc(replyAlloc);
+		if (replykmsg == NULL) {
+//			printf("uext_server: dropping request\n");
+			//	ipc_kmsg_trace_send(request, option);
+			consumeObjects(message, msgin->msgh.msgh_size);
+			ipc_kmsg_destroy(requestkmsg);
+			return KERN_MEMORY_FAILURE;
+		}
+
+		msgout = (typeof(msgout))ipc_kmsg_msg_header(replykmsg);
 		/*
-		 * Same as:
-		 *    ipc_kmsg_alloc(MAX_UEXT_REPLY_SIZE_MACH, MAX_UEXT_REPLY_SIZE_MESSAGE,
-		 *        IPC_KMSG_ALLOC_KERNEL | IPC_KMSG_ALLOC_ZERO | IPC_KMSG_ALLOC_LINEAR |
-		 *        IPC_KMSG_ALLOC_NOFAIL);
+		 * MIG should really assure no data leakage -
+		 * but until it does, pessimistically zero the
+		 * whole reply buffer.
 		 */
-		replykmsg = ipc_kmsg_alloc_uext_reply(MAX_UEXT_REPLY_SIZE);
-		msgout = (typeof(msgout))ikm_header(replykmsg);
-	}
-
-	IORPC rpc = { .message = msgin, .reply = msgout, .sendSize = msgin->msgh.msgh_size, .replySize = replyAlloc, .kernelContent = message };
+		bzero((void *)msgout, replyAlloc);
+	}
+
+	IORPC rpc = { .message = msgin, .sendSize = msgin->msgh.msgh_size, .reply = msgout, .replySize = replyAlloc };
 
 	if (object) {
-		kern_allocation_name_t prior;
-		bool                   setAllocationName;
-
-		setAllocationName = (NULL != fAllocationName);
-		if (setAllocationName) {
-			prior = thread_set_allocation_name(fAllocationName);
-		}
 		thread_iokit_tls_set(0, this);
 		ret = kernelDispatch(object, rpc);
 		thread_iokit_tls_set(0, NULL);
-		if (setAllocationName) {
-			thread_set_allocation_name(prior);
-		}
 	} else {
 		ret = kIOReturnBadArgument;
 	}
 
 	// release objects
-	consumeObjects(msgin, message, msgin->msgh.msgh_size);
+	consumeObjects(message, msgin->msgh.msgh_size);
 
 	// release ports
 	copyInObjects(msgin, message, msgin->msgh.msgh_size, false, true);
@@ -3347,7 +1756,7 @@
 	if (!oneway) {
 		if (kIOReturnSuccess == ret) {
 			replySize = msgout->msgh.msgh_size;
-			reply = IORPCMessageFromMachReply(msgout);
+			reply = IORPCMessageFromMach(msgout, true);
 			if (!reply) {
 				ret = kIOReturnIPCError;
 			} else {
@@ -3359,7 +1768,7 @@
 
 			msgout->msgh_body.msgh_descriptor_count = 0;
 			msgout->msgh.msgh_id                    = kIORPCVersionCurrentReply;
-			errorMsg = (typeof(errorMsg))IORPCMessageFromMachReply(msgout);
+			errorMsg = (typeof(errorMsg))IORPCMessageFromMach(msgout, true);
 			errorMsg->hdr.msgid      = message->msgid;
 			errorMsg->hdr.flags      = kIORPCMessageOneway | kIORPCMessageError;
 			errorMsg->hdr.objectRefs = 0;
@@ -3379,36 +1788,14 @@
 	}
 
 	*pReply = replykmsg;
-	return KERN_SUCCESS;
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-static inline uint32_t
-MAX_OBJECT_COUNT(IORPCMessageMach *mach, size_t size, IORPCMessage *message __unused)
-{
-	assert(mach->msgh.msgh_size == size);
-	size_t used_size;
-	size_t remaining_size;
-	if (os_mul_and_add_overflow(
-		    mach->msgh_body.msgh_descriptor_count,
-		    sizeof(mach_msg_port_descriptor_t),
-		    sizeof(mach->msgh) + sizeof(mach->msgh_body) + offsetof(IORPCMessage, objects[0]),
-		    &used_size)) {
-		return 0;
-	}
-	if (os_sub_overflow(size, used_size, &remaining_size)) {
-		return 0;
-	}
-	return (uint32_t)(remaining_size / sizeof(OSObjectRef));
-}
-
-#pragma pack(push, 4)
-struct UEXTTrapReply {
-	uint64_t replySize;
-	IORPCMessage replyMessage;
-};
-#pragma pack(pop)
+
+	return oneway ? MIG_NO_REPLY : KERN_SUCCESS;
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
+
+#define MAX_OBJECT_COUNT(mach, size, message) \
+	((((size) + ((uintptr_t) (mach))) - ((uintptr_t) (&message->objects[0]))) / sizeof(OSObjectRef))
 
 kern_return_t
 IOUserServerUEXTTrap(OSObject * object, void * p1, void * p2, void * p3, void * p4, void * p5, void * p6)
@@ -3417,7 +1804,7 @@
 	size_t            inSize           = (uintptr_t) p2;
 	user_addr_t       out              = (uintptr_t) p3;
 	size_t            outSize          = (uintptr_t) p4;
-	mach_port_name_t  objectName1      = (mach_port_name_t)(uintptr_t) p5;
+	mach_port_name_t  objectName1      = (uintptr_t) p5;
 	size_t            totalSize;
 	OSObject        * objectArg1;
 
@@ -3442,7 +1829,7 @@
 	uint64_t           refs;
 	uint32_t           maxObjectCount;
 	size_t             copySize;
-	UEXTTrapReply    * replyHdr;
+	uint64_t         * replyHdr;
 	uintptr_t          p;
 
 	bzero(&buffer, sizeof(buffer));
@@ -3470,20 +1857,18 @@
 	if (!(kIORPCMessageSimpleReply & message->flags)) {
 		return kIOReturnUnsupported;
 	}
-	message->flags &= ~(kIORPCMessageKernel | kIORPCMessageRemote);
 
 	descs = (typeof(descs))(p - refs * sizeof(*descs));
 	mach  = (typeof(mach))(p - refs * sizeof(*descs) - sizeof(*mach));
 
 	mach->msgh.msgh_id   = kIORPCVersionCurrent;
-	mach->msgh.msgh_size = (mach_msg_size_t) (sizeof(IORPCMessageMach) + refs * sizeof(*descs) + inSize); // totalSize was checked
-	mach->msgh_body.msgh_descriptor_count = ((mach_msg_size_t) refs);
+	mach->msgh.msgh_size = sizeof(IORPCMessageMach) + refs * sizeof(*descs) + inSize;
+	mach->msgh_body.msgh_descriptor_count = refs;
 
 	rpc.message   = mach;
 	rpc.sendSize  = mach->msgh.msgh_size;
 	rpc.reply     = (IORPCMessageMach *) (p + inSize);
-	rpc.replySize = ((uint32_t) (sizeof(buffer.buffer) - inSize));    // inSize was checked
-	rpc.kernelContent = message;
+	rpc.replySize = sizeof(buffer.buffer) - inSize;
 
 	message->objects[0] = 0;
 	if ((action = OSDynamicCast(OSAction, object))) {
@@ -3491,10 +1876,6 @@
 		if (refs > maxObjectCount) {
 			return kIOReturnBadArgument;
 		}
-		if (refs < 2) {
-			DKLOG("invalid refs count %qd in message id 0x%qx\n", refs, message->msgid);
-			return kIOReturnBadArgument;
-		}
 		object = IOUserServer::target(action, message);
 		message->objects[1] = (OSObjectRef) action;
 		if (kIODKLogIPC & gIODKDebug) {
@@ -3504,11 +1885,9 @@
 	} else {
 		objectArg1 = NULL;
 		if (refs > 1) {
-			if (objectName1) {
-				objectArg1 = iokit_lookup_uext_ref_current_task(objectName1);
-				if (!objectArg1) {
-					return kIOReturnIPCError;
-				}
+			objectArg1 = iokit_lookup_uext_ref_current_task(objectName1);
+			if (!objectArg1) {
+				return kIOReturnIPCError;
 			}
 			message->objects[1] = (OSObjectRef) objectArg1;
 		}
@@ -3525,7 +1904,7 @@
 			if (rpc.reply->msgh_body.msgh_descriptor_count) {
 				return kIOReturnIPCError;
 			}
-			reply = IORPCMessageFromMachReply(rpc.reply);
+			reply = IORPCMessageFromMach(rpc.reply, rpc.reply->msgh.msgh_size);
 			if (!reply) {
 				return kIOReturnIPCError;
 			}
@@ -3533,8 +1912,9 @@
 			if (copySize > outSize) {
 				return kIOReturnIPCError;
 			}
-			replyHdr = (UEXTTrapReply *) ((uintptr_t)reply - sizeof(uint64_t));
-			replyHdr->replySize = copySize;
+			replyHdr = (uint64_t *) reply;
+			replyHdr--;
+			replyHdr[0] = copySize;
 			copyerr = copyout(replyHdr, out, copySize);
 			if (copyerr) {
 				return kIOReturnVMError;
@@ -3545,7 +1925,7 @@
 	return ret;
 }
 
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * * * * * * * * * * */
 
 IOReturn
 IOUserServer::rpc(IORPC rpc)
@@ -3576,9 +1956,9 @@
 
 	assert(sendSize >= (sizeof(IORPCMessageMach) + sizeof(IORPCMessage)));
 
-	message = rpc.kernelContent;
+	message = IORPCMessageFromMach(mach, false);
 	if (!message) {
-		return kIOReturnIPCError;
+		ret = kIOReturnIPCError;
 	}
 	msgid   = message->msgid;
 	machid  = (msgid >> 32);
@@ -3598,7 +1978,7 @@
 		port = queue->ivars->serverPort;
 	}
 	if (port) {
-		sendPort = ipc_port_copy_send_mqueue(port);
+		sendPort = ipc_port_make_send(port);
 	}
 	IOLockUnlock(gIOUserServerLock);
 	if (!sendPort) {
@@ -3610,67 +1990,47 @@
 	ret = copyOutObjects(mach, message, sendSize, false);
 
 	mach->msgh.msgh_bits = MACH_MSGH_BITS_COMPLEX |
-	    MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, (oneway ? 0 : MACH_MSG_TYPE_MAKE_SEND_ONCE));
+	    MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND, (oneway ? 0 : MACH_MSG_TYPE_MAKE_SEND_ONCE));
 	mach->msgh.msgh_remote_port  = sendPort;
 	mach->msgh.msgh_local_port   = (oneway ? MACH_PORT_NULL : mig_get_reply_port());
 	mach->msgh.msgh_id           = kIORPCVersionCurrent;
 	mach->msgh.msgh_reserved     = 0;
 
-	boolean_t message_moved;
-
 	if (oneway) {
-		ret = kernel_mach_msg_send(&mach->msgh, sendSize,
-		    MACH_SEND_KERNEL_DEFAULT, 0, &message_moved);
+		ret = mach_msg_send_from_kernel(&mach->msgh, sendSize);
 	} else {
 		assert(replySize >= (sizeof(IORPCMessageMach) + sizeof(IORPCMessage)));
-		ret = kernel_mach_msg_rpc(&mach->msgh, sendSize, replySize, FALSE, &message_moved);
-	}
-
-	ipc_port_release_send(sendPort);
-
-	if (MACH_MSG_SUCCESS != ret) {
-		if (kIODKLogIPC & gIODKDebug) {
-			DKLOG("mach_msg() failed 0x%x\n", ret);
-		}
-		if (!message_moved) {
-			// release ports
-			copyInObjects(mach, message, sendSize, false, true);
-		}
-	}
-
-	if ((KERN_SUCCESS == ret) && !oneway) {
-		if (kIORPCVersionCurrentReply != mach->msgh.msgh_id) {
-			ret = (MACH_NOTIFY_SEND_ONCE == mach->msgh.msgh_id) ? MIG_SERVER_DIED : MIG_REPLY_MISMATCH;
-		} else if ((replySize = mach->msgh.msgh_size) < (sizeof(IORPCMessageMach) + sizeof(IORPCMessage))) {
+		ret = mach_msg_rpc_from_kernel(&mach->msgh, sendSize, replySize);
+		if (KERN_SUCCESS == ret) {
+			if (kIORPCVersionCurrentReply != mach->msgh.msgh_id) {
+				ret = (MACH_NOTIFY_SEND_ONCE == mach->msgh.msgh_id) ? MIG_SERVER_DIED : MIG_REPLY_MISMATCH;
+			} else if ((replySize = mach->msgh.msgh_size) < (sizeof(IORPCMessageMach) + sizeof(IORPCMessage))) {
 //				printf("BAD REPLY SIZE\n");
-			ret = MIG_BAD_ARGUMENTS;
-		} else {
-			if (!(MACH_MSGH_BITS_COMPLEX & mach->msgh.msgh_bits)) {
-				mach->msgh_body.msgh_descriptor_count = 0;
-			}
-			message = IORPCMessageFromMachReply(mach);
-			if (!message) {
-				ret = kIOReturnIPCError;
-			} else if (message->msgid != msgid) {
-//					printf("BAD REPLY ID\n");
 				ret = MIG_BAD_ARGUMENTS;
 			} else {
-				bool isError = (0 != (kIORPCMessageError & message->flags));
-				ret = copyInObjects(mach, message, replySize, !isError, true);
-				if (kIOReturnSuccess != ret) {
-					if (kIODKLogIPC & gIODKDebug) {
-						DKLOG("rpc copyin(0x%x) %x\n", ret, mach->msgh.msgh_id);
+				if (!(MACH_MSGH_BITS_COMPLEX & mach->msgh.msgh_bits)) {
+					mach->msgh_body.msgh_descriptor_count = 0;
+				}
+				message = IORPCMessageFromMach(mach, true);
+				if (!message) {
+					ret = kIOReturnIPCError;
+				} else if (message->msgid != msgid) {
+//					printf("BAD REPLY ID\n");
+					ret = MIG_BAD_ARGUMENTS;
+				} else {
+					bool isError = (0 != (kIORPCMessageError & message->flags));
+					ret = copyInObjects(mach, message, replySize, !isError, true);
+					if (kIOReturnSuccess != ret) {
+						if (kIODKLogIPC & gIODKDebug) {
+							DKLOG("rpc copyin(0x%x) %x\n", ret, mach->msgh.msgh_id);
+						}
+						return KERN_NOT_SUPPORTED;
 					}
-					if (!isError) {
-						consumeObjects(mach, message, replySize);
-						copyInObjects(mach, message, replySize, false, true);
+					if (isError) {
+						IORPCMessageErrorReturnContent * errorMsg = (typeof(errorMsg))message;
+						ret = errorMsg->result;
 					}
-					return KERN_NOT_SUPPORTED;
 				}
-				if (isError) {
-					IORPCMessageErrorReturnContent * errorMsg = (typeof(errorMsg))message;
-					ret = errorMsg->result;
-				}
 			}
 		}
 	}
@@ -3680,15 +2040,14 @@
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-static IORPCMessage *
-IORPCMessageFromMachReply(IORPCMessageMach * msg)
+IORPCMessage *
+IORPCMessageFromMach(IORPCMessageMach * msg, bool reply)
 {
 	mach_msg_size_t              idx, count;
 	mach_msg_port_descriptor_t * desc;
 	mach_msg_port_descriptor_t * maxDesc;
 	size_t                       size, msgsize;
 	bool                         upgrade;
-	bool                         reply = true;
 
 	msgsize = msg->msgh.msgh_size;
 	count   = msg->msgh_body.msgh_descriptor_count;
@@ -3723,13 +2082,24 @@
 ipc_port_t
 IOUserServer::copySendRightForObject(OSObject * object, ipc_kobject_type_t type)
 {
-	return iokit_port_make_send_for_object(object, type);
+	ipc_port_t port;
+	ipc_port_t sendPort = NULL;
+
+	port = iokit_port_for_object(object, type);
+	if (port) {
+		sendPort = ipc_port_make_send(port);
+		iokit_release_port(port);
+	}
+
+	return sendPort;
 }
 
 OSObject *
 IOUserServer::copyObjectForSendRight(ipc_port_t port, ipc_kobject_type_t type)
 {
-	return iokit_lookup_io_object(port, type);
+	OSObject * object;
+	object = iokit_lookup_io_object(port, type);
+	return object;
 }
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -3793,15 +2163,6 @@
 			descsize = sizeof(mach_msg_port_descriptor_t);
 			port = NULL;
 			if (object) {
-#if DEVELOPMENT || DEBUG
-				if (kIODKLogIPC & gIODKDebug) {
-					IOMemoryDescriptor * iomd = OSDynamicCast(IOMemoryDescriptor, object);
-					if (iomd != NULL && (iomd->getFlags() & kIOMemoryThreadSafe) == 0) {
-						OSReportWithBacktrace("IOMemoryDescriptor %p was created without kIOMemoryThreadSafe flag", iomd);
-					}
-				}
-#endif /* DEVELOPMENT || DEBUG */
-
 				port = copySendRightForObject(object, IKOT_UEXT_OBJECT);
 				if (!port) {
 					break;
@@ -3929,14 +2290,8 @@
 		return kIOReturnBadArgument;
 	}
 
+	desc = &mach->objects[0];
 	for (idx = 0; idx < refs; idx++) {
-		message->objects[idx] = (OSObjectRef) NULL;
-	}
-
-	desc = &mach->objects[0];
-	for (idx = 0; idx < mach->msgh_body.msgh_descriptor_count; idx++) {
-		bool isObjectPort = idx < refs;
-
 		switch (desc->type) {
 		case MACH_MSG_PORT_DESCRIPTOR:
 			descsize = sizeof(mach_msg_port_descriptor_t);
@@ -3944,7 +2299,7 @@
 			object = NULL;
 			port = desc->name;
 			if (port) {
-				if (isObjectPort && copyObjects) {
+				if (copyObjects) {
 					object = copyObjectForSendRight(port, IKOT_UEXT_OBJECT);
 					if (!object) {
 						descsize = -1UL;
@@ -3953,7 +2308,6 @@
 				}
 				if (consumePorts) {
 					ipc_port_release_send(port);
-					desc->name = MACH_PORT_NULL;
 				}
 			}
 			break;
@@ -3963,15 +2317,15 @@
 			ool = (typeof(ool))desc;
 
 			object = NULL;
-			if (isObjectPort && copyObjects && ool->size && ool->address) {
+			if (copyObjects && ool->size && ool->address) {
 				kr = vm_map_copyout(kernel_map, &copyoutdata, (vm_map_copy_t) ool->address);
 				if (KERN_SUCCESS == kr) {
 					object = OSUnserializeXML((const char *) copyoutdata, ool->size);
-					kr = vm_deallocate(kernel_map, copyoutdata, ool->size);
-					assert(KERN_SUCCESS == kr);
 					// vm_map_copyout() has consumed the vm_map_copy_t in the message
 					ool->size = 0;
 					ool->address = NULL;
+					kr = vm_deallocate(kernel_map, copyoutdata, ool->size);
+					assert(KERN_SUCCESS == kr);
 				}
 				if (!object) {
 					descsize = -1UL;
@@ -3987,7 +2341,7 @@
 		if (-1UL == descsize) {
 			break;
 		}
-		if (isObjectPort && copyObjects) {
+		if (copyObjects) {
 			message->objects[idx] = (OSObjectRef) object;
 		}
 		desc = (typeof(desc))(((uintptr_t) desc) + descsize);
@@ -3999,7 +2353,7 @@
 
 	while (idx--) {
 		object = (OSObject *) message->objects[idx];
-		OSSafeReleaseNULL(object);
+		object->release();
 		message->objects[idx] = 0;
 	}
 
@@ -4007,20 +2361,12 @@
 }
 
 IOReturn
-IOUserServer::consumeObjects(IORPCMessageMach *mach, IORPCMessage * message, size_t messageSize)
+IOUserServer::consumeObjects(IORPCMessage * message, size_t messageSize)
 {
 	uint64_t    refs, idx;
 	OSObject  * object;
 
 	refs   = message->objectRefs;
-	uint32_t maxObjectCount = MAX_OBJECT_COUNT(mach, messageSize, message);
-	if (refs > mach->msgh_body.msgh_descriptor_count) {
-		return kIOReturnBadArgument;
-	}
-	if (refs > maxObjectCount) {
-		return kIOReturnBadArgument;
-	}
-
 	for (idx = 0; idx < refs; idx++) {
 		object = (OSObject *) message->objects[idx];
 		if (object) {
@@ -4034,16 +2380,13 @@
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
-static kern_return_t
-acknowledgeSetPowerState(IOService * service);
-
 bool
 IOUserServer::finalize(IOOptionBits options)
 {
 	OSArray   * services;
 
 	if (kIODKLogSetup & gIODKDebug) {
-		DKLOG(DKS "::finalize(%p)\n", DKN(this), this);
+		DKLOG("%s::finalize(%p)\n", getName(), this);
 	}
 
 	IOLockLock(gIOUserServerLock);
@@ -4057,64 +2400,28 @@
 	}
 	IOLockUnlock(fLock);
 
-	IOOptionBits terminateFlags = kIOServiceTerminateNeedWillTerminate | kIOServiceTerminateWithRematch;
-	if (fCheckInToken) {
-		bool can_rematch = fCheckInToken->dextTerminate();
-		if (can_rematch) {
-			terminateFlags |= kIOServiceTerminateWithRematchCurrentDext;
-		} else {
-			DKLOG(DKS "::finalize(%p) dext was replaced, do not rematch current dext\n", DKN(this), this);
-		}
-	} else {
-		terminateFlags |= kIOServiceTerminateWithRematchCurrentDext;
-		DKLOG(DKS "::finalize(%p) could not find fCheckInToken\n", DKN(this), this);
-	}
-
 	if (services) {
 		services->iterateObjects(^bool (OSObject * obj) {
-			int         service __unused;       // hide outer defn
-			IOService * nextService;
+			IOService * service;
 			IOService * provider;
 			bool        started = false;
-			bool        instantiated = false;
-
-			nextService = (IOService *) obj;
+
+			service = (IOService *) obj;
 			if (kIODKLogSetup & gIODKDebug) {
-			        DKLOG(DKS "::terminate(" DKS ")\n", DKN(this), DKN(nextService));
-			}
-			if (nextService->reserved->uvars) {
-			        IOUserClient * nextUserClient = OSDynamicCast(IOUserClient, nextService);
-			        provider = nextService->getProvider();
-			        if (nextUserClient) {
-			                nextUserClient->setTerminateDefer(provider, false);
+			        DKLOG("%s::terminate(" DKS ")\n", getName(), DKN(service));
+			}
+			if (service->reserved->uvars) {
+			        started = service->reserved->uvars->started;
+			        service->reserved->uvars->serverDied = true;
+			        if (started) {
+			                provider = service->getProvider();
+			                serviceDidStop(service, provider);
+			                service->terminate(kIOServiceTerminateNeedWillTerminate | kIOServiceTerminateWithRematch);
 				}
-			        (void)::acknowledgeSetPowerState(nextService);
-			        started = nextService->reserved->uvars->started;
-			        instantiated = nextService->reserved->uvars->instantiated;
-			        nextService->reserved->uvars->serverDied = true;
-
-			        serviceDidStop(nextService, provider);
-			        if (provider != NULL && (terminateFlags & kIOServiceTerminateWithRematchCurrentDext) == 0) {
-			                provider->resetRematchProperties();
-				}
-			        if (started) {
-			                IOService * provider = nextService;
-			                while ((provider = provider->getProvider())) {
-			                        if (-1U != services->getNextIndexOfObject(provider, 0)) {
-			                                break;
-						}
-					}
-			                if (!provider) {
-			                        // this service is the root of the set, so only terminate it
-			                        nextService->terminate(terminateFlags);
-					}
-				}
-			}
-			if (!started || !instantiated) {
-			        DKLOG(DKS "::terminate(" DKS ") server exit before start() instantiated %d\n", DKN(this), DKN(nextService), instantiated);
-			        // Override started since we are forcing serviceStop to happen
-			        nextService->reserved->uvars->started = true;
-			        serviceStop(nextService, NULL);
+			}
+			if (!started) {
+			        DKLOG("%s::terminate(" DKS ") server exit before start()\n", getName(), DKN(service));
+			        serviceStop(service, NULL);
 			}
 			return false;
 		});
@@ -4127,21 +2434,15 @@
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 #undef super
-#define super IOUserClient2022
-
-OSDefineMetaClassAndStructors(IOUserServer, IOUserClient2022)
+#define super IOUserClient
+
+OSDefineMetaClassAndStructors(IOUserServer, IOUserClient)
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 IOUserClient * IOUserServer::withTask(task_t owningTask)
 {
 	IOUserServer * inst;
-
-	assert(owningTask == current_task());
-	if (!task_is_driver(owningTask)) {
-		DKLOG("IOUserServer may only be created with driver tasks\n");
-		return NULL;
-	}
 
 	inst = new IOUserServer;
 	if (inst && !inst->init()) {
@@ -4149,202 +2450,38 @@
 		inst = NULL;
 		return inst;
 	}
-	OS_ANALYZER_SUPPRESS("82033761") inst->PMinit();
+	inst->PMinit();
 
 	inst->fOwningTask = current_task();
-	task_reference(inst->fOwningTask);
-
 	inst->fEntitlements = IOUserClient::copyClientEntitlements(inst->fOwningTask);
 
 	if (!(kIODKDisableEntitlementChecking & gIODKDebug)) {
-		proc_t p;
-		pid_t  pid;
-		const char * name;
-		p = (proc_t)get_bsdtask_info(inst->fOwningTask);
-		if (p) {
-			name = proc_best_name(p);
-			pid = proc_pid(p);
-		} else {
-			name = "unknown";
-			pid = 0;
-		}
-
-		if (inst->fEntitlements == NULL) {
-#if DEVELOPMENT || DEBUG
-			panic("entitlements are missing for %s[%d]\n", name, pid);
-#else
-			DKLOG("entitlements are missing for %s[%d]\n", name, pid);
-#endif /* DEVELOPMENT || DEBUG */
-		}
-
-
-		const char * dextTeamID = csproc_get_teamid(p);
-		if (dextTeamID != NULL) {
-			inst->fTeamIdentifier = OSString::withCString(dextTeamID);
-			DKLOG("%s[%d] has team identifier %s\n", name, pid, dextTeamID);
-		}
-
-		if (!IOCurrentTaskHasEntitlement(gIODriverKitEntitlementKey->getCStringNoCopy())) {
-			IOLog(kIODriverKitEntitlementKey " entitlement check failed for %s[%d]\n", name, pid);
+		if (!inst->fEntitlements || !inst->fEntitlements->getObject(gIODriverKitEntitlementKey)) {
+			proc_t p;
+			pid_t  pid;
+
+			p = (proc_t)get_bsdtask_info(inst->fOwningTask);
+			if (p) {
+				pid = proc_pid(p);
+				IOLog(kIODriverKitEntitlementKey " entitlement check failed for %s[%d]\n", proc_best_name(p), pid);
+			}
 			inst->release();
 			inst = NULL;
 			return inst;
 		}
 	}
-
-	/* Mark the current task's space as eligible for uext object ports */
-	iokit_label_dext_task(inst->fOwningTask);
 
 	inst->fLock     = IOLockAlloc();
 	inst->fServices = OSArray::withCapacity(4);
 	inst->fClasses  = OSDictionary::withCapacity(16);
 	inst->fClasses->setOptions(OSCollection::kSort, OSCollection::kSort);
-	inst->fPlatformDriver = task_get_platform_binary(inst->fOwningTask);
-	if (csproc_get_validation_category(current_proc(), &inst->fCSValidationCategory) != KERN_SUCCESS) {
-		inst->fCSValidationCategory = CS_VALIDATION_CATEGORY_INVALID;
-	}
-	inst->fWorkLoop = IOWorkLoop::workLoop();
-
-	inst->setProperty(kIOUserClientDefaultLockingKey, kOSBooleanTrue);
-	inst->setProperty(kIOUserClientDefaultLockingSetPropertiesKey, kOSBooleanTrue);
-	inst->setProperty(kIOUserClientDefaultLockingSingleThreadExternalMethodKey, kOSBooleanTrue);
-	//requirement for gIODriverKitEntitlementKey is enforced elsewhere conditionally
-	inst->setProperty(kIOUserClientEntitlementsKey, kOSBooleanFalse);
 
 	return inst;
-}
-
-static bool gIOUserServerLeakObjects = false;
-
-bool
-IOUserServer::shouldLeakObjects()
-{
-	return gIOUserServerLeakObjects;
-}
-
-void
-IOUserServer::beginLeakingObjects()
-{
-	gIOUserServerLeakObjects = true;
-}
-
-bool
-IOUserServer::isPlatformDriver()
-{
-	return fPlatformDriver;
-}
-
-int
-IOUserServer::getCSValidationCategory()
-{
-	return fCSValidationCategory;
-}
-
-
-struct IOUserServerRecordExitReasonContext {
-	task_t task;
-	os_reason_t reason;
-};
-
-static bool
-IOUserServerRecordExitReasonMatch(const OSObject *obj, void * context)
-{
-	IOUserServerRecordExitReasonContext * ctx = (IOUserServerRecordExitReasonContext *)context;
-	IOUserServer * us = OSDynamicCast(IOUserServer, obj);
-	if (us == NULL) {
-		return false;
-	}
-
-	if (us->fOwningTask == ctx->task) {
-		assert(us->fTaskCrashReason == OS_REASON_NULL);
-		assert(ctx->reason != OS_REASON_NULL);
-		os_reason_ref(ctx->reason);
-		us->fTaskCrashReason = ctx->reason;
-		return true;
-	}
-
-	return false;
-}
-
-extern "C" void
-IOUserServerRecordExitReason(task_t task, os_reason_t reason)
-{
-	IOUserServerRecordExitReasonContext ctx { task, reason };
-	IOUserServer::gMetaClass.applyToInstances(IOUserServerRecordExitReasonMatch, &ctx);
 }
 
 IOReturn
 IOUserServer::clientClose(void)
 {
-	OSArray   * services;
-	bool __block unexpectedExit = false;
-
-	if (kIODKLogSetup & gIODKDebug) {
-		DKLOG(DKS "::clientClose(%p)\n", DKN(this), this);
-	}
-	services = NULL;
-	IOLockLock(fLock);
-	if (fServices) {
-		services = OSArray::withArray(fServices);
-	}
-	IOLockUnlock(fLock);
-
-	// if this was a an expected exit, termination and stop should have detached at this
-	// point, so send any provider still attached and not owned by this user server
-	// the ClientCrashed() notification
-	if (services) {
-		services->iterateObjects(^bool (OSObject * obj) {
-			int         service __unused;       // hide outer defn
-			IOService * nextService;
-			IOService * provider;
-
-			nextService = (IOService *) obj;
-			if (nextService->isInactive()) {
-			        return false;
-			}
-			if (nextService->reserved && nextService->reserved->uvars && nextService->reserved->uvars->started) {
-			        unexpectedExit = true;
-			}
-			provider = nextService->getProvider();
-			if (provider
-			&& (!provider->reserved->uvars || (provider->reserved->uvars->userServer != this))) {
-			        if (kIODKLogSetup & gIODKDebug) {
-			                DKLOG(DKS "::ClientCrashed(" DKS ")\n", DKN(provider), DKN(nextService));
-				}
-			        if (unexpectedExit) {
-			                provider->unregisterAllInterrupts();
-				}
-			        provider->ClientCrashed(nextService, 0);
-			}
-			return false;
-		});
-		services->release();
-	}
-
-	if (unexpectedExit &&
-	    !gInUserspaceReboot &&
-	    (fTaskCrashReason != OS_REASON_NULL && fTaskCrashReason->osr_namespace != OS_REASON_JETSAM && fTaskCrashReason->osr_namespace != OS_REASON_RUNNINGBOARD) &&
-	    fStatistics != NULL) {
-		OSDextCrashPolicy policy = fStatistics->recordCrash();
-		bool allowPanic;
-#if DEVELOPMENT || DEBUG
-		allowPanic = !restore_boot && fPlatformDriver && fEntitlements->getObject(gIODriverKitTestDriverEntitlementKey) != kOSBooleanTrue && !disable_dext_crash_reboot;
-#else
-		allowPanic = !restore_boot && fPlatformDriver;
-#endif /* DEVELOPMENT || DEBUG */
-
-		if (policy == kOSDextCrashPolicyReboot && allowPanic) {
-			emergencyPanicCoreDumpEnable();
-			panic("Driver %s has crashed too many times (reason %u:%llu)\n",
-			    getName(), fTaskCrashReason->osr_namespace, fTaskCrashReason->osr_code);
-		}
-
-		IOPMrootDomain *rootDomain = IOService::getPMRootDomain();
-		if (rootDomain) {
-			rootDomain->requestRunMode(kIOPMRunModeFullWake);
-		}
-	}
-
 	terminate();
 	return kIOReturnSuccess;
 }
@@ -4359,10 +2496,7 @@
 void
 IOUserServer::stop(IOService * provider)
 {
-	if (fOwningTask) {
-		task_deallocate(fOwningTask);
-		fOwningTask = TASK_NULL;
-	}
+	fOwningTask = TASK_NULL;
 
 	PMstop();
 
@@ -4375,36 +2509,15 @@
 	}
 }
 
-IOWorkLoop *
-IOUserServer::getWorkLoop() const
-{
-	return fWorkLoop;
-}
-
 void
 IOUserServer::free()
 {
 	OSSafeReleaseNULL(fEntitlements);
 	OSSafeReleaseNULL(fClasses);
-	if (fOwningTask) {
-		task_deallocate(fOwningTask);
-		fOwningTask = TASK_NULL;
-	}
 	if (fLock) {
 		IOLockFree(fLock);
 	}
 	OSSafeReleaseNULL(fServices);
-	OSSafeReleaseNULL(fCheckInToken);
-	OSSafeReleaseNULL(fStatistics);
-	OSSafeReleaseNULL(fTeamIdentifier);
-	if (fAllocationName) {
-		kern_allocation_name_release(fAllocationName);
-		fAllocationName = NULL;
-	}
-	if (fTaskCrashReason != OS_REASON_NULL) {
-		os_reason_free(fTaskCrashReason);
-	}
-	OSSafeReleaseNULL(fWorkLoop);
 	IOUserClient::free();
 }
 
@@ -4424,7 +2537,7 @@
 	}
 
 	if (kIODKLogSetup & gIODKDebug) {
-		DKLOG(DKS "::registerClass %s, %d, %d\n", DKN(this), desc->name, desc->queueNamesSize, desc->methodNamesSize);
+		DKLOG("%s::registerClass %s, %d, %d\n", getName(), desc->name, desc->queueNamesSize, desc->methodNamesSize);
 	}
 
 	if (desc->descriptionSize != size) {
@@ -4476,7 +2589,7 @@
 		return kIOReturnNoMemory;
 	}
 
-	cls->description = (typeof(cls->description))IOMallocData(size);
+	cls->description = (typeof(cls->description))IOMalloc(size);
 	assert(cls->description);
 	if (!cls->description) {
 		assert(false);
@@ -4486,7 +2599,7 @@
 	bcopy(desc, cls->description, size);
 
 	cls->methodCount = desc->methodOptionsSize / (2 * sizeof(uint64_t));
-	cls->methods = IONewData(uint64_t, 2 * cls->methodCount);
+	cls->methods = IONew(uint64_t, 2 * cls->methodCount);
 	if (!cls->methods) {
 		assert(false);
 		cls->release();
@@ -4509,33 +2622,13 @@
 
 	cls->name = sym;
 	cls->meta = OSMetaClass::copyMetaClassWithName(sym);
-	IOLockLock(fLock);
 	cls->superMeta = OSDynamicCast(OSUserMetaClass, fClasses->getObject(desc->superName));
-	if (fClasses->getObject(sym) != NULL) {
-		/* class with this name exists */
-		ret = kIOReturnBadArgument;
-	} else {
-		if (fClasses->setObject(sym, cls)) {
-			*pCls = cls;
-		} else {
-			/* could not add class to fClasses */
-			ret = kIOReturnNoMemory;
-		}
-	}
-	IOLockUnlock(fLock);
+	fClasses->setObject(sym, cls);
 	cls->release();
+
+	*pCls = cls;
+
 	return ret;
-}
-
-IOReturn
-IOUserServer::registerClass(OSClassDescription * desc, uint32_t size, OSSharedPtr<OSUserMetaClass>& pCls)
-{
-	OSUserMetaClass* pClsRaw = NULL;
-	IOReturn result = registerClass(desc, size, &pClsRaw);
-	if (result == kIOReturnSuccess) {
-		pCls.reset(pClsRaw, OSRetain);
-	}
-	return result;
 }
 
 IOReturn
@@ -4551,91 +2644,57 @@
 	return kIOReturnSuccess;
 }
 
-
 IOReturn
-IOUserServer::externalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque * args)
-{
-	static const IOExternalMethodDispatch2022 dispatchArray[] = {
-		[kIOUserServerMethodRegisterClass] = {
-			.function                 = &IOUserServer::externalMethodRegisterClass,
-			.checkScalarInputCount    = 0,
-			.checkStructureInputSize  = kIOUCVariableStructureSize,
-			.checkScalarOutputCount   = 2,
-			.checkStructureOutputSize = 0,
-			.allowAsync               = false,
-			.checkEntitlement         = NULL,
-		},
-		[kIOUserServerMethodStart] = {
-			.function                 = &IOUserServer::externalMethodStart,
-			.checkScalarInputCount    = 1,
-			.checkStructureInputSize  = 0,
-			.checkScalarOutputCount   = 1,
-			.checkStructureOutputSize = 0,
-			.allowAsync               = false,
-			.checkEntitlement         = NULL,
-		},
-	};
-
-	return dispatchExternalMethod(selector, args, dispatchArray, sizeof(dispatchArray) / sizeof(dispatchArray[0]), this, NULL);
-}
-
-IOReturn
-IOUserServer::externalMethodRegisterClass(OSObject * target, void * reference, IOExternalMethodArguments * args)
+IOUserServer::externalMethod(uint32_t selector, IOExternalMethodArguments * args,
+    IOExternalMethodDispatch * dispatch, OSObject * target, void * reference)
 {
 	IOReturn ret = kIOReturnBadArgument;
 	mach_port_name_t portname;
 
-	IOUserServer * me = (typeof(me))target;
-
-	OSUserMetaClass * cls;
-	if (!args->structureInputSize) {
-		return kIOReturnBadArgument;
-	}
-
-	ret = me->registerClass((OSClassDescription *) args->structureInput, args->structureInputSize, &cls);
-	if (kIOReturnSuccess == ret) {
-		portname = iokit_make_send_right(me->fOwningTask, cls, IKOT_UEXT_OBJECT);
+	switch (selector) {
+	case kIOUserServerMethodRegisterClass:
+	{
+		OSUserMetaClass * cls;
+		if (!args->structureInputSize) {
+			return kIOReturnBadArgument;
+		}
+		if (args->scalarOutputCount != 2) {
+			return kIOReturnBadArgument;
+		}
+		ret = registerClass((OSClassDescription *) args->structureInput, args->structureInputSize, &cls);
+		if (kIOReturnSuccess == ret) {
+			portname = iokit_make_send_right(fOwningTask, cls, IKOT_UEXT_OBJECT);
+			assert(portname);
+			args->scalarOutput[0] = portname;
+			args->scalarOutput[1] = kOSObjectRPCRemote;
+		}
+		break;
+	}
+	case kIOUserServerMethodStart:
+	{
+		if (args->scalarOutputCount != 1) {
+			return kIOReturnBadArgument;
+		}
+		portname = iokit_make_send_right(fOwningTask, this, IKOT_UEXT_OBJECT);
 		assert(portname);
 		args->scalarOutput[0] = portname;
-		args->scalarOutput[1] = kOSObjectRPCRemote;
+		ret = kIOReturnSuccess;
+		break;
+	}
+	default:
+		break;
 	}
 
 	return ret;
 }
 
-IOReturn
-IOUserServer::externalMethodStart(OSObject * target, void * reference, IOExternalMethodArguments * args)
-{
-	mach_port_name_t portname = 0;
-	IOReturn ret = kIOReturnSuccess;
-
-	IOUserServer * me = (typeof(me))target;
-
-	if (!(kIODKDisableCheckInTokenVerification & gIODKDebug)) {
-		mach_port_name_t checkInPortName = ((typeof(checkInPortName))args->scalarInput[0]);
-		OSObject * obj = iokit_lookup_object_with_port_name(checkInPortName, IKOT_IOKIT_IDENT, me->fOwningTask);
-		IOUserServerCheckInToken * retrievedToken = OSDynamicCast(IOUserServerCheckInToken, obj);
-		if (retrievedToken != NULL) {
-			ret = me->setCheckInToken(retrievedToken);
-		} else {
-			ret = kIOReturnBadArgument;
-		}
-		OSSafeReleaseNULL(obj);
-	}
-	if (ret == kIOReturnSuccess) {
-		portname = iokit_make_send_right(me->fOwningTask, me, IKOT_UEXT_OBJECT);
-		assert(portname);
-	}
-	args->scalarOutput[0] = portname;
-	return ret;
-}
 IOExternalTrap *
 IOUserServer::getTargetAndTrapForIndex( IOService **targetP, UInt32 index )
 {
-	static const OSBoundedArray<IOExternalTrap, 1> trapTemplate = {{
-									       { NULL, (IOTrap) & IOUserServer::waitInterruptTrap},
-								       }};
-	if (index >= trapTemplate.size()) {
+	static const IOExternalTrap trapTemplate[] = {
+		{ NULL, (IOTrap) & IOUserServer::waitInterruptTrap},
+	};
+	if (index >= (sizeof(trapTemplate) / sizeof(IOExternalTrap))) {
 		return NULL;
 	}
 	*targetP = this;
@@ -4643,12 +2702,6 @@
 }
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-void
-IOUserServer::pageout()
-{
-	fPageout = 1;
-}
 
 IOReturn
 IOUserServer::serviceAttach(IOService * service, IOService * provider)
@@ -4657,57 +2710,17 @@
 	OSObjectUserVars * vars;
 	OSObject         * prop;
 	OSString         * str;
-	OSSymbol const*   bundleID;
+	OSSymbolConstPtr   bundleID;
 	char               execPath[1024];
 
-	vars = IOMallocType(OSObjectUserVars);
+	vars = IONewZero(OSObjectUserVars, 1);
 	service->reserved->uvars = vars;
 
 	vars->userServer = this;
 	vars->userServer->retain();
-	vars->uvarsLock = IOLockAlloc();
-	vars->originalProperties = service->dictionaryWithProperties();
 	IOLockLock(fLock);
 	if (-1U == fServices->getNextIndexOfObject(service, 0)) {
 		fServices->setObject(service);
-
-		// Add to IOAssociatedServices
-		OSObject * serviceArrayObj = copyProperty(gIOAssociatedServicesKey);
-		OSArray * serviceArray = OSDynamicCast(OSArray, serviceArrayObj);
-		if (!serviceArray) {
-			serviceArray = OSArray::withCapacity(0);
-		} else {
-			serviceArray = OSDynamicCast(OSArray, serviceArray->copyCollection());
-			assert(serviceArray != NULL);
-		}
-
-		OSNumber * registryEntryNumber = OSNumber::withNumber(service->getRegistryEntryID(), 64);
-		serviceArray->setObject(registryEntryNumber);
-		setProperty(gIOAssociatedServicesKey, serviceArray);
-		OSSafeReleaseNULL(registryEntryNumber);
-		OSSafeReleaseNULL(serviceArray);
-		OSSafeReleaseNULL(serviceArrayObj);
-
-		// populate kIOUserClassesKey
-
-		OSUserMetaClass * userMeta;
-		OSArray         * classesArray;
-		const OSString  * str2;
-
-		classesArray = OSArray::withCapacity(4);
-		prop = service->copyProperty(gIOUserClassKey);
-		str2 = OSDynamicCast(OSString, prop);
-		userMeta = (typeof(userMeta))service->reserved->uvars->userServer->fClasses->getObject(str2);
-		while (str2 && userMeta) {
-			classesArray->setObject(str2);
-			userMeta = userMeta->superMeta;
-			if (userMeta) {
-				str2 = userMeta->name;
-			}
-		}
-		service->setProperty(gIOUserClassesKey, classesArray);
-		OSSafeReleaseNULL(classesArray);
-		OSSafeReleaseNULL(prop);
 	}
 	IOLockUnlock(fLock);
 
@@ -4726,21 +2739,20 @@
 		if (ok) {
 			ret = LoadModule(execPath);
 			if (kIODKLogSetup & gIODKDebug) {
-				DKLOG(DKS "::LoadModule 0x%x %s\n", DKN(this), ret, execPath);
+				DKLOG("%s::LoadModule 0x%x %s\n", getName(), ret, execPath);
 			}
 		}
 	}
 	OSSafeReleaseNULL(prop);
 
 	ret = kIOReturnSuccess;
-	if (kIODKLogSetup & gIODKDebug) {
-		DKLOG(DKS "::serviceAttach(" DKS ", " DKS ")\n", DKN(this), DKN(service), DKN(provider));
-	}
 
 	return ret;
 }
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#define kDriverKitUCPrefix "com.apple.developer.driverkit.userclient-access."
 
 IOReturn
 IOUserServer::serviceNewUserClient(IOService * service, task_t owningTask, void * securityID,
@@ -4752,146 +2764,59 @@
 	OSDictionary     * entitlements;
 	OSObject         * prop;
 	OSObject         * bundleID;
-	bool               ok = false;
-
-	entitlements = IOUserClient::copyClientEntitlements(owningTask);
-	if (!entitlements) {
-		entitlements = OSDictionary::withCapacity(8);
-	}
-	if (entitlements) {
-		if (kIOReturnSuccess == clientHasPrivilege((void *) owningTask, kIOClientPrivilegeAdministrator)) {
-			entitlements->setObject(kIODriverKitUserClientEntitlementAdministratorKey, kOSBooleanTrue);
-		}
-		OSString * creatorName = IOCopyLogNameForPID(proc_selfpid());
-		if (creatorName) {
-			entitlements->setObject(kIOUserClientCreatorKey, creatorName);
-			OSSafeReleaseNULL(creatorName);
-		}
-	}
+	bool               ok;
 
 	*handler = NULL;
-	ret = service->_NewUserClient(type, entitlements, &uc);
-	if (kIOReturnSuccess != ret || uc == NULL) {
-		OSSafeReleaseNULL(uc);
-		OSSafeReleaseNULL(entitlements);
+	ret = service->NewUserClient(type, &uc);
+	if (kIOReturnSuccess != ret) {
 		return ret;
 	}
 	userUC = OSDynamicCast(IOUserUserClient, uc);
 	if (!userUC) {
-		if (uc) {
-			uc->terminate(kIOServiceTerminateNeedWillTerminate);
-			uc->setTerminateDefer(service, false);
-			OSSafeReleaseNULL(uc);
-		}
-		OSSafeReleaseNULL(entitlements);
+		uc->terminate();
+		OSSafeReleaseNULL(uc);
 		return kIOReturnUnsupported;
 	}
 	userUC->setTask(owningTask);
 
 	if (!(kIODKDisableEntitlementChecking & gIODKDebug)) {
-		do {
-			bool checkiOS3pEntitlements;
-
-			// check if client has com.apple.private.driverkit.driver-access and the required entitlements match the driver's entitlements
-			if (entitlements && (prop = entitlements->getObject(gIODriverKitRequiredEntitlementsKey))) {
-				prop->retain();
-				ok = checkEntitlements(fEntitlements, prop, NULL, NULL);
-				if (ok) {
-					break;
-				} else {
-					DKLOG(DKS ":UC failed required entitlement check\n", DKN(userUC));
-				}
-			}
-
-#if XNU_TARGET_OS_IOS
-			checkiOS3pEntitlements = !fPlatformDriver;
-			if (checkiOS3pEntitlements && fTeamIdentifier == NULL) {
-				DKLOG("warning: " DKS " does not have a team identifier\n", DKN(this));
-			}
-#else
-			checkiOS3pEntitlements = false;
-#endif
-			if (checkiOS3pEntitlements) {
-				// App must have com.apple.developer.driverkit.communicates-with-drivers
-				ok = entitlements && entitlements->getObject(gIODriverKitUserClientEntitlementCommunicatesWithDriversKey) == kOSBooleanTrue;
-				if (ok) {
-					// check team ID
-					const char * clientTeamID = csproc_get_teamid(current_proc());
-					bool sameTeam = fTeamIdentifier != NULL && clientTeamID != NULL && strncmp(fTeamIdentifier->getCStringNoCopy(), clientTeamID, CS_MAX_TEAMID_LEN) == 0;
-
-					if (sameTeam) {
-						ok = true;
-					} else {
-						// different team IDs, dext must have com.apple.developer.driverkit.allow-third-party-userclients
-						ok = fEntitlements && fEntitlements->getObject(gIODriverKitUserClientEntitlementAllowThirdPartyUserClientsKey) == kOSBooleanTrue;
-					}
-					if (!ok) {
-						DKLOG(DKS ":UC failed team ID check. client team=%s, driver team=%s\n", DKN(userUC), clientTeamID ? clientTeamID : "(null)", fTeamIdentifier ? fTeamIdentifier->getCStringNoCopy() : "(null)");
-					}
-				} else {
-					DKLOG(DKS ":UC entitlement check failed, app does not have %s entitlement\n", DKN(userUC), gIODriverKitUserClientEntitlementCommunicatesWithDriversKey->getCStringNoCopy());
-				}
-
-				// When checking iOS 3rd party entitlements, do not fall through to other entitlement checks
-				break;
-			}
-
-			// first party dexts and third party macOS dexts
-
-			// check if driver has com.apple.developer.driverkit.allow-any-userclient-access
-			if (fEntitlements && fEntitlements->getObject(gIODriverKitUserClientEntitlementAllowAnyKey)) {
-				ok = true;
-				break;
-			}
-
-			// check if client has com.apple.developer.driverkit.userclient-access and its value matches the bundle ID of the service
-			bundleID = service->copyProperty(gIOModuleIdentifierKey);
-			ok = (entitlements
-			    && bundleID
-			    && (prop = entitlements->getObject(gIODriverKitUserClientEntitlementsKey)));
-			if (ok) {
-				bool found __block = false;
-				ok = prop->iterateObjects(^bool (OSObject * object) {
-					found = object->isEqualTo(bundleID);
-					return found;
-				});
-				ok = found;
-			} else {
-				OSString * bundleIDStr = OSDynamicCast(OSString, bundleID);
-				DKLOG(DKS ":UC failed userclient-access check, needed bundle ID %s\n", DKN(userUC), bundleIDStr ? bundleIDStr->getCStringNoCopy() : "(null)");
-			}
-			OSSafeReleaseNULL(bundleID);
-		} while (false);
-
+		entitlements = IOUserClient::copyClientEntitlements(owningTask);
+		bundleID = service->copyProperty(gIOModuleIdentifierKey);
+		ok = (entitlements
+		    && bundleID
+		    && (prop = entitlements->getObject(gIODriverKitUserClientEntitlementsKey)));
+		if (ok) {
+			bool found __block = false;
+			ok = prop->iterateObjects(^bool (OSObject * object) {
+				found = object->isEqualTo(bundleID);
+				return found;
+			});
+			ok = found;
+		}
 		if (ok) {
 			prop = userUC->copyProperty(gIOServiceDEXTEntitlementsKey);
 			ok = checkEntitlements(entitlements, prop, NULL, NULL);
 		}
-
+		OSSafeReleaseNULL(bundleID);
+		OSSafeReleaseNULL(entitlements);
 		if (!ok) {
 			DKLOG(DKS ":UC entitlements check failed\n", DKN(userUC));
-			uc->terminate(kIOServiceTerminateNeedWillTerminate);
-			uc->setTerminateDefer(service, false);
+			uc->terminate();
 			OSSafeReleaseNULL(uc);
-			OSSafeReleaseNULL(entitlements);
 			return kIOReturnNotPermitted;
 		}
 	}
 
-	OSSafeReleaseNULL(entitlements);
+	ret = userUC->Start(service);
+	if (kIOReturnSuccess != ret) {
+		userUC->detach(this);
+		userUC->release();
+		return ret;
+	}
+
 	*handler = userUC;
 
 	return ret;
-}
-
-IOReturn
-IOUserServer::serviceNewUserClient(IOService * service, task_t owningTask, void * securityID,
-    uint32_t type, OSDictionary * properties, OSSharedPtr<IOUserClient>& handler)
-{
-	IOUserClient* handlerRaw = NULL;
-	IOReturn result = serviceNewUserClient(service, owningTask, securityID, type, properties, &handlerRaw);
-	handler.reset(handlerRaw, OSNoRetain);
-	return result;
 }
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -4907,106 +2832,11 @@
 	    .outputPowerCharacter   = kIOPMLowPower,
 	    .inputPowerRequirement  = kIOPMLowPower},
 	{   .version                = kIOPMPowerStateVersion1,
-	    .capabilityFlags        = kIOPMAOTPower,
-	    .outputPowerCharacter   = kIOPMAOTPower,
-	    .inputPowerRequirement  = kIOPMAOTPower},
-	{   .version                = kIOPMPowerStateVersion1,
 	    .capabilityFlags        = kIOPMPowerOn,
 	    .outputPowerCharacter   = kIOPMPowerOn,
 	    .inputPowerRequirement  = kIOPMPowerOn},
 };
 
-enum {
-	kUserServerMaxPowerState    = 3
-};
-
-IOReturn
-IOUserServer::serviceJoinPMTree(IOService * service)
-{
-	IOReturn    ret;
-	IOService * pmProvider;
-	bool        joinTree;
-
-	if (service->reserved->uvars->userServerPM) {
-		return kIOReturnSuccess;
-	}
-
-	if (!fRootNotifier) {
-		ret = registerPowerDriver(this, sPowerStates, sizeof(sPowerStates) / sizeof(sPowerStates[0]));
-		assert(kIOReturnSuccess == ret);
-		IOServicePH::serverAdd(this);
-		fRootNotifier = true;
-	}
-
-	joinTree = false;
-	if (!(kIODKDisablePM & gIODKDebug) && !service->pm_vars) {
-		kern_return_t  kr;
-		OSDictionary * props;
-		kr = service->CopyProperties_Local(&props);
-		if (kIOReturnSuccess == kr) {
-			if (props->getObject(kIOPMResetPowerStateOnWakeKey) == kOSBooleanTrue) {
-				service->setProperty(kIOPMResetPowerStateOnWakeKey, kOSBooleanTrue);
-			}
-			fAOTAllow |= (NULL != props->getObject(kIOPMAOTAllowKey));
-			if (!(kIODKDisableIOPMSystemOffPhase2Allow & gIODKDebug)) {
-				fSystemOffPhase2Allow |= (NULL != props->getObject(kIOPMSystemOffPhase2AllowKey));
-			}
-			OSSafeReleaseNULL(props);
-		}
-		service->PMinit();
-		ret = service->registerPowerDriver(this, sPowerStates, sizeof(sPowerStates) / sizeof(sPowerStates[0]));
-		assert(kIOReturnSuccess == ret);
-		joinTree = true;
-	}
-
-	pmProvider = service;
-	while (pmProvider && !pmProvider->inPlane(gIOPowerPlane)) {
-		pmProvider = pmProvider->getProvider();
-	}
-	if (!pmProvider) {
-		pmProvider = getPMRootDomain();
-	}
-	if (pmProvider) {
-		IOService * entry;
-		OSObject  * prop;
-		OSObject  * nextProp;
-		OSString  * str;
-
-		entry = pmProvider;
-		prop  = NULL;
-		do {
-			nextProp = entry->copyProperty("non-removable");
-			if (nextProp) {
-				OSSafeReleaseNULL(prop);
-				prop = nextProp;
-			}
-			entry = entry->getProvider();
-		} while (entry);
-		if (prop) {
-			str = OSDynamicCast(OSString, prop);
-			if (str && str->isEqualTo("yes")) {
-				pmProvider = NULL;
-			}
-			prop->release();
-		}
-	}
-
-	if (!(kIODKDisablePM & gIODKDebug) && pmProvider) {
-		IOLockLock(fLock);
-		service->reserved->uvars->powerState = true;
-		IOLockUnlock(fLock);
-
-		if (joinTree) {
-			pmProvider->joinPMtree(service);
-			service->reserved->uvars->userServerPM = true;
-			service->reserved->uvars->resetPowerOnWake = service->propertyExists(kIOPMResetPowerStateOnWakeKey);
-		}
-	}
-
-	service->registerInterestedDriver(this);
-	return kIOReturnSuccess;
-}
-
 IOReturn
 IOUserServer::setPowerState(unsigned long state, IOService * service)
 {
@@ -5016,67 +2846,25 @@
 	return kIOPMAckImplied;
 }
 
-
 IOReturn
-IOUserServer::serviceSetPowerState(IOService * controllingDriver, IOService * service, IOPMPowerFlags flags, unsigned long state)
+IOUserServer::powerStateWillChangeTo(IOPMPowerFlags flags, unsigned long state, IOService * service)
 {
 	IOReturn ret;
-	bool sendIt = false;
-
-	IOLockLock(fLock);
+
 	if (service->reserved->uvars) {
 		if (!fSystemOff && !(kIODKDisablePM & gIODKDebug)) {
 			service->reserved->uvars->willPower = true;
-			service->reserved->uvars->willPowerState = state;
-			service->reserved->uvars->controllingDriver = controllingDriver;
-			sendIt = true;
-		} else {
-			service->reserved->uvars->willPower = false;
-		}
-	}
-	IOLockUnlock(fLock);
-
-	if (sendIt) {
-		uint32_t driverFlags = (uint32_t) flags;
-		if (kIODKLogPM & gIODKDebug) {
-			DKLOG(DKS "::serviceSetPowerState(%ld, 0x%x) %d\n", DKN(service), state, driverFlags, fSystemPowerAck);
-		}
-#if DEBUG || DEVELOPMENT
-		bool pageout = false;
-		uint64_t pageincount = 0;
-		if (gLPWFlags) {
-			pageout = fPageout;
-			if (pageout) {
-				fPageout = false;
-				DKLOG(DKS " pageout\n", DKN(service));
-				pageincount = vm_task_evict_shared_cache(fOwningTask);
-			}
-		}
-#endif /* DEBUG || DEVELOPMENT */
-
-		ret = service->SetPowerState(driverFlags);
-
-#if DEBUG || DEVELOPMENT
-		if (pageout) {
-			DKLOG(DKS " state %ld pageins %qd\n", DKN(service), state, vm_task_pageins(fOwningTask) - pageincount);
-		}
-#endif /* DEBUG || DEVELOPMENT */
-
-		if (kIOReturnSuccess == ret) {
-			return 20 * 1000 * 1000;
-		} else {
-			IOLockLock(fLock);
-			service->reserved->uvars->willPower = false;
-			IOLockUnlock(fLock);
-		}
-	}
-
-	return kIOPMAckImplied;
-}
-
-IOReturn
-IOUserServer::powerStateWillChangeTo(IOPMPowerFlags flags, unsigned long state, IOService * service)
-{
+			if (kIODKLogPM & gIODKDebug) {
+				DKLOG(DKS "::powerStateWillChangeTo(%ld) 0x%qx, %d\n", DKN(service), state, fPowerStates, fSystemPowerAck);
+			}
+			ret = service->SetPowerState(flags);
+			if (kIOReturnSuccess == ret) {
+				return 20 * 1000 * 1000;
+			}
+		}
+		service->reserved->uvars->willPower = false;
+	}
+
 	return kIOPMAckImplied;
 }
 
@@ -5093,200 +2881,47 @@
 		IOLockUnlock(fLock);
 		return kIOPMAckImplied;
 	}
-
-	service->reserved->uvars->powerState = (0 != state);
-	bool allPowerStates __block = service->reserved->uvars->powerState;
-	if (!allPowerStates) {
-		// any service on?
-		fServices->iterateObjects(^bool (OSObject * obj) {
-			int         service __unused;       // hide outer defn
-			IOService * nextService;
-			nextService = (IOService *) obj;
-			allPowerStates = nextService->reserved->uvars->powerState;
-			// early terminate if true
-			return allPowerStates;
-		});
+	assert(idx <= 63);
+
+	if (state) {
+		fPowerStates |= (1ULL << idx);
+	} else {
+		fPowerStates &= ~(1ULL << idx);
 	}
 	if (kIODKLogPM & gIODKDebug) {
-		DKLOG(DKS "::powerStateDidChangeTo(%ld) %d, %d\n", DKN(service), state, allPowerStates, fSystemPowerAck);
-	}
-	if (!allPowerStates && (pmAck = fSystemPowerAck)) {
+		DKLOG(DKS "::powerStateDidChangeTo(%ld) 0x%qx, %d\n", DKN(service), state, fPowerStates, fSystemPowerAck);
+	}
+	if (!fPowerStates && (pmAck = fSystemPowerAck)) {
 		fSystemPowerAck = false;
 		fSystemOff      = true;
 	}
 	IOLockUnlock(fLock);
 
 	if (pmAck) {
-		serverAck();
+		IOServicePH::serverAck(this);
 	}
 
 	return kIOPMAckImplied;
 }
 
-bool
-IOUserServer::checkPMReady()
-{
-	bool __block ready = true;
-
-	IOLockLock(fLock);
-	// Check if any services have not completely joined the PM tree (i.e.
-	// addPowerChild has not compeleted).
-	fServices->iterateObjects(^bool (OSObject * obj) {
-		IOPowerConnection *conn;
-		IOService *service = (IOService *) obj;
-		IORegistryEntry *parent = service->getParentEntry(gIOPowerPlane);
-		if ((conn = OSDynamicCast(IOPowerConnection, parent))) {
-		        if (!conn->getReadyFlag()) {
-		                ready = false;
-		                return true;
-			}
-		}
-		return false;
-	});
-	IOLockUnlock(fLock);
-
-	return ready;
-}
-
-IOReturn
-IOUserServer::serviceCreatePMAssertion(IOService * service, uint32_t assertionBits, uint64_t * assertionID, bool synced)
-{
-	IOReturn ret = kIOReturnSuccess;
-
-	*assertionID = kIOPMUndefinedDriverAssertionID;
-
-	if (!service->reserved->uvars || service->reserved->uvars->userServer != this) {
-		return kIOReturnError;
-	}
-
-	if (!service->reserved->uvars->userServerPM) {
-		// Cannot create PM assertion unless joined PM tree
-		return kIOReturnNotReady;
-	}
-
-	// Check to make sure the bits are allowed
-	uint32_t userAllowedBits = kIOPMDriverAssertionCPUBit |
-	    kIOPMDriverAssertionForceFullWakeupBit;
-	if (synced) {
-		userAllowedBits = kIOPMDriverAssertionCPUBit;
-	}
-	if (0 == (assertionBits & ~userAllowedBits)) {
-		if (synced) {
-			ret = getPMRootDomain()->acquireDriverKitSyncedAssertion(service, assertionID);
-			assert(ret != kIOReturnSuccess || *assertionID != kIOPMUndefinedDriverAssertionID);
-		} else {
-			*assertionID = getPMRootDomain()->createPMAssertion(assertionBits,
-			    kIOPMDriverAssertionLevelOn,
-			    getPMRootDomain(),
-			    service->getName());
-			if (!*assertionID) {
-				ret = kIOReturnInternalError;
-			}
-		}
-	} else {
-		ret = kIOReturnBadArgument;
-	}
-	if (*assertionID != kIOPMUndefinedDriverAssertionID) {
-		IOLockLock(fLock);
-		OSNumber * assertionIDNumber = OSNumber::withNumber(*assertionID, 64);
-		OSArray ** pmAssertions = (synced ? &service->reserved->uvars->pmAssertionsSynced : &service->reserved->uvars->pmAssertions);
-		if (!*pmAssertions) {
-			*pmAssertions = OSArray::withCapacity(1);
-		}
-		(*pmAssertions)->setObject(assertionIDNumber);
-		assertionIDNumber->release();
-		IOLockUnlock(fLock);
-	}
-
-	return ret;
-}
-
-IOReturn
-IOUserServer::serviceReleasePMAssertion(IOService * service, IOPMDriverAssertionID assertionID)
-{
-	kern_return_t ret = kIOReturnSuccess;
-	bool synced = false;
-
-	bool (^findAndRemoveAssertionID)(OSArray *) = ^(OSArray * assertions) {
-		unsigned index;
-		if (!assertions) {
-			return false;
-		}
-		for (index = 0; index < assertions->getCount(); index++) {
-			OSNumber * theID = (OSNumber *)assertions->getObject(index);
-			if (theID->unsigned64BitValue() == assertionID) {
-				break;
-			}
-		}
-		if (index == assertions->getCount()) {
-			return false;
-		}
-		assertions->removeObject(index);
-		return true;
-	};
-
-	if (!service->reserved->uvars || !service->reserved->uvars->userServer) {
-		return kIOReturnError;
-	}
-
-	IOLockLock(fLock);
-	if (findAndRemoveAssertionID(service->reserved->uvars->pmAssertionsSynced)) {
-		synced = true;
-	} else if (!findAndRemoveAssertionID(service->reserved->uvars->pmAssertions)) {
-		ret = kIOReturnNotFound;
-	}
-	IOLockUnlock(fLock);
-
-	if (ret == kIOReturnSuccess) {
-		if (synced) {
-			getPMRootDomain()->releaseDriverKitSyncedAssertion(assertionID);
-		} else {
-			getPMRootDomain()->releasePMAssertion(assertionID);
-		}
-	}
-
-	return ret;
-}
-
-kern_return_t
-IOService::JoinPMTree_Impl(void)
-{
-	if (!reserved->uvars || !reserved->uvars->userServer) {
-		return kIOReturnNotReady;
-	}
-	return reserved->uvars->userServer->serviceJoinPMTree(this);
-}
-
-static kern_return_t
-acknowledgeSetPowerState(IOService * service)
-{
-	if (service->reserved->uvars
-	    && service->reserved->uvars->userServer
-	    && service->reserved->uvars->willPower) {
-		IOReturn ret;
-		service->reserved->uvars->willPower = false;
-		ret = service->reserved->uvars->controllingDriver->setPowerState(service->reserved->uvars->willPowerState, service);
-		if (kIOPMAckImplied == ret) {
-			service->acknowledgeSetPowerState();
-		}
-		return kIOReturnSuccess;
-	}
-	return kIOReturnNotReady;
-}
-
-kern_return_t
-IOService::SetPowerState_Impl(
-	uint32_t powerFlags)
+kern_return_t
+IMPL(IOService, SetPowerState)
 {
 	if (kIODKLogPM & gIODKDebug) {
 		DKLOG(DKS "::SetPowerState(%d), %d\n", DKN(this), powerFlags, reserved->uvars->willPower);
 	}
-	return ::acknowledgeSetPowerState(this);
-}
-
-kern_return_t
-IOService::ChangePowerState_Impl(
-	uint32_t powerFlags)
+	if (reserved->uvars
+	    && reserved->uvars->userServer
+	    && reserved->uvars->willPower) {
+		reserved->uvars->willPower = false;
+		acknowledgePowerChange(reserved->uvars->userServer);
+		return kIOReturnSuccess;
+	}
+	return kIOReturnNotReady;
+}
+
+kern_return_t
+IMPL(IOService, ChangePowerState)
 {
 	switch (powerFlags) {
 	case kIOServicePowerCapabilityOff:
@@ -5296,7 +2931,7 @@
 		changePowerStateToPriv(1);
 		break;
 	case kIOServicePowerCapabilityOn:
-		changePowerStateToPriv(kUserServerMaxPowerState);
+		changePowerStateToPriv(2);
 		break;
 	default:
 		return kIOReturnBadArgument;
@@ -5306,63 +2941,17 @@
 }
 
 kern_return_t
-IOService::SetPowerOverride_Impl(
-	bool enable)
-{
-	kern_return_t ret;
-
-	if (enable) {
-		ret = powerOverrideOnPriv();
-	} else {
-		ret = powerOverrideOffPriv();
-	}
-
-	return ret == IOPMNoErr ? kIOReturnSuccess : kIOReturnError;
-}
-
-kern_return_t
-IOService::_ClaimSystemWakeEvent_Impl(
-	IOService          * device,
-	uint64_t             flags,
-	const char         * reason,
-	OSContainer        * details)
-{
-	IOPMrootDomain * rootDomain;
-	IOOptionBits     pmFlags;
-
-	rootDomain = getPMRootDomain();
-	if (!rootDomain) {
-		return kIOReturnNotReady;
-	}
-	if (os_convert_overflow(flags, &pmFlags)) {
-		return kIOReturnBadArgument;
-	}
-	rootDomain->claimSystemWakeEvent(device, pmFlags, reason, details);
-
-	return kIOReturnSuccess;
-}
-
-kern_return_t
-IOService::Create_Impl(
-	IOService * provider,
-	const char * propertiesKey,
-	IOService ** result)
+IMPL(IOService, Create)
 {
 	OSObject       * inst;
 	IOService      * service;
 	OSString       * str;
 	const OSSymbol * sym;
-	OSObject       * prop = NULL;
-	OSObject       * moduleIdentifier = NULL;
-	OSObject       * userServerName = NULL;
-	OSDictionary   * properties = NULL;
-	OSDictionary   * copyProperties = NULL;
+	OSObject       * prop;
+	OSDictionary   * properties;
 	kern_return_t    ret;
 
 	if (provider != this) {
-		return kIOReturnUnsupported;
-	}
-	if (reserved == NULL || reserved->uvars == NULL) {
 		return kIOReturnUnsupported;
 	}
 
@@ -5370,53 +2959,26 @@
 	inst = NULL;
 	service = NULL;
 
-	prop = reserved->uvars->originalProperties->getObject(propertiesKey);
-	if (!prop) {
-		return kIOReturnBadArgument;
-	}
-	prop->retain();
+	prop = copyProperty(propertiesKey);
 	properties = OSDynamicCast(OSDictionary, prop);
-	if (!properties) {
-		ret = kIOReturnBadArgument;
-		goto finish;
-	}
-	copyProperties = OSDynamicCast(OSDictionary, properties->copyCollection());
-	if (!copyProperties) {
-		ret = kIOReturnNoMemory;
-		goto finish;
-	}
-	moduleIdentifier = copyProperty(gIOModuleIdentifierKey);
-	if (moduleIdentifier) {
-		copyProperties->setObject(gIOModuleIdentifierKey, moduleIdentifier);
-	}
-	userServerName = reserved->uvars->userServer->copyProperty(gIOUserServerNameKey);
-	if (userServerName) {
-		copyProperties->setObject(gIOUserServerNameKey, userServerName);
-	}
-
-	str = OSDynamicCast(OSString, copyProperties->getObject(gIOClassKey));
-	if (!str) {
-		ret = kIOReturnBadArgument;
-		goto finish;
-	}
-	sym = OSSymbol::withString(str);
-	if (sym) {
-		inst = OSMetaClass::allocClassWithName(sym);
-		service = OSDynamicCast(IOService, inst);
-		if (service && service->init(copyProperties) && service->attach(this)) {
-			reserved->uvars->userServer->serviceAttach(service, this);
-			service->reserved->uvars->started = true;
-			ret = kIOReturnSuccess;
-			*result = service;
-		}
-		OSSafeReleaseNULL(sym);
-	}
-
-finish:
+	assert(properties);
+	if (properties) {
+		str = OSDynamicCast(OSString, properties->getObject(gIOClassKey));
+		assert(str);
+		sym = OSSymbol::withString(str);
+		if (sym) {
+			inst = OSMetaClass::allocClassWithName(sym);
+			service = OSDynamicCast(IOService, inst);
+			if (service && service->init(properties) && service->attach(this)) {
+				reserved->uvars->userServer->serviceAttach(service, this);
+				ret = kIOReturnSuccess;
+				*result = service;
+			}
+			OSSafeReleaseNULL(sym);
+		}
+	}
+
 	OSSafeReleaseNULL(prop);
-	OSSafeReleaseNULL(copyProperties);
-	OSSafeReleaseNULL(moduleIdentifier);
-	OSSafeReleaseNULL(userServerName);
 	if (kIOReturnSuccess != ret) {
 		OSSafeReleaseNULL(inst);
 	}
@@ -5425,530 +2987,141 @@
 }
 
 kern_return_t
-IOService::Terminate_Impl(
-	uint64_t options)
-{
-	IOUserServer * us;
-
-	if (options) {
-		return kIOReturnUnsupported;
-	}
-
-	us = (typeof(us))thread_iokit_tls_get(0);
-	if (us && (!reserved->uvars
-	    || (reserved->uvars->userServer != us))) {
-		return kIOReturnNotPermitted;
-	}
-	terminate(kIOServiceTerminateNeedWillTerminate);
-
-	return kIOReturnSuccess;
-}
-
-kern_return_t
-IOService::NewUserClient_Impl(
-	uint32_t type,
-	IOUserClient ** userClient)
+IMPL(IOService, NewUserClient)
 {
 	return kIOReturnError;
 }
 
 kern_return_t
-IOService::_NewUserClient_Impl(
-	uint32_t type,
-	OSDictionary * entitlements,
-	IOUserClient ** userClient)
-{
-	return kIOReturnError;
-}
-
-kern_return_t
-IOService::SearchProperty_Impl(
-	const char * name,
-	const char * plane,
-	uint64_t options,
-	OSContainer ** property)
-{
-	OSObject   * object __block;
-	IOService  * provider;
-	IOOptionBits regOptions;
+IMPL(IOService, SearchProperty)
+{
+	OSObject * object;
 
 	if (kIOServiceSearchPropertyParents & options) {
-		regOptions = kIORegistryIterateParents | kIORegistryIterateRecursively;
+		options = kIORegistryIterateParents | kIORegistryIterateRecursively;
 	} else {
-		regOptions = 0;
-	}
-
-	object = copyProperty(name, IORegistryEntry::getPlane(plane), regOptions);
-
-	if (NULL == object) {
-		for (provider = this; provider; provider = provider->getProvider()) {
-			provider->runPropertyActionBlock(^IOReturn (void) {
-				OSDictionary * userProps;
-				object = provider->getProperty(name);
-				if (!object
-				&& (userProps = OSDynamicCast(OSDictionary, provider->getProperty(gIOUserServicePropertiesKey)))) {
-				        object = userProps->getObject(name);
-				}
-				if (object) {
-				        object->retain();
-				}
-				return kIOReturnSuccess;
-			});
-			if (object || !(kIORegistryIterateParents & regOptions)) {
-				break;
-			}
-		}
-	}
-
+		options = 0;
+	}
+
+	object = copyProperty(name, IORegistryEntry::getPlane(plane), options);
 	*property = object;
 
 	return object ? kIOReturnSuccess : kIOReturnNotFound;
 }
 
-kern_return_t
-IOService::StringFromReturn_Impl(
-	IOReturn retval,
-	OSString ** str)
-{
-	OSString *obj = OSString::withCString(stringFromReturn(retval));
-	*str = obj;
-	return obj ? kIOReturnSuccess : kIOReturnError;
-}
-
-#if PRIVATE_WIFI_ONLY
-const char *
-IOService::StringFromReturn(
-	IOReturn retval)
-{
-	return stringFromReturn(retval);
-}
-#endif /* PRIVATE_WIFI_ONLY */
-
-kern_return_t
-IOService::CopyProviderProperties_Impl(
-	OSArray * propertyKeys,
-	OSArray ** properties)
-{
-	IOReturn    ret;
-	OSArray   * result;
-	IOService * provider;
-
-	result = OSArray::withCapacity(8);
-	if (!result) {
-		return kIOReturnNoMemory;
-	}
-
-	ret = kIOReturnSuccess;
-	for (provider = this; provider; provider = provider->getProvider()) {
-		OSObject     * obj;
-		OSDictionary * props;
-
-		obj = provider->copyProperty(gIOSupportedPropertiesKey);
-		props = OSDynamicCast(OSDictionary, obj);
-		if (!props) {
-			OSSafeReleaseNULL(obj);
-			props = provider->dictionaryWithProperties();
-		}
-		if (!props) {
-			ret = kIOReturnNoMemory;
-			break;
-		}
-
-		bool __block addClass = true;
-		if (propertyKeys) {
-			OSDictionary * retProps;
-			retProps = OSDictionary::withCapacity(4);
-			addClass = false;
-			if (!retProps) {
-				ret = kIOReturnNoMemory;
-				OSSafeReleaseNULL(props);
-				break;
-			}
-			propertyKeys->iterateObjects(^bool (OSObject * _key) {
-				OSString * key = OSDynamicCast(OSString, _key);
-				if (gIOClassKey->isEqualTo(key)) {
-				        addClass = true;
-				        return false;
-				}
-				retProps->setObject(key, props->getObject(key));
-				return false;
-			});
-			OSSafeReleaseNULL(props);
-			props = retProps;
-		}
-		if (addClass) {
-			OSArray * classes = OSArray::withCapacity(8);
-			if (!classes) {
-				OSSafeReleaseNULL(props);
-				ret = kIOReturnNoMemory;
-				break;
-			}
-			for (const OSMetaClass * meta = provider->getMetaClass(); meta; meta = meta->getSuperClass()) {
-				classes->setObject(meta->getClassNameSymbol());
-			}
-			props->setObject(gIOClassKey, classes);
-			OSSafeReleaseNULL(classes);
-		}
-		bool ok = result->setObject(props);
-		props->release();
-		if (!ok) {
-			ret = kIOReturnNoMemory;
-			break;
-		}
-	}
-	if (kIOReturnSuccess != ret) {
-		OSSafeReleaseNULL(result);
-	}
-	*properties = result;
-	return ret;
-}
-
-IOReturn
-IOService::AdjustBusy_Impl(int32_t delta)
-{
-	adjustBusy(delta);
-	return kIOReturnSuccess;
-}
-
-IOReturn
-IOService::GetBusyState_Impl(uint32_t *busyState)
-{
-	*busyState = getBusyState();
-	return kIOReturnSuccess;
-}
-
-kern_return_t
-IOService::CreatePMAssertion_Impl(uint32_t assertionBits, uint64_t * assertionID, bool synced)
-{
-	*assertionID = kIOPMUndefinedDriverAssertionID;
-
-	if (!reserved->uvars || !reserved->uvars->userServer) {
-		return kIOReturnError;
-	}
-
-	return reserved->uvars->userServer->serviceCreatePMAssertion(this, assertionBits, assertionID, synced);
-}
-
-kern_return_t
-IOService::ReleasePMAssertion_Impl(uint64_t assertionID)
-{
-	if (!reserved->uvars || !reserved->uvars->userServer) {
-		return kIOReturnError;
-	}
-
-	return reserved->uvars->userServer->serviceReleasePMAssertion(this, assertionID);
-}
-
 void
-IOUserServer::serverAck(void)
-{
-	IOServicePH::serverAck(this);
-}
-
-OSArray *
-IOUserServer::servicesWithPowerState(bool state)
-{
-	OSArray * result = OSArray::withCapacity(1);
-	if (!result) {
-		return NULL;
-	}
+IOUserServer::systemPower(bool powerOff)
+{
+	OSArray * services;
+
+	if (kIODKLogPM & gIODKDebug) {
+		DKLOG("%s::powerOff(%d) 0x%qx\n", getName(), powerOff, fPowerStates);
+	}
+
 	IOLockLock(fLock);
-	fServices->iterateObjects(^(OSObject * object) {
-		IOService * service = OSDynamicCast(IOService, object);
-		if (service && service->reserved->uvars->powerState == state) {
-		        result->setObject(service);
-		}
-		return false;
-	});
-	IOLockUnlock(fLock);
-	if (!result->getCount()) {
-		OSSafeReleaseNULL(result);
-	}
-	return result;
-}
-
-void
-IOUserServer::systemSuspend()
-{
-	if (fSystemOff && !fSuspended) {
-		KDBG(MACHDBG_CODE(DBG_MACH_SCHED, MACH_SUSPEND_DRIVERKIT_USERSPACE) | DBG_FUNC_START,
-		    task_pid(fOwningTask));
-		task_suspend_internal(fOwningTask);
-		DKLOG(DKS " did task_suspend_internal\n", DKN(this));
-		fSuspended = true;
-	}
-}
-
-void
-IOUserServer::systemPower(uint8_t systemState, bool hibernate)
-{
-	OSArray * services;
-	{
-		OSDictionary * sleepDescription;
-		OSObject     * prop;
-
-		sleepDescription = OSDictionary::withCapacity(3);
-		if (sleepDescription) {
-			prop = getPMRootDomain()->copyProperty(kRootDomainSleepReasonKey);
-			if (prop) {
-				sleepDescription->setObject(gIOSystemStateSleepDescriptionReasonKey, prop);
-				OSSafeReleaseNULL(prop);
-			}
-			prop = getPMRootDomain()->copyProperty(kIOHibernateStateKey);
-			if (prop) {
-				sleepDescription->setObject(gIOSystemStateSleepDescriptionHibernateStateKey, prop);
-				OSSafeReleaseNULL(prop);
-			}
-			if (hibernate) {
-				uint32_t correctHibernateState = kIOSystemStateSleepDescriptionHibernateStateHibernating;
-				OSData *correctHibernateStateData = OSData::withValue(correctHibernateState);
-				assert(correctHibernateStateData != NULL);
-				sleepDescription->setObject(gIOSystemStateSleepDescriptionHibernateStateKey, correctHibernateStateData);
-				OSSafeReleaseNULL(correctHibernateStateData);
-			}
-			getSystemStateNotificationService()->StateNotificationItemSet(gIOSystemStateSleepDescriptionKey, sleepDescription);
-			OSSafeReleaseNULL(sleepDescription);
-		}
-	}
-	if (!IsIOServiceSystemStateOff(systemState)) {
-		OSDictionary * wakeDescription;
-		OSObject     * prop;
-		char           wakeReasonString[128];
-
-		wakeDescription = OSDictionary::withCapacity(2);
-		if (wakeDescription) {
-			wakeReasonString[0] = 0;
-			getPMRootDomain()->copyWakeReasonString(wakeReasonString, sizeof(wakeReasonString));
-
-			if (wakeReasonString[0]) {
-				prop = OSString::withCString(&wakeReasonString[0]);
-				wakeDescription->setObject(gIOSystemStateWakeDescriptionWakeReasonKey, prop);
-				OSSafeReleaseNULL(prop);
-			}
-#if defined(__arm__) || defined(__arm64__)
-			prop = OSNumber::withNumber(ml_get_conttime_offset(), sizeof(uint64_t) * CHAR_BIT);
-			wakeDescription->setObject(gIOSystemStateWakeDescriptionContinuousTimeOffsetKey, prop);
-			OSSafeReleaseNULL(prop);
-#endif /* defined(__arm__) || defined(__arm64__) */
-			getSystemStateNotificationService()->StateNotificationItemSet(gIOSystemStateWakeDescriptionKey, wakeDescription);
-			OSSafeReleaseNULL(wakeDescription);
-		}
-	}
-
-	IOLockLock(fLock);
-
 	services = OSArray::withArray(fServices);
 
-	bool allPowerStates __block = 0;
-	// any service on?
-	fServices->iterateObjects(^bool (OSObject * obj) {
-		int         service __unused;       // hide outer defn
-		IOService * nextService;
-		nextService = (IOService *) obj;
-		allPowerStates = nextService->reserved->uvars->powerState;
-		// early terminate if true
-		return allPowerStates;
-	});
-
-	// figure what phase this DK server process will be suspended in,
-	// and make sure its power changes complete before suspension
-
-	bool effectiveOff = IsIOServiceSystemStateOff(systemState) && !allPowerStates;
-	effectiveOff |= ((kIOServiceSystemStateOffPhase1 == systemState) && !fSystemOffPhase2Allow);
-	effectiveOff |= (kIOServiceSystemStateOffPhase2 == systemState);
-	effectiveOff |= ((kIOServiceSystemStateAOT == systemState) && !fAOTAllow);
-
-	DKLOG(DKS "::systemPower(0x%x) effective %d current %d\n", DKN(this), systemState, !effectiveOff, allPowerStates != 0);
-
-	if (effectiveOff) {
-		fSystemPowerAck = allPowerStates;
+	if (powerOff) {
+		fSystemPowerAck = (0 != fPowerStates);
 		if (!fSystemPowerAck) {
 			fSystemOff = true;
 		}
 		IOLockUnlock(fLock);
 
 		if (!fSystemPowerAck) {
-			serverAck();
+			IOServicePH::serverAck(this);
 		} else {
 			if (services) {
 				services->iterateObjects(^bool (OSObject * obj) {
-					int         service __unused;       // hide outer defn
-					IOService * nextService;
-					nextService = (IOService *) obj;
+					IOService * service;
+					service = (IOService *) obj;
 					if (kIODKLogPM & gIODKDebug) {
-					        DKLOG("changePowerStateWithOverrideTo(" DKS ", %d)\n", DKN(nextService), 0);
+					        DKLOG("changePowerStateWithOverrideTo(" DKS ", %d)\n", DKN(service), 0);
 					}
-					nextService->reserved->uvars->powerOverride = nextService->reserved->uvars->userServerPM ? kUserServerMaxPowerState : nextService->getPowerState();
-					nextService->changePowerStateWithOverrideTo(0, 0);
+					service->reserved->uvars->powerOverride = service->getPowerState();
+					service->changePowerStateWithOverrideTo(0, 0);
 					return false;
 				});
 			}
 		}
-	} else if (fSystemOff) {
+	} else {
 		fSystemOff = false;
-
-		if (fSuspended) {
-			KDBG(MACHDBG_CODE(DBG_MACH_SCHED, MACH_SUSPEND_DRIVERKIT_USERSPACE) | DBG_FUNC_END,
-			    task_pid(fOwningTask));
-			task_resume_internal(fOwningTask);
-			DKLOG(DKS " did task_resume_internal\n", DKN(this));
-			fSuspended = false;
-		}
-
 		IOLockUnlock(fLock);
 		if (services) {
 			services->iterateObjects(^bool (OSObject * obj) {
-				int         service __unused;       // hide outer defn
-				IOService * nextService;
-				nextService = (IOService *) obj;
-				if (-1U != nextService->reserved->uvars->powerOverride) {
+				IOService * service;
+				service = (IOService *) obj;
+				if (-1U != service->reserved->uvars->powerOverride) {
 				        if (kIODKLogPM & gIODKDebug) {
-				                DKLOG("%schangePowerStateWithOverrideTo(" DKS ", %d)\n", nextService->reserved->uvars->resetPowerOnWake ? "!" : "", DKN(nextService), nextService->reserved->uvars->powerOverride);
+				                DKLOG("changePowerStateWithOverrideTo(" DKS ", %d)\n", DKN(service), service->reserved->uvars->powerOverride);
 					}
-				        if (!nextService->reserved->uvars->resetPowerOnWake) {
-				                nextService->changePowerStateWithOverrideTo(nextService->reserved->uvars->powerOverride, 0);
-					}
-				        nextService->reserved->uvars->powerOverride = -1U;
+				        service->changePowerStateWithOverrideTo(service->reserved->uvars->powerOverride, 0);
+				        service->reserved->uvars->powerOverride = -1U;
 				}
 				return false;
 			});
 		}
-	} else {
-		IOLockUnlock(fLock);
-		serverAck();
 	}
 	OSSafeReleaseNULL(services);
 }
 
-void
-IOUserServer::systemHalt(int howto)
-{
-	OSArray * services;
-
-	if (true || (kIODKLogPM & gIODKDebug)) {
-		DKLOG(DKS "::systemHalt()\n", DKN(this));
-	}
-
-	{
-		OSDictionary * haltDescription;
-		OSNumber     * state;
-		uint64_t       haltStateFlags;
-
-		haltDescription = OSDictionary::withCapacity(4);
-		if (haltDescription) {
-			haltStateFlags = 0;
-			if (RB_HALT & howto) {
-				haltStateFlags |= kIOServiceHaltStatePowerOff;
-			} else {
-				haltStateFlags |= kIOServiceHaltStateRestart;
-			}
-			state = OSNumber::withNumber(haltStateFlags, 64);
-			haltDescription->setObject(gIOSystemStateHaltDescriptionHaltStateKey, state);
-			getSystemStateNotificationService()->StateNotificationItemSet(gIOSystemStateHaltDescriptionKey, haltDescription);
-
-			OSSafeReleaseNULL(state);
-			OSSafeReleaseNULL(haltDescription);
-		}
-	}
-
-	IOLockLock(fLock);
-	services = OSArray::withArray(fServices);
-	IOLockUnlock(fLock);
-
-	if (services) {
-		services->iterateObjects(^bool (OSObject * obj) {
-			int         service __unused;       // hide outer defn
-			IOService  * nextService;
-			IOService  * provider;
-			IOOptionBits terminateOptions;
-			bool         root;
-
-			nextService = (IOService *) obj;
-			provider = nextService->getProvider();
-			if (!provider) {
-			        DKLOG("stale service " DKS " found, skipping termination\n", DKN(nextService));
-			        return false;
-			}
-			root = (NULL == provider->getProperty(gIOUserServerNameKey, gIOServicePlane));
-			if (true || (kIODKLogPM & gIODKDebug)) {
-			        DKLOG("%d: terminate(" DKS ")\n", root, DKN(nextService));
-			}
-			if (!root) {
-			        return false;
-			}
-			if (nextService->reserved && nextService->reserved->uvars) {
-			        if (nextService->reserved->uvars->started) {
-			                terminateOptions = kIOServiceRequired | kIOServiceTerminateNeedWillTerminate;
-			                if (!nextService->terminate(terminateOptions)) {
-			                        IOLog("failed to terminate service %s-0x%llx\n", nextService->getName(), nextService->getRegistryEntryID());
-					}
-				} else {
-			                IOLog("service %s-0x%llx not started, skipped termination\n", nextService->getName(), nextService->getRegistryEntryID());
-				}
-			}
-			return false;
-		});
-	}
-	OSSafeReleaseNULL(services);
-}
-
-void
-IOUserServer::powerSourceChanged(bool acAttached)
-{
-	OSDictionary * powerSourceDescription;
-
-	powerSourceDescription = OSDictionary::withCapacity(4);
-	if (!powerSourceDescription) {
-		return;
-	}
-	powerSourceDescription->setObject(gIOSystemStatePowerSourceDescriptionACAttachedKey, acAttached ? kOSBooleanTrue : kOSBooleanFalse);
-	getSystemStateNotificationService()->StateNotificationItemSet(gIOSystemStatePowerSourceDescriptionKey, powerSourceDescription);
-
-	OSSafeReleaseNULL(powerSourceDescription);
-}
+
 
 IOReturn
 IOUserServer::serviceStarted(IOService * service, IOService * provider, bool result)
 {
 	IOReturn    ret;
-	bool        needStop = false;
+	IOService * pmProvider;
 
 	DKLOG(DKS "::start(" DKS ") %s\n", DKN(service), DKN(provider), result ? "ok" : "fail");
 
 	if (!result) {
-		if (!service->reserved->uvars->instantiated && provider) {
-			// Object instantiation did not happen. This can happen if,
-			// 1. Dext crashed, in which case the user server has been terminated when the task is marked as corpse
-			// 2. Kernel IOService failed start, and it did not attempt Start
-			// A rematch should be attempted for 1, not 2
-			bool shouldReRegister = true;
-			if (lockForArbitration()) {
-				shouldReRegister = (__state[0] & kIOServiceInactiveState);
-				unlockForArbitration();
-			}
-			if (shouldReRegister) {
-				provider->registerService(kIOServiceAsynchronous);
-			}
-		}
 		ret = kIOReturnSuccess;
 		return ret;
 	}
 
-	ret = serviceJoinPMTree(service);
-
-	IOLockLock(service->reserved->uvars->uvarsLock);
+	if (!fRootNotifier) {
+		ret = registerPowerDriver(this, sPowerStates, sizeof(sPowerStates) / sizeof(sPowerStates[0]));
+		assert(kIOReturnSuccess == ret);
+		IOServicePH::serverAdd(this);
+		fRootNotifier = true;
+	}
+
+	if (!(kIODKDisablePM & gIODKDebug) && !service->pm_vars) {
+		service->PMinit();
+		ret = service->registerPowerDriver(this, sPowerStates, sizeof(sPowerStates) / sizeof(sPowerStates[0]));
+		assert(kIOReturnSuccess == ret);
+
+		pmProvider = service;
+		while (pmProvider && !pmProvider->inPlane(gIOPowerPlane)) {
+			pmProvider = pmProvider->getProvider();
+		}
+		if (pmProvider) {
+			OSObject  * prop;
+			OSString  * str;
+			prop = pmProvider->copyProperty("non-removable");
+			if (prop) {
+				str = OSDynamicCast(OSString, prop);
+				if (str && str->isEqualTo("yes")) {
+					pmProvider = NULL;
+				}
+				prop->release();
+			}
+		}
+		if (pmProvider) {
+			IOLockLock(fLock);
+			unsigned int idx = fServices->getNextIndexOfObject(service, 0);
+			assert(idx <= 63);
+			fPowerStates |= (1ULL << idx);
+			IOLockUnlock(fLock);
+
+			pmProvider->joinPMtree(service);
+			service->reserved->uvars->userServerPM = true;
+		}
+	}
+
+	service->registerInterestedDriver(this);
 	service->reserved->uvars->started = true;
-	needStop = service->reserved->uvars->needStop;
-	IOLockUnlock(service->reserved->uvars->uvarsLock);
-	if (needStop) {
-		serviceStop(service, provider);
-		return kIOReturnSuccess;
-	}
-
-	if (service->reserved->uvars->deferredRegisterService) {
-		service->registerService(kIOServiceAsynchronous | kIOServiceDextRequirePowerForMatching);
-		service->reserved->uvars->deferredRegisterService = false;
-	}
 
 	return kIOReturnSuccess;
 }
@@ -5958,25 +3131,15 @@
 IOUserServer::serviceOpen(IOService * provider, IOService * client)
 {
 	OSObjectUserVars * uvars;
-	IOReturn ret;
-
-	IOLockLock(client->reserved->uvars->uvarsLock);
+
 	uvars = client->reserved->uvars;
-	if (uvars->willTerminate || uvars->stopped) {
-		DKLOG(DKS "- " DKS " blocked attempt to open " DKS "\n", DKN(this), DKN(client), DKN(provider));
-		ret = kIOReturnBadArgument;
-	} else {
-		if (!uvars->openProviders) {
-			uvars->openProviders = OSArray::withObjects((const OSObject **) &provider, 1);
-		} else if (-1U == uvars->openProviders->getNextIndexOfObject(provider, 0)) {
-			uvars->openProviders->setObject(provider);
-		}
-		ret = kIOReturnSuccess;
-	}
-
-	IOLockUnlock(client->reserved->uvars->uvarsLock);
-
-	return ret;
+	if (!uvars->openProviders) {
+		uvars->openProviders = OSArray::withObjects((const OSObject **) &provider, 1);
+	} else if (-1U == uvars->openProviders->getNextIndexOfObject(client, 0)) {
+		uvars->openProviders->setObject(provider);
+	}
+
+	return kIOReturnSuccess;
 }
 
 IOReturn
@@ -5984,152 +3147,43 @@
 {
 	OSObjectUserVars * uvars;
 	unsigned int       idx;
-	IOReturn           ret;
-
-	IOLockLock(client->reserved->uvars->uvarsLock);
+
 	uvars = client->reserved->uvars;
 	if (!uvars->openProviders) {
-		ret = kIOReturnNotOpen;
-		goto finish;
-	}
-	idx = uvars->openProviders->getNextIndexOfObject(provider, 0);
+		return kIOReturnNotOpen;
+	}
+	idx = uvars->openProviders->getNextIndexOfObject(client, 0);
 	if (-1U == idx) {
-		ret = kIOReturnNotOpen;
-		goto finish;
+		return kIOReturnNotOpen;
 	}
 	uvars->openProviders->removeObject(idx);
-	if (!uvars->openProviders->getCount()) {
-		OSSafeReleaseNULL(uvars->openProviders);
-	}
-
-	ret = kIOReturnSuccess;
-
-finish:
-	IOLockUnlock(client->reserved->uvars->uvarsLock);
-	if (kIODKLogSetup & gIODKDebug) {
-		DKLOG(DKS "::serviceClose(" DKS ", " DKS ") -> %x\n", DKN(this), DKN(provider), DKN(client), ret);
-	}
-
-	return ret;
+
+	return kIOReturnSuccess;
 }
 
 
 IOReturn
-IOUserServer::serviceStop(IOService * service, IOService *provider)
+IOUserServer::serviceStop(IOService * service, IOService *)
 {
 	IOReturn           ret;
-	uint32_t           idx;
-	bool               pmAck;
-	bool               deferred = false;
-	OSObjectUserVars * uvars = service->reserved->uvars;
-
-	IOLockLock(uvars->uvarsLock);
-	if (!uvars->started) {
-		// started will be set, at a later point
-		uvars->needStop = true;
-		deferred = true;
-	}
-	IOLockUnlock(uvars->uvarsLock);
-	if (deferred) {
-		return kIOReturnSuccess;
-	}
-
-	pmAck = false;
+	uint32_t           idx, queueAlloc;
+	OSObjectUserVars * uvars;
+
 	IOLockLock(fLock);
 	idx = fServices->getNextIndexOfObject(service, 0);
 	if (-1U != idx) {
 		fServices->removeObject(idx);
-
-		// Remove the service from IOAssociatedServices
-		OSObject * serviceArrayObj = copyProperty(gIOAssociatedServicesKey);
-		OSArray * serviceArray = OSDynamicCast(OSArray, serviceArrayObj);
-		assert(serviceArray != NULL);
-
-		serviceArray = OSDynamicCast(OSArray, serviceArray->copyCollection());
-		assert(serviceArray != NULL);
-
-		// Index should be the same as it was in fServices
-		OSNumber * __assert_only registryEntryID = OSDynamicCast(OSNumber, serviceArray->getObject(idx));
-		assert(registryEntryID);
-
-		// ensure it is the right service
-		assert(registryEntryID->unsigned64BitValue() == service->getRegistryEntryID());
-		serviceArray->removeObject(idx);
-
-		setProperty(gIOAssociatedServicesKey, serviceArray);
-		OSSafeReleaseNULL(serviceArray);
-		OSSafeReleaseNULL(serviceArrayObj);
-
+		uvars = service->reserved->uvars;
 		uvars->stopped = true;
-		uvars->powerState = 0;
-
-		bool allPowerStates __block = 0;
-		// any service on?
-		fServices->iterateObjects(^bool (OSObject * obj) {
-			int         service __unused;       // hide outer defn
-			IOService * nextService;
-			nextService = (IOService *) obj;
-			allPowerStates = nextService->reserved->uvars->powerState;
-			// early terminate if true
-			return allPowerStates;
-		});
-
-		if (!allPowerStates && (pmAck = fSystemPowerAck)) {
-			fSystemPowerAck = false;
-			fSystemOff      = true;
-		}
 	}
 	IOLockUnlock(fLock);
-	if (pmAck) {
-		serverAck();
-	}
 
 	if (-1U == idx) {
-		if (kIODKLogSetup & gIODKDebug) {
-			DKLOG(DKS "::serviceStop(" DKS ", " DKS "): could not find service\n", DKN(this), DKN(service), DKN(provider));
-		}
 		return kIOReturnSuccess;
 	}
 
-	(void) service->deRegisterInterestedDriver(this);
-	if (uvars->userServerPM) {
-		IOPMrootDomain * rootDomain = getPMRootDomain();
-		service->PMstop();
-		service->acknowledgeSetPowerState();
-		if (uvars->pmAssertions) {
-			uvars->pmAssertions->iterateObjects(^(OSObject * obj) {
-				rootDomain->releasePMAssertion(((OSNumber *)obj)->unsigned64BitValue());
-				return false;
-			});
-			OSSafeReleaseNULL(uvars->pmAssertions);
-		}
-		if (uvars->pmAssertionsSynced) {
-			uvars->pmAssertionsSynced->iterateObjects(^(OSObject * obj) {
-				rootDomain->releaseDriverKitSyncedAssertion(((OSNumber *)obj)->unsigned64BitValue());
-				return false;
-			});
-			OSSafeReleaseNULL(uvars->pmAssertionsSynced);
-		}
-	}
-	if (kIODKLogSetup & gIODKDebug) {
-		DKLOG(DKS "::serviceStop(" DKS ", " DKS ")\n", DKN(this), DKN(service), DKN(provider));
-	}
-
-	ret = kIOReturnSuccess;
-	return ret;
-}
-
-void
-IOUserServer::serviceFree(IOService * service)
-{
-	OSObjectUserVars * uvars;
-	uint32_t idx, queueAlloc;
-	IODispatchQueue ** unboundedQueueArray = NULL;
-
-	uvars = service->reserved->uvars;
-	if (!uvars) {
-		return;
-	}
+	IOMachPortDestroyUserReferences(service, IKOT_UEXT_OBJECT);
+
 	if (uvars->queueArray && uvars->userMeta) {
 		queueAlloc = 1;
 		if (uvars->userMeta->queueNames) {
@@ -6138,14 +3192,29 @@
 		for (idx = 0; idx < queueAlloc; idx++) {
 			OSSafeReleaseNULL(uvars->queueArray[idx]);
 		}
-		unboundedQueueArray = uvars->queueArray.data();
-		IOSafeDeleteNULL(unboundedQueueArray, IODispatchQueue *, queueAlloc);
-		uvars->queueArray = OSBoundedArrayRef<IODispatchQueue *>();
+		IOSafeDeleteNULL(uvars->queueArray, IODispatchQueue *, queueAlloc);
+	}
+
+	(void) service->deRegisterInterestedDriver(this);
+	if (uvars->userServerPM) {
+		service->PMstop();
+	}
+
+	ret = kIOReturnSuccess;
+	return ret;
+}
+
+void
+IOUserServer::serviceFree(IOService * service)
+{
+	OSObjectUserVars * uvars;
+
+	uvars = service->reserved->uvars;
+	if (!uvars) {
+		return;
 	}
 	OSSafeReleaseNULL(uvars->userServer);
-	IOLockFree(uvars->uvarsLock);
-	OSSafeReleaseNULL(service->reserved->uvars->originalProperties);
-	IOFreeType(service->reserved->uvars, OSObjectUserVars);
+	IOSafeDeleteNULL(service->reserved->uvars, OSObjectUserVars, 1);
 }
 
 void
@@ -6155,36 +3224,19 @@
 	bool     willTerminate;
 
 	willTerminate = false;
-	IOLockLock(client->reserved->uvars->uvarsLock);
-	if (!client->reserved->uvars->serverDied
-	    && !client->reserved->uvars->willTerminate) {
-		client->reserved->uvars->willTerminate = true;
-		willTerminate = true;
-	}
-	IOLockUnlock(client->reserved->uvars->uvarsLock);
-	if (kIODKLogSetup & gIODKDebug) {
-		DKLOG("serviceWillTerminate(" DKS ", " DKS ")\n", DKN(client), DKN(provider));
+	if (client->lockForArbitration(true)) {
+		if (!client->reserved->uvars->serverDied
+		    && !client->reserved->uvars->willTerminate) {
+			client->reserved->uvars->willTerminate = true;
+			willTerminate = true;
+		}
+		client->unlockForArbitration();
 	}
 
 	if (willTerminate) {
-		if (provider->isInactive() || IOServicePH::serverSlept()) {
-			if (kIODKLogIPC & gIODKDebug) {
-				DKLOG(DKS "->Stop_async(" DKS ")\n", DKN(client), DKN(provider));
-			}
-			client->Stop_async(provider);
-			ret = kIOReturnOffline;
-		} else {
-			if (kIODKLogIPC & gIODKDebug) {
-				DKLOG(DKS "->Stop(" DKS ")\n", DKN(client), DKN(provider));
-			}
-			ret = client->Stop(provider);
-			if (kIODKLogIPC & gIODKDebug) {
-				DKLOG(DKS "->Stop(" DKS ") returned %x\n", DKN(client), DKN(provider), ret);
-			}
-		}
+		ret = client->Stop(provider);
 		if (kIOReturnSuccess != ret) {
-			IOUserServer::serviceDidStop(client, provider);
-			ret = kIOReturnSuccess;
+			ret = client->IOService::Stop(provider);
 		}
 	}
 }
@@ -6192,15 +3244,13 @@
 void
 IOUserServer::serviceDidTerminate(IOService * client, IOService * provider, IOOptionBits options, bool * defer)
 {
-	IOLockLock(client->reserved->uvars->uvarsLock);
-	client->reserved->uvars->didTerminate = true;
-	if (!client->reserved->uvars->serverDied
-	    && !client->reserved->uvars->stopped) {
-		*defer = true;
-	}
-	IOLockUnlock(client->reserved->uvars->uvarsLock);
-	if (kIODKLogSetup & gIODKDebug) {
-		DKLOG("serviceDidTerminate(" DKS ", " DKS ") -> defer %d\n", DKN(client), DKN(provider), *defer);
+	if (client->lockForArbitration(true)) {
+		client->reserved->uvars->didTerminate = true;
+		if (!client->reserved->uvars->serverDied
+		    && !client->reserved->uvars->stopped) {
+			*defer = true;
+		}
+		client->unlockForArbitration();
 	}
 }
 
@@ -6213,37 +3263,32 @@
 	complete = false;
 	closeArray = NULL;
 
-	IOLockLock(client->reserved->uvars->uvarsLock);
-	if (client->reserved->uvars
-	    && client->reserved->uvars->willTerminate
-	    && !client->reserved->uvars->stopped) {
-		client->reserved->uvars->stopped = true;
-		complete = client->reserved->uvars->didTerminate;
-	}
-
-	if (client->reserved->uvars) {
-		closeArray = client->reserved->uvars->openProviders;
-		client->reserved->uvars->openProviders = NULL;
-	}
-	IOLockUnlock(client->reserved->uvars->uvarsLock);
-
-	if (kIODKLogSetup & gIODKDebug) {
-		DKLOG("serviceDidStop(" DKS ", " DKS ") -> complete %d\n", DKN(client), DKN(provider), complete);
-	}
-
-	if (closeArray) {
-		closeArray->iterateObjects(^bool (OSObject * obj) {
-			IOService * toClose;
-			toClose = OSDynamicCast(IOService, obj);
-			if (toClose) {
-			        DKLOG(DKS ":force close (" DKS ")\n", DKN(client), DKN(toClose));
-			        toClose->close(client);
-			}
-			return false;
-		});
-		closeArray->release();
-	}
-
+	if (client->lockForArbitration(true)) {
+		if (client->reserved->uvars
+		    && client->reserved->uvars->willTerminate
+		    && !client->reserved->uvars->stopped) {
+			client->reserved->uvars->stopped = true;
+			complete = client->reserved->uvars->didTerminate;
+		}
+
+		if (client->reserved->uvars) {
+			closeArray = client->reserved->uvars->openProviders;
+			client->reserved->uvars->openProviders = NULL;
+		}
+		client->unlockForArbitration();
+		if (closeArray) {
+			closeArray->iterateObjects(^bool (OSObject * obj) {
+				IOService * toClose;
+				toClose = OSDynamicCast(IOService, obj);
+				if (toClose) {
+				        DKLOG(DKS ":force close (" DKS ")\n", DKN(client), DKN(toClose));
+				        toClose->close(client);
+				}
+				return false;
+			});
+			closeArray->release();
+		}
+	}
 	if (complete) {
 		bool defer = false;
 		client->didTerminate(provider, 0, &defer);
@@ -6251,26 +3296,17 @@
 }
 
 kern_return_t
-IOService::ClientCrashed_Impl(
-	IOService * client,
-	uint64_t    options)
+IMPL(IOService, Stop)
+{
+	IOUserServer::serviceDidStop(this, provider);
+
+	return kIOReturnSuccess;
+}
+
+kern_return_t
+IMPL(IOInterruptDispatchSource, Cancel)
 {
 	return kIOReturnUnsupported;
-}
-
-kern_return_t
-IOService::Stop_Impl(
-	IOService * provider)
-{
-	IOUserServer::serviceDidStop(this, provider);
-
-	return kIOReturnSuccess;
-}
-
-void
-IOService::Stop_async_Impl(
-	IOService * provider)
-{
 }
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@@ -6281,40 +3317,6 @@
 OSDefineMetaClassAndStructors(IOUserUserClient, IOUserClient)
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-bool
-IOUserUserClient::init(OSDictionary * properties)
-{
-	if (!super::init(properties)) {
-		return false;
-	}
-
-	fWorkGroups = OSDictionary::withCapacity(0);
-	if (fWorkGroups == NULL) {
-		return false;
-	}
-
-	fEventLinks = OSDictionary::withCapacity(0);
-	if (fEventLinks == NULL) {
-		return false;
-	}
-
-	fLock = IOLockAlloc();
-
-	return true;
-}
-
-void
-IOUserUserClient::free()
-{
-	OSSafeReleaseNULL(fWorkGroups);
-	OSSafeReleaseNULL(fEventLinks);
-	if (fLock) {
-		IOLockFree(fLock);
-	}
-
-	super::free();
-}
 
 IOReturn
 IOUserUserClient::setTask(task_t task)
@@ -6338,7 +3340,7 @@
 IOReturn
 IOUserUserClient::clientClose(void)
 {
-	terminate(kIOServiceTerminateNeedWillTerminate);
+	terminate();
 	return kIOReturnSuccess;
 }
 
@@ -6348,172 +3350,13 @@
 	IOReturn ret = kIOReturnUnsupported;
 	return ret;
 }
-
-// p1 - name of object
-// p2 - length of object name
-// p3 - mach port name
-
-kern_return_t
-IOUserUserClient::eventlinkConfigurationTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6)
-{
-	user_addr_t userObjectName = (user_addr_t)p1;
-	mach_port_name_t portName = (mach_port_name_t)(uintptr_t)p3;
-	mach_port_t port = MACH_PORT_NULL;
-	char eventlinkName[kIOEventLinkMaxNameLength + 1] = {0};
-	size_t eventLinkNameLen;
-	OSString * eventlinkNameStr = NULL; // must release
-	IOEventLink * eventLink = NULL; // do not release
-	kern_return_t ret;
-
-	ret = copyinstr(userObjectName, &eventlinkName[0], sizeof(eventlinkName), &eventLinkNameLen);
-	if (ret != kIOReturnSuccess) {
-		goto finish;
-	}
-
-	// ensure string length matches trap argument
-	if (eventLinkNameLen != (size_t)p2 + 1) {
-		ret = kIOReturnBadArgument;
-		goto finish;
-	}
-
-	eventlinkNameStr = OSString::withCStringNoCopy(eventlinkName);
-	if (eventlinkNameStr == NULL) {
-		ret = kIOReturnNoMemory;
-		goto finish;
-	}
-
-	IOLockLock(fLock);
-	eventLink = OSDynamicCast(IOEventLink, fEventLinks->getObject(eventlinkNameStr));
-	if (eventLink) {
-		eventLink->retain();
-	}
-	IOLockUnlock(fLock);
-
-	if (eventLink == NULL) {
-		ret = kIOReturnNotFound;
-		goto finish;
-	}
-
-	ret = iokit_lookup_raw_current_task(portName, IKOT_EVENTLINK, &port);
-	if (ret != kIOReturnSuccess) {
-		goto finish;
-	}
-
-	ret = eventLink->SetEventlinkPort(port);
-	if (ret != kIOReturnSuccess) {
-		if (kIODKLogSetup & gIODKDebug) {
-			DKLOG(DKS " %s SetEventlinkPort() returned %x\n", DKN(this), eventlinkNameStr->getCStringNoCopy(), ret);
-		}
-		goto finish;
-	}
-
-finish:
-	if (port != NULL) {
-		iokit_release_port_send(port);
-	}
-
-	OSSafeReleaseNULL(eventlinkNameStr);
-	OSSafeReleaseNULL(eventLink);
-
-	return ret;
-}
-
-kern_return_t
-IOUserUserClient::workgroupConfigurationTrap(void * p1, void * p2, void * p3, void * p4, void * p5, void * p6)
-{
-	user_addr_t userObjectName = (user_addr_t)p1;
-	mach_port_name_t portName = (mach_port_name_t)(uintptr_t)p3;
-	mach_port_t port = MACH_PORT_NULL;
-	char workgroupName[kIOWorkGroupMaxNameLength + 1] = {0};
-	size_t workgroupNameLen;
-	OSString * workgroupNameStr = NULL; // must release
-	IOWorkGroup * workgroup = NULL; // do not release
-	kern_return_t ret;
-
-	ret = copyinstr(userObjectName, &workgroupName[0], sizeof(workgroupName), &workgroupNameLen);
-	if (ret != kIOReturnSuccess) {
-		goto finish;
-	}
-
-	// ensure string length matches trap argument
-	if (workgroupNameLen != (size_t)p2 + 1) {
-		ret = kIOReturnBadArgument;
-		goto finish;
-	}
-
-	workgroupNameStr = OSString::withCStringNoCopy(workgroupName);
-	if (workgroupNameStr == NULL) {
-		ret = kIOReturnNoMemory;
-		goto finish;
-	}
-
-	IOLockLock(fLock);
-	workgroup = OSDynamicCast(IOWorkGroup, fWorkGroups->getObject(workgroupNameStr));
-	if (workgroup) {
-		workgroup->retain();
-	}
-	IOLockUnlock(fLock);
-
-	if (workgroup == NULL) {
-		ret = kIOReturnNotFound;
-		goto finish;
-	}
-
-	ret = iokit_lookup_raw_current_task(portName, IKOT_WORK_INTERVAL, &port);
-	if (ret != kIOReturnSuccess) {
-		goto finish;
-	}
-
-	ret = workgroup->SetWorkGroupPort(port);
-	if (ret != kIOReturnSuccess) {
-		if (kIODKLogSetup & gIODKDebug) {
-			DKLOG(DKS " %s SetWorkGroupPort() returned %x\n", DKN(this), workgroupNameStr->getCStringNoCopy(), ret);
-		}
-		goto finish;
-	}
-
-finish:
-
-	if (port != NULL) {
-		iokit_release_port_send(port);
-	}
-
-	OSSafeReleaseNULL(workgroupNameStr);
-	OSSafeReleaseNULL(workgroup);
-
-	return ret;
-}
-
-IOExternalTrap *
-IOUserUserClient::getTargetAndTrapForIndex( IOService **targetP, UInt32 index )
-{
-	static const OSBoundedArray<IOExternalTrap, 2> trapTemplate = {{
-									       { NULL, (IOTrap) & IOUserUserClient::eventlinkConfigurationTrap},
-									       { NULL, (IOTrap) & IOUserUserClient::workgroupConfigurationTrap},
-								       }};
-	if (index >= trapTemplate.size()) {
-		return NULL;
-	}
-	*targetP = this;
-	return (IOExternalTrap *)&trapTemplate[index];
-}
-
-kern_return_t
-IOUserClient::CopyClientEntitlements_Impl(OSDictionary ** entitlements)
-{
-	return kIOReturnUnsupported;
-};
 
 struct IOUserUserClientActionRef {
 	OSAsyncReference64 asyncRef;
 };
 
 void
-IOUserClient::KernelCompletion_Impl(
-	OSAction * action,
-	IOReturn status,
-	const unsigned long long * asyncData,
-	uint32_t asyncDataCount)
+IMPL(IOUserClient, KernelCompletion)
 {
 	IOUserUserClientActionRef * ref;
 
@@ -6523,18 +3366,7 @@
 }
 
 kern_return_t
-IOUserClient::_ExternalMethod_Impl(
-	uint64_t selector,
-	const unsigned long long * scalarInput,
-	uint32_t scalarInputCount,
-	OSData * structureInput,
-	IOMemoryDescriptor * structureInputDescriptor,
-	unsigned long long * scalarOutput,
-	uint32_t * scalarOutputCount,
-	uint64_t structureOutputMaximumSize,
-	OSData ** structureOutput,
-	IOMemoryDescriptor * structureOutputDescriptor,
-	OSAction * completion)
+IMPL(IOUserClient, _ExternalMethod)
 {
 	return kIOReturnUnsupported;
 }
@@ -6575,34 +3407,20 @@
 	uint64_t   structureOutputSize;
 	OSAction                  * action;
 	IOUserUserClientActionRef * ref;
-	mach_port_t wake_port = MACH_PORT_NULL;
 
 	kr             = kIOReturnUnsupported;
 	structureInput = NULL;
 	action         = NULL;
-	ref            = NULL;
 
 	if (args->structureInputSize) {
 		structureInput = OSData::withBytesNoCopy((void *) args->structureInput, args->structureInputSize);
 	}
 
 	if (MACH_PORT_NULL != args->asyncWakePort) {
-		// this retain is for the OSAction to release
-		wake_port = ipc_port_make_send_mqueue(args->asyncWakePort);
 		kr = CreateActionKernelCompletion(sizeof(IOUserUserClientActionRef), &action);
 		assert(KERN_SUCCESS == kr);
 		ref = (typeof(ref))action->GetReference();
 		bcopy(args->asyncReference, &ref->asyncRef[0], args->asyncReferenceCount * sizeof(ref->asyncRef[0]));
-		kr = action->SetAbortedHandler(^(void) {
-			IOUserUserClientActionRef * ref;
-			IOReturn ret;
-
-			ref = (typeof(ref))action->GetReference();
-			ret = releaseAsyncReference64(ref->asyncRef);
-			assert(kIOReturnSuccess == ret);
-			bzero(&ref->asyncRef[0], sizeof(ref->asyncRef));
-		});
-		assert(KERN_SUCCESS == kr);
 	}
 
 	if (args->structureVariableOutputData) {
@@ -6622,7 +3440,10 @@
 	OSSafeReleaseNULL(structureInput);
 	OSSafeReleaseNULL(action);
 
-	if (kr == kIOReturnSuccess && structureOutput) {
+	if (kIOReturnSuccess != kr) {
+		return kr;
+	}
+	if (structureOutput) {
 		if (args->structureVariableOutputData) {
 			*args->structureVariableOutputData = structureOutput;
 		} else {
@@ -6631,1418 +3452,12 @@
 				kr = kIOReturnBadArgument;
 			} else {
 				bcopy((const void *) structureOutput->getBytesNoCopy(), args->structureOutput, copylen);
-				args->structureOutputSize = (uint32_t) copylen;
 			}
 			OSSafeReleaseNULL(structureOutput);
 		}
 	}
 
-	if (kIOReturnSuccess != kr) {
-		// mig will destroy any async port
-		return kr;
-	}
-
-	// We must never return error after this point in order to preserve MIG ownership semantics
-	assert(kr == kIOReturnSuccess);
-	if (MACH_PORT_NULL != wake_port) {
-		// this release is for the mig created send right
-		iokit_release_port_send(wake_port);
-	}
-
 	return kr;
 }
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-/*
- * IOUserServerCheckInToken state machine
- *
- *         token
- *        creation
- *            |
- *            |
- *            v            dext
- *      +-----------+    check-in    +-----------+
- *      |  Pending  +--------------->| Complete  |
- *      +-----+-----+                +-----+-----+
- *            |                            |
- * dext crash |                            |  dext crash
- *   before   |                            | before server
- *  check-in  |                            | registration
- *            |      +-----------+         |
- *            +----->| Canceled  |<--------+
- *                   +-----------+
- */
-
-extern IORecursiveLock               * gDriverKitLaunchLock;
-extern OSSet                         * gDriverKitLaunches;
-
-_IOUserServerCheckInCancellationHandler *
-IOUserServerCheckInToken::setCancellationHandler(IOUserServerCheckInCancellationHandler handler,
-    void* handlerArgs)
-{
-	_IOUserServerCheckInCancellationHandler * handlerObj = _IOUserServerCheckInCancellationHandler::withHandler(handler, handlerArgs);
-	if (!handlerObj) {
-		goto finish;
-	}
-
-	IORecursiveLockLock(gDriverKitLaunchLock);
-
-	if (fState == kIOUserServerCheckInCanceled) {
-		// Send cancel notification if we set the handler after this was canceled
-		handlerObj->call(this);
-	} else if (fState == kIOUserServerCheckInPending) {
-		fHandlers->setObject(handlerObj);
-	}
-
-	IORecursiveLockUnlock(gDriverKitLaunchLock);
-
-finish:
-	return handlerObj;
-}
-
-void
-IOUserServerCheckInToken::removeCancellationHandler(_IOUserServerCheckInCancellationHandler * handler)
-{
-	IORecursiveLockLock(gDriverKitLaunchLock);
-
-	fHandlers->removeObject(handler);
-
-	IORecursiveLockUnlock(gDriverKitLaunchLock);
-}
-
-void
-IOUserServerCheckInToken::cancel()
-{
-	IORecursiveLockLock(gDriverKitLaunchLock);
-
-	if (fState != kIOUserServerCheckInCanceled) {
-		// Move the state to canceled even if the token has completed
-		// This is to cover the gap between dext check-in and the registration of user server
-		// Cancellation listeners must be informed of a crash in between
-		fState = kIOUserServerCheckInCanceled;
-
-		if (gDriverKitLaunches != NULL) {
-			// Remove pending launch from list, if we have not shut down yet.
-			gDriverKitLaunches->removeObject(this);
-		}
-
-		fHandlers->iterateObjects(^bool (OSObject * obj){
-			_IOUserServerCheckInCancellationHandler * handlerObj = OSDynamicCast(_IOUserServerCheckInCancellationHandler, obj);
-			if (handlerObj) {
-			        handlerObj->call(this);
-			}
-			return false;
-		});
-		fHandlers->flushCollection();
-	}
-
-	IORecursiveLockUnlock(gDriverKitLaunchLock);
-}
-
-IOReturn
-IOUserServerCheckInToken::complete()
-{
-	IOReturn ret;
-	IORecursiveLockLock(gDriverKitLaunchLock);
-
-	if (fState == kIOUserServerCheckInCanceled) {
-		ret = kIOReturnError;
-	} else {
-		ret = kIOReturnSuccess;
-	}
-
-	if (fState == kIOUserServerCheckInPending) {
-		fState = kIOUserServerCheckInComplete;
-		if (gDriverKitLaunches != NULL) {
-			// Remove pending launch from list, if we have not shut down yet.
-			gDriverKitLaunches->removeObject(this);
-		}
-
-		// Do not flush the cancellation handlers, as we might still trigger them
-	}
-
-	IORecursiveLockUnlock(gDriverKitLaunchLock);
-	return ret;
-}
-
-bool
-IOUserServerCheckInToken::init(const OSSymbol * serverName, OSNumber * serverTag, OSKext *driverKext, OSData *serverDUI)
-{
-	if (!OSObject::init()) {
-		return false;
-	}
-
-	if (!serverName) {
-		return false;
-	}
-	fServerName = serverName;
-	fServerName->retain();
-
-	if (!serverTag) {
-		return false;
-	}
-	fServerTag = serverTag;
-	fServerTag->retain();
-
-	fHandlers = OSSet::withCapacity(0);
-	if (!fHandlers) {
-		return false;
-	}
-
-	fState = kIOUserServerCheckInPending;
-
-	fKextBundleID = NULL;
-	fNeedDextDec = false;
-
-	fExecutableName = NULL;
-
-	if (driverKext) {
-		fExecutableName = OSDynamicCast(OSSymbol, driverKext->getBundleExecutable());
-
-		if (fExecutableName) {
-			fExecutableName->retain();
-		}
-
-		/*
-		 * We need to keep track of how many dexts we have started.
-		 * For every new dext we are going to create a new token, and
-		 * we consider the token creation as the initial step to
-		 * create a dext as it is the data structure that will back up
-		 * the userspace dance to start a dext.
-		 * We later have to decrement only once per token.
-		 * If no error occurs we consider the finalize() call on IOUserServer
-		 * as the moment in which we do not consider the dext "alive" anymore;
-		 * however in case of errors we will still need to decrement the count
-		 * otherwise upgrades of the dext will never make progress.
-		 */
-		if (OSKext::incrementDextLaunchCount(driverKext, serverDUI)) {
-			/*
-			 * If fKext holds a pointer,
-			 * it is the indication that a decrements needs
-			 * to be called.
-			 */
-			fNeedDextDec = true;
-			fKextBundleID = OSDynamicCast(OSString, driverKext->getIdentifier());
-			fKextBundleID->retain();
-		} else {
-			return false;
-		}
-	}
-
-	return true;
-}
-
-/*
- * Returns if the dext can be re-used
- * for matching.
- */
-bool
-IOUserServerCheckInToken::dextTerminate(void)
-{
-	bool ret = true;
-
-	if (fNeedDextDec == true) {
-		/*
-		 * We can decrement DextLaunchCount only
-		 * once per token.
-		 */
-		ret = !(OSKext::decrementDextLaunchCount(fKextBundleID));
-		fNeedDextDec = false;
-	}
-
-	return ret;
-}
-
-void
-IOUserServerCheckInToken::free()
-{
-	OSSafeReleaseNULL(fServerName);
-	OSSafeReleaseNULL(fServerTag);
-	OSSafeReleaseNULL(fExecutableName);
-	OSSafeReleaseNULL(fHandlers);
-	if (fKextBundleID != NULL) {
-		dextTerminate();
-		OSSafeReleaseNULL(fKextBundleID);
-	}
-
-	OSObject::free();
-}
-
-const OSSymbol *
-IOUserServerCheckInToken::copyServerName() const
-{
-	fServerName->retain();
-	return fServerName;
-}
-
-OSNumber *
-IOUserServerCheckInToken::copyServerTag() const
-{
-	fServerTag->retain();
-	return fServerTag;
-}
-
-/*
- * Wait for a IOUserServer to check in
- */
-
-static
-__attribute__((noinline, not_tail_called))
-IOUserServer *
-__WAITING_FOR_USER_SERVER__(IOUserServerCheckInToken * token, uint64_t * timeoutMS)
-{
-	IOUserServer * result = NULL;
-	IOService * server = NULL;
-	const OSSymbol * serverName = token->copyServerName();
-	OSNumber       * serverTag = token->copyServerTag();
-	OSDictionary   * matching = IOService::serviceMatching(gIOUserServerClassKey);
-	uint64_t         startTime = 0, endTime = 0;
-
-	if (!matching || !serverName || !serverTag) {
-		goto finish;
-	}
-	IOService::propertyMatching(gIOUserServerNameKey, serverName, matching);
-	if (!(kIODKDisableDextTag & gIODKDebug)) {
-		IOService::propertyMatching(gIOUserServerTagKey, serverTag, matching);
-	}
-
-	absolutetime_to_nanoseconds(mach_absolute_time(), &startTime);
-	startTime /= NSEC_PER_MSEC;
-	server = IOService::waitForMatchingServiceWithToken(matching, (*timeoutMS) * NSEC_PER_MSEC, token);
-	result = OSDynamicCast(IOUserServer, server);
-	if (!result) {
-		// Calculate the remaining timeout if the server isn't registered
-		OSSafeReleaseNULL(server);
-		token->cancel();
-		absolutetime_to_nanoseconds(mach_absolute_time(), &endTime);
-		endTime /= NSEC_PER_MSEC;
-		if (endTime > startTime) {
-			if (os_sub_overflow(*timeoutMS, endTime - startTime, timeoutMS)) {
-				*timeoutMS = 0;
-			}
-		}
-	}
-
-finish:
-	OSSafeReleaseNULL(matching);
-	OSSafeReleaseNULL(serverName);
-	OSSafeReleaseNULL(serverTag);
-
-	return result;
-}
-
-IOUserServer *
-IOUserServer::launchUserServer(IOService * provider, IOService * service, OSString * bundleID, const OSSymbol * serverName, OSNumber * serverTag, bool reuseIfExists, OSData *serverDUI)
-{
-	IOUserServer *me = NULL, *providerServer = NULL;
-	IOUserServerCheckInToken * token = NULL;
-	OSDictionary * matching = NULL;  // must release
-	OSKext * driverKext = NULL; // must release
-	OSDextStatistics * driverStatistics = NULL; // must release
-	bool reslide = false;
-	uint32_t retries = kIOUserServerCheckInMaxRetry;
-	uint64_t timeRemainingMS = kIOUserServerCheckInTimeoutMSecs;
-
-	/* TODO: Check we are looking for same dextID
-	 * and if it is not the same
-	 * restart the matching process.
-	 */
-	driverKext = OSKext::lookupDextWithIdentifier(bundleID, serverDUI);
-	if (driverKext != NULL) {
-		driverStatistics = driverKext->copyDextStatistics();
-		if (driverStatistics == NULL) {
-			panic("Kext %s was not a DriverKit OSKext", bundleID->getCStringNoCopy());
-		}
-		IOLog("Driver %s has crashed %zu time(s)\n", bundleID->getCStringNoCopy(), driverStatistics->getCrashCount());
-		reslide = driverStatistics->getCrashCount() > 0;
-	} else {
-		DKLOG("Could not find OSKext for %s\n", bundleID->getCStringNoCopy());
-		return NULL;
-	}
-
-	if (reuseIfExists) {
-		const char * serverNameCStr;
-		const char * bundleIDCStr;
-		const char * endOrgCStr;
-
-		serverNameCStr = serverName->getCStringNoCopy();
-		bundleIDCStr = bundleID->getCStringNoCopy();
-		(endOrgCStr = strchr(bundleIDCStr, '.')) && (endOrgCStr = strchr(endOrgCStr + 1, '.'));
-		reuseIfExists = endOrgCStr && (0 == strncmp(bundleIDCStr, serverNameCStr, endOrgCStr + 1 - bundleIDCStr));
-		if (!reuseIfExists) {
-			IOLog(kIOUserServerNameKey " \"%s\" not correct organization for bundleID \"%s\"\n", serverNameCStr, bundleIDCStr);
-		}
-	}
-
-	if (reuseIfExists) {
-		// Check provider's user server, if exists
-		if (provider->reserved && provider->reserved->uvars && (providerServer = provider->reserved->uvars->userServer) != NULL) {
-			OSString * providerServerName = OSDynamicCast(OSString, providerServer->getProperty(gIOUserServerNameKey));
-			if (providerServerName && providerServerName->isEqualTo(serverName)) {
-				// Reuse is required
-
-				DKLOG("using existing server " DKS " from provider " DKS "\n", DKN(providerServer), DKN(provider));
-
-				// If provider has the user server that we are supposed to reuse, and it has become inactive
-				// start of this service should simply fail
-				// If the user server become inactive after this check, start should fail at a later stage
-				if (!providerServer->isInactive()) {
-					providerServer->retain();
-					me = providerServer;
-				} else {
-					DKLOG(DKS " cannot reuse inactive server\n", DKN(service));
-					// Must not create a token as reuse is required
-				}
-				goto finish;
-			}
-		}
-	}
-
-	do {
-		const OSSymbol * tokenServerName;
-		OSNumber * tokenServerTag;
-
-		IORecursiveLockLock(gDriverKitLaunchLock);
-
-		if (gDriverKitLaunches == NULL) {
-			// About to shut down, don't launch anything
-			IORecursiveLockUnlock(gDriverKitLaunchLock);
-			goto finish;
-		}
-
-		// Find existing server
-		if (reuseIfExists) {
-			token = IOUserServerCheckInToken::findExistingToken(serverName);
-			if (!token) {
-				// Check if launch completed
-
-				matching = IOService::serviceMatching(gIOUserServerClassKey);
-				if (!matching) {
-					IORecursiveLockUnlock(gDriverKitLaunchLock);
-					goto finish;
-				}
-				IOService::propertyMatching(gIOUserServerNameKey, serverName, matching);
-				IOService * service = IOService::copyMatchingService(matching);
-				IOUserServer * userServer = OSDynamicCast(IOUserServer, service);
-				if (userServer) {
-					// found existing user server
-					me = userServer;
-					IORecursiveLockUnlock(gDriverKitLaunchLock);
-					goto finish;
-				} else {
-					OSSafeReleaseNULL(service);
-				}
-			}
-		}
-
-		if (!token) {
-			// No existing server, request launch
-			token = new IOUserServerCheckInToken;
-			if (!token) {
-				IORecursiveLockUnlock(gDriverKitLaunchLock);
-				goto finish;
-			}
-
-			/*
-			 * TODO: If the init fails because the personalities are not up to date
-			 * restart the whole matching process.
-			 */
-			if (token && !token->init(serverName, serverTag, driverKext, serverDUI)) {
-				DKLOG(DKS " could not initialize token\n", DKN(service));
-				IORecursiveLockUnlock(gDriverKitLaunchLock);
-				OSSafeReleaseNULL(token);
-				goto finish;
-			}
-
-			/*
-			 * If the launch fails at any point terminate() will
-			 * be called on this IOUserServer.
-			 */
-			gDriverKitLaunches->setObject(token);
-			OSKext::requestDaemonLaunch(bundleID, (OSString *)serverName, serverTag, reslide ? kOSBooleanTrue : kOSBooleanFalse, token, serverDUI);
-		}
-
-		IORecursiveLockUnlock(gDriverKitLaunchLock);
-
-		tokenServerName = token->copyServerName();
-		tokenServerTag = token->copyServerTag();
-		assert(tokenServerName && tokenServerTag);
-		DKLOG(DKS " waiting for server %s-%llx\n", DKN(service), tokenServerName->getCStringNoCopy(), tokenServerTag->unsigned64BitValue());
-
-		me = __WAITING_FOR_USER_SERVER__(token, &timeRemainingMS);
-		if (me) {
-			OSSafeReleaseNULL(tokenServerName);
-			OSSafeReleaseNULL(tokenServerTag);
-			break;
-		}
-		DKLOG(DKS " failed to find server %s-%llx, remaining %llums, retries %u\n", DKN(service),
-		    tokenServerName->getCStringNoCopy(), tokenServerTag->unsigned64BitValue(), timeRemainingMS, retries - 1);
-		OSSafeReleaseNULL(tokenServerName);
-		OSSafeReleaseNULL(tokenServerTag);
-		OSSafeReleaseNULL(token);
-		// If the loop continues it means the dext has been killed
-		// We don't record a crash since start never happened. No client code has run
-	} while (--retries && timeRemainingMS && !gInUserspaceReboot);
-
-	if (me) {
-		DKLOG(DKS " server launched, validating\n", DKN(service));
-		if (token && !(kIODKDisableCheckInTokenVerification & gIODKDebug)) {
-			if (!me->serviceMatchesCheckInToken(token)) {
-				DKLOG(DKS " server does not match token\n", DKN(service));
-				me->exit("Check In Token verification failed");
-				OSSafeReleaseNULL(me);
-			}
-		}
-	} else {
-#if DEVELOPMENT || DEBUG
-		driverkit_checkin_timed_out = mach_absolute_time();
-#endif
-	}
-
-finish:
-	OSSafeReleaseNULL(matching);
-	OSSafeReleaseNULL(driverStatistics);
-	OSSafeReleaseNULL(driverKext);
-	OSSafeReleaseNULL(token);
-
-	return me;
-}
-
-/*
- * IOUserServerCheckInTokens are used to track dext launches. They have three possible states:
- *
- * - Pending: A dext launch is pending
- * - Canceled: Dext launch failed
- * - Complete: Dext launch is complete
- *
- * A token can be shared among multiple IOServices that are waiting for dexts if the IOUserServerName
- * is the same. This allows dexts to be reused and host multiple services. All pending tokens are stored
- * in gDriverKitLaunches and we check here before creating a new token when launching a dext.
- *
- * A token starts in the pending state with a pending count of 1. When we reuse a token, we increase the
- * pending count of the token.
- *
- * The token is sent to userspace as a mach port through kernelmanagerd/driverkitd to the dext. The dext then
- * uses that token to check in to the kernel. If any part of the dext launch failed (dext crashed, kmd crashed, etc.)
- * we get a no-senders notification for the token in the kernel and the token goes into the Canceled state.
- *
- * Once the dext checks in to the kernel, we decrement the pending count for the token. When the pending count reaches
- * 0, the token goes into the Complete state. So if the token is in the Complete state, there are no kernel matching threads
- * waiting on the dext to check in.
- */
-
-IOUserServerCheckInToken *
-IOUserServerCheckInToken::findExistingToken(const OSSymbol * serverName)
-{
-	IOUserServerCheckInToken * __block result = NULL;
-
-	IORecursiveLockLock(gDriverKitLaunchLock);
-	if (gDriverKitLaunches == NULL) {
-		goto finish;
-	}
-
-	gDriverKitLaunches->iterateObjects(^(OSObject * obj) {
-		IOUserServerCheckInToken * token = OSDynamicCast(IOUserServerCheckInToken, obj);
-		if (token) {
-		        // Check if server name matches
-		        const OSSymbol * tokenServerName = token->fServerName;
-		        if (tokenServerName->isEqualTo(serverName)) {
-		                assert(token->fState == kIOUserServerCheckInPending);
-		                result = token;
-		                result->retain();
-			}
-		}
-		return result != NULL;
-	});
-
-finish:
-	IORecursiveLockUnlock(gDriverKitLaunchLock);
-	return result;
-}
-
-void
-IOUserServerCheckInToken::cancelAll()
-{
-	OSSet * tokensToCancel;
-
-	IORecursiveLockLock(gDriverKitLaunchLock);
-	tokensToCancel = gDriverKitLaunches;
-	gDriverKitLaunches = NULL;
-
-
-	tokensToCancel->iterateObjects(^(OSObject *obj) {
-		IOUserServerCheckInToken * token = OSDynamicCast(IOUserServerCheckInToken, obj);
-		if (token) {
-		        token->cancel();
-		}
-		return false;
-	});
-
-	IORecursiveLockUnlock(gDriverKitLaunchLock);
-
-	OSSafeReleaseNULL(tokensToCancel);
-}
-
-void
-_IOUserServerCheckInCancellationHandler::call(IOUserServerCheckInToken * token)
-{
-	fHandler(token, fHandlerArgs);
-}
-
-_IOUserServerCheckInCancellationHandler *
-_IOUserServerCheckInCancellationHandler::withHandler(IOUserServerCheckInCancellationHandler handler, void * args)
-{
-	_IOUserServerCheckInCancellationHandler * handlerObj = NULL;
-	if (!handler) {
-		goto finish;
-	}
-
-	handlerObj = new _IOUserServerCheckInCancellationHandler;
-	if (!handlerObj) {
-		goto finish;
-	}
-
-	handlerObj->fHandler = handler;
-	handlerObj->fHandlerArgs = args;
-
-finish:
-	return handlerObj;
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-struct IOServiceStateNotificationDispatchSource_IVars {
-	IOLock                       * fLock;
-	IOService                    * fStateNotification;
-	IOStateNotificationListenerRef fListener;
-	OSAction                     * fAction;
-	bool                           fEnable;
-	bool                           fArmed;
-};
-
-kern_return_t
-IOServiceStateNotificationDispatchSource::Create_Impl(IOService * service, OSArray * items,
-    IODispatchQueue * queue, IOServiceStateNotificationDispatchSource ** outSource)
-{
-	kern_return_t kr;
-	IOServiceStateNotificationDispatchSource * source;
-
-	source = OSTypeAlloc(IOServiceStateNotificationDispatchSource);
-	source->init();
-
-	source->ivars->fStateNotification = service;
-	kr = service->stateNotificationListenerAdd(items, &source->ivars->fListener, ^kern_return_t () {
-		OSAction * action;
-
-		action = NULL;
-		IOLockLock(source->ivars->fLock);
-		if (source->ivars->fArmed && source->ivars->fAction) {
-		        source->ivars->fArmed = false;
-		        action = source->ivars->fAction;
-		        action->retain();
-		}
-		IOLockUnlock(source->ivars->fLock);
-		if (action) {
-		        source->StateNotificationReady(action);
-		        OSSafeReleaseNULL(action);
-		}
-		return kIOReturnSuccess;
-	});
-
-	if (kIOReturnSuccess != kr) {
-		OSSafeReleaseNULL(source);
-	}
-	*outSource = source;
-
-	return kr;
-}
-
-
-bool
-IOServiceStateNotificationDispatchSource::init()
-{
-	if (!IODispatchSource::init()) {
-		return false;
-	}
-	ivars = IOMallocType(IOServiceStateNotificationDispatchSource_IVars);
-	if (!ivars) {
-		return false;
-	}
-	ivars->fLock = IOLockAlloc();
-	if (!ivars->fLock) {
-		return false;
-	}
-	ivars->fArmed = true;
-
-	return true;
-}
-
-void
-IOServiceStateNotificationDispatchSource::free()
-{
-	if (ivars) {
-		if (ivars->fListener) {
-			ivars->fStateNotification->stateNotificationListenerRemove(ivars->fListener);
-		}
-		if (ivars->fLock) {
-			IOLockFree(ivars->fLock);
-		}
-		IOFreeType(ivars, IOServiceStateNotificationDispatchSource_IVars);
-	}
-	IODispatchSource::free();
-}
-
-kern_return_t
-IOServiceStateNotificationDispatchSource::SetHandler_Impl(OSAction * action)
-{
-	IOReturn ret;
-	bool     notifyReady;
-
-	notifyReady = false;
-
-	IOLockLock(ivars->fLock);
-	action->retain();
-	OSSafeReleaseNULL(ivars->fAction);
-	ivars->fAction = action;
-	if (action) {
-		notifyReady = true;
-	}
-	IOLockUnlock(ivars->fLock);
-
-	if (notifyReady) {
-		StateNotificationReady(action);
-	}
-	ret = kIOReturnSuccess;
-
-	return ret;
-}
-
-kern_return_t
-IOServiceStateNotificationDispatchSource::SetEnableWithCompletion_Impl(
-	bool enable,
-	IODispatchSourceCancelHandler handler)
-{
-	if (enable == ivars->fEnable) {
-		return kIOReturnSuccess;
-	}
-
-	IOLockLock(ivars->fLock);
-	ivars->fEnable = enable;
-	IOLockUnlock(ivars->fLock);
-
-	return kIOReturnSuccess;
-}
-
-kern_return_t
-IOServiceStateNotificationDispatchSource::Cancel_Impl(
-	IODispatchSourceCancelHandler handler)
-{
-	return kIOReturnUnsupported;
-}
-
-kern_return_t
-IOServiceStateNotificationDispatchSource::StateNotificationBegin_Impl(void)
-{
-	IOLockLock(ivars->fLock);
-	ivars->fArmed = true;
-	IOLockUnlock(ivars->fLock);
-
-	return kIOReturnSuccess;
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-#include <IOKit/IOServiceStateNotificationEventSource.h>
-
-OSDefineMetaClassAndStructors(IOServiceStateNotificationEventSource, IOEventSource)
-OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 0);
-OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 1);
-OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 2);
-OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 3);
-OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 4);
-OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 5);
-OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 6);
-OSMetaClassDefineReservedUnused(IOServiceStateNotificationEventSource, 7);
-
-OSPtr<IOServiceStateNotificationEventSource>
-IOServiceStateNotificationEventSource::serviceStateNotificationEventSource(IOService *service,
-    OSArray * items,
-    ActionBlock inAction)
-{
-	kern_return_t kr;
-	IOServiceStateNotificationEventSource * source;
-
-	source = OSTypeAlloc(IOServiceStateNotificationEventSource);
-	if (source && !source->init(service, NULL)) {
-		OSSafeReleaseNULL(source);
-	}
-
-	if (!source) {
-		return nullptr;
-	}
-
-	source->fStateNotification = service;
-	kr = service->stateNotificationListenerAdd(items, &source->fListener, ^kern_return_t () {
-		if (!source->workLoop) {
-		        return kIOReturnSuccess;
-		}
-		source->workLoop->runActionBlock(^IOReturn (void) {
-			source->fArmed = true;
-			return kIOReturnSuccess;
-		});
-		source->signalWorkAvailable();
-		return kIOReturnSuccess;
-	});
-
-	if (kIOReturnSuccess != kr) {
-		OSSafeReleaseNULL(source);
-	}
-
-	if (source) {
-		source->setActionBlock((IOEventSource::ActionBlock) inAction);
-	}
-
-	return source;
-}
-
-void
-IOServiceStateNotificationEventSource::free()
-{
-	if (fListener) {
-		fStateNotification->stateNotificationListenerRemove(fListener);
-	}
-	IOEventSource::free();
-}
-
-void
-IOServiceStateNotificationEventSource::enable()
-{
-	fEnable = true;
-}
-
-void
-IOServiceStateNotificationEventSource::disable()
-{
-	fEnable = false;
-}
-
-void
-IOServiceStateNotificationEventSource::setWorkLoop(IOWorkLoop *inWorkLoop)
-{
-	IOEventSource::setWorkLoop(inWorkLoop);
-}
-
-bool
-IOServiceStateNotificationEventSource::checkForWork()
-{
-	ActionBlock intActionBlock = (ActionBlock) actionBlock;
-
-	if (fArmed) {
-		fArmed = false;
-		(intActionBlock)();
-	}
-
-	return false;
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-OSDefineMetaClassAndStructors(IOSystemStateNotification, IOService);
-
-class IOStateNotificationItem : public OSObject
-{
-	OSDeclareDefaultStructors(IOStateNotificationItem);
-
-public:
-	virtual bool init() override;
-
-	OSDictionary * fValue;
-	OSSet        * fListeners;
-};
-OSDefineMetaClassAndStructors(IOStateNotificationItem, OSObject);
-
-
-class IOStateNotificationListener : public OSObject
-{
-	OSDeclareDefaultStructors(IOStateNotificationListener);
-
-public:
-	virtual bool init() override;
-	virtual void free() override;
-
-	IOStateNotificationHandler fHandler;
-};
-OSDefineMetaClassAndStructors(IOStateNotificationListener, OSObject);
-
-
-bool
-IOStateNotificationItem::init()
-{
-	return OSObject::init();
-}
-
-bool
-IOStateNotificationListener::init()
-{
-	return OSObject::init();
-}
-
-void
-IOStateNotificationListener::free()
-{
-	if (fHandler) {
-		Block_release(fHandler);
-	}
-	OSObject::free();
-}
-
-
-struct IOServiceStateChangeVars {
-	IOLock       * fLock;
-	OSDictionary * fItems;
-};
-
-IOService *
-IOSystemStateNotification::initialize(void)
-{
-	IOSystemStateNotification * me;
-	IOServiceStateChangeVars  * vars;
-
-	me = OSTypeAlloc(IOSystemStateNotification);
-	me->init();
-	vars = IOMallocType(IOServiceStateChangeVars);
-	me->reserved->svars = vars;
-	vars->fLock  = IOLockAlloc();
-	vars->fItems = OSDictionary::withCapacity(16);
-	{
-		kern_return_t ret;
-
-		gIOSystemStateSleepDescriptionKey = (OSString *)OSSymbol::withCStringNoCopy(kIOSystemStateSleepDescriptionKey);
-		gIOSystemStateSleepDescriptionHibernateStateKey = OSSymbol::withCStringNoCopy(kIOSystemStateSleepDescriptionHibernateStateKey);
-		gIOSystemStateSleepDescriptionReasonKey = OSSymbol::withCStringNoCopy(kIOSystemStateSleepDescriptionReasonKey);
-
-		ret = me->StateNotificationItemCreate(gIOSystemStateSleepDescriptionKey, NULL);
-		assert(kIOReturnSuccess == ret);
-
-		gIOSystemStateWakeDescriptionKey = (OSString *)OSSymbol::withCStringNoCopy(kIOSystemStateWakeDescriptionKey);
-		gIOSystemStateWakeDescriptionWakeReasonKey = OSSymbol::withCStringNoCopy(kIOSystemStateWakeDescriptionWakeReasonKey);
-		gIOSystemStateWakeDescriptionContinuousTimeOffsetKey = OSSymbol::withCStringNoCopy(kIOSystemStateWakeDescriptionContinuousTimeOffsetKey);
-
-#if defined(__arm__) || defined(__arm64__)
-		// Make ml_get_conttime_offset available before systemPower
-		OSDictionary * wakeDescription = OSDictionary::withCapacity(1);
-		OSObject * prop = OSNumber::withNumber(ml_get_conttime_offset(), sizeof(uint64_t) * CHAR_BIT);
-		wakeDescription->setObject(gIOSystemStateWakeDescriptionContinuousTimeOffsetKey, prop);
-		ret = me->StateNotificationItemCreate(gIOSystemStateWakeDescriptionKey, wakeDescription);
-		OSSafeReleaseNULL(prop);
-		OSSafeReleaseNULL(wakeDescription);
-		assert(kIOReturnSuccess == ret);
-#else /* !defined(__arm__) && !defined(__arm64__) */
-		ret = me->StateNotificationItemCreate(gIOSystemStateWakeDescriptionKey, NULL);
-		assert(kIOReturnSuccess == ret);
-#endif /* defined(__arm__) || defined(__arm64__) */
-
-		gIOSystemStateHaltDescriptionKey = (OSString *)OSSymbol::withCStringNoCopy(kIOSystemStateHaltDescriptionKey);
-		gIOSystemStateHaltDescriptionHaltStateKey = OSSymbol::withCStringNoCopy(kIOSystemStateHaltDescriptionHaltStateKey);
-
-		ret = me->StateNotificationItemCreate(gIOSystemStateHaltDescriptionKey, NULL);
-		assert(kIOReturnSuccess == ret);
-
-		gIOSystemStatePowerSourceDescriptionKey = (OSString *)OSSymbol::withCStringNoCopy(kIOSystemStatePowerSourceDescriptionKey);
-		gIOSystemStatePowerSourceDescriptionACAttachedKey = OSSymbol::withCStringNoCopy(kIOSystemStatePowerSourceDescriptionACAttachedKey);
-
-		ret = me->StateNotificationItemCreate(gIOSystemStatePowerSourceDescriptionKey, NULL);
-		assert(kIOReturnSuccess == ret);
-	}
-
-	return me;
-}
-
-bool
-IOSystemStateNotification::serializeProperties(OSSerialize * s) const
-{
-	IOServiceStateChangeVars * ivars = reserved->svars;
-
-	bool ok;
-	OSDictionary * result;
-
-	result = OSDictionary::withCapacity(16);
-
-	IOLockLock(ivars->fLock);
-	ivars->fItems->iterateObjects(^bool (const OSSymbol * key, OSObject * object) {
-		IOStateNotificationItem * item;
-
-		item = (typeof(item))object;
-		if (!item->fValue) {
-		        return false;
-		}
-		result->setObject(key, item->fValue);
-		return false;
-	});
-	IOLockUnlock(ivars->fLock);
-
-	ok = result->serialize(s);
-	OSSafeReleaseNULL(result);
-
-	return ok;
-}
-
-kern_return_t
-IOSystemStateNotification::setProperties(OSObject * properties)
-{
-	kern_return_t  kr;
-	OSDictionary * dict;
-	OSDictionary * value;
-	OSString     * itemName;
-
-	dict = OSDynamicCast(OSDictionary, properties);
-	if (!dict) {
-		return kIOReturnBadArgument;
-	}
-
-	if (!IOCurrentTaskHasEntitlement(kIOSystemStateEntitlement)) {
-		return kIOReturnNotPermitted;
-	}
-
-	if ((value = OSDynamicCast(OSDictionary, dict->getObject(kIOStateNotificationItemCreateKey)))) {
-		itemName = OSDynamicCast(OSString, value->getObject(kIOStateNotificationNameKey));
-		itemName->retain();
-		value->removeObject(kIOStateNotificationNameKey);
-		kr = StateNotificationItemCreate(itemName, value);
-		itemName->release();
-	} else if ((value = OSDynamicCast(OSDictionary, dict->getObject(kIOStateNotificationItemSetKey)))) {
-		itemName = OSDynamicCast(OSString, value->getObject(kIOStateNotificationNameKey));
-		itemName->retain();
-		value->removeObject(kIOStateNotificationNameKey);
-		kr = StateNotificationItemSet(itemName, value);
-		itemName->release();
-	} else {
-		kr = kIOReturnError;
-	}
-
-	return kr;
-}
-
-kern_return_t
-IOService::CopySystemStateNotificationService_Impl(IOService ** outService)
-{
-	IOService * service;
-
-	service = getSystemStateNotificationService();
-	service->retain();
-	*outService = service;
-
-	return kIOReturnSuccess;
-}
-
-IOStateNotificationItem *
-IOService::stateNotificationItemCopy(OSString * itemName, OSDictionary * initialValue)
-{
-	IOServiceStateChangeVars * ivars = reserved->svars;
-
-	const OSSymbol          * name;
-	IOStateNotificationItem * item;
-
-	name = OSSymbol::withString(itemName);
-
-	IOLockLock(ivars->fLock);
-	if ((item = (typeof(item))ivars->fItems->getObject(name))) {
-		item->retain();
-	} else {
-		item = OSTypeAlloc(IOStateNotificationItem);
-		item->init();
-		item->fListeners = OSSet::withCapacity(16);
-
-		if (initialValue) {
-			initialValue->retain();
-			item->fValue = initialValue;
-		}
-		ivars->fItems->setObject(name, item);
-	}
-	IOLockUnlock(ivars->fLock);
-
-	OSSafeReleaseNULL(name);
-
-	return item;
-}
-
-kern_return_t
-IOService::StateNotificationItemCreate_Impl(OSString * itemName, OSDictionary * value)
-{
-	IOStateNotificationItem * item;
-
-	item = stateNotificationItemCopy(itemName, value);
-	if (!item) {
-		return kIOReturnNoMemory;
-	}
-	item->release();
-
-	return kIOReturnSuccess;
-}
-
-kern_return_t
-IOService::StateNotificationItemSet_Impl(OSString * itemName, OSDictionary * value)
-{
-	kern_return_t              ret = kIOReturnSuccess;
-	IOServiceStateChangeVars * ivars = reserved->svars;
-
-	OSSet                    * listeners = NULL;
-	IOStateNotificationItem  * item;
-
-	value->retain();
-	IOLockLock(ivars->fLock);
-	do {
-		item = (typeof(item))ivars->fItems->getObject(itemName);
-		if (!item) {
-			ret = kIOReturnNotFound;
-			value->release();
-			break;
-		}
-		OSSafeReleaseNULL(item->fValue);
-		item->fValue = value;
-		if (item->fListeners->getCount()) {
-			listeners = OSSet::withSet(item->fListeners);
-		}
-	} while (false);
-	IOLockUnlock(ivars->fLock);
-
-	if (listeners) {
-		listeners->iterateObjects(^bool (OSObject * object) {
-			IOStateNotificationListener * listener;
-
-			listener = (typeof(listener))object;
-			listener->fHandler();
-			return false;
-		});
-		OSSafeReleaseNULL(listeners);
-	}
-
-	return ret;
-}
-
-kern_return_t
-IOService::StateNotificationItemCopy_Impl(OSString * itemName, OSDictionary ** outValue)
-{
-	IOServiceStateChangeVars * ivars = reserved->svars;
-
-	kern_return_t              ret;
-	IOStateNotificationItem  * item;
-	OSDictionary             * value;
-
-	IOLockLock(ivars->fLock);
-	item = (typeof(item))ivars->fItems->getObject(itemName);
-	if (item) {
-		value = item->fValue;
-	} else {
-		value = NULL;
-	}
-	if (!value) {
-		ret = kIOReturnNotFound;
-	} else {
-		value->retain();
-		ret = kIOReturnSuccess;
-	}
-	IOLockUnlock(ivars->fLock);
-
-	*outValue = value;
-
-	return ret;
-}
-
-kern_return_t
-IOService::stateNotificationListenerAdd(OSArray * items,
-    IOStateNotificationListenerRef * outRef,
-    IOStateNotificationHandler handler)
-{
-	IOServiceStateChangeVars * ivars = reserved->svars;
-
-	kern_return_t                 kr __block;
-	IOStateNotificationListener * listener;
-
-	listener = OSTypeAlloc(IOStateNotificationListener);
-	listener->init();
-	listener->fHandler = Block_copy(handler);
-
-	kr = kIOReturnSuccess;
-	items->iterateObjects(^bool (OSObject * object) {
-		OSString                * itemName;
-		IOStateNotificationItem * item;
-
-		itemName = OSDynamicCast(OSString, object);
-		if (!itemName) {
-		        kr = kIOReturnBadArgument;
-		        return true;
-		}
-		item = stateNotificationItemCopy(itemName, NULL);
-		if (!item) {
-		        kr = kIOReturnNoMemory;
-		        return true;
-		}
-		IOLockLock(ivars->fLock);
-		item->fListeners->setObject(listener);
-		IOLockUnlock(ivars->fLock);
-		item->release();
-		return false;
-	});
-
-	if (kIOReturnSuccess != kr) {
-		stateNotificationListenerRemove(listener);
-		OSSafeReleaseNULL(listener);
-	}
-	*outRef = listener;
-
-	return kr;
-}
-
-
-kern_return_t
-IOService::stateNotificationListenerRemove(IOStateNotificationListenerRef ref)
-{
-	IOServiceStateChangeVars * ivars = reserved->svars;
-
-	IOStateNotificationListener * listener;
-	kern_return_t                 kr;
-
-	kr = kIOReturnSuccess;
-	listener = (typeof(listener))ref;
-
-	IOLockLock(ivars->fLock);
-	ivars->fItems->iterateObjects(^bool (const OSSymbol * key, OSObject * object) {
-		IOStateNotificationItem * item;
-
-		item = (typeof(item))object;
-		item->fListeners->removeObject(listener);
-		return false;
-	});
-	IOLockUnlock(ivars->fLock);
-
-	return kr;
-}
-
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-kern_return_t
-IOWorkGroup::Create_Impl(OSString * name, IOUserClient * userClient, IOWorkGroup ** workgroup)
-{
-	IOWorkGroup * inst = NULL;
-	IOUserUserClient * uc = NULL;
-	kern_return_t ret = kIOReturnError;
-	IOUserServer * us;
-
-	if (name == NULL) {
-		ret = kIOReturnBadArgument;
-		goto finish;
-	}
-
-	if (name->getLength() > kIOWorkGroupMaxNameLength) {
-		ret = kIOReturnBadArgument;
-		goto finish;
-	}
-
-	uc = OSDynamicCast(IOUserUserClient, userClient);
-	if (uc == NULL) {
-		ret = kIOReturnBadArgument;
-		goto finish;
-	}
-
-	inst = OSTypeAlloc(IOWorkGroup);
-	if (!inst->init()) {
-		inst->free();
-		inst = NULL;
-		ret = kIOReturnNoMemory;
-		goto finish;
-	}
-
-	us = (typeof(us))thread_iokit_tls_get(0);
-	inst->ivars->userServer = OSDynamicCast(IOUserServer, us);
-
-	if (inst->ivars->userServer == NULL) {
-		ret = kIOReturnBadArgument;
-		goto finish;
-	}
-	inst->ivars->userServer->retain();
-
-	inst->ivars->name = name;
-	inst->ivars->name->retain();
-
-	inst->ivars->userClient = uc; // no retain
-
-	IOLockLock(uc->fLock);
-	uc->fWorkGroups->setObject(name, inst);
-	IOLockUnlock(uc->fLock);
-	ret = kIOReturnSuccess;
-
-finish:
-	if (ret != kIOReturnSuccess) {
-		OSSafeReleaseNULL(inst);
-	} else {
-		*workgroup = inst;
-	}
-
-	return ret;
-}
-
-kern_return_t
-IOWorkGroup::InvalidateKernel_Impl(IOUserClient * client)
-{
-	IOUserUserClient * uc = OSDynamicCast(IOUserUserClient, client);
-
-	if (uc == NULL) {
-		return kIOReturnBadArgument;
-	}
-
-	if (uc != ivars->userClient) {
-		return kIOReturnBadArgument;
-	}
-
-	IOLockLock(uc->fLock);
-	uc->fWorkGroups->removeObject(ivars->name);
-	IOLockUnlock(uc->fLock);
-
-	return kIOReturnSuccess;
-}
-
-kern_return_t
-IOWorkGroup::SetWorkGroupPort_Impl(mach_port_t port)
-{
-	return kIOReturnUnsupported;
-}
-
-bool
-IOWorkGroup::init()
-{
-	if (!OSObject::init()) {
-		return false;
-	}
-	ivars = IOMallocType(IOWorkGroup_IVars);
-
-	return true;
-}
-
-void
-IOWorkGroup::free()
-{
-	if (ivars) {
-		OSSafeReleaseNULL(ivars->userServer);
-		OSSafeReleaseNULL(ivars->name);
-		IOFreeType(ivars, IOWorkGroup_IVars);
-	}
-
-	OSObject::free();
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-kern_return_t
-IOEventLink::Create_Impl(OSString * name, IOUserClient * userClient, IOEventLink ** eventlink)
-{
-	IOEventLink * inst = NULL;
-	IOUserUserClient * uc = NULL;
-	IOUserServer * us;
-	kern_return_t ret = kIOReturnError;
-
-	if (name == NULL) {
-		ret = kIOReturnBadArgument;
-		goto finish;
-	}
-
-	if (name->getLength() > kIOEventLinkMaxNameLength) {
-		ret = kIOReturnBadArgument;
-		goto finish;
-	}
-
-	uc = OSDynamicCast(IOUserUserClient, userClient);
-	if (uc == NULL) {
-		ret = kIOReturnBadArgument;
-		goto finish;
-	}
-
-	inst = OSTypeAlloc(IOEventLink);
-	if (!inst->init()) {
-		inst->free();
-		inst = NULL;
-		ret = kIOReturnNoMemory;
-		goto finish;
-	}
-
-	us = (typeof(us))thread_iokit_tls_get(0);
-	inst->ivars->userServer = OSDynamicCast(IOUserServer, us);
-
-	if (inst->ivars->userServer == NULL) {
-		ret = kIOReturnBadArgument;
-		goto finish;
-	}
-	inst->ivars->userServer->retain();
-
-	inst->ivars->name = name;
-	inst->ivars->name->retain();
-
-	inst->ivars->userClient = uc; // no retain
-
-	IOLockLock(uc->fLock);
-	uc->fEventLinks->setObject(name, inst);
-	IOLockUnlock(uc->fLock);
-
-	ret = kIOReturnSuccess;
-
-finish:
-	if (ret != kIOReturnSuccess) {
-		OSSafeReleaseNULL(inst);
-	} else {
-		*eventlink = inst;
-	}
-
-	return ret;
-}
-
-kern_return_t
-IOEventLink::InvalidateKernel_Impl(IOUserClient * client)
-{
-	IOUserUserClient * uc = OSDynamicCast(IOUserUserClient, client);
-
-	if (uc == NULL) {
-		return kIOReturnBadArgument;
-	}
-
-	if (uc != ivars->userClient) {
-		return kIOReturnBadArgument;
-	}
-
-	IOLockLock(uc->fLock);
-	uc->fEventLinks->removeObject(ivars->name);
-	IOLockUnlock(uc->fLock);
-
-	return kIOReturnSuccess;
-}
-
-bool
-IOEventLink::init()
-{
-	if (!OSObject::init()) {
-		return false;
-	}
-	ivars = IOMallocType(IOEventLink_IVars);
-
-	return true;
-}
-
-void
-IOEventLink::free()
-{
-	if (ivars) {
-		OSSafeReleaseNULL(ivars->userServer);
-		OSSafeReleaseNULL(ivars->name);
-		IOFreeType(ivars, IOEventLink_IVars);
-	}
-
-	OSObject::free();
-}
-
-kern_return_t
-IOEventLink::SetEventlinkPort_Impl(mach_port_t port __unused)
-{
-	return kIOReturnUnsupported;
-}