diff --git a/desktop/api.cpp b/desktop/api.cpp
index 9e37a0d..12f1e42 100644
--- a/desktop/api.cpp
+++ b/desktop/api.cpp
@@ -1483,7 +1483,7 @@ extern "C" void _start(EsProcessStartupInformation *_startupInformation) {
 
 		while (!api.foundBootFileSystem) {
 			EsMessage *message = EsMessageReceive();
-			DesktopMessage(message);
+			DesktopSendMessage(message);
 		}
 
 		size_t fileSize;
diff --git a/desktop/desktop.cpp b/desktop/desktop.cpp
index c62dbcd..dd2cdea 100644
--- a/desktop/desktop.cpp
+++ b/desktop/desktop.cpp
@@ -238,6 +238,7 @@ void WallpaperLoad(EsGeneric);
 WindowTab *WindowTabCreate(ContainerWindow *container);
 ContainerWindow *ContainerWindowCreate();
 void ContainerWindowShow(ContainerWindow *, int32_t width, int32_t height);
+void ShutdownModalCreate();
 
 #include "settings.cpp"
 
@@ -626,6 +627,8 @@ int ProcessGlobalKeyboardShortcuts(EsElement *, EsMessage *message) {
 					ApplicationInstanceCreate(desktop.installedApplications[i]->id, nullptr, nullptr);
 				}
 			}
+		} else if (scancode == ES_SCANCODE_ACPI_POWER) {
+			ShutdownModalCreate();
 		} else {
 			return 0;
 		}
@@ -2964,14 +2967,12 @@ void EmbeddedWindowDestroyed(EsObjectID id) {
 	EsHeapFree(instance);
 }
 
