Fixes Issue 419 by checking validity of StdHandle values. Also:

* handful of minor code cleanups, and some warning removals for ICC.
 * replaced the dualshock.png with a dualshock.jpg (120k smaller!)
 * Updated the About Box, and added Zeydlitz / ZZogl to the plugin author credits.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1902 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-09-22 04:37:11 +00:00
parent 1c7719e0ec
commit 6907b78640
19 changed files with 155 additions and 159 deletions

View File

@ -70,7 +70,11 @@
# endif
# else
# define jBREAKPOINT() __debugbreak();
# define jASSUME(exp) do { if(exp) ; else jBREAKPOINT(); } while(0);
# ifdef wxASSERT
# define jASSUME(exp) wxASSERT(exp)
# else
# define jASSUME(exp) do { if(exp) ; else jBREAKPOINT(); } while(0);
# endif
# endif
#endif

View File

@ -203,7 +203,7 @@ namespace x86Emitter
Factor++;
else
{
jASSUME( Index.IsEmpty() ); // or die if we already have an index!
DevAssert( Index.IsEmpty(), "x86Emitter: Only one scaled index register is allowed in an address modifier." );
Index = src;
Factor = 2;
}
@ -213,7 +213,7 @@ namespace x86Emitter
else if( Index.IsEmpty() )
Index = src;
else
assert( false ); // oops, only 2 regs allowed per ModRm!
wxASSERT_MSG( false, L"x86Emitter: address modifiers cannot have more than two index registers." ); // oops, only 2 regs allowed per ModRm!
return *this;
}
@ -237,7 +237,7 @@ namespace x86Emitter
else if( Index == src.Index )
Factor++;
else
assert( false ); // oops, only 2 regs allowed!
wxASSERT_MSG( false, L"x86Emitter: address modifiers cannot have more than two index registers." ); // oops, only 2 regs allowed per ModRm!
return *this;
}
@ -283,7 +283,7 @@ namespace x86Emitter
{
if( !is_s8( displacement ) )
{
assert( false );
wxASSERT( false );
// Don't ask. --arcum42
#if !defined(__LINUX__) || !defined(DEBUG)

View File

@ -282,7 +282,7 @@ int TranslateGDKtoWXK( u32 keysym )
// 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()
PipeRedirectionBase* NewPipeRedir( FILE* stdstream )
{
return NULL;
}

View File

@ -664,8 +664,7 @@ PluginManager::PluginManager( const wxString (&folders)[PluginId_Count] )
{
Console::Status( "Loading plugins..." );
const PluginInfo* pi = tbl_PluginInfo-1;
while( ++pi, pi->shortname != NULL )
const PluginInfo* pi = tbl_PluginInfo; do
{
const PluginsEnum_t pid = pi->id;
@ -700,7 +699,7 @@ PluginManager::PluginManager( const wxString (&folders)[PluginId_Count] )
// Bind Optional Functions
// (leave pointer null and do not generate error)
}
} while( ++pi, pi->shortname != NULL );
// Hack for PAD's stupid parameter passed on Init
PADinit = (_PADinit)m_info[PluginId_PAD].CommonBindings.Init;
@ -916,9 +915,9 @@ void PluginManager::Open()
{
Console::Status( "Opening plugins..." );
const PluginInfo* pi = tbl_PluginInfo-1;
while( ++pi, pi->shortname != NULL )
const PluginInfo* pi = tbl_PluginInfo; do {
g_plugins->Open( pi->id );
} while( ++pi, pi->shortname != NULL );
Console::Status( "Plugins opened successfully." );
}
@ -970,8 +969,7 @@ void PluginManager::Close( bool closegs )
void PluginManager::Init()
{
bool printlog = false;
const PluginInfo* pi = tbl_PluginInfo-1;
while( ++pi, pi->shortname != NULL )
const PluginInfo* pi = tbl_PluginInfo; do
{
const PluginsEnum_t pid = pi->id;
@ -985,7 +983,7 @@ void PluginManager::Init()
m_info[pid].IsInitialized = true;
if( 0 != m_info[pid].CommonBindings.Init() )
throw Exception::PluginInitError( pid );
}
} while( ++pi, pi->shortname != NULL );
if( EmuPlugins.Mcd == NULL )
{
@ -1106,13 +1104,10 @@ void PluginManager::Freeze( PluginsEnum_t pid, SaveStateBase& state )
bool PluginManager::KeyEvent( const keyEvent& evt )
{
const PluginInfo* pi = tbl_PluginInfo-1;
while( ++pi, pi->shortname != NULL )
{
const PluginInfo* pi = tbl_PluginInfo; do {
if( pi->id != PluginId_PAD )
m_info[pi->id].CommonBindings.KeyEvent( const_cast<keyEvent*>(&evt) );
}
} while( ++pi, pi->shortname != NULL );
return false;
}
@ -1135,9 +1130,9 @@ PluginManager* PluginManager_Create( const wxChar* (&folders)[PluginId_Count] )
{
wxString passins[PluginId_Count];
const PluginInfo* pi = tbl_PluginInfo-1;
while( ++pi, pi->shortname != NULL )
const PluginInfo* pi = tbl_PluginInfo; do {
passins[pi->id] = folders[pi->id];
} while( ++pi, pi->shortname != NULL );
return PluginManager_Create( passins );
}

View File

@ -318,22 +318,20 @@ __forceinline void _vuAddLowerStalls(VURegs * VU, _VURegsNum *VUregsn) {
#ifndef INT_VUDOUBLEHACK
static float __fastcall vuDouble(u32 f)
{
switch(f & 0x7f800000){
switch(f & 0x7f800000)
{
case 0x0:
f &= 0x80000000;
return *(float*)&f;
break;
case 0x7f800000:
{
u32 d;
d = (f & 0x80000000)|0x7f7fffff;
u32 d = (f & 0x80000000)|0x7f7fffff;
return *(float*)&d;
break;
}
default:
return *(float*)&f;
break;
}
return *(float*)&f;
}
#else
static __forceinline float vuDouble(u32 f)

View File

@ -298,7 +298,8 @@ protected:
wxScopedPtr<wxImageList> m_ToolbarImages;
wxScopedPtr<wxBitmap> m_Bitmap_Logo;
wxScopedPtr<PipeRedirectionBase>m_PipeRedirHandle;
wxScopedPtr<PipeRedirectionBase>m_StdoutRedirHandle;
wxScopedPtr<PipeRedirectionBase>m_StderrRedirHandle;
public:
wxScopedPtr<SysCoreAllocations> m_CoreAllocs;

View File

@ -325,13 +325,11 @@ void Pcsx2App::OnInitCmdLine( wxCmdLineParser& parser )
parser.AddSwitch( wxEmptyString,L"forcewiz",_("Forces PCSX2 to start the First-time Wizard") );
const PluginInfo* pi = tbl_PluginInfo-1;
while( ++pi, pi->shortname != NULL )
{
const PluginInfo* pi = tbl_PluginInfo; do {
parser.AddOption( wxEmptyString, pi->GetShortname().Lower(),
wxsFormat( _("specify the file to use as the %s plugin"), pi->GetShortname().c_str() )
);
}
} while( ++pi, pi->shortname != NULL );
parser.SetSwitchChars( L"-" );
}
@ -356,8 +354,7 @@ bool Pcsx2App::OnCmdLineParsed( wxCmdLineParser& parser )
//bool yay = parser.Found(L"nogui");
m_ForceWizard = parser.Found( L"forcewiz" );
const PluginInfo* pi = tbl_PluginInfo-1;
while( ++pi, pi->shortname != NULL )
const PluginInfo* pi = tbl_PluginInfo; do
{
wxString dest;
if( !parser.Found( pi->GetShortname().Lower(), &dest ) ) continue;
@ -377,7 +374,7 @@ bool Pcsx2App::OnCmdLineParsed( wxCmdLineParser& parser )
if( !result ) return false;
}
}
} while( ++pi, pi->shortname != NULL );
parser.Found( L"cfgpath", &OverrideOptions.SettingsFolder );
@ -394,16 +391,9 @@ bool Pcsx2App::OnInit()
g_Conf.reset( new AppConfig() );
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() );
}
m_StdoutRedirHandle.reset( NewPipeRedir(stdout) );
m_StderrRedirHandle.reset( NewPipeRedir(stderr) );
wxLocale::AddCatalogLookupPathPrefix( wxGetCwd() );
#define pxMessageBoxEventThing(func) \
(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(pxMessageBoxEventFunction, &func )

View File

@ -42,7 +42,7 @@ protected:
PipeRedirectionBase() {}
};
extern PipeRedirectionBase* NewPipeRedir();
extern PipeRedirectionBase* NewPipeRedir( FILE* stdstream );
// --------------------------------------------------------------------------------------
// pxLogConsole

