smsvn -> ssc-hg glue: rearrange directory structure
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
#include "global.h"
|
||||
#include "AppInstance.h"
|
||||
|
||||
AppInstance::AppInstance()
|
||||
{
|
||||
/* Little trick to get an HINSTANCE of ourself without having access to the hwnd ... */
|
||||
TCHAR szFullAppPath[MAX_PATH];
|
||||
GetModuleFileName(NULL, szFullAppPath, MAX_PATH);
|
||||
h = LoadLibrary(szFullAppPath);
|
||||
/* h will be NULL if this fails. Most operations that take an HINSTANCE
|
||||
* will still work without one (but may be missing graphics); that's OK. */
|
||||
}
|
||||
|
||||
AppInstance::~AppInstance()
|
||||
{
|
||||
if(h)
|
||||
FreeLibrary(h);
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2002-2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/* AppInstance - get an HINSTANCE for starting dialog boxes. */
|
||||
|
||||
#ifndef APP_INSTANCE_H
|
||||
#define APP_INSTANCE_H
|
||||
|
||||
#if !defined(_XBOX)
|
||||
# include "windows.h"
|
||||
#endif
|
||||
|
||||
class AppInstance
|
||||
{
|
||||
public:
|
||||
AppInstance();
|
||||
~AppInstance();
|
||||
HINSTANCE Get() const { return h; }
|
||||
operator HINSTANCE () const { return h; }
|
||||
|
||||
private:
|
||||
HINSTANCE h;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2002-2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,74 @@
|
||||
#include "global.h"
|
||||
#include "CommandLine.h"
|
||||
#include <windows.h>
|
||||
|
||||
/* Ugh. Windows doesn't give us the argv[] parser; all it gives is CommandLineToArgvW,
|
||||
* which is NT-only, so we have to do this ourself. Don't be fancy; only handle double
|
||||
* quotes. */
|
||||
int GetWin32CmdLine( char** &argv )
|
||||
{
|
||||
char *pCmdLine = GetCommandLine();
|
||||
int argc = 0;
|
||||
argv = NULL;
|
||||
|
||||
int i = 0;
|
||||
while( pCmdLine[i] )
|
||||
{
|
||||
argv = (char **) realloc( argv, (argc+1) * sizeof(char *) );
|
||||
argv[argc] = pCmdLine+i;
|
||||
++argc;
|
||||
|
||||
/* Skip to the end of this argument. */
|
||||
while( pCmdLine[i] && pCmdLine[i] != ' ' )
|
||||
{
|
||||
if( pCmdLine[i] == '"' )
|
||||
{
|
||||
/* Erase the quote. */
|
||||
memmove( pCmdLine+i, pCmdLine+i+1, strlen(pCmdLine+i+1)+1 );
|
||||
|
||||
/* Skip to the close quote. */
|
||||
while( pCmdLine[i] && pCmdLine[i] != '"' )
|
||||
++i;
|
||||
|
||||
/* Erase the close quote. */
|
||||
if( pCmdLine[i] == '"' )
|
||||
memmove( pCmdLine+i, pCmdLine+i+1, strlen(pCmdLine+i+1)+1 );
|
||||
}
|
||||
else
|
||||
++i;
|
||||
}
|
||||
|
||||
if( pCmdLine[i] == ' ' )
|
||||
{
|
||||
pCmdLine[i] = '\0';
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return argc;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2006 Chris Danford
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,33 @@
|
||||
/* Helper to simulate standard argv[] semantics with WinMain. */
|
||||
|
||||
#ifndef CommandLine_H
|
||||
#define CommandLine_H
|
||||
|
||||
int GetWin32CmdLine( char** &argv );
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2002-2004 Chris Danford
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,639 @@
|
||||
#include "global.h"
|
||||
|
||||
// DO NOT USE stdio.h! printf() calls malloc()!
|
||||
//#include <stdio.h>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "arch/Threads/Threads_Win32.h"
|
||||
#include "crash.h"
|
||||
#include "CrashHandlerInternal.h"
|
||||
#include "RageLog.h" /* for RageLog::GetAdditionalLog and Flush */
|
||||
#include "RageThreads.h" /* for GetCheckpointLogs */
|
||||
#include "PrefsManager.h" /* for g_bAutoRestart */
|
||||
#include "RestartProgram.h"
|
||||
|
||||
// WARNING: This is called from crash-time conditions! No malloc() or new!!!
|
||||
|
||||
#define malloc not_allowed_here
|
||||
#define new not_allowed_here
|
||||
|
||||
|
||||
static void SpliceProgramPath(char *buf, int bufsiz, const char *fn) {
|
||||
char tbuf[MAX_PATH];
|
||||
char *pszFile;
|
||||
|
||||
GetModuleFileName(NULL, tbuf, sizeof tbuf);
|
||||
GetFullPathName(tbuf, bufsiz, buf, &pszFile);
|
||||
strcpy(pszFile, fn);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const struct ExceptionLookup {
|
||||
DWORD code;
|
||||
const char *name;
|
||||
} exceptions[]={
|
||||
{ EXCEPTION_ACCESS_VIOLATION, "Access Violation" },
|
||||
{ EXCEPTION_BREAKPOINT, "Breakpoint" },
|
||||
{ EXCEPTION_FLT_DENORMAL_OPERAND, "FP Denormal Operand" },
|
||||
{ EXCEPTION_FLT_DIVIDE_BY_ZERO, "FP Divide-by-Zero" },
|
||||
{ EXCEPTION_FLT_INEXACT_RESULT, "FP Inexact Result" },
|
||||
{ EXCEPTION_FLT_INVALID_OPERATION, "FP Invalid Operation" },
|
||||
{ EXCEPTION_FLT_OVERFLOW, "FP Overflow", },
|
||||
{ EXCEPTION_FLT_STACK_CHECK, "FP Stack Check", },
|
||||
{ EXCEPTION_FLT_UNDERFLOW, "FP Underflow", },
|
||||
{ EXCEPTION_INT_DIVIDE_BY_ZERO, "Integer Divide-by-Zero", },
|
||||
{ EXCEPTION_INT_OVERFLOW, "Integer Overflow", },
|
||||
{ EXCEPTION_PRIV_INSTRUCTION, "Privileged Instruction", },
|
||||
{ EXCEPTION_ILLEGAL_INSTRUCTION, "Illegal instruction" },
|
||||
{ EXCEPTION_INVALID_HANDLE, "Invalid handle" },
|
||||
{ EXCEPTION_STACK_OVERFLOW, "Stack overflow" },
|
||||
{ 0xe06d7363, "Unhandled Microsoft C++ Exception", },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
static const char *LookupException( DWORD code )
|
||||
{
|
||||
for( int i = 0; exceptions[i].code; ++i )
|
||||
if( exceptions[i].code == code )
|
||||
return exceptions[i].name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static CrashInfo g_CrashInfo;
|
||||
static void GetReason( const EXCEPTION_RECORD *pRecord, CrashInfo *crash )
|
||||
{
|
||||
// fill out bomb reason
|
||||
const char *reason = LookupException( pRecord->ExceptionCode );
|
||||
|
||||
if( reason == NULL )
|
||||
wsprintf( crash->m_CrashReason, "unknown exception 0x%08lx", pRecord->ExceptionCode );
|
||||
else
|
||||
strcpy( crash->m_CrashReason, reason );
|
||||
}
|
||||
|
||||
static HWND g_hForegroundWnd = NULL;
|
||||
void CrashHandler::SetForegroundWindow( HWND hWnd )
|
||||
{
|
||||
g_hForegroundWnd = hWnd;
|
||||
}
|
||||
|
||||
void WriteToChild( HANDLE hPipe, const void *pData, size_t iSize )
|
||||
{
|
||||
while( iSize )
|
||||
{
|
||||
DWORD iActual;
|
||||
if( !WriteFile(hPipe, pData, iSize, &iActual, NULL) )
|
||||
return;
|
||||
iSize -= iActual;
|
||||
}
|
||||
}
|
||||
|
||||
/* Execute the child process. Return a handle to the process, a writable handle
|
||||
* to its stdin, and a readable handle to its stdout. */
|
||||
bool StartChild( HANDLE &hProcess, HANDLE &hToStdin, HANDLE &hFromStdout )
|
||||
{
|
||||
char cwd[MAX_PATH];
|
||||
SpliceProgramPath( cwd, MAX_PATH, "" );
|
||||
|
||||
STARTUPINFO si;
|
||||
ZeroMemory( &si, sizeof(si) );
|
||||
si.dwFlags |= STARTF_USESTDHANDLES;
|
||||
|
||||
{
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sa.bInheritHandle = true;
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
|
||||
CreatePipe( &si.hStdInput, &hToStdin, &sa, 0 );
|
||||
CreatePipe( &hFromStdout, &si.hStdOutput, &sa, 0 );
|
||||
SetHandleInformation( hToStdin, HANDLE_FLAG_INHERIT, 0 );
|
||||
SetHandleInformation( hFromStdout, HANDLE_FLAG_INHERIT, 0 );
|
||||
}
|
||||
|
||||
char szBuf[256] = "";
|
||||
GetModuleFileName( NULL, szBuf, MAX_PATH );
|
||||
strcat( szBuf, " " );
|
||||
strcat( szBuf, CHILD_MAGIC_PARAMETER );
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
int iRet = CreateProcess(
|
||||
NULL, // pointer to name of executable module
|
||||
szBuf, // pointer to command line string
|
||||
NULL, // process security attributes
|
||||
NULL, // thread security attributes
|
||||
true, // handle inheritance flag
|
||||
0, // creation flags
|
||||
NULL, // pointer to new environment block
|
||||
cwd, // pointer to current directory name
|
||||
&si, // pointer to STARTUPINFO
|
||||
&pi // pointer to PROCESS_INFORMATION
|
||||
);
|
||||
|
||||
CloseHandle( si.hStdInput );
|
||||
CloseHandle( si.hStdOutput );
|
||||
|
||||
if( !iRet )
|
||||
{
|
||||
CloseHandle( hToStdin );
|
||||
CloseHandle( hFromStdout );
|
||||
return false;
|
||||
}
|
||||
|
||||
hProcess = pi.hProcess;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char *CrashGetModuleBaseName(HMODULE hmod, char *pszBaseName)
|
||||
{
|
||||
char szPath1[MAX_PATH];
|
||||
char szPath2[MAX_PATH];
|
||||
|
||||
__try {
|
||||
if( !GetModuleFileName(hmod, szPath1, sizeof(szPath1)) )
|
||||
return NULL;
|
||||
|
||||
char *pszFile;
|
||||
DWORD dw = GetFullPathName( szPath1, sizeof(szPath2), szPath2, &pszFile );
|
||||
|
||||
if( !dw || dw > sizeof(szPath2) )
|
||||
return NULL;
|
||||
|
||||
strcpy( pszBaseName, pszFile );
|
||||
|
||||
pszFile = pszBaseName;
|
||||
|
||||
char *period = NULL;
|
||||
while( *pszFile++ )
|
||||
if( pszFile[-1]=='.' )
|
||||
period = pszFile-1;
|
||||
|
||||
if( period )
|
||||
*period = 0;
|
||||
} __except(1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pszBaseName;
|
||||
}
|
||||
|
||||
void RunChild()
|
||||
{
|
||||
HANDLE hProcess, hToStdin, hFromStdout;
|
||||
StartChild( hProcess, hToStdin, hFromStdout );
|
||||
|
||||
/* 0. Send a handle of this process to the crash handling process, which it can use to handle symbol lookups. */
|
||||
{
|
||||
HANDLE hTargetHandle;
|
||||
DuplicateHandle(
|
||||
GetCurrentProcess(),
|
||||
GetCurrentProcess(),
|
||||
hProcess,
|
||||
&hTargetHandle,
|
||||
0,
|
||||
false,
|
||||
DUPLICATE_SAME_ACCESS
|
||||
);
|
||||
|
||||
WriteToChild( hToStdin, &hTargetHandle, sizeof(hTargetHandle) );
|
||||
}
|
||||
|
||||
/* 1. Write the CrashData. */
|
||||
WriteToChild( hToStdin, &g_CrashInfo, sizeof(g_CrashInfo) );
|
||||
|
||||
/* 2. Write info. */
|
||||
const char *p = RageLog::GetInfo();
|
||||
int iSize = strlen( p );
|
||||
WriteToChild( hToStdin, &iSize, sizeof(iSize) );
|
||||
WriteToChild( hToStdin, p, iSize );
|
||||
|
||||
/* 3. Write AdditionalLog. */
|
||||
p = RageLog::GetAdditionalLog();
|
||||
iSize = strlen( p );
|
||||
WriteToChild( hToStdin, &iSize, sizeof(iSize) );
|
||||
WriteToChild( hToStdin, p, iSize );
|
||||
|
||||
/* 4. Write RecentLogs. */
|
||||
int cnt = 0;
|
||||
const char *ps[1024];
|
||||
while( cnt < 1024 && (ps[cnt] = RageLog::GetRecentLog( cnt )) != NULL )
|
||||
++cnt;
|
||||
|
||||
WriteToChild(hToStdin, &cnt, sizeof(cnt));
|
||||
for( int i = 0; i < cnt; ++i )
|
||||
{
|
||||
iSize = strlen(ps[i])+1;
|
||||
WriteToChild( hToStdin, &iSize, sizeof(iSize) );
|
||||
WriteToChild( hToStdin, ps[i], iSize );
|
||||
}
|
||||
|
||||
/* 5. Write CHECKPOINTs. */
|
||||
static char buf[1024*32];
|
||||
Checkpoints::GetLogs( buf, sizeof(buf), "$$" );
|
||||
iSize = strlen( buf )+1;
|
||||
WriteToChild( hToStdin, &iSize, sizeof(iSize) );
|
||||
WriteToChild( hToStdin, buf, iSize );
|
||||
|
||||
/* 6. Write the crashed thread's name. */
|
||||
p = RageThread::GetCurrentThreadName();
|
||||
iSize = strlen( p )+1;
|
||||
WriteToChild( hToStdin, &iSize, sizeof(iSize) );
|
||||
WriteToChild( hToStdin, p, iSize );
|
||||
|
||||
/* The parent process needs to access this process briefly. When it's done, it'll
|
||||
* close the handle. Wait until we see that before exiting. */
|
||||
while(1)
|
||||
{
|
||||
/* Ugly: the new process can't execute GetModuleFileName on this process,
|
||||
* since GetModuleFileNameEx might not be available. Run the requests here. */
|
||||
HMODULE hMod;
|
||||
DWORD iActual;
|
||||
if( !ReadFile( hFromStdout, &hMod, sizeof(hMod), &iActual, NULL) )
|
||||
break;
|
||||
|
||||
char szName[MAX_PATH];
|
||||
if( !CrashGetModuleBaseName(hMod, szName) )
|
||||
strcpy( szName, "???" );
|
||||
iSize = strlen( szName );
|
||||
WriteToChild( hToStdin, &iSize, sizeof(iSize) );
|
||||
WriteToChild( hToStdin, szName, iSize );
|
||||
}
|
||||
}
|
||||
|
||||
static long MainExceptionHandler( EXCEPTION_POINTERS *pExc )
|
||||
{
|
||||
/* Flush the log it isn't cut off at the end. */
|
||||
/* 1. We can't do regular file access in the crash handler.
|
||||
* 2. We can't access LOG itself at all, since it may not be set up or the pointer might
|
||||
* be munged. We must only ever use the RageLog:: methods that access static data, that
|
||||
* we're being very careful to null-terminate as needed.
|
||||
*
|
||||
* Logs are rarely important, anyway. Only info.txt and crashinfo.txt are needed 99%
|
||||
* of the time. */
|
||||
// LOG->Flush();
|
||||
|
||||
/* We aren't supposed to receive these exceptions. For example, if you do
|
||||
* a floating point divide by zero, you should receive a result of #INF. Only
|
||||
* if the floating point exception for _EM_ZERODIVIDE is unmasked does this
|
||||
* exception occur, and we never unmask it.
|
||||
*
|
||||
* However, once in a while some driver or library turns evil and unmasks an
|
||||
* exception flag on us. If this happens, re-mask it and continue execution. */
|
||||
switch( pExc->ExceptionRecord->ExceptionCode )
|
||||
{
|
||||
case EXCEPTION_FLT_INVALID_OPERATION:
|
||||
case EXCEPTION_FLT_DENORMAL_OPERAND:
|
||||
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
|
||||
case EXCEPTION_FLT_OVERFLOW:
|
||||
case EXCEPTION_FLT_UNDERFLOW:
|
||||
case EXCEPTION_FLT_INEXACT_RESULT:
|
||||
pExc->ContextRecord->FloatSave.ControlWord |= 0x3F;
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
|
||||
static int InHere = 0;
|
||||
if( InHere > 0 )
|
||||
{
|
||||
/* If we get here, then we've been called recursively, which means we crashed.
|
||||
* If InHere is greater than 1, then we crashed after writing the crash dump;
|
||||
* say so. */
|
||||
SetUnhandledExceptionFilter(NULL);
|
||||
MessageBox( NULL,
|
||||
InHere == 1?
|
||||
"The error reporting interface has crashed.\n":
|
||||
"The error reporting interface has crashed. However, crashinfo.txt was"
|
||||
"written successfully to the program directory.\n",
|
||||
"Fatal Error", MB_OK );
|
||||
#ifdef DEBUG
|
||||
DebugBreak();
|
||||
#endif
|
||||
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
++InHere;
|
||||
/////////////////////////
|
||||
|
||||
RageThread::HaltAllThreads( false );
|
||||
|
||||
if( !g_CrashInfo.m_CrashReason[0] )
|
||||
GetReason( pExc->ExceptionRecord, &g_CrashInfo );
|
||||
CrashHandler::do_backtrace( g_CrashInfo.m_BacktracePointers, BACKTRACE_MAX_SIZE, GetCurrentProcess(), GetCurrentThread(), pExc->ContextRecord );
|
||||
|
||||
RunChild();
|
||||
|
||||
++InHere;
|
||||
|
||||
if( g_bAutoRestart )
|
||||
Win32RestartProgram();
|
||||
|
||||
/* Now things get more risky. If we're fullscreen, the window will obscure the
|
||||
* crash dialog. Try to hide the window. Things might blow up here; do this
|
||||
* after DoSave, so we always write a crash dump. */
|
||||
if( GetWindowThreadProcessId( g_hForegroundWnd, NULL ) == GetCurrentThreadId() )
|
||||
{
|
||||
/* The thread that crashed was the thread that created the main window. Hide
|
||||
* the window. This will also restore the video mode, if necessary. */
|
||||
ShowWindow( g_hForegroundWnd, SW_HIDE );
|
||||
} else {
|
||||
/* A different thread crashed. Simply kill all other windows. We can't safely
|
||||
* call ShowWindow; the main thread might be deadlocked. */
|
||||
RageThread::HaltAllThreads( true );
|
||||
ChangeDisplaySettings( NULL, 0 );
|
||||
}
|
||||
|
||||
InHere = false;
|
||||
|
||||
SetUnhandledExceptionFilter( NULL );
|
||||
|
||||
/* Forcibly terminate; if we keep going, we'll try to shut down threads and do other
|
||||
* things that may deadlock, which is confusing for users. */
|
||||
TerminateProcess( GetCurrentProcess(), 0 );
|
||||
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
long __stdcall CrashHandler::ExceptionHandler( EXCEPTION_POINTERS *pExc )
|
||||
{
|
||||
/* If the stack overflowed, we have a very limited amount of stack space. Allocate
|
||||
* a new stack, and run the exception handler in it, to increase the chances of success. */
|
||||
int iSize = 1024*32;
|
||||
char *pStack = (char *) VirtualAlloc( NULL, iSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE );
|
||||
pStack += iSize;
|
||||
_asm mov esp, pStack;
|
||||
|
||||
return MainExceptionHandler( pExc );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool IsValidCall(char *buf, int len)
|
||||
{
|
||||
// Permissible CALL sequences that we care about:
|
||||
//
|
||||
// E8 xx xx xx xx CALL near relative
|
||||
// FF (group 2) CALL near absolute indirect
|
||||
//
|
||||
// Minimum sequence is 2 bytes (call eax).
|
||||
// Maximum sequence is 7 bytes (call dword ptr [eax+disp32]).
|
||||
|
||||
if (len >= 5 && buf[-5] == '\xe8')
|
||||
return true;
|
||||
|
||||
// FF 14 xx CALL [reg32+reg32*scale]
|
||||
|
||||
if (len >= 3 && buf[-3] == '\xff' && buf[-2]=='\x14')
|
||||
return true;
|
||||
|
||||
// FF 15 xx xx xx xx CALL disp32
|
||||
|
||||
if (len >= 6 && buf[-6] == '\xff' && buf[-5]=='\x15')
|
||||
return true;
|
||||
|
||||
// FF 00-3F(!14/15) CALL [reg32]
|
||||
|
||||
if (len >= 2 && buf[-2] == '\xff' && (unsigned char)buf[-1] < '\x40')
|
||||
return true;
|
||||
|
||||
// FF D0-D7 CALL reg32
|
||||
|
||||
if (len >= 2 && buf[-2] == '\xff' && (buf[-1]&0xF8) == '\xd0')
|
||||
return true;
|
||||
|
||||
// FF 50-57 xx CALL [reg32+reg32*scale+disp8]
|
||||
|
||||
if (len >= 3 && buf[-3] == '\xff' && (buf[-2]&0xF8) == '\x50')
|
||||
return true;
|
||||
|
||||
// FF 90-97 xx xx xx xx xx CALL [reg32+reg32*scale+disp32]
|
||||
|
||||
if (len >= 7 && buf[-7] == '\xff' && (buf[-6]&0xF8) == '\x90')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool IsExecutableProtection(DWORD dwProtect) {
|
||||
MEMORY_BASIC_INFORMATION meminfo;
|
||||
|
||||
// Windows NT/2000 allows Execute permissions, but Win9x seems to
|
||||
// rip it off. So we query the permissions on our own code block,
|
||||
// and use it to determine if READONLY/READWRITE should be
|
||||
// considered 'executable.'
|
||||
|
||||
VirtualQuery(IsExecutableProtection, &meminfo, sizeof meminfo);
|
||||
|
||||
switch((unsigned char)dwProtect) {
|
||||
case PAGE_READONLY: // *sigh* Win9x...
|
||||
case PAGE_READWRITE: // *sigh*
|
||||
return meminfo.Protect==PAGE_READONLY || meminfo.Protect==PAGE_READWRITE;
|
||||
|
||||
case PAGE_EXECUTE:
|
||||
case PAGE_EXECUTE_READ:
|
||||
case PAGE_EXECUTE_READWRITE:
|
||||
case PAGE_EXECUTE_WRITECOPY:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool PointsToValidCall( unsigned long ptr )
|
||||
{
|
||||
char buf[7];
|
||||
int len = 7;
|
||||
|
||||
memset( buf, 0, sizeof(buf) );
|
||||
|
||||
while(len > 0 && !ReadProcessMemory(GetCurrentProcess(), (void *)(ptr-len), buf+7-len, len, NULL))
|
||||
--len;
|
||||
|
||||
return IsValidCall(buf+7, len);
|
||||
}
|
||||
|
||||
void CrashHandler::do_backtrace( const void **buf, size_t size,
|
||||
HANDLE hProcess, HANDLE hThread, const CONTEXT *pContext )
|
||||
{
|
||||
const void **pLast = buf + size - 1;
|
||||
bool bFirst = true;
|
||||
|
||||
/* The EIP of the position that crashed is normally on the stack, since the exception
|
||||
* handler was called on the same stack. However, once in a while, due to stack corruption,
|
||||
* we might not be able to get any frames from the stack. Pull it out of pContext->Eip,
|
||||
* which is always valid, and then discard the first stack frame if it's the same. */
|
||||
if( buf+1 != pLast && pContext->Eip != NULL )
|
||||
{
|
||||
*buf = (void *) pContext->Eip;
|
||||
++buf;
|
||||
}
|
||||
|
||||
// Retrieve stack pointers.
|
||||
const char *pStackBase;
|
||||
{
|
||||
LDT_ENTRY sel;
|
||||
if( !GetThreadSelectorEntry( hThread, pContext->SegFs, &sel ) )
|
||||
{
|
||||
*buf = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
const NT_TIB *tib = (NT_TIB *) ((sel.HighWord.Bits.BaseHi<<24)+(sel.HighWord.Bits.BaseMid<<16)+sel.BaseLow);
|
||||
const NT_TIB *pTib = tib->Self;
|
||||
pStackBase = (char *)pTib->StackBase;
|
||||
}
|
||||
|
||||
// Walk up the stack.
|
||||
const char *lpAddr = (const char *)pContext->Esp;
|
||||
|
||||
const void *data = (void *) pContext->Eip;
|
||||
do {
|
||||
if( buf == pLast )
|
||||
break;
|
||||
|
||||
bool fValid = true;
|
||||
|
||||
/* The first entry is usually EIP. We already logged it; skip it, so we don't always
|
||||
* show the first frame twice. */
|
||||
if( bFirst && data == (void *) pContext->Eip )
|
||||
fValid = false;
|
||||
bFirst = false;
|
||||
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION meminfo;
|
||||
|
||||
VirtualQuery((void *)data, &meminfo, sizeof meminfo);
|
||||
|
||||
if (!IsExecutableProtection(meminfo.Protect) || meminfo.State!=MEM_COMMIT)
|
||||
fValid = false;
|
||||
|
||||
if ( data != (void *) pContext->Eip && !PointsToValidCall((unsigned long)data) )
|
||||
fValid = false;
|
||||
}
|
||||
|
||||
if( fValid )
|
||||
{
|
||||
*buf = data;
|
||||
++buf;
|
||||
}
|
||||
|
||||
if (lpAddr >= pStackBase)
|
||||
break;
|
||||
|
||||
lpAddr += 4;
|
||||
} while( ReadProcessMemory(hProcess, lpAddr-4, &data, 4, NULL));
|
||||
|
||||
*buf = NULL;
|
||||
}
|
||||
|
||||
/* Trigger the crash handler. This works even in the debugger. */
|
||||
static void NORETURN debug_crash()
|
||||
{
|
||||
__try {
|
||||
__asm xor ebx,ebx
|
||||
__asm mov eax,dword ptr [ebx]
|
||||
// __asm mov dword ptr [ebx],eax
|
||||
// __asm lock add dword ptr cs:[00000000h], 12345678h
|
||||
} __except( CrashHandler::ExceptionHandler((EXCEPTION_POINTERS*)_exception_info()) ) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Get a stack trace of the current thread and the specified thread. If
|
||||
* iID == GetInvalidThreadId(), then output a stack trace for every thread. */
|
||||
void CrashHandler::ForceDeadlock( RString reason, uint64_t iID )
|
||||
{
|
||||
strncpy( g_CrashInfo.m_CrashReason, reason, sizeof(g_CrashInfo.m_CrashReason) );
|
||||
g_CrashInfo.m_CrashReason[ sizeof(g_CrashInfo.m_CrashReason)-1 ] = 0;
|
||||
|
||||
/* Suspend the other thread we're going to backtrace. (We need to at least suspend
|
||||
* hThread, for GetThreadContext to work.) */
|
||||
RageThread::HaltAllThreads( false );
|
||||
|
||||
if( iID == GetInvalidThreadId() )
|
||||
{
|
||||
/* Backtrace all threads. */
|
||||
int iCnt = 0;
|
||||
for( int i = 0; RageThread::EnumThreadIDs(i, iID); ++i )
|
||||
{
|
||||
if( iID == GetInvalidThreadId() )
|
||||
continue;
|
||||
|
||||
if( iID == GetCurrentThreadId() )
|
||||
continue;
|
||||
|
||||
const HANDLE hThread = Win32ThreadIdToHandle( iID );
|
||||
|
||||
CONTEXT context;
|
||||
context.ContextFlags = CONTEXT_FULL;
|
||||
if( !GetThreadContext( hThread, &context ) )
|
||||
wsprintf( g_CrashInfo.m_CrashReason + strlen(g_CrashInfo.m_CrashReason),
|
||||
"; GetThreadContext(%x) failed", (int) hThread );
|
||||
else
|
||||
{
|
||||
static const void *BacktracePointers[BACKTRACE_MAX_SIZE];
|
||||
do_backtrace( g_CrashInfo.m_AlternateThreadBacktrace[iCnt], BACKTRACE_MAX_SIZE, GetCurrentProcess(), hThread, &context );
|
||||
|
||||
const char *pName = RageThread::GetThreadNameByID( iID );
|
||||
strncpy( g_CrashInfo.m_AlternateThreadName[iCnt], pName? pName:"???", sizeof(g_CrashInfo.m_AlternateThreadName[iCnt])-1 );
|
||||
|
||||
++iCnt;
|
||||
}
|
||||
|
||||
if( iCnt == CrashInfo::MAX_BACKTRACE_THREADS )
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
const HANDLE hThread = Win32ThreadIdToHandle( iID );
|
||||
|
||||
CONTEXT context;
|
||||
context.ContextFlags = CONTEXT_FULL;
|
||||
if( !GetThreadContext( hThread, &context ) )
|
||||
strcat( g_CrashInfo.m_CrashReason, "(GetThreadContext failed)" );
|
||||
else
|
||||
{
|
||||
static const void *BacktracePointers[BACKTRACE_MAX_SIZE];
|
||||
do_backtrace( g_CrashInfo.m_AlternateThreadBacktrace[0], BACKTRACE_MAX_SIZE, GetCurrentProcess(), hThread, &context );
|
||||
|
||||
const char *pName = RageThread::GetThreadNameByID( iID );
|
||||
strncpy( g_CrashInfo.m_AlternateThreadName[0], pName? pName:"???", sizeof(g_CrashInfo.m_AlternateThreadName[0])-1 );
|
||||
}
|
||||
}
|
||||
|
||||
debug_crash();
|
||||
}
|
||||
|
||||
void CrashHandler::ForceCrash( const char *reason )
|
||||
{
|
||||
strncpy( g_CrashInfo.m_CrashReason, reason, sizeof(g_CrashInfo.m_CrashReason) );
|
||||
g_CrashInfo.m_CrashReason[ sizeof(g_CrashInfo.m_CrashReason)-1 ] = 0;
|
||||
|
||||
debug_crash();
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 1998-2001 Avery Lee
|
||||
* (c) 2003-2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/* Win32 crash handling. */
|
||||
|
||||
#ifndef CRASH_H
|
||||
#define CRASH_H
|
||||
#include <windows.h>
|
||||
namespace CrashHandler
|
||||
{
|
||||
extern long __stdcall ExceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo);
|
||||
|
||||
void do_backtrace( const void **buf, size_t size, HANDLE hProcess, HANDLE hThread, const CONTEXT *pContext );
|
||||
void SymLookup( const void *ptr, char *buf );
|
||||
void ForceCrash( const char *reason );
|
||||
void ForceDeadlock( RString reason, uint64_t iID );
|
||||
|
||||
/* Inform the crash handler of a foreground window that may be fullscreen. If
|
||||
* set, the crash handler will attempt to hide the window or reset the video
|
||||
* mode. */
|
||||
void SetForegroundWindow( HWND hWnd );
|
||||
|
||||
void CrashHandlerHandleArgs( int argc, char* argv[] );
|
||||
};
|
||||
|
||||
#endif
|
||||
/*
|
||||
* (c) 1998-2001 Avery Lee
|
||||
* (c) 2003-2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,903 @@
|
||||
#include "global.h"
|
||||
#include "CrashHandlerInternal.h"
|
||||
#include "Crash.h"
|
||||
#include <errno.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include "archutils/Win32/ddk/dbghelp.h"
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "arch/ArchHooks/ArchHooks.h"
|
||||
#include "archutils/Win32/WindowsResources.h"
|
||||
#include "archutils/Win32/DialogUtil.h"
|
||||
#include "archutils/Win32/ErrorStrings.h"
|
||||
#include "archutils/Win32/GotoURL.h"
|
||||
#include "archutils/Win32/RestartProgram.h"
|
||||
#include "archutils/Win32/CrashHandlerNetworking.h"
|
||||
#include "archutils/Win32/WindowsDialogBox.h"
|
||||
#include "ProductInfo.h"
|
||||
#include "RageUtil.h"
|
||||
#include "XmlFile.h"
|
||||
#include "XmlFileUtil.h"
|
||||
#include "LocalizedString.h"
|
||||
#include "RageFileDriverDeflate.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma comment(lib, "archutils/Win32/ddk/dbghelp.lib")
|
||||
#endif
|
||||
|
||||
extern unsigned long version_num;
|
||||
extern const char *const version_time;
|
||||
|
||||
// VDI symbol lookup:
|
||||
namespace VDDebugInfo
|
||||
{
|
||||
struct Context
|
||||
{
|
||||
Context() { pRVAHeap=NULL; }
|
||||
bool Loaded() const { return pRVAHeap != NULL; }
|
||||
RString sRawBlock;
|
||||
|
||||
int nBuildNumber;
|
||||
|
||||
const unsigned char *pRVAHeap;
|
||||
unsigned nFirstRVA;
|
||||
|
||||
const char *pFuncNameHeap;
|
||||
const unsigned long (*pSegments)[2];
|
||||
int nSegments;
|
||||
char sFilename[1024];
|
||||
RString sError;
|
||||
};
|
||||
|
||||
static void GetVDIPath( char *buf, int bufsiz )
|
||||
{
|
||||
GetModuleFileName( NULL, buf, bufsiz );
|
||||
buf[bufsiz-5] = 0;
|
||||
char *p = strrchr( buf, '.' );
|
||||
if( p )
|
||||
strcpy( p, ".vdi" );
|
||||
else
|
||||
strcat( buf, ".vdi" );
|
||||
}
|
||||
|
||||
bool VDDebugInfoInitFromMemory( Context *pctx )
|
||||
{
|
||||
if( pctx->sRawBlock[0] == '\x1f' &&
|
||||
pctx->sRawBlock[1] == '\x8b' )
|
||||
{
|
||||
RString sBufOut;
|
||||
RString sError;
|
||||
if( !GunzipString(pctx->sRawBlock, sBufOut, sError) )
|
||||
{
|
||||
pctx->sError = werr_ssprintf( GetLastError(), "VDI error: %s", sError.c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
pctx->sRawBlock = sBufOut;
|
||||
}
|
||||
|
||||
|
||||
const unsigned char *src = (const unsigned char *) pctx->sRawBlock.data();
|
||||
|
||||
pctx->pRVAHeap = NULL;
|
||||
|
||||
static const char *header = "symbolic debug information";
|
||||
if( memcmp(src, header, strlen(header)) )
|
||||
{
|
||||
pctx->sError = "header doesn't match";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extract fields
|
||||
|
||||
src += 64;
|
||||
|
||||
pctx->nBuildNumber = *(int *)src;
|
||||
pctx->pRVAHeap = (const unsigned char *)(src + 20);
|
||||
pctx->nFirstRVA = *(const long *)(src + 16);
|
||||
pctx->pFuncNameHeap = (const char *)pctx->pRVAHeap - 4 + *(const long *)(src + 4);
|
||||
pctx->pSegments = (unsigned long (*)[2])(pctx->pFuncNameHeap + *(const long *)(src + 8));
|
||||
pctx->nSegments = *(const long *)(src + 12);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VDDebugInfoDeinit( Context *pctx )
|
||||
{
|
||||
if( !pctx->sRawBlock.empty() )
|
||||
pctx->sRawBlock = RString();
|
||||
}
|
||||
|
||||
bool VDDebugInfoInitFromFile( Context *pctx )
|
||||
{
|
||||
if( pctx->Loaded() )
|
||||
return true;
|
||||
|
||||
pctx->sRawBlock = RString();
|
||||
pctx->pRVAHeap = NULL;
|
||||
GetVDIPath( pctx->sFilename, ARRAYLEN(pctx->sFilename) );
|
||||
pctx->sError = RString();
|
||||
|
||||
HANDLE h = CreateFile( pctx->sFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
if( h == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
pctx->sError = werr_ssprintf( GetLastError(), "CreateFile failed" );
|
||||
return false;
|
||||
}
|
||||
|
||||
do {
|
||||
DWORD dwFileSize = GetFileSize( h, NULL );
|
||||
if( dwFileSize == INVALID_FILE_SIZE )
|
||||
break;
|
||||
|
||||
char *pBuf = pctx->sRawBlock.GetBuffer( dwFileSize );
|
||||
if( pBuf == NULL )
|
||||
break;
|
||||
|
||||
DWORD dwActual;
|
||||
int iRet = ReadFile(h, pBuf, dwFileSize, &dwActual, NULL);
|
||||
CloseHandle(h);
|
||||
pctx->sRawBlock.ReleaseBuffer( dwActual );
|
||||
|
||||
if( !iRet || dwActual != dwFileSize )
|
||||
break;
|
||||
|
||||
if( VDDebugInfoInitFromMemory(pctx) )
|
||||
return true;
|
||||
} while(0);
|
||||
|
||||
VDDebugInfoDeinit(pctx);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool PointerIsInAnySegment( const Context *pctx, unsigned rva )
|
||||
{
|
||||
for( int i=0; i<pctx->nSegments; ++i )
|
||||
{
|
||||
if (rva >= pctx->pSegments[i][0] && rva < pctx->pSegments[i][0] + pctx->pSegments[i][1])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char *GetNameFromHeap(const char *heap, int idx)
|
||||
{
|
||||
while(idx--)
|
||||
while(*heap++);
|
||||
|
||||
return heap;
|
||||
}
|
||||
|
||||
long VDDebugInfoLookupRVA( const Context *pctx, unsigned rva, char *buf, int buflen )
|
||||
{
|
||||
if( !PointerIsInAnySegment(pctx, rva) )
|
||||
return -1;
|
||||
|
||||
const unsigned char *pr = pctx->pRVAHeap;
|
||||
const unsigned char *pr_limit = (const unsigned char *)pctx->pFuncNameHeap;
|
||||
int idx = 0;
|
||||
|
||||
// Linearly unpack RVA deltas and find lower_bound
|
||||
rva -= pctx->nFirstRVA;
|
||||
|
||||
if( (signed)rva < 0 )
|
||||
return -1;
|
||||
|
||||
while( pr < pr_limit )
|
||||
{
|
||||
unsigned char c;
|
||||
unsigned diff = 0;
|
||||
|
||||
do
|
||||
{
|
||||
c = *pr++;
|
||||
|
||||
diff = (diff << 7) | (c & 0x7f);
|
||||
} while(c & 0x80);
|
||||
|
||||
rva -= diff;
|
||||
|
||||
if ((signed)rva < 0) {
|
||||
rva += diff;
|
||||
break;
|
||||
}
|
||||
|
||||
++idx;
|
||||
}
|
||||
if( pr >= pr_limit )
|
||||
return -1;
|
||||
|
||||
// Decompress name for RVA
|
||||
const char *fn_name = GetNameFromHeap(pctx->pFuncNameHeap, idx);
|
||||
|
||||
if( !*fn_name )
|
||||
fn_name = "(special)";
|
||||
|
||||
strncpy( buf, fn_name, buflen );
|
||||
buf[buflen-1] = 0;
|
||||
|
||||
return rva;
|
||||
}
|
||||
}
|
||||
|
||||
bool ReadFromParent( int fd, void *p, int size )
|
||||
{
|
||||
char *buf = (char *) p;
|
||||
int got = 0;
|
||||
while( got < size )
|
||||
{
|
||||
int ret = read( fd, buf+got, size-got );
|
||||
if( ret == -1 )
|
||||
{
|
||||
if( errno == EINTR )
|
||||
continue;
|
||||
fprintf( stderr, "Crash handler: error communicating with parent: %s\n", strerror(errno) );
|
||||
return false;
|
||||
}
|
||||
|
||||
if( ret == 0 )
|
||||
{
|
||||
fprintf( stderr, "Crash handler: EOF communicating with parent.\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
got += ret;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// General symbol lookup; uses VDDebugInfo for detailed information within the
|
||||
// process, and DbgHelp for simpler information about loaded DLLs.
|
||||
namespace SymbolLookup
|
||||
{
|
||||
HANDLE g_hParent;
|
||||
|
||||
bool InitDbghelp()
|
||||
{
|
||||
static bool bInitted = false;
|
||||
if( !bInitted )
|
||||
{
|
||||
SymSetOptions( SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS );
|
||||
|
||||
if( !SymInitialize(g_hParent, NULL, TRUE) )
|
||||
return false;
|
||||
|
||||
bInitted = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SYMBOL_INFO *GetSym( unsigned long ptr, DWORD64 &disp )
|
||||
{
|
||||
InitDbghelp();
|
||||
|
||||
static BYTE buffer[1024];
|
||||
SYMBOL_INFO *pSymbol = (PSYMBOL_INFO)buffer;
|
||||
|
||||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
pSymbol->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO) + 1;
|
||||
|
||||
if( !SymFromAddr(g_hParent, ptr, &disp, pSymbol) )
|
||||
return NULL;
|
||||
|
||||
return pSymbol;
|
||||
}
|
||||
|
||||
const char *Demangle( const char *buf )
|
||||
{
|
||||
if( !InitDbghelp() )
|
||||
return buf;
|
||||
|
||||
static char obuf[1024];
|
||||
if( !UnDecorateSymbolName(buf, obuf, sizeof(obuf),
|
||||
UNDNAME_COMPLETE
|
||||
| UNDNAME_NO_CV_THISTYPE
|
||||
| UNDNAME_NO_ALLOCATION_MODEL
|
||||
| UNDNAME_NO_ACCESS_SPECIFIERS // no public:
|
||||
| UNDNAME_NO_MS_KEYWORDS // no __cdecl
|
||||
| UNDNAME_NO_MEMBER_TYPE // no virtual, static
|
||||
) )
|
||||
{
|
||||
return buf;
|
||||
}
|
||||
|
||||
if( obuf[0] == '_' )
|
||||
{
|
||||
strcat( obuf, "()" ); /* _main -> _main() */
|
||||
return obuf+1; /* _main -> main */
|
||||
}
|
||||
|
||||
return obuf;
|
||||
}
|
||||
|
||||
RString CrashChildGetModuleBaseName( HMODULE hMod )
|
||||
{
|
||||
write( _fileno(stdout), &hMod, sizeof(hMod) );
|
||||
|
||||
int iFD = fileno(stdin);
|
||||
int iSize;
|
||||
if( !ReadFromParent(iFD, &iSize, sizeof(iSize)) )
|
||||
return "???";
|
||||
RString sName;
|
||||
char *pBuf = sName.GetBuffer( iSize );
|
||||
if( !ReadFromParent(iFD, pBuf, iSize) )
|
||||
return "???";
|
||||
sName.ReleaseBuffer( iSize );
|
||||
return sName;
|
||||
}
|
||||
|
||||
void SymLookup( VDDebugInfo::Context *pctx, const void *ptr, char *buf )
|
||||
{
|
||||
if( !pctx->Loaded() )
|
||||
{
|
||||
strcpy( buf, "error" );
|
||||
return;
|
||||
}
|
||||
|
||||
MEMORY_BASIC_INFORMATION meminfo;
|
||||
VirtualQueryEx( g_hParent, ptr, &meminfo, sizeof meminfo );
|
||||
|
||||
char tmp[512];
|
||||
long iAddress = VDDebugInfo::VDDebugInfoLookupRVA(pctx, (unsigned int)ptr, tmp, sizeof(tmp));
|
||||
if( iAddress >= 0 )
|
||||
{
|
||||
wsprintf( buf, "%08x: %s [%08lx+%lx+%lx]", ptr, Demangle(tmp),
|
||||
pctx->nFirstRVA,
|
||||
((unsigned int) ptr) - pctx->nFirstRVA - iAddress,
|
||||
iAddress );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
RString sName = CrashChildGetModuleBaseName( (HMODULE)meminfo.AllocationBase );
|
||||
|
||||
DWORD64 disp;
|
||||
SYMBOL_INFO *pSymbol = GetSym( (unsigned int)ptr, disp );
|
||||
|
||||
if( pSymbol )
|
||||
{
|
||||
wsprintf( buf, "%08lx: %s!%s [%08lx+%lx+%lx]",
|
||||
(unsigned long) ptr, sName.c_str(), pSymbol->Name,
|
||||
(unsigned long) meminfo.AllocationBase,
|
||||
(unsigned long) (pSymbol->Address) - (unsigned long) (meminfo.AllocationBase),
|
||||
(unsigned long) disp);
|
||||
return;
|
||||
}
|
||||
|
||||
wsprintf( buf, "%08lx: %s!%08lx",
|
||||
(unsigned long) ptr, sName.c_str(),
|
||||
(unsigned long) meminfo.AllocationBase );
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
RString SpliceProgramPath( RString fn )
|
||||
{
|
||||
char szBuf[MAX_PATH];
|
||||
GetModuleFileName( NULL, szBuf, sizeof(szBuf) );
|
||||
|
||||
char szModName[MAX_PATH];
|
||||
char *pszFile;
|
||||
GetFullPathName( szBuf, sizeof(szModName), szModName, &pszFile );
|
||||
strcpy( pszFile, fn );
|
||||
|
||||
return szModName;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
VDDebugInfo::Context g_debugInfo;
|
||||
|
||||
RString ReportCallStack( const void * const *Backtrace )
|
||||
{
|
||||
if( !g_debugInfo.Loaded() )
|
||||
return ssprintf( "debug resource file '%s': %s.\n", g_debugInfo.sFilename, g_debugInfo.sError.c_str() );
|
||||
|
||||
if( g_debugInfo.nBuildNumber != int(version_num) )
|
||||
{
|
||||
return ssprintf( "Incorrect %s file (build %d, expected %d) for this version of " PRODUCT_FAMILY " -- call stack unavailable.\n",
|
||||
g_debugInfo.sFilename, g_debugInfo.nBuildNumber, int(version_num) );
|
||||
}
|
||||
|
||||
RString sRet;
|
||||
for( int i = 0; Backtrace[i]; ++i )
|
||||
{
|
||||
char buf[10240];
|
||||
SymbolLookup::SymLookup( &g_debugInfo, Backtrace[i], buf );
|
||||
sRet += ssprintf( "%s\n", buf );
|
||||
}
|
||||
|
||||
return sRet;
|
||||
}
|
||||
}
|
||||
|
||||
struct CompleteCrashData
|
||||
{
|
||||
CrashInfo m_CrashInfo;
|
||||
RString m_sInfo;
|
||||
RString m_sAdditionalLog;
|
||||
RString m_sCrashedThread;
|
||||
vector<RString> m_asRecent;
|
||||
vector<RString> m_asCheckpoints;
|
||||
};
|
||||
|
||||
static void MakeCrashReport( const CompleteCrashData &Data, RString &sOut )
|
||||
{
|
||||
sOut += ssprintf(
|
||||
"%s crash report (build %d, %s)\n"
|
||||
"--------------------------------------\n\n",
|
||||
PRODUCT_ID_VER, version_num, version_time );
|
||||
|
||||
sOut += ssprintf( "Crash reason: %s\n", Data.m_CrashInfo.m_CrashReason );
|
||||
sOut += ssprintf( "\n" );
|
||||
|
||||
// Dump thread stacks
|
||||
static char buf[1024*32];
|
||||
sOut += ssprintf( "%s\n", join("\n", Data.m_asCheckpoints).c_str() );
|
||||
|
||||
sOut += ReportCallStack( Data.m_CrashInfo.m_BacktracePointers );
|
||||
sOut += ssprintf( "\n" );
|
||||
|
||||
if( Data.m_CrashInfo.m_AlternateThreadBacktrace[0] )
|
||||
{
|
||||
for( int i = 0; i < CrashInfo::MAX_BACKTRACE_THREADS; ++i )
|
||||
{
|
||||
if( !Data.m_CrashInfo.m_AlternateThreadBacktrace[i][0] )
|
||||
continue;
|
||||
|
||||
sOut += ssprintf( "Thread %s:\n", Data.m_CrashInfo.m_AlternateThreadName[i] );
|
||||
sOut += ssprintf( "\n" );
|
||||
sOut += ReportCallStack( Data.m_CrashInfo.m_AlternateThreadBacktrace[i] );
|
||||
sOut += ssprintf( "" );
|
||||
}
|
||||
}
|
||||
|
||||
sOut += ssprintf( "Static log:\n" );
|
||||
sOut += ssprintf( "%s", Data.m_sInfo.c_str() );
|
||||
sOut += ssprintf( "%s", Data.m_sAdditionalLog.c_str() );
|
||||
sOut += ssprintf( "\n" );
|
||||
|
||||
sOut += ssprintf( "Partial log:\n" );
|
||||
for( size_t i = 0; i < Data.m_asRecent.size(); ++i )
|
||||
sOut += ssprintf( "%s\n", Data.m_asRecent[i].c_str() );
|
||||
sOut += ssprintf( "\n" );
|
||||
|
||||
sOut += ssprintf( "-- End of report\n" );
|
||||
}
|
||||
|
||||
static void DoSave( const RString &sReport )
|
||||
{
|
||||
RString sName = SpliceProgramPath( "../crashinfo.txt" );
|
||||
|
||||
SetFileAttributes( sName, FILE_ATTRIBUTE_NORMAL );
|
||||
FILE *pFile = fopen( sName, "w+" );
|
||||
if( pFile == NULL )
|
||||
return;
|
||||
fprintf( pFile, "%s", sReport.c_str() );
|
||||
|
||||
fclose( pFile );
|
||||
|
||||
/* Discourage changing crashinfo.txt. */
|
||||
SetFileAttributes( sName, FILE_ATTRIBUTE_READONLY );
|
||||
}
|
||||
|
||||
void ViewWithNotepad(const char *str)
|
||||
{
|
||||
char buf[256] = "";
|
||||
strcat( buf, "notepad.exe " );
|
||||
strcat( buf, str );
|
||||
|
||||
RString cwd = SpliceProgramPath( "" );
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFO si;
|
||||
ZeroMemory( &si, sizeof(si) );
|
||||
|
||||
CreateProcess(
|
||||
NULL, // pointer to name of executable module
|
||||
buf, // pointer to command line string
|
||||
NULL, // process security attributes
|
||||
NULL, // thread security attributes
|
||||
false, // handle inheritance flag
|
||||
0, // creation flags
|
||||
NULL, // pointer to new environment block
|
||||
cwd, // pointer to current directory name
|
||||
&si, // pointer to STARTUPINFO
|
||||
&pi // pointer to PROCESS_INFORMATION
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
bool ReadCrashDataFromParent( int iFD, CompleteCrashData &Data )
|
||||
{
|
||||
_setmode( _fileno(stdin), O_BINARY );
|
||||
|
||||
/* 0. Read the parent handle. */
|
||||
if( !ReadFromParent(iFD, &SymbolLookup::g_hParent, sizeof(SymbolLookup::g_hParent)) )
|
||||
return false;
|
||||
|
||||
/* 1. Read the CrashData. */
|
||||
if( !ReadFromParent(iFD, &Data.m_CrashInfo, sizeof(Data.m_CrashInfo)) )
|
||||
return false;
|
||||
|
||||
/* 2. Read info. */
|
||||
int iSize;
|
||||
if( !ReadFromParent(iFD, &iSize, sizeof(iSize)) )
|
||||
return false;
|
||||
|
||||
char *pBuf = Data.m_sInfo.GetBuffer( iSize );
|
||||
if( !ReadFromParent(iFD, pBuf, iSize) )
|
||||
return false;
|
||||
Data.m_sInfo.ReleaseBuffer( iSize );
|
||||
|
||||
/* 3. Read AdditionalLog. */
|
||||
if( !ReadFromParent(iFD, &iSize, sizeof(iSize)) )
|
||||
return false;
|
||||
|
||||
pBuf = Data.m_sAdditionalLog.GetBuffer( iSize );
|
||||
if( !ReadFromParent(iFD, pBuf, iSize) )
|
||||
return false;
|
||||
Data.m_sAdditionalLog.ReleaseBuffer( iSize );
|
||||
|
||||
/* 4. Read RecentLogs. */
|
||||
int iCnt = 0;
|
||||
if( !ReadFromParent(iFD, &iCnt, sizeof(iCnt)) )
|
||||
return false;
|
||||
for( int i = 0; i < iCnt; ++i )
|
||||
{
|
||||
if( !ReadFromParent(iFD, &iSize, sizeof(iSize)) )
|
||||
return false;
|
||||
RString sBuf;
|
||||
pBuf = sBuf.GetBuffer( iSize );
|
||||
if( !ReadFromParent(iFD, pBuf, iSize) )
|
||||
return false;
|
||||
Data.m_asRecent.push_back( sBuf );
|
||||
sBuf.ReleaseBuffer( iSize );
|
||||
}
|
||||
|
||||
/* 5. Read CHECKPOINTs. */
|
||||
if( !ReadFromParent(iFD, &iSize, sizeof(iSize)) )
|
||||
return false;
|
||||
|
||||
RString sBuf;
|
||||
pBuf = sBuf.GetBuffer( iSize );
|
||||
if( !ReadFromParent(iFD, pBuf, iSize) )
|
||||
return false;
|
||||
|
||||
split( sBuf, "$$", Data.m_asCheckpoints );
|
||||
sBuf.ReleaseBuffer( iSize );
|
||||
|
||||
/* 6. Read the crashed thread's name. */
|
||||
if( !ReadFromParent(iFD, &iSize, sizeof(iSize)) )
|
||||
return false;
|
||||
pBuf = Data.m_sCrashedThread.GetBuffer( iSize );
|
||||
if( !ReadFromParent(iFD, pBuf, iSize) )
|
||||
return false;
|
||||
Data.m_sCrashedThread.ReleaseBuffer();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Localization for the crash handler is different, and a little tricky. We don't
|
||||
* have ThemeManager loaded, so we have to localize it ourself. We can supply
|
||||
* translations with our own substitution function. We need to figure out which
|
||||
* language to use. Since these strings won't be pulled from the theme, defer
|
||||
* loading them until we use them. XXX
|
||||
*/
|
||||
static LocalizedString A_CRASH_HAS_OCCURRED;
|
||||
static LocalizedString REPORTING_THE_PROBLEM;
|
||||
static LocalizedString CLOSE;
|
||||
static LocalizedString CANCEL;
|
||||
static LocalizedString VIEW_UPDATE;
|
||||
static LocalizedString UPDATE_IS_AVAILABLE;
|
||||
static LocalizedString UPDATE_IS_NOT_AVAILABLE;
|
||||
static LocalizedString ERROR_SENDING_REPORT;
|
||||
|
||||
// #define AUTOMATED_CRASH_REPORTS
|
||||
#define CRASH_REPORT_HOST "example.com"
|
||||
#define CRASH_REPORT_PORT 80
|
||||
#define CRASH_REPORT_PATH "/report.cgi"
|
||||
|
||||
void LoadLocalizedStrings()
|
||||
{
|
||||
#if defined(AUTOMATED_CRASH_REPORTS)
|
||||
A_CRASH_HAS_OCCURRED.Load( "CrashHandler",
|
||||
"A crash has occurred. Would you like to automatically report the "
|
||||
"problem and check for updates?" );
|
||||
#else
|
||||
A_CRASH_HAS_OCCURRED.Load( "CrashHandler",
|
||||
"A crash has occurred. Diagnostic information has been saved to a file "
|
||||
"called \"crashinfo.txt\" in the game program directory." );
|
||||
#endif
|
||||
REPORTING_THE_PROBLEM.Load( "CrashHandler",
|
||||
"Reporting the problem and checking for updates ..." );
|
||||
CLOSE.Load( "CrashHandler", "&Close" );
|
||||
CANCEL.Load( "CrashHandler", "&Cancel" );
|
||||
VIEW_UPDATE.Load( "CrashHandler", "View &update" );
|
||||
UPDATE_IS_AVAILABLE.Load( "CrashHandler", "An update is available." );
|
||||
UPDATE_IS_NOT_AVAILABLE.Load( "CrashHandler", "The error has been reported. No updates are available." );
|
||||
ERROR_SENDING_REPORT.Load( "CrashHandler", "An error was encountered sending the report." );
|
||||
}
|
||||
|
||||
class CrashDialog: public WindowsDialogBox
|
||||
{
|
||||
public:
|
||||
CrashDialog( const RString &sCrashReport, const CompleteCrashData &CrashData );
|
||||
~CrashDialog();
|
||||
|
||||
protected:
|
||||
virtual BOOL HandleMessage( UINT msg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
private:
|
||||
void SetDialogInitial();
|
||||
|
||||
NetworkPostData *m_pPost;
|
||||
RString m_sUpdateURL;
|
||||
const RString m_sCrashReport;
|
||||
CompleteCrashData m_CrashData;
|
||||
};
|
||||
|
||||
CrashDialog::CrashDialog( const RString &sCrashReport, const CompleteCrashData &CrashData ):
|
||||
m_sCrashReport( sCrashReport ),
|
||||
m_CrashData( CrashData )
|
||||
{
|
||||
LoadLocalizedStrings();
|
||||
m_pPost = NULL;
|
||||
}
|
||||
|
||||
CrashDialog::~CrashDialog()
|
||||
{
|
||||
delete m_pPost;
|
||||
}
|
||||
|
||||
void CrashDialog::SetDialogInitial()
|
||||
{
|
||||
HWND hDlg = GetHwnd();
|
||||
|
||||
SetWindowText( GetDlgItem(hDlg, IDC_MAIN_TEXT), A_CRASH_HAS_OCCURRED.GetValue() );
|
||||
SetWindowText( GetDlgItem(hDlg, IDC_BUTTON_CLOSE), CLOSE.GetValue() );
|
||||
ShowWindow( GetDlgItem(hDlg, IDC_PROGRESS), false );
|
||||
ShowWindow( GetDlgItem(hDlg, IDC_BUTTON_AUTO_REPORT), true );
|
||||
}
|
||||
|
||||
BOOL CrashDialog::HandleMessage( UINT msg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
HWND hDlg = GetHwnd();
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
SetDialogInitial();
|
||||
DialogUtil::SetHeaderFont( hDlg, IDC_STATIC_HEADER_TEXT );
|
||||
return TRUE;
|
||||
|
||||
case WM_CTLCOLORSTATIC:
|
||||
{
|
||||
HDC hdc = (HDC)wParam;
|
||||
HWND hwndStatic = (HWND)lParam;
|
||||
HBRUSH hbr = NULL;
|
||||
|
||||
// TODO: Change any attributes of the DC here
|
||||
switch( GetDlgCtrlID(hwndStatic) )
|
||||
{
|
||||
case IDC_STATIC_HEADER_TEXT:
|
||||
case IDC_STATIC_ICON:
|
||||
hbr = (HBRUSH)::GetStockObject(WHITE_BRUSH);
|
||||
SetBkMode( hdc, OPAQUE );
|
||||
SetBkColor( hdc, RGB(255,255,255) );
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: Return a different brush if the default is not desired
|
||||
return (BOOL)hbr;
|
||||
}
|
||||
|
||||
case WM_COMMAND:
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
case IDC_BUTTON_CLOSE:
|
||||
if( m_pPost != NULL )
|
||||
{
|
||||
/* Cancel reporting, and revert the dialog as if "report" had not been pressed. */
|
||||
m_pPost->Cancel();
|
||||
KillTimer( hDlg, 0 );
|
||||
|
||||
SetDialogInitial();
|
||||
SAFE_DELETE( m_pPost );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Close the dialog. */
|
||||
EndDialog(hDlg, FALSE);
|
||||
return TRUE;
|
||||
case IDOK:
|
||||
// EndDialog(hDlg, TRUE); /* don't always exit on ENTER */
|
||||
return TRUE;
|
||||
case IDC_VIEW_LOG:
|
||||
ViewWithNotepad("../log.txt");
|
||||
break;
|
||||
case IDC_CRASH_SAVE:
|
||||
ViewWithNotepad("../crashinfo.txt");
|
||||
return TRUE;
|
||||
case IDC_BUTTON_RESTART:
|
||||
Win32RestartProgram();
|
||||
EndDialog( hDlg, FALSE );
|
||||
break;
|
||||
case IDC_BUTTON_REPORT:
|
||||
GotoURL( REPORT_BUG_URL );
|
||||
break;
|
||||
case IDC_BUTTON_AUTO_REPORT:
|
||||
if( !m_sUpdateURL.empty() )
|
||||
{
|
||||
/* We already sent the report, were told that there's an update, and
|
||||
* substituted the URL. */
|
||||
GotoURL( m_sUpdateURL );
|
||||
break;
|
||||
}
|
||||
|
||||
ShowWindow( GetDlgItem(hDlg, IDC_BUTTON_AUTO_REPORT), false );
|
||||
ShowWindow( GetDlgItem(hDlg, IDC_PROGRESS), true );
|
||||
SetWindowText( GetDlgItem(hDlg, IDC_MAIN_TEXT), REPORTING_THE_PROBLEM.GetValue() );
|
||||
SetWindowText( GetDlgItem(hDlg, IDC_BUTTON_CLOSE), CANCEL.GetValue() );
|
||||
SendDlgItemMessage( hDlg, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM(0,100) );
|
||||
SendDlgItemMessage( hDlg, IDC_PROGRESS, PBM_SETPOS, 0, 0 );
|
||||
|
||||
/* Create the form data to send. */
|
||||
m_pPost = new NetworkPostData;
|
||||
m_pPost->SetData( "Product", PRODUCT_ID );
|
||||
m_pPost->SetData( "Version", PRODUCT_VER );
|
||||
m_pPost->SetData( "Arch", HOOKS->GetArchName().c_str() );
|
||||
m_pPost->SetData( "Report", m_sCrashReport );
|
||||
m_pPost->SetData( "Reason", m_CrashData.m_CrashInfo.m_CrashReason );
|
||||
|
||||
m_pPost->Start( CRASH_REPORT_HOST, CRASH_REPORT_PORT, CRASH_REPORT_PATH );
|
||||
|
||||
SetTimer( hDlg, 0, 100, NULL );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WM_TIMER:
|
||||
{
|
||||
if( m_pPost == NULL )
|
||||
break;
|
||||
|
||||
float fProgress = m_pPost->GetProgress();
|
||||
SendDlgItemMessage( hDlg, IDC_PROGRESS, PBM_SETPOS, int(fProgress*100), 0 );
|
||||
|
||||
if( m_pPost->IsFinished() )
|
||||
{
|
||||
KillTimer( hDlg, 0 );
|
||||
|
||||
/* Grab the result, which is the data output from the HTTP request. It's
|
||||
* simple XML. */
|
||||
RString sResult = m_pPost->GetResult();
|
||||
RString sError = m_pPost->GetError();
|
||||
if( sError.empty() && sResult.empty() )
|
||||
sError = "No data received";
|
||||
|
||||
SAFE_DELETE( m_pPost );
|
||||
|
||||
XNode xml;
|
||||
if( sError.empty() )
|
||||
{
|
||||
RString sError;
|
||||
XmlFileUtil::Load( &xml, sResult, sError );
|
||||
if( !sError.empty() )
|
||||
{
|
||||
sError = ssprintf( "Error parsing response: %s", sError.c_str() );
|
||||
xml.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
int iID;
|
||||
if( !sError.empty() )
|
||||
{
|
||||
/* On error, don't show the "report" button again. If the submission was actually
|
||||
* successful, then it'd be too easy to accidentally spam the server by holding
|
||||
* down the button. */
|
||||
SetWindowText( GetDlgItem(hDlg, IDC_MAIN_TEXT), ERROR_SENDING_REPORT.GetValue() );
|
||||
}
|
||||
else if( xml.GetAttrValue("UpdateAvailable", m_sUpdateURL) )
|
||||
{
|
||||
SetWindowText( GetDlgItem(hDlg, IDC_MAIN_TEXT), UPDATE_IS_AVAILABLE.GetValue() );
|
||||
SetWindowText( GetDlgItem(hDlg, IDC_BUTTON_AUTO_REPORT), VIEW_UPDATE.GetValue() );
|
||||
ShowWindow( GetDlgItem(hDlg, IDC_BUTTON_AUTO_REPORT), true );
|
||||
}
|
||||
else if( xml.GetAttrValue("ReportId", iID) )
|
||||
{
|
||||
SetWindowText( GetDlgItem(hDlg, IDC_MAIN_TEXT), UPDATE_IS_NOT_AVAILABLE.GetValue() );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowText( GetDlgItem(hDlg, IDC_MAIN_TEXT), ERROR_SENDING_REPORT.GetValue() );
|
||||
}
|
||||
|
||||
if( xml.GetAttrValue("ReportId", iID) )
|
||||
{
|
||||
char sBuf[1024];
|
||||
GetWindowText( hDlg, sBuf, 1024 );
|
||||
SetWindowText( hDlg, ssprintf("%s (#%i)", sBuf, iID) );
|
||||
}
|
||||
|
||||
ShowWindow( GetDlgItem(hDlg, IDC_PROGRESS), false );
|
||||
SetWindowText( GetDlgItem(hDlg, IDC_BUTTON_CLOSE), CLOSE.GetValue() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void ChildProcess()
|
||||
{
|
||||
/* Read the crash data from the crashed parent. */
|
||||
CompleteCrashData Data;
|
||||
ReadCrashDataFromParent( fileno(stdin), Data );
|
||||
|
||||
RString sCrashReport;
|
||||
VDDebugInfo::VDDebugInfoInitFromFile( &g_debugInfo );
|
||||
MakeCrashReport( Data, sCrashReport );
|
||||
VDDebugInfo::VDDebugInfoDeinit( &g_debugInfo );
|
||||
|
||||
DoSave( sCrashReport );
|
||||
|
||||
/* Tell the crashing process that it can exit. Be sure to write crashinfo.txt first. */
|
||||
fclose( stdout );
|
||||
|
||||
/* Now that we've done that, the process is gone. Don't use g_hParent. */
|
||||
CloseHandle( SymbolLookup::g_hParent );
|
||||
SymbolLookup::g_hParent = NULL;
|
||||
|
||||
CrashDialog cd( sCrashReport, Data );
|
||||
#if defined(AUTOMATED_CRASH_REPORTS)
|
||||
cd.Run( IDD_REPORT_CRASH );
|
||||
#else
|
||||
cd.Run( IDD_DISASM_CRASH );
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CrashHandler::CrashHandlerHandleArgs( int argc, char* argv[] )
|
||||
{
|
||||
if( argc == 2 && !strcmp(argv[1], CHILD_MAGIC_PARAMETER) )
|
||||
{
|
||||
ChildProcess();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2003-2006 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,52 @@
|
||||
#ifndef CRASH_HANDLER_INTERNAL_H
|
||||
#define CRASH_HANDLER_INTERNAL_H
|
||||
|
||||
#define BACKTRACE_MAX_SIZE 100
|
||||
|
||||
struct CrashInfo
|
||||
{
|
||||
char m_CrashReason[1024*8];
|
||||
|
||||
const void *m_BacktracePointers[BACKTRACE_MAX_SIZE];
|
||||
|
||||
enum { MAX_BACKTRACE_THREADS = 32 };
|
||||
const void *m_AlternateThreadBacktrace[MAX_BACKTRACE_THREADS][BACKTRACE_MAX_SIZE];
|
||||
char m_AlternateThreadName[MAX_BACKTRACE_THREADS][128];
|
||||
|
||||
CrashInfo()
|
||||
{
|
||||
m_CrashReason[0] = 0;
|
||||
memset( m_AlternateThreadBacktrace, 0, sizeof(m_AlternateThreadBacktrace) );
|
||||
memset( m_AlternateThreadName, 0, sizeof(m_AlternateThreadName) );
|
||||
m_BacktracePointers[0] = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
#define CHILD_MAGIC_PARAMETER "--private-do-crash-handler"
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2003-2006 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,788 @@
|
||||
#include "global.h"
|
||||
#include "CrashHandlerNetworking.h"
|
||||
#include "RageThreads.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageThreads.h"
|
||||
#include "RageTimer.h"
|
||||
#include "RageUtil.h"
|
||||
#include "Foreach.h"
|
||||
|
||||
#if defined(WINDOWS)
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#pragma comment(lib, "wsock32.lib")
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This has an arch-like abstraction layout, since it's intended to become one.
|
||||
* It'll be moved out of here as things get polished further. The Winsock and
|
||||
* BSD implementations will be kept separate, since while they look similar,
|
||||
* they're different in the details, especially when you want to cleanly support
|
||||
* cancellation.
|
||||
*
|
||||
* Design notes:
|
||||
*
|
||||
* - Allow cancellation at any time. The only thing more annoying than a laggy
|
||||
* network, is an application that won't immediately respond to cancelling.
|
||||
* (This is even more important here, since we're using this after a crash.)
|
||||
* - Assume some operations and/or some architectures are going to have problems
|
||||
* doing everything nonblockingly, and do everything in a thread. This also allows
|
||||
* more complex network interactions, since it doesn't need to maintain an equally
|
||||
* complex state machine.
|
||||
* - When an operation is cancelled or an error occurs, all operations until the
|
||||
* next call to Close() become no-ops. This allows lenient error checking; it's
|
||||
* guaranteed that further calls to Read or Write will not reset the error state.
|
||||
* - The only function that may be called from another thread without serialization is
|
||||
* Cancel().
|
||||
*
|
||||
* All calls are blocking, except for:
|
||||
*
|
||||
* - Cancel(), which is always nonblocking. The operation in progress, if any,
|
||||
* will be aborted immediately. (The only exception here is incomplete
|
||||
* implementations, which may block);
|
||||
* - Close(), if Shutdown() was called first, since the necessary blocking occurs
|
||||
* during Shutdown;
|
||||
* - Close(), if an error or cancellation occurred.
|
||||
*
|
||||
* Accepting incoming TCP connections is beyond the immediate scope of this interface
|
||||
* (that would involve a second listener class, which would be a factory for NetworkStream).
|
||||
* UDP is probably within the scope of this class, but there are some outstanding design
|
||||
* issues and it's beyond the work I'm doing right now.
|
||||
*/
|
||||
|
||||
class NetworkStream
|
||||
{
|
||||
public:
|
||||
enum ConnectionType
|
||||
{
|
||||
CONN_TCP,
|
||||
CONN_UDP,
|
||||
};
|
||||
NetworkStream() { }
|
||||
virtual ~NetworkStream() { }
|
||||
|
||||
/*
|
||||
* Open a connection. Must be in STATE_IDLE.
|
||||
*/
|
||||
virtual void Open( const RString &sHost, int iPort, ConnectionType ct = CONN_TCP ) = 0;
|
||||
|
||||
/*
|
||||
* Close down a connection. Returns to STATE_IDLE.
|
||||
*/
|
||||
virtual void Close() = 0;
|
||||
|
||||
/*
|
||||
* Wait for all sent data to be flushed, and shut down the connection.
|
||||
*/
|
||||
virtual void Shutdown() = 0;
|
||||
|
||||
/*
|
||||
* Read data. Block until any data is received, then return all data
|
||||
* available. Return the number of bytes read. The return value will
|
||||
* always be >= 0, unless an error or cancellation occured.
|
||||
*/
|
||||
virtual int Read( void *pBuffer, size_t iSize ) = 0;
|
||||
|
||||
/*
|
||||
* Write data to the socket. (Design note: we always write all of the
|
||||
* data unless an error or cancellation occurs, and those states are checked
|
||||
* with GetState(). If that happens, the number of bytes written is
|
||||
* meaningless, since it may have simply been buffered and never sent. So,
|
||||
* this function returns no value.)
|
||||
*/
|
||||
virtual void Write( const void *pBuffer, size_t iSize ) = 0;
|
||||
|
||||
/*
|
||||
* Cancel the connection. This operation can clear an error state, aborts
|
||||
* any blocking calls, never fails, and will always result in the socket
|
||||
* being in STATE_CANCELLED.
|
||||
*
|
||||
* This is true even if the state was STATE_IDLE. For example, the user
|
||||
* thread may be closing one connection on this object and opening another,
|
||||
* and the UI thread may call Cancel() in between these operations.
|
||||
*
|
||||
* This operation is threadsafe: a socket can be cancelled from any thread
|
||||
* while another thread is reading or writing. This is the only function
|
||||
* that can be called without serialization.
|
||||
*/
|
||||
virtual void Cancel() = 0;
|
||||
|
||||
enum State
|
||||
{
|
||||
/* The stream is closed, and is ready to be opened. */
|
||||
STATE_IDLE,
|
||||
|
||||
/* The stream is connected and able to send and receive data. */
|
||||
STATE_CONNECTED,
|
||||
|
||||
/* The stream has been shut down on either end (either an EOF from
|
||||
* the other end, or shutdown() being called). */
|
||||
STATE_SHUTDOWN,
|
||||
|
||||
/* When in CANCELLED, all blocking calls fail immediately; this state must be
|
||||
* cleared explicitly by calling Close(). */
|
||||
STATE_CANCELLED,
|
||||
STATE_ERROR
|
||||
};
|
||||
|
||||
State GetState() const { return m_State; }
|
||||
RString GetError() const { return m_sError; }
|
||||
|
||||
protected:
|
||||
State m_State;
|
||||
RString m_sError;
|
||||
};
|
||||
|
||||
class NetworkStream_Win32: public NetworkStream
|
||||
{
|
||||
public:
|
||||
NetworkStream_Win32();
|
||||
~NetworkStream_Win32();
|
||||
|
||||
void Open( const RString &sHost, int iPort, ConnectionType ct = CONN_TCP );
|
||||
void Shutdown();
|
||||
void Close();
|
||||
int Read( void *pBuffer, size_t iSize );
|
||||
void Write( const void *pBuffer, size_t iSize );
|
||||
|
||||
void Cancel();
|
||||
|
||||
private:
|
||||
int WaitForCompletionOrCancellation( int iEvent );
|
||||
void SetError( const RString &sError );
|
||||
static RString WinSockErrorToString( int iError );
|
||||
|
||||
SOCKET m_Socket;
|
||||
HANDLE m_hResolve;
|
||||
HWND m_hResolveHwnd;
|
||||
|
||||
/* This event is signalled on cancellation, to wake us up if we're blocking. */
|
||||
HANDLE m_hCompletionEvent;
|
||||
|
||||
RString m_sHost;
|
||||
int m_iPort;
|
||||
|
||||
RageMutex m_Mutex;
|
||||
};
|
||||
|
||||
NetworkStream *CreateNetworkStream()
|
||||
{
|
||||
static bool bInitted = false;
|
||||
if( !bInitted )
|
||||
{
|
||||
bInitted = true;
|
||||
WSADATA WSAData;
|
||||
WORD iVersionRequested = MAKEWORD(2,0);
|
||||
if( WSAStartup(iVersionRequested, &WSAData) != 0 )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new NetworkStream_Win32;
|
||||
}
|
||||
|
||||
/* WinSock implementation of NetworkStream. */
|
||||
NetworkStream_Win32::NetworkStream_Win32():
|
||||
m_Mutex( "NetworkTCPSocket" )
|
||||
{
|
||||
m_iPort = -1;
|
||||
m_State = STATE_IDLE;
|
||||
m_Socket = NULL;
|
||||
#if defined(WINDOWS)
|
||||
m_hResolve = NULL;
|
||||
m_hResolveHwnd = NULL;
|
||||
m_hCompletionEvent = CreateEvent( NULL, true, false, NULL );
|
||||
#endif
|
||||
}
|
||||
|
||||
NetworkStream_Win32::~NetworkStream_Win32()
|
||||
{
|
||||
Close();
|
||||
CloseHandle( m_hCompletionEvent );
|
||||
}
|
||||
|
||||
/* Wait for the specified network event to occur, or cancellation, whichever
|
||||
* happens first. On cancellation, return -1; on error, return the error
|
||||
* code; on success, return 0. */
|
||||
int NetworkStream_Win32::WaitForCompletionOrCancellation( int iEvent )
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
int iRet = WaitForSingleObject( m_hCompletionEvent, INFINITE );
|
||||
if( iRet != WAIT_OBJECT_0 )
|
||||
continue;
|
||||
|
||||
m_Mutex.Lock();
|
||||
|
||||
/* This will reset the event. Do this while we hold the lock. */
|
||||
WSANETWORKEVENTS events;
|
||||
WSAEnumNetworkEvents( m_Socket, m_hCompletionEvent, &events );
|
||||
|
||||
/* Was the event signalled due to cancellation? */
|
||||
if( m_State == STATE_CANCELLED )
|
||||
{
|
||||
m_Mutex.Unlock();
|
||||
return -1;
|
||||
}
|
||||
|
||||
m_Mutex.Unlock();
|
||||
|
||||
/* If the event didn't actually occur, keep waiting. */
|
||||
if( (events.lNetworkEvents & (1<<iEvent)) )
|
||||
return events.iErrorCode[iEvent];
|
||||
|
||||
/* If the socket was closed while we were waiting, stop. Note that when the
|
||||
* connection closes immediately after sending data, we'll receive both this
|
||||
* message and FD_READ at the same time. Only do this if the event we really
|
||||
* want hasn't happened yet. */
|
||||
if( (events.lNetworkEvents & (1<<FD_CLOSE_BIT)) )
|
||||
return WSAECONNRESET;
|
||||
}
|
||||
}
|
||||
|
||||
RString NetworkStream_Win32::WinSockErrorToString( int iError )
|
||||
{
|
||||
/* If iError is -1, we were cancelled and WaitForCompletionOrCancellation returned it. We won't
|
||||
* use the error string. */
|
||||
if( iError == -1 )
|
||||
return RString();
|
||||
|
||||
switch( iError )
|
||||
{
|
||||
case WSAEINTR: return "Interrupted function call.";
|
||||
case WSAEACCES: return "Permission denied.";
|
||||
case WSAEFAULT: return "Bad address.";
|
||||
case WSAEINVAL: return "Invalid argument.";
|
||||
case WSAEMFILE: return "Too many open files.";
|
||||
case WSAEWOULDBLOCK: return "Resource temporarily unavailable.";
|
||||
case WSAEINPROGRESS: return "Operation now in progress.";
|
||||
case WSAEALREADY: return "Operation already in progress.";
|
||||
case WSAENOTSOCK: return "Socket operation on nonsocket.";
|
||||
case WSAEDESTADDRREQ: return "Destination address required.";
|
||||
case WSAEMSGSIZE: return "Message too long.";
|
||||
case WSAEPROTOTYPE: return "Protocol wrong type for socket.";
|
||||
case WSAENOPROTOOPT: return "Bad protocol option.";
|
||||
case WSAEPROTONOSUPPORT: return "Protocol not supported.";
|
||||
case WSAESOCKTNOSUPPORT: return "Socket type not supported.";
|
||||
case WSAEOPNOTSUPP: return "Operation not supported.";
|
||||
case WSAEPFNOSUPPORT: return "Protocol family not supported.";
|
||||
case WSAEAFNOSUPPORT: return "Address family not supported by protocol family.";
|
||||
case WSAEADDRINUSE: return "Address already in use.";
|
||||
case WSAEADDRNOTAVAIL: return "Cannot assign requested address.";
|
||||
case WSAENETDOWN: return "Network is down.";
|
||||
case WSAENETUNREACH: return "Network is unreachable.";
|
||||
case WSAENETRESET: return "Network dropped connection on reset.";
|
||||
case WSAECONNABORTED: return "Software caused connection abort.";
|
||||
case WSAECONNRESET: return "Connection reset by peer.";
|
||||
case WSAENOBUFS: return "No buffer space available.";
|
||||
case WSAEISCONN: return "Socket is already connected.";
|
||||
case WSAENOTCONN: return "Socket is not connected.";
|
||||
case WSAESHUTDOWN: return "Cannot send after socket shutdown.";
|
||||
case WSAETIMEDOUT: return "Connection timed out.";
|
||||
case WSAECONNREFUSED: return "Connection refused.";
|
||||
case WSAEHOSTDOWN: return "Host is down.";
|
||||
case WSAEHOSTUNREACH: return "No route to host.";
|
||||
case WSAEPROCLIM: return "Too many processes.";
|
||||
case WSASYSNOTREADY: return "Network subsystem is unavailable.";
|
||||
case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range.";
|
||||
case WSANOTINITIALISED: return "Successful WSAStartup not yet performed.";
|
||||
case WSAEDISCON: return "Graceful shutdown in progress. ";
|
||||
case WSATYPE_NOT_FOUND: return "Class type not found.";
|
||||
case WSAHOST_NOT_FOUND: return "Host not found.";
|
||||
case WSATRY_AGAIN: return "Nonauthoritative host not found.";
|
||||
case WSANO_RECOVERY: return "This is a nonrecoverable error.";
|
||||
case WSANO_DATA: return "Valid name, no data record of requested type.";
|
||||
case WSA_INVALID_HANDLE: return "Specified event object handle is invalid.";
|
||||
case WSA_INVALID_PARAMETER: return "One or more parameters are invalid.";
|
||||
case WSA_IO_INCOMPLETE: return "Overlapped I/O event object not in signaled state.";
|
||||
case WSA_IO_PENDING: return "Overlapped operations will complete later.";
|
||||
case WSA_NOT_ENOUGH_MEMORY: return "Insufficient memory available.";
|
||||
case WSA_OPERATION_ABORTED: return "Overlapped operation aborted.";
|
||||
case WSASYSCALLFAILURE: return "System call failure.";
|
||||
default: return ssprintf( "unknown Winsock error %i", iError );
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkStream_Win32::SetError( const RString &sError )
|
||||
{
|
||||
m_Mutex.Lock();
|
||||
if( m_State != STATE_CANCELLED )
|
||||
{
|
||||
m_sError = sError;
|
||||
m_State = STATE_ERROR;
|
||||
}
|
||||
|
||||
if( m_Socket != INVALID_SOCKET )
|
||||
{
|
||||
closesocket( m_Socket );
|
||||
m_Socket = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
m_Mutex.Unlock();
|
||||
}
|
||||
|
||||
/* WSAAsyncGetHostByName returns events through a window. */
|
||||
#include "MessageWindow.h"
|
||||
class ResolveMessageWindow: public MessageWindow
|
||||
{
|
||||
public:
|
||||
ResolveMessageWindow(): MessageWindow("DNS notification window")
|
||||
{
|
||||
m_iResult = 0;
|
||||
}
|
||||
|
||||
int GetResult() const { return m_iResult; }
|
||||
|
||||
protected:
|
||||
bool HandleMessage( UINT msg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
if( msg == WM_USER )
|
||||
{
|
||||
m_iResult = WSAGETASYNCERROR( lParam );
|
||||
StopRunning();
|
||||
return true;
|
||||
}
|
||||
|
||||
if( msg == WM_USER+1 )
|
||||
{
|
||||
m_iResult = 0;
|
||||
StopRunning();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int m_iResult;
|
||||
};
|
||||
|
||||
void NetworkStream_Win32::Open( const RString &sHost, int iPort, ConnectionType ct )
|
||||
{
|
||||
m_Mutex.Lock();
|
||||
if( m_State == STATE_CANCELLED )
|
||||
{
|
||||
m_Mutex.Unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Always shut down a stream completely before reusing it. */
|
||||
ASSERT_M( m_State == STATE_IDLE, ssprintf("%s:%i: %i", sHost.c_str(), iPort, m_State) );
|
||||
|
||||
m_sHost = sHost;
|
||||
m_iPort = iPort;
|
||||
|
||||
/* Look up the hostname. */
|
||||
hostent *pHost = NULL;
|
||||
char pBuf[MAXGETHOSTSTRUCT];
|
||||
{
|
||||
pHost = (hostent *) pBuf;
|
||||
|
||||
ResolveMessageWindow mw;
|
||||
m_hResolve = WSAAsyncGetHostByName(
|
||||
mw.GetHwnd(),
|
||||
WM_USER,
|
||||
m_sHost,
|
||||
(char *) pHost,
|
||||
MAXGETHOSTSTRUCT
|
||||
);
|
||||
m_hResolveHwnd = mw.GetHwnd();
|
||||
m_Mutex.Unlock();
|
||||
|
||||
mw.Run();
|
||||
|
||||
m_Mutex.Lock();
|
||||
m_hResolve = NULL;
|
||||
m_hResolveHwnd = NULL;
|
||||
if( m_State == STATE_CANCELLED )
|
||||
{
|
||||
m_Mutex.Unlock();
|
||||
return;
|
||||
}
|
||||
int iError = mw.GetResult();
|
||||
if( iError )
|
||||
{
|
||||
SetError( ssprintf("DNS error: %s", WinSockErrorToString(iError).c_str() ) );
|
||||
m_Mutex.Unlock();
|
||||
return;
|
||||
}
|
||||
m_Mutex.Unlock();
|
||||
}
|
||||
|
||||
{
|
||||
sockaddr_in addr;
|
||||
addr.sin_addr.s_addr = *(DWORD *)pHost->h_addr_list[0];
|
||||
addr.sin_family = PF_INET;
|
||||
addr.sin_port = htons( (uint16_t) iPort );
|
||||
|
||||
m_Mutex.Lock();
|
||||
m_Socket = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
|
||||
if( m_Socket == INVALID_SOCKET )
|
||||
{
|
||||
int iError = WSAGetLastError();
|
||||
SetError( ssprintf("Error creating socket: %s", WinSockErrorToString(iError).c_str() ) );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set up the completion event to be signalled when these events occur. This
|
||||
* also sets the socket to nonblocking. */
|
||||
WSAEventSelect( m_Socket, m_hCompletionEvent, FD_CONNECT|FD_READ|FD_WRITE|FD_CLOSE );
|
||||
|
||||
// fcntl( m_Socket, O_NONBLOCK, 1 );
|
||||
|
||||
/* Start opening the connection. */
|
||||
int iResult = connect(m_Socket, (SOCKADDR *) &addr, sizeof(addr));
|
||||
|
||||
m_Mutex.Unlock();
|
||||
|
||||
/* We expect EINPROGRESS/WSAEWOULDBLOCK. */
|
||||
if( iResult == SOCKET_ERROR )
|
||||
{
|
||||
/* Block until the connection attempt completes. */
|
||||
int iError = WSAGetLastError();
|
||||
if( iError == WSAEWOULDBLOCK )
|
||||
iError = WaitForCompletionOrCancellation( FD_CONNECT_BIT );
|
||||
if( iError )
|
||||
{
|
||||
SetError( ssprintf("Couldn't connect: %s", WinSockErrorToString(iError).c_str() ) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_State = STATE_CONNECTED;
|
||||
}
|
||||
|
||||
void NetworkStream_Win32::Close()
|
||||
{
|
||||
if( m_State == STATE_IDLE )
|
||||
return;
|
||||
|
||||
/* If we have an active, stable connection, make sure we flush any data
|
||||
* completely before closing. If you don't want to do this, call Cancel()
|
||||
* first. */
|
||||
Shutdown();
|
||||
|
||||
m_Mutex.Lock();
|
||||
if( m_State == STATE_CANCELLED )
|
||||
return;
|
||||
|
||||
if( m_Socket != INVALID_SOCKET )
|
||||
closesocket( m_Socket );
|
||||
m_Socket = INVALID_SOCKET;
|
||||
m_State = STATE_IDLE;
|
||||
m_Mutex.Unlock();
|
||||
}
|
||||
|
||||
void NetworkStream_Win32::Shutdown()
|
||||
{
|
||||
/* If we're not in a normal, stable state (eg. an error occurred, or we were
|
||||
* cancelled), don't wait to flush. */
|
||||
if( m_State != STATE_CONNECTED )
|
||||
return;
|
||||
|
||||
shutdown( m_Socket, SD_BOTH );
|
||||
m_State = STATE_SHUTDOWN;
|
||||
}
|
||||
|
||||
void NetworkStream_Win32::Cancel()
|
||||
{
|
||||
m_Mutex.Lock();
|
||||
|
||||
/* Mark cancellation. */
|
||||
m_State = STATE_CANCELLED;
|
||||
|
||||
/* If resolving, abort the resolve. */
|
||||
if( m_hResolve != NULL )
|
||||
{
|
||||
/* When we cancel the request, no message at all will be sent to the window,
|
||||
* so we need to do it ourself to inform it that it was cancelled. Be sure
|
||||
* to only do this on successful cancel. */
|
||||
if( WSACancelAsyncRequest(m_hResolve) == 0 )
|
||||
PostMessage( m_hResolveHwnd, WM_USER+1, 0, 0 );
|
||||
}
|
||||
|
||||
/* Break out if we're waiting in WaitForCompletionOrCancellation(). */
|
||||
SetEvent( m_hCompletionEvent );
|
||||
|
||||
m_Mutex.Unlock();
|
||||
}
|
||||
|
||||
int NetworkStream_Win32::Read( void *pBuffer, size_t iSize )
|
||||
{
|
||||
if( m_State != STATE_CONNECTED )
|
||||
return 0;
|
||||
|
||||
char *p = (char *) pBuffer;
|
||||
int iRead = 0;
|
||||
while( iSize > 0 )
|
||||
{
|
||||
int iRet = recv( m_Socket, p, iSize, 0 );
|
||||
if( iRet > 0 )
|
||||
{
|
||||
p += iRet;
|
||||
iSize -= iRet;
|
||||
iRead += iRet;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( iRet == 0 )
|
||||
{
|
||||
/* We hit EOF. */
|
||||
break;
|
||||
}
|
||||
|
||||
int iError = WSAGetLastError();
|
||||
if( iError == WSAEWOULDBLOCK )
|
||||
{
|
||||
/* There's no date to read. If we've already received some data, return it. */
|
||||
if( iRead > 0 )
|
||||
break;
|
||||
|
||||
iError = WaitForCompletionOrCancellation( FD_READ_BIT );
|
||||
if( iError == 0 )
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If the other side closed the connection, just return EOF. */
|
||||
if( iError == WSAECONNRESET )
|
||||
break;
|
||||
|
||||
/* If we're cancelled or hit an error while reading, do return the data we managed
|
||||
* to get. Be sure not to overwrite CANCELLED with ERROR. */
|
||||
SetError( ssprintf("Error reading: %s", WinSockErrorToString(iError).c_str() ) );
|
||||
break;
|
||||
}
|
||||
|
||||
return iRead;
|
||||
}
|
||||
|
||||
void NetworkStream_Win32::Write( const void *pBuffer, size_t iSize )
|
||||
{
|
||||
if( m_State != STATE_CONNECTED )
|
||||
return;
|
||||
|
||||
const char *p = (const char *) pBuffer;
|
||||
while( iSize > 0 )
|
||||
{
|
||||
int iRet = send( m_Socket, p, iSize, 0 );
|
||||
ASSERT( iRet != 0 );
|
||||
if( iRet > 0 )
|
||||
{
|
||||
p += iRet;
|
||||
iSize -= iRet;
|
||||
continue;
|
||||
}
|
||||
|
||||
int iError = WSAGetLastError();
|
||||
if( iError == WSAEWOULDBLOCK )
|
||||
{
|
||||
iError = WaitForCompletionOrCancellation( FD_WRITE_BIT );
|
||||
if( iError == 0 )
|
||||
continue;
|
||||
}
|
||||
|
||||
SetError( ssprintf("Error writing: %s", WinSockErrorToString(iError).c_str() ) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a set of data over HTTP, as a POST form.
|
||||
*/
|
||||
|
||||
NetworkPostData::NetworkPostData():
|
||||
m_Mutex( "NetworkPostData" )
|
||||
{
|
||||
m_pStream = CreateNetworkStream();
|
||||
}
|
||||
|
||||
NetworkPostData::~NetworkPostData()
|
||||
{
|
||||
delete m_pStream;
|
||||
}
|
||||
|
||||
/* Create a MIME multipart data block from the given set of fields. */
|
||||
void NetworkPostData::CreateMimeData( const map<RString,RString> &mapNameToData, RString &sOut, RString &sMimeBoundaryOut )
|
||||
{
|
||||
/* Find a non-conflicting mime boundary. */
|
||||
while(1)
|
||||
{
|
||||
sMimeBoundaryOut = ssprintf( "--%08i", rand() );
|
||||
FOREACHM_CONST( RString, RString, mapNameToData, d )
|
||||
if( d->second.find(sMimeBoundaryOut) != RString::npos )
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
FOREACHM_CONST( RString, RString, mapNameToData, d )
|
||||
{
|
||||
sOut += "--" + sMimeBoundaryOut + "\r\n";
|
||||
sOut += ssprintf( "Content-Disposition: form-data; name=\"%s\"\r\n", d->first.c_str() );
|
||||
sOut += "\r\n";
|
||||
sOut += d->second;
|
||||
sOut += "\r\n";
|
||||
}
|
||||
if( sOut.size() )
|
||||
sOut += "--" + sMimeBoundaryOut + "--\r\n";
|
||||
|
||||
}
|
||||
|
||||
void NetworkPostData::HttpThread()
|
||||
{
|
||||
RString sData, sMimeBoundary;
|
||||
CreateMimeData( m_Data, sData, sMimeBoundary );
|
||||
|
||||
// Stick to HTTP/1.0, since the protocol is simpler.
|
||||
RString sBuf = ssprintf(
|
||||
"%s %s HTTP/1.0\r\n"
|
||||
"Accept: */*\r\n"
|
||||
"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)\r\n"
|
||||
"Host: %s\r\n"
|
||||
"Cache-Control: no-cache\r\n",
|
||||
sData.size()? "POST":"GET",
|
||||
m_sPath.c_str(),
|
||||
m_sHost.c_str() );
|
||||
|
||||
if( sData.size() )
|
||||
{
|
||||
// sBuf += "Content-Type: application/x-www-form-urlencoded\r\n"
|
||||
sBuf += "Content-Type: multipart/form-data; boundary=" + sMimeBoundary + "\r\n";
|
||||
sBuf += ssprintf( "Content-Length: %i\r\n", sData.size() );
|
||||
}
|
||||
sBuf += "\r\n";
|
||||
|
||||
if( sData.size() )
|
||||
sBuf += sData;
|
||||
|
||||
/* The "progress" is currently faked; it shows when we've connected, and when
|
||||
* we've received data. We send and receive too little data to do more. */
|
||||
SetProgress( 0 );
|
||||
|
||||
/*
|
||||
* Begin connecting.
|
||||
*/
|
||||
m_pStream->Open( m_sHost, m_iPort );
|
||||
SetProgress( 0.25f );
|
||||
|
||||
/* Send the form. */
|
||||
m_pStream->Write( sBuf.data(), sBuf.size() );
|
||||
|
||||
/* Read the result. */
|
||||
RString sResult;
|
||||
while( m_pStream->GetState() == NetworkStream::STATE_CONNECTED )
|
||||
{
|
||||
sBuf.clear();
|
||||
void *p = sBuf.GetBuffer( 1024 );
|
||||
int iGot = m_pStream->Read( p, 1024 );
|
||||
if( iGot >= 0 )
|
||||
sBuf.ReleaseBuffer( iGot );
|
||||
if( iGot <= 0 )
|
||||
break;
|
||||
sResult += sBuf;
|
||||
}
|
||||
|
||||
SetProgress( 1.0f );
|
||||
|
||||
/* Parse the results. */
|
||||
int iStart = 0, iSize = -1;
|
||||
map<RString,RString> mapHeaders;
|
||||
while( 1 )
|
||||
{
|
||||
split( sResult, "\n", iStart, iSize, false );
|
||||
if( iStart == (int) sResult.size() )
|
||||
break;
|
||||
|
||||
RString sLine = sResult.substr( iStart, iSize );
|
||||
StripCrnl( sLine );
|
||||
if( sLine.empty() )
|
||||
{
|
||||
m_sResult = sResult.substr( iStart+iSize+1 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_bFinished = true;
|
||||
}
|
||||
|
||||
void NetworkPostData::Start( const RString &sHost, int iPort, const RString &sPath )
|
||||
{
|
||||
m_bFinished = false;
|
||||
m_sHost = sHost;
|
||||
m_iPort = iPort;
|
||||
m_sPath = sPath;
|
||||
m_sStatus.clear();
|
||||
m_fProgress = 0;
|
||||
|
||||
m_Thread.SetName( "HTTP thread" );
|
||||
m_Thread.Create( HttpThread_Start, this );
|
||||
}
|
||||
|
||||
void NetworkPostData::Cancel()
|
||||
{
|
||||
m_pStream->Cancel();
|
||||
m_Thread.Wait();
|
||||
}
|
||||
|
||||
bool NetworkPostData::IsFinished()
|
||||
{
|
||||
if( !m_bFinished )
|
||||
return false;
|
||||
|
||||
m_Thread.Wait();
|
||||
m_bFinished = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
RString NetworkPostData::GetStatus() const
|
||||
{
|
||||
LockMut( m_Mutex );
|
||||
return m_sStatus;
|
||||
}
|
||||
|
||||
float NetworkPostData::GetProgress() const
|
||||
{
|
||||
LockMut( m_Mutex );
|
||||
return m_fProgress;
|
||||
}
|
||||
|
||||
RString NetworkPostData::GetError() const
|
||||
{
|
||||
return m_pStream->GetError();
|
||||
}
|
||||
|
||||
void NetworkPostData::SetProgress( float fProgress )
|
||||
{
|
||||
m_Mutex.Lock();
|
||||
m_fProgress = fProgress;
|
||||
m_Mutex.Unlock();
|
||||
}
|
||||
|
||||
void NetworkPostData::SetData( const RString &sKey, const RString &sData )
|
||||
{
|
||||
m_Data[sKey] = sData;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2006 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,83 @@
|
||||
#ifndef CRASH_HANDLER_NETWORKING_H
|
||||
#define CRASH_HANDLER_NETWORKING_H
|
||||
|
||||
#include "RageThreads.h"
|
||||
#include <map>
|
||||
|
||||
class NetworkStream;
|
||||
|
||||
/*
|
||||
* Send a set of data over HTTP, as a POST form.
|
||||
*/
|
||||
class NetworkPostData
|
||||
{
|
||||
public:
|
||||
NetworkPostData();
|
||||
~NetworkPostData();
|
||||
|
||||
void SetData( const RString &sKey, const RString &sData );
|
||||
|
||||
/* For simplicity, we don't parse URLs here. */
|
||||
void Start( const RString &sHost, int iPort, const RString &sPath );
|
||||
|
||||
/* Cancel the running operation, and close the thread. */
|
||||
void Cancel();
|
||||
|
||||
/* If the operation is unfinished, return false. Otherwise, close the thread and return true. */
|
||||
bool IsFinished();
|
||||
|
||||
RString GetStatus() const;
|
||||
float GetProgress() const;
|
||||
RString GetError() const;
|
||||
RString GetResult() const { return m_sResult; }
|
||||
|
||||
private:
|
||||
static void CreateMimeData( const map<RString,RString> &mapNameToData, RString &sOut, RString &sMimeBoundaryOut );
|
||||
void SetProgress( float fProgress );
|
||||
|
||||
RageThread m_Thread;
|
||||
void HttpThread();
|
||||
static int HttpThread_Start( void *p ) { ((NetworkPostData *) p)->HttpThread(); return 0; }
|
||||
|
||||
mutable RageMutex m_Mutex;
|
||||
RString m_sStatus;
|
||||
float m_fProgress;
|
||||
|
||||
/* When the thread exists, it owns the rest of the data, regardless of m_Mutex. */
|
||||
map<RString, RString> m_Data;
|
||||
|
||||
bool m_bFinished;
|
||||
RString m_sHost;
|
||||
int m_iPort;
|
||||
RString m_sPath;
|
||||
RString m_sResult;
|
||||
|
||||
NetworkStream *m_pStream;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2006 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,286 @@
|
||||
#include "global.h"
|
||||
#include "DebugInfoHunt.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
#include "VideoDriverInfo.h"
|
||||
#include "RegistryAccess.h"
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
|
||||
static void LogVideoDriverInfo( VideoDriverInfo info )
|
||||
{
|
||||
LOG->Info( "Video driver: %s [%s]", info.sDescription.c_str(), info.sProvider.c_str() );
|
||||
LOG->Info( " %s, %s [%s]", info.sVersion.c_str(), info.sDate.c_str(), info.sDeviceID.c_str() );
|
||||
}
|
||||
|
||||
static void GetMemoryDebugInfo()
|
||||
{
|
||||
MEMORYSTATUS mem;
|
||||
GlobalMemoryStatus(&mem);
|
||||
|
||||
LOG->Info("Memory: %imb total, %imb swap (%imb swap avail)",
|
||||
mem.dwTotalPhys / 1048576,
|
||||
mem.dwTotalPageFile / 1048576,
|
||||
mem.dwAvailPageFile / 1048576);
|
||||
}
|
||||
|
||||
static void GetDisplayDriverDebugInfo()
|
||||
{
|
||||
RString sPrimaryDeviceName = GetPrimaryVideoName();
|
||||
|
||||
if( sPrimaryDeviceName == "" )
|
||||
LOG->Info( "Primary display driver could not be determined." );
|
||||
|
||||
bool LoggedSomething = false;
|
||||
for( int i=0; true; i++ )
|
||||
{
|
||||
VideoDriverInfo info;
|
||||
if( !GetVideoDriverInfo(i, info) )
|
||||
break;
|
||||
|
||||
if( sPrimaryDeviceName == "" ) // failed to get primary display name (NT4)
|
||||
{
|
||||
LogVideoDriverInfo( info );
|
||||
LoggedSomething = true;
|
||||
}
|
||||
else if( info.sDescription == sPrimaryDeviceName )
|
||||
{
|
||||
LogVideoDriverInfo( info );
|
||||
LoggedSomething = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !LoggedSomething )
|
||||
{
|
||||
LOG->Info( "Primary display driver: %s", sPrimaryDeviceName.c_str() );
|
||||
LOG->Warn("Couldn't find primary display driver; logging all drivers");
|
||||
|
||||
for( int i=0; true; i++ )
|
||||
{
|
||||
VideoDriverInfo info;
|
||||
if( !GetVideoDriverInfo(i, info) )
|
||||
break;
|
||||
|
||||
LogVideoDriverInfo( info );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static RString wo_ssprintf( MMRESULT err, const char *fmt, ...)
|
||||
{
|
||||
char buf[MAXERRORLENGTH];
|
||||
waveOutGetErrorText(err, buf, MAXERRORLENGTH);
|
||||
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
RString s = vssprintf( fmt, va );
|
||||
va_end(va);
|
||||
|
||||
return s += ssprintf( "(%s)", buf );
|
||||
}
|
||||
|
||||
static void GetDriveDebugInfo9x()
|
||||
{
|
||||
|
||||
/*
|
||||
* HKEY_LOCAL_MACHINE\Enum\ESDI
|
||||
* *\ (disk id)
|
||||
* *\ (eg. MF&CHILD0000&PCI&VEN_8086&DEV_7111&SUBSYS_197615AD&REV_01&BUS_00&DEV_07&FUNC_0100)
|
||||
* DMACurrentlyUsed 0 or 1
|
||||
* DeviceDesc "GENERIC IDE DISK TYPE01"
|
||||
*/
|
||||
vector<RString> Drives;
|
||||
if( !RegistryAccess::GetRegSubKeys( "HKEY_LOCAL_MACHINE\\Enum\\ESDI", Drives ) )
|
||||
return;
|
||||
|
||||
for( unsigned drive = 0; drive < Drives.size(); ++drive )
|
||||
{
|
||||
vector<RString> IDs;
|
||||
if( !RegistryAccess::GetRegSubKeys( Drives[drive], IDs ) )
|
||||
continue;
|
||||
|
||||
for( unsigned id = 0; id < IDs.size(); ++id )
|
||||
{
|
||||
RString DeviceDesc;
|
||||
|
||||
RegistryAccess::GetRegValue( IDs[id], "DeviceDesc", DeviceDesc );
|
||||
TrimRight( DeviceDesc );
|
||||
|
||||
int DMACurrentlyUsed = -1;
|
||||
RegistryAccess::GetRegValue( IDs[id], "DMACurrentlyUsed", DMACurrentlyUsed );
|
||||
|
||||
LOG->Info( "Drive: \"%s\" DMA: %s",
|
||||
DeviceDesc.c_str(), DMACurrentlyUsed? "yes":"NO" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GetDriveDebugInfoNT()
|
||||
{
|
||||
/*
|
||||
* HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\Scsi\
|
||||
* Scsi Port *\
|
||||
* DMAEnabled 0 or 1
|
||||
* Driver "Ultra", "atapi", etc
|
||||
* Scsi Bus *\
|
||||
* Target Id *\
|
||||
* Logical Unit Id *\
|
||||
* Identifier "WDC WD1200JB-75CRA0"
|
||||
* Type "DiskPeripheral"
|
||||
*/
|
||||
vector<RString> Ports;
|
||||
if( !RegistryAccess::GetRegSubKeys( "HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\Scsi", Ports ) )
|
||||
return;
|
||||
|
||||
for( unsigned i = 0; i < Ports.size(); ++i )
|
||||
{
|
||||
int DMAEnabled = -1;
|
||||
RegistryAccess::GetRegValue( Ports[i], "DMAEnabled", DMAEnabled );
|
||||
|
||||
RString Driver;
|
||||
RegistryAccess::GetRegValue( Ports[i], "Driver", Driver );
|
||||
|
||||
vector<RString> Busses;
|
||||
if( !RegistryAccess::GetRegSubKeys( Ports[i], Busses, "Scsi Bus .*" ) )
|
||||
continue;
|
||||
|
||||
for( unsigned bus = 0; bus < Busses.size(); ++bus )
|
||||
{
|
||||
vector<RString> TargetIDs;
|
||||
if( !RegistryAccess::GetRegSubKeys( Busses[bus], TargetIDs, "Target Id .*" ) )
|
||||
continue;
|
||||
|
||||
for( unsigned tid = 0; tid < TargetIDs.size(); ++tid )
|
||||
{
|
||||
vector<RString> LUIDs;
|
||||
if( !RegistryAccess::GetRegSubKeys( TargetIDs[tid], LUIDs, "Logical Unit Id .*" ) )
|
||||
continue;
|
||||
|
||||
for( unsigned luid = 0; luid < LUIDs.size(); ++luid )
|
||||
{
|
||||
RString Identifier;
|
||||
RegistryAccess::GetRegValue( LUIDs[luid], "Identifier", Identifier );
|
||||
TrimRight( Identifier );
|
||||
LOG->Info( "Drive: \"%s\" Driver: %s DMA: %s",
|
||||
Identifier.c_str(), Driver.c_str(), DMAEnabled == 1? "yes":DMAEnabled == -1? "N/A":"NO" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GetDriveDebugInfo()
|
||||
{
|
||||
OSVERSIONINFO ovi;
|
||||
ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
if( !GetVersionEx(&ovi) )
|
||||
{
|
||||
LOG->Info("GetVersionEx failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
switch( ovi.dwPlatformId )
|
||||
{
|
||||
case VER_PLATFORM_WIN32_WINDOWS:
|
||||
GetDriveDebugInfo9x(); break;
|
||||
case VER_PLATFORM_WIN32_NT:
|
||||
GetDriveDebugInfoNT(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void GetWindowsVersionDebugInfo()
|
||||
{
|
||||
/* Detect operating system. */
|
||||
OSVERSIONINFO ovi;
|
||||
ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
if (!GetVersionEx(&ovi))
|
||||
{
|
||||
LOG->Info("GetVersionEx failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
RString Ver = ssprintf("Windows %i.%i (", ovi.dwMajorVersion, ovi.dwMinorVersion);
|
||||
if(ovi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
|
||||
{
|
||||
if(ovi.dwMinorVersion == 0)
|
||||
Ver += "Win95";
|
||||
else if(ovi.dwMinorVersion == 10)
|
||||
Ver += "Win98";
|
||||
else if(ovi.dwMinorVersion == 90)
|
||||
Ver += "WinME";
|
||||
else
|
||||
Ver += "unknown 9x-based";
|
||||
}
|
||||
else if(ovi.dwPlatformId == VER_PLATFORM_WIN32_NT)
|
||||
{
|
||||
if(ovi.dwMajorVersion == 4 && ovi.dwMinorVersion == 0)
|
||||
Ver += "WinNT 4.0";
|
||||
else if(ovi.dwMajorVersion == 5 && ovi.dwMinorVersion == 0)
|
||||
Ver += "Win2000";
|
||||
else if(ovi.dwMajorVersion == 5 && ovi.dwMinorVersion == 1)
|
||||
Ver += "WinXP";
|
||||
else
|
||||
Ver += "unknown NT-based";
|
||||
} else Ver += "???";
|
||||
|
||||
Ver += ssprintf(") build %i [%s]", ovi.dwBuildNumber & 0xffff, ovi.szCSDVersion);
|
||||
LOG->Info("%s", Ver.c_str());
|
||||
}
|
||||
|
||||
static void GetSoundDriverDebugInfo()
|
||||
{
|
||||
int cnt = waveOutGetNumDevs();
|
||||
|
||||
for(int i = 0; i < cnt; ++i)
|
||||
{
|
||||
WAVEOUTCAPS caps;
|
||||
|
||||
MMRESULT ret = waveOutGetDevCaps(i, &caps, sizeof(caps));
|
||||
if(ret != MMSYSERR_NOERROR)
|
||||
{
|
||||
LOG->Info(wo_ssprintf(ret, "waveOutGetDevCaps(%i) failed", i));
|
||||
continue;
|
||||
}
|
||||
LOG->Info("Sound device %i: %s, %i.%i, MID %i, PID %i %s", i, caps.szPname,
|
||||
HIBYTE(caps.vDriverVersion),
|
||||
LOBYTE(caps.vDriverVersion),
|
||||
caps.wMid, caps.wPid,
|
||||
caps.dwSupport & WAVECAPS_SAMPLEACCURATE? "":"(INACCURATE)");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SearchForDebugInfo()
|
||||
{
|
||||
GetWindowsVersionDebugInfo();
|
||||
GetMemoryDebugInfo();
|
||||
GetDisplayDriverDebugInfo();
|
||||
GetDriveDebugInfo();
|
||||
GetSoundDriverDebugInfo();
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2003-2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef DEBUG_INFO_HUNT_H
|
||||
#define DEBUG_INFO_HUNT_H
|
||||
|
||||
/* We want debug information; Windows makes us hunt for it. */
|
||||
void SearchForDebugInfo();
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2003-2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,109 @@
|
||||
#include "global.h"
|
||||
#include "DialogUtil.h"
|
||||
#include "RageUtil.h"
|
||||
#include "ThemeManager.h"
|
||||
#include "archutils/Win32/ErrorStrings.h"
|
||||
|
||||
// Create*Font copied from MFC's CFont
|
||||
|
||||
// pLogFont->nHeight is interpreted as PointSize * 10
|
||||
static HFONT CreatePointFontIndirect(const LOGFONT* lpLogFont)
|
||||
{
|
||||
HDC hDC = ::GetDC(NULL);
|
||||
|
||||
// convert nPointSize to logical units based on pDC
|
||||
LOGFONT logFont = *lpLogFont;
|
||||
POINT pt;
|
||||
pt.y = ::GetDeviceCaps(hDC, LOGPIXELSY) * logFont.lfHeight;
|
||||
pt.y /= 720; // 72 points/inch, 10 decipoints/point
|
||||
pt.x = 0;
|
||||
::DPtoLP(hDC, &pt, 1);
|
||||
POINT ptOrg = { 0, 0 };
|
||||
::DPtoLP(hDC, &ptOrg, 1);
|
||||
logFont.lfHeight = -abs(pt.y - ptOrg.y);
|
||||
|
||||
ReleaseDC(NULL, hDC);
|
||||
|
||||
return ::CreateFontIndirect(&logFont);
|
||||
}
|
||||
|
||||
// nPointSize is actually scaled 10x
|
||||
static HFONT CreatePointFont(int nPointSize, LPCTSTR lpszFaceName)
|
||||
{
|
||||
ASSERT(lpszFaceName);
|
||||
|
||||
LOGFONT logFont;
|
||||
memset(&logFont, 0, sizeof(LOGFONT));
|
||||
logFont.lfCharSet = DEFAULT_CHARSET;
|
||||
logFont.lfHeight = nPointSize;
|
||||
lstrcpyn(logFont.lfFaceName, lpszFaceName, strlen(logFont.lfFaceName));
|
||||
|
||||
return ::CreatePointFontIndirect(&logFont);
|
||||
}
|
||||
|
||||
void DialogUtil::SetHeaderFont( HWND hdlg, int nID )
|
||||
{
|
||||
ASSERT( hdlg );
|
||||
|
||||
HWND hControl = ::GetDlgItem( hdlg, nID );
|
||||
ASSERT( hControl );
|
||||
|
||||
// TODO: Fix font leak
|
||||
const int FONT_POINTS = 16;
|
||||
HFONT hfont = CreatePointFont( FONT_POINTS*10, "Arial Black" );
|
||||
::SendMessage( hControl, WM_SETFONT, (WPARAM)hfont, TRUE );
|
||||
}
|
||||
|
||||
void DialogUtil::LocalizeDialogAndContents( HWND hdlg )
|
||||
{
|
||||
ASSERT( THEME );
|
||||
|
||||
const int LARGE_STRING = 256;
|
||||
char szTemp[LARGE_STRING] = "";
|
||||
RString sGroup;
|
||||
|
||||
{
|
||||
::GetWindowText( hdlg, szTemp, ARRAYLEN(szTemp) );
|
||||
RString s = szTemp;
|
||||
sGroup = "Dialog-"+s;
|
||||
s = THEME->GetString( sGroup, s );
|
||||
::SetWindowText( hdlg, ConvertUTF8ToACP(s).c_str() );
|
||||
}
|
||||
|
||||
for( HWND hwndChild = ::GetTopWindow(hdlg); hwndChild != NULL; hwndChild = ::GetNextWindow(hwndChild,GW_HWNDNEXT) )
|
||||
{
|
||||
::GetWindowText( hwndChild, szTemp, ARRAYLEN(szTemp) );
|
||||
RString s = szTemp;
|
||||
if( s.empty() )
|
||||
continue;
|
||||
s = THEME->GetString( sGroup, s );
|
||||
::SetWindowText( hwndChild, ConvertUTF8ToACP(s).c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (c) 2002-2004 Chris Danford
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef DialogUtil_H
|
||||
#define DialogUtil_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
namespace DialogUtil
|
||||
{
|
||||
void SetHeaderFont( HWND hdlg, int nID );
|
||||
void LocalizeDialogAndContents( HWND hdlg );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2002-2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "global.h"
|
||||
#include "DirectXHelpers.h"
|
||||
#include "RageUtil.h"
|
||||
|
||||
#ifdef _XBOX
|
||||
# include <D3DX8Core.h>
|
||||
#else
|
||||
# include <windows.h>
|
||||
# include <dxerr8.h>
|
||||
# if defined(_MSC_VER)
|
||||
# pragma comment(lib, "dxerr8.lib")
|
||||
# endif
|
||||
#endif
|
||||
|
||||
RString hr_ssprintf( int hr, const char *fmt, ... )
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
RString s = vssprintf( fmt, va );
|
||||
va_end(va);
|
||||
|
||||
#ifdef _XBOX
|
||||
char szError[1024] = "";
|
||||
D3DXGetErrorString( hr, szError, sizeof(szError) );
|
||||
#else
|
||||
const char *szError = DXGetErrorString8( hr );
|
||||
#endif
|
||||
|
||||
return s + ssprintf( " (%s)", szError );
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2005 Chris Danford, Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef DIRECTX_HELPERS_H
|
||||
#define DIRECTX_HELPERS_H
|
||||
|
||||
RString hr_ssprintf( int hr, const char *fmt, ... );
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2005 Chris Danford, Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,97 @@
|
||||
#include "global.h"
|
||||
#include "ErrorStrings.h"
|
||||
#include "RageUtil.h"
|
||||
|
||||
#if !defined(XBOX)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
RString werr_ssprintf( int err, const char *fmt, ... )
|
||||
{
|
||||
char buf[1024] = "";
|
||||
#ifndef _XBOX
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
0, err, 0, buf, sizeof(buf), NULL);
|
||||
#endif
|
||||
|
||||
/* Why is FormatMessage returning text ending with \r\n? */
|
||||
RString text = buf;
|
||||
text.Replace( "\n", "" );
|
||||
text.Replace( "\r", " " ); /* foo\r\nbar -> foo bar */
|
||||
TrimRight( text ); /* "foo\r\n" -> "foo" */
|
||||
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
RString s = vssprintf( fmt, va );
|
||||
va_end(va);
|
||||
|
||||
return s += ssprintf( " (%s)", text.c_str() );
|
||||
}
|
||||
|
||||
RString ConvertWstringToCodepage( wstring s, int iCodePage )
|
||||
{
|
||||
if( s.empty() )
|
||||
return RString();
|
||||
|
||||
int iBytes = WideCharToMultiByte( iCodePage, 0, s.data(), s.size(),
|
||||
NULL, 0, NULL, FALSE );
|
||||
ASSERT_M( iBytes > 0, werr_ssprintf( GetLastError(), "WideCharToMultiByte" ).c_str() );
|
||||
|
||||
RString ret;
|
||||
WideCharToMultiByte( CP_ACP, 0, s.data(), s.size(),
|
||||
ret.GetBuffer( iBytes ), iBytes, NULL, FALSE );
|
||||
ret.ReleaseBuffer( iBytes );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
RString ConvertUTF8ToACP( const RString &s )
|
||||
{
|
||||
return ConvertWstringToCodepage( RStringToWstring(s), CP_ACP );
|
||||
}
|
||||
|
||||
wstring ConvertCodepageToWString( RString s, int iCodePage )
|
||||
{
|
||||
if( s.empty() )
|
||||
return wstring();
|
||||
|
||||
int iBytes = MultiByteToWideChar( iCodePage, 0, s.data(), s.size(), NULL, 0 );
|
||||
ASSERT_M( iBytes > 0, werr_ssprintf( GetLastError(), "MultiByteToWideChar" ).c_str() );
|
||||
|
||||
wchar_t *pTemp = new wchar_t[iBytes];
|
||||
MultiByteToWideChar( iCodePage, 0, s.data(), s.size(), pTemp, iBytes );
|
||||
wstring sRet( pTemp, iBytes );
|
||||
delete [] pTemp;
|
||||
|
||||
return sRet;
|
||||
}
|
||||
|
||||
RString ConvertACPToUTF8( const RString &s )
|
||||
{
|
||||
return WStringToRString( ConvertCodepageToWString(s, CP_ACP) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2005 Chris Danford, Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef ERROR_STRINGS_H
|
||||
#define ERROR_STRINGS_H
|
||||
|
||||
RString werr_ssprintf( int err, const char *fmt, ... );
|
||||
RString ConvertWstringToCodepage( wstring s, int iCodePage );
|
||||
RString ConvertUTF8ToACP( const RString &s );
|
||||
wstring ConvertCodepageToWString( RString s, int iCodePage );
|
||||
RString ConvertACPToUTF8( const RString &s );
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2005 Chris Danford, Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,196 @@
|
||||
#include "global.h"
|
||||
#include "GetFileInformation.h"
|
||||
|
||||
#include "RageUtil.h"
|
||||
#include "archutils/Win32/ErrorStrings.h"
|
||||
#include <sys/stat.h>
|
||||
#include <windows.h>
|
||||
#include <tlhelp32.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma comment(lib, "version.lib")
|
||||
#endif
|
||||
|
||||
bool GetFileVersion( RString sFile, RString &sOut )
|
||||
{
|
||||
do {
|
||||
/* Cast away const to work around header bug in VC6. */
|
||||
DWORD ignore;
|
||||
DWORD iSize = GetFileVersionInfoSize( const_cast<char *>(sFile.c_str()), &ignore );
|
||||
if( !iSize )
|
||||
break;
|
||||
|
||||
RString VersionBuffer( iSize, ' ' );
|
||||
/* Also VC6: */
|
||||
if( !GetFileVersionInfo( const_cast<char *>(sFile.c_str()), NULL, iSize, VersionBuffer.GetBuffer() ) )
|
||||
break;
|
||||
|
||||
WORD *iTrans;
|
||||
UINT iTransCnt;
|
||||
|
||||
if( !VerQueryValue( (void *) VersionBuffer.c_str() , "\\VarFileInfo\\Translation",
|
||||
(void **) &iTrans, &iTransCnt ) )
|
||||
break;
|
||||
|
||||
if( iTransCnt == 0 )
|
||||
break;
|
||||
|
||||
char *str;
|
||||
UINT len;
|
||||
|
||||
RString sRes = ssprintf( "\\StringFileInfo\\%04x%04x\\FileVersion",
|
||||
iTrans[0], iTrans[1] );
|
||||
if( !VerQueryValue( (void *) VersionBuffer.c_str(), (char *) sRes.c_str(),
|
||||
(void **) &str, &len ) || len < 1)
|
||||
break;
|
||||
|
||||
sOut = RString( str, len-1 );
|
||||
} while(0);
|
||||
|
||||
/* Get the size and date. */
|
||||
struct stat st;
|
||||
if( stat( sFile, &st ) != -1 )
|
||||
{
|
||||
struct tm t;
|
||||
gmtime_r( &st.st_mtime, &t );
|
||||
if( !sOut.empty() )
|
||||
sOut += " ";
|
||||
sOut += ssprintf( "[%ib, %02i-%02i-%04i]", st.st_size, t.tm_mon+1, t.tm_mday, t.tm_year+1900 );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RString FindSystemFile( RString sFile )
|
||||
{
|
||||
char szWindowsPath[MAX_PATH];
|
||||
GetWindowsDirectory( szWindowsPath, MAX_PATH );
|
||||
|
||||
const char *szPaths[] =
|
||||
{
|
||||
"/system32/",
|
||||
"/system32/drivers/",
|
||||
"/system/",
|
||||
"/system/drivers/",
|
||||
"/",
|
||||
NULL
|
||||
};
|
||||
|
||||
for( int i = 0; szPaths[i]; ++i )
|
||||
{
|
||||
RString sPath = ssprintf( "%s%s%s", szWindowsPath, szPaths[i], sFile.c_str() );
|
||||
struct stat buf;
|
||||
if( !stat(sPath, &buf) )
|
||||
return sPath;
|
||||
}
|
||||
|
||||
return RString();
|
||||
}
|
||||
|
||||
/* Get the full path of the process running in iProcessID. On error, false is
|
||||
* returned and an error message is placed in sName. */
|
||||
bool GetProcessFileName( uint32_t iProcessID, RString &sName )
|
||||
{
|
||||
/* This method works in everything except for NT4, and only uses kernel32.lib functions. */
|
||||
do {
|
||||
HANDLE hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, iProcessID );
|
||||
if( hSnap == NULL )
|
||||
{
|
||||
sName = werr_ssprintf( GetLastError(), "OpenProcess" );
|
||||
break;
|
||||
}
|
||||
|
||||
MODULEENTRY32 me;
|
||||
ZERO( me );
|
||||
me.dwSize = sizeof(MODULEENTRY32);
|
||||
bool bRet = !!Module32First( hSnap, &me );
|
||||
CloseHandle( hSnap );
|
||||
|
||||
if( bRet )
|
||||
{
|
||||
sName = me.szExePath;
|
||||
return true;
|
||||
}
|
||||
|
||||
sName = werr_ssprintf( GetLastError(), "Module32First" );
|
||||
} while(0);
|
||||
|
||||
/* This method only works in NT/2K/XP. */
|
||||
do {
|
||||
static HINSTANCE hPSApi = NULL;
|
||||
typedef DWORD (WINAPI* pfnGetModuleFileNameEx)(HANDLE,HMODULE,LPSTR,DWORD);
|
||||
static pfnGetModuleFileNameEx pGetModuleFileNameEx = NULL;
|
||||
static bool bTried = false;
|
||||
|
||||
if( !bTried )
|
||||
{
|
||||
bTried = true;
|
||||
|
||||
hPSApi = LoadLibrary("psapi.dll");
|
||||
if( hPSApi == NULL )
|
||||
{
|
||||
sName = werr_ssprintf( GetLastError(), "LoadLibrary" );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
pGetModuleFileNameEx = (pfnGetModuleFileNameEx) GetProcAddress( hPSApi, "GetModuleFileNameExA" );
|
||||
if( pGetModuleFileNameEx == NULL )
|
||||
{
|
||||
sName = werr_ssprintf( GetLastError(), "GetProcAddress" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( pGetModuleFileNameEx != NULL )
|
||||
{
|
||||
HANDLE hProc = OpenProcess( PROCESS_VM_READ|PROCESS_QUERY_INFORMATION, NULL, iProcessID );
|
||||
if( hProc == NULL )
|
||||
{
|
||||
sName = werr_ssprintf( GetLastError(), "OpenProcess" );
|
||||
break;
|
||||
}
|
||||
|
||||
char buf[1024];
|
||||
int iRet = pGetModuleFileNameEx( hProc, NULL, buf, 1024 );
|
||||
CloseHandle( hProc );
|
||||
|
||||
if( iRet )
|
||||
{
|
||||
buf[iRet] = 0;
|
||||
sName = buf;
|
||||
return true;
|
||||
}
|
||||
|
||||
sName = werr_ssprintf( GetLastError(), "GetModuleFileNameEx" );
|
||||
}
|
||||
} while(0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,35 @@
|
||||
/* Windows-specific file helpers. */
|
||||
|
||||
#ifndef GET_FILE_INFORMATION_H
|
||||
#define GET_FILE_INFORMATION_H
|
||||
|
||||
bool GetFileVersion( RString fsFile, RString &sOut );
|
||||
RString FindSystemFile( RString sFile );
|
||||
bool GetProcessFileName( uint32_t iProcessID, RString &sName );
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,86 @@
|
||||
#include "global.h"
|
||||
#include "GotoURL.h"
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
/* This is called from the crash handler; don't use RegistryAccess, since it's
|
||||
* not crash-conditions safe. */
|
||||
static LONG GetRegKey( HKEY key, RString subkey, LPTSTR retdata )
|
||||
{
|
||||
HKEY hKey;
|
||||
LONG iRet = RegOpenKeyEx( key, subkey, 0, KEY_QUERY_VALUE, &hKey );
|
||||
|
||||
if( iRet != ERROR_SUCCESS )
|
||||
return iRet;
|
||||
|
||||
long iDataSize = MAX_PATH;
|
||||
char data[MAX_PATH];
|
||||
RegQueryValue( hKey, "emulation", data, &iDataSize );
|
||||
strcpy( retdata, data );
|
||||
RegCloseKey( hKey );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
bool GotoURL( RString sUrl )
|
||||
{
|
||||
// First try ShellExecute()
|
||||
int iRet = (int) ShellExecute( NULL, "open", sUrl, NULL, NULL, SW_SHOWDEFAULT );
|
||||
|
||||
// If it failed, get the .htm regkey and lookup the program
|
||||
if( iRet > 32 )
|
||||
return true;
|
||||
|
||||
char key[2*MAX_PATH];
|
||||
if( GetRegKey(HKEY_CLASSES_ROOT, ".htm", key) != ERROR_SUCCESS )
|
||||
return false;
|
||||
|
||||
strcpy( key, "\\shell\\open\\command" );
|
||||
|
||||
if( GetRegKey(HKEY_CLASSES_ROOT, key, key) != ERROR_SUCCESS )
|
||||
return false;
|
||||
|
||||
char *szPos = strstr( key, "\"%1\"" );
|
||||
if( szPos == NULL )
|
||||
{
|
||||
// No quotes found. Check for %1 without quotes
|
||||
szPos = strstr( key, "%1" );
|
||||
if( szPos == NULL )
|
||||
szPos = key+lstrlen(key)-1; // No parameter.
|
||||
else
|
||||
*szPos = '\0'; // Remove the parameter
|
||||
}
|
||||
else
|
||||
*szPos = '\0'; // Remove the parameter
|
||||
|
||||
strcat( szPos, " " );
|
||||
strcat( szPos, sUrl );
|
||||
|
||||
return WinExec( key, SW_SHOWDEFAULT ) > 32;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2002-2004 Chris Danford
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,33 @@
|
||||
/* Open URLs in a browser. */
|
||||
|
||||
#ifndef GOTO_URL_H
|
||||
#define GOTO_URL_H
|
||||
|
||||
bool GotoURL( RString sUrl );
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2002-2004 Chris Danford
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,545 @@
|
||||
#include "global.h"
|
||||
#include "GraphicsWindow.h"
|
||||
#include "ProductInfo.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageDisplay.h"
|
||||
#include "DisplayResolutions.h"
|
||||
#include "arch/ArchHooks/ArchHooks.h"
|
||||
#include "archutils/Win32/AppInstance.h"
|
||||
#include "archutils/Win32/Crash.h"
|
||||
#include "archutils/Win32/ErrorStrings.h"
|
||||
#include "archutils/Win32/WindowIcon.h"
|
||||
#include "archutils/Win32/GetFileInformation.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
static const RString g_sClassName = PRODUCT_ID;
|
||||
|
||||
static HWND g_hWndMain;
|
||||
static HDC g_HDC;
|
||||
static VideoModeParams g_CurrentParams;
|
||||
static bool g_bResolutionChanged = false;
|
||||
static bool g_bHasFocus = true;
|
||||
static HICON g_hIcon = NULL;
|
||||
static bool m_bWideWindowClass;
|
||||
static bool g_bD3D = false;
|
||||
|
||||
/* If we're fullscreen, this is the mode we set. */
|
||||
static DEVMODE g_FullScreenDevMode;
|
||||
static bool g_bRecreatingVideoMode = false;
|
||||
|
||||
static UINT g_iQueryCancelAutoPlayMessage = 0;
|
||||
|
||||
static RString GetNewWindow()
|
||||
{
|
||||
HWND h = GetForegroundWindow();
|
||||
if( h == NULL )
|
||||
return "(NULL)";
|
||||
|
||||
DWORD iProcessID;
|
||||
GetWindowThreadProcessId( h, &iProcessID );
|
||||
|
||||
RString sName;
|
||||
GetProcessFileName( iProcessID, sName );
|
||||
|
||||
sName = Basename(sName);
|
||||
|
||||
return sName;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK GraphicsWindow_WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
CHECKPOINT_M( ssprintf("%p, %u, %08x, %08x", hWnd, msg, wParam, lParam) );
|
||||
|
||||
/* Suppress autorun. */
|
||||
if( msg == g_iQueryCancelAutoPlayMessage )
|
||||
return true;
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
case WM_ACTIVATE:
|
||||
{
|
||||
const bool bInactive = (LOWORD(wParam) == WA_INACTIVE);
|
||||
const bool bMinimized = (HIWORD(wParam) != 0);
|
||||
const bool bHadFocus = g_bHasFocus;
|
||||
g_bHasFocus = !bInactive && !bMinimized;
|
||||
LOG->Trace( "WM_ACTIVATE (%i, %i): %s", bInactive, bMinimized, g_bHasFocus? "has focus":"doesn't have focus" );
|
||||
if( !g_bHasFocus )
|
||||
{
|
||||
RString sName = GetNewWindow();
|
||||
static set<RString> sLostFocusTo;
|
||||
sLostFocusTo.insert( sName );
|
||||
RString sStr;
|
||||
for( set<RString>::const_iterator it = sLostFocusTo.begin(); it != sLostFocusTo.end(); ++it )
|
||||
sStr += (sStr.size()?", ":"") + *it;
|
||||
|
||||
LOG->MapLog( "LOST_FOCUS", "Lost focus to: %s", sStr.c_str() );
|
||||
}
|
||||
|
||||
if( !g_bD3D && !g_CurrentParams.windowed && !g_bRecreatingVideoMode )
|
||||
{
|
||||
/* In OpenGL (not D3D), it's our job to unset and reset the full-screen video mode
|
||||
* when we focus changes, and to hide and show the window. Hiding is done in WM_KILLFOCUS,
|
||||
* because that's where most other apps seem to do it. */
|
||||
if( g_bHasFocus && !bHadFocus )
|
||||
{
|
||||
ChangeDisplaySettings( &g_FullScreenDevMode, CDS_FULLSCREEN );
|
||||
ShowWindow( g_hWndMain, SW_SHOWNORMAL );
|
||||
}
|
||||
else if( !g_bHasFocus && bHadFocus )
|
||||
{
|
||||
ChangeDisplaySettings( NULL, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
case WM_KILLFOCUS:
|
||||
if( !g_bD3D && !g_CurrentParams.windowed && !g_bRecreatingVideoMode )
|
||||
ShowWindow( g_hWndMain, SW_SHOWMINNOACTIVE );
|
||||
break;
|
||||
|
||||
/* Is there any reason we should care what size the user resizes the window to? */
|
||||
// case WM_GETMINMAXINFO:
|
||||
|
||||
case WM_SETCURSOR:
|
||||
if( !g_CurrentParams.windowed )
|
||||
{
|
||||
SetCursor( NULL );
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SYSCOMMAND:
|
||||
switch( wParam&0xFFF0 )
|
||||
{
|
||||
case SC_MONITORPOWER:
|
||||
case SC_SCREENSAVE:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_PAINT:
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
BeginPaint( hWnd, &ps );
|
||||
EndPaint( hWnd, &ps );
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_KEYDOWN:
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_SYSKEYUP:
|
||||
/* We handle all input ourself, via DirectInput. */
|
||||
return 0;
|
||||
|
||||
case WM_CLOSE:
|
||||
LOG->Trace("WM_CLOSE: shutting down");
|
||||
ArchHooks::SetUserQuit();
|
||||
return 0;
|
||||
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
{
|
||||
/* If we're fullscreen and don't have focus, our window is hidden, so GetClientRect
|
||||
* isn't meaningful. */
|
||||
if( !g_CurrentParams.windowed && !g_bHasFocus )
|
||||
break;
|
||||
|
||||
RECT rect;
|
||||
GetClientRect( hWnd, &rect );
|
||||
|
||||
int iWidth = rect.right - rect.left;
|
||||
int iHeight = rect.bottom - rect.top;
|
||||
if( g_CurrentParams.width != iWidth || g_CurrentParams.height != iHeight )
|
||||
{
|
||||
g_CurrentParams.width = iWidth;
|
||||
g_CurrentParams.height = iHeight;
|
||||
g_bResolutionChanged = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CHECKPOINT_M( ssprintf("%p, %u, %08x, %08x", hWnd, msg, wParam, lParam) );
|
||||
|
||||
if( m_bWideWindowClass )
|
||||
return DefWindowProcW( hWnd, msg, wParam, lParam );
|
||||
else
|
||||
return DefWindowProcA( hWnd, msg, wParam, lParam );
|
||||
}
|
||||
|
||||
static void AdjustVideoModeParams( VideoModeParams &p )
|
||||
{
|
||||
DEVMODE dm;
|
||||
ZERO( dm );
|
||||
dm.dmSize = sizeof(dm);
|
||||
if( !EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm) )
|
||||
{
|
||||
p.rate = 60;
|
||||
LOG->Warn( "%s", werr_ssprintf(GetLastError(), "EnumDisplaySettings failed").c_str() );
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* On a nForce 2 IGP on Windows 98, dm.dmDisplayFrequency sometimes
|
||||
* (but not always) is 0.
|
||||
*
|
||||
* MSDN: When you call the EnumDisplaySettings function, the
|
||||
* dmDisplayFrequency member may return with the value 0 or 1.
|
||||
* These values represent the display hardware's default refresh rate.
|
||||
* This default rate is typically set by switches on a display card or
|
||||
* computer motherboard, or by a configuration program that does not
|
||||
* use Win32 display functions such as ChangeDisplaySettings.
|
||||
*/
|
||||
if( !(dm.dmFields & DM_DISPLAYFREQUENCY) ||
|
||||
dm.dmDisplayFrequency == 0 ||
|
||||
dm.dmDisplayFrequency == 1 )
|
||||
{
|
||||
p.rate = 60;
|
||||
LOG->Warn( "EnumDisplaySettings doesn't know what the refresh rate is. %d %d %d", dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel );
|
||||
}
|
||||
else
|
||||
{
|
||||
p.rate = dm.dmDisplayFrequency;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the display mode to the given size, bit depth and refresh. The refresh
|
||||
* setting may be ignored. */
|
||||
RString GraphicsWindow::SetScreenMode( const VideoModeParams &p )
|
||||
{
|
||||
if( p.windowed )
|
||||
{
|
||||
/* We're going windowed. If we were previously fullscreen, reset. */
|
||||
ChangeDisplaySettings( NULL, 0 );
|
||||
|
||||
return RString();
|
||||
}
|
||||
|
||||
DEVMODE DevMode;
|
||||
ZERO( DevMode );
|
||||
DevMode.dmSize = sizeof(DEVMODE);
|
||||
DevMode.dmPelsWidth = p.width;
|
||||
DevMode.dmPelsHeight = p.height;
|
||||
DevMode.dmBitsPerPel = p.bpp;
|
||||
DevMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
|
||||
|
||||
if( p.rate != REFRESH_DEFAULT )
|
||||
{
|
||||
DevMode.dmDisplayFrequency = p.rate;
|
||||
DevMode.dmFields |= DM_DISPLAYFREQUENCY;
|
||||
}
|
||||
ChangeDisplaySettings( NULL, 0 );
|
||||
|
||||
int ret = ChangeDisplaySettings( &DevMode, CDS_FULLSCREEN );
|
||||
if( ret != DISP_CHANGE_SUCCESSFUL && (DevMode.dmFields & DM_DISPLAYFREQUENCY) )
|
||||
{
|
||||
DevMode.dmFields &= ~DM_DISPLAYFREQUENCY;
|
||||
ret = ChangeDisplaySettings( &DevMode, CDS_FULLSCREEN );
|
||||
}
|
||||
|
||||
/* XXX: append error */
|
||||
if( ret != DISP_CHANGE_SUCCESSFUL )
|
||||
return "Couldn't set screen mode";
|
||||
|
||||
g_FullScreenDevMode = DevMode;
|
||||
return RString();
|
||||
}
|
||||
|
||||
static int GetWindowStyle( bool bWindowed )
|
||||
{
|
||||
if( bWindowed )
|
||||
return WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
||||
else
|
||||
return WS_POPUP;
|
||||
}
|
||||
|
||||
/* Set the final window size, set the window text and icon, and then unhide the
|
||||
* window. */
|
||||
void GraphicsWindow::CreateGraphicsWindow( const VideoModeParams &p, bool bForceRecreateWindow )
|
||||
{
|
||||
g_CurrentParams = p;
|
||||
|
||||
// Adjust g_CurrentParams to reflect the actual display settings.
|
||||
AdjustVideoModeParams( g_CurrentParams );
|
||||
|
||||
if( g_hWndMain == NULL || bForceRecreateWindow )
|
||||
{
|
||||
int iWindowStyle = GetWindowStyle( p.windowed );
|
||||
|
||||
AppInstance inst;
|
||||
HWND hWnd = CreateWindow( g_sClassName, "app", iWindowStyle,
|
||||
0, 0, 0, 0, NULL, NULL, inst, NULL );
|
||||
if( hWnd == NULL )
|
||||
RageException::Throw( "%s", werr_ssprintf( GetLastError(), "CreateWindow" ).c_str() );
|
||||
|
||||
/* If an old window exists, transfer focus to the new window before deleting
|
||||
* it, or some other window may temporarily get focus, which can cause it
|
||||
* to be resized. */
|
||||
if( g_hWndMain != NULL )
|
||||
{
|
||||
/* While we change to the new window, don't do ChangeDisplaySettings in WM_ACTIVATE. */
|
||||
g_bRecreatingVideoMode = true;
|
||||
SetForegroundWindow( hWnd );
|
||||
g_bRecreatingVideoMode = false;
|
||||
|
||||
GraphicsWindow::DestroyGraphicsWindow();
|
||||
}
|
||||
|
||||
g_hWndMain = hWnd;
|
||||
CrashHandler::SetForegroundWindow( g_hWndMain );
|
||||
g_HDC = GetDC( g_hWndMain );
|
||||
}
|
||||
|
||||
/* Update the window title. */
|
||||
do
|
||||
{
|
||||
if( m_bWideWindowClass )
|
||||
{
|
||||
if( SetWindowText( g_hWndMain, ConvertUTF8ToACP(p.sWindowTitle).c_str() ) )
|
||||
break;
|
||||
}
|
||||
|
||||
SetWindowTextA( g_hWndMain, ConvertUTF8ToACP(p.sWindowTitle) );
|
||||
} while(0);
|
||||
|
||||
/* Update the window icon. */
|
||||
if( g_hIcon != NULL )
|
||||
{
|
||||
SetClassLong( g_hWndMain, GCL_HICON, (LONG) LoadIcon(NULL,IDI_APPLICATION) );
|
||||
DestroyIcon( g_hIcon );
|
||||
g_hIcon = NULL;
|
||||
}
|
||||
g_hIcon = IconFromFile( p.sIconFile );
|
||||
if( g_hIcon != NULL )
|
||||
SetClassLong( g_hWndMain, GCL_HICON, (LONG) g_hIcon );
|
||||
|
||||
/* The window style may change as a result of switching to or from fullscreen;
|
||||
* apply it. Don't change the WS_VISIBLE bit. */
|
||||
int iWindowStyle = GetWindowStyle( p.windowed );
|
||||
if( GetWindowLong( g_hWndMain, GWL_STYLE ) & WS_VISIBLE )
|
||||
iWindowStyle |= WS_VISIBLE;
|
||||
SetWindowLong( g_hWndMain, GWL_STYLE, iWindowStyle );
|
||||
|
||||
RECT WindowRect;
|
||||
SetRect( &WindowRect, 0, 0, p.width, p.height );
|
||||
AdjustWindowRect( &WindowRect, iWindowStyle, FALSE );
|
||||
|
||||
//LOG->Warn( "w = %d, h = %d", p.width, p.height );
|
||||
|
||||
const int iWidth = WindowRect.right - WindowRect.left;
|
||||
const int iHeight = WindowRect.bottom - WindowRect.top;
|
||||
|
||||
/* If windowed, center the window. */
|
||||
int x = 0, y = 0;
|
||||
if( p.windowed )
|
||||
{
|
||||
x = GetSystemMetrics(SM_CXSCREEN)/2-iWidth/2;
|
||||
y = GetSystemMetrics(SM_CYSCREEN)/2-iHeight/2;
|
||||
}
|
||||
|
||||
/* Move and resize the window. SWP_FRAMECHANGED causes the above SetWindowLong
|
||||
* to take effect. */
|
||||
if( !SetWindowPos( g_hWndMain, HWND_NOTOPMOST, x, y, iWidth, iHeight, SWP_FRAMECHANGED|SWP_SHOWWINDOW ) )
|
||||
LOG->Warn( "%s", werr_ssprintf( GetLastError(), "SetWindowPos" ).c_str() );
|
||||
|
||||
SetForegroundWindow( g_hWndMain );
|
||||
|
||||
/* Pump messages quickly, to make sure the window is completely set up.
|
||||
* If we don't do this, then starting up in a D3D fullscreen window may
|
||||
* cause all other windows on the system to be resized. */
|
||||
MSG msg;
|
||||
while( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
|
||||
{
|
||||
GetMessage( &msg, NULL, 0, 0 );
|
||||
DispatchMessage( &msg );
|
||||
}
|
||||
}
|
||||
|
||||
/* Shut down the window, but don't reset the video mode. */
|
||||
void GraphicsWindow::DestroyGraphicsWindow()
|
||||
{
|
||||
if( g_HDC != NULL )
|
||||
{
|
||||
ReleaseDC( g_hWndMain, g_HDC );
|
||||
g_HDC = NULL;
|
||||
}
|
||||
|
||||
CHECKPOINT;
|
||||
|
||||
if( g_hWndMain != NULL )
|
||||
{
|
||||
DestroyWindow( g_hWndMain );
|
||||
g_hWndMain = NULL;
|
||||
CrashHandler::SetForegroundWindow( g_hWndMain );
|
||||
}
|
||||
|
||||
CHECKPOINT;
|
||||
|
||||
if( g_hIcon != NULL )
|
||||
{
|
||||
DestroyIcon( g_hIcon );
|
||||
g_hIcon = NULL;
|
||||
}
|
||||
|
||||
CHECKPOINT;
|
||||
|
||||
MSG msg;
|
||||
while( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
|
||||
{
|
||||
CHECKPOINT;
|
||||
GetMessage( &msg, NULL, 0, 0 );
|
||||
CHECKPOINT;
|
||||
DispatchMessage( &msg );
|
||||
}
|
||||
|
||||
CHECKPOINT;
|
||||
}
|
||||
|
||||
void GraphicsWindow::Initialize( bool bD3D )
|
||||
{
|
||||
/* A few things need to be handled differently for D3D. */
|
||||
g_bD3D = bD3D;
|
||||
|
||||
AppInstance inst;
|
||||
do
|
||||
{
|
||||
const wstring wsClassName = RStringToWstring( g_sClassName );
|
||||
WNDCLASSW WindowClassW =
|
||||
{
|
||||
CS_OWNDC | CS_BYTEALIGNCLIENT,
|
||||
GraphicsWindow_WndProc,
|
||||
0, /* cbClsExtra */
|
||||
0, /* cbWndExtra */
|
||||
inst, /* hInstance */
|
||||
NULL, /* set icon later */
|
||||
LoadCursor( NULL, IDC_ARROW ), /* default cursor */
|
||||
NULL, /* hbrBackground */
|
||||
NULL, /* lpszMenuName */
|
||||
wsClassName.c_str() /* lpszClassName */
|
||||
};
|
||||
|
||||
m_bWideWindowClass = true;
|
||||
if( RegisterClassW( &WindowClassW ) )
|
||||
break;
|
||||
|
||||
WNDCLASS WindowClassA =
|
||||
{
|
||||
CS_OWNDC | CS_BYTEALIGNCLIENT,
|
||||
GraphicsWindow_WndProc,
|
||||
0, /* cbClsExtra */
|
||||
0, /* cbWndExtra */
|
||||
inst, /* hInstance */
|
||||
NULL, /* set icon later */
|
||||
LoadCursor( NULL, IDC_ARROW ), /* default cursor */
|
||||
NULL, /* hbrBackground */
|
||||
NULL, /* lpszMenuName */
|
||||
g_sClassName /* lpszClassName */
|
||||
};
|
||||
|
||||
m_bWideWindowClass = false;
|
||||
if( !RegisterClassA( &WindowClassA ) )
|
||||
RageException::Throw( "%s", werr_ssprintf( GetLastError(), "RegisterClass" ).c_str() );
|
||||
} while(0);
|
||||
|
||||
g_iQueryCancelAutoPlayMessage = RegisterWindowMessage( "QueryCancelAutoPlay" );
|
||||
}
|
||||
|
||||
void GraphicsWindow::Shutdown()
|
||||
{
|
||||
DestroyGraphicsWindow();
|
||||
|
||||
/*
|
||||
* Return to the desktop resolution, if needed.
|
||||
*
|
||||
* It'd be nice to not do this: Windows will do it when we quit, and if we're
|
||||
* shutting down OpenGL to try D3D, this will cause extra mode switches. However,
|
||||
* we need to do this before displaying dialogs.
|
||||
*/
|
||||
ChangeDisplaySettings( NULL, 0 );
|
||||
|
||||
AppInstance inst;
|
||||
UnregisterClass( g_sClassName, inst );
|
||||
}
|
||||
|
||||
HDC GraphicsWindow::GetHDC()
|
||||
{
|
||||
ASSERT( g_HDC != NULL );
|
||||
return g_HDC;
|
||||
}
|
||||
|
||||
const VideoModeParams &GraphicsWindow::GetParams()
|
||||
{
|
||||
return g_CurrentParams;
|
||||
}
|
||||
|
||||
void GraphicsWindow::Update()
|
||||
{
|
||||
MSG msg;
|
||||
while( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
|
||||
{
|
||||
GetMessage( &msg, NULL, 0, 0 );
|
||||
DispatchMessage( &msg );
|
||||
}
|
||||
|
||||
HOOKS->SetHasFocus( g_bHasFocus );
|
||||
|
||||
if( g_bResolutionChanged && DISPLAY != NULL )
|
||||
{
|
||||
//LOG->Warn( "Changing resolution" );
|
||||
|
||||
/* Let DISPLAY know that our resolution has changed. (Note that ResolutionChanged()
|
||||
* can come back here, so reset g_bResolutionChanged first.) */
|
||||
g_bResolutionChanged = false;
|
||||
DISPLAY->ResolutionChanged();
|
||||
}
|
||||
}
|
||||
|
||||
HWND GraphicsWindow::GetHwnd()
|
||||
{
|
||||
return g_hWndMain;
|
||||
}
|
||||
|
||||
void GraphicsWindow::GetDisplayResolutions( DisplayResolutions &out )
|
||||
{
|
||||
DEVMODE dm;
|
||||
ZERO( dm );
|
||||
dm.dmSize = sizeof(dm);
|
||||
int i=0;
|
||||
while(EnumDisplaySettings(NULL, i++, &dm))
|
||||
{
|
||||
if(ChangeDisplaySettings(&dm, CDS_TEST)==DISP_CHANGE_SUCCESSFUL)
|
||||
{
|
||||
DisplayResolution res = { dm.dmPelsWidth, dm.dmPelsHeight };
|
||||
out.insert( res );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (c) 2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,61 @@
|
||||
/* GraphicsWindow - Sets up a window for OpenGL/D3D. */
|
||||
|
||||
#ifndef GRAPHICS_WINDOW_H
|
||||
#define GRAPHICS_WINDOW_H
|
||||
|
||||
#include <windows.h>
|
||||
#include "DisplayResolutions.h"
|
||||
class VideoModeParams;
|
||||
class DisplayResolution;
|
||||
|
||||
namespace GraphicsWindow
|
||||
{
|
||||
/* Set up, and create a hidden window. This only needs to be called once. */
|
||||
void Initialize( bool bD3D );
|
||||
|
||||
/* Shut down completely. */
|
||||
void Shutdown();
|
||||
|
||||
/* Set the display mode. p will not be second-guessed, except to try disabling
|
||||
* the refresh rate setting. */
|
||||
RString SetScreenMode( const VideoModeParams &p );
|
||||
|
||||
/* Create the window. This also updates VideoModeParams (returned by GetParams). */
|
||||
void CreateGraphicsWindow( const VideoModeParams &p, bool bForceRecreateWindow = false );
|
||||
void DestroyGraphicsWindow();
|
||||
|
||||
void GetDisplayResolutions( DisplayResolutions &out );
|
||||
|
||||
const VideoModeParams &GetParams();
|
||||
HDC GetHDC();
|
||||
void Update();
|
||||
|
||||
HWND GetHwnd();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,92 @@
|
||||
#include "global.h"
|
||||
#include "MessageWindow.h"
|
||||
#include "RageUtil.h"
|
||||
#include "AppInstance.h"
|
||||
#include "archutils/Win32/ErrorStrings.h"
|
||||
|
||||
MessageWindow::MessageWindow( const RString &sClassName )
|
||||
{
|
||||
AppInstance inst;
|
||||
WNDCLASS WindowClass =
|
||||
{
|
||||
CS_OWNDC | CS_BYTEALIGNCLIENT,
|
||||
WndProc,
|
||||
0, /* cbClsExtra */
|
||||
0, /* cbWndExtra */
|
||||
inst, /* hInstance */
|
||||
NULL, /* set icon later */
|
||||
LoadCursor( NULL, IDC_ARROW ), /* default cursor */
|
||||
NULL, /* hbrBackground */
|
||||
NULL, /* lpszMenuName */
|
||||
sClassName /* lpszClassName */
|
||||
};
|
||||
|
||||
if( !RegisterClassA(&WindowClass) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS )
|
||||
RageException::Throw( "%s", werr_ssprintf( GetLastError(), "RegisterClass" ).c_str() );
|
||||
|
||||
// XXX: on 2k/XP, use HWND_MESSAGE as parent
|
||||
m_hWnd = CreateWindow( sClassName, sClassName, WS_DISABLED, 0, 0, 0, 0, NULL, NULL, inst, NULL );
|
||||
ASSERT( m_hWnd != NULL );
|
||||
|
||||
SetProp( m_hWnd, "MessageWindow", this );
|
||||
}
|
||||
|
||||
MessageWindow::~MessageWindow()
|
||||
{
|
||||
RemoveProp( m_hWnd, "MessageWindow" );
|
||||
DestroyWindow( m_hWnd );
|
||||
}
|
||||
|
||||
void MessageWindow::Run()
|
||||
{
|
||||
/* Process messages until StopRunning is called. */
|
||||
m_bDone = false;
|
||||
while( !m_bDone )
|
||||
{
|
||||
MSG msg;
|
||||
int iRet = GetMessage( &msg, m_hWnd, 0, 0 );
|
||||
ASSERT( iRet != -1 );
|
||||
if( iRet == 0 )
|
||||
break;
|
||||
DispatchMessage( &msg );
|
||||
}
|
||||
}
|
||||
|
||||
void MessageWindow::StopRunning()
|
||||
{
|
||||
m_bDone = true;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK MessageWindow::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
MessageWindow *pThis = (MessageWindow *) GetProp( hWnd, "MessageWindow" );
|
||||
if( pThis != NULL && pThis->HandleMessage(msg, wParam, lParam) )
|
||||
return 0;
|
||||
|
||||
return DefWindowProc( hWnd, msg, wParam, lParam );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2006 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,54 @@
|
||||
/* MessageWindow - simplifies creation of windows that exist only to receive messages. */
|
||||
|
||||
#ifndef MESSAGE_WINDOW_H
|
||||
#define MESSAGE_WINDOW_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
class MessageWindow
|
||||
{
|
||||
public:
|
||||
MessageWindow( const RString &sClassName );
|
||||
~MessageWindow();
|
||||
|
||||
/* Run the message loop until WM_QUIT is received. */
|
||||
void Run();
|
||||
|
||||
HWND GetHwnd() { return m_hWnd; }
|
||||
|
||||
protected:
|
||||
virtual bool HandleMessage( UINT msg, WPARAM wParam, LPARAM lParam ) { return false; }
|
||||
void StopRunning();
|
||||
|
||||
private:
|
||||
static LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
|
||||
HWND m_hWnd;
|
||||
bool m_bDone;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2006 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,243 @@
|
||||
#include "global.h"
|
||||
#include "RegistryAccess.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
#include "archutils/Win32/ErrorStrings.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/* Given "HKEY_LOCAL_MACHINE\hardware\foo", return "hardware\foo", and place
|
||||
* the HKEY_LOCAL_MACHINE constant in key. */
|
||||
static bool GetRegKeyType( const RString &sIn, RString &sOut, HKEY &key )
|
||||
{
|
||||
size_t iBackslash = sIn.find( '\\' );
|
||||
if( iBackslash == sIn.npos )
|
||||
{
|
||||
LOG->Warn( "Invalid registry key: \"%s\" ", sIn.c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
RString sType = sIn.substr( 0, iBackslash );
|
||||
|
||||
if( !sType.CompareNoCase( "HKEY_CLASSES_ROOT" ) ) key = HKEY_CLASSES_ROOT;
|
||||
else if( !sType.CompareNoCase( "HKEY_CURRENT_CONFIG" ) ) key = HKEY_CURRENT_CONFIG;
|
||||
else if( !sType.CompareNoCase( "HKEY_CURRENT_USER" ) ) key = HKEY_CURRENT_USER;
|
||||
else if( !sType.CompareNoCase( "HKEY_LOCAL_MACHINE" ) ) key = HKEY_LOCAL_MACHINE;
|
||||
else if( !sType.CompareNoCase( "HKEY_USERS" ) ) key = HKEY_USERS;
|
||||
else
|
||||
{
|
||||
LOG->Warn( "Invalid registry key: \"%s\" ", sIn.c_str() );
|
||||
return false;
|
||||
}
|
||||
|
||||
sOut = sIn.substr( iBackslash+1 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Given a full key, eg. "HKEY_LOCAL_MACHINE\hardware\foo", open it and return it.
|
||||
* On error, return NULL. */
|
||||
enum RegKeyMode { READ, WRITE };
|
||||
static HKEY OpenRegKey( const RString &sKey, RegKeyMode mode, bool bWarnOnError = true )
|
||||
{
|
||||
RString sSubkey;
|
||||
HKEY hType;
|
||||
if( !GetRegKeyType(sKey, sSubkey, hType) )
|
||||
return NULL;
|
||||
|
||||
HKEY hRetKey;
|
||||
LONG retval = RegOpenKeyEx( hType, sSubkey, 0, (mode==READ) ? KEY_READ:KEY_WRITE, &hRetKey );
|
||||
if ( retval != ERROR_SUCCESS )
|
||||
{
|
||||
if( bWarnOnError )
|
||||
LOG->Warn( werr_ssprintf(retval, "RegOpenKeyEx(%x,%s) error", hType, sSubkey.c_str()) );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hRetKey;
|
||||
}
|
||||
|
||||
bool RegistryAccess::GetRegValue( const RString &sKey, const RString &sName, RString &sVal )
|
||||
{
|
||||
HKEY hKey = OpenRegKey( sKey, READ );
|
||||
if( hKey == NULL )
|
||||
return false;
|
||||
|
||||
char sBuffer[MAX_PATH];
|
||||
DWORD iSize = sizeof(sBuffer);
|
||||
DWORD iType;
|
||||
LONG iRet = RegQueryValueEx( hKey, sName, NULL, &iType, (LPBYTE)sBuffer, &iSize );
|
||||
RegCloseKey( hKey );
|
||||
if( iRet != ERROR_SUCCESS )
|
||||
return false;
|
||||
|
||||
/* Actually, CStrings are 8-bit clean, so we can accept any type of data. Remove
|
||||
* this if that becomes useful. */
|
||||
if( iType != REG_SZ && iType != REG_MULTI_SZ && iType != REG_EXPAND_SZ && iType != REG_BINARY )
|
||||
return false; /* type mismatch */
|
||||
|
||||
if( iSize && (iType == REG_SZ || iType == REG_MULTI_SZ || iType == REG_EXPAND_SZ) )
|
||||
--iSize; /* remove nul terminator */
|
||||
|
||||
sVal = RString( sBuffer, iSize );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RegistryAccess::GetRegValue( const RString &sKey, const RString &sName, int &iVal, bool bWarnOnError )
|
||||
{
|
||||
HKEY hKey = OpenRegKey( sKey, READ, bWarnOnError );
|
||||
if( hKey == NULL )
|
||||
return false;
|
||||
|
||||
DWORD iValue;
|
||||
DWORD iSize = sizeof(iValue);
|
||||
DWORD iType;
|
||||
LONG iRet = RegQueryValueEx( hKey, sName, NULL, &iType, (LPBYTE) &iValue, &iSize );
|
||||
RegCloseKey( hKey );
|
||||
if( iRet != ERROR_SUCCESS )
|
||||
return false;
|
||||
|
||||
if( iType != REG_DWORD )
|
||||
return false; /* type mismatch */
|
||||
|
||||
iVal = iValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RegistryAccess::GetRegValue( const RString &sKey, const RString &sName, bool &bVal )
|
||||
{
|
||||
int iVal;
|
||||
bool b = GetRegValue( sKey, sName, iVal );
|
||||
bVal = !!iVal;
|
||||
return b;
|
||||
}
|
||||
|
||||
bool RegistryAccess::GetRegSubKeys( const RString &sKey, vector<RString> &lst, const RString ®ex, bool bReturnPathToo )
|
||||
{
|
||||
HKEY hKey = OpenRegKey( sKey, READ );
|
||||
if( hKey == NULL )
|
||||
return false;
|
||||
|
||||
Regex re(regex);
|
||||
|
||||
bool bError = false;
|
||||
for( int index = 0; ; ++index )
|
||||
{
|
||||
FILETIME ft;
|
||||
char szBuffer[MAX_PATH];
|
||||
DWORD iSize = sizeof(szBuffer);
|
||||
LONG iRet = RegEnumKeyEx( hKey, index, szBuffer, &iSize, NULL, NULL, NULL, &ft);
|
||||
if( iRet == ERROR_NO_MORE_ITEMS )
|
||||
break;
|
||||
|
||||
if( iRet != ERROR_SUCCESS )
|
||||
{
|
||||
LOG->Warn( werr_ssprintf(iRet, "GetRegSubKeys(%p,%i) error", hKey, index) );
|
||||
bError = true;
|
||||
break;
|
||||
}
|
||||
|
||||
RString sStr( szBuffer, iSize );
|
||||
|
||||
if( re.Compare(sStr) )
|
||||
{
|
||||
if( bReturnPathToo )
|
||||
sStr = sKey + "\\" + sStr;
|
||||
lst.push_back( sStr );
|
||||
}
|
||||
}
|
||||
|
||||
RegCloseKey( hKey );
|
||||
|
||||
return !bError;
|
||||
}
|
||||
|
||||
bool RegistryAccess::SetRegValue( const RString &sKey, const RString &sName, const RString &sVal )
|
||||
{
|
||||
HKEY hKey = OpenRegKey( sKey, WRITE );
|
||||
if( hKey == NULL )
|
||||
return false;
|
||||
|
||||
bool bSuccess = true;
|
||||
TCHAR sz[255];
|
||||
|
||||
if( sVal.size() > 254 )
|
||||
return false;
|
||||
|
||||
strcpy( sz, sVal.c_str() );
|
||||
|
||||
LONG lResult = ::RegSetValueEx(hKey, LPCTSTR(sName), 0, REG_SZ, (LPBYTE)sz, strlen(sz) + 1);
|
||||
if( lResult != ERROR_SUCCESS )
|
||||
bSuccess = false;
|
||||
|
||||
::RegCloseKey(hKey);
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
bool RegistryAccess::SetRegValue( const RString &sKey, const RString &sName, bool bVal )
|
||||
{
|
||||
HKEY hKey = OpenRegKey( sKey, WRITE );
|
||||
if( hKey == NULL )
|
||||
return false;
|
||||
|
||||
bool bSuccess = true;
|
||||
|
||||
if (::RegSetValueEx(hKey, LPCTSTR(sName), 0,
|
||||
REG_BINARY, (LPBYTE)&bVal, sizeof(bVal))
|
||||
!= ERROR_SUCCESS)
|
||||
bSuccess = false;
|
||||
|
||||
::RegCloseKey(hKey);
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
bool RegistryAccess::CreateKey( const RString &sKey )
|
||||
{
|
||||
RString sSubkey;
|
||||
HKEY hType;
|
||||
if( !GetRegKeyType(sKey, sSubkey, hType) )
|
||||
return NULL;
|
||||
|
||||
HKEY hKey;
|
||||
DWORD dwDisposition = 0;
|
||||
if( ::RegCreateKeyEx(
|
||||
hType,
|
||||
sSubkey,
|
||||
0,
|
||||
NULL,
|
||||
REG_OPTION_NON_VOLATILE,
|
||||
KEY_ALL_ACCESS,
|
||||
NULL,
|
||||
&hKey,
|
||||
&dwDisposition ) != ERROR_SUCCESS )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
::RegCloseKey(hKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,46 @@
|
||||
/* RegistryAccess - Windows registry helpers */
|
||||
|
||||
#ifndef REGISTRY_ACCESS_H
|
||||
#define REGISTRY_ACCESS_H
|
||||
|
||||
namespace RegistryAccess
|
||||
{
|
||||
bool GetRegValue( const RString &sKey, const RString &sName, RString &val );
|
||||
bool GetRegValue( const RString &sKey, const RString &sName, int &val, bool bWarnOnError = true );
|
||||
bool GetRegValue( const RString &sKey, const RString &sName, bool &val );
|
||||
|
||||
bool GetRegSubKeys( const RString &sKey, vector<RString> &asList, const RString &sRegex = ".*", bool bReturnPathToo = true );
|
||||
|
||||
bool SetRegValue( const RString &sKey, const RString &sName, const RString &val );
|
||||
bool SetRegValue( const RString &sKey, const RString &sName, int val );
|
||||
bool SetRegValue( const RString &sKey, const RString &sName, bool val );
|
||||
|
||||
bool CreateKey( const RString &sKey );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "global.h"
|
||||
#include "RestartProgram.h"
|
||||
#include <windows.h>
|
||||
|
||||
void Win32RestartProgram()
|
||||
{
|
||||
TCHAR szFullAppPath[MAX_PATH];
|
||||
GetModuleFileName(NULL, szFullAppPath, MAX_PATH);
|
||||
|
||||
// Relaunch
|
||||
PROCESS_INFORMATION pi;
|
||||
STARTUPINFO si;
|
||||
ZeroMemory( &si, sizeof(si) );
|
||||
CreateProcess(
|
||||
NULL, // pointer to name of executable module
|
||||
szFullAppPath, // pointer to command line string
|
||||
NULL, // process security attributes
|
||||
NULL, // thread security attributes
|
||||
false, // handle inheritance flag
|
||||
0, // creation flags
|
||||
NULL, // pointer to new environment block
|
||||
NULL, // pointer to current directory name
|
||||
&si, // pointer to STARTUPINFO
|
||||
&pi // pointer to PROCESS_INFORMATION
|
||||
);
|
||||
|
||||
ExitProcess( 0 );
|
||||
|
||||
/* not reached */
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2002-2004 Chris Danford
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef RESTART_PROGRAM_H
|
||||
#define RESTART_PROGRAM_H
|
||||
|
||||
void Win32RestartProgram();
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2002-2004 Chris Danford
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "global.h"
|
||||
#include "SpecialDirs.h"
|
||||
#include <shlobj.h>
|
||||
|
||||
static RString GetSpecialFolderPath( int csidl )
|
||||
{
|
||||
RString sDir;
|
||||
TCHAR szDir[MAX_PATH] = "";
|
||||
BOOL bResult = SHGetSpecialFolderPath( NULL, szDir, csidl, FALSE );
|
||||
ASSERT( bResult );
|
||||
sDir = szDir;
|
||||
sDir += "/";
|
||||
return sDir;
|
||||
}
|
||||
|
||||
RString SpecialDirs::GetAppDataDir()
|
||||
{
|
||||
return GetSpecialFolderPath( CSIDL_APPDATA );
|
||||
}
|
||||
|
||||
RString SpecialDirs::GetDesktopDir()
|
||||
{
|
||||
return GetSpecialFolderPath( CSIDL_DESKTOP );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (c) 2002-2004 Chris Danford
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef SpecialDirs_H
|
||||
#define SpecialDirs_H
|
||||
|
||||
namespace SpecialDirs
|
||||
{
|
||||
RString GetAppDataDir();
|
||||
RString GetDesktopDir();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2002-2004 Chris Danford
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 105 KiB |
@@ -0,0 +1,246 @@
|
||||
#include "global.h"
|
||||
#include "USB.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
#include "archutils/Win32/ErrorStrings.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma comment(lib, "archutils/Win32/ddk/setupapi.lib")
|
||||
#pragma comment(lib, "archutils/Win32/ddk/hid.lib")
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include "archutils/Win32/ddk/setupapi.h"
|
||||
/* Quiet header warning: */
|
||||
#include "archutils/Win32/ddk/hidsdi.h"
|
||||
}
|
||||
|
||||
static RString GetUSBDevicePath( int iNum )
|
||||
{
|
||||
GUID guid;
|
||||
HidD_GetHidGuid( &guid );
|
||||
|
||||
HDEVINFO DeviceInfo = SetupDiGetClassDevs( &guid, NULL, NULL, (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE) );
|
||||
|
||||
SP_DEVICE_INTERFACE_DATA DeviceInterface;
|
||||
DeviceInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
|
||||
if( !SetupDiEnumDeviceInterfaces (DeviceInfo,
|
||||
NULL, &guid, iNum, &DeviceInterface) )
|
||||
{
|
||||
SetupDiDestroyDeviceInfoList( DeviceInfo );
|
||||
return RString();
|
||||
}
|
||||
|
||||
unsigned long iSize;
|
||||
SetupDiGetDeviceInterfaceDetail( DeviceInfo, &DeviceInterface, NULL, 0, &iSize, 0 );
|
||||
|
||||
PSP_INTERFACE_DEVICE_DETAIL_DATA DeviceDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc( iSize );
|
||||
DeviceDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
|
||||
|
||||
RString sRet;
|
||||
if( SetupDiGetDeviceInterfaceDetail(DeviceInfo, &DeviceInterface,
|
||||
DeviceDetail, iSize, &iSize, NULL) )
|
||||
sRet = DeviceDetail->DevicePath;
|
||||
free( DeviceDetail );
|
||||
|
||||
SetupDiDestroyDeviceInfoList( DeviceInfo );
|
||||
return sRet;
|
||||
}
|
||||
|
||||
bool USBDevice::Open( int iVID, int iPID, int iBlockSize, int iNum, void (*pfnInit)(HANDLE) )
|
||||
{
|
||||
DWORD iIndex = 0;
|
||||
|
||||
RString path;
|
||||
while( (path = GetUSBDevicePath(iIndex++)) != "" )
|
||||
{
|
||||
HANDLE h = CreateFile( path, GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
|
||||
|
||||
if( h == INVALID_HANDLE_VALUE )
|
||||
continue;
|
||||
|
||||
HIDD_ATTRIBUTES attr;
|
||||
if( !HidD_GetAttributes(h, &attr) )
|
||||
{
|
||||
CloseHandle( h );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( (iVID != -1 && attr.VendorID != iVID) ||
|
||||
(iPID != -1 && attr.ProductID != iPID) )
|
||||
{
|
||||
CloseHandle( h );
|
||||
continue; /* This isn't it. */
|
||||
}
|
||||
|
||||
/* The VID and PID match. */
|
||||
if( iNum-- > 0 )
|
||||
{
|
||||
CloseHandle( h );
|
||||
continue;
|
||||
}
|
||||
|
||||
if( pfnInit )
|
||||
pfnInit( h );
|
||||
CloseHandle(h);
|
||||
|
||||
m_IO.Open( path, iBlockSize );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool USBDevice::IsOpen() const
|
||||
{
|
||||
return m_IO.IsOpen();
|
||||
}
|
||||
|
||||
|
||||
int USBDevice::GetPadEvent()
|
||||
{
|
||||
if( !IsOpen() )
|
||||
return -1;
|
||||
|
||||
long iBuf;
|
||||
if( m_IO.read(&iBuf) <= 0 )
|
||||
return -1;
|
||||
|
||||
return iBuf;
|
||||
}
|
||||
|
||||
WindowsFileIO::WindowsFileIO()
|
||||
{
|
||||
ZeroMemory( &m_Overlapped, sizeof(m_Overlapped) );
|
||||
m_Handle = INVALID_HANDLE_VALUE;
|
||||
m_pBuffer = NULL;
|
||||
}
|
||||
|
||||
WindowsFileIO::~WindowsFileIO()
|
||||
{
|
||||
if( m_Handle != INVALID_HANDLE_VALUE )
|
||||
CloseHandle( m_Handle );
|
||||
delete[] m_pBuffer;
|
||||
}
|
||||
|
||||
bool WindowsFileIO::Open( RString path, int iBlockSize )
|
||||
{
|
||||
LOG->Trace( "WindowsFileIO::open(%s)", path.c_str() );
|
||||
m_iBlockSize = iBlockSize;
|
||||
|
||||
if( m_pBuffer )
|
||||
delete[] m_pBuffer;
|
||||
m_pBuffer = new char[m_iBlockSize];
|
||||
|
||||
if( m_Handle != INVALID_HANDLE_VALUE )
|
||||
CloseHandle( m_Handle );
|
||||
|
||||
m_Handle = CreateFile( path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );
|
||||
|
||||
if( m_Handle == INVALID_HANDLE_VALUE )
|
||||
return false;
|
||||
|
||||
queue_read();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WindowsFileIO::queue_read()
|
||||
{
|
||||
/* Request feedback from the device. */
|
||||
unsigned long iRead;
|
||||
ReadFile( m_Handle, m_pBuffer, m_iBlockSize, &iRead, &m_Overlapped );
|
||||
}
|
||||
|
||||
int WindowsFileIO::finish_read( void *p )
|
||||
{
|
||||
LOG->Trace( "this %p, %p", this, p );
|
||||
/* We do; get the result. It'll go into the original m_pBuffer
|
||||
* we supplied on the original call; that's why m_pBuffer is a
|
||||
* member instead of a local. */
|
||||
unsigned long iCnt;
|
||||
int iRet = GetOverlappedResult( m_Handle, &m_Overlapped, &iCnt, FALSE );
|
||||
|
||||
if( iRet == 0 && (GetLastError() == ERROR_IO_PENDING || GetLastError() == ERROR_IO_INCOMPLETE) )
|
||||
return -1;
|
||||
|
||||
queue_read();
|
||||
|
||||
if( iRet == 0 )
|
||||
{
|
||||
LOG->Warn( werr_ssprintf(GetLastError(), "Error reading USB device") );
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy( p, m_pBuffer, iCnt );
|
||||
return iCnt;
|
||||
}
|
||||
|
||||
int WindowsFileIO::read( void *p )
|
||||
{
|
||||
LOG->Trace( "WindowsFileIO::read()" );
|
||||
|
||||
/* See if we have a response for our request (which we may
|
||||
* have made on a previous call): */
|
||||
if( WaitForSingleObjectEx(m_Handle, 0, TRUE) == WAIT_TIMEOUT )
|
||||
return -1;
|
||||
|
||||
return finish_read(p);
|
||||
}
|
||||
|
||||
int WindowsFileIO::read_several(const vector<WindowsFileIO *> &sources, void *p, int &actual, float timeout)
|
||||
{
|
||||
HANDLE *Handles = new HANDLE[sources.size()];
|
||||
for( unsigned i = 0; i < sources.size(); ++i )
|
||||
Handles[i] = sources[i]->m_Handle;
|
||||
|
||||
int ret = WaitForMultipleObjectsEx( sources.size(), Handles, false, int(timeout * 1000), true);
|
||||
delete[] Handles;
|
||||
|
||||
if( ret == -1 )
|
||||
{
|
||||
LOG->Trace( werr_ssprintf(GetLastError(), "WaitForMultipleObjectsEx failed") );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( ret >= int(WAIT_OBJECT_0) && ret < int(WAIT_OBJECT_0+sources.size()) )
|
||||
{
|
||||
actual = ret - WAIT_OBJECT_0;
|
||||
return sources[actual]->finish_read(p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool WindowsFileIO::IsOpen() const
|
||||
{
|
||||
return m_Handle != INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2002-2005 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,68 @@
|
||||
/* WindowsFileIO - Windows device I/O. */
|
||||
|
||||
#ifndef WIN32_USB_H
|
||||
#define WIN32_USB_H
|
||||
|
||||
#include <vector>
|
||||
#include <windows.h>
|
||||
|
||||
class WindowsFileIO
|
||||
{
|
||||
public:
|
||||
WindowsFileIO();
|
||||
~WindowsFileIO();
|
||||
bool Open( RString sPath, int iBlockSize );
|
||||
bool IsOpen() const;
|
||||
|
||||
/* Nonblocking read. size must always be the same. Returns the number of bytes
|
||||
* read, or 0. */
|
||||
int read( void *p );
|
||||
static int read_several( const vector<WindowsFileIO *> &sources, void *p, int &actual, float timeout );
|
||||
|
||||
private:
|
||||
void queue_read();
|
||||
int finish_read( void *p );
|
||||
|
||||
HANDLE m_Handle;
|
||||
OVERLAPPED m_Overlapped;
|
||||
char *m_pBuffer;
|
||||
int m_iBlockSize;
|
||||
};
|
||||
|
||||
/* WindowsFileIO - Windows USB I/O */
|
||||
class USBDevice
|
||||
{
|
||||
public:
|
||||
int GetPadEvent();
|
||||
bool Open( int iVID, int iPID, int iBlockSize, int iNum, void (*pfnInit)(HANDLE) );
|
||||
bool IsOpen() const;
|
||||
|
||||
WindowsFileIO m_IO;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2002-2005 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,147 @@
|
||||
#include "global.h"
|
||||
#include "VideoDriverInfo.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageLog.h"
|
||||
#include "RegistryAccess.h"
|
||||
#include <windows.h>
|
||||
|
||||
// this will not work on 95 and NT because of EnumDisplayDevices
|
||||
RString GetPrimaryVideoName()
|
||||
{
|
||||
typedef BOOL (WINAPI* pfnEnumDisplayDevices)(PVOID,DWORD,PDISPLAY_DEVICE,DWORD);
|
||||
pfnEnumDisplayDevices EnumDisplayDevices;
|
||||
HINSTANCE hInstUser32;
|
||||
|
||||
hInstUser32 = LoadLibrary( "User32.DLL" );
|
||||
if( !hInstUser32 )
|
||||
return RString();
|
||||
|
||||
// VC6 don't have a stub to static link with, so link dynamically.
|
||||
EnumDisplayDevices = (pfnEnumDisplayDevices)GetProcAddress(hInstUser32,"EnumDisplayDevicesA");
|
||||
if( EnumDisplayDevices == NULL )
|
||||
{
|
||||
FreeLibrary(hInstUser32);
|
||||
return RString();
|
||||
}
|
||||
|
||||
RString sPrimaryDeviceName;
|
||||
for( int i=0; true; ++i )
|
||||
{
|
||||
DISPLAY_DEVICE dd;
|
||||
ZERO( dd );
|
||||
dd.cb = sizeof(dd);
|
||||
if( !EnumDisplayDevices(NULL, i, &dd, 0) )
|
||||
break;
|
||||
if( dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE )
|
||||
{
|
||||
sPrimaryDeviceName = (char*)dd.DeviceString;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FreeLibrary( hInstUser32 );
|
||||
TrimRight( sPrimaryDeviceName );
|
||||
return sPrimaryDeviceName;
|
||||
}
|
||||
|
||||
RString GetPrimaryVideoDriverName()
|
||||
{
|
||||
RString sPrimaryDeviceName = GetPrimaryVideoName();
|
||||
if( sPrimaryDeviceName != "" )
|
||||
return sPrimaryDeviceName;
|
||||
|
||||
LOG->Warn("GetPrimaryVideoName failed; renderer selection may be wrong");
|
||||
|
||||
VideoDriverInfo info;
|
||||
if( !GetVideoDriverInfo(0, info) )
|
||||
return "(ERROR DETECTING VIDEO DRIVER)";
|
||||
|
||||
return info.sDescription;
|
||||
}
|
||||
|
||||
/* Get info for the given card number. Return false if that card doesn't exist. */
|
||||
bool GetVideoDriverInfo( int iCardno, VideoDriverInfo &info )
|
||||
{
|
||||
OSVERSIONINFO version;
|
||||
version.dwOSVersionInfoSize = sizeof(version);
|
||||
GetVersionEx(&version);
|
||||
const bool bIsWin9x = version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS;
|
||||
|
||||
static bool bInitialized=false;
|
||||
static vector<RString> lst;
|
||||
if( !bInitialized )
|
||||
{
|
||||
bInitialized = true;
|
||||
|
||||
const RString sTopKey = bIsWin9x?
|
||||
"HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Class\\Display":
|
||||
"HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E968-E325-11CE-BFC1-08002BE10318}";
|
||||
|
||||
RegistryAccess::GetRegSubKeys( sTopKey, lst, ".*", false );
|
||||
|
||||
for( int i=lst.size()-1; i >= 0; --i )
|
||||
{
|
||||
/* Remove all keys that aren't four characters long ("Properties"). */
|
||||
if( lst[i].size() != 4 )
|
||||
{
|
||||
lst.erase( lst.begin()+i );
|
||||
continue;
|
||||
}
|
||||
|
||||
lst[i] = sTopKey + "\\" + lst[i];
|
||||
}
|
||||
|
||||
if( lst.size() == 0 )
|
||||
{
|
||||
LOG->Warn("GetVideoDriverInfo error: no cards found!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
while( iCardno < (int)lst.size() )
|
||||
{
|
||||
const RString sKey = lst[iCardno];
|
||||
|
||||
if( !RegistryAccess::GetRegValue( sKey, "DriverDesc", info.sDescription ) )
|
||||
{
|
||||
/* Remove this one from the list and ignore it, */
|
||||
lst.erase( lst.begin()+iCardno );
|
||||
continue;
|
||||
}
|
||||
TrimRight( info.sDescription );
|
||||
|
||||
RegistryAccess::GetRegValue( sKey, "DriverDate", info.sDate );
|
||||
RegistryAccess::GetRegValue( sKey, "MatchingDeviceId", info.sDeviceID );
|
||||
RegistryAccess::GetRegValue( sKey, "ProviderName", info.sProvider );
|
||||
RegistryAccess::GetRegValue( sKey, bIsWin9x? "Ver":"DriverVersion", info.sVersion );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2002-2004 Chris Danford, Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,44 @@
|
||||
/* GetVideoDriverInfo - Get information about Win32 video drivers. */
|
||||
|
||||
#ifndef VIDEO_DRIVER_INFO_H
|
||||
#define VIDEO_DRIVER_INFO_H
|
||||
|
||||
struct VideoDriverInfo
|
||||
{
|
||||
RString sProvider;
|
||||
RString sDescription;
|
||||
RString sVersion;
|
||||
RString sDate;
|
||||
RString sDeviceID;
|
||||
};
|
||||
|
||||
RString GetPrimaryVideoName();
|
||||
bool GetVideoDriverInfo( int iCardno, VideoDriverInfo &info );
|
||||
RString GetPrimaryVideoDriverName();
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2002-2004 Chris Danford, Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,130 @@
|
||||
#include "global.h"
|
||||
#include "archutils/Win32/WindowIcon.h"
|
||||
#include "RageLog.h"
|
||||
#include "RageUtil.h"
|
||||
#include "RageSurface.h"
|
||||
#include "RageSurfaceUtils.h"
|
||||
#include "RageSurface_Load.h"
|
||||
#include "archutils/Win32/ErrorStrings.h"
|
||||
|
||||
#include <wingdi.h>
|
||||
|
||||
HICON IconFromSurface( const RageSurface *pSrcImg )
|
||||
{
|
||||
RageSurface *pImg;
|
||||
|
||||
{
|
||||
/* Round the width up to a multiple of 8, convert to 32-bit BGR, and reduce
|
||||
* to one-bit alpha. */
|
||||
int iWidth = pSrcImg->w;
|
||||
iWidth = (iWidth+7) & ~7;
|
||||
|
||||
pImg = CreateSurface( iWidth, pSrcImg->h, 32,
|
||||
0x00FF0000,
|
||||
0x0000FF00,
|
||||
0x000000FF,
|
||||
0xFF000000 );
|
||||
RageSurfaceUtils::Blit( pSrcImg, pImg );
|
||||
}
|
||||
|
||||
RageSurfaceUtils::FlipVertically( pImg );
|
||||
|
||||
int iSize = sizeof(BITMAPINFOHEADER);
|
||||
int iSizeImage = 0;
|
||||
iSizeImage += pImg->h * pImg->pitch; /* image */
|
||||
iSizeImage += (pImg->h * pImg->w) / 8; /* mask */
|
||||
|
||||
BITMAPINFOHEADER *pBitmap = (BITMAPINFOHEADER *) malloc( iSize + iSizeImage );
|
||||
memset( pBitmap, 0, iSize + iSizeImage );
|
||||
|
||||
pBitmap->biSize = sizeof(BITMAPINFOHEADER);
|
||||
pBitmap->biWidth = pImg->w;
|
||||
pBitmap->biHeight = pImg->h * 2;
|
||||
pBitmap->biPlanes = 1;
|
||||
pBitmap->biBitCount = 32;
|
||||
pBitmap->biCompression = BI_RGB;
|
||||
pBitmap->biSizeImage = pImg->h * pImg->pitch;
|
||||
|
||||
uint8_t *pImage = ((uint8_t *) pBitmap) + iSize;
|
||||
uint8_t *pMask = pImage + pImg->h * pImg->pitch;
|
||||
|
||||
memcpy( pImage, pImg->pixels, pImg->h * pImg->pitch );
|
||||
|
||||
int iMaskPitch = pImg->w/8;
|
||||
for( int y = 0; y < pImg->h; ++y )
|
||||
{
|
||||
int bit = 0x80;
|
||||
uint32_t *pRow = (uint32_t *) (pImage + y*pImg->pitch);
|
||||
uint8_t *pMaskRow = pMask + y*iMaskPitch;
|
||||
for( int x = 0; x < pImg->w; ++x )
|
||||
{
|
||||
if( !(pRow[x] & pImg->fmt.Mask[3]) )
|
||||
{
|
||||
/* Transparent; set this mask bit. */
|
||||
*pMaskRow |= bit;
|
||||
pRow[x] = 0;
|
||||
}
|
||||
|
||||
bit >>= 1;
|
||||
if( bit == 0 )
|
||||
{
|
||||
bit = 0x80;
|
||||
++pMaskRow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HICON icon = CreateIconFromResourceEx( (BYTE *) pBitmap, iSize + iSizeImage, TRUE, 0x00030000, pImg->w, pImg->h, LR_DEFAULTCOLOR );
|
||||
|
||||
delete pImg;
|
||||
pImg = NULL;
|
||||
free( pBitmap );
|
||||
|
||||
if( icon == NULL )
|
||||
{
|
||||
LOG->Trace( "%s", werr_ssprintf( GetLastError(), "CreateIconFromResourceEx" ).c_str() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
HICON IconFromFile( const RString &sIconFile )
|
||||
{
|
||||
RString sError;
|
||||
RageSurface *pImg = RageSurfaceUtils::LoadFile( sIconFile, sError );
|
||||
if( pImg == NULL )
|
||||
{
|
||||
LOG->Warn( "Couldn't open icon \"%s\": %s", sIconFile.c_str(), sError.c_str() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HICON icon = IconFromSurface( pImg );
|
||||
delete pImg;
|
||||
return icon;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,36 @@
|
||||
/* Win32 helper - load an HICON */
|
||||
#ifndef WINDOW_ICON_H
|
||||
#define WINDOW_ICON_H
|
||||
|
||||
#include <windows.h>
|
||||
struct RageSurface;
|
||||
|
||||
HICON IconFromSurface( const RageSurface *pImg );
|
||||
HICON IconFromFile( const RString &sIconFile );
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,56 @@
|
||||
#include "global.h"
|
||||
#include "WindowsDialogBox.h"
|
||||
|
||||
WindowsDialogBox::WindowsDialogBox()
|
||||
{
|
||||
m_hWnd = NULL;
|
||||
}
|
||||
|
||||
void WindowsDialogBox::Run( int iDialog )
|
||||
{
|
||||
char szFullAppPath[MAX_PATH];
|
||||
GetModuleFileName( NULL, szFullAppPath, MAX_PATH );
|
||||
HINSTANCE hHandle = LoadLibrary( szFullAppPath );
|
||||
|
||||
DialogBoxParam( hHandle, MAKEINTRESOURCE(iDialog), NULL, DlgProc, (LPARAM) this );
|
||||
}
|
||||
|
||||
BOOL APIENTRY WindowsDialogBox::DlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
if( msg == WM_INITDIALOG )
|
||||
SetProp( hDlg, "WindowsDialogBox", (HANDLE) lParam );
|
||||
|
||||
WindowsDialogBox *pThis = (WindowsDialogBox *) GetProp( hDlg, "WindowsDialogBox" );
|
||||
if( pThis == NULL )
|
||||
return FALSE;
|
||||
|
||||
if( pThis->m_hWnd == NULL )
|
||||
pThis->m_hWnd = hDlg;
|
||||
|
||||
return pThis->HandleMessage( msg, wParam, lParam );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2006 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,50 @@
|
||||
/* WindowsDialogBox - Simplifies the creation of modal Windows dialog boxes. */
|
||||
|
||||
#ifndef WINDOWS_DIALOG_BOX_H
|
||||
#define WINDOWS_DIALOG_BOX_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
class WindowsDialogBox
|
||||
{
|
||||
public:
|
||||
WindowsDialogBox();
|
||||
virtual ~WindowsDialogBox() { }
|
||||
void Run( int iDialog );
|
||||
|
||||
HWND GetHwnd() { return m_hWnd; }
|
||||
|
||||
protected:
|
||||
virtual BOOL HandleMessage( UINT msg, WPARAM wParam, LPARAM lParam ) { return false; }
|
||||
|
||||
private:
|
||||
static BOOL APIENTRY DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
HWND m_hWnd;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2006 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,60 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by WindowsResources.rc
|
||||
//
|
||||
#define IDC_CRASH_SAVE 16
|
||||
#define IDD_ERROR_DIALOG 111
|
||||
#define IDD_LOADING_DIALOG 116
|
||||
#define BITMAP_LOADING 117
|
||||
#define IDD_OK 118
|
||||
#define IDD_DISASM_CRASH 120
|
||||
#define BITMAP_CRASH 121
|
||||
#define IDD_REPORT_CRASH 121
|
||||
#define BITMAP_ERROR 129
|
||||
#define IDC_SHOCKWAVEFLASH1 1000
|
||||
#define IDC_BUTTON_RESTART 1001
|
||||
#define IDM_TOGGLEFULLSCREEN 1002
|
||||
#define IDC_BUTTON_REPORT 1002
|
||||
#define IDM_CHANGERESOLUTION 1003
|
||||
#define IDC_BUTTON_VIEW_LOG 1003
|
||||
#define IDM_CHANGEDETAIL 1003
|
||||
#define IDM_CHANGEDISPLAYCOLOR 1004
|
||||
#define IDM_CHANGETEXTURECOLOR 1005
|
||||
#define IDC_EDIT_ERROR 1005
|
||||
#define IDM_TOGGLESTATISTICS 1006
|
||||
#define IDI_ICON 1007
|
||||
#define IDC_CURSOR 1008
|
||||
#define IDC_STATIC_MESSAGE1 1010
|
||||
#define IDC_STATIC_MESSAGE2 1011
|
||||
#define IDC_BUTTON_CLOSE 1011
|
||||
#define IDC_VIEW_LOG 1012
|
||||
#define IDC_STATIC_MESSAGE3 1013
|
||||
#define IDC_PROGRESS1 1014
|
||||
#define IDC_PROGRESS 1014
|
||||
#define IDC_HUSH 1016
|
||||
#define IDC_MESSAGE 1017
|
||||
#define IDC_CHECK2 1019
|
||||
#define IDC_SPLASH 1020
|
||||
#define IDC_STATIC_HEADER_TEXT 1021
|
||||
#define IDC_STATIC_ICON 1022
|
||||
#define IDC_BUTTON_AUTO_REPORT 1026
|
||||
#define IDC_RESULT_ID 1028
|
||||
#define IDC_MAIN_TEXT 1029
|
||||
#define IDC_ASMBOX 1133
|
||||
#define IDC_REGDUMP 1283
|
||||
#define IDC_STATIC_BOMBREASON 1284
|
||||
#define IDC_STATIC_BOMBREASON2 1285
|
||||
#define IDC_CALL_STACK 1310
|
||||
#define IDI_ICON1 1311
|
||||
#define IDM_EXIT 40003
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 134
|
||||
#define _APS_NEXT_COMMAND_VALUE 40009
|
||||
#define _APS_NEXT_CONTROL_VALUE 1030
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,229 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "WindowsResources.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Dialog
|
||||
//
|
||||
|
||||
IDD_ERROR_DIALOG DIALOGEX 0, 0, 332, 234
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION
|
||||
CAPTION "Fatal Error"
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x0
|
||||
BEGIN
|
||||
CONTROL "",IDC_STATIC,"Static",SS_WHITERECT,0,0,332,35
|
||||
DEFPUSHBUTTON "Close",IDOK,265,215,60,15
|
||||
EDITTEXT IDC_EDIT_ERROR,5,59,320,151,ES_MULTILINE | ES_READONLY | WS_VSCROLL | NOT WS_TABSTOP
|
||||
PUSHBUTTON "View Log",IDC_BUTTON_VIEW_LOG,8,215,74,15
|
||||
PUSHBUTTON "Report Error",IDC_BUTTON_REPORT,90,215,76,15
|
||||
PUSHBUTTON "Restart Game",IDC_BUTTON_RESTART,175,215,80,15
|
||||
LTEXT "Specific details about the error are shown in the box below:",IDC_STATIC,7,45,319,11
|
||||
LTEXT "Fatal Error",IDC_STATIC_HEADER_TEXT,5,5,249,23
|
||||
ICON IDI_ICON,IDC_STATIC_ICON,296,6,21,20
|
||||
CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,0,34,332,1
|
||||
END
|
||||
|
||||
IDD_LOADING_DIALOG DIALOG 0, 0, 312, 82
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE
|
||||
FONT 8, "MS Sans Serif"
|
||||
BEGIN
|
||||
CTEXT "line1",IDC_STATIC_MESSAGE1,0,41,310,10,SS_NOPREFIX | SS_CENTERIMAGE
|
||||
CTEXT "line2",IDC_STATIC_MESSAGE2,0,54,310,10,SS_NOPREFIX | SS_CENTERIMAGE
|
||||
CTEXT "line3",IDC_STATIC_MESSAGE3,0,65,310,10,SS_NOPREFIX | SS_CENTERIMAGE
|
||||
CONTROL "",IDC_SPLASH,"Static",SS_BITMAP,0,0,310,25
|
||||
END
|
||||
|
||||
IDD_DISASM_CRASH DIALOGEX 0, 0, 332, 114
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x0
|
||||
BEGIN
|
||||
PUSHBUTTON "&View Crash Info",IDC_CRASH_SAVE,40,73,94,15
|
||||
PUSHBUTTON "View &Log",IDC_VIEW_LOG,137,73,63,15
|
||||
PUSHBUTTON "Report the &Error",IDC_BUTTON_REPORT,203,73,89,15
|
||||
PUSHBUTTON "&Restart Game",IDC_BUTTON_RESTART,197,95,78,15
|
||||
PUSHBUTTON "&Close",IDC_BUTTON_CLOSE,278,95,50,15
|
||||
LTEXT "A crash has occurred. Diagnostic information has been saved to a file called ""crashinfo.txt"" in the game program directory.",IDC_STATIC,8,41,312,19
|
||||
CONTROL "",IDC_STATIC,"Static",SS_WHITERECT,0,0,332,35
|
||||
LTEXT "Program Crash",IDC_STATIC_HEADER_TEXT,5,5,249,23
|
||||
ICON IDI_ICON,IDC_STATIC_ICON,296,6,20,20
|
||||
CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,0,34,332,1
|
||||
END
|
||||
|
||||
IDD_OK DIALOGEX 0, 0, 336, 98
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION
|
||||
CAPTION "Prompt"
|
||||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,143,77,50,14
|
||||
CONTROL "&Don't display this message again",IDC_HUSH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,63,181,10
|
||||
EDITTEXT IDC_MESSAGE,7,7,322,55,ES_CENTER | ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | WS_VSCROLL
|
||||
END
|
||||
|
||||
IDD_REPORT_CRASH DIALOGEX 0, 0, 287, 98
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | DS_CENTERMOUSE | WS_POPUP | WS_CAPTION
|
||||
CAPTION "Program Crash"
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x0
|
||||
BEGIN
|
||||
PUSHBUTTON "&Send Error Report",IDC_BUTTON_AUTO_REPORT,132,79,89,15
|
||||
PUSHBUTTON "&View Error Report",IDC_CRASH_SAVE,6,79,86,15
|
||||
CONTROL "",IDC_PROGRESS,"msctls_progress32",NOT WS_VISIBLE | WS_BORDER,132,79,89,15
|
||||
PUSHBUTTON "&Don't Send",IDC_BUTTON_CLOSE,224,79,59,15
|
||||
LTEXT "The program has encountered an error. Click Send Error Report to automatically report the problem and check for updates.",IDC_MAIN_TEXT,13,48,263,18
|
||||
CONTROL "",IDC_STATIC,"Static",SS_WHITERECT,0,0,287,35
|
||||
LTEXT "Program Crash",IDC_STATIC_HEADER_TEXT,5,5,249,23
|
||||
ICON IDI_ICON,IDC_STATIC_ICON,259,6,21,20
|
||||
CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,0,34,287,1
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DESIGNINFO
|
||||
//
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
GUIDELINES DESIGNINFO
|
||||
BEGIN
|
||||
IDD_LOADING_DIALOG, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 305
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 75
|
||||
END
|
||||
|
||||
IDD_DISASM_CRASH, DIALOG
|
||||
BEGIN
|
||||
RIGHTMARGIN, 328
|
||||
VERTGUIDE, 6
|
||||
BOTTOMMARGIN, 110
|
||||
HORZGUIDE, 96
|
||||
END
|
||||
|
||||
IDD_OK, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 329
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 91
|
||||
END
|
||||
|
||||
IDD_REPORT_CRASH, DIALOG
|
||||
BEGIN
|
||||
RIGHTMARGIN, 283
|
||||
VERTGUIDE, 6
|
||||
BOTTOMMARGIN, 94
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"WindowsResources.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_ICON1 ICON "smzip.ico"
|
||||
IDI_ICON ICON "StepMania.ICO"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,1
|
||||
PRODUCTVERSION 1,0,0,1
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "http://www.stepmania.com"
|
||||
VALUE "FileDescription", "StepMania"
|
||||
VALUE "FileVersion", "1, 0, 0, 1"
|
||||
VALUE "InternalName", "StepMania"
|
||||
VALUE "LegalCopyright", "Copyright © 2001-2002"
|
||||
VALUE "OriginalFilename", "StepMania.exe"
|
||||
VALUE "ProductName", " StepMania"
|
||||
VALUE "ProductVersion", "1, 0, 0, 1"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "global.h"
|
||||
#include "arch_setup.h"
|
||||
#ifdef _WINDOWS
|
||||
# include <windows.h>
|
||||
#endif
|
||||
#include "CommandLine.h"
|
||||
|
||||
#if defined(WINDOWS)
|
||||
int main( int argc, char* argv[] );
|
||||
int __stdcall WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, char *pCmdLine, int nCmdShow )
|
||||
{
|
||||
char **argv;
|
||||
int argc = GetWin32CmdLine( argv );
|
||||
|
||||
return main( argc, argv );
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,236 @@
|
||||
#ifndef ARCH_SETUP_WINDOWS_H
|
||||
#define ARCH_SETUP_WINDOWS_H
|
||||
|
||||
#if !defined(XBOX)
|
||||
#define HAVE_FFMPEG
|
||||
#define HAVE_THEORA
|
||||
#endif
|
||||
|
||||
#if !defined(XBOX)
|
||||
#define SUPPORT_OPENGL
|
||||
#endif
|
||||
#define SUPPORT_D3D
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
#define _WINDOWS // This isn't defined under MinGW
|
||||
#define NEED_CSTDLIB_WORKAROUND // Needed for llabs() in MinGW
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
#if _MSC_VER == 1400 // VC8 specific warnings
|
||||
#pragma warning (disable : 4996) // deprecated functions vs "ISO C++ conformant names". (stricmp vs _stricmp)
|
||||
#pragma warning (disable : 4005) // macro redefinitions (ARRAYSIZE)
|
||||
#endif
|
||||
|
||||
#define snprintf _snprintf // Unsure if this goes with __MINGW32__ right now.
|
||||
|
||||
#pragma warning (disable : 4275) // non dll-interface class 'stdext::exception' used as base for dll-interface class 'std::bad_cast', bug in VC <exception> when exceptions disabled
|
||||
#pragma warning (disable : 4201) // nonstandard extension used : nameless struct/union (Windows headers do this)
|
||||
#pragma warning (disable : 4786) // turn off broken debugger warning
|
||||
#pragma warning (disable : 4512) // assignment operator could not be generated (so?)
|
||||
/* "unreachable code". This warning crops up in incorrect places (end of do ... while(0)
|
||||
* blocks, try/catch blocks), and I've never found it to be useful. */
|
||||
#pragma warning (disable : 4702) // assignment operator could not be generated (so?)
|
||||
/* "unreferenced formal parameter"; we *want* that in many cases */
|
||||
#pragma warning (disable : 4100)
|
||||
/* "case 'aaa' is not a valid value for switch of enum 'bbb'
|
||||
* Actually, this is a valid warning, but we do it all over the
|
||||
* place, eg. with ScreenMessages. Those should be fixed, but later. XXX */
|
||||
#pragma warning (disable : 4063)
|
||||
#pragma warning (disable : 4127)
|
||||
#pragma warning (disable : 4786) /* VC6: identifier was truncated to '255' characters in the debug information */
|
||||
#pragma warning (disable : 4505) // removed unferenced local function from integer.cpp & algebra.h
|
||||
#pragma warning (disable : 4244) // converting of data = possible data loss. (This pragma should eventually go away)
|
||||
#pragma warning (disable : 4355) // 'this' : used in base member initializer list
|
||||
|
||||
/* Fix VC breakage. */
|
||||
#define PATH_MAX _MAX_PATH
|
||||
|
||||
/* Disable false deprecation warnings in VC2005. */
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#define _SCL_SECURE_NO_DEPRECATE
|
||||
|
||||
/* Disable false deprecation warnings in VC2008. */
|
||||
#define _CRT_NONSTDC_NO_WARNINGS
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1400 // this is needed in VC8 but breaks VC7
|
||||
#define _HAS_EXCEPTIONS 0
|
||||
#endif
|
||||
|
||||
/* Don't include windows.h everywhere; when we do eventually include it, use these: */
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define VC_EXTRALEAN
|
||||
|
||||
/* Pull in NT-only definitions. Note that we support Win98 and WinME; you can make
|
||||
* NT calls, but be sure to fall back on 9x if they're not supported. */
|
||||
#define _WIN32_WINNT 0x0400
|
||||
#define _WIN32_IE 0x0400
|
||||
|
||||
/* If this isn't defined to 0, VC fails to define things like stat and alloca. */
|
||||
#define __STDC__ 0
|
||||
|
||||
#endif
|
||||
|
||||
#include <direct.h> /* has stuff that should be in unistd.h */
|
||||
#include <wchar.h> /* needs to be included before our fixes below */
|
||||
|
||||
#define lstat stat
|
||||
#define fsync _commit
|
||||
#define isnan _isnan
|
||||
#define isfinite _finite
|
||||
|
||||
/* mkdir is missing the mode arg */
|
||||
#define mkdir(p,m) mkdir(p)
|
||||
|
||||
typedef time_t time_t;
|
||||
struct tm;
|
||||
struct tm *my_localtime_r( const time_t *timep, struct tm *result );
|
||||
#define localtime_r my_localtime_r
|
||||
struct tm *my_gmtime_r( const time_t *timep, struct tm *result );
|
||||
#define gmtime_r my_gmtime_r
|
||||
void my_usleep( unsigned long usec );
|
||||
#define usleep my_usleep
|
||||
|
||||
|
||||
|
||||
/* Missing stdint types: */
|
||||
#if !defined(__MINGW32__) // MinGW headers define these for us
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef int int32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#define INT64_C(i) i##i64
|
||||
#define UINT64_C(i) i##i64
|
||||
static inline int64_t llabs( int64_t i ) { return i >= 0? i: -i; }
|
||||
#endif
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
#define NOMINMAX /* make sure Windows doesn't try to define this */
|
||||
|
||||
/* Windows is missing some basic math functions: */
|
||||
// But MinGW isn't.
|
||||
#if !defined(__MINGW32__)
|
||||
#define NEED_TRUNCF
|
||||
#define NEED_ROUNDF
|
||||
#define NEED_STRTOF
|
||||
#define MISSING_STDINT_H
|
||||
#endif
|
||||
|
||||
// MinGW provides us with this function already
|
||||
#if !defined(__MINGW32__)
|
||||
inline long int lrintf( float f )
|
||||
{
|
||||
int retval;
|
||||
|
||||
_asm fld f;
|
||||
_asm fistp retval;
|
||||
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* For RageLog. */
|
||||
#define HAVE_VERSION_INFO
|
||||
|
||||
/* We implement the crash handler interface (though that interface isn't completely
|
||||
* uniform across platforms yet). */
|
||||
#if !defined(_XBOX) && !defined(SMPACKAGE)
|
||||
#define CRASH_HANDLER
|
||||
#endif
|
||||
|
||||
#define ENDIAN_LITTLE
|
||||
|
||||
#if defined(_XBOX)
|
||||
#if defined(_DEBUG)
|
||||
#define OGG_LIB_DIR "vorbis/xbox/debug/"
|
||||
#else
|
||||
#define OGG_LIB_DIR "vorbis/xbox/release/"
|
||||
#endif
|
||||
#else
|
||||
#define OGG_LIB_DIR "vorbis/win32/"
|
||||
#endif
|
||||
|
||||
#if defined(XBOX)
|
||||
#include "ArchUtils/Xbox/arch_setup.h"
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__GNUC__) // It might be MinGW or Cygwin(?)
|
||||
#include "archutils/Common/gcc_byte_swaps.h"
|
||||
#else // XXX: Should we test for MSVC?
|
||||
#define HAVE_BYTE_SWAPS
|
||||
|
||||
inline uint32_t ArchSwap32( uint32_t n )
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, n
|
||||
xchg al, ah
|
||||
ror eax, 16
|
||||
xchg al, ah
|
||||
mov n, eax
|
||||
};
|
||||
return n;
|
||||
}
|
||||
|
||||
inline uint32_t ArchSwap24( uint32_t n )
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, n
|
||||
xchg al, ah
|
||||
ror eax, 16
|
||||
xchg al, ah
|
||||
ror eax, 8
|
||||
mov n, eax
|
||||
};
|
||||
return n;
|
||||
}
|
||||
|
||||
inline uint16_t ArchSwap16( uint16_t n )
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov ax, n
|
||||
xchg al, ah
|
||||
mov n, ax
|
||||
};
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* (c) 2002-2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "global.h"
|
||||
#include "arch_setup.h"
|
||||
#include "RageThreads.h"
|
||||
#include <time.h>
|
||||
#ifdef _WINDOWS
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
struct tm *my_localtime_r( const time_t *timep, struct tm *result )
|
||||
{
|
||||
static RageMutex mut("my_localtime_r");
|
||||
LockMut(mut);
|
||||
|
||||
*result = *localtime( timep );
|
||||
return result;
|
||||
}
|
||||
|
||||
struct tm *my_gmtime_r( const time_t *timep, struct tm *result )
|
||||
{
|
||||
static RageMutex mut("my_gmtime_r");
|
||||
LockMut(mut);
|
||||
|
||||
*result = *gmtime( timep );
|
||||
return result;
|
||||
}
|
||||
|
||||
void my_usleep( unsigned long usec )
|
||||
{
|
||||
::Sleep( usec/1000 );
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2004 Glenn Maynard
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,413 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 1996 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
HIDSDI.H
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains the PUBLIC definitions for the
|
||||
code that implements the HID dll.
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel & user mode
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#ifndef _HIDSDI_H
|
||||
#define _HIDSDI_H
|
||||
|
||||
#include <pshpack4.h>
|
||||
|
||||
//#include "wtypes.h"
|
||||
|
||||
//#include <windef.h>
|
||||
//#include <win32.h>
|
||||
//#include <basetyps.h>
|
||||
|
||||
typedef LONG NTSTATUS;
|
||||
#include "hidusage.h"
|
||||
#include "hidpi.h"
|
||||
|
||||
typedef struct _HIDD_CONFIGURATION {
|
||||
PVOID cookie;
|
||||
ULONG size;
|
||||
ULONG RingBufferSize;
|
||||
} HIDD_CONFIGURATION, *PHIDD_CONFIGURATION;
|
||||
|
||||
typedef struct _HIDD_ATTRIBUTES {
|
||||
ULONG Size; // = sizeof (struct _HIDD_ATTRIBUTES)
|
||||
|
||||
//
|
||||
// Vendor ids of this hid device
|
||||
//
|
||||
USHORT VendorID;
|
||||
USHORT ProductID;
|
||||
USHORT VersionNumber;
|
||||
|
||||
//
|
||||
// Additional fields will be added to the end of this structure.
|
||||
//
|
||||
} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
|
||||
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetAttributes (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PHIDD_ATTRIBUTES Attributes
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
Fill in the given HIDD_ATTRIBUTES structure with the attributes of the
|
||||
given hid device.
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
void __stdcall
|
||||
HidD_GetHidGuid (
|
||||
OUT LPGUID HidGuid
|
||||
);
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetPreparsedData (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PHIDP_PREPARSED_DATA * PreparsedData
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
Given a handle to a valid Hid Class Device Object, retrieve the preparsed
|
||||
data for the device. This routine will allocate the appropriately
|
||||
sized buffer to hold this preparsed data. It is up to client to call
|
||||
HidP_FreePreparsedData to free the memory allocated to this structure when
|
||||
it is no longer needed.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device that the client obtains using
|
||||
a call to CreateFile on a valid Hid device string name.
|
||||
The string name can be obtained using standard PnP calls.
|
||||
|
||||
PreparsedData An opaque data structure used by other functions in this
|
||||
library to retrieve information about a given device.
|
||||
|
||||
Return Value:
|
||||
TRUE if successful.
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_FreePreparsedData (
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData
|
||||
);
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_FlushQueue (
|
||||
IN HANDLE HidDeviceObject
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
Flush the input queue for the given HID device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device that the client obtains using
|
||||
a call to CreateFile on a valid Hid device string name.
|
||||
The string name can be obtained using standard PnP calls.
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetConfiguration (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PHIDD_CONFIGURATION Configuration,
|
||||
IN ULONG ConfigurationLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
Get the configuration information for this Hid device
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
Configuration A configuration structure. HidD_GetConfiguration MUST
|
||||
be called before the configuration can be modified and
|
||||
set using HidD_SetConfiguration
|
||||
|
||||
ConfigurationLength That is ``sizeof (HIDD_CONFIGURATION)''. Using this
|
||||
parameter, we can later increase the length of the
|
||||
configuration array and not break older apps.
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_SetConfiguration (
|
||||
IN HANDLE HidDeviceObject,
|
||||
IN PHIDD_CONFIGURATION Configuration,
|
||||
IN ULONG ConfigurationLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
Set the configuration information for this Hid device...
|
||||
|
||||
NOTE: HidD_GetConfiguration must be called to retrieve the current
|
||||
configuration information before this information can be modified
|
||||
and set.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
Configuration A configuration structure. HidD_GetConfiguration MUST
|
||||
be called before the configuration can be modified and
|
||||
set using HidD_SetConfiguration
|
||||
|
||||
ConfigurationLength That is ``sizeof (HIDD_CONFIGURATION)''. Using this
|
||||
parameter, we can later increase the length of the
|
||||
configuration array and not break older apps.
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetFeature (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PVOID ReportBuffer,
|
||||
IN ULONG ReportBufferLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
Retrieve a feature report from a HID device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
ReportBuffer The buffer that the feature report should be placed
|
||||
into. The first byte of the buffer should be set to
|
||||
the report ID of the desired report
|
||||
|
||||
ReportBufferLength The size (in bytes) of ReportBuffer. This value
|
||||
should be greater than or equal to the
|
||||
FeatureReportByteLength field as specified in the
|
||||
HIDP_CAPS structure for the device
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_SetFeature (
|
||||
IN HANDLE HidDeviceObject,
|
||||
IN PVOID ReportBuffer,
|
||||
IN ULONG ReportBufferLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
Send a feature report to a HID device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
ReportBuffer The buffer of the feature report to send to the device
|
||||
|
||||
ReportBufferLength The size (in bytes) of ReportBuffer. This value
|
||||
should be greater than or equal to the
|
||||
FeatureReportByteLength field as specified in the
|
||||
HIDP_CAPS structure for the device
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetNumInputBuffers (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PULONG NumberBuffers
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
This function returns the number of input buffers used by the specified
|
||||
file handle to the Hid device. Each file object has a number of buffers
|
||||
associated with it to queue reports read from the device but which have
|
||||
not yet been read by the user-mode app with a handle to that device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
NumberBuffers Number of buffers currently being used for this file
|
||||
handle to the Hid device
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_SetNumInputBuffers (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT ULONG NumberBuffers
|
||||
);
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
This function sets the number of input buffers used by the specified
|
||||
file handle to the Hid device. Each file object has a number of buffers
|
||||
associated with it to queue reports read from the device but which have
|
||||
not yet been read by the user-mode app with a handle to that device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
NumberBuffers New number of buffers to use for this file handle to
|
||||
the Hid device
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetPhysicalDescriptor (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG BufferLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
This function retrieves the raw physical descriptor for the specified
|
||||
Hid device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
Buffer Buffer which on return will contain the physical
|
||||
descriptor if one exists for the specified device
|
||||
handle
|
||||
|
||||
BufferLength Length of buffer (in bytes)
|
||||
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetManufacturerString (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG BufferLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
This function retrieves the manufacturer string from the specified
|
||||
Hid device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
Buffer Buffer which on return will contain the manufacturer
|
||||
string returned from the device. This string is a
|
||||
wide-character string
|
||||
|
||||
BufferLength Length of Buffer (in bytes)
|
||||
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetProductString (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG BufferLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
This function retrieves the product string from the specified
|
||||
Hid device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
Buffer Buffer which on return will contain the product
|
||||
string returned from the device. This string is a
|
||||
wide-character string
|
||||
|
||||
BufferLength Length of Buffer (in bytes)
|
||||
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetIndexedString (
|
||||
IN HANDLE HidDeviceObject,
|
||||
IN ULONG StringIndex,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG BufferLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
This function retrieves a string from the specified Hid device that is
|
||||
specified with a certain string index.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
StringIndex Index of the string to retrieve
|
||||
|
||||
Buffer Buffer which on return will contain the product
|
||||
string returned from the device. This string is a
|
||||
wide-character string
|
||||
|
||||
BufferLength Length of Buffer (in bytes)
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetSerialNumberString (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG BufferLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
This function retrieves the serial number string from the specified
|
||||
Hid device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
Buffer Buffer which on return will contain the serial number
|
||||
string returned from the device. This string is a
|
||||
wide-character string
|
||||
|
||||
BufferLength Length of Buffer (in bytes)
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
|
||||
#include <poppack.h>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 1996, 1997 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
HIDUSAGE.H
|
||||
|
||||
Abstract:
|
||||
|
||||
Public Definitions of HID USAGES.
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel & user mode
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef __HIDUSAGE_H__
|
||||
#define __HIDUSAGE_H__
|
||||
|
||||
//
|
||||
// Usage Pages
|
||||
//
|
||||
|
||||
typedef USHORT USAGE, *PUSAGE;
|
||||
|
||||
#define HID_USAGE_PAGE_GENERIC ((USAGE) 0x01)
|
||||
#define HID_USAGE_PAGE_SIMULATION ((USAGE) 0x02)
|
||||
#define HID_USAGE_PAGE_VR ((USAGE) 0x03)
|
||||
#define HID_USAGE_PAGE_SPORT ((USAGE) 0x04)
|
||||
#define HID_USAGE_PAGE_GAME ((USAGE) 0x05)
|
||||
#define HID_USAGE_PAGE_KEYBOARD ((USAGE) 0x07)
|
||||
#define HID_USAGE_PAGE_LED ((USAGE) 0x08)
|
||||
#define HID_USAGE_PAGE_BUTTON ((USAGE) 0x09)
|
||||
#define HID_USAGE_PAGE_ORDINAL ((USAGE) 0x0A)
|
||||
#define HID_USAGE_PAGE_TELEPHONY ((USAGE) 0x0B)
|
||||
#define HID_USAGE_PAGE_CONSUMER ((USAGE) 0x0C)
|
||||
#define HID_USAGE_PAGE_DIGITIZER ((USAGE) 0x0D)
|
||||
#define HID_USAGE_PAGE_UNICODE ((USAGE) 0x10)
|
||||
#define HID_USAGE_PAGE_ALPHANUMERIC ((USAGE) 0x14)
|
||||
|
||||
|
||||
//
|
||||
// Usages from Generic Desktop Page (0x01)
|
||||
//
|
||||
|
||||
#define HID_USAGE_GENERIC_POINTER ((USAGE) 0x01)
|
||||
#define HID_USAGE_GENERIC_MOUSE ((USAGE) 0x02)
|
||||
#define HID_USAGE_GENERIC_JOYSTICK ((USAGE) 0x04)
|
||||
#define HID_USAGE_GENERIC_GAMEPAD ((USAGE) 0x05)
|
||||
#define HID_USAGE_GENERIC_KEYBOARD ((USAGE) 0x06)
|
||||
#define HID_USAGE_GENERIC_KEYPAD ((USAGE) 0x07)
|
||||
#define HID_USAGE_GENERIC_SYSTEM_CTL ((USAGE) 0x80)
|
||||
|
||||
#define HID_USAGE_GENERIC_X ((USAGE) 0x30)
|
||||
#define HID_USAGE_GENERIC_Y ((USAGE) 0x31)
|
||||
#define HID_USAGE_GENERIC_Z ((USAGE) 0x32)
|
||||
#define HID_USAGE_GENERIC_RX ((USAGE) 0x33)
|
||||
#define HID_USAGE_GENERIC_RY ((USAGE) 0x34)
|
||||
#define HID_USAGE_GENERIC_RZ ((USAGE) 0x35)
|
||||
#define HID_USAGE_GENERIC_SLIDER ((USAGE) 0x36)
|
||||
#define HID_USAGE_GENERIC_DIAL ((USAGE) 0x37)
|
||||
#define HID_USAGE_GENERIC_WHEEL ((USAGE) 0x38)
|
||||
#define HID_USAGE_GENERIC_HATSWITCH ((USAGE) 0x39)
|
||||
#define HID_USAGE_GENERIC_COUNTED_BUFFER ((USAGE) 0x3A)
|
||||
#define HID_USAGE_GENERIC_BYTE_COUNT ((USAGE) 0x3B)
|
||||
#define HID_USAGE_GENERIC_MOTION_WAKEUP ((USAGE) 0x3C)
|
||||
#define HID_USAGE_GENERIC_VX ((USAGE) 0x40)
|
||||
#define HID_USAGE_GENERIC_VY ((USAGE) 0x41)
|
||||
#define HID_USAGE_GENERIC_VZ ((USAGE) 0x42)
|
||||
#define HID_USAGE_GENERIC_VBRX ((USAGE) 0x43)
|
||||
#define HID_USAGE_GENERIC_VBRY ((USAGE) 0x44)
|
||||
#define HID_USAGE_GENERIC_VBRZ ((USAGE) 0x45)
|
||||
#define HID_USAGE_GENERIC_VNO ((USAGE) 0x46)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_POWER ((USAGE) 0x81)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_SLEEP ((USAGE) 0x82)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_WAKE ((USAGE) 0x83)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_CONTEXT_MENU ((USAGE) 0x84)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_MAIN_MENU ((USAGE) 0x85)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_APP_MENU ((USAGE) 0x86)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_HELP_MENU ((USAGE) 0x87)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_MENU_EXIT ((USAGE) 0x88)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_MENU_SELECT ((USAGE) 0x89)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_MENU_RIGHT ((USAGE) 0x8A)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_MENU_LEFT ((USAGE) 0x8B)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_MENU_UP ((USAGE) 0x8C)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_MENU_DOWN ((USAGE) 0x8D)
|
||||
|
||||
//
|
||||
// Usages from Simulation Controls Page (0x02)
|
||||
//
|
||||
|
||||
#define HID_USAGE_SIMULATION_RUDDER ((USAGE) 0xBA)
|
||||
#define HID_USAGE_SIMULATION_THROTTLE ((USAGE) 0xBB)
|
||||
|
||||
//
|
||||
// Virtual Reality Controls Page (0x03)
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Sport Controls Page (0x04)
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Game Controls Page (0x05)
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Keyboard/Keypad Page (0x07)
|
||||
//
|
||||
|
||||
// Error "keys"
|
||||
#define HID_USAGE_KEYBOARD_NOEVENT ((USAGE) 0x00)
|
||||
#define HID_USAGE_KEYBOARD_ROLLOVER ((USAGE) 0x01)
|
||||
#define HID_USAGE_KEYBOARD_POSTFAIL ((USAGE) 0x02)
|
||||
#define HID_USAGE_KEYBOARD_UNDEFINED ((USAGE) 0x03)
|
||||
|
||||
// Letters
|
||||
#define HID_USAGE_KEYBOARD_aA ((USAGE) 0x04)
|
||||
#define HID_USAGE_KEYBOARD_zZ ((USAGE) 0x1D)
|
||||
// Numbers
|
||||
#define HID_USAGE_KEYBOARD_ONE ((USAGE) 0x1E)
|
||||
#define HID_USAGE_KEYBOARD_ZERO ((USAGE) 0x27)
|
||||
// Modifier Keys
|
||||
#define HID_USAGE_KEYBOARD_LCTRL ((USAGE) 0xE0)
|
||||
#define HID_USAGE_KEYBOARD_LSHFT ((USAGE) 0xE1)
|
||||
#define HID_USAGE_KEYBOARD_LALT ((USAGE) 0xE2)
|
||||
#define HID_USAGE_KEYBOARD_LGUI ((USAGE) 0xE3)
|
||||
#define HID_USAGE_KEYBOARD_RCTRL ((USAGE) 0xE4)
|
||||
#define HID_USAGE_KEYBOARD_RSHFT ((USAGE) 0xE5)
|
||||
#define HID_USAGE_KEYBOARD_RALT ((USAGE) 0xE6)
|
||||
#define HID_USAGE_KEYBOARD_RGUI ((USAGE) 0xE7)
|
||||
#define HID_USAGE_KEYBOARD_SCROLL_LOCK ((USAGE) 0x47)
|
||||
#define HID_USAGE_KEYBOARD_NUM_LOCK ((USAGE) 0x53)
|
||||
#define HID_USAGE_KEYBOARD_CAPS_LOCK ((USAGE) 0x39)
|
||||
// Funtion keys
|
||||
#define HID_USAGE_KEYBOARD_F1 ((USAGE) 0x3A)
|
||||
#define HID_USAGE_KEYBOARD_F12 ((USAGE) 0x45)
|
||||
|
||||
#define HID_USAGE_KEYBOARD_RETURN ((USAGE) 0x28)
|
||||
#define HID_USAGE_KEYBOARD_ESCAPE ((USAGE) 0x29)
|
||||
#define HID_USAGE_KEYBOARD_DELETE ((USAGE) 0x2A)
|
||||
|
||||
#define HID_USAGE_KEYBOARD_PRINT_SCREEN ((USAGE) 0x46)
|
||||
|
||||
// and hundreds more...
|
||||
|
||||
//
|
||||
// LED Page (0x08)
|
||||
//
|
||||
|
||||
#define HID_USAGE_LED_NUM_LOCK ((USAGE) 0x01)
|
||||
#define HID_USAGE_LED_CAPS_LOCK ((USAGE) 0x02)
|
||||
#define HID_USAGE_LED_SCROLL_LOCK ((USAGE) 0x03)
|
||||
#define HID_USAGE_LED_COMPOSE ((USAGE) 0x04)
|
||||
#define HID_USAGE_LED_KANA ((USAGE) 0x05)
|
||||
#define HID_USAGE_LED_POWER ((USAGE) 0x06)
|
||||
#define HID_USAGE_LED_SHIFT ((USAGE) 0x07)
|
||||
#define HID_USAGE_LED_DO_NOT_DISTURB ((USAGE) 0x08)
|
||||
#define HID_USAGE_LED_MUTE ((USAGE) 0x09)
|
||||
#define HID_USAGE_LED_TONE_ENABLE ((USAGE) 0x0A)
|
||||
#define HID_USAGE_LED_HIGH_CUT_FILTER ((USAGE) 0x0B)
|
||||
#define HID_USAGE_LED_LOW_CUT_FILTER ((USAGE) 0x0C)
|
||||
#define HID_USAGE_LED_EQUALIZER_ENABLE ((USAGE) 0x0D)
|
||||
#define HID_USAGE_LED_SOUND_FIELD_ON ((USAGE) 0x0E)
|
||||
#define HID_USAGE_LED_SURROUND_FIELD_ON ((USAGE) 0x0F)
|
||||
#define HID_USAGE_LED_REPEAT ((USAGE) 0x10)
|
||||
#define HID_USAGE_LED_STEREO ((USAGE) 0x11)
|
||||
#define HID_USAGE_LED_SAMPLING_RATE_DETECT ((USAGE) 0x12)
|
||||
#define HID_USAGE_LED_SPINNING ((USAGE) 0x13)
|
||||
#define HID_USAGE_LED_CAV ((USAGE) 0x14)
|
||||
#define HID_USAGE_LED_CLV ((USAGE) 0x15)
|
||||
#define HID_USAGE_LED_RECORDING_FORMAT_DET ((USAGE) 0x16)
|
||||
#define HID_USAGE_LED_OFF_HOOK ((USAGE) 0x17)
|
||||
#define HID_USAGE_LED_RING ((USAGE) 0x18)
|
||||
#define HID_USAGE_LED_MESSAGE_WAITING ((USAGE) 0x19)
|
||||
#define HID_USAGE_LED_DATA_MODE ((USAGE) 0x1A)
|
||||
#define HID_USAGE_LED_BATTERY_OPERATION ((USAGE) 0x1B)
|
||||
#define HID_USAGE_LED_BATTERY_OK ((USAGE) 0x1C)
|
||||
#define HID_USAGE_LED_BATTERY_LOW ((USAGE) 0x1D)
|
||||
#define HID_USAGE_LED_SPEAKER ((USAGE) 0x1E)
|
||||
#define HID_USAGE_LED_HEAD_SET ((USAGE) 0x1F)
|
||||
#define HID_USAGE_LED_HOLD ((USAGE) 0x20)
|
||||
#define HID_USAGE_LED_MICROPHONE ((USAGE) 0x21)
|
||||
#define HID_USAGE_LED_COVERAGE ((USAGE) 0x22)
|
||||
#define HID_USAGE_LED_NIGHT_MODE ((USAGE) 0x23)
|
||||
#define HID_USAGE_LED_SEND_CALLS ((USAGE) 0x24)
|
||||
#define HID_USAGE_LED_CALL_PICKUP ((USAGE) 0x25)
|
||||
#define HID_USAGE_LED_CONFERENCE ((USAGE) 0x26)
|
||||
#define HID_USAGE_LED_STAND_BY ((USAGE) 0x27)
|
||||
#define HID_USAGE_LED_CAMERA_ON ((USAGE) 0x28)
|
||||
#define HID_USAGE_LED_CAMERA_OFF ((USAGE) 0x29)
|
||||
#define HID_USAGE_LED_ON_LINE ((USAGE) 0x2A)
|
||||
#define HID_USAGE_LED_OFF_LINE ((USAGE) 0x2B)
|
||||
#define HID_USAGE_LED_BUSY ((USAGE) 0x2C)
|
||||
#define HID_USAGE_LED_READY ((USAGE) 0x2D)
|
||||
#define HID_USAGE_LED_PAPER_OUT ((USAGE) 0x2E)
|
||||
#define HID_USAGE_LED_PAPER_JAM ((USAGE) 0x2F)
|
||||
#define HID_USAGE_LED_REMOTE ((USAGE) 0x30)
|
||||
#define HID_USAGE_LED_FORWARD ((USAGE) 0x31)
|
||||
#define HID_USAGE_LED_REVERSE ((USAGE) 0x32)
|
||||
#define HID_USAGE_LED_STOP ((USAGE) 0x33)
|
||||
#define HID_USAGE_LED_REWIND ((USAGE) 0x34)
|
||||
#define HID_USAGE_LED_FAST_FORWARD ((USAGE) 0x35)
|
||||
#define HID_USAGE_LED_PLAY ((USAGE) 0x36)
|
||||
#define HID_USAGE_LED_PAUSE ((USAGE) 0x37)
|
||||
#define HID_USAGE_LED_RECORD ((USAGE) 0x38)
|
||||
#define HID_USAGE_LED_ERROR ((USAGE) 0x39)
|
||||
#define HID_USAGE_LED_SELECTED_INDICATOR ((USAGE) 0x3A)
|
||||
#define HID_USAGE_LED_IN_USE_INDICATOR ((USAGE) 0x3B)
|
||||
#define HID_USAGE_LED_MULTI_MODE_INDICATOR ((USAGE) 0x3C)
|
||||
#define HID_USAGE_LED_INDICATOR_ON ((USAGE) 0x3D)
|
||||
#define HID_USAGE_LED_INDICATOR_FLASH ((USAGE) 0x3E)
|
||||
#define HID_USAGE_LED_INDICATOR_SLOW_BLINK ((USAGE) 0x3F)
|
||||
#define HID_USAGE_LED_INDICATOR_FAST_BLINK ((USAGE) 0x40)
|
||||
#define HID_USAGE_LED_INDICATOR_OFF ((USAGE) 0x41)
|
||||
#define HID_USAGE_LED_FLASH_ON_TIME ((USAGE) 0x42)
|
||||
#define HID_USAGE_LED_SLOW_BLINK_ON_TIME ((USAGE) 0x43)
|
||||
#define HID_USAGE_LED_SLOW_BLINK_OFF_TIME ((USAGE) 0x44)
|
||||
#define HID_USAGE_LED_FAST_BLINK_ON_TIME ((USAGE) 0x45)
|
||||
#define HID_USAGE_LED_FAST_BLINK_OFF_TIME ((USAGE) 0x46)
|
||||
#define HID_USAGE_LED_INDICATOR_COLOR ((USAGE) 0x47)
|
||||
#define HID_USAGE_LED_RED ((USAGE) 0x48)
|
||||
#define HID_USAGE_LED_GREEN ((USAGE) 0x49)
|
||||
#define HID_USAGE_LED_AMBER ((USAGE) 0x4A)
|
||||
#define HID_USAGE_LED_GENERIC_INDICATOR ((USAGE) 0x3B)
|
||||
|
||||
//
|
||||
// Button Page (0x09)
|
||||
//
|
||||
// There is no need to label these usages.
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Ordinal Page (0x0A)
|
||||
//
|
||||
// There is no need to label these usages.
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Telephony Device Page (0x0B)
|
||||
//
|
||||
|
||||
#define HID_USAGE_TELEPHONY_PHONE ((USAGE) 0x01)
|
||||
#define HID_USAGE_TELEPHONY_ANSWERING_MACHINE ((USAGE) 0x02)
|
||||
#define HID_USAGE_TELEPHONY_MESSAGE_CONTROLS ((USAGE) 0x03)
|
||||
#define HID_USAGE_TELEPHONY_HANDSET ((USAGE) 0x04)
|
||||
#define HID_USAGE_TELEPHONY_HEADSET ((USAGE) 0x05)
|
||||
#define HID_USAGE_TELEPHONY_KEYPAD ((USAGE) 0x06)
|
||||
#define HID_USAGE_TELEPHONY_PROGRAMMABLE_BUTTON ((USAGE) 0x07)
|
||||
|
||||
//
|
||||
// and others...
|
||||
//
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -0,0 +1,330 @@
|
||||
// mapconv - symbolic debugging info generator for VirtualDub
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define MAX_CNAMBUF (0x20000)
|
||||
#define MAX_FNAMBUF (0x800000)
|
||||
#define MAX_SEGMENTS (64)
|
||||
#define MAX_GROUPS (64)
|
||||
|
||||
struct RVAEnt {
|
||||
long rva;
|
||||
char *line;
|
||||
};
|
||||
|
||||
std::vector<RVAEnt> rvabuf;
|
||||
|
||||
char fnambuf[MAX_FNAMBUF];
|
||||
char *fnamptr = fnambuf;
|
||||
|
||||
long segbuf[MAX_SEGMENTS][2];
|
||||
int segcnt=0;
|
||||
int seggrp[MAX_SEGMENTS];
|
||||
long grpstart[MAX_GROUPS];
|
||||
|
||||
char line[8192];
|
||||
long codeseg_flags = 0;
|
||||
FILE *f, *fo;
|
||||
|
||||
char *strtack(char *s, const char *t, const char *s_max) {
|
||||
while(s < s_max && (*s = *t))
|
||||
++s, ++t;
|
||||
|
||||
if (s == s_max)
|
||||
return NULL;
|
||||
|
||||
return s+1;
|
||||
}
|
||||
|
||||
bool readline() {
|
||||
if (!fgets(line, sizeof line, f))
|
||||
return false;
|
||||
|
||||
int l = strlen(line);
|
||||
|
||||
if (l>0 && line[l-1]=='\n')
|
||||
line[l-1]=0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool findline(const char *searchstr) {
|
||||
while(readline()) {
|
||||
if (strstr(line, searchstr))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* dbghelp UnDecorateSymbolName() doesn't handle anonymous namespaces,
|
||||
* which look like "?A0x30dd143a". Remove "@?A0x????????"; we don't
|
||||
* want to see "<anonymous namespace>::" in crash dump output, anyway. */
|
||||
void RemoveAnonymousNamespaces( char *p )
|
||||
{
|
||||
while( p = strstr( p, "@?A" ) )
|
||||
{
|
||||
int skip = 0, i;
|
||||
if( strlen(p) < 13 )
|
||||
break;
|
||||
|
||||
for( i = 5; i < 13; ++i )
|
||||
if( !isxdigit(p[i]) )
|
||||
skip = 1;
|
||||
if( p[3] != '0' || p[4] != 'x' )
|
||||
skip = 1;
|
||||
if( skip )
|
||||
{
|
||||
++p;
|
||||
continue;
|
||||
}
|
||||
|
||||
memmove( p, p+13, strlen(p+13)+1 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void parsename(long rva, char *func_name) {
|
||||
RemoveAnonymousNamespaces( func_name );
|
||||
|
||||
fnamptr = strtack(fnamptr, func_name, fnambuf+MAX_FNAMBUF);
|
||||
if(!fnamptr)
|
||||
throw "Too many func names; increase MAX_FNAMBUF.";
|
||||
}
|
||||
|
||||
struct RVASorter {
|
||||
bool operator()(const RVAEnt& e1, const RVAEnt& e2) {
|
||||
return e1.rva < e2.rva;
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int ver=0;
|
||||
int i;
|
||||
long load_addr;
|
||||
|
||||
if (argc<3) {
|
||||
printf("mapconv <listing-file> <output-name>\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (f=fopen("version.bin", "rb")) {
|
||||
fread(&ver,4,1,f);
|
||||
fclose(f);
|
||||
} else {
|
||||
printf("can't read version file\n");
|
||||
return 20;
|
||||
}
|
||||
|
||||
if (!(f=fopen(argv[1], "r"))) {
|
||||
printf("can't open listing file \"%s\"\n", argv[1]);
|
||||
return 20;
|
||||
}
|
||||
|
||||
if (!(fo=fopen(argv[2], "wb"))) {
|
||||
printf("can't open output file \"%s\"\n", argv[2]);
|
||||
return 20;
|
||||
}
|
||||
|
||||
// Begin parsing file
|
||||
|
||||
try {
|
||||
line[0] = 0;
|
||||
|
||||
// printf("Looking for segment list.\n");
|
||||
|
||||
if (!findline("Start Length"))
|
||||
throw "can't find segment list";
|
||||
|
||||
// printf("Reading in segment list.\n");
|
||||
|
||||
while(readline()) {
|
||||
long grp, start, len;
|
||||
|
||||
if (3!=sscanf(line, "%lx:%lx %lx", &grp, &start, &len))
|
||||
break;
|
||||
|
||||
if (strstr(line+49, "CODE")) {
|
||||
// printf("%04x:%08lx %08lx type code\n", grp, start, len);
|
||||
|
||||
codeseg_flags |= 1<<grp;
|
||||
|
||||
segbuf[segcnt][0] = start;
|
||||
segbuf[segcnt][1] = len;
|
||||
seggrp[segcnt] = grp;
|
||||
++segcnt;
|
||||
}
|
||||
}
|
||||
|
||||
// printf("Looking for public symbol list.\n");
|
||||
|
||||
if (!findline("Publics by Value"))
|
||||
throw "Can't find public symbol list.";
|
||||
|
||||
readline();
|
||||
|
||||
// printf("Found public symbol list.\n");
|
||||
|
||||
while(readline()) {
|
||||
long grp, start, rva;
|
||||
char symname[2048];
|
||||
int i;
|
||||
|
||||
if (4!=sscanf(line, "%lx:%lx %s %lx", &grp, &start, symname, &rva))
|
||||
break;
|
||||
|
||||
if (!(codeseg_flags & (1<<grp)) && strcmp(symname, "___ImageBase") )
|
||||
continue;
|
||||
|
||||
RVAEnt entry = { rva, strdup(line) };
|
||||
|
||||
rvabuf.push_back(entry);
|
||||
|
||||
// parsename(rva,symname);
|
||||
}
|
||||
|
||||
// printf("Looking for static symbol list.\n");
|
||||
|
||||
if (!findline("Static symbols"))
|
||||
printf("WARNING: No static symbols found!\n");
|
||||
else {
|
||||
readline();
|
||||
|
||||
while(readline()) {
|
||||
long grp, start, rva;
|
||||
char symname[4096];
|
||||
|
||||
if (4!=sscanf(line, "%lx:%lx %s %lx", &grp, &start, symname, &rva))
|
||||
break;
|
||||
|
||||
if (!(codeseg_flags & (1<<grp)))
|
||||
continue;
|
||||
|
||||
RVAEnt entry = { rva, strdup(line) };
|
||||
|
||||
rvabuf.push_back(entry);
|
||||
|
||||
// parsename(rva,symname);
|
||||
}
|
||||
}
|
||||
|
||||
// printf("Sorting RVA entries...\n");
|
||||
|
||||
std::sort(rvabuf.begin(), rvabuf.end(), RVASorter());
|
||||
|
||||
// printf("Processing RVA entries...\n");
|
||||
|
||||
for(i=0; i<rvabuf.size(); i++) {
|
||||
long grp, start, rva;
|
||||
char symname[4096];
|
||||
|
||||
sscanf(rvabuf[i].line, "%lx:%lx %s %lx", &grp, &start, symname, &rva);
|
||||
|
||||
grpstart[grp] = rva - start;
|
||||
|
||||
parsename(rva, symname);
|
||||
}
|
||||
|
||||
// printf("Processing segment entries...\n");
|
||||
|
||||
for(i=0; i<segcnt; i++) {
|
||||
segbuf[i][0] += grpstart[seggrp[i]];
|
||||
// printf("\t#%-2d %08lx-%08lx\n", i+1, segbuf[i][0], segbuf[i][0]+segbuf[i][1]-1);
|
||||
}
|
||||
/*
|
||||
printf("Raw statistics:\n");
|
||||
printf("\tRVA bytes: %ld\n", rvabuf.size()*4);
|
||||
printf("\tFunc name bytes: %ld\n", fnamptr - fnambuf);
|
||||
|
||||
printf("\nPacking RVA data..."); fflush(stdout);
|
||||
*/
|
||||
std::vector<RVAEnt>::iterator itRVA = rvabuf.begin(), itRVAEnd = rvabuf.end();
|
||||
std::vector<char> rvaout;
|
||||
long firstrva = (*itRVA++).rva;
|
||||
long lastrva = firstrva;
|
||||
|
||||
for(; itRVA != itRVAEnd; ++itRVA) {
|
||||
long rvadiff = (*itRVA).rva - lastrva;
|
||||
|
||||
lastrva += rvadiff;
|
||||
|
||||
if (rvadiff & 0xF0000000) rvaout.push_back((char)(0x80 | ((rvadiff>>28) & 0x7F)));
|
||||
if (rvadiff & 0xFFE00000) rvaout.push_back((char)(0x80 | ((rvadiff>>21) & 0x7F)));
|
||||
if (rvadiff & 0xFFFFC000) rvaout.push_back((char)(0x80 | ((rvadiff>>14) & 0x7F)));
|
||||
if (rvadiff & 0xFFFFFF80) rvaout.push_back((char)(0x80 | ((rvadiff>> 7) & 0x7F)));
|
||||
rvaout.push_back((char)(rvadiff & 0x7F));
|
||||
}
|
||||
|
||||
// printf("%ld bytes\n", rvaout.size());
|
||||
|
||||
// dump data
|
||||
|
||||
static const char header[64]="symbolic debug information\r\n\x1A";
|
||||
|
||||
fwrite(header, 64, 1, fo);
|
||||
|
||||
long t;
|
||||
|
||||
t = ver;
|
||||
fwrite(&t, 4, 1, fo);
|
||||
|
||||
t = rvaout.size() + 4;
|
||||
fwrite(&t, 4, 1, fo);
|
||||
|
||||
t = fnamptr - fnambuf;
|
||||
fwrite(&t, 4, 1, fo);
|
||||
|
||||
t = segcnt;
|
||||
fwrite(&t, 4, 1, fo);
|
||||
|
||||
fwrite(&firstrva, 4, 1, fo);
|
||||
fwrite(&rvaout[0], rvaout.size(), 1, fo);
|
||||
fwrite(fnambuf, fnamptr - fnambuf, 1, fo);
|
||||
fwrite(segbuf, segcnt*8, 1, fo);
|
||||
|
||||
// really all done
|
||||
|
||||
if (fclose(fo))
|
||||
throw "output file close failed";
|
||||
|
||||
} catch(const char *s) {
|
||||
fprintf(stderr, "%s: %s\n", argv[1], s);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* (c) 2002 Avery Lee
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||
* whom the Software is furnished to do so, provided that the above
|
||||
* copyright notice(s) and this permission notice appear in all copies of
|
||||
* the Software and that both the above copyright notice(s) and this
|
||||
* permission notice appear in supporting documentation.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
Binary file not shown.
@@ -0,0 +1,21 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 7.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mapconv", "mapconv.vcproj", "{46C1AA00-F02C-4E0A-8150-542C9728474C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
ConfigName.0 = Debug
|
||||
ConfigName.1 = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectDependencies) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{46C1AA00-F02C-4E0A-8150-542C9728474C}.Debug.ActiveCfg = Debug|Win32
|
||||
{46C1AA00-F02C-4E0A-8150-542C9728474C}.Debug.Build.0 = Debug|Win32
|
||||
{46C1AA00-F02C-4E0A-8150-542C9728474C}.Release.ActiveCfg = Release|Win32
|
||||
{46C1AA00-F02C-4E0A-8150-542C9728474C}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.00"
|
||||
Name="mapconv"
|
||||
ProjectGUID="{46C1AA00-F02C-4E0A-8150-542C9728474C}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="5"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/mapconv.exe"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/mapconv.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="4"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/mapconv.exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath=".\mapconv.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
@@ -0,0 +1,54 @@
|
||||
// Ehhh....
|
||||
//
|
||||
// I think I'll just put this one in the public domain
|
||||
// (with no warranty as usual).
|
||||
//
|
||||
// --Avery
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <time.h>
|
||||
|
||||
typedef unsigned long ulong;
|
||||
|
||||
int main(void) {
|
||||
FILE *f;
|
||||
ulong build=0,build_t;
|
||||
char s[25];
|
||||
time_t tm;
|
||||
struct tm *ptm;
|
||||
//////////////
|
||||
|
||||
if (f=fopen("version.bin","rb")) {
|
||||
if (1==fread(&build_t,sizeof build_t,1,f))
|
||||
build=build_t;
|
||||
}
|
||||
|
||||
++build;
|
||||
// printf("Incrementing to build %d\n",build);
|
||||
|
||||
time(&tm);
|
||||
|
||||
//memcpy(version_time, asctime(localtime(&tm)), sizeof(version_time)-1);
|
||||
ptm = localtime(&tm);
|
||||
strftime(s, sizeof(s), "%Y%m%d", ptm);
|
||||
s[sizeof(s)-1]=0;
|
||||
|
||||
|
||||
if (f=fopen("verstub.cpp","w")) {
|
||||
fprintf(f,
|
||||
"unsigned long version_num = %ld;\n"
|
||||
"extern const char *const version_time = \"%s\";\n"
|
||||
,build
|
||||
,s);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
if (f=fopen("version.bin","wb")) {
|
||||
fwrite(&build,sizeof build,1,f);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,21 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mapconv", "verinc.vcproj", "{46C1AA00-F02C-4E0A-8150-542C9728474C}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
Release = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{46C1AA00-F02C-4E0A-8150-542C9728474C}.Debug.ActiveCfg = Debug|Win32
|
||||
{46C1AA00-F02C-4E0A-8150-542C9728474C}.Debug.Build.0 = Debug|Win32
|
||||
{46C1AA00-F02C-4E0A-8150-542C9728474C}.Release.ActiveCfg = Release|Win32
|
||||
{46C1AA00-F02C-4E0A-8150-542C9728474C}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="verinc"
|
||||
ProjectGUID="{46C1AA00-F02C-4E0A-8150-542C9728474C}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="5"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/verinc.exe"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/verinc.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="4"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/verinc.exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath=".\verinc.c">
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
Reference in New Issue
Block a user