-void DesktopMessage(EsMessage *message) {
+void DesktopSendMessage(EsMessage *message) {
 	if (!desktop.clockReady) {
 		desktop.clockReady = EsEventCreate(false);
 	}
 
-	if (message->type == ES_MSG_POWER_BUTTON_PRESSED) {
-		ShutdownModalCreate();
-	} else if (message->type == ES_MSG_EMBEDDED_WINDOW_DESTROYED) {
+	if (message->type == ES_MSG_EMBEDDED_WINDOW_DESTROYED) {
 		EmbeddedWindowDestroyed(message->desktop.windowID);
 	} else if (message->type == ES_MSG_DESKTOP) {
 		uint8_t *buffer = (uint8_t *) EsHeapAllocate(message->desktop.bytes, false);
@@ -3073,6 +3074,6 @@ void DesktopEntry() {
 
 	while (true) {
 		EsMessage *message = EsMessageReceive();
-		DesktopMessage(message);
+		DesktopSendMessage(message);
 	}
 }
diff --git a/desktop/os.header b/desktop/os.header
index a2bd3c6..bc31c74 100644
--- a/desktop/os.header
+++ b/desktop/os.header
@@ -966,7 +966,6 @@ enum EsMessageType {
 	ES_MSG_SLIDER_MOVED			= 0x3006	// The slider has been moved.
 
 	// Desktop messages: 
-	ES_MSG_POWER_BUTTON_PRESSED		= 0x4801
 	ES_MSG_EMBEDDED_WINDOW_DESTROYED 	= 0x4802
 	ES_MSG_SET_SCREEN_RESOLUTION		= 0x4803
 	ES_MSG_REGISTER_FILE_SYSTEM		= 0x4804
diff --git a/drivers/acpica.cpp b/drivers/acpica.cpp
index 1a3ef65..24dea2a 100644
--- a/drivers/acpica.cpp
+++ b/drivers/acpica.cpp
@@ -425,9 +425,8 @@ ES_EXTERN_C ACPI_STATUS AcpiOsEnterSleep(UINT8 sleepState, UINT32 registerAValue
 
 UINT32 ACPIPowerButtonPressed(void *) {
 	KRegisterAsyncTask(&powerButtonAsyncTask, [] (KAsyncTask *) {
-		_EsMessageWithObject m = { nullptr, ES_MSG_POWER_BUTTON_PRESSED };
-		if (scheduler.shutdown) return;
-		if (desktopProcess) desktopProcess->messageQueue.SendMessage(&m);
+		KKeyPress(ES_SCANCODE_ACPI_POWER | K_SCANCODE_KEY_PRESSED);
+		KKeyPress(ES_SCANCODE_ACPI_POWER | K_SCANCODE_KEY_RELEASED);
 	});
 
 	return 0;
diff --git a/kernel/cache.cpp b/kernel/cache.cpp
index 0bfb35a..2f441ec 100644
--- a/kernel/cache.cpp
+++ b/kernel/cache.cpp
@@ -79,6 +79,8 @@ void CCSpaceUncover(CCSpace *cache, EsFileOffset removeStart, EsFileOffset remov
 EsError CCSpaceAccess(CCSpace *cache, K_USER_BUFFER void *buffer, EsFileOffset offset, EsFileOffset count, uint32_t flags, 
 		MMSpace *mapSpace = nullptr, unsigned mapFlags = ES_FLAGS_DEFAULT);
 
+MMActiveSectionManager activeSectionManager;
+
 #else
 
 CCCachedSection *CCFindCachedSectionContaining(CCSpace *cache, EsFileOffset sectionOffset) {
diff --git a/kernel/drivers.cpp b/kernel/drivers.cpp
index f463673..a808b9e 100644
--- a/kernel/drivers.cpp
+++ b/kernel/drivers.cpp
@@ -119,11 +119,11 @@ void DeviceRemovedRecurse(KDevice *device) {
 	}
 
 	if (device->flags & K_DEVICE_VISIBLE_TO_USER) {
-		EsMessage m;
+		_EsMessageWithObject m;
 		EsMemoryZero(&m, sizeof(m));
-		m.type = ES_MSG_DEVICE_DISCONNECTED;
-		m.device.id = device->objectID;
-		desktopProcess->messageQueue.SendMessage(nullptr, &m);
+		m.message.type = ES_MSG_DEVICE_DISCONNECTED;
+		m.message.device.id = device->objectID;
+		DesktopSendMessage(&m);
 	}
 
 	if (device->removed) {
@@ -145,16 +145,16 @@ void KDeviceSendConnectedMessage(KDevice *device, EsDeviceType type) {
 
 	KDeviceOpenHandle(device);
 
-	EsMessage m;
+	_EsMessageWithObject m;
 	EsMemoryZero(&m, sizeof(m));
-	m.type = ES_MSG_DEVICE_CONNECTED;
-	m.device.id = device->objectID;
-	m.device.type = type;
-	m.device.handle = desktopProcess->handleTable.OpenHandle(device, 0, KERNEL_OBJECT_DEVICE);
+	m.message.type = ES_MSG_DEVICE_CONNECTED;
+	m.message.device.id = device->objectID;
+	m.message.device.type = type;
+	m.message.device.handle = DesktopOpenHandle(device, 0, KERNEL_OBJECT_DEVICE);
 
-	if (m.device.handle) {
-		if (!desktopProcess->messageQueue.SendMessage(nullptr, &m)) {
-			desktopProcess->handleTable.CloseHandle(m.device.handle); // This will check that the handle is still valid.
+	if (m.message.device.handle) {
+		if (!DesktopSendMessage(&m)) {
+			DesktopCloseHandle(m.message.device.handle); // This will check that the handle is still valid.
 		}
 	}
 }
diff --git a/kernel/files.cpp b/kernel/files.cpp
index 628c5dc..5ee77b0 100644
--- a/kernel/files.cpp
+++ b/kernel/files.cpp
@@ -1876,11 +1876,11 @@ void FSRegisterBootFileSystem(KFileSystem *fileSystem, EsUniqueIdentifier identi
 
 void FSFileSystemDeviceRemoved(KDevice *device) {
 	KFileSystem *fileSystem = (KFileSystem *) device;
-	EsMessage m;
-	EsMemoryZero(&m, sizeof(EsMessage));
-	m.type = ES_MSG_UNREGISTER_FILE_SYSTEM;
-	m.unregisterFileSystem.id = fileSystem->objectID;
-	desktopProcess->messageQueue.SendMessage(nullptr, &m);
+	_EsMessageWithObject m;
+	EsMemoryZero(&m, sizeof(m));
+	m.message.type = ES_MSG_UNREGISTER_FILE_SYSTEM;
+	m.message.unregisterFileSystem.id = fileSystem->objectID;
+	DesktopSendMessage(&m);
 }
 
 void FSRegisterFileSystem(KFileSystem *fileSystem) {
@@ -1893,16 +1893,15 @@ void FSRegisterFileSystem(KFileSystem *fileSystem) {
 	fileSystem->rootDirectory->directoryEntry->directoryChildren = fileSystem->rootDirectoryInitialChildren;
 	FSNodeOpenHandle(fileSystem->rootDirectory, ES_FLAGS_DEFAULT, fileSystem->isBootFileSystem ? FS_NODE_OPEN_HANDLE_STANDARD : FS_NODE_OPEN_HANDLE_FIRST);
 
-	EsMessage m;
-	EsMemoryZero(&m, sizeof(EsMessage));
-	m.type = ES_MSG_REGISTER_FILE_SYSTEM;
-	m.registerFileSystem.isBootFileSystem = fileSystem->isBootFileSystem;
+	_EsMessageWithObject m;
+	EsMemoryZero(&m, sizeof(m));
+	m.message.type = ES_MSG_REGISTER_FILE_SYSTEM;
+	m.message.registerFileSystem.isBootFileSystem = fileSystem->isBootFileSystem;
+	m.message.registerFileSystem.rootDirectory = DesktopOpenHandle(fileSystem->rootDirectory, _ES_NODE_DIRECTORY_WRITE, KERNEL_OBJECT_NODE);
 
-	m.registerFileSystem.rootDirectory = desktopProcess->handleTable.OpenHandle(fileSystem->rootDirectory, _ES_NODE_DIRECTORY_WRITE, KERNEL_OBJECT_NODE);
-
-	if (m.registerFileSystem.rootDirectory) {
-		if (!desktopProcess->messageQueue.SendMessage(nullptr, &m)) {
-			desktopProcess->handleTable.CloseHandle(m.registerFileSystem.rootDirectory); // This will check that the handle is still valid.
+	if (m.message.registerFileSystem.rootDirectory) {
+		if (!DesktopSendMessage(&m)) {
+			DesktopCloseHandle(m.message.registerFileSystem.rootDirectory); // This will check that the handle is still valid.
 		}
 	}
 
diff --git a/kernel/graphics.cpp b/kernel/graphics.cpp
index 63e41e5..bcac19c 100644
--- a/kernel/graphics.cpp
+++ b/kernel/graphics.cpp
@@ -113,10 +113,10 @@ void KRegisterGraphicsTarget(KGraphicsTarget *target) {
 #else
 	windowManager.Initialise();
 
-	EsMessage m;
-	EsMemoryZero(&m, sizeof(EsMessage));
-	m.type = ES_MSG_SET_SCREEN_RESOLUTION;
-	desktopProcess->messageQueue.SendMessage(nullptr, &m);
+	_EsMessageWithObject m;
+	EsMemoryZero(&m, sizeof(m));
+	m.message.type = ES_MSG_SET_SCREEN_RESOLUTION;
+	DesktopSendMessage(&m);
 #endif
 }
 
diff --git a/kernel/memory.cpp b/kernel/memory.cpp
index cf9d01b..96b9b73 100644
--- a/kernel/memory.cpp
+++ b/kernel/memory.cpp
@@ -302,7 +302,6 @@ void PMCopy(uintptr_t page, void *source, size_t pageCount);
 
 MMSpace _kernelMMSpace, _coreMMSpace;
 PMM pmm;
-MMActiveSectionManager activeSectionManager;
 
 MMRegion *mmCoreRegions = (MMRegion *) MM_CORE_REGIONS_START;
 size_t mmCoreRegionCount, mmCoreRegionArrayCommit;
diff --git a/kernel/objects.cpp b/kernel/objects.cpp
index 0b076fb..3930f19 100644
--- a/kernel/objects.cpp
+++ b/kernel/objects.cpp
@@ -574,10 +574,6 @@ EsHandle MakeConstantBuffer(K_USER_BUFFER const void *data, size_t bytes, Proces
 	return object ? process->handleTable.OpenHandle(object, 0, KERNEL_OBJECT_CONSTANT_BUFFER) : ES_INVALID_HANDLE; 
 }
 
-EsHandle MakeConstantBufferForDesktop(K_USER_BUFFER const void *data, size_t bytes) {
-	return MakeConstantBuffer(data, bytes, desktopProcess);
-}
-
 size_t Pipe::Access(void *_buffer, size_t bytes, bool write, bool user) {
 	size_t amount = 0;
 	Thread *currentThread = GetCurrentThread();
@@ -730,6 +726,12 @@ bool MessageQueue::SendMessage(_EsMessageWithObject *_message) {
 
 	KEventSet(&notEmpty, true);
 
+	// TODO Temporary.
+	static int largest = 0;
+	int size = messages.Length();
+	if (size > largest) largest = size;
+	if (size > 40) KernelPanic("what\n");
+
 	return true;
 }
 
diff --git a/kernel/scheduler.cpp b/kernel/scheduler.cpp
index 33c0911..54d3ca5 100644
--- a/kernel/scheduler.cpp
+++ b/kernel/scheduler.cpp
@@ -188,8 +188,6 @@ struct Process {
 };
 
 struct Scheduler {
-	// External API:
-
 	void Yield(InterruptContext *context);
 	void CreateProcessorThreads(CPULocalStorage *local);
 	void AddActiveThread(Thread *thread, bool start /* put it at the start of the active list */); // Add an active thread into the queue.
@@ -199,8 +197,6 @@ struct Scheduler {
 	Thread *PickThread(CPULocalStorage *local); // Pick the next thread to execute.
 	int8_t GetThreadEffectivePriority(Thread *thread);
 
-	// Variables:
-
 	KSpinlock dispatchSpinlock; // For accessing synchronisation objects, thread states, scheduling lists, etc. TODO Break this up!
 	KSpinlock activeTimersSpinlock; // For accessing the activeTimers lists.
 	LinkedList<Thread> activeThreads[THREAD_PRIORITY_COUNT];
@@ -244,9 +240,14 @@ void ThreadSetTemporaryAddressSpace(MMSpace *space);
 Thread *ThreadSpawn(const char *cName, uintptr_t startAddress, uintptr_t argument1 = 0, 
 		uint32_t flags = ES_FLAGS_DEFAULT, Process *process = nullptr, uintptr_t argument2 = 0);
 
+bool DesktopSendMessage(_EsMessageWithObject *message);
+EsHandle DesktopOpenHandle(void *object, uint32_t flags, KernelObjectType type);
+void DesktopCloseHandle(EsHandle handle);
+
 Process _kernelProcess;
 Process *kernelProcess = &_kernelProcess;
 Process *desktopProcess;
+KMutex desktopMutex;
 Scheduler scheduler;
 
 #endif
@@ -544,7 +545,7 @@ void ProcessKill(Process *process) {
 		EsMemoryZero(&m, sizeof(m));
 		m.message.type = ES_MSG_PROCESS_TERMINATED;
 		m.message.crash.pid = process->id;
-		desktopProcess->messageQueue.SendMessage(&m);
+		DesktopSendMessage(&m);
 	}
 }
 
@@ -728,7 +729,7 @@ void ProcessLoadExecutable() {
 
 	KLoadedExecutable application = {};
 
-	if (thisProcess != desktopProcess && loadError == ES_SUCCESS) {
+	if (thisProcess->type != PROCESS_DESKTOP && loadError == ES_SUCCESS) {
 		loadError = KLoadELF(thisProcess->executableNode, &application);
 	}
 
@@ -754,7 +755,7 @@ void ProcessLoadExecutable() {
 		if (!startupInformation) {
 			success = false;
 		} else {
-			startupInformation->isDesktop = thisProcess == desktopProcess;
+			startupInformation->isDesktop = thisProcess->type == PROCESS_DESKTOP;
 			startupInformation->isBundle = application.isBundle;
 			startupInformation->applicationStartAddress = application.startAddress;
 			startupInformation->tlsImageStart = application.tlsImageStart;
@@ -1086,7 +1087,7 @@ void ProcessCrash(Process *process, EsCrashReason *crashReason) {
 		m.message.type = ES_MSG_APPLICATION_CRASH;
 		m.message.crash.pid = process->id;
 		EsMemoryCopy(&m.message.crash.reason, crashReason, sizeof(EsCrashReason));
-		desktopProcess->messageQueue.SendMessage(&m);
+		DesktopSendMessage(&m);
 	}
 
 	KMutexRelease(&process->crashMutex);
@@ -1272,11 +1273,16 @@ void Scheduler::Yield(InterruptContext *context) {
 }
 
 void ProcessTerminateAll() {
+	KMutexAcquire(&desktopMutex);
+
 	scheduler.shutdown = true;
 
 	// Close our handle to the desktop process.
 	CloseHandleToObject(desktopProcess->executableMainThread, KERNEL_OBJECT_THREAD);
 	CloseHandleToObject(desktopProcess, KERNEL_OBJECT_PROCESS);
+	desktopProcess = nullptr;
+
+	KMutexRelease(&desktopMutex);
 
 	KernelLog(LOG_INFO, "Scheduler", "terminating all processes", "ProcessTerminateAll - Terminating all processes....\n");
 
@@ -1331,6 +1337,31 @@ void KYield() {
 	ProcessorFakeTimerInterrupt();
 }
 
+bool DesktopSendMessage(_EsMessageWithObject *message) {
+	bool result = false;
+	KMutexAcquire(&desktopMutex);
+	if (desktopProcess) result = desktopProcess->messageQueue.SendMessage(message);
+	KMutexRelease(&desktopMutex);
+	return result;
+}
+
+EsHandle DesktopOpenHandle(void *object, uint32_t flags, KernelObjectType type) {
+	EsHandle result = ES_INVALID_HANDLE;
+	bool close = false;
+	KMutexAcquire(&desktopMutex);
+	if (desktopProcess) result = desktopProcess->handleTable.OpenHandle(object, flags, type);
+	else close = true;
+	KMutexRelease(&desktopMutex);
+	if (close) CloseHandleToObject(object, type, flags);
+	return result;
+}
+
+void DesktopCloseHandle(EsHandle handle) {
+	KMutexAcquire(&desktopMutex);
+	if (desktopProcess) desktopProcess->handleTable.CloseHandle(handle); // This will check that the handle is still valid.
+	KMutexRelease(&desktopMutex);
+}
+
 uint64_t KCPUCurrentID() 	{ return GetLocalStorage() ->processorID; }
 uint64_t KProcessCurrentID()	{ return GetCurrentThread()->process->id; }
 uint64_t KThreadCurrentID()	{ return GetCurrentThread()         ->id; }
diff --git a/kernel/synchronisation.cpp b/kernel/synchronisation.cpp
index 594d02e..bbb9809 100644
--- a/kernel/synchronisation.cpp
+++ b/kernel/synchronisation.cpp
@@ -4,10 +4,6 @@
 
 #ifdef IMPLEMENTATION
 
-#ifdef DEBUG_BUILD
-uintptr_t nextMutexID;
-#endif
-
 void KSpinlockAcquire(KSpinlock *spinlock) {
 	if (scheduler.panic) return;
 
@@ -187,6 +183,7 @@ bool KMutexAcquire(KMutex *mutex) {
 	KMutexAssertLocked(mutex);
 
 	if (!mutex->id) {
+		static uintptr_t nextMutexID;
 		mutex->id = __sync_fetch_and_add(&nextMutexID, 1);
 	}
 
diff --git a/kernel/syscall.cpp b/kernel/syscall.cpp
index d21e059..9ca77c9 100644
--- a/kernel/syscall.cpp
+++ b/kernel/syscall.cpp
@@ -8,8 +8,6 @@
 
 #ifdef IMPLEMENTATION
 
-KMutex eventForwardMutex;
-
 #define SYSCALL_BUFFER_LIMIT (64 * 1024 * 1024) // To prevent overflow and DOS attacks.
 #define SYSCALL_BUFFER(address, length, index, write) \
 	MMRegion *_region ## index = MMFindAndPinRegion(currentVMM, (address), (length)); \
@@ -1368,17 +1366,19 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_MESSAGE_DESKTOP) {
 			OpenHandleToObject(pipe, KERNEL_OBJECT_PIPE, PIPE_WRITER);
 		}
 
+		void *constantBuffer = MakeConstantBuffer(buffer, argument1);
+
 		_EsMessageWithObject m = {};
 		m.message.type = ES_MSG_DESKTOP;
-		m.message.desktop.buffer = MakeConstantBufferForDesktop(buffer, argument1);
+		m.message.desktop.buffer = constantBuffer ? DesktopOpenHandle(constantBuffer, ES_FLAGS_DEFAULT, KERNEL_OBJECT_CONSTANT_BUFFER) : ES_INVALID_HANDLE;
 		m.message.desktop.bytes = argument1;
 		m.message.desktop.windowID = window ? window->id : 0;
 		m.message.desktop.processID = currentProcess->id;
-		m.message.desktop.pipe = pipe ? desktopProcess->handleTable.OpenHandle(pipe, PIPE_WRITER, KERNEL_OBJECT_PIPE) : ES_INVALID_HANDLE;
+		m.message.desktop.pipe = pipe ? DesktopOpenHandle(pipe, PIPE_WRITER, KERNEL_OBJECT_PIPE) : ES_INVALID_HANDLE;
 
-		if (!m.message.desktop.buffer || !desktopProcess->messageQueue.SendMessage(&m)) {
-			desktopProcess->handleTable.CloseHandle(m.message.desktop.buffer); 
-			desktopProcess->handleTable.CloseHandle(m.message.desktop.pipe); 
+		if (!m.message.desktop.buffer || !DesktopSendMessage(&m)) {
+			DesktopCloseHandle(m.message.desktop.buffer); 
+			DesktopCloseHandle(m.message.desktop.pipe); 
 		}
 	}
 
diff --git a/kernel/windows.cpp b/kernel/windows.cpp
index b167dd3..5a38dd1 100644
--- a/kernel/windows.cpp
+++ b/kernel/windows.cpp
@@ -399,12 +399,11 @@ void WindowManager::PressKey(uint32_t scancode) {
 	KernelLog(LOG_VERBOSE, "WM", "press key", "WindowManager::PressKey - Received key press %x. Modifiers are %X. Keys held: %d/%d%z.\n", 
 			scancode, modifiers, keysHeld, maximumKeysHeld, message.keyboard.single ? " (single)" : "");
 
-	if ((modifiers & ES_MODIFIER_CTRL) && (modifiers & ES_MODIFIER_FLAG)) {
-		desktopProcess->messageQueue.SendMessage(nullptr, &message);
-	} else if (activeWindow) {
-		SendMessageToWindow(activeWindow, &message);
+	if (((modifiers & ES_MODIFIER_CTRL) && (modifiers & ES_MODIFIER_FLAG)) || !activeWindow) {
+		_EsMessageWithObject messageWithObject = { nullptr, message };
+		DesktopSendMessage(&messageWithObject);
 	} else {
-		desktopProcess->messageQueue.SendMessage(nullptr, &message);
+		SendMessageToWindow(activeWindow, &message);
 	}
 
 	KMutexRelease(&mutex);
@@ -928,17 +927,16 @@ void EmbeddedWindow::Destroy() {
 void EmbeddedWindow::Close() {
 	KMutexAssertLocked(&windowManager.mutex);
 
-	EsMessage message;
-	EsMemoryZero(&message, sizeof(EsMessage));
-	message.type = ES_MSG_WINDOW_DESTROYED;
-	owner->messageQueue.SendMessage(apiWindow, &message); 
+	_EsMessageWithObject m;
+	EsMemoryZero(&m, sizeof(m));
+	m.object = apiWindow;
+	m.message.type = ES_MSG_WINDOW_DESTROYED;
+	owner->messageQueue.SendMessage(&m); 
 	SetEmbedOwner(nullptr);
-
-	if (!scheduler.shutdown) {
-		message.type = ES_MSG_EMBEDDED_WINDOW_DESTROYED;
-		message.desktop.windowID = id;
-		desktopProcess->messageQueue.SendMessage(nullptr, &message); 
-	}
+	m.object = nullptr;
+	m.message.type = ES_MSG_EMBEDDED_WINDOW_DESTROYED;
+	m.message.desktop.windowID = id;
+	DesktopSendMessage(&m);
 
 	if (container && container->embed == this) {
 		container->SetEmbed(nullptr);