Library Manager now complete just one last option needed, debugger will now throw an event when the process were attached to dies & testing for IPC so we dont try to load the helper multiple times.
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
enum GeneralIPCCommands
|
||||
{
|
||||
GIPC_HELLO,
|
||||
GIPC_LIB_LIST,
|
||||
GIPC_LIB_LOAD,
|
||||
GIPC_LIB_UNLOAD,
|
||||
|
||||
@@ -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<kinfo_proc> 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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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<LibraryPacket>& Libraries)
|
||||
{
|
||||
// Open a new local socket connection for the process.
|
||||
@@ -55,6 +92,9 @@ bool GeneralIPC::GetLibraryList(int pid, std::vector<LibraryPacket>& 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<LibraryPacket>& 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<LibraryPacket>& 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;
|
||||
}
|
||||
@@ -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<LibraryPacket>& Libraries);
|
||||
static bool LoadLibrary(int pid, const char* Path, int* HandleOut);
|
||||
static bool UnLoadLibrary(int pid, int Handle);
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -48,8 +48,10 @@
|
||||
<StackPanel HorizontalAlignment="Right"
|
||||
Margin="6">
|
||||
|
||||
<simpleControls:SimpleTextField FieldName="SPRX Path"
|
||||
FieldText="/data/something.sprx"
|
||||
<simpleControls:SimpleTextField Name="SPRXPath"
|
||||
FieldName="SPRX Path"
|
||||
FieldText=""
|
||||
IsReadOnly="False"
|
||||
VerticalContentAlignment="Center"
|
||||
Width="180"/>
|
||||
|
||||
@@ -65,19 +67,25 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<simpleControls:SimpleButton Grid.Column="0"
|
||||
Name="LoadPRX"
|
||||
Content="Load"
|
||||
Width="56"
|
||||
Height="25"/>
|
||||
Height="25"
|
||||
Click="LoadPRX_Click"/>
|
||||
|
||||
<simpleControls:SimpleButton Grid.Column="2"
|
||||
Name="UnloadPRX"
|
||||
Content="Unload"
|
||||
Width="56"
|
||||
Height="25"/>
|
||||
Height="25"
|
||||
Click="UnloadPRX_Click"/>
|
||||
|
||||
<simpleControls:SimpleButton Grid.Column="4"
|
||||
Name="ReloadPRX"
|
||||
Content="Reload"
|
||||
Width="56"
|
||||
Height="25"/>
|
||||
Height="25"
|
||||
Click="ReloadPRX_Click"/>
|
||||
</Grid>
|
||||
|
||||
|
||||
@@ -87,8 +95,9 @@
|
||||
<StackPanel HorizontalAlignment="Right"
|
||||
Margin="0 6 6 6">
|
||||
|
||||
<simpleControls:SimpleTextField FieldName="Currently Debugging"
|
||||
FieldText="SceShellUI.ELF (75)"
|
||||
<simpleControls:SimpleTextField Name="CurrentDebuggingProccess"
|
||||
FieldName="Currently Debugging"
|
||||
FieldText="N/A"
|
||||
VerticalContentAlignment="Center"
|
||||
Width="180"/>
|
||||
|
||||
@@ -127,13 +136,14 @@
|
||||
ImageMargin="2"
|
||||
Click="DetachProcess_Click"/>
|
||||
|
||||
<controls:ImageButton x:Name="Send"
|
||||
<controls:ImageButton x:Name="LoadSomething"
|
||||
Grid.Column="4"
|
||||
Width="25"
|
||||
Height="25"
|
||||
ToolTip="Browse for something to load from local machine"
|
||||
ImageSource="/OrbisLibraryManager;component/Images/Send.png"
|
||||
ImageMargin="5"/>
|
||||
ImageMargin="5"
|
||||
Click="LoadSomething_Click"/>
|
||||
|
||||
<controls:ImageButton x:Name="KillProcess"
|
||||
Grid.Column="6"
|
||||
@@ -141,7 +151,8 @@
|
||||
Height="25"
|
||||
ToolTip="Kills the currently attached process"
|
||||
ImageSource="/OrbisLibraryManager;component/Images/KillProcess.png"
|
||||
ImageMargin="1"/>
|
||||
ImageMargin="1"
|
||||
Click="KillProcess_Click"/>
|
||||
|
||||
<controls:ImageButton x:Name="RestartTarget"
|
||||
Grid.Column="8"
|
||||
@@ -149,7 +160,8 @@
|
||||
Height="25"
|
||||
ToolTip="Restart the Target"
|
||||
ImageSource="/OrbisLibraryManager;component/Images/Restart.png"
|
||||
ImageMargin="0"/>
|
||||
ImageMargin="0"
|
||||
Click="RestartTarget_Click"/>
|
||||
|
||||
<controls:ImageButton x:Name="ShutdownTarget"
|
||||
Grid.Column="10"
|
||||
@@ -157,7 +169,8 @@
|
||||
Height="25"
|
||||
ToolTip="Shutdown the Target"
|
||||
ImageSource="/OrbisLibraryManager;component/Images/Shutdown.png"
|
||||
ImageMargin="0"/>
|
||||
ImageMargin="0"
|
||||
Click="ShutdownTarget_Click"/>
|
||||
|
||||
</Grid>
|
||||
|
||||
@@ -187,7 +200,10 @@
|
||||
|
||||
<ListView.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="Refresh" Click="Refresh_Click"/>
|
||||
<MenuItem Name="RefreshLibraries" Header="Refresh Library List" Click="Refresh_Click"/>
|
||||
<Separator/>
|
||||
<MenuItem Name="UnloadLibrary" Header="Unload Library"/>
|
||||
<MenuItem Name="ReloadLibrary" Header="Reload Library"/>
|
||||
</ContextMenu>
|
||||
</ListView.ContextMenu>
|
||||
|
||||
|
||||
@@ -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<LibraryInfo>().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<LibraryInfo>().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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
2336
|
||||
2371
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user