You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1307 lines
33 KiB
1307 lines
33 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// LOCAL_CMDS.CPP |
|
// |
|
// Local commands ( *xxxx ) executed by this application. |
|
//=====================================================================================// |
|
#include "vxconsole.h" |
|
|
|
localCommand_t g_localCommands[] = |
|
{ |
|
// Command name, Flags Handler Help string |
|
// console commands |
|
{ "*cls", FN_CONSOLE, lc_cls, ": Clear the screen" }, |
|
{ "*connect", FN_CONSOLE, lc_autoConnect, ": Connect and listen until successful" }, |
|
{ "*disconnect", FN_CONSOLE, lc_disconnect, ": Terminate Debug Console session" }, |
|
{ "*help", FN_CONSOLE, lc_help, "[command] : List commands/usage" }, |
|
{ "*quit", FN_CONSOLE, lc_quit, ": Terminate console" }, |
|
{ "*run", FN_XBOX, lc_run, "[app.xex] : Run application or Reboot" }, |
|
{ "*reset", FN_XBOX, lc_reset, "Reboot" }, |
|
{ "*screenshot", FN_XBOX, lc_screenshot, "<file.bmp> : Copy the screen to file.bmp" }, |
|
{ "*memory", FN_APP, lc_memory, ": Dump Memory Stats" }, |
|
{ "*dir", FN_XBOX, lc_dir, "<filepath> [/s]: Directory listing" }, |
|
{ "*del", FN_XBOX, lc_del, "<filepath> [/s] [/q]: Delete file" }, |
|
{ "*modules", FN_XBOX, lc_modules, ": Lists currently loaded modules" }, |
|
{ "*sections", FN_XBOX, lc_sections, "<module> : Lists the sections in the module" }, |
|
{ "*bug", FN_CONSOLE, lc_bug, ": Open bug submission form" }, |
|
{ "*clearconfigs", FN_XBOX, lc_ClearConfigs, ": Erase all game configs" }, |
|
|
|
// xcommands |
|
{ "*break", FN_XBOX, NULL, " addr=<address> | 'Write'/'Read'/'Execute'=<address> size=<DataSize> ['clear']: Sets/Clears a breakpoint" }, |
|
// { "*bye", FN_XBOX, NULL, ": Closes connection" }, |
|
{ "*continue", FN_XBOX, NULL, " thread=<threadid>: Resumes execution of a thread which has been stopped" }, |
|
// { "*delete", FN_XBOX, NULL, " name=<remotefile>: Deletes a file on the Xbox" }, |
|
// { "*dirlist", FN_XBOX, NULL, " name=<remotedir>: Lists the items in the directory" }, |
|
{ "*getcontext", FN_XBOX, NULL, " thread=<threadid> 'Control' | 'Int' | 'FP' | 'Full': Gets the context of the thread" }, |
|
{ "*getfileattributes", FN_XBOX, NULL, " name=<remotefile>: Gets attributes of a file" }, |
|
{ "*getmem", FN_XBOX, NULL, " addr=<address> length=<len>: Reads memory from the Xbox" }, |
|
{ "*go", FN_XBOX, NULL, ": Resumes suspended title threads" }, |
|
{ "*halt", FN_XBOX, NULL, " thread=<threadid> Breaks a thread" }, |
|
{ "*isstopped", FN_XBOX, NULL, " thread=<threadid>: Determines if a thread is stopped and why" }, |
|
{ "*mkdir", FN_XBOX, NULL, " name=<remotedir>: Creates a new directory on the Xbox" }, |
|
{ "*modlong", FN_XBOX, NULL, " name=<module>: Lists the long name of the module" }, |
|
// { "*reboot", FN_XBOX, NULL, " [warm] [wait]: Reboots the xbox" }, |
|
{ "*rename", FN_XBOX, NULL, " name=<remotefile> newname=<newname>: Renames a file on the Xbox" }, |
|
{ "*resume", FN_XBOX, NULL, " thread=<threadid>: Resumes thread execution" }, |
|
{ "*setcontext", FN_XBOX, NULL, " thread=<threadid>: Sets the context of the thread." }, |
|
{ "*setfileattributes", FN_XBOX, NULL, " <remotefile> <attrs>: Sets attributes of a file" }, |
|
{ "*setmem", FN_XBOX, NULL, " addr=<address> data=<rawdata>: Sets memory on the Xbox" }, |
|
{ "*stop", FN_XBOX, NULL, ": Stops the process" }, |
|
{ "*suspend", FN_XBOX, NULL, " thread=<threadid>: Suspends the thread" }, |
|
{ "*systime", FN_XBOX, NULL, ": Gets the system time of the xbox" }, |
|
{ "*threadinfo", FN_XBOX, NULL, " thread=<threadid>: Gets thread info" }, |
|
{ "*threads", FN_XBOX, lc_threads, ": Gets the thread list" }, |
|
// { "*title", FN_XBOX, NULL, " dir=<remotedir> name=<remotexex> [cmdline=<cmdline>]: Sets title to run" }, |
|
{ "*xexinfo", FN_XBOX, NULL, " name=<remotexex | 'running'>: Gets info on an xex" }, |
|
{ "*crash", FN_XBOX, lc_crashdump, " crash the console, emitting a dump" }, |
|
}; |
|
const int g_numLocalCommands = sizeof( g_localCommands )/sizeof( g_localCommands[0] ); |
|
|
|
static BOOL g_bAutoConnectQuiet; |
|
static int g_bAutoConnectWait; |
|
|
|
//----------------------------------------------------------------------------- |
|
// MatchCommands |
|
// |
|
//----------------------------------------------------------------------------- |
|
int MatchLocalCommands( char* cmdStr, const char* cmdList[], int maxCmds ) |
|
{ |
|
int numCommands = 0; |
|
|
|
// look in local |
|
int matchLen = strlen( cmdStr ); |
|
for ( int i=0; i<g_numLocalCommands; i++ ) |
|
{ |
|
if ( !strnicmp( cmdStr, g_localCommands[i].strCommand, matchLen ) ) |
|
{ |
|
cmdList[numCommands++] = g_localCommands[i].strCommand; |
|
if ( numCommands >= maxCmds ) |
|
break; |
|
} |
|
} |
|
|
|
return ( numCommands ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// DecodeRebootArgs |
|
// |
|
//----------------------------------------------------------------------------- |
|
void DecodeRebootArgs( int argc, char** argv, char* xexPath, char* xexName, char* xexArgs ) |
|
{ |
|
char drive[MAX_PATH]; |
|
char dir[MAX_PATH]; |
|
char filename[MAX_PATH]; |
|
char extension[MAX_PATH]; |
|
|
|
xexPath[0] = '\0'; |
|
xexName[0] = '\0'; |
|
xexArgs[0] = '\0'; |
|
|
|
if ( !argc ) |
|
return; |
|
|
|
_splitpath( argv[0], drive, dir, filename, extension ); |
|
|
|
sprintf( xexPath, "%s%s", drive, dir ); |
|
sprintf( xexName, "%s%s", filename, extension ); |
|
|
|
for ( int i=1; i<argc; i++ ) |
|
{ |
|
strcat( xexArgs, argv[i] ); |
|
if ( i < argc-1 ) |
|
strcat( xexArgs, " " ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Helper function. Causes a disconnect, has optional re-connect time. |
|
// A non-zero wait will delay before attempting re-connect. |
|
//----------------------------------------------------------------------------- |
|
void DoDisconnect( BOOL bKeepConnection, int waitTime ) |
|
{ |
|
// save state, user gates auto-connect ability |
|
int autoConnect = g_autoConnect; |
|
|
|
// full disconnect, disables autoconnect |
|
lc_disconnect( 0, NULL ); |
|
|
|
if ( autoConnect && bKeepConnection && waitTime > 0 ) |
|
{ |
|
// restore autoconnect status |
|
lc_autoConnect( 0, NULL ); |
|
|
|
// lets the system settle a little between contexts |
|
g_bAutoConnectWait = waitTime; |
|
g_bAutoConnectQuiet = FALSE; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_bug |
|
// |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_bug( int argc, char* argv[] ) |
|
{ |
|
if ( argc != 1 ) |
|
{ |
|
char* args[2] = {"*help", argv[0]}; |
|
lc_help( 1, args ); |
|
goto cleanUp; |
|
} |
|
|
|
BugDlg_Open(); |
|
|
|
return TRUE; |
|
|
|
cleanUp: |
|
return FALSE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_dir |
|
// |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_dir( int argc, char* argv[] ) |
|
{ |
|
fileNode_t *nodePtr; |
|
fileNode_t *pFileList; |
|
int numFiles; |
|
int numDirs; |
|
__int64 totalBytes; |
|
bool recurse; |
|
char dateTimeString[256]; |
|
char sizeString[64]; |
|
char filePath[MAX_PATH]; |
|
char fileName[MAX_PATH]; |
|
char targetName[MAX_PATH]; |
|
char newPath[MAX_PATH]; |
|
SYSTEMTIME systemTime; |
|
SYSTEMTIME localTime; |
|
const char *dirString; |
|
BOOL errCode; |
|
int nPass; |
|
TIME_ZONE_INFORMATION tzInfo; |
|
|
|
pFileList = NULL; |
|
errCode = FALSE; |
|
|
|
if ( argc < 2 ) |
|
{ |
|
char* args[2] = {"*dir", argv[0]}; |
|
lc_help( 2, args ); |
|
goto cleanUp; |
|
} |
|
|
|
strcpy( newPath, argv[1] ); |
|
|
|
// seperate components |
|
Sys_StripFilename( newPath, filePath, sizeof( filePath ) ); |
|
Sys_StripPath( newPath, fileName, sizeof( fileName ) ); |
|
|
|
if ( fileName[0] ) |
|
{ |
|
if ( !strstr( fileName,"*" ) && !strstr( fileName,"?" ) ) |
|
{ |
|
// assume filename was a directory name |
|
strcat( newPath, "\\" ); |
|
Sys_StripFilename( newPath, filePath, sizeof( filePath ) ); |
|
Sys_StripPath( newPath, fileName, sizeof( fileName ) ); |
|
} |
|
} |
|
|
|
recurse = false; |
|
if ( argc >= 3 ) |
|
{ |
|
if ( !stricmp( argv[2], "/s" ) ) |
|
recurse = true; |
|
} |
|
|
|
if ( !GetTargetFileList_r( filePath, recurse, FA_NORMAL|FA_DIRECTORY|FA_READONLY, 0, &pFileList ) ) |
|
{ |
|
ConsoleWindowPrintf( RGB( 255,0,0 ), "Bad Target Path '%s'\n", filePath ); |
|
goto cleanUp; |
|
} |
|
|
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "\nDirectory of %s\n\n", argv[1] ); |
|
|
|
GetTimeZoneInformation( &tzInfo ); |
|
|
|
numFiles = 0; |
|
numDirs = 0; |
|
totalBytes = 0; |
|
for ( nPass=0; nPass<2; nPass++ ) |
|
{ |
|
for ( nodePtr=pFileList; nodePtr; nodePtr=nodePtr->nextPtr ) |
|
{ |
|
if ( !nPass && !( nodePtr->attributes & FA_DIRECTORY ) ) |
|
{ |
|
// first pass, dirs only |
|
continue; |
|
} |
|
else if ( nPass && ( nodePtr->attributes & FA_DIRECTORY ) ) |
|
{ |
|
// second pass, files only |
|
continue; |
|
} |
|
|
|
Sys_StripPath( nodePtr->filename, targetName, sizeof( targetName ) ); |
|
|
|
if ( fileName[0] && !Sys_IsWildcardMatch( fileName, targetName, false ) ) |
|
continue; |
|
|
|
FileTimeToSystemTime( &nodePtr->changeTime, &systemTime ); |
|
SystemTimeToTzSpecificLocalTime( &tzInfo, &systemTime, &localTime ); |
|
SystemTimeToString( &localTime, dateTimeString, sizeof( dateTimeString ) ); |
|
|
|
__int64 fullSize = MAKEINT64( nodePtr->sizeHigh, nodePtr->sizeLow ); |
|
|
|
if ( nodePtr->attributes & FA_DIRECTORY ) |
|
{ |
|
numDirs++; |
|
dirString = "<DIR>"; |
|
sprintf( sizeString, "%s", " " ); |
|
} |
|
else |
|
{ |
|
numFiles++; |
|
dirString = " "; |
|
Sys_NumberToCommaString( fullSize, sizeString, sizeof( sizeString ) ); |
|
totalBytes += fullSize; |
|
} |
|
|
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%s %s %12s %s\n", dateTimeString, dirString, sizeString, targetName ); |
|
} |
|
} |
|
|
|
Sys_NumberToCommaString( totalBytes, sizeString, sizeof( sizeString ) ); |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%9s %d File(s) %s bytes\n", " ", numFiles, sizeString ); |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%9s %d Dir(s)\n", " ", numDirs ); |
|
|
|
// success |
|
errCode = TRUE; |
|
|
|
cleanUp: |
|
if ( pFileList ) |
|
FreeTargetFileList( pFileList ); |
|
|
|
return errCode; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_del |
|
// |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_del( int argc, char* argv[] ) |
|
{ |
|
HRESULT hr; |
|
fileNode_t *nodePtr; |
|
fileNode_t *pFileList; |
|
int numDeleted; |
|
int numErrors; |
|
bool recurse; |
|
char filePath[MAX_PATH]; |
|
char fileName[MAX_PATH]; |
|
char targetName[MAX_PATH]; |
|
BOOL errCode; |
|
|
|
pFileList = NULL; |
|
errCode = FALSE; |
|
|
|
if ( argc < 2 ) |
|
{ |
|
char* args[2] = {"*del", argv[0]}; |
|
lc_help( 2, args ); |
|
goto cleanUp; |
|
} |
|
|
|
// seperate components |
|
Sys_StripFilename( argv[1], filePath, sizeof( filePath ) ); |
|
Sys_StripPath( argv[1], fileName, sizeof( fileName ) ); |
|
|
|
bool bQuiet = false; |
|
recurse = false; |
|
if ( argc >= 3 ) |
|
{ |
|
for ( int i = 2; i < argc; i++ ) |
|
{ |
|
if ( !V_stricmp( argv[i], "/s" ) ) |
|
{ |
|
recurse = true; |
|
} |
|
else if ( !V_stricmp( argv[i], "/q" ) ) |
|
{ |
|
// silence errors |
|
bQuiet = true; |
|
} |
|
} |
|
} |
|
|
|
if ( !GetTargetFileList_r( filePath, recurse, FA_NORMAL|FA_READONLY|FA_DIRECTORY, 0, &pFileList ) ) |
|
{ |
|
ConsoleWindowPrintf( XBX_CLR_RED, "Bad Target Path '%s'\n", filePath ); |
|
goto cleanUp; |
|
} |
|
|
|
numErrors = 0; |
|
numDeleted = 0; |
|
for ( nodePtr=pFileList; nodePtr; nodePtr=nodePtr->nextPtr ) |
|
{ |
|
Sys_StripPath( nodePtr->filename, targetName, sizeof( targetName ) ); |
|
|
|
if ( fileName[0] && !Sys_IsWildcardMatch( fileName, targetName, false ) ) |
|
continue; |
|
|
|
hr = DmDeleteFile( nodePtr->filename, ( nodePtr->attributes & FA_DIRECTORY ) != 0 ); |
|
if ( hr != XBDM_NOERR ) |
|
{ |
|
if ( !bQuiet ) |
|
{ |
|
ConsoleWindowPrintf( XBX_CLR_RED, "Error Deleting '%s'\n", nodePtr->filename ); |
|
} |
|
numErrors++; |
|
} |
|
else |
|
{ |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Deleted '%s'\n", nodePtr->filename ); |
|
numDeleted++; |
|
} |
|
} |
|
|
|
if ( !numDeleted && !numErrors ) |
|
{ |
|
ConsoleWindowPrintf( XBX_CLR_RED, "No Files found for '%s'\n", argv[1] ); |
|
} |
|
else |
|
{ |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%d files deleted.\n", numDeleted ); |
|
} |
|
|
|
// success |
|
errCode = TRUE; |
|
|
|
cleanUp: |
|
if ( pFileList ) |
|
FreeTargetFileList( pFileList ); |
|
|
|
return errCode; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_memory |
|
// |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_memory( int argc, char* argv[] ) |
|
{ |
|
HRESULT hr; |
|
|
|
hr = DmAPI_SendCommand( VXCONSOLE_COMMAND_PREFIX "!" "__memory__", true ); |
|
if ( FAILED( hr ) ) |
|
return FALSE; |
|
|
|
// success |
|
return TRUE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_screenshot |
|
// |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_screenshot( int argc, char* argv[] ) |
|
{ |
|
char filename[MAX_PATH]; |
|
char filepath[MAX_PATH]; |
|
static int shot = 0; |
|
struct _stat dummyStat; |
|
|
|
if ( argc <= 1 ) |
|
{ |
|
strcpy( filepath, g_localPath ); |
|
Sys_AddFileSeperator( filepath, sizeof( filepath ) ); |
|
|
|
// spin up to available file |
|
while ( 1 ) |
|
{ |
|
sprintf( filename, "%sscreenshot_%4.4d.bmp", filepath, shot ); |
|
if ( _stat( filename, &dummyStat ) == -1 ) |
|
{ |
|
// filename not in use |
|
break; |
|
} |
|
shot++; |
|
} |
|
} |
|
else if ( argc == 2 ) |
|
{ |
|
strcpy( filename, argv[1] ); |
|
Sys_AddExtension( ".bmp", filename, sizeof( filename ) ); |
|
} |
|
else if ( argc > 2 ) |
|
{ |
|
char* args[2] = {"*help", argv[0]}; |
|
lc_help( 2, args ); |
|
goto cleanUp; |
|
} |
|
|
|
HRESULT hr = DmScreenShot( filename ); |
|
if ( FAILED( hr ) ) |
|
{ |
|
DmAPI_DisplayError( "lc_screenshot(): DmScreenShot() failure", hr ); |
|
goto cleanUp; |
|
} |
|
|
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Screenshot saved to %s\n", filename ); |
|
|
|
// advance the shot |
|
shot++; |
|
|
|
// success |
|
return TRUE; |
|
|
|
cleanUp: |
|
return FALSE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_modules |
|
// |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_modules( int argc, char* argv[] ) |
|
{ |
|
HRESULT hr; |
|
PDM_WALK_MODULES pWalkMod = NULL; |
|
CUtlVector< DMN_MODLOAD > list; |
|
|
|
// add a fake module at 0xFFFFFFFF to make sorting simple |
|
DMN_MODLOAD modLoad = { 0 }; |
|
modLoad.BaseAddress = (VOID*)0xFFFFFFFF; |
|
list.AddToTail( modLoad ); |
|
|
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Modules:\n" ); |
|
while ( 1 ) |
|
{ |
|
hr = DmWalkLoadedModules( &pWalkMod, &modLoad ); |
|
if ( hr == XBDM_ENDOFLIST ) |
|
{ |
|
hr = XBDM_NOERR; |
|
break; |
|
} |
|
else if ( FAILED( hr ) ) |
|
{ |
|
DmAPI_DisplayError( "lc_modules(): DmWalkLoadedModules() failure", hr ); |
|
break; |
|
} |
|
|
|
// add in ascending address order |
|
for ( int i = 0; i < list.Count(); i++ ) |
|
{ |
|
if ( modLoad.BaseAddress <= list[i].BaseAddress ) |
|
{ |
|
list.InsertBefore( i, modLoad ); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
unsigned int total = 0; |
|
for ( int i = 0; i < list.Count()-1; i++ ) |
|
{ |
|
DMN_MODLOAD *pModule = &list[i]; |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Base: 0x%8.8x, Size: %5.2f MB, [%s]\n", pModule->BaseAddress, pModule->Size/( 1024.0f*1024.0f ), pModule->Name ); |
|
|
|
total += pModule->Size; |
|
} |
|
|
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Total: %.2f MB\n\n", total/( 1024.0f*1024.0f ) ); |
|
|
|
if ( pWalkMod ) |
|
{ |
|
DmCloseLoadedModules( pWalkMod ); |
|
} |
|
|
|
if ( !FAILED( hr ) ) |
|
{ |
|
// success |
|
return TRUE; |
|
} |
|
|
|
return FALSE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_sections |
|
// |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_sections( int argc, char* argv[] ) |
|
{ |
|
char moduleName[MAX_PATH]; |
|
HRESULT hr; |
|
PDM_WALK_MODSECT pWalkModSect = NULL; |
|
DMN_SECTIONLOAD sectLoad; |
|
|
|
if ( argc != 2 ) |
|
{ |
|
char* args[2] = {"*help", argv[0]}; |
|
lc_help( 2, args ); |
|
goto cleanUp; |
|
} |
|
|
|
strcpy( moduleName, argv[1] ); |
|
|
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Sections:\n" ); |
|
while ( 1 ) |
|
{ |
|
hr = DmWalkModuleSections( &pWalkModSect, moduleName, §Load ); |
|
if ( hr == XBDM_ENDOFLIST ) |
|
{ |
|
hr = XBDM_NOERR; |
|
break; |
|
} |
|
else if ( FAILED( hr ) ) |
|
{ |
|
DmAPI_DisplayError( "lc_sections(): DmWalkModuleSections() failure", hr ); |
|
break; |
|
} |
|
|
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "[%s]:\n", sectLoad.Name ); |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, " Base: 0x%8.8x\n", sectLoad.BaseAddress ); |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, " Size: %.2f MB ( %d bytes )\n", sectLoad.Size/( 1024.0f*1024.0f ), sectLoad.Size ); |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, " Index: %d\n", sectLoad.Index ); |
|
} |
|
|
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "End.\n\n" ); |
|
|
|
if ( pWalkModSect ) |
|
DmCloseModuleSections( pWalkModSect ); |
|
|
|
if ( !FAILED( hr ) ) |
|
{ |
|
// success |
|
return TRUE; |
|
} |
|
|
|
cleanUp: |
|
return FALSE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_threads |
|
// |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_threads( int argc, char* argv[] ) |
|
{ |
|
char nameBuff[256]; |
|
char suspendBuff[32]; |
|
|
|
DWORD threadList[256]; |
|
DWORD numThreads = 256; |
|
memset( &threadList, 0, sizeof( threadList ) ); |
|
HRESULT hr = DmGetThreadList( threadList, &numThreads ); |
|
if ( FAILED( hr ) ) |
|
return FALSE; |
|
|
|
// enumerate threads and display sorted by processor |
|
DM_THREADINFOEX threadInfoEx; |
|
for ( int core = 0; core < 3; core++ ) |
|
{ |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "\n--- CORE %d ---\n", core ); |
|
|
|
for ( int unit = 0; unit < 2; unit++ ) |
|
{ |
|
for ( int i = 0; i < (int)numThreads; i++ ) |
|
{ |
|
threadInfoEx.Size = sizeof( DM_THREADINFOEX ); |
|
hr = DmGetThreadInfoEx( threadList[i], &threadInfoEx ); |
|
if ( FAILED( hr ) ) |
|
return FALSE; |
|
|
|
if ( threadInfoEx.CurrentProcessor != core*2 + unit ) |
|
{ |
|
continue; |
|
} |
|
|
|
nameBuff[0] = '\0'; |
|
DmGetMemory( threadInfoEx.ThreadNameAddress, threadInfoEx.ThreadNameLength, nameBuff, NULL ); |
|
if ( !nameBuff[0] ) |
|
{ |
|
strcpy( nameBuff, "???" ); |
|
} |
|
|
|
suspendBuff[0] = '\0'; |
|
if ( threadInfoEx.SuspendCount ) |
|
{ |
|
sprintf( suspendBuff, "(Suspend: %d)", threadInfoEx.SuspendCount ); |
|
} |
|
|
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, " Id: 0x%8.8x Pri: %2d Proc: %1d Stack: %7.2f KB [%s] %s\n", |
|
threadList[i], |
|
threadInfoEx.Priority, |
|
threadInfoEx.CurrentProcessor, |
|
(float)( (unsigned int)threadInfoEx.StackBase - (unsigned int)threadInfoEx.StackLimit )/1024.0f, |
|
nameBuff, |
|
suspendBuff ); |
|
} |
|
} |
|
} |
|
|
|
return TRUE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_run |
|
// |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_run( int argc, char* argv[] ) |
|
{ |
|
HRESULT hr; |
|
char xexDrive[MAX_PATH]; |
|
char xexPath[MAX_PATH]; |
|
char xexName[MAX_PATH]; |
|
char xexArgs[MAX_PATH]; |
|
|
|
if ( !argc ) |
|
{ |
|
char* args[2] = {"*help", argv[0]}; |
|
lc_help( 2, args ); |
|
goto cleanUp; |
|
} |
|
|
|
// copy args |
|
g_rebootArgc = argc-1; |
|
for ( int i=1; i<argc; i++ ) |
|
{ |
|
if ( i==1 ) |
|
{ |
|
strcpy( xexPath, argv[i] ); |
|
Sys_AddExtension( ".xex", xexPath, sizeof( xexPath ) ); |
|
_splitpath( xexPath, xexDrive, NULL, NULL, NULL ); |
|
if ( !xexDrive[0] ) |
|
{ |
|
char szTempPath[MAX_PATH]; |
|
V_strncpy( szTempPath, "e:\\", sizeof( szTempPath ) ); |
|
V_strncat( szTempPath, xexPath, sizeof( szTempPath ) ); |
|
V_strncpy( xexPath, szTempPath, sizeof( xexPath ) ); |
|
} |
|
|
|
g_rebootArgv[i-1] = Sys_CopyString( xexPath ); |
|
} |
|
else |
|
{ |
|
g_rebootArgv[i-1] = Sys_CopyString( argv[i] ); |
|
} |
|
} |
|
|
|
if ( !g_rebootArgc ) |
|
{ |
|
// reboot |
|
hr = DmReboot( DMBOOT_COLD ); |
|
} |
|
else |
|
{ |
|
DecodeRebootArgs( g_rebootArgc, g_rebootArgv, xexPath, xexName, xexArgs ); |
|
|
|
// trial set title - ensure title is present |
|
hr = DmSetTitle( xexPath, xexName, xexArgs ); |
|
if ( FAILED( hr ) ) |
|
{ |
|
DmAPI_DisplayError( "lc_Run(): DmSetTitle() failure", hr ); |
|
goto cleanUp; |
|
} |
|
|
|
// reboot - wait for 15s to connect and run title |
|
hr = DmReboot( DMBOOT_WAIT ); |
|
} |
|
if ( FAILED( hr ) ) |
|
{ |
|
DmAPI_DisplayError( "lc_Run(): DmReboot() failure", hr ); |
|
goto cleanUp; |
|
} |
|
|
|
// set reboot state |
|
g_reboot = true; |
|
|
|
return TRUE; |
|
|
|
cleanUp: |
|
// free args |
|
for ( int i=0; i<g_rebootArgc; i++ ) |
|
Sys_Free( g_rebootArgv[i] ); |
|
g_rebootArgc = 0; |
|
|
|
return FALSE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_reset |
|
// |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_reset( int argc, char* argv[] ) |
|
{ |
|
if ( !argc ) |
|
{ |
|
char* args[2] = {"*help", argv[0]}; |
|
lc_help( 2, args ); |
|
return FALSE; |
|
} |
|
|
|
HRESULT hr = DmReboot( DMBOOT_COLD ); |
|
|
|
if ( FAILED( hr ) ) |
|
{ |
|
DmAPI_DisplayError( "lc_Run(): DmReboot() failure", hr ); |
|
return FALSE; |
|
} |
|
|
|
// set reboot state |
|
g_reboot = true; |
|
|
|
return TRUE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_help |
|
// |
|
// Handles the "help" command. If no args, prints a list of built-in |
|
// and remote commands ( remote only if connected ). If a command |
|
// is specified, prints detailed help for that command |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_help( int argc, char* argv[] ) |
|
{ |
|
if ( argc <= 1 ) |
|
{ |
|
// no arguments - print out our list of commands |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "\n" ); |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Console Commands:\n" ); |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "---------------\n" ); |
|
for ( int i = 0; i < g_numLocalCommands; i++ ) |
|
{ |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%s\n", g_localCommands[i].strCommand ); |
|
} |
|
|
|
if ( g_connectedToApp ) |
|
{ |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Remote Commands: ( %d )\n", g_numRemoteCommands ); |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "----------------\n" ); |
|
if ( !g_numRemoteCommands ) |
|
{ |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "( None )\n" ); |
|
} |
|
else |
|
{ |
|
for ( int i=0; i<g_numRemoteCommands; i++ ) |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%s\n", g_remoteCommands[i]->strCommand ); |
|
} |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "\n" ); |
|
} |
|
} |
|
else |
|
{ |
|
// match as many as possible |
|
int cch = lstrlenA( argv[1] ); |
|
|
|
// print help description for all local matches |
|
for ( int i=0; i<g_numLocalCommands; i++ ) |
|
{ |
|
if ( !_strnicmp( g_localCommands[i].strCommand, argv[1], cch ) && g_localCommands[i].strHelp ) |
|
{ |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%s %s\n", g_localCommands[i].strCommand, g_localCommands[i].strHelp ); |
|
} |
|
} |
|
|
|
// print help description for all remote matches |
|
if ( g_connectedToApp ) |
|
{ |
|
for ( int i=0; i<g_numRemoteCommands; i++ ) |
|
{ |
|
if ( !_strnicmp( g_remoteCommands[i]->strCommand, argv[1], cch ) && g_remoteCommands[i]->strHelp ) |
|
{ |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%s %s\n", g_remoteCommands[i]->strCommand, g_remoteCommands[i]->strHelp ); |
|
} |
|
} |
|
} |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "\n" ); |
|
} |
|
|
|
return TRUE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_cls |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_cls( int argc, char* argv[] ) |
|
{ |
|
SetWindowText( g_hwndOutputWindow, "" ); |
|
|
|
// non't let the compiler complain about unused parameters |
|
( VOID )argc; |
|
( VOID )argv; |
|
|
|
return TRUE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_connect |
|
// |
|
// Connect to XBox |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_connect( int argc, char* argv[] ) |
|
{ |
|
HRESULT hr; |
|
BOOL connected = FALSE; |
|
|
|
if ( g_connectedToXBox ) |
|
{ |
|
if ( !lc_disconnect( 0, NULL ) ) |
|
return FALSE; |
|
} |
|
|
|
if ( argc >= 1 && argv[0][0] ) |
|
{ |
|
hr = DmSetXboxName( argv[0] ); |
|
if ( FAILED( hr ) ) |
|
{ |
|
char message[255]; |
|
sprintf( message, "ConnectToXBox(): DmSetXboxName( %s ) failure", argv[0] ); |
|
DmAPI_DisplayError( message, hr ); |
|
goto cleanUp; |
|
} |
|
} |
|
|
|
// open connection |
|
hr = DmOpenConnection( &g_pdmConnection ); |
|
if ( FAILED( hr ) ) |
|
{ |
|
DmAPI_DisplayError( "ConnectToXBox(): DmOpenConnection() failure", hr ); |
|
goto cleanUp; |
|
} |
|
connected = TRUE; |
|
|
|
DWORD namelen = MAX_XBOXNAMELEN; |
|
hr = DmGetXboxName( g_xboxName, &namelen ); |
|
if ( FAILED( hr ) ) |
|
{ |
|
DmAPI_DisplayError( "ConnectToXBox(): DmGetXboxName() failure", hr ); |
|
goto cleanUp; |
|
} |
|
hr = DmResolveXboxName( &g_xboxAddress ); |
|
if ( FAILED( hr ) ) |
|
{ |
|
DmAPI_DisplayError( "ConnectToXBox(): DmResolveXboxName() failure", hr ); |
|
goto cleanUp; |
|
} |
|
|
|
// success |
|
g_connectedToXBox = TRUE; |
|
g_connectFailure = 0; |
|
|
|
if ( !g_connectCount ) |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Connected To: '%s'(%d.%d.%d.%d)\n", g_xboxName, ( ( byte* )&g_xboxAddress )[3], ( ( byte* )&g_xboxAddress )[2], ( ( byte* )&g_xboxAddress )[1], ( ( byte* )&g_xboxAddress )[0] ); |
|
g_connectCount++; |
|
|
|
SetConnectionIcon( ICON_CONNECTED_XBOX ); |
|
|
|
if ( g_connectCount == 1 ) |
|
{ |
|
// inital connect |
|
} |
|
|
|
return TRUE; |
|
|
|
cleanUp: |
|
if ( connected ) |
|
DmCloseConnection( g_pdmConnection ); |
|
|
|
return FALSE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_listen |
|
// |
|
// Open listen session with App |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_listen( int argc, char* argv[] ) |
|
{ |
|
HRESULT hr; |
|
BOOL success; |
|
BOOL sessionStarted; |
|
BOOL sessionValid; |
|
char *args[1]; |
|
char cmdStr[256]; |
|
|
|
if ( g_connectedToXBox || g_connectedToApp ) |
|
{ |
|
if ( !lc_disconnect( 0, NULL ) ) |
|
return ( FALSE ); |
|
} |
|
|
|
if ( !g_connectedToXBox ) |
|
{ |
|
// connect to xbox |
|
args[0] = g_xboxTargetName; |
|
if ( !lc_connect( 1, args ) ) |
|
return FALSE; |
|
} |
|
|
|
// until otherwise |
|
success = FALSE; |
|
sessionStarted = FALSE; |
|
sessionValid = FALSE; |
|
|
|
// init session |
|
hr = DmOpenNotificationSession( 0, &g_pdmnSession ); |
|
if ( FAILED( hr ) ) |
|
{ |
|
DmAPI_DisplayError( "lc_session(): DmOpenNotificationSession() failure", hr ); |
|
goto cleanUp; |
|
} |
|
sessionStarted = TRUE; |
|
|
|
// get notifications of app debugging output |
|
hr = DmNotify( g_pdmnSession, DM_DEBUGSTR, Remote_NotifyDebugString ); |
|
if ( FAILED( hr ) ) |
|
{ |
|
DmAPI_DisplayError( "lc_session(): DmNotify() failure", hr ); |
|
goto cleanUp; |
|
} |
|
|
|
// get command notifications |
|
hr = DmRegisterNotificationProcessor( g_pdmnSession, VXCONSOLE_COMMAND_PREFIX, Remote_NotifyCommandFunc ); |
|
if ( FAILED( hr ) ) |
|
{ |
|
DmAPI_DisplayError( "lc_session(): DmRegisterNotificationProcessor() failure", hr ); |
|
goto cleanUp; |
|
} |
|
|
|
// get print notifications |
|
hr = DmRegisterNotificationProcessor( g_pdmnSession, VXCONSOLE_PRINT_PREFIX, Remote_NotifyPrintFunc ); |
|
if ( FAILED( hr ) ) |
|
{ |
|
DmAPI_DisplayError( "lc_session(): DmRegisterNotificationProcessor() failure", hr ); |
|
goto cleanUp; |
|
} |
|
sessionValid = TRUE; |
|
|
|
// Send initial connect command to the External Command Processor so it knows we're here |
|
sprintf( cmdStr, "%s %d", VXCONSOLE_COMMAND_PREFIX "!" "__connect__", VXCONSOLE_PROTOCOL_VERSION ); |
|
hr = DmAPI_SendCommand( cmdStr, true ); |
|
if ( FAILED( hr ) ) |
|
{ |
|
if ( !g_autoConnect ) |
|
ConsoleWindowPrintf( RGB( 255,0,0 ), "Couldn't Find Application\n" ); |
|
goto cleanUp; |
|
} |
|
else |
|
{ |
|
// connected |
|
success = TRUE; |
|
g_connectedToApp = TRUE; |
|
g_connectedTime = Sys_GetSystemTime(); |
|
SetConnectionIcon( ICON_CONNECTED_APP1 ); |
|
|
|
if ( g_clsOnConnect ) |
|
{ |
|
if ( g_bPlayTestMode ) |
|
{ |
|
// demarcate the log |
|
ConsoleWindowPrintf( CLR_DEFAULT, "\n******** CONNECTION ********\n" ); |
|
} |
|
|
|
lc_cls( 0, NULL ); |
|
CpuProfile_Clear(); |
|
TimeStampLog_Clear(); |
|
} |
|
|
|
goto cleanUp; |
|
} |
|
|
|
cleanUp: |
|
if ( !success ) |
|
{ |
|
if ( sessionValid ) |
|
DmNotify( g_pdmnSession, DM_NONE, NULL ); |
|
|
|
if ( sessionStarted ) |
|
DmCloseNotificationSession( g_pdmnSession ); |
|
} |
|
|
|
return ( success ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// AutoConnectTimerProc |
|
// |
|
//----------------------------------------------------------------------------- |
|
void AutoConnectTimerProc( HWND hwnd, UINT_PTR idEvent ) |
|
{ |
|
static BOOL busy; |
|
int icon; |
|
char* cmdStr; |
|
BOOL bKeepConnection = TRUE; |
|
|
|
// blink the connection icon |
|
if ( g_connectedToApp && (! g_bSuppressBlink ) ) |
|
{ |
|
if ( g_currentIcon == ICON_CONNECTED_APP0 ) |
|
icon = ICON_CONNECTED_APP1; |
|
else |
|
icon = ICON_CONNECTED_APP0; |
|
SetConnectionIcon( icon ); |
|
} |
|
|
|
if ( busy ) |
|
{ |
|
// not ready for new tick |
|
return; |
|
} |
|
|
|
if ( g_bAutoConnectWait > 0 ) |
|
{ |
|
if ( g_bAutoConnectWait && !g_bAutoConnectQuiet ) |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Waiting... %d seconds remaining\n", g_bAutoConnectWait ); |
|
g_bAutoConnectWait--; |
|
return; |
|
} |
|
|
|
// no more ticks until ready |
|
busy = TRUE; |
|
|
|
if ( !g_connectedToApp ) |
|
{ |
|
// looking for application - must force re-connect every time |
|
if ( g_connectedToXBox ) |
|
{ |
|
// temporary "partial" disconnect |
|
DmCloseConnection( g_pdmConnection ); |
|
g_connectedToXBox = FALSE; |
|
} |
|
|
|
// attempt to start or re-establish connection and session |
|
lc_listen( 0, NULL ); |
|
|
|
if ( !g_connectedToXBox ) |
|
{ |
|
SetConnectionIcon( ICON_DISCONNECTED ); |
|
g_connectFailure++; |
|
} |
|
|
|
if ( g_reboot && g_connectedToXBox ) |
|
{ |
|
char xexPath[MAX_PATH]; |
|
char xexName[MAX_PATH]; |
|
char xexArgs[MAX_PATH]; |
|
|
|
DecodeRebootArgs( g_rebootArgc, g_rebootArgv, xexPath, xexName, xexArgs ); |
|
|
|
if ( g_rebootArgc ) |
|
{ |
|
// free args |
|
for ( int i=0; i<g_rebootArgc; i++ ) |
|
Sys_Free( g_rebootArgv[i] ); |
|
g_rebootArgc = 0; |
|
|
|
HRESULT hr = DmSetTitle( xexPath, xexName, xexArgs ); |
|
if ( FAILED( hr ) ) |
|
DmAPI_DisplayError( "Reboot: DmSetTitle() failure", hr ); |
|
else |
|
{ |
|
hr = DmGo(); |
|
if ( FAILED( hr ) ) |
|
DmAPI_DisplayError( "Reboot: DmGo() failure", hr ); |
|
} |
|
} |
|
|
|
g_reboot = false; |
|
} |
|
|
|
if ( !g_connectFailure ) |
|
{ |
|
// quietly attempt re-connection or ping every 3 seconds |
|
g_bAutoConnectWait = 3; |
|
g_bAutoConnectQuiet = TRUE; |
|
busy = FALSE; |
|
} |
|
else |
|
{ |
|
if ( g_connectFailure == 1 ) |
|
{ |
|
// console may be rebooting, allow sufficient dvd boot up delay, then attempt re-connection |
|
// 5 seconds barely covers the xbox splash |
|
g_bAutoConnectWait = 15; |
|
g_bAutoConnectQuiet = FALSE; |
|
busy = FALSE; |
|
} |
|
else |
|
{ |
|
// a sustained connection failure means the xbox is just not there |
|
// re-trying is too cpu intensive and causes pc to appear locked |
|
// warn and stop auto connecting, user must fix |
|
bKeepConnection = FALSE; |
|
goto disconnect; |
|
} |
|
} |
|
return; |
|
} |
|
else |
|
{ |
|
// try to send ping across open connection at an idle interval |
|
cmdStr = VXCONSOLE_COMMAND_PREFIX "!"; |
|
HRESULT hr = DmAPI_SendCommand( cmdStr, false ); |
|
if ( FAILED( hr ) && hr != XBDM_UNDEFINED ) |
|
goto disconnect; |
|
|
|
// quietly ping |
|
g_bAutoConnectWait = 3; |
|
g_bAutoConnectQuiet = TRUE; |
|
busy = FALSE; |
|
return; |
|
} |
|
|
|
disconnect: |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Connection To Xbox Lost.\n" ); |
|
|
|
DoDisconnect( bKeepConnection, 3 ); |
|
|
|
busy = FALSE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_autoConnect |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_autoConnect( int argc, char* argv[] ) |
|
{ |
|
if ( !g_autoConnect ) |
|
{ |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Enabling Auto Connect.\n" ); |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Looking for Connection...\n" ); |
|
g_autoConnect = TRUE; |
|
} |
|
else |
|
{ |
|
// already enabled |
|
return ( TRUE ); |
|
} |
|
|
|
if ( !g_autoConnectTimer ) |
|
{ |
|
UINT_PTR timer = TIMERID_AUTOCONNECT; |
|
g_autoConnectTimer = SetTimer( g_hDlgMain, timer, 1000, NULL ); |
|
} |
|
|
|
return ( TRUE ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_disconnect |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_disconnect( int argc, char* argv[] ) |
|
{ |
|
if ( g_autoConnect ) |
|
{ |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Disabling Auto Connect.\n" ); |
|
if ( g_autoConnectTimer ) |
|
{ |
|
UINT_PTR timer = TIMERID_AUTOCONNECT; |
|
KillTimer( g_hDlgMain, timer ); |
|
} |
|
g_autoConnectTimer = 0; |
|
g_autoConnect = FALSE; |
|
} |
|
|
|
if ( g_connectedToApp ) |
|
{ |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Closing Session.\n" ); |
|
|
|
DmAPI_SendCommand( VXCONSOLE_COMMAND_PREFIX "!" "__disconnect__", false ); |
|
|
|
// close session |
|
DmNotify( g_pdmnSession, DM_NONE, NULL ); |
|
DmCloseNotificationSession( g_pdmnSession ); |
|
|
|
g_connectedToApp = FALSE; |
|
} |
|
|
|
if ( g_connectedToXBox ) |
|
{ |
|
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Closing Connection.\n" ); |
|
|
|
// close connection |
|
DmCloseConnection( g_pdmConnection ); |
|
|
|
// set the command ready mutex |
|
SetEvent( g_hCommandReadyEvent ); |
|
|
|
g_connectedToXBox = FALSE; |
|
g_xboxName[0] = '\0'; |
|
g_xboxAddress = 0; |
|
} |
|
|
|
SetConnectionIcon( ICON_DISCONNECTED ); |
|
|
|
g_connectCount = 0; |
|
|
|
// free remote commands |
|
Remote_DeleteCommands(); |
|
|
|
// Don't let the compiler complain about unused parameters |
|
( VOID )argc; |
|
( VOID )argv; |
|
|
|
return TRUE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_crashdump |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_crashdump( int argc, char* argv[] ) |
|
{ |
|
DmCrashDump(); |
|
|
|
// Don't let the compiler complain about unused parameters |
|
( VOID )argc; |
|
( VOID )argv; |
|
|
|
return TRUE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_quit |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_quit( int argc, char* argv[] ) |
|
{ |
|
PostMessage( g_hDlgMain, WM_CLOSE, 0, 0 ); |
|
|
|
// don't let the compiler complain about unused parameters |
|
( VOID )argc; |
|
( VOID )argv; |
|
|
|
return TRUE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// lc_ClearConfigs |
|
// |
|
//----------------------------------------------------------------------------- |
|
BOOL lc_ClearConfigs( int argc, char* argv[] ) |
|
{ |
|
if ( argc != 1 ) |
|
{ |
|
char* args[2] = {"*help", argv[0]}; |
|
lc_help( 1, args ); |
|
goto cleanUp; |
|
} |
|
|
|
// delete any configurations (ignore errors) |
|
char szTempFilename[MAX_PATH]; |
|
V_ComposeFileName( "HDD:\\Content", "*.*", szTempFilename, sizeof( szTempFilename ) ); |
|
char *pArgs[4]; |
|
pArgs[0] = "*del"; |
|
pArgs[1] = szTempFilename; |
|
pArgs[2] = "/s"; |
|
pArgs[3] = "/q"; |
|
lc_del( 4, pArgs ); |
|
|
|
return TRUE; |
|
|
|
cleanUp: |
|
return FALSE; |
|
}
|
|
|