View File

@ -47,19 +47,18 @@ namespace Dialogs
// --------------------------------------------------------------------------------------
Dialogs::AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ):
wxDialog( parent, id, _("About PCSX2"), parent->GetPosition()-wxSize( 32, 32 ) ),
m_bitmap_logo( this, wxID_ANY, wxGetApp().GetLogoBitmap(),
wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN ),
m_bitmap_ps2system( this, wxID_ANY, wxBitmap( EmbeddedImage<res_Dualshock>().Get() ),
wxDialogWithHelpers( parent, id, _("About PCSX2"), false ),
m_bitmap_dualshock( this, wxID_ANY, wxBitmap( EmbeddedImage<res_Dualshock>().Get() ),
wxDefaultPosition, wxDefaultSize, wxBORDER_SUNKEN )
{
static const wxString LabelAuthors = wxString::FromAscii(
"PCSX2, a PS2 emulator\n\n"
"Active Devs: Arcum42, Refraction,"
"drk||raziel, cottonvibes, gigaherz,"
"rama, Jake.Stine, saqib, Tmkk"
static const wxString LabelAuthors = wxString::FromUTF8(
"Developers"
"\n\n"
"Inactive devs: Alexey silinov, Aumatt,"
"v0.9.6+: Arcum42, Refraction,"
"drk||raziel, cottonvibes, gigaherz,"
"rama, Jake.Stine, saqib, Tmkk, pseudonym"
"\n\n"
"Previous versions: Alexey silinov, Aumatt,"
"Florin, goldfinger, Linuzappz, loser,"
"Nachbrenner, shadow, Zerofrog"
"\n\n"
@ -70,19 +69,23 @@ Dialogs::AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ):
"Webmasters: CKemu, Falcon4ever"
);
static const wxString LabelGreets = wxString::FromAscii(
"Contributors: Hiryu and Sjeep for libcvd (the iso parsing and\n"
"filesystem driver code), nneeve, pseudonym\n"
"\n"
"Plugin Specialists: ChickenLiver (Lilypad), Efp (efp),\n"
"Gabest (Gsdx, Cdvdolio, Xpad)\n"
"\n"
"Special thanks to: black_wd, Belmont, BGome, _Demo_, Dreamtime,\n"
static const wxString LabelGreets = wxString::FromUTF8(
"Contributors"
"\n\n"
"Hiryu and Sjeep for libcvd (the iso parsing and"
"filesystem driver code), nneeve (fpu and vu help)"
"\n\n"
"Plugin Specialists: ChickenLiver (Lilypad), Efp (efp),"
"Gabest (Gsdx, Cdvdolio, Xpad), Zeydlitz (ZZogl)"
"\n\n"
"Special thanks to: black_wd, Belmont, BGome, _Demo_, Dreamtime,"
"F|RES, MrBrown, razorblade, Seta-san, Skarmeth"
);
wxBoxSizer& mainSizer = *new wxBoxSizer( wxVERTICAL );
AddStaticText( mainSizer, _("PCSX2 - Playstation 2 Emulator") );
// This sizer holds text of the authors and a logo!
wxBoxSizer& AuthLogoSizer = *new wxBoxSizer( wxHORIZONTAL );
@ -95,20 +98,19 @@ Dialogs::AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ):
StaticTextCentered* label_auth = new StaticTextCentered( this, LabelAuthors );
StaticTextCentered* label_greets = new StaticTextCentered( this, LabelGreets );
label_auth->Wrap( m_bitmap_logo.GetSize().GetWidth() / 2 );
label_greets->Wrap( (m_bitmap_logo.GetSize().GetWidth() * 4) / 3 );
label_auth->Wrap( 340 );
label_greets->Wrap( 200 );
aboutUs.Add( label_auth, SizerFlags::StdSpace() );
aboutUs.Add( label_auth, SizerFlags::StdExpand() );
contribs.Add( label_greets, SizerFlags::StdExpand() );
AuthLogoSizer.Add( &aboutUs );
AuthLogoSizer.AddSpacer( 7 );
AuthLogoSizer.Add( &m_bitmap_logo, wxSizerFlags().Border( wxALL, 4 ) );
AuthLogoSizer.Add( &contribs );
ContribSizer.AddStretchSpacer( 1 );
ContribSizer.Add( &m_bitmap_ps2system, SizerFlags::StdSpace() );
ContribSizer.Add( &m_bitmap_dualshock, SizerFlags::StdSpace() );
ContribSizer.AddStretchSpacer( 1 );
ContribSizer.Add( &contribs, wxSizerFlags(7).HorzBorder().Expand() );
mainSizer.Add( &AuthLogoSizer, SizerFlags::StdSpace() );
@ -123,4 +125,6 @@ Dialogs::AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ):
mainSizer.Add( new wxButton( this, wxID_OK, L"I've seen enough"), SizerFlags::StdCenter() );
SetSizerAndFit( &mainSizer );
CenterOnScreen();
}

