diff --git a/Misc/General_IPC.h b/Misc/General_IPC.h index f50ad2f..0073e5b 100644 --- a/Misc/General_IPC.h +++ b/Misc/General_IPC.h @@ -5,6 +5,7 @@ enum GeneralIPCCommands { + GIPC_HELLO, GIPC_LIB_LIST, GIPC_LIB_LOAD, GIPC_LIB_UNLOAD, diff --git a/Playstation/OrbisLibAPI/Debug.cpp b/Playstation/OrbisLibAPI/Debug.cpp index 1c7a5c5..3a0d7ca 100644 --- a/Playstation/OrbisLibAPI/Debug.cpp +++ b/Playstation/OrbisLibAPI/Debug.cpp @@ -90,18 +90,89 @@ bool Debug::TryDetach(int pid) int res = ptrace(PT_DETACH, pid, nullptr, 0); if (res != 0) { + // Check if proc is dead anyway and just detach. + klog("DetachProcess(): ptrace(PT_DETACH) failed with error %llX\n", res); return false; } - // TODO: Kill the watching thread and Remove any Watchpoints / Breakpoints now. - + // Reset vars. IsDebugging = false; CurrentPID = -1; + // Wait for the current proc thread to die. + scePthreadJoin(*ProcMonitorThreadHandle, nullptr); + return true; } +void* Debug::ProcessMonotorThread() +{ + while (IsDebugging && CurrentPID != -1) + { + std::vector procList; + GetProcessList(procList); + + int currentPID = CurrentPID; + if (std::find_if(procList.begin(), procList.end(), [¤tPID](const kinfo_proc& arg) { + return arg.pid == currentPID; + }) == procList.end()) + { + klog("Proc %d has died.\n", CurrentPID); + + // Aquire lock. + scePthreadMutexLock(&DebugMutex); + + // Reset vars. + IsDebugging = false; + CurrentPID = -1; + + // Send attach event to host. + Events::SendEvent(Events::EVENT_DIE, CurrentPID); + + // Let the process die. + ptrace(PT_CONTINUE, CurrentPID, (void*)1, SIGKILL); + + // release the lock. + scePthreadMutexUnlock(&DebugMutex); + + goto Thread_Exit; + } + + int status; + auto debuggiePid = wait4(CurrentPID, &status, WNOHANG, nullptr); + if (debuggiePid == CurrentPID) + { + int signal = WSTOPSIG(status); + klog("Process %d has recieved the signal %d\n", CurrentPID, signal); + + switch (signal) + { + case SIGSTOP: + klog("SIGSTOP\n"); + break; + } + } + + sceKernelSleep(1); + } + +Thread_Exit: + klog("Client Thread Exiting!\n"); + + // TODO: Remove any Watchpoints / Breakpoints now. + // Unless the process is dying maybe? + + // Kill our thread and exit. + scePthreadExit(NULL); + return nullptr; +} + +void* Debug::ProcessMonotorThreadHelper(void* tdParam) +{ + return ((Debug*)tdParam)->ProcessMonotorThread(); +} + void Debug::Attach(OrbisNetId Sock) { auto pid = RecieveInt(Sock); @@ -156,6 +227,9 @@ void Debug::Attach(OrbisNetId Sock) IsDebugging = true; CurrentPID = pid; + // Create thread to monitor the state of the running process. + scePthreadCreate(&ProcMonitorThreadHandle, NULL, &ProcessMonotorThreadHelper, this, "Process Monitor Thread"); + // release the lock. scePthreadMutexUnlock(&DebugMutex); @@ -166,23 +240,27 @@ void Debug::Attach(OrbisNetId Sock) SendStatus(Sock, 1); - if (strcmp(processName, "SceShellCore")) + // Check the satus of the general helper. + if (!GeneralIPC::TestConnection(pid)) { - // Get app info. - OrbisAppInfo appInfo; - sceKernelGetAppInfo(pid, &appInfo); + if (strcmp(processName, "SceShellCore")) + { + // Get app info. + OrbisAppInfo appInfo; + sceKernelGetAppInfo(pid, &appInfo); - // Get sandbox path. - char sandBoxPath[PATH_MAX]; - snprintf(sandBoxPath, sizeof(sandBoxPath), "/mnt/sandbox/%s_000/data", appInfo.TitleId); + // Get sandbox path. + char sandBoxPath[PATH_MAX]; + snprintf(sandBoxPath, sizeof(sandBoxPath), "/mnt/sandbox/%s_000/data", appInfo.TitleId); - // Mount data into sandbox - LinkDir("/data/", sandBoxPath); + // Mount data into sandbox + LinkDir("/data/", sandBoxPath); + } + + // Load the helper library. + int handle = sys_sdk_proc_prx_load(processName, HelperPrxPath); + klog("Helper handle = %llX\n", handle); } - - // Load the helper library. - int handle = sys_sdk_proc_prx_load(processName, HelperPrxPath); - klog("Helper handle = %llX\n", handle); } void Debug::Detach(OrbisNetId Sock) diff --git a/Playstation/OrbisLibAPI/Debug.h b/Playstation/OrbisLibAPI/Debug.h index ee0cece..6cdacc0 100644 --- a/Playstation/OrbisLibAPI/Debug.h +++ b/Playstation/OrbisLibAPI/Debug.h @@ -4,6 +4,7 @@ class Debug { public: OrbisPthreadMutex DebugMutex; + OrbisPthread* ProcMonitorThreadHandle; bool IsDebugging; int CurrentPID; @@ -13,6 +14,8 @@ public: private: bool TryDetach(int pid); + void* ProcessMonotorThread(); + static void* ProcessMonotorThreadHelper(void* tdParam); void Attach(OrbisNetId Sock); void Detach(OrbisNetId Sock); diff --git a/Playstation/OrbisLibAPI/GeneralIPC.cpp b/Playstation/OrbisLibAPI/GeneralIPC.cpp index d0f1d37..881113f 100644 --- a/Playstation/OrbisLibAPI/GeneralIPC.cpp +++ b/Playstation/OrbisLibAPI/GeneralIPC.cpp @@ -42,6 +42,43 @@ bool GeneralIPC::SendCommand(OrbisNetId Sock, int Command) return Status == GIPC_OK; } +bool GeneralIPC::TestConnection(int pid) +{ + // Open a new local socket connection for the process. + auto sock = Connect(pid); + if (!sock) + { + klog("[GeneralIPC] Failed to connect to socket.\n"); + return false; + } + + // Send the command. + if (!SendCommand(sock, GIPC_HELLO)) + { + // Close the socket. + sceNetSocketClose(sock); + + klog("[GeneralIPC] Failed to send command.\n"); + return false; + } + + // Get the library count. + int status = 0; + if (!Sockets::RecvInt(sock, &status)) + { + // Close the socket. + sceNetSocketClose(sock); + + klog("[GeneralIPC] Failed to recv status.\n"); + return false; + } + + // Close the socket. + sceNetSocketClose(sock); + + return status == GIPC_OK; +} + bool GeneralIPC::GetLibraryList(int pid, std::vector& Libraries) { // Open a new local socket connection for the process. @@ -55,6 +92,9 @@ bool GeneralIPC::GetLibraryList(int pid, std::vector& Libraries) // Send the command. if (!SendCommand(sock, GIPC_LIB_LIST)) { + // Close the socket. + sceNetSocketClose(sock); + klog("[GeneralIPC] Failed to send command.\n"); return false; } @@ -63,6 +103,9 @@ bool GeneralIPC::GetLibraryList(int pid, std::vector& Libraries) int LibraryCount = 0; if (!Sockets::RecvInt(sock, &LibraryCount)) { + // Close the socket. + sceNetSocketClose(sock); + klog("[GeneralIPC] Failed to recv library count.\n"); return false; } @@ -72,10 +115,16 @@ bool GeneralIPC::GetLibraryList(int pid, std::vector& Libraries) if (!Sockets::RecvLargeData(sock, (unsigned char*)Libraries.data(), LibraryCount * sizeof(LibPacket))) { + // Close the socket. + sceNetSocketClose(sock); + klog("[GeneralIPC] Failed to recv library data.\n"); return false; } + // Close the socket. + sceNetSocketClose(sock); + return true; } @@ -92,6 +141,9 @@ bool GeneralIPC::LoadLibrary(int pid, const char* Path, int* HandleOut) // Send the command. if (!SendCommand(sock, GIPC_LIB_LOAD)) { + // Close the socket. + sceNetSocketClose(sock); + klog("[GeneralIPC] Failed to send command.\n"); return false; } @@ -106,6 +158,9 @@ bool GeneralIPC::LoadLibrary(int pid, const char* Path, int* HandleOut) // Send the packet. if (sceNetSend(sock, Packet, sizeof(LibPacket), 0) < 0) { + // Close the socket. + sceNetSocketClose(sock); + klog("[GeneralIPC] Failed to send LibPacket.\n"); // Restore the jail. @@ -117,6 +172,9 @@ bool GeneralIPC::LoadLibrary(int pid, const char* Path, int* HandleOut) // Recieve the result. if (!Sockets::RecvInt(sock, HandleOut)) { + // Close the socket. + sceNetSocketClose(sock); + klog("[GeneralIPC] Failed to recv handle.\n"); // Restore the jail. @@ -128,6 +186,9 @@ bool GeneralIPC::LoadLibrary(int pid, const char* Path, int* HandleOut) // Check to see if it was loaded successfully. if (*HandleOut <= 0) { + // Close the socket. + sceNetSocketClose(sock); + klog("[GeneralIPC] Failed to load PRX '%s' (0x%llX).\n", *HandleOut); // Restore the jail. @@ -139,6 +200,9 @@ bool GeneralIPC::LoadLibrary(int pid, const char* Path, int* HandleOut) // Restore the jail. Jail(pid); + // Close the socket. + sceNetSocketClose(sock); + return true; } @@ -155,6 +219,9 @@ bool GeneralIPC::UnLoadLibrary(int pid, int Handle) // Send the command. if (!SendCommand(sock, GIPC_LIB_UNLOAD)) { + // Close the socket. + sceNetSocketClose(sock); + klog("[GeneralIPC] Failed to send command.\n"); return false; } @@ -163,6 +230,9 @@ bool GeneralIPC::UnLoadLibrary(int pid, int Handle) int result = 0; if (!Sockets::RecvInt(sock, &result)) { + // Close the socket. + sceNetSocketClose(sock); + klog("[GeneralIPC] Failed to recv result.\n"); return false; } @@ -170,10 +240,16 @@ bool GeneralIPC::UnLoadLibrary(int pid, int Handle) // Check to see if it was unloaded successfully. if (result != 0) { + // Close the socket. + sceNetSocketClose(sock); + klog("[GeneralIPC] Failed to un load PRX '%s' (0x%llX).\n", result); return false; } + // Close the socket. + sceNetSocketClose(sock); + return true; } @@ -190,6 +266,9 @@ bool GeneralIPC::Jailbreak(int pid) // Send the command. if (!SendCommand(sock, GIPC_JAILBREAK)) { + // Close the socket. + sceNetSocketClose(sock); + klog("[GeneralIPC] Failed to send command.\n"); return false; } @@ -198,11 +277,17 @@ bool GeneralIPC::Jailbreak(int pid) int result = 0; if (!Sockets::RecvInt(sock, &result)) { + // Close the socket. + sceNetSocketClose(sock); + klog("[GeneralIPC] Failed to recv result.\n"); return false; } - return result == 1; + // Close the socket. + sceNetSocketClose(sock); + + return result == GIPC_OK; } bool GeneralIPC::Jail(int pid) @@ -218,6 +303,9 @@ bool GeneralIPC::Jail(int pid) // Send the command. if (!SendCommand(sock, GIPC_JAIL)) { + // Close the socket. + sceNetSocketClose(sock); + klog("[GeneralIPC] Failed to send command.\n"); return false; } @@ -226,9 +314,15 @@ bool GeneralIPC::Jail(int pid) int result = 0; if (!Sockets::RecvInt(sock, &result)) { + // Close the socket. + sceNetSocketClose(sock); + klog("[GeneralIPC] Failed to recv result.\n"); return false; } - return result == 1; + // Close the socket. + sceNetSocketClose(sock); + + return result == GIPC_OK; } \ No newline at end of file diff --git a/Playstation/OrbisLibAPI/GeneralIPC.h b/Playstation/OrbisLibAPI/GeneralIPC.h index 30fb403..4074a87 100644 --- a/Playstation/OrbisLibAPI/GeneralIPC.h +++ b/Playstation/OrbisLibAPI/GeneralIPC.h @@ -8,6 +8,7 @@ private: static bool SendCommand(OrbisNetId Sock, int Command); public: + static bool TestConnection(int pid); static bool GetLibraryList(int pid, std::vector& Libraries); static bool LoadLibrary(int pid, const char* Path, int* HandleOut); static bool UnLoadLibrary(int pid, int Handle); diff --git a/Playstation/OrbisLibAPI/SocketListener.cpp b/Playstation/OrbisLibAPI/SocketListener.cpp index f5eed43..9e7cc93 100644 --- a/Playstation/OrbisLibAPI/SocketListener.cpp +++ b/Playstation/OrbisLibAPI/SocketListener.cpp @@ -127,10 +127,8 @@ void* SocketListener::ListenThread(void* tdParam) return ((SocketListener*)tdParam)->DoWork(); } - SocketListener::SocketListener(void(*ClientCallBack)(void* tdParam, OrbisNetId Sock, OrbisNetInAddr sin_addr), void* tdParam, unsigned short Port) { - klog("Socket Listener.\n"); this->ClientCallBack = ClientCallBack; this->tdParam = tdParam; this->ServerRunning = true; @@ -145,7 +143,7 @@ SocketListener::~SocketListener() klog("~Socket Listener.\n"); this->ServerRunning = false; - while (!this->ThreadCleanedUp) { sceKernelUsleep(10); } + scePthreadJoin(*ListenThreadHandle, nullptr); klog("Destruction sucessful.\n"); } \ No newline at end of file diff --git a/Playstation/OrbisLibAPI/Version.h b/Playstation/OrbisLibAPI/Version.h index da06592..302f62f 100644 --- a/Playstation/OrbisLibAPI/Version.h +++ b/Playstation/OrbisLibAPI/Version.h @@ -1,11 +1,11 @@ -#pragma once -#define ORBISLIB_MAJOR 3 -#define ORBISLIB_MINOR 0 -#define ORBISLIB_BUILDVERSION 951 -#define stringify(a) stringify_(a) -#define stringify_(a) #a -#if defined(_DEBUG) -#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Dev Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__) -#else -#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__) -#endif +#pragma once +#define ORBISLIB_MAJOR 3 +#define ORBISLIB_MINOR 0 +#define ORBISLIB_BUILDVERSION 984 +#define stringify(a) stringify_(a) +#define stringify_(a) #a +#if defined(_DEBUG) +#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Dev Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__) +#else +#define ORBISLIB_BUILDSTRING ("[OrbisLib Daemon " stringify(ORBISLIB_MAJOR) "." stringify(ORBISLIB_MINOR) "] Build " stringify(ORBISLIB_BUILDVERSION) " " __DATE__ " " __TIME__) +#endif diff --git a/Playstation/OrbisLibAPI/main.cpp b/Playstation/OrbisLibAPI/main.cpp index 256c7c6..a053fe5 100644 --- a/Playstation/OrbisLibAPI/main.cpp +++ b/Playstation/OrbisLibAPI/main.cpp @@ -21,8 +21,16 @@ void exiting() } +// Signal handler function +void signal_handler(int signum) { + klog("Signal %d\n", signum); +} + int main() { + signal(17, signal_handler); + signal(SIGTERM, signal_handler); + // Jailbreak our current process. if (!Jailbreak()) { diff --git a/Playstation/OrbisLibGeneralHelper/OrbisLibGeneralHelper.cpp b/Playstation/OrbisLibGeneralHelper/OrbisLibGeneralHelper.cpp index 436b364..9a910d2 100644 --- a/Playstation/OrbisLibGeneralHelper/OrbisLibGeneralHelper.cpp +++ b/Playstation/OrbisLibGeneralHelper/OrbisLibGeneralHelper.cpp @@ -83,6 +83,12 @@ void ListenerClientThread(void* tdParam, OrbisNetId Sock) klog("Invalid Command enum %i\n", Command); break; + case GIPC_HELLO: + + Sockets::SendInt(Sock, GIPC_OK); + + break; + case GIPC_LIB_LIST: SendLibraryList(Sock); // Really Only needed for the path. break; diff --git a/Windows/OrbisLibraryManager/OrbisLibraryManager.xaml b/Windows/OrbisLibraryManager/OrbisLibraryManager.xaml index ce52bdc..7749ee0 100644 --- a/Windows/OrbisLibraryManager/OrbisLibraryManager.xaml +++ b/Windows/OrbisLibraryManager/OrbisLibraryManager.xaml @@ -48,8 +48,10 @@ - @@ -65,19 +67,25 @@ + Height="25" + Click="LoadPRX_Click"/> + Height="25" + Click="UnloadPRX_Click"/> + Height="25" + Click="ReloadPRX_Click"/> @@ -87,8 +95,9 @@ - @@ -127,13 +136,14 @@ ImageMargin="2" Click="DetachProcess_Click"/> - + ImageMargin="5" + Click="LoadSomething_Click"/> + ImageMargin="1" + Click="KillProcess_Click"/> + ImageMargin="0" + Click="RestartTarget_Click"/> + ImageMargin="0" + Click="ShutdownTarget_Click"/> @@ -187,7 +200,10 @@ - + + + + diff --git a/Windows/OrbisLibraryManager/OrbisLibraryManager.xaml.cs b/Windows/OrbisLibraryManager/OrbisLibraryManager.xaml.cs index fe4fc0b..cf43f26 100644 --- a/Windows/OrbisLibraryManager/OrbisLibraryManager.xaml.cs +++ b/Windows/OrbisLibraryManager/OrbisLibraryManager.xaml.cs @@ -1,10 +1,13 @@ -using OrbisLib2.Common.Dispatcher; +using OrbisLib2.Common.Database.Types; +using OrbisLib2.Common.Dispatcher; using OrbisLib2.General; using OrbisLib2.Targets; +using OrbisLib2.Dialog; using SimpleUI.Controls; -using System; using System.Threading.Tasks; using System.Windows; +using System.Linq; +using System.Threading; namespace OrbisLibraryManager { @@ -20,22 +23,11 @@ namespace OrbisLibraryManager Events.ProcAttach += Events_ProcAttach; Events.ProcDetach += Events_ProcDetach; - } + Events.ProcDie += Events_ProcDie; + Events.TargetStateChanged += Events_TargetStateChanged; - private void Events_ProcDetach(object? sender, ProcDetachEvent e) - { - if(e.SendingTarget.IPAddress == TargetManager.SelectedTarget.IPAddress) - { - Console.WriteLine("ProcDetach"); - } - } - - private void Events_ProcAttach(object? sender, ProcAttachEvent e) - { - if (e.SendingTarget.IPAddress == TargetManager.SelectedTarget.IPAddress) - { - Console.WriteLine($"ProcAttach {e.NewProcessId}"); - } + // Update State + Task.Run(() => EnableTargetOptions(TargetManager.SelectedTarget.Info.Status == TargetStatusType.APIAvailable)); } private void RefreshLibraryList() @@ -62,9 +54,191 @@ namespace OrbisLibraryManager }); } + #region Events + + private void EnableProgram(bool Attached) + { + if(Attached) + { + RefreshLibraryList(); + } + else + { + LibraryList.ItemsSource = null; + } + + LoadPRX.IsEnabled = Attached; + UnloadPRX.IsEnabled = Attached; + ReloadPRX.IsEnabled = Attached; + + RefreshLibraries.IsEnabled = Attached; + UnloadLibrary.IsEnabled = Attached; + ReloadLibrary.IsEnabled = Attached; + + DetachProcess.IsEnabled = Attached; + KillProcess.IsEnabled = Attached; + } + + private void EnableTargetOptions(bool state) + { + Dispatcher.Invoke(() => + { + AttachProcess.IsEnabled = state; + DetachProcess.IsEnabled = state; + LoadSomething.IsEnabled = state; + RestartTarget.IsEnabled = state; + ShutdownTarget.IsEnabled = state; + + EnableProgram(TargetManager.SelectedTarget.Debug.IsDebugging); + }); + } + + private void Events_TargetStateChanged(object? sender, TargetStateChangedEvent e) + { + EnableTargetOptions(e.State == TargetStateChangedEvent.TargetState.APIAvailable); + } + + private void Events_ProcDie(object? sender, ProcDieEvent e) + { + if (e.SendingTarget.IPAddress == TargetManager.SelectedTarget.IPAddress) + { + Dispatcher.Invoke(() => + { + CurrentDebuggingProccess.FieldText = "N/A"; + EnableProgram(false); + }); + } + } + + private void Events_ProcDetach(object? sender, ProcDetachEvent e) + { + if(e.SendingTarget.IPAddress == TargetManager.SelectedTarget.IPAddress) + { + Dispatcher.Invoke(() => + { + CurrentDebuggingProccess.FieldText = "N/A"; + EnableProgram(false); + }); + } + } + + private void Events_ProcAttach(object? sender, ProcAttachEvent e) + { + if (e.SendingTarget.IPAddress == TargetManager.SelectedTarget.IPAddress) + { + var processList = TargetManager.SelectedTarget.Process.GetList(); + var proc = processList.Find(x => x.ProcessId == e.NewProcessId); + if(proc != null) + { + Dispatcher.Invoke(() => + { + CurrentDebuggingProccess.FieldText = $"{proc.Name}({e.NewProcessId})"; + EnableProgram(true); + }); + } + } + } + + #endregion + + #region Context Menu + + private void Refresh_Click(object sender, RoutedEventArgs e) + { + RefreshLibraryList(); + } + + private void UnloadLibrary_Click(object sender, RoutedEventArgs e) + { + var selectedLibrary = LibraryList.SelectedItems.Cast().FirstOrDefault(); + if(selectedLibrary != null) + { + Task.Run(() => + { + TargetManager.SelectedTarget.Debug.UnloadLibrary((int)selectedLibrary.Handle); + Dispatcher.Invoke(() => RefreshLibraryList()); + }); + } + } + + private void ReloadLibrary_Click(object sender, RoutedEventArgs e) + { + var selectedLibrary = LibraryList.SelectedItems.Cast().FirstOrDefault(); + if (selectedLibrary != null) + { + Task.Run(() => + { + TargetManager.SelectedTarget.Debug.UnloadLibrary((int)selectedLibrary.Handle); + Thread.Sleep(2000); + TargetManager.SelectedTarget.Debug.LoadLibrary(selectedLibrary.Path); + Dispatcher.Invoke(() => RefreshLibraryList()); + }); + } + } + + #endregion + + #region Buttons + + private void LoadPRX_Click(object sender, RoutedEventArgs e) + { + var libraryList = TargetManager.SelectedTarget.Debug.GetLibraries(); + var library = libraryList.Find(x => x.Path == SPRXPath.FieldText); + if (library == null) + { + Task.Run(() => + { + TargetManager.SelectedTarget.Debug.LoadLibrary(SPRXPath.FieldText); + Dispatcher.Invoke(() => RefreshLibraryList()); + }); + } + else + { + SimpleMessageBox.ShowError(Window.GetWindow(this), $"Could not load \"{SPRXPath}\" since it is already loaded.", "Error: Failed to load SPRX."); + } + } + + private void UnloadPRX_Click(object sender, RoutedEventArgs e) + { + var libraryList = TargetManager.SelectedTarget.Debug.GetLibraries(); + var library = libraryList.Find(x => x.Path == SPRXPath.FieldText); + if (library != null) + { + Task.Run(() => + { + TargetManager.SelectedTarget.Debug.UnloadLibrary((int)library.Handle); + Dispatcher.Invoke(() => RefreshLibraryList()); + }); + } + else + { + SimpleMessageBox.ShowError(Window.GetWindow(this), $"Could not unload \"{SPRXPath}\" since it is not loaded.", "Error: Failed to unload SPRX."); + } + } + + private void ReloadPRX_Click(object sender, RoutedEventArgs e) + { + var libraryList = TargetManager.SelectedTarget.Debug.GetLibraries(); + var library = libraryList.Find(x => x.Path == SPRXPath.FieldText); + if (library != null) + { + Task.Run(() => + { + TargetManager.SelectedTarget.Debug.UnloadLibrary((int)library.Handle); + Thread.Sleep(2000); + TargetManager.SelectedTarget.Debug.LoadLibrary(library.Path); + Dispatcher.Invoke(() => RefreshLibraryList()); + }); + } + else + { + SimpleMessageBox.ShowError(Window.GetWindow(this), $"Could not reload \"{SPRXPath}\" since it is not loaded.", "Error: Failed to reload SPRX."); + } + } + private void AttachProcess_Click(object sender, RoutedEventArgs e) { - OrbisLib2.Dialog.SelectProcess.ShowDialog(GetWindow(this)); + SelectProcess.ShowDialog(GetWindow(this)); } private void DetachProcess_Click(object sender, RoutedEventArgs e) @@ -72,9 +246,39 @@ namespace OrbisLibraryManager TargetManager.SelectedTarget.Debug.Detach(); } - private void Refresh_Click(object sender, RoutedEventArgs e) + private void LoadSomething_Click(object sender, RoutedEventArgs e) { - RefreshLibraryList(); + } + + private void KillProcess_Click(object sender, RoutedEventArgs e) + { + var currentTarget = TargetManager.SelectedTarget; + var processList = TargetManager.SelectedTarget.Process.GetList(); + var process = processList.Find(x => x.ProcessId == currentTarget.Debug.GetCurrentProcessId()); + if(process != null) + { + if(process.AppId > 0) + { + currentTarget.Application.Stop(process.TitleId); + } + else + { + SimpleMessageBox.ShowError(Window.GetWindow(this), $"Could not kill process \"{process.Name}\" because Orbis Suite doesnt currently support killing processes with out an appId.", "Error: Could not kill this process."); + } + } + } + + private void RestartTarget_Click(object sender, RoutedEventArgs e) + { + TargetManager.SelectedTarget.Reboot(); + } + + private void ShutdownTarget_Click(object sender, RoutedEventArgs e) + { + TargetManager.SelectedTarget.Shutdown(); + } + + #endregion } } diff --git a/Windows/OrbisNeighborHood/Resources/BuildNumber.txt b/Windows/OrbisNeighborHood/Resources/BuildNumber.txt index d61563f..42dfd9d 100644 --- a/Windows/OrbisNeighborHood/Resources/BuildNumber.txt +++ b/Windows/OrbisNeighborHood/Resources/BuildNumber.txt @@ -1 +1 @@ -2336 +2371 diff --git a/Windows/OrbisNeighborHood/Resources/BuildString.txt b/Windows/OrbisNeighborHood/Resources/BuildString.txt index b72e2a4..ff9132f 100644 --- a/Windows/OrbisNeighborHood/Resources/BuildString.txt +++ b/Windows/OrbisNeighborHood/Resources/BuildString.txt @@ -1 +1 @@ -Version 3.0.2336 Debug Build Friday January 06 2023 10:36 PM +Version 3.0.2371 Debug Build Saturday January 07 2023 8:48 PM