public KernelResult EnqueueRequest(KSessionRequest request) { if (_parent.ClientSession.State != ChannelState.Open) { return(KernelResult.PortRemoteClosed); } if (request.AsyncEvent == null) { if (request.ClientThread.ShallBeTerminated || request.ClientThread.SchedFlags == ThreadSchedState.TerminationPending) { return(KernelResult.ThreadTerminating); } request.ClientThread.Reschedule(ThreadSchedState.Paused); } _requests.AddLast(request); if (_requests.Count == 1) { Signal(); } return(KernelResult.Success); }
public KernelResult SendAsyncRequest(KWritableEvent asyncEvent, ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0) { KThread currentThread = KernelStatic.GetCurrentThread(); KSessionRequest request = new KSessionRequest(currentThread, customCmdBuffAddr, customCmdBuffSize, asyncEvent); KernelContext.CriticalSection.Enter(); KernelResult result = _parent.ServerSession.EnqueueRequest(request); KernelContext.CriticalSection.Leave(); return(result); }
private void SendResultToAsyncRequestClient(KSessionRequest request, KernelResult result) { KProcess clientProcess = request.ClientThread.Owner; ulong address = clientProcess.MemoryManager.GetDramAddressFromVa(request.CustomCmdBuffAddr); KernelContext.Memory.Write <ulong>(address, 0); KernelContext.Memory.Write(address + 8, (int)result); clientProcess.MemoryManager.UnborrowIpcBuffer( request.CustomCmdBuffAddr, request.CustomCmdBuffSize); request.AsyncEvent.Signal(); }
private void WakeClientThread(KSessionRequest request, KernelResult result) { // Wait client thread waiting for a response for the given request. if (request.AsyncEvent != null) { SendResultToAsyncRequestClient(request, result); } else { KernelContext.CriticalSection.Enter(); WakeAndSetResult(request.ClientThread, result); KernelContext.CriticalSection.Leave(); } }
private void SendResultToAsyncRequestClient(KSessionRequest request, KernelResult result) { KProcess clientProcess = request.ClientThread.Owner; if (result != KernelResult.Success) { ulong address = request.CustomCmdBuffAddr; clientProcess.CpuMemory.Write <ulong>(address, 0); clientProcess.CpuMemory.Write(address + 8, (int)result); } clientProcess.MemoryManager.UnborrowIpcBuffer(request.CustomCmdBuffAddr, request.CustomCmdBuffSize); request.AsyncEvent.Signal(); }
private void CancelRequest(KSessionRequest request, KernelResult result) { KProcess clientProcess = request.ClientThread.Owner; KProcess serverProcess = request.ServerProcess; KernelResult unmapResult = KernelResult.Success; if (serverProcess != null) { unmapResult = request.BufferDescriptorTable.UnmapServerBuffers(serverProcess.MemoryManager); } if (unmapResult == KernelResult.Success) { request.BufferDescriptorTable.RestoreClientBuffers(clientProcess.MemoryManager); } WakeClientThread(request, result); }
private bool DequeueRequest(out KSessionRequest request) { request = null; KernelContext.CriticalSection.Enter(); bool hasRequest = _requests.First != null; if (hasRequest) { request = _requests.First.Value; _requests.RemoveFirst(); } KernelContext.CriticalSection.Leave(); return(hasRequest); }
public KernelResult SendSyncRequest(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0) { KThread currentThread = KernelStatic.GetCurrentThread(); KSessionRequest request = new KSessionRequest(currentThread, customCmdBuffAddr, customCmdBuffSize); KernelContext.CriticalSection.Enter(); currentThread.SignaledObj = null; currentThread.ObjSyncResult = KernelResult.Success; KernelResult result = _parent.ServerSession.EnqueueRequest(request); KernelContext.CriticalSection.Leave(); if (result == KernelResult.Success) { result = currentThread.ObjSyncResult; } return(result); }
private IEnumerable <KSessionRequest> IterateWithRemovalOfAllRequests() { KernelContext.CriticalSection.Enter(); if (_activeRequest != null) { KSessionRequest request = _activeRequest; _activeRequest = null; KernelContext.CriticalSection.Leave(); yield return(request); } else { KernelContext.CriticalSection.Leave(); } while (DequeueRequest(out KSessionRequest request)) { yield return(request); } }
public KernelResult Reply(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0) { KThread serverThread = KernelContext.Scheduler.GetCurrentThread(); KProcess serverProcess = serverThread.Owner; KernelContext.CriticalSection.Enter(); if (_activeRequest == null) { KernelContext.CriticalSection.Leave(); return(KernelResult.InvalidState); } KSessionRequest request = _activeRequest; _activeRequest = null; if (_requests.Count != 0) { Signal(); } KernelContext.CriticalSection.Leave(); KThread clientThread = request.ClientThread; KProcess clientProcess = clientThread.Owner; Message clientMsg = new Message(request); Message serverMsg = new Message(serverThread, customCmdBuffAddr, customCmdBuffSize); MessageHeader clientHeader = GetClientMessageHeader(clientMsg); MessageHeader serverHeader = GetServerMessageHeader(serverMsg); KernelResult clientResult = KernelResult.Success; KernelResult serverResult = KernelResult.Success; void CleanUpForError() { CloseAllHandles(clientMsg, serverHeader, clientProcess); CancelRequest(request, clientResult); } if (clientHeader.ReceiveListType < 2 && clientHeader.ReceiveListOffset > clientMsg.Size) { CleanUpForError(); return(KernelResult.InvalidCombination); } else if (clientHeader.ReceiveListType == 2 && clientHeader.ReceiveListOffset + 8 > clientMsg.Size) { CleanUpForError(); return(KernelResult.InvalidCombination); } else if (clientHeader.ReceiveListType > 2 && clientHeader.ReceiveListType * 8 - 0x10 + clientHeader.ReceiveListOffset > clientMsg.Size) { CleanUpForError(); return(KernelResult.InvalidCombination); } if (clientHeader.ReceiveListOffsetInWords < clientHeader.MessageSizeInWords) { CleanUpForError(); return(KernelResult.InvalidCombination); } if (serverHeader.MessageSizeInWords * 4 > clientMsg.Size) { CleanUpForError(); return(KernelResult.CmdBufferTooSmall); } if (serverHeader.SendBuffersCount != 0 || serverHeader.ReceiveBuffersCount != 0 || serverHeader.ExchangeBuffersCount != 0) { CleanUpForError(); return(KernelResult.InvalidCombination); } // Read receive list. ulong[] receiveList = GetReceiveList( clientMsg, clientHeader.ReceiveListType, clientHeader.ReceiveListOffset); // Copy receive and exchange buffers. clientResult = request.BufferDescriptorTable.CopyBuffersToClient(clientProcess.MemoryManager); if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } // Copy header. KernelContext.Memory.Write(clientMsg.DramAddress + 0, serverHeader.Word0); KernelContext.Memory.Write(clientMsg.DramAddress + 4, serverHeader.Word1); // Copy handles. uint offset; if (serverHeader.HasHandles) { offset = 3; KernelContext.Memory.Write(clientMsg.DramAddress + 8, serverHeader.Word2); if (serverHeader.HasPid) { KernelContext.Memory.Write(clientMsg.DramAddress + offset * 4, serverProcess.Pid); offset += 2; } for (int index = 0; index < serverHeader.CopyHandlesCount; index++) { int newHandle = 0; int handle = serverProcess.CpuMemory.Read <int>(serverMsg.Address + offset * 4); if (handle != 0) { GetCopyObjectHandle(serverThread, clientProcess, handle, out newHandle); } KernelContext.Memory.Write(clientMsg.DramAddress + offset * 4, newHandle); offset++; } for (int index = 0; index < serverHeader.MoveHandlesCount; index++) { int newHandle = 0; int handle = serverProcess.CpuMemory.Read <int>(serverMsg.Address + offset * 4); if (handle != 0) { if (clientResult == KernelResult.Success) { clientResult = GetMoveObjectHandle(serverProcess, clientProcess, handle, out newHandle); } else { serverProcess.HandleTable.CloseHandle(handle); } } KernelContext.Memory.Write(clientMsg.DramAddress + offset * 4, newHandle); offset++; } } else { offset = 2; } // Copy pointer/receive list buffers. uint recvListDstOffset = 0; for (int index = 0; index < serverHeader.PointerBuffersCount; index++) { ulong pointerDesc = serverProcess.CpuMemory.Read <ulong>(serverMsg.Address + offset * 4); PointerBufferDesc descriptor = new PointerBufferDesc(pointerDesc); if (descriptor.BufferSize != 0) { clientResult = GetReceiveListAddress( descriptor, clientMsg, clientHeader.ReceiveListType, serverHeader.MessageSizeInWords, receiveList, ref recvListDstOffset, out ulong recvListBufferAddress); if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } clientResult = clientProcess.MemoryManager.CopyDataFromCurrentProcess( recvListBufferAddress, descriptor.BufferSize, MemoryState.IsPoolAllocated, MemoryState.IsPoolAllocated, MemoryPermission.Read, MemoryAttribute.Uncached, MemoryAttribute.None, descriptor.BufferAddress); if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } } offset += 2; } // Set send, receive and exchange buffer descriptors to zero. uint totalBuffersCount = serverHeader.SendBuffersCount + serverHeader.ReceiveBuffersCount + serverHeader.ExchangeBuffersCount; for (int index = 0; index < totalBuffersCount; index++) { ulong dstDescAddress = clientMsg.DramAddress + offset * 4; KernelContext.Memory.Write(dstDescAddress + 0, 0); KernelContext.Memory.Write(dstDescAddress + 4, 0); KernelContext.Memory.Write(dstDescAddress + 8, 0); offset += 3; } // Copy raw data. if (serverHeader.RawDataSizeInWords != 0) { ulong copyDst = clientMsg.Address + offset * 4; ulong copySrc = serverMsg.Address + offset * 4; ulong copySize = serverHeader.RawDataSizeInWords * 4; if (serverMsg.IsCustom || clientMsg.IsCustom) { MemoryPermission permission = clientMsg.IsCustom ? MemoryPermission.None : MemoryPermission.Read; clientResult = clientProcess.MemoryManager.CopyDataFromCurrentProcess( copyDst, copySize, MemoryState.IsPoolAllocated, MemoryState.IsPoolAllocated, permission, MemoryAttribute.Uncached, MemoryAttribute.None, copySrc); } else { copyDst = clientProcess.MemoryManager.GetDramAddressFromVa(copyDst); copySrc = serverProcess.MemoryManager.GetDramAddressFromVa(copySrc); KernelContext.Memory.Copy(copyDst, copySrc, copySize); } } // Unmap buffers from server. clientResult = request.BufferDescriptorTable.UnmapServerBuffers(serverProcess.MemoryManager); if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } WakeClientThread(request, clientResult); return(serverResult); }
public Message(KSessionRequest request) : this( request.ClientThread, request.CustomCmdBuffAddr, request.CustomCmdBuffSize) { }
public KernelResult Receive(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0) { KThread serverThread = KernelContext.Scheduler.GetCurrentThread(); KProcess serverProcess = serverThread.Owner; KernelContext.CriticalSection.Enter(); if (_parent.ClientSession.State != ChannelState.Open) { KernelContext.CriticalSection.Leave(); return(KernelResult.PortRemoteClosed); } if (_activeRequest != null || !DequeueRequest(out KSessionRequest request)) { KernelContext.CriticalSection.Leave(); return(KernelResult.NotFound); } if (request.ClientThread == null) { KernelContext.CriticalSection.Leave(); return(KernelResult.PortRemoteClosed); } KThread clientThread = request.ClientThread; KProcess clientProcess = clientThread.Owner; KernelContext.CriticalSection.Leave(); _activeRequest = request; request.ServerProcess = serverProcess; Message clientMsg = new Message(request); Message serverMsg = new Message(serverThread, customCmdBuffAddr, customCmdBuffSize); MessageHeader clientHeader = GetClientMessageHeader(clientMsg); MessageHeader serverHeader = GetServerMessageHeader(serverMsg); KernelResult serverResult = KernelResult.NotFound; KernelResult clientResult = KernelResult.Success; void CleanUpForError() { if (request.BufferDescriptorTable.UnmapServerBuffers(serverProcess.MemoryManager) == KernelResult.Success) { request.BufferDescriptorTable.RestoreClientBuffers(clientProcess.MemoryManager); } CloseAllHandles(serverMsg, clientHeader, serverProcess); KernelContext.CriticalSection.Enter(); _activeRequest = null; if (_requests.Count != 0) { Signal(); } KernelContext.CriticalSection.Leave(); WakeClientThread(request, clientResult); } if (clientHeader.ReceiveListType < 2 && clientHeader.ReceiveListOffset > clientMsg.Size) { CleanUpForError(); return(KernelResult.InvalidCombination); } else if (clientHeader.ReceiveListType == 2 && clientHeader.ReceiveListOffset + 8 > clientMsg.Size) { CleanUpForError(); return(KernelResult.InvalidCombination); } else if (clientHeader.ReceiveListType > 2 && clientHeader.ReceiveListType * 8 - 0x10 + clientHeader.ReceiveListOffset > clientMsg.Size) { CleanUpForError(); return(KernelResult.InvalidCombination); } if (clientHeader.ReceiveListOffsetInWords < clientHeader.MessageSizeInWords) { CleanUpForError(); return(KernelResult.InvalidCombination); } if (clientHeader.MessageSizeInWords * 4 > clientMsg.Size) { CleanUpForError(); return(KernelResult.CmdBufferTooSmall); } ulong[] receiveList = GetReceiveList( serverMsg, serverHeader.ReceiveListType, serverHeader.ReceiveListOffset); serverProcess.CpuMemory.Write(serverMsg.Address + 0, clientHeader.Word0); serverProcess.CpuMemory.Write(serverMsg.Address + 4, clientHeader.Word1); uint offset; // Copy handles. if (clientHeader.HasHandles) { if (clientHeader.MoveHandlesCount != 0) { CleanUpForError(); return(KernelResult.InvalidCombination); } serverProcess.CpuMemory.Write(serverMsg.Address + 8, clientHeader.Word2); offset = 3; if (clientHeader.HasPid) { serverProcess.CpuMemory.Write(serverMsg.Address + offset * 4, clientProcess.Pid); offset += 2; } for (int index = 0; index < clientHeader.CopyHandlesCount; index++) { int newHandle = 0; int handle = KernelContext.Memory.Read <int>(clientMsg.DramAddress + offset * 4); if (clientResult == KernelResult.Success && handle != 0) { clientResult = GetCopyObjectHandle(clientThread, serverProcess, handle, out newHandle); } serverProcess.CpuMemory.Write(serverMsg.Address + offset * 4, newHandle); offset++; } for (int index = 0; index < clientHeader.MoveHandlesCount; index++) { int newHandle = 0; int handle = KernelContext.Memory.Read <int>(clientMsg.DramAddress + offset * 4); if (handle != 0) { if (clientResult == KernelResult.Success) { clientResult = GetMoveObjectHandle(clientProcess, serverProcess, handle, out newHandle); } else { clientProcess.HandleTable.CloseHandle(handle); } } serverProcess.CpuMemory.Write(serverMsg.Address + offset * 4, newHandle); offset++; } if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } } else { offset = 2; } // Copy pointer/receive list buffers. uint recvListDstOffset = 0; for (int index = 0; index < clientHeader.PointerBuffersCount; index++) { ulong pointerDesc = KernelContext.Memory.Read <ulong>(clientMsg.DramAddress + offset * 4); PointerBufferDesc descriptor = new PointerBufferDesc(pointerDesc); if (descriptor.BufferSize != 0) { clientResult = GetReceiveListAddress( descriptor, serverMsg, serverHeader.ReceiveListType, clientHeader.MessageSizeInWords, receiveList, ref recvListDstOffset, out ulong recvListBufferAddress); if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } clientResult = clientProcess.MemoryManager.CopyDataToCurrentProcess( recvListBufferAddress, descriptor.BufferSize, descriptor.BufferAddress, MemoryState.IsPoolAllocated, MemoryState.IsPoolAllocated, MemoryPermission.Read, MemoryAttribute.Uncached, MemoryAttribute.None); if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } descriptor.BufferAddress = recvListBufferAddress; } else { descriptor.BufferAddress = 0; } serverProcess.CpuMemory.Write(serverMsg.Address + offset * 4, descriptor.Pack()); offset += 2; } // Copy send, receive and exchange buffers. uint totalBuffersCount = clientHeader.SendBuffersCount + clientHeader.ReceiveBuffersCount + clientHeader.ExchangeBuffersCount; for (int index = 0; index < totalBuffersCount; index++) { ulong clientDescAddress = clientMsg.DramAddress + offset * 4; uint descWord0 = KernelContext.Memory.Read <uint>(clientDescAddress + 0); uint descWord1 = KernelContext.Memory.Read <uint>(clientDescAddress + 4); uint descWord2 = KernelContext.Memory.Read <uint>(clientDescAddress + 8); bool isSendDesc = index < clientHeader.SendBuffersCount; bool isExchangeDesc = index >= clientHeader.SendBuffersCount + clientHeader.ReceiveBuffersCount; bool notReceiveDesc = isSendDesc || isExchangeDesc; bool isReceiveDesc = !notReceiveDesc; MemoryPermission permission = index >= clientHeader.SendBuffersCount ? MemoryPermission.ReadAndWrite : MemoryPermission.Read; uint sizeHigh4 = (descWord2 >> 24) & 0xf; ulong bufferSize = descWord0 | (ulong)sizeHigh4 << 32; ulong dstAddress = 0; if (bufferSize != 0) { ulong bufferAddress; bufferAddress = descWord2 >> 28; bufferAddress |= ((descWord2 >> 2) & 7) << 4; bufferAddress = (bufferAddress << 32) | descWord1; MemoryState state = IpcMemoryStates[(descWord2 + 1) & 3]; clientResult = serverProcess.MemoryManager.MapBufferFromClientProcess( bufferSize, bufferAddress, clientProcess.MemoryManager, permission, state, notReceiveDesc, out dstAddress); if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } if (isSendDesc) { clientResult = request.BufferDescriptorTable.AddSendBuffer(bufferAddress, dstAddress, bufferSize, state); } else if (isReceiveDesc) { clientResult = request.BufferDescriptorTable.AddReceiveBuffer(bufferAddress, dstAddress, bufferSize, state); } else /* if (isExchangeDesc) */ { clientResult = request.BufferDescriptorTable.AddExchangeBuffer(bufferAddress, dstAddress, bufferSize, state); } if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } } descWord1 = (uint)dstAddress; descWord2 &= 3; descWord2 |= sizeHigh4 << 24; descWord2 |= (uint)(dstAddress >> 34) & 0x3ffffffc; descWord2 |= (uint)(dstAddress >> 4) & 0xf0000000; ulong serverDescAddress = serverMsg.Address + offset * 4; serverProcess.CpuMemory.Write(serverDescAddress + 0, descWord0); serverProcess.CpuMemory.Write(serverDescAddress + 4, descWord1); serverProcess.CpuMemory.Write(serverDescAddress + 8, descWord2); offset += 3; } // Copy raw data. if (clientHeader.RawDataSizeInWords != 0) { ulong copySrc = clientMsg.Address + offset * 4; ulong copyDst = serverMsg.Address + offset * 4; ulong copySize = clientHeader.RawDataSizeInWords * 4; if (serverMsg.IsCustom || clientMsg.IsCustom) { MemoryPermission permission = clientMsg.IsCustom ? MemoryPermission.None : MemoryPermission.Read; clientResult = clientProcess.MemoryManager.CopyDataToCurrentProcess( copyDst, copySize, copySrc, MemoryState.IsPoolAllocated, MemoryState.IsPoolAllocated, permission, MemoryAttribute.Uncached, MemoryAttribute.None); } else { copySrc = clientProcess.MemoryManager.GetDramAddressFromVa(copySrc); copyDst = serverProcess.MemoryManager.GetDramAddressFromVa(copyDst); KernelContext.Memory.Copy(copyDst, copySrc, copySize); } if (clientResult != KernelResult.Success) { CleanUpForError(); return(serverResult); } } return(KernelResult.Success); }