View File

@ -121,7 +121,7 @@ FirstTimeWizard::FirstTimeWizard( wxWindow* parent ) :
Connect( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, wxCommandEventHandler(FirstTimeWizard::OnDoubleClicked) );
}
FirstTimeWizard::~FirstTimeWizard()
FirstTimeWizard::~FirstTimeWizard() throw()
{
g_ApplyState.DoCleanup();
}

View File

@ -48,7 +48,7 @@ protected:
public:
FirstTimeWizard( wxWindow* parent );
virtual ~FirstTimeWizard();
virtual ~FirstTimeWizard() throw();
wxWizardPage *GetUsermodePage() const { return &m_page_usermode; }
wxWizardPage *GetPostUsermodePage() const { return &m_page_plugins; }
@ -66,15 +66,15 @@ protected:
namespace Dialogs
{
class AboutBoxDialog: public wxDialog
class AboutBoxDialog: public wxDialogWithHelpers
{
public:
AboutBoxDialog( wxWindow* parent=NULL, int id=DialogId_About );
virtual ~AboutBoxDialog() throw() {}
protected:
wxStaticBitmap m_bitmap_logo;
wxStaticBitmap m_bitmap_ps2system;
//wxStaticBitmap m_bitmap_logo;
wxStaticBitmap m_bitmap_dualshock;
};
class PickUserModeDialog : public wxDialogWithHelpers
@ -85,6 +85,7 @@ namespace Dialogs
public:
PickUserModeDialog( wxWindow* parent, int id=wxID_ANY );
virtual ~PickUserModeDialog() throw() {}
protected:
void OnOk_Click( wxCommandEvent& evt );
@ -95,6 +96,7 @@ namespace Dialogs
{
public:
ImportSettingsDialog( wxWindow* parent );
virtual ~ImportSettingsDialog() throw() {}
protected:
void OnImport_Click( wxCommandEvent& evt );

View File

@ -114,7 +114,7 @@ namespace Panels
void StartWizard();
bool ApplyAll( bool saveOnSuccess=true );
bool ApplyPage( int pageid, bool saveOnSuccess=true );
void DoCleanup();
void DoCleanup() throw();
};
extern StaticApplyState g_ApplyState;

View File

@ -30,7 +30,7 @@ Panels::StaticApplyState Panels::g_ApplyState;
// on dialog destruction. It asserts if the ApplyList hasn't been cleaned up
// and then cleans it up forcefully.
//
void Panels::StaticApplyState::DoCleanup()
void Panels::StaticApplyState::DoCleanup() throw()
{
wxASSERT_MSG( PanelList.size() != 0, L"PanelList list hasn't been cleaned up." );
PanelList.clear();

View File

@ -303,12 +303,10 @@ void Panels::PluginSelectorPanel::Apply()
// Need to unload the current emulation state if the user changed plugins, because
// the whole plugin system needs to be re-loaded.
const PluginInfo* pi = tbl_PluginInfo-1;
while( ++pi, pi->shortname != NULL )
{
const PluginInfo* pi = tbl_PluginInfo; do {
if( g_Conf->FullpathTo( pi->id ) != g_Conf->FullpathTo( pi->id ) )
break;
}
} while( ++pi, pi->shortname != NULL );
if( pi->shortname != NULL )
{

View File

@ -158,14 +158,13 @@ void Pcsx2App::ReloadPlugins()
wxString passins[PluginId_Count];
const PluginInfo* pi = tbl_PluginInfo-1;
while( ++pi, pi->shortname != NULL )
const PluginInfo* pi = tbl_PluginInfo; do
{
passins[pi->id] = OverrideOptions.Filenames[pi->id].GetFullPath();
if( passins[pi->id].IsEmpty() || !wxFileExists( passins[pi->id] ) )
passins[pi->id] = g_Conf->FullpathTo( pi->id );
}
} while( ++pi, pi->shortname != NULL );
_loadTask.reset( new LoadPluginsTask( passins ) );
// ... and when it finishes it posts up a OnLoadPluginsComplete(). Bye. :)

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

View File

@ -2362,7 +2362,7 @@
</FileConfiguration>
</File>
<File
RelativePath="..\..\gui\Resources\Dualshock.png"
RelativePath="..\..\gui\Resources\Dualshock.jpg"
>
<FileConfiguration
Name="Debug|Win32"
@ -2370,7 +2370,7 @@
<Tool
Name="VCCustomBuildTool"
Description=""
CommandLine="&quot;$(InputDir)\bin2cpp.cmd&quot; $(InputFileName)&#x0D;&#x0A;"
CommandLine="&quot;$(InputDir)\bin2cpp.cmd&quot; $(InputFileName)"
Outputs="&quot;$(InputDir)\$(InputName).h"
/>
</FileConfiguration>
@ -2380,7 +2380,7 @@
<Tool
Name="VCCustomBuildTool"
Description=""
CommandLine="&quot;$(InputDir)\bin2cpp.cmd&quot; $(InputFileName)&#x0D;&#x0A;"
CommandLine="&quot;$(InputDir)\bin2cpp.cmd&quot; $(InputFileName)"
Outputs="&quot;$(InputDir)\$(InputName).h"
/>
</FileConfiguration>
@ -2390,7 +2390,7 @@
<Tool
Name="VCCustomBuildTool"
Description=""
CommandLine="&quot;$(InputDir)\bin2cpp.cmd&quot; $(InputFileName)&#x0D;&#x0A;"
CommandLine="&quot;$(InputDir)\bin2cpp.cmd&quot; $(InputFileName)"
Outputs="&quot;$(InputDir)\$(InputName).h"
/>
</FileConfiguration>

View File

@ -72,14 +72,14 @@ namespace Exception
using namespace Threading;
static void CreatePipe( HANDLE& ph_Pipe, HANDLE& ph_File )
static __forceinline 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++);
GetCurrentProcessId(), GetCurrentThreadId(), GetTickCount(), ++s32_Counter);
SECURITY_ATTRIBUTES k_Secur;
k_Secur.nLength = sizeof(SECURITY_ATTRIBUTES);
@ -108,8 +108,10 @@ static void CreatePipe( HANDLE& ph_Pipe, HANDLE& ph_File )
// 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 )
static __forceinline bool ReadPipe(HANDLE h_Pipe, Console::Colors color )
{
if( h_Pipe == INVALID_HANDLE_VALUE ) return false;
// 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!!
@ -143,22 +145,19 @@ static bool ReadPipe(HANDLE h_Pipe, Console::Colors color )
class WinPipeThread : public PersistentThread
{
protected:
const HANDLE& mh_OutPipe;
const HANDLE& mh_ErrPipe;
const HANDLE& m_outpipe;
const Console::Colors m_color;
public:
WinPipeThread( const HANDLE& outpipe, const HANDLE& errpipe ) :
mh_OutPipe( outpipe )
, mh_ErrPipe( errpipe )
//, mk_OverOut( overout )
//, mk_OverErr( overerr )
WinPipeThread( const HANDLE& outpipe, Console::Colors color ) :
m_outpipe( outpipe )
, m_color( color )
{
}
virtual ~WinPipeThread() throw()
{
PersistentThread::Cancel();
SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL );
}
protected:
@ -166,12 +165,12 @@ protected:
{
try
{
SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL );
while( true )
{
Sleep( 100 );
pthread_testcancel();
ReadPipe(mh_OutPipe, Color_Black );
ReadPipe(mh_ErrPipe, Color_Red );
ReadPipe(m_outpipe, m_color );
}
}
catch( Exception::Win32Error& ex )
@ -189,88 +188,94 @@ 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;
HANDLE m_pipe;
HANDLE m_file;
int m_crtFile;
FILE* m_fp;
WinPipeThread m_Thread;
public:
WinPipeRedirection();
WinPipeRedirection( FILE* stdstream );
virtual ~WinPipeRedirection() throw();
void Cleanup() 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 )
WinPipeRedirection::WinPipeRedirection( FILE* stdstream ) :
m_pipe(INVALID_HANDLE_VALUE)
, m_file(INVALID_HANDLE_VALUE)
, m_crtFile(-1)
, m_fp(NULL)
, m_Thread( m_pipe, (stdstream == stderr) ? Color_Red : Color_Black )
{
CreatePipe(mh_OutPipe, mh_OutFile );
CreatePipe(mh_ErrPipe, mh_ErrFile );
try
{
wxASSERT( stdstream == stderr || stdstream == stdout );
DWORD stdhandle = ( stdstream == stderr ) ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE;
SetStdHandle( STD_OUTPUT_HANDLE, mh_OutFile );
SetStdHandle( STD_ERROR_HANDLE, mh_ErrFile );
CreatePipe( m_pipe, m_file );
SetStdHandle( stdhandle, m_file );
m_hCrtOut = _open_osfhandle( (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT );
m_hCrtErr = _open_osfhandle( (intptr_t)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT );
// In some cases GetStdHandle can fail, even when the one we just assigned above is valid.
HANDLE newhandle = GetStdHandle(stdhandle);
if( newhandle == INVALID_HANDLE_VALUE )
throw Exception::Win32Error( "GetStdHandle failed." );
h_fpOut = _fdopen( m_hCrtOut, "w" );
h_fpErr = _fdopen( m_hCrtErr, "w" );
if( newhandle == NULL )
throw Exception::RuntimeError( "GetStdHandle returned NULL." ); // not a Win32error (no error code)
*stdout = *h_fpOut;
*stderr = *h_fpErr;
m_crtFile = _open_osfhandle( (intptr_t)newhandle, _O_TEXT );
m_fp = _fdopen( m_crtFile, "w" );
setvbuf( stdout, NULL, _IONBF, 0 );
setvbuf( stderr, NULL, _IONBF, 0 );
*stdstream = *m_fp;
setvbuf( stdstream, NULL, _IONBF, 0 );
m_Thread.Start();
m_Thread.Start();
}
catch( ... )
{
Cleanup(); throw;
}
}
WinPipeRedirection::~WinPipeRedirection() throw()
WinPipeRedirection::~WinPipeRedirection()
{
Cleanup();
}
void WinPipeRedirection::Cleanup() 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 )
if( m_fp != NULL )
{
fclose( h_fpOut );
h_fpOut = NULL;
}
if( h_fpErr != NULL )
{
fclose( h_fpErr );
h_fpErr = NULL;
fclose( m_fp );
m_fp = NULL;
}
#define safe_close( ptr ) \
((void) (( ( ptr != -1 ) && (!!_close( ptr ), !!0) ), ptr = -1))
// crtFile is closed implicitly when closing m_fp
// m_file is closed implicitly when closing crtFile
// CrtOut and CrtErr are closed implicitly when closing fpOut/fpErr
// OutFile and ErrFile are closed implicitly when closing m_hCrtOut/Err
if( m_pipe != INVALID_HANDLE_VALUE )
{
CloseHandle( m_pipe );
m_pipe = INVALID_HANDLE_VALUE;
}
}
// The win32 specific implementation of PipeRedirection.
PipeRedirectionBase* NewPipeRedir()
PipeRedirectionBase* NewPipeRedir( FILE* stdstream )
{
return new WinPipeRedirection();
try
{
return new WinPipeRedirection( stdstream );
}
catch( Exception::RuntimeError& ex )
{
// Entirely non-critical errors. Log 'em and move along.
Console::Error( ex.FormatDiagnosticMessage() );
}
return NULL;
}