mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Implement svcGetHandleInfo, svcOpenProcess/Thread, svcGetProcessList (#6243)
* Implement svcGetHandleInfo, svcOpenProcess/Thread, svcGetProcessList * Apply suggestions * Add comment to stubbed enum values in svcGetHandleInfo * Revert u32 -> size_t
This commit is contained in:
		
							parent
							
								
									a298e4969b
								
							
						
					
					
						commit
						9c6035f254
					
				
					 4 changed files with 145 additions and 12 deletions
				
			
		|  | @ -224,6 +224,10 @@ public: | ||||||
|     /// Retrieves a process from the current list of processes.
 |     /// Retrieves a process from the current list of processes.
 | ||||||
|     std::shared_ptr<Process> GetProcessById(u32 process_id) const; |     std::shared_ptr<Process> GetProcessById(u32 process_id) const; | ||||||
| 
 | 
 | ||||||
|  |     const std::vector<std::shared_ptr<Process>>& GetProcessList() const { | ||||||
|  |         return process_list; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     std::shared_ptr<Process> GetCurrentProcess() const; |     std::shared_ptr<Process> GetCurrentProcess() const; | ||||||
|     void SetCurrentProcess(std::shared_ptr<Process> process); |     void SetCurrentProcess(std::shared_ptr<Process> process); | ||||||
|     void SetCurrentProcessForCPU(std::shared_ptr<Process> process, u32 core_id); |     void SetCurrentProcessForCPU(std::shared_ptr<Process> process, u32 core_id); | ||||||
|  |  | ||||||
|  | @ -44,6 +44,7 @@ void Process::serialize(Archive& ar, const unsigned int file_version) { | ||||||
|     ar& ideal_processor; |     ar& ideal_processor; | ||||||
|     ar& status; |     ar& status; | ||||||
|     ar& process_id; |     ar& process_id; | ||||||
|  |     ar& creation_time_ticks; | ||||||
|     ar& vm_manager; |     ar& vm_manager; | ||||||
|     ar& memory_used; |     ar& memory_used; | ||||||
|     ar& memory_region; |     ar& memory_region; | ||||||
|  | @ -72,6 +73,7 @@ std::shared_ptr<Process> KernelSystem::CreateProcess(std::shared_ptr<CodeSet> co | ||||||
|     process->flags.memory_region.Assign(MemoryRegion::APPLICATION); |     process->flags.memory_region.Assign(MemoryRegion::APPLICATION); | ||||||
|     process->status = ProcessStatus::Created; |     process->status = ProcessStatus::Created; | ||||||
|     process->process_id = ++next_process_id; |     process->process_id = ++next_process_id; | ||||||
|  |     process->creation_time_ticks = timing.GetTicks(); | ||||||
| 
 | 
 | ||||||
|     process_list.push_back(process); |     process_list.push_back(process); | ||||||
|     return process; |     return process; | ||||||
|  |  | ||||||
|  | @ -185,6 +185,9 @@ public: | ||||||
|     /// The id of this process
 |     /// The id of this process
 | ||||||
|     u32 process_id; |     u32 process_id; | ||||||
| 
 | 
 | ||||||
|  |     // Creation time in ticks of the process.
 | ||||||
|  |     u64 creation_time_ticks; | ||||||
|  | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Parses a list of kernel capability descriptors (as found in the ExHeader) and applies them |      * Parses a list of kernel capability descriptors (as found in the ExHeader) and applies them | ||||||
|      * to this process. |      * to this process. | ||||||
|  |  | ||||||
|  | @ -80,6 +80,22 @@ struct PageInfo { | ||||||
|     u32 flags; |     u32 flags; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | // Values accepted by svcGetHandleInfo.
 | ||||||
|  | enum class HandleInfoType { | ||||||
|  |     /**
 | ||||||
|  |      * Returns the time in ticks the KProcess referenced by the handle was created. | ||||||
|  |      */ | ||||||
|  |     KPROCESS_ELAPSED_TICKS = 0, | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Get internal refcount for kernel object. | ||||||
|  |      */ | ||||||
|  |     REFERENCE_COUNT = 1, | ||||||
|  | 
 | ||||||
|  |     STUBBED_1 = 2, | ||||||
|  |     STUBBED_2 = 0x32107, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /// Values accepted by svcGetSystemInfo's type parameter.
 | /// Values accepted by svcGetSystemInfo's type parameter.
 | ||||||
| enum class SystemInfoType { | enum class SystemInfoType { | ||||||
|     /**
 |     /**
 | ||||||
|  | @ -358,6 +374,8 @@ private: | ||||||
|     ResultCode UnmapMemoryBlock(Handle handle, u32 addr); |     ResultCode UnmapMemoryBlock(Handle handle, u32 addr); | ||||||
|     ResultCode ConnectToPort(Handle* out_handle, VAddr port_name_address); |     ResultCode ConnectToPort(Handle* out_handle, VAddr port_name_address); | ||||||
|     ResultCode SendSyncRequest(Handle handle); |     ResultCode SendSyncRequest(Handle handle); | ||||||
|  |     ResultCode OpenProcess(Handle* out_handle, u32 process_id); | ||||||
|  |     ResultCode OpenThread(Handle* out_handle, Handle process_handle, u32 thread_id); | ||||||
|     ResultCode CloseHandle(Handle handle); |     ResultCode CloseHandle(Handle handle); | ||||||
|     ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds); |     ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds); | ||||||
|     ResultCode WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle_count, |     ResultCode WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle_count, | ||||||
|  | @ -399,6 +417,7 @@ private: | ||||||
|     ResultCode CancelTimer(Handle handle); |     ResultCode CancelTimer(Handle handle); | ||||||
|     void SleepThread(s64 nanoseconds); |     void SleepThread(s64 nanoseconds); | ||||||
|     s64 GetSystemTick(); |     s64 GetSystemTick(); | ||||||
|  |     ResultCode GetHandleInfo(s64* out, Handle handle, u32 type); | ||||||
|     ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission, |     ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission, | ||||||
|                                  u32 other_permission); |                                  u32 other_permission); | ||||||
|     ResultCode CreatePort(Handle* server_port, Handle* client_port, VAddr name_address, |     ResultCode CreatePort(Handle* server_port, Handle* client_port, VAddr name_address, | ||||||
|  | @ -409,6 +428,8 @@ private: | ||||||
|     ResultCode GetSystemInfo(s64* out, u32 type, s32 param); |     ResultCode GetSystemInfo(s64* out, u32 type, s32 param); | ||||||
|     ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type); |     ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type); | ||||||
|     ResultCode GetThreadInfo(s64* out, Handle thread_handle, u32 type); |     ResultCode GetThreadInfo(s64* out, Handle thread_handle, u32 type); | ||||||
|  |     ResultCode GetProcessList(s32* process_count, VAddr out_process_array, | ||||||
|  |                               s32 out_process_array_count); | ||||||
|     ResultCode InvalidateInstructionCacheRange(u32 addr, u32 size); |     ResultCode InvalidateInstructionCacheRange(u32 addr, u32 size); | ||||||
|     ResultCode InvalidateEntireInstructionCache(); |     ResultCode InvalidateEntireInstructionCache(); | ||||||
|     u32 ConvertVaToPa(u32 addr); |     u32 ConvertVaToPa(u32 addr); | ||||||
|  | @ -594,14 +615,16 @@ ResultCode SVC::UnmapMemoryBlock(Handle handle, u32 addr) { | ||||||
| 
 | 
 | ||||||
| /// Connect to an OS service given the port name, returns the handle to the port to out
 | /// Connect to an OS service given the port name, returns the handle to the port to out
 | ||||||
| ResultCode SVC::ConnectToPort(Handle* out_handle, VAddr port_name_address) { | ResultCode SVC::ConnectToPort(Handle* out_handle, VAddr port_name_address) { | ||||||
|     if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), port_name_address)) |     if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), port_name_address)) { | ||||||
|         return ERR_NOT_FOUND; |         return ERR_NOT_FOUND; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     static constexpr std::size_t PortNameMaxLength = 11; |     static constexpr std::size_t PortNameMaxLength = 11; | ||||||
|     // Read 1 char beyond the max allowed port name to detect names that are too long.
 |     // Read 1 char beyond the max allowed port name to detect names that are too long.
 | ||||||
|     std::string port_name = memory.ReadCString(port_name_address, PortNameMaxLength + 1); |     std::string port_name = memory.ReadCString(port_name_address, PortNameMaxLength + 1); | ||||||
|     if (port_name.size() > PortNameMaxLength) |     if (port_name.size() > PortNameMaxLength) { | ||||||
|         return ERR_PORT_NAME_TOO_LONG; |         return ERR_PORT_NAME_TOO_LONG; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     LOG_TRACE(Kernel_SVC, "called port_name={}", port_name); |     LOG_TRACE(Kernel_SVC, "called port_name={}", port_name); | ||||||
| 
 | 
 | ||||||
|  | @ -642,6 +665,50 @@ ResultCode SVC::SendSyncRequest(Handle handle) { | ||||||
|     return session->SendSyncRequest(thread); |     return session->SendSyncRequest(thread); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | ResultCode SVC::OpenProcess(Handle* out_handle, u32 process_id) { | ||||||
|  |     std::shared_ptr<Process> process = kernel.GetProcessById(process_id); | ||||||
|  |     if (!process) { | ||||||
|  |         // Result 0xd9001818 (process not found?)
 | ||||||
|  |         return ResultCode(24, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); | ||||||
|  |     } | ||||||
|  |     auto result_handle = kernel.GetCurrentProcess()->handle_table.Create(process); | ||||||
|  |     if (result_handle.empty()) { | ||||||
|  |         return result_handle.Code(); | ||||||
|  |     } | ||||||
|  |     *out_handle = result_handle.Unwrap(); | ||||||
|  |     return RESULT_SUCCESS; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ResultCode SVC::OpenThread(Handle* out_handle, Handle process_handle, u32 thread_id) { | ||||||
|  |     if (process_handle == 0) { | ||||||
|  |         LOG_ERROR(Kernel_SVC, "Uninplemented svcOpenThread process_handle=0"); | ||||||
|  |         // Result 0xd9001819 (thread not found?)
 | ||||||
|  |         return ResultCode(25, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     std::shared_ptr<Process> process = | ||||||
|  |         kernel.GetCurrentProcess()->handle_table.Get<Process>(process_handle); | ||||||
|  |     if (!process) { | ||||||
|  |         return ERR_INVALID_HANDLE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     for (u32 core_id = 0; core_id < system.GetNumCores(); core_id++) { | ||||||
|  |         auto& thread_list = kernel.GetThreadManager(core_id).GetThreadList(); | ||||||
|  |         for (auto& thread : thread_list) { | ||||||
|  |             if (thread->owner_process.lock() == process && thread.get()->thread_id == thread_id) { | ||||||
|  |                 auto result_handle = kernel.GetCurrentProcess()->handle_table.Create(thread); | ||||||
|  |                 if (result_handle.empty()) { | ||||||
|  |                     return result_handle.Code(); | ||||||
|  |                 } | ||||||
|  |                 *out_handle = result_handle.Unwrap(); | ||||||
|  |                 return RESULT_SUCCESS; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     // Result 0xd9001819 (thread not found?)
 | ||||||
|  |     return ResultCode(25, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /// Close a handle
 | /// Close a handle
 | ||||||
| ResultCode SVC::CloseHandle(Handle handle) { | ResultCode SVC::CloseHandle(Handle handle) { | ||||||
|     LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); |     LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); | ||||||
|  | @ -761,16 +828,18 @@ ResultCode SVC::WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle | ||||||
|                                      bool wait_all, s64 nano_seconds) { |                                      bool wait_all, s64 nano_seconds) { | ||||||
|     Thread* thread = kernel.GetCurrentThreadManager().GetCurrentThread(); |     Thread* thread = kernel.GetCurrentThreadManager().GetCurrentThread(); | ||||||
| 
 | 
 | ||||||
|     if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address)) |     if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address)) { | ||||||
|         return ERR_INVALID_POINTER; |         return ERR_INVALID_POINTER; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If
 |     // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If
 | ||||||
|     // this happens, the running application will crash.
 |     // this happens, the running application will crash.
 | ||||||
|     ASSERT_MSG(out != nullptr, "invalid output pointer specified!"); |     ASSERT_MSG(out != nullptr, "invalid output pointer specified!"); | ||||||
| 
 | 
 | ||||||
|     // Check if 'handle_count' is invalid
 |     // Check if 'handle_count' is invalid
 | ||||||
|     if (handle_count < 0) |     if (handle_count < 0) { | ||||||
|         return ERR_OUT_OF_RANGE; |         return ERR_OUT_OF_RANGE; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     using ObjectPtr = std::shared_ptr<WaitObject>; |     using ObjectPtr = std::shared_ptr<WaitObject>; | ||||||
|     std::vector<ObjectPtr> objects(handle_count); |     std::vector<ObjectPtr> objects(handle_count); | ||||||
|  | @ -907,12 +976,14 @@ static ResultCode ReceiveIPCRequest(Kernel::KernelSystem& kernel, Memory::Memory | ||||||
| /// In a single operation, sends a IPC reply and waits for a new request.
 | /// In a single operation, sends a IPC reply and waits for a new request.
 | ||||||
| ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_count, | ResultCode SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_count, | ||||||
|                                 Handle reply_target) { |                                 Handle reply_target) { | ||||||
|     if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address)) |     if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), handles_address)) { | ||||||
|         return ERR_INVALID_POINTER; |         return ERR_INVALID_POINTER; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     // Check if 'handle_count' is invalid
 |     // Check if 'handle_count' is invalid
 | ||||||
|     if (handle_count < 0) |     if (handle_count < 0) { | ||||||
|         return ERR_OUT_OF_RANGE; |         return ERR_OUT_OF_RANGE; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     using ObjectPtr = std::shared_ptr<WaitObject>; |     using ObjectPtr = std::shared_ptr<WaitObject>; | ||||||
|     std::vector<ObjectPtr> objects(handle_count); |     std::vector<ObjectPtr> objects(handle_count); | ||||||
|  | @ -1522,6 +1593,40 @@ s64 SVC::GetSystemTick() { | ||||||
|     return result; |     return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Returns information of the specified handle
 | ||||||
|  | ResultCode SVC::GetHandleInfo(s64* out, Handle handle, u32 type) { | ||||||
|  |     std::shared_ptr<Object> KObject = kernel.GetCurrentProcess()->handle_table.GetGeneric(handle); | ||||||
|  |     if (!KObject) { | ||||||
|  |         return ERR_INVALID_HANDLE; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Not initialized in real kernel, but we don't want to leak memory.
 | ||||||
|  |     s64 value = 0; | ||||||
|  |     std::shared_ptr<Process> process; | ||||||
|  | 
 | ||||||
|  |     switch (static_cast<HandleInfoType>(type)) { | ||||||
|  |     case HandleInfoType::KPROCESS_ELAPSED_TICKS: | ||||||
|  |         process = DynamicObjectCast<Process>(KObject); | ||||||
|  |         if (process) { | ||||||
|  |             value = process->creation_time_ticks; | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |     case HandleInfoType::REFERENCE_COUNT: | ||||||
|  |         // This is the closest approximation we can get without a full KObject impl.
 | ||||||
|  |         value = KObject.use_count() - 1; | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |     // These values are stubbed in real kernel, they do nothing.
 | ||||||
|  |     case HandleInfoType::STUBBED_1: | ||||||
|  |     case HandleInfoType::STUBBED_2: | ||||||
|  |         break; | ||||||
|  |     default: | ||||||
|  |         return ERR_INVALID_ENUM_VALUE; | ||||||
|  |     } | ||||||
|  |     *out = value; | ||||||
|  |     return RESULT_SUCCESS; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /// Creates a memory block at the specified address with the specified permissions and size
 | /// Creates a memory block at the specified address with the specified permissions and size
 | ||||||
| ResultCode SVC::CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission, | ResultCode SVC::CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission, | ||||||
|                                   u32 other_permission) { |                                   u32 other_permission) { | ||||||
|  | @ -1833,6 +1938,25 @@ ResultCode SVC::GetThreadInfo(s64* out, Handle thread_handle, u32 type) { | ||||||
|     return RESULT_SUCCESS; |     return RESULT_SUCCESS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | ResultCode SVC::GetProcessList(s32* process_count, VAddr out_process_array, | ||||||
|  |                                s32 out_process_array_count) { | ||||||
|  |     if (!memory.IsValidVirtualAddress(*kernel.GetCurrentProcess(), out_process_array)) { | ||||||
|  |         return ERR_INVALID_POINTER; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     s32 written = 0; | ||||||
|  |     for (const auto process : kernel.GetProcessList()) { | ||||||
|  |         if (written >= out_process_array_count) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         if (process) { | ||||||
|  |             memory.Write32(out_process_array + written++ * sizeof(u32), process->process_id); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     *process_count = written; | ||||||
|  |     return RESULT_SUCCESS; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| ResultCode SVC::InvalidateInstructionCacheRange(u32 addr, u32 size) { | ResultCode SVC::InvalidateInstructionCacheRange(u32 addr, u32 size) { | ||||||
|     Core::GetRunningCore().InvalidateCacheRange(addr, size); |     Core::GetRunningCore().InvalidateCacheRange(addr, size); | ||||||
|     return RESULT_SUCCESS; |     return RESULT_SUCCESS; | ||||||
|  | @ -1952,8 +2076,8 @@ ResultCode SVC::ControlProcess(Handle process_handle, u32 process_OP, u32 varg2, | ||||||
|         return RESULT_SUCCESS; |         return RESULT_SUCCESS; | ||||||
|     } |     } | ||||||
|     case ControlProcessOP::PROCESSOP_SCHEDULE_THREADS_WITHOUT_TLS_MAGIC: { |     case ControlProcessOP::PROCESSOP_SCHEDULE_THREADS_WITHOUT_TLS_MAGIC: { | ||||||
|         for (u32 i = 0; i < system.GetNumCores(); i++) { |         for (u32 core_id = 0; core_id < system.GetNumCores(); core_id++) { | ||||||
|             auto& thread_list = kernel.GetThreadManager(i).GetThreadList(); |             auto& thread_list = kernel.GetThreadManager(core_id).GetThreadList(); | ||||||
|             for (auto& thread : thread_list) { |             for (auto& thread : thread_list) { | ||||||
|                 if (thread->owner_process.lock() != process) { |                 if (thread->owner_process.lock() != process) { | ||||||
|                     continue; |                     continue; | ||||||
|  | @ -2026,7 +2150,7 @@ const std::array<SVC::FunctionDef, 180> SVC::SVC_Table{{ | ||||||
|     {0x26, nullptr, "SignalAndWait"}, |     {0x26, nullptr, "SignalAndWait"}, | ||||||
|     {0x27, &SVC::Wrap<&SVC::DuplicateHandle>, "DuplicateHandle"}, |     {0x27, &SVC::Wrap<&SVC::DuplicateHandle>, "DuplicateHandle"}, | ||||||
|     {0x28, &SVC::Wrap<&SVC::GetSystemTick>, "GetSystemTick"}, |     {0x28, &SVC::Wrap<&SVC::GetSystemTick>, "GetSystemTick"}, | ||||||
|     {0x29, nullptr, "GetHandleInfo"}, |     {0x29, &SVC::Wrap<&SVC::GetHandleInfo>, "GetHandleInfo"}, | ||||||
|     {0x2A, &SVC::Wrap<&SVC::GetSystemInfo>, "GetSystemInfo"}, |     {0x2A, &SVC::Wrap<&SVC::GetSystemInfo>, "GetSystemInfo"}, | ||||||
|     {0x2B, &SVC::Wrap<&SVC::GetProcessInfo>, "GetProcessInfo"}, |     {0x2B, &SVC::Wrap<&SVC::GetProcessInfo>, "GetProcessInfo"}, | ||||||
|     {0x2C, &SVC::Wrap<&SVC::GetThreadInfo>, "GetThreadInfo"}, |     {0x2C, &SVC::Wrap<&SVC::GetThreadInfo>, "GetThreadInfo"}, | ||||||
|  | @ -2036,8 +2160,8 @@ const std::array<SVC::FunctionDef, 180> SVC::SVC_Table{{ | ||||||
|     {0x30, nullptr, "SendSyncRequest3"}, |     {0x30, nullptr, "SendSyncRequest3"}, | ||||||
|     {0x31, nullptr, "SendSyncRequest4"}, |     {0x31, nullptr, "SendSyncRequest4"}, | ||||||
|     {0x32, &SVC::Wrap<&SVC::SendSyncRequest>, "SendSyncRequest"}, |     {0x32, &SVC::Wrap<&SVC::SendSyncRequest>, "SendSyncRequest"}, | ||||||
|     {0x33, nullptr, "OpenProcess"}, |     {0x33, &SVC::Wrap<&SVC::OpenProcess>, "OpenProcess"}, | ||||||
|     {0x34, nullptr, "OpenThread"}, |     {0x34, &SVC::Wrap<&SVC::OpenThread>, "OpenThread"}, | ||||||
|     {0x35, &SVC::Wrap<&SVC::GetProcessId>, "GetProcessId"}, |     {0x35, &SVC::Wrap<&SVC::GetProcessId>, "GetProcessId"}, | ||||||
|     {0x36, &SVC::Wrap<&SVC::GetProcessIdOfThread>, "GetProcessIdOfThread"}, |     {0x36, &SVC::Wrap<&SVC::GetProcessIdOfThread>, "GetProcessIdOfThread"}, | ||||||
|     {0x37, &SVC::Wrap<&SVC::GetThreadId>, "GetThreadId"}, |     {0x37, &SVC::Wrap<&SVC::GetThreadId>, "GetThreadId"}, | ||||||
|  | @ -2086,7 +2210,7 @@ const std::array<SVC::FunctionDef, 180> SVC::SVC_Table{{ | ||||||
|     {0x62, nullptr, "TerminateDebugProcess"}, |     {0x62, nullptr, "TerminateDebugProcess"}, | ||||||
|     {0x63, nullptr, "GetProcessDebugEvent"}, |     {0x63, nullptr, "GetProcessDebugEvent"}, | ||||||
|     {0x64, nullptr, "ContinueDebugEvent"}, |     {0x64, nullptr, "ContinueDebugEvent"}, | ||||||
|     {0x65, nullptr, "GetProcessList"}, |     {0x65, &SVC::Wrap<&SVC::GetProcessList>, "GetProcessList"}, | ||||||
|     {0x66, nullptr, "GetThreadList"}, |     {0x66, nullptr, "GetThreadList"}, | ||||||
|     {0x67, nullptr, "GetDebugThreadContext"}, |     {0x67, nullptr, "GetDebugThreadContext"}, | ||||||
|     {0x68, nullptr, "SetDebugThreadContext"}, |     {0x68, nullptr, "SetDebugThreadContext"}, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue