mirror of https://gitlab.com/nakst/essence
use pipe for desktop requests
This commit is contained in:
parent
afed49f30b
commit
9e610bd928
|
@ -191,6 +191,8 @@ struct {
|
|||
Array<EsSystemConfigurationGroup> systemConfigurationGroups;
|
||||
EsMutex systemConfigurationMutex;
|
||||
|
||||
EsHandle desktopRequestPipe, desktopResponsePipe;
|
||||
|
||||
Array<MountPoint> mountPoints;
|
||||
Array<EsMessageDevice> connectedDevices;
|
||||
bool foundBootFileSystem;
|
||||
|
@ -1049,7 +1051,7 @@ EsMessage *EsMessageReceive() {
|
|||
} else if (message.message.type == ES_MSG_APPLICATION_EXIT) {
|
||||
if (api.startupInformation->isDesktop) {
|
||||
// Desktop tracks the number of instances it owns, so it needs to know when it exits.
|
||||
ApplicationProcessTerminated(EsProcessGetID(ES_CURRENT_PROCESS));
|
||||
ApplicationProcessTerminated(DesktopGetApplicationProcessForDesktop());
|
||||
} else {
|
||||
api.workFinish = true;
|
||||
if (api.workAvailable) EsEventSet(api.workAvailable);
|
||||
|
@ -1573,6 +1575,8 @@ extern "C" void _start(EsProcessStartupInformation *_startupInformation) {
|
|||
|
||||
const SystemStartupDataHeader *header = (const SystemStartupDataHeader *) EsBufferRead(&buffer, sizeof(SystemStartupDataHeader));
|
||||
theming.cursorData = header->themeCursorData;
|
||||
api.desktopRequestPipe = header->desktopRequestPipe;
|
||||
api.desktopResponsePipe = header->desktopResponsePipe;
|
||||
|
||||
for (uintptr_t i = 0; i < header->initialMountPointCount; i++) {
|
||||
const EsMountPoint *mountPoint = (const EsMountPoint *) EsBufferRead(&buffer, sizeof(EsMountPoint));
|
||||
|
|
|
@ -138,6 +138,7 @@ struct BlankTabInstance : EsInstance {
|
|||
struct ApplicationProcess {
|
||||
EsObjectID id;
|
||||
EsHandle handle;
|
||||
EsHandle desktopRequestPipe, desktopResponsePipe;
|
||||
InstalledApplication *application;
|
||||
size_t instanceCount;
|
||||
};
|
||||
|
@ -1664,6 +1665,127 @@ void ApplicationTemporaryDestroy(InstalledApplication *application) {
|
|||
EsAssert(false);
|
||||
}
|
||||
|
||||
void ApplicationProcessTerminated(ApplicationProcess *process) {
|
||||
EsMessageMutexCheck();
|
||||
|
||||
desktop.allApplicationProcesses.FindAndDeleteSwap(process, true /* assert found */);
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
||||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||
|
||||
if (instance->process == process) {
|
||||
EmbeddedWindowDestroyed(instance->embeddedWindowID);
|
||||
i--; // EmbeddedWindowDestroyed removes it from the array.
|
||||
}
|
||||
}
|
||||
|
||||
InstalledApplication *application = process->application;
|
||||
|
||||
if (application) {
|
||||
if (application->singleProcess == process) {
|
||||
application->singleProcess = nullptr;
|
||||
}
|
||||
|
||||
application->singleInstance = nullptr;
|
||||
ApplicationTemporaryDestroy(application);
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.openDocuments.Count(); i++) {
|
||||
OpenDocument *document = &desktop.openDocuments[i];
|
||||
|
||||
if (document->currentWriter == process->id) {
|
||||
document->currentWriter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!desktop.allApplicationProcesses.Length() && desktop.inShutdown) {
|
||||
EsEventSet(desktop.shutdownReadyEvent);
|
||||
}
|
||||
|
||||
EsAssert(!process->instanceCount);
|
||||
EsHandleClose(process->handle);
|
||||
|
||||
if (process->desktopRequestPipe) {
|
||||
EsHandleClose(process->desktopRequestPipe);
|
||||
EsHandleClose(process->desktopResponsePipe);
|
||||
} else {
|
||||
// This must be a Desktop-owned instance.
|
||||
}
|
||||
|
||||
EsHeapFree(process);
|
||||
}
|
||||
|
||||
void DesktopRequestThread(EsGeneric argument) {
|
||||
ApplicationProcess *process = (ApplicationProcess *) argument.p;
|
||||
|
||||
uint32_t length;
|
||||
size_t bytes;
|
||||
EsObjectID embeddedWindowID;
|
||||
|
||||
while (true) {
|
||||
bytes = EsPipeRead(process->desktopRequestPipe, &length, sizeof(length));
|
||||
if (bytes != sizeof(length)) break; // Process has terminated or closed the pipe.
|
||||
bytes = EsPipeRead(process->desktopRequestPipe, &embeddedWindowID, sizeof(embeddedWindowID));
|
||||
if (bytes != sizeof(embeddedWindowID)) break; // Process has terminated or closed the pipe.
|
||||
|
||||
if (length < 1 || length > DESKTOP_MESSAGE_SIZE_LIMIT) {
|
||||
// Discard the message.
|
||||
// TODO Crash the process.
|
||||
EsPipeRead(process->desktopRequestPipe, nullptr, length);
|
||||
continue;
|
||||
}
|
||||
|
||||
void *buffer = EsHeapAllocate(length, false);
|
||||
bytes = EsPipeRead(process->desktopRequestPipe, buffer, length);
|
||||
if (bytes != length) break; // Process has terminated or closed the pipe.
|
||||
|
||||
if (!buffer) {
|
||||
// The buffer could not be allocated, and the data read from the pipe was discarded.
|
||||
continue;
|
||||
}
|
||||
|
||||
EsBuffer response = { .canGrow = true };
|
||||
|
||||
EsMessageMutexAcquire();
|
||||
|
||||
if (!DesktopSyscall(embeddedWindowID, process, (uint8_t *) buffer, length, &response)) {
|
||||
// TODO Crash the process.
|
||||
EsPrint("Process %d running application '%z' had a fatal error (this usually means a permission check failed) with desktop request #%d.\n",
|
||||
process->id, process->application->cName, *(uint8_t *) buffer);
|
||||
}
|
||||
|
||||
EsMessageMutexRelease();
|
||||
|
||||
if (!response.error) {
|
||||
length = response.position;
|
||||
EsPipeWrite(process->desktopResponsePipe, &length, sizeof(length));
|
||||
EsPipeWrite(process->desktopResponsePipe, response.out, response.position);
|
||||
} else {
|
||||
length = 0;
|
||||
EsPipeWrite(process->desktopResponsePipe, &length, sizeof(length));
|
||||
}
|
||||
|
||||
EsHeapFree(response.out);
|
||||
EsHeapFree(buffer);
|
||||
}
|
||||
|
||||
EsMessageMutexAcquire();
|
||||
ApplicationProcessTerminated(process);
|
||||
EsMessageMutexRelease();
|
||||
}
|
||||
|
||||
ApplicationProcess *DesktopGetApplicationProcessForDesktop() {
|
||||
EsObjectID desktopProcessID = EsProcessGetID(ES_CURRENT_PROCESS);
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationProcesses.Length(); i++) {
|
||||
if (desktop.allApplicationProcesses[i]->id == desktopProcessID) {
|
||||
return desktop.allApplicationProcesses[i];
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool ApplicationInstanceStart(int64_t applicationID, _EsApplicationStartupInformation *startupInformation, ApplicationInstance *instance) {
|
||||
if (desktop.inShutdown) {
|
||||
return false;
|
||||
|
@ -1708,19 +1830,12 @@ bool ApplicationInstanceStart(int64_t applicationID, _EsApplicationStartupInform
|
|||
ApplicationProcess *process = application->singleProcess;
|
||||
|
||||
if (application->createInstance) {
|
||||
EsObjectID desktopProcessID = EsProcessGetID(ES_CURRENT_PROCESS);
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationProcesses.Length(); i++) {
|
||||
if (desktop.allApplicationProcesses[i]->id == desktopProcessID) {
|
||||
process = desktop.allApplicationProcesses[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
process = DesktopGetApplicationProcessForDesktop();
|
||||
|
||||
if (!process) {
|
||||
process = (ApplicationProcess *) EsHeapAllocate(sizeof(ApplicationProcess), true);
|
||||
process->handle = EsSyscall(ES_SYSCALL_HANDLE_SHARE, ES_CURRENT_PROCESS, ES_CURRENT_PROCESS, 0, 0);
|
||||
process->id = desktopProcessID;
|
||||
process->id = EsProcessGetID(ES_CURRENT_PROCESS);
|
||||
desktop.allApplicationProcesses.Add(process);
|
||||
}
|
||||
} else if (!process) {
|
||||
|
@ -1810,10 +1925,16 @@ bool ApplicationInstanceStart(int64_t applicationID, _EsApplicationStartupInform
|
|||
}
|
||||
}
|
||||
|
||||
EsHandle desktopRequestReadEnd, desktopRequestWriteEnd, desktopResponseReadEnd, desktopResponseWriteEnd;
|
||||
EsPipeCreate(&desktopRequestReadEnd, &desktopRequestWriteEnd);
|
||||
EsPipeCreate(&desktopResponseReadEnd, &desktopResponseWriteEnd);
|
||||
|
||||
EsBuffer buffer = { .canGrow = true };
|
||||
header.initialMountPointCount = initialMountPoints.Length();
|
||||
header.initialDeviceCount = initialDevices.Length();
|
||||
header.themeCursorData = theming.cursorData;
|
||||
header.desktopRequestPipe = desktopRequestWriteEnd;
|
||||
header.desktopResponsePipe = desktopResponseReadEnd;
|
||||
EsBufferWrite(&buffer, &header, sizeof(header));
|
||||
EsBufferWrite(&buffer, initialMountPoints.array, sizeof(EsMountPoint) * header.initialMountPointCount);
|
||||
EsBufferWrite(&buffer, initialDevices.array, sizeof(EsMessageDevice) * header.initialDeviceCount);
|
||||
|
@ -1822,6 +1943,10 @@ bool ApplicationInstanceStart(int64_t applicationID, _EsApplicationStartupInform
|
|||
handleModeDuplicateList.Add(0);
|
||||
handleDuplicateList.Add(header.themeCursorData);
|
||||
handleModeDuplicateList.Add(0);
|
||||
handleDuplicateList.Add(header.desktopRequestPipe);
|
||||
handleModeDuplicateList.Add(0);
|
||||
handleDuplicateList.Add(header.desktopResponsePipe);
|
||||
handleModeDuplicateList.Add(0);
|
||||
EsHeapFree(buffer.out);
|
||||
|
||||
arguments.handles = handleDuplicateList.array;
|
||||
|
@ -1835,6 +1960,9 @@ bool ApplicationInstanceStart(int64_t applicationID, _EsApplicationStartupInform
|
|||
if (settingsNode.handle) EsHandleClose(settingsNode.handle);
|
||||
if (arguments.data.systemData) EsHandleClose(arguments.data.systemData);
|
||||
|
||||
EsHandleClose(desktopResponseReadEnd);
|
||||
EsHandleClose(desktopRequestWriteEnd);
|
||||
|
||||
if (!ES_CHECK_ERROR(error)) {
|
||||
EsHandleClose(information.mainThread.handle);
|
||||
|
||||
|
@ -1842,8 +1970,17 @@ bool ApplicationInstanceStart(int64_t applicationID, _EsApplicationStartupInform
|
|||
process->handle = information.handle;
|
||||
process->id = information.pid;
|
||||
process->application = application;
|
||||
process->desktopResponsePipe = desktopResponseWriteEnd;
|
||||
process->desktopRequestPipe = desktopRequestReadEnd;
|
||||
desktop.allApplicationProcesses.Add(process);
|
||||
|
||||
EsThreadInformation information;
|
||||
EsThreadCreate(DesktopRequestThread, &information, process);
|
||||
EsHandleClose(information.handle);
|
||||
} else {
|
||||
EsHandleClose(desktopRequestReadEnd);
|
||||
EsHandleClose(desktopResponseWriteEnd);
|
||||
|
||||
ApplicationTemporaryDestroy(application);
|
||||
_EsApplicationStartupInformation s = {};
|
||||
s.data = CRASHED_TAB_INVALID_EXECUTABLE;
|
||||
|
@ -1931,15 +2068,11 @@ ApplicationInstance *ApplicationInstanceCreate(int64_t id, _EsApplicationStartup
|
|||
}
|
||||
}
|
||||
|
||||
ApplicationProcess *ApplicationProcessFindByPID(EsObjectID pid, bool removeIfFound = false) {
|
||||
ApplicationProcess *ApplicationProcessFindByPID(EsObjectID pid) {
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationProcesses.Length(); i++) {
|
||||
ApplicationProcess *process = desktop.allApplicationProcesses[i];
|
||||
|
||||
if (process->id == pid) {
|
||||
if (removeIfFound) {
|
||||
desktop.allApplicationProcesses.DeleteSwap(i);
|
||||
}
|
||||
|
||||
return process;
|
||||
}
|
||||
}
|
||||
|
@ -1994,48 +2127,6 @@ void ApplicationInstanceCrashed(EsMessage *message) {
|
|||
EsHandleClose(processHandle);
|
||||
}
|
||||
|
||||
void ApplicationProcessTerminated(EsObjectID pid) {
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
||||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||
|
||||
if (instance->process->id == pid) {
|
||||
EmbeddedWindowDestroyed(instance->embeddedWindowID);
|
||||
i--; // EmbeddedWindowDestroyed removes it from the array.
|
||||
}
|
||||
}
|
||||
|
||||
ApplicationProcess *process = ApplicationProcessFindByPID(pid, true /* remove from array */);
|
||||
|
||||
if (process) {
|
||||
InstalledApplication *application = process->application;
|
||||
|
||||
if (application) {
|
||||
if (application->singleProcess && application->singleProcess->id == pid) {
|
||||
application->singleProcess = nullptr;
|
||||
}
|
||||
|
||||
application->singleInstance = nullptr;
|
||||
ApplicationTemporaryDestroy(application);
|
||||
}
|
||||
|
||||
EsAssert(!process->instanceCount);
|
||||
EsHandleClose(process->handle);
|
||||
EsHeapFree(process);
|
||||
}
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.openDocuments.Count(); i++) {
|
||||
OpenDocument *document = &desktop.openDocuments[i];
|
||||
|
||||
if (document->currentWriter == pid) {
|
||||
document->currentWriter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!desktop.allApplicationProcesses.Length() && desktop.inShutdown) {
|
||||
EsEventSet(desktop.shutdownReadyEvent);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Document management:
|
||||
//////////////////////////////////////////////////////
|
||||
|
@ -2693,60 +2784,61 @@ void DesktopSetup() {
|
|||
desktop.setupDesktopUIComplete = true;
|
||||
}
|
||||
|
||||
void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
|
||||
ApplicationInstance *instance = ApplicationInstanceFindByWindowID(message->desktop.windowID);
|
||||
bool /* returns false on fatal error */ DesktopSyscall(EsObjectID windowID, ApplicationProcess *process, uint8_t *buffer, size_t bytes, EsBuffer *pipe) {
|
||||
EsMessageMutexCheck();
|
||||
EsAssert(process);
|
||||
|
||||
ApplicationInstance *instance = ApplicationInstanceFindByWindowID(windowID);
|
||||
InstalledApplication *application = process->application;
|
||||
|
||||
if (instance && instance->process != process) {
|
||||
EsPrint("DesktopSyscall - Process %d cannot operate on instance %d.\n", process->id, instance->embeddedWindowID);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buffer[0] == DESKTOP_MSG_START_APPLICATION) {
|
||||
InstalledApplication *application = ApplicationFindByPID(message->desktop.processID);
|
||||
if (~application->permissions & APPLICATION_PERMISSION_START_APPLICATION) return false;
|
||||
|
||||
if (application && (application->permissions & APPLICATION_PERMISSION_START_APPLICATION)) {
|
||||
// TODO Restricting what flags can be requested?
|
||||
EsBuffer b = { .in = buffer + 1, .bytes = message->desktop.bytes - 1 };
|
||||
EsApplicationStartupRequest request = {};
|
||||
EsBufferReadInto(&b, &request, sizeof(EsApplicationStartupRequest));
|
||||
request.filePath = (const char *) EsBufferRead(&b, request.filePathBytes);
|
||||
// TODO Restricting what flags can be requested?
|
||||
EsBuffer b = { .in = buffer + 1, .bytes = bytes - 1 };
|
||||
EsApplicationStartupRequest request = {};
|
||||
EsBufferReadInto(&b, &request, sizeof(EsApplicationStartupRequest));
|
||||
request.filePath = (const char *) EsBufferRead(&b, request.filePathBytes);
|
||||
|
||||
if (!b.error) {
|
||||
ContainerWindow *container = nullptr /* new container */;
|
||||
if (!b.error) {
|
||||
ContainerWindow *container = nullptr /* new container */;
|
||||
|
||||
if ((request.flags & ES_APPLICATION_STARTUP_IN_SAME_CONTAINER) && instance && instance->tab) {
|
||||
container = instance->tab->container;
|
||||
}
|
||||
|
||||
OpenDocumentWithApplication(&request, container);
|
||||
if ((request.flags & ES_APPLICATION_STARTUP_IN_SAME_CONTAINER) && instance && instance->tab) {
|
||||
container = instance->tab->container;
|
||||
}
|
||||
|
||||
OpenDocumentWithApplication(&request, container);
|
||||
}
|
||||
} else if (buffer[0] == DESKTOP_MSG_CREATE_CLIPBOARD_FILE && pipe) {
|
||||
EsHandle processHandle = EsProcessOpen(message->desktop.processID);
|
||||
EsHandle handle;
|
||||
char *path;
|
||||
size_t pathBytes;
|
||||
EsError error = TemporaryFileCreate(&handle, &path, &pathBytes, ES_FILE_WRITE);
|
||||
|
||||
if (processHandle) {
|
||||
EsHandle handle;
|
||||
char *path;
|
||||
size_t pathBytes;
|
||||
EsError error = TemporaryFileCreate(&handle, &path, &pathBytes, ES_FILE_WRITE);
|
||||
|
||||
if (error == ES_SUCCESS) {
|
||||
if (desktop.nextClipboardFile) {
|
||||
EsHandleClose(desktop.nextClipboardFile);
|
||||
}
|
||||
|
||||
desktop.nextClipboardFile = handle;
|
||||
desktop.nextClipboardProcessID = message->desktop.processID;
|
||||
|
||||
handle = EsSyscall(ES_SYSCALL_HANDLE_SHARE, handle, processHandle, 0, 0);
|
||||
|
||||
EsHeapFree(path);
|
||||
} else {
|
||||
handle = ES_INVALID_HANDLE;
|
||||
if (error == ES_SUCCESS) {
|
||||
if (desktop.nextClipboardFile) {
|
||||
EsHandleClose(desktop.nextClipboardFile);
|
||||
}
|
||||
|
||||
EsBufferWrite(pipe, &handle, sizeof(handle));
|
||||
EsBufferWrite(pipe, &error, sizeof(error));
|
||||
desktop.nextClipboardFile = handle;
|
||||
desktop.nextClipboardProcessID = process->id;
|
||||
|
||||
EsHandleClose(processHandle);
|
||||
handle = EsSyscall(ES_SYSCALL_HANDLE_SHARE, handle, process->handle, 0, 0);
|
||||
|
||||
EsHeapFree(path);
|
||||
} else {
|
||||
handle = ES_INVALID_HANDLE;
|
||||
}
|
||||
} else if (buffer[0] == DESKTOP_MSG_CLIPBOARD_PUT && message->desktop.bytes == sizeof(ClipboardInformation)
|
||||
&& desktop.nextClipboardFile && desktop.nextClipboardProcessID == message->desktop.processID) {
|
||||
|
||||
EsBufferWrite(pipe, &handle, sizeof(handle));
|
||||
EsBufferWrite(pipe, &error, sizeof(error));
|
||||
} else if (buffer[0] == DESKTOP_MSG_CLIPBOARD_PUT && bytes == sizeof(ClipboardInformation)
|
||||
&& desktop.nextClipboardFile && desktop.nextClipboardProcessID == process->id) {
|
||||
ClipboardInformation *information = (ClipboardInformation *) buffer;
|
||||
|
||||
if (information->error == ES_SUCCESS) {
|
||||
|
@ -2772,83 +2864,62 @@ void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
|
|||
desktop.nextClipboardFile = ES_INVALID_HANDLE;
|
||||
desktop.nextClipboardProcessID = 0;
|
||||
} else if (buffer[0] == DESKTOP_MSG_CLIPBOARD_GET && pipe) {
|
||||
EsHandle processHandle = EsProcessOpen(message->desktop.processID);
|
||||
|
||||
if (processHandle) {
|
||||
EsHandle fileHandle = desktop.clipboardFile
|
||||
? EsSyscall(ES_SYSCALL_HANDLE_SHARE, desktop.clipboardFile, processHandle, 1 /* ES_FILE_READ_SHARED */, 0) : ES_INVALID_HANDLE;
|
||||
EsBufferWrite(pipe, &desktop.clipboardInformation, sizeof(desktop.clipboardInformation));
|
||||
EsBufferWrite(pipe, &fileHandle, sizeof(fileHandle));
|
||||
EsHandleClose(processHandle);
|
||||
}
|
||||
EsHandle fileHandle = desktop.clipboardFile
|
||||
? EsSyscall(ES_SYSCALL_HANDLE_SHARE, desktop.clipboardFile, process->handle, 1 /* ES_FILE_READ_SHARED */, 0) : ES_INVALID_HANDLE;
|
||||
EsBufferWrite(pipe, &desktop.clipboardInformation, sizeof(desktop.clipboardInformation));
|
||||
EsBufferWrite(pipe, &fileHandle, sizeof(fileHandle));
|
||||
} else if (buffer[0] == DESKTOP_MSG_SYSTEM_CONFIGURATION_GET && pipe) {
|
||||
InstalledApplication *application = ApplicationFindByPID(message->desktop.processID);
|
||||
|
||||
ConfigurationWriteSectionsToBuffer("font", nullptr, false, pipe);
|
||||
ConfigurationWriteSectionsToBuffer(nullptr, "ui_fonts", false, pipe);
|
||||
|
||||
if (application && (application->permissions & APPLICATION_PERMISSION_ALL_FILES)) {
|
||||
if (application->permissions & APPLICATION_PERMISSION_ALL_FILES) {
|
||||
ConfigurationWriteSectionsToBuffer(nullptr, "paths", false, pipe);
|
||||
}
|
||||
} else if (buffer[0] == DESKTOP_MSG_REQUEST_SHUTDOWN) {
|
||||
InstalledApplication *application = ApplicationFindByPID(message->desktop.processID);
|
||||
|
||||
if (application && (application->permissions & APPLICATION_PERMISSION_SHUTDOWN)) {
|
||||
ShutdownModalCreate();
|
||||
}
|
||||
if (~application->permissions & APPLICATION_PERMISSION_SHUTDOWN) return false;
|
||||
ShutdownModalCreate();
|
||||
} else if (buffer[0] == DESKTOP_MSG_FILE_TYPES_GET && pipe) {
|
||||
InstalledApplication *application = ApplicationFindByPID(message->desktop.processID);
|
||||
if (~application->permissions & APPLICATION_PERMISSION_VIEW_FILE_TYPES) return false;
|
||||
ConfigurationWriteSectionsToBuffer("file_type", nullptr, false, pipe);
|
||||
} else if (buffer[0] == DESKTOP_MSG_ANNOUNCE_PATH_MOVED && bytes > 1 + sizeof(uintptr_t) * 2) {
|
||||
if (~application->permissions & APPLICATION_PERMISSION_ALL_FILES) return false;
|
||||
|
||||
if (application && (application->permissions & APPLICATION_PERMISSION_VIEW_FILE_TYPES)) {
|
||||
ConfigurationWriteSectionsToBuffer("file_type", nullptr, false, pipe);
|
||||
uintptr_t oldPathBytes, newPathBytes;
|
||||
EsMemoryCopy(&oldPathBytes, buffer + 1, sizeof(uintptr_t));
|
||||
EsMemoryCopy(&newPathBytes, buffer + 1 + sizeof(uintptr_t), sizeof(uintptr_t));
|
||||
|
||||
if (oldPathBytes >= 0x4000 || newPathBytes >= 0x4000
|
||||
|| oldPathBytes + newPathBytes + sizeof(uintptr_t) * 2 + 1 != bytes) {
|
||||
return true;
|
||||
}
|
||||
} else if (buffer[0] == DESKTOP_MSG_ANNOUNCE_PATH_MOVED && message->desktop.bytes > 1 + sizeof(uintptr_t) * 2) {
|
||||
InstalledApplication *application = ApplicationFindByPID(message->desktop.processID);
|
||||
|
||||
if (application && (application->permissions & APPLICATION_PERMISSION_ALL_FILES)) {
|
||||
uintptr_t oldPathBytes, newPathBytes;
|
||||
EsMemoryCopy(&oldPathBytes, buffer + 1, sizeof(uintptr_t));
|
||||
EsMemoryCopy(&newPathBytes, buffer + 1 + sizeof(uintptr_t), sizeof(uintptr_t));
|
||||
const char *oldPath = (const char *) buffer + 1 + sizeof(uintptr_t) * 2;
|
||||
const char *newPath = (const char *) buffer + 1 + sizeof(uintptr_t) * 2 + oldPathBytes;
|
||||
|
||||
if (oldPathBytes >= 0x4000 || newPathBytes >= 0x4000
|
||||
|| oldPathBytes + newPathBytes + sizeof(uintptr_t) * 2 + 1 != message->desktop.bytes) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char *oldPath = (const char *) buffer + 1 + sizeof(uintptr_t) * 2;
|
||||
const char *newPath = (const char *) buffer + 1 + sizeof(uintptr_t) * 2 + oldPathBytes;
|
||||
|
||||
InstanceAnnouncePathMoved(application, oldPath, oldPathBytes, newPath, newPathBytes);
|
||||
}
|
||||
InstanceAnnouncePathMoved(application, oldPath, oldPathBytes, newPath, newPathBytes);
|
||||
} else if (buffer[0] == DESKTOP_MSG_START_USER_TASK && pipe) {
|
||||
ApplicationProcess *process = ApplicationProcessFindByPID(message->desktop.processID);
|
||||
|
||||
if (!process || !process->instanceCount) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
InstalledApplication *application = process->application;
|
||||
|
||||
// HACK User tasks use an embedded window object for IPC.
|
||||
// This allows us to basically treat them like other instances.
|
||||
|
||||
EsHandle processHandle = EsProcessOpen(message->desktop.processID);
|
||||
EsHandle windowHandle = EsSyscall(ES_SYSCALL_WINDOW_CREATE, ES_WINDOW_NORMAL, 0, 0, 0);
|
||||
ApplicationInstance *instance = (ApplicationInstance *) EsHeapAllocate(sizeof(ApplicationInstance), true);
|
||||
bool added = false;
|
||||
|
||||
if (processHandle && windowHandle && instance) {
|
||||
if (windowHandle && instance) {
|
||||
added = desktop.allApplicationInstances.Add(instance);
|
||||
}
|
||||
|
||||
if (!processHandle || !windowHandle || !instance || !added) {
|
||||
if (processHandle) EsHandleClose(processHandle);
|
||||
if (!windowHandle || !instance || !added) {
|
||||
if (windowHandle) EsHandleClose(windowHandle);
|
||||
if (instance) EsHeapFree(instance);
|
||||
|
||||
EsHandle invalid = ES_INVALID_HANDLE;
|
||||
EsBufferWrite(pipe, &invalid, sizeof(invalid));
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
instance->title[0] = ' ';
|
||||
|
@ -2860,99 +2931,94 @@ void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
|
|||
instance->process->instanceCount++;
|
||||
instance->application = application;
|
||||
|
||||
EsHandle targetWindowHandle = EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, windowHandle, processHandle, 0, ES_WINDOW_PROPERTY_EMBED_OWNER);
|
||||
EsHandle targetWindowHandle = EsSyscall(ES_SYSCALL_WINDOW_SET_PROPERTY, windowHandle, process->handle, 0, ES_WINDOW_PROPERTY_EMBED_OWNER);
|
||||
EsBufferWrite(pipe, &targetWindowHandle, sizeof(targetWindowHandle));
|
||||
|
||||
desktop.allOngoingUserTasks.Add(instance);
|
||||
TaskBarTasksButtonUpdate();
|
||||
} else if (buffer[0] == DESKTOP_MSG_QUERY_OPEN_DOCUMENT) {
|
||||
InstalledApplication *application = ApplicationFindByPID(message->desktop.processID);
|
||||
if (~application->permissions & APPLICATION_PERMISSION_ALL_FILES) return false;
|
||||
|
||||
if (application && (application->permissions & APPLICATION_PERMISSION_ALL_FILES)) {
|
||||
EsObjectID id = 0;
|
||||
EsObjectID id = 0;
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.openDocuments.Count(); i++) {
|
||||
OpenDocument *document = &desktop.openDocuments[i];
|
||||
for (uintptr_t i = 0; i < desktop.openDocuments.Count(); i++) {
|
||||
OpenDocument *document = &desktop.openDocuments[i];
|
||||
|
||||
if (0 == EsStringCompare(document->path, document->pathBytes, (char *) buffer + 1, message->desktop.bytes - 1)) {
|
||||
id = document->id;
|
||||
if (0 == EsStringCompare(document->path, document->pathBytes, (char *) buffer + 1, bytes - 1)) {
|
||||
id = document->id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EsOpenDocumentInformation information;
|
||||
EsMemoryZero(&information, sizeof(information));
|
||||
|
||||
if (id) {
|
||||
information.isOpen = true;
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
||||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||
|
||||
if (instance->documentID == id) {
|
||||
information.isModified = instance->tab && (instance->tab->closeButton->customStyleState & THEME_STATE_CHECKED);
|
||||
information.applicationNameBytes = MinimumInteger(EsCStringLength(instance->application->cName),
|
||||
sizeof(information.applicationName));
|
||||
EsMemoryCopy(information.applicationName, instance->application->cName, information.applicationNameBytes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EsOpenDocumentInformation information;
|
||||
EsMemoryZero(&information, sizeof(information));
|
||||
|
||||
if (id) {
|
||||
information.isOpen = true;
|
||||
|
||||
for (uintptr_t i = 0; i < desktop.allApplicationInstances.Length(); i++) {
|
||||
ApplicationInstance *instance = desktop.allApplicationInstances[i];
|
||||
|
||||
if (instance->documentID == id) {
|
||||
information.isModified = instance->tab && (instance->tab->closeButton->customStyleState & THEME_STATE_CHECKED);
|
||||
information.applicationNameBytes = MinimumInteger(EsCStringLength(instance->application->cName),
|
||||
sizeof(information.applicationName));
|
||||
EsMemoryCopy(information.applicationName, instance->application->cName, information.applicationNameBytes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EsBufferWrite(pipe, &information, sizeof(information));
|
||||
}
|
||||
|
||||
EsBufferWrite(pipe, &information, sizeof(information));
|
||||
} else if (buffer[0] == DESKTOP_MSG_LIST_OPEN_DOCUMENTS) {
|
||||
InstalledApplication *application = ApplicationFindByPID(message->desktop.processID);
|
||||
if (~application->permissions & APPLICATION_PERMISSION_ALL_FILES) return false;
|
||||
|
||||
if (application && (application->permissions & APPLICATION_PERMISSION_ALL_FILES)) {
|
||||
size_t count = desktop.openDocuments.Count();
|
||||
EsBufferWrite(pipe, &count, sizeof(size_t));
|
||||
size_t count = desktop.openDocuments.Count();
|
||||
EsBufferWrite(pipe, &count, sizeof(size_t));
|
||||
|
||||
for (uintptr_t i = 0; i < count; i++) {
|
||||
OpenDocument *document = &desktop.openDocuments[i];
|
||||
EsBufferWrite(pipe, &document->pathBytes, sizeof(size_t));
|
||||
EsBufferWrite(pipe, document->path, document->pathBytes);
|
||||
}
|
||||
for (uintptr_t i = 0; i < count; i++) {
|
||||
OpenDocument *document = &desktop.openDocuments[i];
|
||||
EsBufferWrite(pipe, &document->pathBytes, sizeof(size_t));
|
||||
EsBufferWrite(pipe, document->path, document->pathBytes);
|
||||
}
|
||||
} else if (buffer[0] == DESKTOP_MSG_RUN_TEMPORARY_APPLICATION) {
|
||||
InstalledApplication *requestingApplication = ApplicationFindByPID(message->desktop.processID);
|
||||
InstalledApplication *requestingApplication = application;
|
||||
if (~requestingApplication->permissions & APPLICATION_PERMISSION_RUN_TEMPORARY_APPLICATION) return false;
|
||||
|
||||
if (requestingApplication && (requestingApplication->permissions & APPLICATION_PERMISSION_RUN_TEMPORARY_APPLICATION)) {
|
||||
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
|
||||
if (EsCStringLength(desktop.installedApplications[i]->cExecutable) == message->desktop.bytes - 1
|
||||
&& 0 == EsMemoryCompare(desktop.installedApplications[i]->cExecutable, buffer + 1, message->desktop.bytes - 1)) {
|
||||
ApplicationInstanceCreate(desktop.installedApplications[i]->id, nullptr, nullptr);
|
||||
return;
|
||||
}
|
||||
for (uintptr_t i = 0; i < desktop.installedApplications.Length(); i++) {
|
||||
if (EsCStringLength(desktop.installedApplications[i]->cExecutable) == bytes - 1
|
||||
&& 0 == EsMemoryCompare(desktop.installedApplications[i]->cExecutable, buffer + 1, bytes - 1)) {
|
||||
ApplicationInstanceCreate(desktop.installedApplications[i]->id, nullptr, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
InstalledApplication *application = (InstalledApplication *) EsHeapAllocate(sizeof(InstalledApplication), true);
|
||||
if (!application) return;
|
||||
application->temporary = true;
|
||||
application->hidden = true;
|
||||
application->useSingleProcess = true;
|
||||
application->cExecutable = (char *) EsHeapAllocate(message->desktop.bytes, false);
|
||||
if (!application->cExecutable) { EsHeapFree(application); return; }
|
||||
EsMemoryCopy(application->cExecutable, buffer + 1, message->desktop.bytes - 1);
|
||||
application->cExecutable[message->desktop.bytes - 1] = 0;
|
||||
static int64_t nextTemporaryID = -1;
|
||||
application->id = nextTemporaryID--;
|
||||
application->cName = (char *) EsHeapAllocate(32, false);
|
||||
if (!application->cName) { EsHeapFree(application->cExecutable); EsHeapFree(application); return; }
|
||||
for (int i = 1; i < 31; i++) application->cName[i] = (EsRandomU8() % 26) + 'a';
|
||||
application->cName[0] = '_', application->cName[31] = 0;
|
||||
EsHandle handle;
|
||||
EsError error = TemporaryFileCreate(&handle, &application->settingsPath, &application->settingsPathBytes, ES_NODE_DIRECTORY);
|
||||
if (error == ES_SUCCESS) EsHandleClose(handle);
|
||||
desktop.installedApplications.Add(application);
|
||||
ApplicationInstanceCreate(application->id, nullptr, nullptr);
|
||||
}
|
||||
|
||||
InstalledApplication *temporaryApplication = (InstalledApplication *) EsHeapAllocate(sizeof(InstalledApplication), true);
|
||||
if (!temporaryApplication) return true;
|
||||
temporaryApplication->temporary = true;
|
||||
temporaryApplication->hidden = true;
|
||||
temporaryApplication->useSingleProcess = true;
|
||||
temporaryApplication->cExecutable = (char *) EsHeapAllocate(bytes, false);
|
||||
if (!temporaryApplication->cExecutable) { EsHeapFree(temporaryApplication); return true; }
|
||||
EsMemoryCopy(temporaryApplication->cExecutable, buffer + 1, bytes - 1);
|
||||
temporaryApplication->cExecutable[bytes - 1] = 0;
|
||||
static int64_t nextTemporaryID = -1;
|
||||
temporaryApplication->id = nextTemporaryID--;
|
||||
temporaryApplication->cName = (char *) EsHeapAllocate(32, false);
|
||||
if (!temporaryApplication->cName) { EsHeapFree(temporaryApplication->cExecutable); EsHeapFree(temporaryApplication); return true; }
|
||||
for (int i = 1; i < 31; i++) temporaryApplication->cName[i] = (EsRandomU8() % 26) + 'a';
|
||||
temporaryApplication->cName[0] = '_', temporaryApplication->cName[31] = 0;
|
||||
EsHandle handle;
|
||||
EsError error = TemporaryFileCreate(&handle, &temporaryApplication->settingsPath, &temporaryApplication->settingsPathBytes, ES_NODE_DIRECTORY);
|
||||
if (error == ES_SUCCESS) EsHandleClose(handle);
|
||||
desktop.installedApplications.Add(temporaryApplication);
|
||||
ApplicationInstanceCreate(temporaryApplication->id, nullptr, nullptr);
|
||||
} else if ((buffer[0] == DESKTOP_MSG_SET_TITLE || buffer[0] == DESKTOP_MSG_SET_ICON) && instance) {
|
||||
if (buffer[0] == DESKTOP_MSG_SET_TITLE) {
|
||||
instance->titleBytes = EsStringFormat(instance->title, sizeof(instance->title), "%s",
|
||||
message->desktop.bytes - 1, buffer + 1);
|
||||
bytes - 1, buffer + 1);
|
||||
} else {
|
||||
if (message->desktop.bytes == 5) {
|
||||
if (bytes == 5) {
|
||||
EsMemoryCopy(&instance->iconID, buffer + 1, sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
|
@ -2968,11 +3034,11 @@ void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
|
|||
instance->tab->container->taskBarButton->Repaint(true);
|
||||
}
|
||||
}
|
||||
} else if (buffer[0] == DESKTOP_MSG_SET_MODIFIED && message->desktop.bytes == 2 && instance) {
|
||||
} else if (buffer[0] == DESKTOP_MSG_SET_MODIFIED && bytes == 2 && instance) {
|
||||
if (instance->tab) {
|
||||
EsButtonSetCheck(instance->tab->closeButton, buffer[1] ? ES_CHECK_CHECKED : ES_CHECK_UNCHECKED, false);
|
||||
}
|
||||
} else if (buffer[0] == DESKTOP_MSG_SET_PROGRESS && message->desktop.bytes == 1 + sizeof(double) && instance->isUserTask && instance) {
|
||||
} else if (buffer[0] == DESKTOP_MSG_SET_PROGRESS && bytes == 1 + sizeof(double) && instance->isUserTask && instance) {
|
||||
double progress;
|
||||
EsMemoryCopy(&progress, buffer + 1, sizeof(double));
|
||||
|
||||
|
@ -2982,10 +3048,10 @@ void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
|
|||
EsElementRepaint(desktop.tasksButton);
|
||||
}
|
||||
} else if (buffer[0] == DESKTOP_MSG_REQUEST_SAVE && instance) {
|
||||
ApplicationInstanceRequestSave(instance, (const char *) buffer + 1, message->desktop.bytes - 1, false);
|
||||
ApplicationInstanceRequestSave(instance, (const char *) buffer + 1, bytes - 1, false);
|
||||
} else if (buffer[0] == DESKTOP_MSG_RENAME && instance) {
|
||||
const char *newName = (const char *) buffer + 1;
|
||||
size_t newNameBytes = message->desktop.bytes - 1;
|
||||
size_t newNameBytes = bytes - 1;
|
||||
OpenDocument *document = desktop.openDocuments.Get(&instance->documentID);
|
||||
|
||||
if (!instance->documentID) {
|
||||
|
@ -3033,7 +3099,10 @@ void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe) {
|
|||
}
|
||||
} else {
|
||||
EsPrint("DesktopSyscall - Received unhandled message %d.\n", buffer[0]);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EmbeddedWindowDestroyed(EsObjectID id) {
|
||||
|
@ -3063,25 +3132,9 @@ void DesktopSendMessage(EsMessage *message) {
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
if (buffer) {
|
||||
EsConstantBufferRead(message->desktop.buffer, buffer);
|
||||
EsBuffer pipe = { .canGrow = true };
|
||||
DesktopSyscall(message, buffer, &pipe);
|
||||
if (message->desktop.pipe) EsPipeWrite(message->desktop.pipe, pipe.out, pipe.position);
|
||||
EsHeapFree(pipe.out);
|
||||
EsHeapFree(buffer);
|
||||
}
|
||||
|
||||
EsHandleClose(message->desktop.buffer);
|
||||
if (message->desktop.pipe) EsHandleClose(message->desktop.pipe);
|
||||
EmbeddedWindowDestroyed(message->embeddedWindowDestroyedID);
|
||||
} else if (message->type == ES_MSG_APPLICATION_CRASH) {
|
||||
ApplicationInstanceCrashed(message);
|
||||
} else if (message->type == ES_MSG_PROCESS_TERMINATED) {
|
||||
ApplicationProcessTerminated(message->crash.pid);
|
||||
} else if (message->type == ES_MSG_REGISTER_FILE_SYSTEM) {
|
||||
EsHandle rootDirectory = message->registerFileSystem.rootDirectory;
|
||||
|
||||
|
|
|
@ -856,8 +856,6 @@ private enum EsSyscallType {
|
|||
ES_SYSCALL_WINDOW_SET_CURSOR
|
||||
ES_SYSCALL_WINDOW_SET_PROPERTY
|
||||
|
||||
ES_SYSCALL_MESSAGE_DESKTOP
|
||||
|
||||
// IO.
|
||||
|
||||
ES_SYSCALL_NODE_OPEN
|
||||
|
@ -1782,12 +1780,6 @@ struct EsMessageProcessCrash {
|
|||
uintptr_t pid;
|
||||
};
|
||||
|
||||
struct EsMessageDesktop {
|
||||
EsObjectID windowID, processID;
|
||||
EsHandle buffer, pipe;
|
||||
size_t bytes;
|
||||
};
|
||||
|
||||
struct EsMessageEyedrop {
|
||||
uint32_t color;
|
||||
bool cancelled;
|
||||
|
@ -1892,13 +1884,13 @@ struct EsMessage {
|
|||
// Internal messages:
|
||||
void *_argument;
|
||||
EsMessageProcessCrash crash;
|
||||
EsMessageDesktop desktop;
|
||||
EsMessageEyedrop eyedrop;
|
||||
EsMessageCreateInstance createInstance;
|
||||
EsMessageTabOperation tabOperation;
|
||||
EsMessageRegisterFileSystem registerFileSystem;
|
||||
EsMessageUnregisterFileSystem unregisterFileSystem;
|
||||
EsMessageDevice device;
|
||||
EsObjectID embeddedWindowDestroyedID;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -2247,7 +2239,7 @@ function bool EsMouseIsMiddleHeld();
|
|||
// Pipes.
|
||||
|
||||
function void EsPipeCreate(EsHandle *readEnd, EsHandle *writeEnd);
|
||||
function size_t EsPipeRead(EsHandle pipe, void *buffer, size_t bytes);
|
||||
function size_t EsPipeRead(EsHandle pipe, void *buffer, size_t bytes); // If buffer is null, then the data is discarded.
|
||||
function size_t EsPipeWrite(EsHandle pipe, const void *buffer, size_t bytes);
|
||||
|
||||
// Synchronisation and timing.
|
||||
|
|
|
@ -352,6 +352,7 @@ struct SystemStartupDataHeader {
|
|||
size_t initialMountPointCount;
|
||||
size_t initialDeviceCount;
|
||||
uintptr_t themeCursorData;
|
||||
uintptr_t desktopRequestPipe, desktopResponsePipe;
|
||||
};
|
||||
|
||||
#ifdef KERNEL
|
||||
|
@ -397,9 +398,9 @@ extern "C" void *EsBufferWrite(EsBuffer *buffer, const void *source, size_t writ
|
|||
#define ES_THEME_CURSORS_WIDTH (264)
|
||||
#define ES_THEME_CURSORS_HEIGHT (128)
|
||||
|
||||
/* Desktop messages: */
|
||||
/* Messages sent from Kernel to Desktop: */
|
||||
#define ES_MSG_EMBEDDED_WINDOW_DESTROYED ((EsMessageType) (ES_MSG_SYSTEM_START + 0x001))
|
||||
#define ES_MSG_DESKTOP ((EsMessageType) (ES_MSG_SYSTEM_START + 0x005))
|
||||
#define ES_MSG_APPLICATION_CRASH ((EsMessageType) (ES_MSG_SYSTEM_START + 0x002))
|
||||
|
||||
/* Messages sent from Desktop to application instances: */
|
||||
#define ES_MSG_TAB_INSPECT_UI ((EsMessageType) (ES_MSG_SYSTEM_START + 0x101))
|
||||
|
@ -409,16 +410,12 @@ extern "C" void *EsBufferWrite(EsBuffer *buffer, const void *source, size_t writ
|
|||
#define ES_MSG_INSTANCE_DOCUMENT_UPDATED ((EsMessageType) (ES_MSG_SYSTEM_START + 0x105))
|
||||
#define ES_MSG_INSTANCE_RENAME_RESPONSE ((EsMessageType) (ES_MSG_SYSTEM_START + 0x107))
|
||||
|
||||
/* Debugger messages: */
|
||||
#define ES_MSG_APPLICATION_CRASH ((EsMessageType) (ES_MSG_SYSTEM_START + 0x201))
|
||||
#define ES_MSG_PROCESS_TERMINATED ((EsMessageType) (ES_MSG_SYSTEM_START + 0x202))
|
||||
|
||||
/* Misc messages: */
|
||||
#define ES_MSG_EYEDROP_REPORT ((EsMessageType) (ES_MSG_SYSTEM_START + 0x301))
|
||||
#define ES_MSG_TIMER ((EsMessageType) (ES_MSG_SYSTEM_START + 0x302))
|
||||
#define ES_MSG_PING ((EsMessageType) (ES_MSG_SYSTEM_START + 0x303)) /* Sent by Desktop to check processes are processing messages. */
|
||||
#define ES_MSG_WAKEUP ((EsMessageType) (ES_MSG_SYSTEM_START + 0x304)) /* Sent to wakeup the message thread, so that it can process locally posted messages. */
|
||||
#define ES_MSG_INSTANCE_OPEN_DELAYED ((EsMessageType) (ES_MSG_SYSTEM_START + 0x305))
|
||||
#define ES_MSG_EYEDROP_REPORT ((EsMessageType) (ES_MSG_SYSTEM_START + 0x201))
|
||||
#define ES_MSG_TIMER ((EsMessageType) (ES_MSG_SYSTEM_START + 0x202))
|
||||
#define ES_MSG_PING ((EsMessageType) (ES_MSG_SYSTEM_START + 0x203)) /* Sent by Desktop to check processes are processing messages. */
|
||||
#define ES_MSG_WAKEUP ((EsMessageType) (ES_MSG_SYSTEM_START + 0x204)) /* Sent to wakeup the message thread, so that it can process locally posted messages. */
|
||||
#define ES_MSG_INSTANCE_OPEN_DELAYED ((EsMessageType) (ES_MSG_SYSTEM_START + 0x205))
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -749,36 +749,36 @@ size_t EsGameControllerStatePoll(EsGameControllerState *buffer) {
|
|||
return EsSyscall(ES_SYSCALL_GAME_CONTROLLER_STATE_POLL, (uintptr_t) buffer, 0, 0, 0);
|
||||
}
|
||||
|
||||
void DesktopSyscall(EsMessage *message, uint8_t *buffer, EsBuffer *pipe);
|
||||
bool DesktopSyscall(EsObjectID windowID, struct ApplicationProcess *process, uint8_t *buffer, size_t bytes, EsBuffer *pipe);
|
||||
struct ApplicationProcess *DesktopGetApplicationProcessForDesktop();
|
||||
|
||||
void MessageDesktop(void *message, size_t messageBytes, EsHandle embeddedWindow = ES_INVALID_HANDLE, EsBuffer *responseBuffer = nullptr) {
|
||||
static EsMutex messageDesktopMutex = {};
|
||||
|
||||
EsObjectID embeddedWindowID = embeddedWindow ? EsSyscall(ES_SYSCALL_WINDOW_GET_ID, embeddedWindow, 0, 0, 0) : 0;
|
||||
|
||||
EsMutexAcquire(&messageDesktopMutex);
|
||||
|
||||
if (api.startupInformation->isDesktop) {
|
||||
EsMessage m = {};
|
||||
m.type = ES_MSG_DESKTOP;
|
||||
m.desktop.windowID = embeddedWindow ? EsSyscall(ES_SYSCALL_WINDOW_GET_ID, embeddedWindow, 0, 0, 0) : 0;
|
||||
m.desktop.processID = EsProcessGetID(ES_CURRENT_PROCESS);
|
||||
m.desktop.bytes = messageBytes;
|
||||
DesktopSyscall(&m, (uint8_t *) message, responseBuffer);
|
||||
struct ApplicationProcess *process = DesktopGetApplicationProcessForDesktop();
|
||||
bool noFatalErrors = DesktopSyscall(embeddedWindowID, process, (uint8_t *) message, messageBytes, responseBuffer);
|
||||
EsAssert(noFatalErrors);
|
||||
} else {
|
||||
EsHandle pipeRead = ES_INVALID_HANDLE, pipeWrite = ES_INVALID_HANDLE;
|
||||
if (messageBytes <= DESKTOP_MESSAGE_SIZE_LIMIT) {
|
||||
uint32_t length = messageBytes;
|
||||
EsPipeWrite(api.desktopRequestPipe, &length, sizeof(length));
|
||||
EsPipeWrite(api.desktopRequestPipe, &embeddedWindowID, sizeof(embeddedWindowID));
|
||||
EsPipeWrite(api.desktopRequestPipe, message, messageBytes);
|
||||
EsPipeRead(api.desktopResponsePipe, &length, sizeof(length));
|
||||
EsAssert((length != 0) == (responseBuffer != 0));
|
||||
|
||||
if (responseBuffer) {
|
||||
EsPipeCreate(&pipeRead, &pipeWrite);
|
||||
}
|
||||
|
||||
EsSyscall(ES_SYSCALL_MESSAGE_DESKTOP, (uintptr_t) message, messageBytes, embeddedWindow, pipeWrite);
|
||||
|
||||
if (responseBuffer) {
|
||||
char buffer[4096];
|
||||
EsHandleClose(pipeWrite);
|
||||
|
||||
while (true) {
|
||||
size_t bytesRead = EsPipeRead(pipeRead, buffer, sizeof(buffer));
|
||||
while (length) {
|
||||
char buffer[4096];
|
||||
size_t bytesRead = EsPipeRead(api.desktopResponsePipe, buffer, sizeof(buffer) > length ? length : sizeof(buffer));
|
||||
if (!bytesRead) break;
|
||||
EsBufferWrite(responseBuffer, buffer, bytesRead);
|
||||
length -= bytesRead;
|
||||
}
|
||||
|
||||
EsHandleClose(pipeRead);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -786,6 +786,8 @@ void MessageDesktop(void *message, size_t messageBytes, EsHandle embeddedWindow
|
|||
responseBuffer->bytes = responseBuffer->position;
|
||||
responseBuffer->position = 0;
|
||||
}
|
||||
|
||||
EsMutexRelease(&messageDesktopMutex);
|
||||
}
|
||||
|
||||
struct ClipboardInformation {
|
||||
|
|
|
@ -607,14 +607,14 @@ size_t Pipe::Access(void *_buffer, size_t bytes, bool write, bool user) {
|
|||
// EsPrint("\tunread: %d; wp: %d\n", unreadData, writePosition);
|
||||
// EsPrint("\t%d, %d, %d, %d, %d\n", spaceAvailable, spaceAvailableRight, toWrite, toWriteRight, toWriteLeft);
|
||||
|
||||
EsMemoryCopy((uint8_t *) buffer + writePosition, _buffer, toWriteRight);
|
||||
EsMemoryCopy((uint8_t *) buffer, (uint8_t *) _buffer + toWriteRight, toWriteLeft);
|
||||
if (_buffer) EsMemoryCopy((uint8_t *) buffer + writePosition, _buffer, toWriteRight);
|
||||
if (_buffer) EsMemoryCopy((uint8_t *) buffer, (uint8_t *) _buffer + toWriteRight, toWriteLeft);
|
||||
|
||||
writePosition += toWrite;
|
||||
writePosition %= PIPE_BUFFER_SIZE;
|
||||
unreadData += toWrite;
|
||||
bytes -= toWrite;
|
||||
_buffer = (uint8_t *) _buffer + toWrite;
|
||||
if (_buffer) _buffer = (uint8_t *) _buffer + toWrite;
|
||||
amount += toWrite;
|
||||
|
||||
KEventSet(&canRead, true);
|
||||
|
@ -640,14 +640,14 @@ size_t Pipe::Access(void *_buffer, size_t bytes, bool write, bool user) {
|
|||
// EsPrint("\tunread: %d; rp: %d\n", unreadData, readPosition);
|
||||
// EsPrint("\t%d, %d, %d, %d, %d\n", dataAvailable, spaceAvailableRight, toRead, toReadRight, toReadLeft);
|
||||
|
||||
EsMemoryCopy(_buffer, (uint8_t *) buffer + readPosition, toReadRight);
|
||||
EsMemoryCopy((uint8_t *) _buffer + toReadRight, (uint8_t *) buffer, toReadLeft);
|
||||
if (_buffer) EsMemoryCopy(_buffer, (uint8_t *) buffer + readPosition, toReadRight);
|
||||
if (_buffer) EsMemoryCopy((uint8_t *) _buffer + toReadRight, (uint8_t *) buffer, toReadLeft);
|
||||
|
||||
readPosition += toRead;
|
||||
readPosition %= PIPE_BUFFER_SIZE;
|
||||
unreadData -= toRead;
|
||||
bytes -= toRead;
|
||||
_buffer = (uint8_t *) _buffer + toRead;
|
||||
if (_buffer) _buffer = (uint8_t *) _buffer + toRead;
|
||||
amount += toRead;
|
||||
|
||||
KEventSet(&canWrite, true);
|
||||
|
|
|
@ -549,15 +549,6 @@ void ProcessKill(Process *process) {
|
|||
// Don't actually deallocate it yet though; that is done on an async task queued by ProcessRemove.
|
||||
// This must be destroyed after the handle table!
|
||||
MMSpaceDestroy(process->vmm);
|
||||
|
||||
// Tell Desktop the process has terminated.
|
||||
if (!scheduler.shutdown) {
|
||||
_EsMessageWithObject m;
|
||||
EsMemoryZero(&m, sizeof(m));
|
||||
m.message.type = ES_MSG_PROCESS_TERMINATED;
|
||||
m.message.crash.pid = process->id;
|
||||
DesktopSendMessage(&m);
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadKill(KAsyncTask *task) {
|
||||
|
@ -1089,6 +1080,8 @@ void ProcessPause(Process *process, bool resume) {
|
|||
}
|
||||
|
||||
void ProcessCrash(Process *process, EsCrashReason *crashReason) {
|
||||
EsAssert(process == GetCurrentThread()->process); // TODO Test this function when crashing other processes!
|
||||
|
||||
if (process == kernelProcess) {
|
||||
KernelPanic("ProcessCrash - Kernel process has crashed (%d).\n", crashReason->errorCode);
|
||||
}
|
||||
|
@ -1097,36 +1090,34 @@ void ProcessCrash(Process *process, EsCrashReason *crashReason) {
|
|||
KernelPanic("ProcessCrash - A critical process has crashed (%d).\n", crashReason->errorCode);
|
||||
}
|
||||
|
||||
if (GetCurrentThread()->process != process) {
|
||||
KernelPanic("ProcessCrash - Attempt to crash process from different process.\n");
|
||||
}
|
||||
bool pauseProcess = false;
|
||||
|
||||
KMutexAcquire(&process->crashMutex);
|
||||
|
||||
if (process->crashed) {
|
||||
KMutexRelease(&process->crashMutex);
|
||||
return;
|
||||
}
|
||||
if (!process->crashed) {
|
||||
process->crashed = true;
|
||||
pauseProcess = true;
|
||||
|
||||
process->crashed = true;
|
||||
KernelLog(LOG_ERROR, "Scheduler", "process crashed", "Process %x has crashed! (%d)\n", process, crashReason->errorCode);
|
||||
|
||||
KernelLog(LOG_ERROR, "Scheduler", "process crashed", "Process %x has crashed! (%d)\n", process, crashReason->errorCode);
|
||||
EsMemoryCopy(&process->crashReason, crashReason, sizeof(EsCrashReason));
|
||||
|
||||
EsMemoryCopy(&process->crashReason, crashReason, sizeof(EsCrashReason));
|
||||
|
||||
if (!scheduler.shutdown) {
|
||||
_EsMessageWithObject m;
|
||||
EsMemoryZero(&m, sizeof(m));
|
||||
m.message.type = ES_MSG_APPLICATION_CRASH;
|
||||
m.message.crash.pid = process->id;
|
||||
EsMemoryCopy(&m.message.crash.reason, crashReason, sizeof(EsCrashReason));
|
||||
DesktopSendMessage(&m);
|
||||
if (!scheduler.shutdown) {
|
||||
_EsMessageWithObject m;
|
||||
EsMemoryZero(&m, sizeof(m));
|
||||
m.message.type = ES_MSG_APPLICATION_CRASH;
|
||||
m.message.crash.pid = process->id;
|
||||
EsMemoryCopy(&m.message.crash.reason, crashReason, sizeof(EsCrashReason));
|
||||
DesktopSendMessage(&m);
|
||||
}
|
||||
}
|
||||
|
||||
KMutexRelease(&process->crashMutex);
|
||||
|
||||
// TODO Shouldn't this be done before sending the desktop message?
|
||||
ProcessPause(GetCurrentThread()->process, false);
|
||||
if (pauseProcess) {
|
||||
// TODO Shouldn't this be done before sending the desktop message?
|
||||
ProcessPause(process, false);
|
||||
}
|
||||
}
|
||||
|
||||
Thread *Scheduler::PickThread(CPULocalStorage *local) {
|
||||
|
|
|
@ -1367,45 +1367,6 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_SCREEN_WORK_AREA_GET) {
|
|||
SYSCALL_RETURN(ES_SUCCESS, false);
|
||||
}
|
||||
|
||||
SYSCALL_IMPLEMENT(ES_SYSCALL_MESSAGE_DESKTOP) {
|
||||
char *buffer;
|
||||
if (argument1 > DESKTOP_MESSAGE_SIZE_LIMIT) SYSCALL_RETURN(ES_ERROR_INSUFFICIENT_RESOURCES, false);
|
||||
SYSCALL_READ_HEAP(buffer, argument0, argument1);
|
||||
|
||||
SYSCALL_HANDLE_2(argument2, (KernelObjectType) (KERNEL_OBJECT_EMBEDDED_WINDOW | KERNEL_OBJECT_NONE), _window);
|
||||
SYSCALL_HANDLE_2(argument3, (KernelObjectType) (KERNEL_OBJECT_PIPE | KERNEL_OBJECT_NONE), _pipe);
|
||||
|
||||
EmbeddedWindow *window = (EmbeddedWindow *) _window.object;
|
||||
Pipe *pipe = (Pipe *) _pipe.object;
|
||||
|
||||
if (pipe && (~_pipe.flags & PIPE_WRITER)) {
|
||||
SYSCALL_RETURN(ES_FATAL_ERROR_INCORRECT_FILE_ACCESS, true);
|
||||
}
|
||||
|
||||
if (!scheduler.shutdown) {
|
||||
if (pipe) {
|
||||
OpenHandleToObject(pipe, KERNEL_OBJECT_PIPE, PIPE_WRITER);
|
||||
}
|
||||
|
||||
void *constantBuffer = ConstantBufferCreate(buffer, argument1);
|
||||
|
||||
_EsMessageWithObject m = {};
|
||||
m.message.type = ES_MSG_DESKTOP;
|
||||
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 ? DesktopOpenHandle(pipe, PIPE_WRITER, KERNEL_OBJECT_PIPE) : ES_INVALID_HANDLE;
|
||||
|
||||
if (!m.message.desktop.buffer || !DesktopSendMessage(&m)) {
|
||||
DesktopCloseHandle(m.message.desktop.buffer);
|
||||
DesktopCloseHandle(m.message.desktop.pipe);
|
||||
}
|
||||
}
|
||||
|
||||
SYSCALL_RETURN(ES_SUCCESS, false);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_POSIX_SUBSYSTEM
|
||||
SYSCALL_IMPLEMENT(ES_SYSCALL_POSIX) {
|
||||
SYSCALL_PERMISSION(ES_PERMISSION_POSIX_SUBSYSTEM);
|
||||
|
@ -1457,8 +1418,14 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_PIPE_READ) {
|
|||
SYSCALL_HANDLE_2(argument0, KERNEL_OBJECT_PIPE, _pipe);
|
||||
Pipe *pipe = (Pipe *) _pipe.object;
|
||||
if ((~_pipe.flags & PIPE_READER)) SYSCALL_RETURN(ES_FATAL_ERROR_INCORRECT_FILE_ACCESS, true);
|
||||
SYSCALL_BUFFER(argument1, argument2, 2, false);
|
||||
SYSCALL_RETURN(pipe->Access((void *) argument1, argument2, false, true), false);
|
||||
|
||||
if (argument1) {
|
||||
SYSCALL_BUFFER(argument1, argument2, 2, false);
|
||||
SYSCALL_RETURN(pipe->Access((void *) argument1, argument2, false, true), false);
|
||||
} else {
|
||||
// Discard data.
|
||||
SYSCALL_RETURN(pipe->Access(nullptr, argument2, false, true), false);
|
||||
}
|
||||
}
|
||||
|
||||
SYSCALL_IMPLEMENT(ES_SYSCALL_PIPE_WRITE) {
|
||||
|
|
|
@ -936,7 +936,7 @@ void EmbeddedWindow::Close() {
|
|||
SetEmbedOwner(nullptr);
|
||||
m.object = nullptr;
|
||||
m.message.type = ES_MSG_EMBEDDED_WINDOW_DESTROYED;
|
||||
m.message.desktop.windowID = id;
|
||||
m.message.embeddedWindowDestroyedID = id;
|
||||
DesktopSendMessage(&m);
|
||||
|
||||
if (container && container->embed == this) {
|
||||
|
|
Loading…
Reference in New Issue