use pipe for desktop requests

This commit is contained in:
nakst 2022-01-07 08:53:25 +00:00
parent afed49f30b
commit 9e610bd928
9 changed files with 360 additions and 354 deletions

View File

@ -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));

View File

@ -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;

View File

@ -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.

View File

@ -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

View File

@ -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 {

View File

@ -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);

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {