mirror of https://github.com/PCSX2/pcsx2.git
Win32: Added stdout and stderr pipe support for the ConsoleLogger; such that plugins using printf or fprintf will have their messages show up in the new-style console log and in the emuLog.txt file.
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1897 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
fc623d0719
commit
8d91458c95
|
@ -41,7 +41,7 @@
|
||||||
# define DeclareNoncopyableObject(classname) \
|
# define DeclareNoncopyableObject(classname) \
|
||||||
private: \
|
private: \
|
||||||
explicit classname(const classname&); \
|
explicit classname(const classname&); \
|
||||||
classname& operator=(const classname&);
|
classname& operator=(const classname&)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -62,7 +62,7 @@ extern void pcsx2_aligned_free(void* pmem);
|
||||||
template< typename T >
|
template< typename T >
|
||||||
class SafeArray
|
class SafeArray
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(SafeArray)
|
DeclareNoncopyableObject(SafeArray);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const int DefaultChunkSize = 0x1000 * sizeof(T);
|
static const int DefaultChunkSize = 0x1000 * sizeof(T);
|
||||||
|
@ -221,7 +221,7 @@ protected:
|
||||||
template< typename T >
|
template< typename T >
|
||||||
class SafeList
|
class SafeList
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(SafeList)
|
DeclareNoncopyableObject(SafeList);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const int DefaultChunkSize = 0x80 * sizeof(T);
|
static const int DefaultChunkSize = 0x80 * sizeof(T);
|
||||||
|
|
|
@ -117,7 +117,7 @@ namespace Threading
|
||||||
//
|
//
|
||||||
class PersistentThread
|
class PersistentThread
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(PersistentThread)
|
DeclareNoncopyableObject(PersistentThread);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef int (*PlainJoeFP)();
|
typedef int (*PlainJoeFP)();
|
||||||
|
@ -165,7 +165,7 @@ namespace Threading
|
||||||
//
|
//
|
||||||
class ScopedLock
|
class ScopedLock
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(ScopedLock)
|
DeclareNoncopyableObject(ScopedLock);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MutexLock& m_lock;
|
MutexLock& m_lock;
|
||||||
|
|
|
@ -635,7 +635,7 @@ __forceinline void xWrite( T val )
|
||||||
//
|
//
|
||||||
class xSmartJump
|
class xSmartJump
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(xSmartJump)
|
DeclareNoncopyableObject(xSmartJump);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
u8* m_baseptr; // base address of the instruction (passed to the instruction emitter)
|
u8* m_baseptr; // base address of the instruction (passed to the instruction emitter)
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include <gdk/gdkkeysyms.h>
|
#include <gdk/gdkkeysyms.h>
|
||||||
#include <gdk/gdkx.h>
|
#include <gdk/gdkx.h>
|
||||||
|
|
||||||
|
|
||||||
// Returns a WXK_* keycode, given osome kinda GKT input mess!
|
// Returns a WXK_* keycode, given osome kinda GKT input mess!
|
||||||
int TranslateGDKtoWXK( u32 keysym )
|
int TranslateGDKtoWXK( u32 keysym )
|
||||||
{
|
{
|
||||||
|
@ -277,3 +276,12 @@ int TranslateGDKtoWXK( u32 keysym )
|
||||||
return key_code;
|
return key_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewPipeRedir .. Homeless function for now .. This is as good a spot as any.
|
||||||
|
// Eventually we might be so fancy as to have a linux console pipe to our own console
|
||||||
|
// window, same as the Win32 one. Not sure how doable it is, and it's not as urgent
|
||||||
|
// anyway since Linux has better generic console support and commandline piping.
|
||||||
|
//
|
||||||
|
PipeRedirectionBase* NewPipeRedir()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -221,7 +221,7 @@ extern EmuPluginBindings EmuPlugins;
|
||||||
//
|
//
|
||||||
class PluginManagerBase
|
class PluginManagerBase
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject( PluginManagerBase )
|
DeclareNoncopyableObject( PluginManagerBase );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PluginManagerBase() {}
|
PluginManagerBase() {}
|
||||||
|
@ -250,7 +250,7 @@ public:
|
||||||
//
|
//
|
||||||
class PluginManager : public PluginManagerBase
|
class PluginManager : public PluginManagerBase
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject( PluginManager )
|
DeclareNoncopyableObject( PluginManager );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct PluginStatus_t
|
struct PluginStatus_t
|
||||||
|
|
|
@ -16,9 +16,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// This shouldn't break Win compiles, but it does.
|
// This shouldn't break Win compiles, but it does.
|
||||||
#ifdef __LINUX__
|
|
||||||
#include "PS2Edefs.h"
|
#include "PS2Edefs.h"
|
||||||
#endif
|
|
||||||
#include "System.h"
|
#include "System.h"
|
||||||
|
|
||||||
// Savestate Versioning!
|
// Savestate Versioning!
|
||||||
|
|
|
@ -296,10 +296,10 @@ protected:
|
||||||
|
|
||||||
wxScopedPtr<wxImageList> m_ToolbarImages;
|
wxScopedPtr<wxImageList> m_ToolbarImages;
|
||||||
wxScopedPtr<wxBitmap> m_Bitmap_Logo;
|
wxScopedPtr<wxBitmap> m_Bitmap_Logo;
|
||||||
|
wxScopedPtr<PipeRedirectionBase>m_PipeRedirHandle;
|
||||||
wxScopedPtr<SysCoreAllocations> m_CoreAllocs;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
wxScopedPtr<SysCoreAllocations> m_CoreAllocs;
|
||||||
wxScopedPtr<PluginManager> m_CorePlugins;
|
wxScopedPtr<PluginManager> m_CorePlugins;
|
||||||
wxScopedPtr<SysCoreThread> m_CoreThread;
|
wxScopedPtr<SysCoreThread> m_CoreThread;
|
||||||
|
|
||||||
|
|
|
@ -393,7 +393,16 @@ bool Pcsx2App::OnInit()
|
||||||
|
|
||||||
g_Conf.reset( new AppConfig() );
|
g_Conf.reset( new AppConfig() );
|
||||||
|
|
||||||
wxLocale::AddCatalogLookupPathPrefix( wxGetCwd() );
|
try
|
||||||
|
{
|
||||||
|
m_PipeRedirHandle.reset( NewPipeRedir() );
|
||||||
|
wxLocale::AddCatalogLookupPathPrefix( wxGetCwd() );
|
||||||
|
}
|
||||||
|
catch( Exception::RuntimeError& ex )
|
||||||
|
{
|
||||||
|
// Entirely non-critical errors. Log 'em and move along.
|
||||||
|
Console::Error( ex.FormatDiagnosticMessage() );
|
||||||
|
}
|
||||||
|
|
||||||
#define pxMessageBoxEventThing(func) \
|
#define pxMessageBoxEventThing(func) \
|
||||||
(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(pxMessageBoxEventFunction, &func )
|
(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(pxMessageBoxEventFunction, &func )
|
||||||
|
@ -420,6 +429,8 @@ bool Pcsx2App::OnInit()
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
InitDefaultGlobalAccelerators();
|
||||||
|
|
||||||
delete wxLog::SetActiveTarget( new pxLogConsole() );
|
delete wxLog::SetActiveTarget( new pxLogConsole() );
|
||||||
ReadUserModeSettings();
|
ReadUserModeSettings();
|
||||||
|
|
||||||
|
@ -725,7 +736,6 @@ Pcsx2App::Pcsx2App() :
|
||||||
{
|
{
|
||||||
SetAppName( L"pcsx2" );
|
SetAppName( L"pcsx2" );
|
||||||
BuildCommandHash();
|
BuildCommandHash();
|
||||||
InitDefaultGlobalAccelerators();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Pcsx2App::~Pcsx2App()
|
Pcsx2App::~Pcsx2App()
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include <wx/file.h>
|
#include <wx/file.h>
|
||||||
#include <wx/textfile.h>
|
#include <wx/textfile.h>
|
||||||
|
|
||||||
// Custom ConsoleLogger, because the built-in wxWidgets one is poop.
|
using Console::Colors;
|
||||||
|
|
||||||
BEGIN_DECLARE_EVENT_TYPES()
|
BEGIN_DECLARE_EVENT_TYPES()
|
||||||
DECLARE_EVENT_TYPE(wxEVT_LOG_Write, -1)
|
DECLARE_EVENT_TYPE(wxEVT_LOG_Write, -1)
|
||||||
|
@ -37,7 +37,8 @@ DEFINE_EVENT_TYPE(wxEVT_SetTitleText)
|
||||||
DEFINE_EVENT_TYPE(wxEVT_DockConsole)
|
DEFINE_EVENT_TYPE(wxEVT_DockConsole)
|
||||||
DEFINE_EVENT_TYPE(wxEVT_SemaphoreWait)
|
DEFINE_EVENT_TYPE(wxEVT_SemaphoreWait)
|
||||||
|
|
||||||
using Console::Colors;
|
// C++ requires abstract destructors to exist, even thought hey're abstract.
|
||||||
|
PipeRedirectionBase::~PipeRedirectionBase() throw() {}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
|
|
@ -26,11 +26,31 @@ using namespace Threading;
|
||||||
|
|
||||||
class LogWriteEvent;
|
class LogWriteEvent;
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// PipeRedirectionBase
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// Implementations for this class are found in Win/Lnx specific modules. Class creation
|
||||||
|
// should be done using NewPipeRedir() only (hence the protected constructor in this class).
|
||||||
|
//
|
||||||
|
class PipeRedirectionBase
|
||||||
|
{
|
||||||
|
DeclareNoncopyableObject( PipeRedirectionBase );
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
public:
|
||||||
// pxLogConsole
|
virtual ~PipeRedirectionBase() throw()=0; // abstract destructor, forces abstract class behavior
|
||||||
|
|
||||||
|
protected:
|
||||||
|
PipeRedirectionBase() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
extern PipeRedirectionBase* NewPipeRedir();
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// pxLogConsole
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
// This is a custom logging facility that pipes wxLog messages to our very own console
|
// This is a custom logging facility that pipes wxLog messages to our very own console
|
||||||
// log window.
|
// log window. Useful for catching and redirecting wx's internal logs (although like
|
||||||
|
// 3/4ths of them are worthless and we would probably rather ignore them anyway).
|
||||||
//
|
//
|
||||||
class pxLogConsole : public wxLog
|
class pxLogConsole : public wxLog
|
||||||
{
|
{
|
||||||
|
@ -41,10 +61,12 @@ protected:
|
||||||
virtual void DoLog(wxLogLevel level, const wxChar *szString, time_t t);
|
virtual void DoLog(wxLogLevel level, const wxChar *szString, time_t t);
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// ConsoleThreadTest -- useful class for unit testing the thread safety and general performance
|
// --------------------------------------------------------------------------------------
|
||||||
// of the console logger.
|
// ConsoleThreadTest -- useful class for unit testing the thread safety and general performance
|
||||||
//
|
// of the console logger.
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class ConsoleTestThread : public PersistentThread
|
class ConsoleTestThread : public PersistentThread
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -63,12 +85,12 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
// ConsoleLogFrame -- Because the one built in wx is poop.
|
||||||
//
|
// --------------------------------------------------------------------------------------
|
||||||
class ConsoleLogFrame : public wxFrame
|
class ConsoleLogFrame : public wxFrame
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(ConsoleLogFrame)
|
DeclareNoncopyableObject(ConsoleLogFrame);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef AppConfig::ConsoleLogOptions ConLogConfig;
|
typedef AppConfig::ConsoleLogOptions ConLogConfig;
|
||||||
|
@ -76,7 +98,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
class ColorArray
|
class ColorArray
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(ColorArray)
|
DeclareNoncopyableObject(ColorArray);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SafeArray<wxTextAttr> m_table;
|
SafeArray<wxTextAttr> m_table;
|
||||||
|
|
|
@ -1890,6 +1890,14 @@
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="Windows"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\WinSysExec.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="AppHost"
|
Name="AppHost"
|
||||||
|
@ -2528,7 +2536,7 @@
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\WinSysExec.cpp"
|
RelativePath="..\WinConsolePipe.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
|
|
@ -0,0 +1,276 @@
|
||||||
|
/* PCSX2 - PS2 Emulator for PCs
|
||||||
|
* Copyright (C) 2002-2009 PCSX2 Dev Team
|
||||||
|
*
|
||||||
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||||
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||||
|
* ation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||||
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||||
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PrecompiledHeader.h"
|
||||||
|
#include "Win32.h"
|
||||||
|
|
||||||
|
#include "App.h"
|
||||||
|
#include "ConsoleLogger.h"
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// Exception::Win32Error
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace Exception
|
||||||
|
{
|
||||||
|
class Win32Error : public RuntimeError
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int ErrorId;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DEFINE_EXCEPTION_COPYTORS( Win32Error )
|
||||||
|
|
||||||
|
Win32Error( const char* msg="" )
|
||||||
|
{
|
||||||
|
ErrorId = GetLastError();
|
||||||
|
BaseException::InitBaseEx( msg );
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString GetMsgFromWindows() const
|
||||||
|
{
|
||||||
|
if (!ErrorId)
|
||||||
|
return wxString();
|
||||||
|
|
||||||
|
const DWORD BUF_LEN = 2048;
|
||||||
|
TCHAR t_Msg[BUF_LEN];
|
||||||
|
if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, ErrorId, 0, t_Msg, BUF_LEN, 0))
|
||||||
|
return wxsFormat( L"Win32 Error #%d: %s", ErrorId, t_Msg );
|
||||||
|
|
||||||
|
return wxsFormat( L"Win32 Error #%d (no text msg available)", ErrorId );
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual wxString FormatDisplayMessage() const
|
||||||
|
{
|
||||||
|
return m_message_user + L"\n\n" + GetMsgFromWindows();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual wxString FormatDiagnosticMessage() const
|
||||||
|
{
|
||||||
|
return m_message_diag + L"\n\t" + GetMsgFromWindows();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
// Win32 Console Pipes
|
||||||
|
// As a courtesy and convenience, we redirect stdout/stderr to the console and logfile.
|
||||||
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
using namespace Threading;
|
||||||
|
|
||||||
|
static void CreatePipe( HANDLE& ph_Pipe, HANDLE& ph_File )
|
||||||
|
{
|
||||||
|
// Create a threadsafe unique name for the Pipe
|
||||||
|
static int s32_Counter = 0;
|
||||||
|
|
||||||
|
wxString s_PipeName;
|
||||||
|
s_PipeName.Printf( L"\\\\.\\pipe\\pcsxPipe%X_%X_%X_%X",
|
||||||
|
GetCurrentProcessId(), GetCurrentThreadId(), GetTickCount(), s32_Counter++);
|
||||||
|
|
||||||
|
SECURITY_ATTRIBUTES k_Secur;
|
||||||
|
k_Secur.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
|
k_Secur.lpSecurityDescriptor = 0;
|
||||||
|
k_Secur.bInheritHandle = TRUE;
|
||||||
|
|
||||||
|
ph_Pipe = CreateNamedPipe(s_PipeName, PIPE_ACCESS_DUPLEX, 0, 1, 2048, 2048, 0, &k_Secur);
|
||||||
|
|
||||||
|
if (ph_Pipe == INVALID_HANDLE_VALUE)
|
||||||
|
throw Exception::Win32Error( "Error creating Named Pipe." );
|
||||||
|
|
||||||
|
ph_File = CreateFile(s_PipeName, GENERIC_READ|GENERIC_WRITE, 0, &k_Secur, OPEN_EXISTING, 0, NULL);
|
||||||
|
|
||||||
|
if (ph_File == INVALID_HANDLE_VALUE)
|
||||||
|
throw Exception::Win32Error( "Error creating Pipe Reader." );
|
||||||
|
|
||||||
|
if (!ConnectNamedPipe(ph_Pipe, NULL))
|
||||||
|
{
|
||||||
|
if (GetLastError() != ERROR_PIPE_CONNECTED)
|
||||||
|
throw Exception::Win32Error( "Error connecting Pipe." );
|
||||||
|
}
|
||||||
|
|
||||||
|
SetHandleInformation(ph_Pipe, HANDLE_FLAG_INHERIT, 0);
|
||||||
|
SetHandleInformation(ph_File, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads from the Pipe and appends the read data to ps_Data
|
||||||
|
// returns TRUE if something was printed to console, or false if the stdout/err were idle.
|
||||||
|
static bool ReadPipe(HANDLE h_Pipe, Console::Colors color )
|
||||||
|
{
|
||||||
|
// IMPORTANT: Check if there is data that can be read.
|
||||||
|
// The first console output will be lost if ReadFile() is called before data becomes available!
|
||||||
|
// It does not make any sense but the following 5 lines are indispensable!!
|
||||||
|
DWORD u32_Avail = 0;
|
||||||
|
if (!PeekNamedPipe(h_Pipe, 0, 0, 0, &u32_Avail, 0))
|
||||||
|
throw Exception::Win32Error( "Error peeking Pipe." );
|
||||||
|
|
||||||
|
if (!u32_Avail)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
char s8_Buf[2049];
|
||||||
|
DWORD u32_Read = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (!ReadFile(h_Pipe, s8_Buf, sizeof(s8_Buf)-1, &u32_Read, NULL))
|
||||||
|
{
|
||||||
|
if (GetLastError() != ERROR_IO_PENDING)
|
||||||
|
throw Exception::Win32Error( "Error reading Pipe." );
|
||||||
|
}
|
||||||
|
|
||||||
|
// ATTENTION: The Console always prints ANSI to the pipe independent if compiled as UNICODE or MBCS!
|
||||||
|
s8_Buf[u32_Read] = 0;
|
||||||
|
OemToCharA(s8_Buf, s8_Buf); // convert DOS codepage -> ANSI
|
||||||
|
Console::Write( color, s8_Buf ); // convert ANSI -> Unicode if compiled as Unicode
|
||||||
|
}
|
||||||
|
while (u32_Read == sizeof(s8_Buf)-1);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
class WinPipeThread : public PersistentThread
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
const HANDLE& mh_OutPipe;
|
||||||
|
const HANDLE& mh_ErrPipe;
|
||||||
|
|
||||||
|
public:
|
||||||
|
WinPipeThread( const HANDLE& outpipe, const HANDLE& errpipe ) :
|
||||||
|
mh_OutPipe( outpipe )
|
||||||
|
, mh_ErrPipe( errpipe )
|
||||||
|
//, mk_OverOut( overout )
|
||||||
|
//, mk_OverErr( overerr )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~WinPipeThread() throw()
|
||||||
|
{
|
||||||
|
PersistentThread::Cancel();
|
||||||
|
SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int ExecuteTask()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
Sleep( 100 );
|
||||||
|
pthread_testcancel();
|
||||||
|
ReadPipe(mh_OutPipe, Color_Black );
|
||||||
|
ReadPipe(mh_ErrPipe, Color_Red );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( Exception::Win32Error& ex )
|
||||||
|
{
|
||||||
|
// Log error, and fail silently. It's not really important if the
|
||||||
|
// pipe fails. PCSX2 will run fine without it in any case.
|
||||||
|
Console::Error( ex.FormatDiagnosticMessage() );
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class WinPipeRedirection : public PipeRedirectionBase
|
||||||
|
{
|
||||||
|
DeclareNoncopyableObject( WinPipeRedirection );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HANDLE mh_OutPipe;
|
||||||
|
HANDLE mh_ErrPipe;
|
||||||
|
HANDLE mh_OutFile;
|
||||||
|
HANDLE mh_ErrFile;
|
||||||
|
|
||||||
|
int m_hCrtOut;
|
||||||
|
int m_hCrtErr;
|
||||||
|
|
||||||
|
FILE* h_fpOut;
|
||||||
|
FILE* h_fpErr;
|
||||||
|
|
||||||
|
WinPipeThread m_Thread;
|
||||||
|
|
||||||
|
public:
|
||||||
|
WinPipeRedirection();
|
||||||
|
virtual ~WinPipeRedirection() throw();
|
||||||
|
};
|
||||||
|
|
||||||
|
WinPipeRedirection::WinPipeRedirection() :
|
||||||
|
mh_OutPipe(INVALID_HANDLE_VALUE)
|
||||||
|
, mh_ErrPipe(INVALID_HANDLE_VALUE)
|
||||||
|
, mh_OutFile(INVALID_HANDLE_VALUE)
|
||||||
|
, mh_ErrFile(INVALID_HANDLE_VALUE)
|
||||||
|
, m_hCrtOut(-1)
|
||||||
|
, m_hCrtErr(-1)
|
||||||
|
, h_fpOut(NULL)
|
||||||
|
, h_fpErr(NULL)
|
||||||
|
|
||||||
|
, m_Thread( mh_OutPipe, mh_ErrPipe )
|
||||||
|
{
|
||||||
|
CreatePipe(mh_OutPipe, mh_OutFile );
|
||||||
|
CreatePipe(mh_ErrPipe, mh_ErrFile );
|
||||||
|
|
||||||
|
SetStdHandle( STD_OUTPUT_HANDLE, mh_OutFile );
|
||||||
|
SetStdHandle( STD_ERROR_HANDLE, mh_ErrFile );
|
||||||
|
|
||||||
|
m_hCrtOut = _open_osfhandle( (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT );
|
||||||
|
m_hCrtErr = _open_osfhandle( (intptr_t)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT );
|
||||||
|
|
||||||
|
h_fpOut = _fdopen( m_hCrtOut, "w" );
|
||||||
|
h_fpErr = _fdopen( m_hCrtErr, "w" );
|
||||||
|
|
||||||
|
*stdout = *h_fpOut;
|
||||||
|
*stderr = *h_fpErr;
|
||||||
|
|
||||||
|
setvbuf( stdout, NULL, _IONBF, 0 );
|
||||||
|
setvbuf( stderr, NULL, _IONBF, 0 );
|
||||||
|
|
||||||
|
m_Thread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
WinPipeRedirection::~WinPipeRedirection() throw()
|
||||||
|
{
|
||||||
|
m_Thread.Cancel();
|
||||||
|
|
||||||
|
#define safe_CloseHandle( ptr ) \
|
||||||
|
((void) (( ( ptr != INVALID_HANDLE_VALUE ) && (!!CloseHandle( ptr ), !!0) ), ptr = INVALID_HANDLE_VALUE))
|
||||||
|
|
||||||
|
safe_CloseHandle(mh_OutPipe);
|
||||||
|
safe_CloseHandle(mh_ErrPipe);
|
||||||
|
|
||||||
|
if( h_fpOut != NULL )
|
||||||
|
{
|
||||||
|
fclose( h_fpOut );
|
||||||
|
h_fpOut = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( h_fpErr != NULL )
|
||||||
|
{
|
||||||
|
fclose( h_fpErr );
|
||||||
|
h_fpErr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define safe_close( ptr ) \
|
||||||
|
((void) (( ( ptr != -1 ) && (!!_close( ptr ), !!0) ), ptr = -1))
|
||||||
|
|
||||||
|
// CrtOut and CrtErr are closed implicitly when closing fpOut/fpErr
|
||||||
|
// OutFile and ErrFile are closed implicitly when closing m_hCrtOut/Err
|
||||||
|
}
|
||||||
|
|
||||||
|
// The win32 specific implementation of PipeRedirection.
|
||||||
|
PipeRedirectionBase* NewPipeRedir()
|
||||||
|
{
|
||||||
|
return new WinPipeRedirection();
|
||||||
|
}
|
|
@ -15,11 +15,9 @@
|
||||||
|
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
#include "Win32.h"
|
#include "Win32.h"
|
||||||
|
|
||||||
#include <winnt.h>
|
#include <winnt.h>
|
||||||
#include "Common.h"
|
|
||||||
|
|
||||||
#include "cdvd/CDVD.h"
|
#include "Common.h"
|
||||||
|
|
||||||
int SysPageFaultExceptionFilter( EXCEPTION_POINTERS* eps )
|
int SysPageFaultExceptionFilter( EXCEPTION_POINTERS* eps )
|
||||||
{
|
{
|
||||||
|
@ -40,41 +38,3 @@ int SysPageFaultExceptionFilter( EXCEPTION_POINTERS* eps )
|
||||||
|
|
||||||
return EXCEPTION_CONTINUE_EXECUTION;
|
return EXCEPTION_CONTINUE_EXECUTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace HostSys
|
|
||||||
{
|
|
||||||
void *Mmap(uptr base, u32 size)
|
|
||||||
{
|
|
||||||
return VirtualAlloc((void*)base, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Munmap(uptr base, u32 size)
|
|
||||||
{
|
|
||||||
if( base == NULL ) return;
|
|
||||||
VirtualFree((void*)base, size, MEM_DECOMMIT);
|
|
||||||
VirtualFree((void*)base, 0, MEM_RELEASE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MemProtect( void* baseaddr, size_t size, PageProtectionMode mode, bool allowExecution )
|
|
||||||
{
|
|
||||||
DWORD winmode = 0;
|
|
||||||
|
|
||||||
switch( mode )
|
|
||||||
{
|
|
||||||
case Protect_NoAccess:
|
|
||||||
winmode = ( allowExecution ) ? PAGE_EXECUTE : PAGE_NOACCESS;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Protect_ReadOnly:
|
|
||||||
winmode = ( allowExecution ) ? PAGE_EXECUTE_READ : PAGE_READONLY;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Protect_ReadWrite:
|
|
||||||
winmode = ( allowExecution ) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD OldProtect; // enjoy my uselessness, yo!
|
|
||||||
VirtualProtect( baseaddr, size, winmode, &OldProtect );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#include "Win32.h"
|
|
Loading…
Reference in New Issue