Windows2003-3790/sdktools/remote/remote.c
2020-09-30 16:53:55 +02:00

1517 lines
42 KiB
C

/******************************************************************************\
* This is a part of the Microsoft Source Code Samples.
* Copyright 1993 - 1997 Microsoft Corporation.
* All rights reserved.
* This source code is only intended as a supplement to
* Microsoft Development Tools and/or WinHelp documentation.
* See these sources for detailed information regarding the
* Microsoft samples programs.
\******************************************************************************/
/*++
Copyright 1993 - 1997 Microsoft Corporation
Module Name:
Remote.c
Abstract:
This module contains the main() entry point for Remote.
Calls the Server or the Client depending on the first parameter.
Author:
Rajivendra Nath 2-Jan-1993
Environment:
Console App. User mode.
Revision History:
--*/
#include <precomp.h>
#include "Remote.h"
char HostName[HOSTNAMELEN];
char* ChildCmd;
char* PipeName;
char* ServerName;
char * DaclNames[ MAX_DACL_NAMES ];
DWORD DaclNameCount = 0;
char * DaclDenyNames[ MAX_DACL_NAMES ];
DWORD DaclDenyNameCount = 0 ;
BOOL SaveDaclToRegistry ;
HANDLE MyStdOut;
HANDLE hAttachedProcess = INVALID_HANDLE_VALUE;
HANDLE hAttachedWriteChildStdIn = INVALID_HANDLE_VALUE;
HANDLE hAttachedReadChildStdOut = INVALID_HANDLE_VALUE;
BOOL IsAdvertise;
DWORD ClientToServerFlag;
BOOL bForceTwoPipes;
typedef struct _tagKeywordAndColor
{
char *szKeyword;
WORD color;
struct _tagKeywordAndColor *next;
} KeywordAndColor;
KeywordAndColor *pKeyColors;
const char* ColorList[]={"black" ,"blue" ,"green" ,"cyan" ,"red" ,"purple" ,"yellow" ,"white",
"lblack","lblue","lgreen","lcyan","lred","lpurple","lyellow","lwhite"};
typedef enum { LINE_TOO_LONG } WARNING_MESSAGE;
VOID
DisplayWarning(
WARNING_MESSAGE warn
);
WORD
GetColorNum(
char* color
);
VOID
SetColor(
WORD attr
);
BOOL
GetColorFromBuffer(
char **ppBuffer,
char *pBufferInvalid,
WORD *color,
BOOL bStayOnLine
);
VOID
AssocKeysAndColors(
KeywordAndColor **ppKeyAndColors,
char *szFileName
);
BOOL
GetNextConnectInfo(
char** SrvName,
char** PipeName
);
CONSOLE_SCREEN_BUFFER_INFO csbiOriginal;
int
__cdecl
main(
int argc,
char** argv
)
{
WORD RunType; // Server or Client end of Remote
DWORD len=HOSTNAMELEN;
int i, FirstArg;
char sTitle[120]; // New Title
char orgTitle[200]; // Old Title
BOOL bPromptForArgs=FALSE; // Is /P option
WORD wAttrib; // Console Attributes
int privacy; // Allows exposing or hidng sessions to remote /q
BOOL Deny ;
int rc=1;
GetComputerName((LPTSTR)HostName,&len);
MyStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (GetConsoleScreenBufferInfo(MyStdOut,&csbiOriginal)) {
wAttrib = csbiOriginal.wAttributes;
if (!GetConsoleTitle(orgTitle,sizeof(orgTitle))) {
orgTitle[0] = 0;
}
} else {
//
// either stdout is a pipe, or it wasn't opened for
// GENERIC_READ along with GENERIC_WRITE, in which
// case our color manipulations will work so we need
// to pick default colors.
//
wAttrib = FOREGROUND_GREEN |
FOREGROUND_INTENSITY;
orgTitle[0] = 0;
}
privacy = PRIVACY_DEFAULT;
pKeyColors = NULL;
//
// Parameter Processing
//
// For Server:
// Remote /S <Executable> <PipeName> [Optional Params]
//
// For Client:
// Remote /C <Server Name> <PipeName> [Optional Params]
// or
// Remote /P
// This will loop continously prompting for different
// Servers and Pipename
if ((argc<2)||((argv[1][0]!='/')&&(argv[1][0]!='-')))
{
DisplayServerHlp();
DisplayClientHlp();
return(1);
}
switch(argv[1][1])
{
case 'c':
case 'C':
//
// Is Client End of Remote
//
if ((argc<4)||((argv[1][0]!='/')&&(argv[1][0]!='-')))
{
DisplayServerHlp();
DisplayClientHlp();
return(1);
}
ServerName=argv[2];
PipeName=argv[3];
FirstArg=4;
RunType=RUNTYPE_CLIENT;
break;
case 'q':
case 'Q':
//
// Query for possible conexions
//
if ((argc != 3)||((argv[1][0]!='/')&&(argv[1][0]!='-')))
{
DisplayServerHlp();
DisplayClientHlp();
return(1);
}
QueryRemotePipes(argv[2]); // Send ServerName as a param
return(0);
case 'p':
case 'P':
//
// Is Client End of Remote
//
bPromptForArgs=TRUE;
RunType=RUNTYPE_CLIENT;
FirstArg=2;
break;
case 's':
case 'S':
//
// Is Server End of Remote
//
if ((argc<4)||((argv[1][0]!='/')&&(argv[1][0]!='-')))
{
DisplayServerHlp();
DisplayClientHlp();
return(1);
}
ChildCmd=argv[2];
PipeName=argv[3];
FirstArg=4;
RunType=REMOTE_SERVER;
break;
case 'a':
case 'A':
//
// Is Server End of Remote Attaching to existing process.
//
if ((argc<7)||((argv[1][0]!='/')&&(argv[1][0]!='-')))
{
DisplayServerHlp();
DisplayClientHlp();
return(1);
}
hAttachedProcess = (HANDLE)IntToPtr(atoi(argv[2]));
hAttachedWriteChildStdIn = (HANDLE)IntToPtr(atoi(argv[3]));
hAttachedReadChildStdOut = (HANDLE)IntToPtr(atoi(argv[4]));
ChildCmd=argv[5]; // for display only
PipeName=argv[6];
FirstArg=7;
RunType = REMOTE_SERVER;
privacy = PRIVACY_VISIBLE; // presumably ntsd/*kd
break;
default:
DisplayServerHlp();
DisplayClientHlp();
return(1);
}
if (RunType==REMOTE_SERVER)
{
//
// Base Name of Executable
// For setting the title
//
char *tcmd=ChildCmd;
while ((*tcmd!=' ') && (*tcmd!=0)) tcmd++;
while ((tcmd > ChildCmd) && (*tcmd!='\\')) tcmd--;
if (*tcmd=='\\') tcmd++;
ZeroMemory(sTitle, sizeof(sTitle));
_snprintf(sTitle,sizeof(sTitle),"%-41.40s [Remote /C %s \"%.30s\"]",tcmd,HostName,PipeName);
}
//
//Process Common (Optional) Parameters
//
for (i=FirstArg;i<argc;i++)
{
if ((argv[i][0]!='/')&&(argv[i][0]!='-'))
{
printf("Invalid parameter %s:Ignoring\n",argv[i]);
continue;
}
switch(argv[i][1])
{
case 'l': // Only Valid for client End
case 'L': // Max Number of Lines to recieve from Server
i++;
if (i>=argc)
{
printf("Incomplete Param %s..Ignoring\n",argv[i-1]);
break;
}
LinesToSend=(DWORD)atoi(argv[i])+1;
break;
case 't': // Title to be set instead of the default
case 'T':
i++;
if (i>=argc)
{
printf("Incomplete Param %s..Ignoring\n",argv[i-1]);
break;
}
ZeroMemory(sTitle, sizeof(sTitle));
strncpy(sTitle,argv[i], sizeof(sTitle)/sizeof(sTitle[0])-1);
break;
case 'b': // Background color
case 'B':
i++;
if (i>=argc)
{
printf("Incomplete Param %s..Ignoring\n",argv[i-1]);
break;
}
{
WORD col=GetColorNum(argv[i]);
if (col!=0xffff)
{
wAttrib=col<<4|(wAttrib&0x000f);
}
break;
}
case 'f': // Foreground color
case 'F':
i++;
if (i>=argc)
{
printf("Incomplete Param %s..Ignoring\n",argv[i-1]);
break;
}
{
WORD col=GetColorNum(argv[i]);
if (col!=0xffff)
{
wAttrib=col|(wAttrib&0x00f0);
}
break;
}
case 'k': // Color "keyword" lines
case 'K':
i++;
// Currently only support client-side coloring
if (RunType==REMOTE_SERVER)
{
printf("%s invalid on server side..Ignoring\n",argv[i-1]);
break;
}
else if (i>=argc)
{
printf("Incomplete Param %s..Ignoring\n",argv[i-1]);
break;
}
else
{
AssocKeysAndColors( &pKeyColors, argv[i] );
break;
}
case 'v':
case 'V':
privacy = PRIVACY_VISIBLE;
break;
case '-':
if( (argv[i][2] == 'v')
|| (argv[i][2] == 'V'))
privacy = PRIVACY_NOT_VISIBLE;
else
printf("Unknown Parameter=%s %s\n",argv[i-1],argv[i]);
break;
case 'q':
case 'Q':
ClientToServerFlag|=0x80000000;
break;
case 'u':
case 'U':
if ( (argv[i][2] == 'd') ||
(argv[i][2] == 'D' ) )
{
Deny = TRUE ;
}
else if ( (argv[i][2] == 's' ) ||
(argv[i][2] == 'S' ) )
{
SaveDaclToRegistry = TRUE ;
break;
}
else
{
Deny = FALSE ;
}
i++ ;
if ( i >= argc )
{
printf( "Incomplete Param %s..Ignoring\n", argv[i-1] );
break;
}
if ( Deny )
{
if (DaclDenyNameCount == MAX_DACL_NAMES )
{
printf("Too many names specified (max %d). Ignoring user %s\n",
MAX_DACL_NAMES, argv[i] );
break;
}
DaclDenyNames[ DaclDenyNameCount++ ] = argv[i];
}
else
{
if (DaclNameCount == MAX_DACL_NAMES )
{
printf("Too many names specified (max %d). Ignoring user %s\n",
MAX_DACL_NAMES, argv[i] );
break;
}
DaclNames[ DaclNameCount++ ] = argv[i];
}
break;
case '2':
bForceTwoPipes = TRUE;
break;
default:
printf("Unknown Parameter=%s %s\n",argv[i-1],argv[i]);
break;
}
}
//
//Now Set various Parameters
//
//
//Colors
//
SetColor(wAttrib);
if (RunType==RUNTYPE_CLIENT)
{
BOOL done=FALSE;
BOOL gotinfo;
//
// Set Client end defaults and start client
//
while(!done)
{
if (!bPromptForArgs ||
(gotinfo = GetNextConnectInfo(&ServerName,&PipeName))
)
{
ZeroMemory(sTitle, sizeof(sTitle));
_snprintf(sTitle,sizeof(sTitle), "Remote /C %s \"%s\"",ServerName,PipeName);
SetConsoleTitle(sTitle);
//
// Start Client (Client.C)
//
rc = Client(ServerName,PipeName);
}
done = !bPromptForArgs || !gotinfo;
}
}
if (RunType==REMOTE_SERVER)
{
if (privacy == PRIVACY_VISIBLE ||
(privacy == PRIVACY_DEFAULT && IsKdString(ChildCmd))) {
strncat(sTitle, " visible", sizeof(sTitle) - strlen(sTitle) - 1);
IsAdvertise = TRUE;
}
SetConsoleTitle(sTitle);
rc = OverlappedServer(ChildCmd, PipeName);
}
//
//Reset Colors
//
SetColor(csbiOriginal.wAttributes);
if (orgTitle[0]) {
SetConsoleTitle(orgTitle);
}
return rc;
}
/*************************************************************/
VOID
ErrorExit(
char* str
)
{
extern PSZ pszPipeName;
DWORD dwErr;
dwErr = GetLastError();
printf("REMOTE error %d: %s\n", dwErr, str);
#if DBG
{
char szMsg[1024];
_snprintf(szMsg, sizeof(szMsg), "REMOTE error %d: %s\n", dwErr, str);
OutputDebugString(szMsg);
if (pszPipeName) { // ad-hoc: if server
if (IsDebuggerPresent()) {
DebugBreak();
}
}
}
#endif
exit(1);
}
/*************************************************************/
VOID
DisplayClientHlp()
{
printf("\n"
" To Start the CLIENT end of REMOTE\n"
" ---------------------------------\n"
" Syntax : REMOTE /C <ServerName> \"<Unique Id>\" [Param]\n"
" Example1: REMOTE /C %s imbroglio\n"
" This would connect to a server session on %s with Id\n"
" \"imbroglio\" if there is a REMOTE /S <\"Cmd\"> imbroglio\n"
" running on %s.\n\n"
" Example2: REMOTE /C %s \"name with spaces\"\n"
" This would connect to a server session on %s with Id\n"
" \"name with spaces\" if there is a REMOTE /S <\"Cmd\"> \"name with spaces\"\n"
" running on %s.\n\n"
" To Exit: %cQ (Leaves the Remote Server Running)\n"
" [Param]: /L <# of Lines to Get>\n"
" [Param]: /F <Foreground color eg blue, lred..>\n"
" [Param]: /K <Set keywords and colors from file>\n"
" [Param]: /B <Background color eg cyan, lwhite..>\n"
"\n"
" Keywords And Colors File Format\n"
" -------------------------------\n"
" <KEYWORDs - CASE INSENSITIVE>\n"
" <FOREGROUND>[, <BACKGROUND>]\n"
" ...\n"
" EX:\n"
" ERROR\n"
" black, lred\n"
" WARNING\n"
" lblue\n"
" COLOR THIS LINE\n"
" lgreen\n"
"\n"
" To Query the visible sessions on a server\n"
" -----------------------------------------\n"
" Syntax: REMOTE /Q %s\n"
" This would retrieve the available <Unique Id>s\n"
" visible connections on the computer named %s.\n"
"\n",
HostName, HostName, HostName,
HostName, HostName, HostName,
COMMANDCHAR, HostName, HostName);
}
/*************************************************************/
VOID
DisplayServerHlp()
{
printf("\n"
" To Start the SERVER end of REMOTE\n"
" ---------------------------------\n"
" Syntax : REMOTE /S <\"Cmd\"> <Unique Id> [Param]\n"
" Example1: REMOTE /S \"i386kd -v\" imbroglio\n"
" To interact with this \"Cmd\" from some other machine,\n"
" start the client end using: REMOTE /C %s imbroglio\n\n"
" Example2: REMOTE /S \"i386kd -v\" \"name with spaces\"\n"
" start the client end using: REMOTE /C %s \"name with spaces\"\n\n"
" To Exit: %cK \n"
" [Param]: /F <Foreground color eg yellow, black..>\n"
" [Param]: /B <Background color eg lblue, white..>\n"
" [Param]: /U username or groupname\n"
" specifies which users or groups may connect\n"
" may be specified more than once, e.g\n"
" /U user1 /U group2 /U user2\n"
" [Param]: /UD username or groupname\n"
" specifically denies access to that user or group\n"
" [Param]: /V Makes this session visible to remote /Q\n"
" [Param]: /-V Hides this session from remote /q (invisible)\n"
" By default, if \"Cmd\" looks like a debugger,\n"
" the session is visible, otherwise not\n"
"\n",
HostName, HostName, COMMANDCHAR);
}
VOID
DisplayWarning(
WARNING_MESSAGE warn
)
{
switch ( warn )
{
case LINE_TOO_LONG:
fputs( "\n[REMOTE: WARNING: LINE TOO LONG TO PARSE FOR COLOR KEYWORDS]\n", stdout );
break;
default:
fputs( "\n[REMOTE: WARNING: UNSPECIFIED PROBLEM COLORING LINE]\n", stdout );
}
}
WORD
GetColorNum(
char *color
)
{
WORD i;
_strlwr(color);
for (i=0;i<16;i++)
{
if (strcmp(ColorList[i],color)==0)
{
return(i);
}
}
return ((WORD)atoi(color));
}
VOID
SetColor(
WORD attr
)
{
COORD origin={0,0};
DWORD dwrite;
FillConsoleOutputAttribute
(
MyStdOut,attr,csbiOriginal.dwSize.
X*csbiOriginal.dwSize.Y,origin,&dwrite
);
SetConsoleTextAttribute(MyStdOut,attr);
}
BOOL
pColorLine(
char *sLine,
int cbLine,
WORD wDefaultColor,
WORD *color
)
{
KeywordAndColor *pCurKeyColor = NULL;
char *pString1;
int cbCmpString;
pCurKeyColor = pKeyColors;
while ( pCurKeyColor )
{
cbCmpString = strlen( pCurKeyColor->szKeyword );
pString1 = sLine;
// Need to do case-insensitive compare
while ( pString1 <= sLine + cbLine - cbCmpString )
{
if ( !_memicmp( (PVOID)pString1,
(PVOID)pCurKeyColor->szKeyword,
cbCmpString ) )
{
*color = pCurKeyColor->color;
// Check if we are to use default background color
if ( (0xfff0 & *color) == 0xfff0 )
*color = (wDefaultColor & 0x00f0) |
(*color & 0x000f);
return TRUE;
}
pString1++;
}
// Next keyword/color combination
pCurKeyColor = pCurKeyColor->next;
}
return FALSE;
}
BOOL
pWantColorLines(
VOID
)
{
return ( NULL != pKeyColors );
}
VOID
AssocKeysAndColors(
KeywordAndColor **ppKeyColors,
char *szFileName
)
{
char szPathName[_MAX_PATH],
*szSimpleName;
char *buffer,
*pBegin,
*pEnd;
USHORT usForeColor,
usBackColor;
KeywordAndColor *pCurKeyColor,
*pNextKeyColor;
HANDLE hFile;
WIN32_FIND_DATA wfdInfo;
DWORD dwBytesRead;
// Locate the specified file somewhere in the path
if ( !SearchPath( NULL,
szFileName,
NULL,
_MAX_PATH,
szPathName,
&szSimpleName ) )
{
fprintf( stderr, "Error locating keyword/color file \"%s\"!\n",
szFileName );
return;
}
// Get the size of the file so we can read all of it in
hFile = FindFirstFile( szPathName, &wfdInfo );
if ( INVALID_HANDLE_VALUE == hFile )
{
fprintf( stderr, "Error locating keyword/color file \"%s\"!\n",
szPathName );
return;
}
FindClose( hFile );
hFile = INVALID_HANDLE_VALUE;
if ( wfdInfo.nFileSizeLow < 5 ||
wfdInfo.nFileSizeHigh )
{
fprintf( stderr, "Invalid keyword/color file: %s!\n",
szPathName );
return;
}
// Allocate memory to store file contents
buffer = malloc( wfdInfo.nFileSizeLow );
if ( NULL == buffer )
{
fputs( "Error! Unable to allocate memory to read in keyword/color file!\n", stderr );
return;
}
// Attempt to open the given file-name
hFile = CreateFile( szPathName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL );
if ( INVALID_HANDLE_VALUE == hFile )
{
fprintf( stderr, "Error opening keyword/color file %s!\n",
szPathName );
return;
}
// Attempt to read in the contents of the file
if (!ReadFile( hFile, buffer, wfdInfo.nFileSizeLow, &dwBytesRead, NULL ))
{
fprintf( stderr, "Error reading keyword/color file: %s!\n", szPathName );
free( buffer );
return;
}
CloseHandle( hFile );
if ( dwBytesRead != wfdInfo.nFileSizeLow )
{
fprintf( stderr, "Error reading keyword/color file: %s!\n", szPathName );
free( buffer );
return;
}
// Parse contents of file, storing keyword(s) and color combinations
pBegin = buffer;
pCurKeyColor = NULL;
while ( pBegin < buffer + dwBytesRead )
{
// Skip any newline/CR at beginning
while ( pBegin < buffer + dwBytesRead &&
( *pBegin == '\r' ||
*pBegin == '\n' ) ) pBegin++;
if ( pBegin >= buffer + dwBytesRead )
continue;
pEnd = pBegin;
while ( pEnd < buffer + dwBytesRead &&
*pEnd != '\r' ) pEnd++;
// point at last character
pEnd--;
// Add new KeywordAndColor member to list
if ( NULL == pCurKeyColor )
{
*ppKeyColors = pCurKeyColor = malloc( sizeof( KeywordAndColor ) );
}
else
{
pCurKeyColor->next = malloc( sizeof( KeywordAndColor ) );
pCurKeyColor = pCurKeyColor->next;
}
// Verify we allocated memory for another list member
if ( NULL == pCurKeyColor )
{
fputs( "Error allocating memory for keyword/color storage!\n", stderr );
// Cleanup any we did create
while ( *ppKeyColors )
{
pCurKeyColor = ((KeywordAndColor *)*ppKeyColors)->next;
if ( ((KeywordAndColor *)*ppKeyColors)->szKeyword )
free( ((KeywordAndColor *)*ppKeyColors)->szKeyword );
free( (KeywordAndColor *)*ppKeyColors );
(KeywordAndColor *)*ppKeyColors = pCurKeyColor;
}
return;
}
// This is now the last member of the list
pCurKeyColor->next = NULL;
// Already have keyword(s) -- allocate room for it
pCurKeyColor->szKeyword = malloc( pEnd - pBegin + 2 );
if ( NULL == pCurKeyColor->szKeyword )
{
fputs( "Error allocating memory for keyword/color storage!\n", stderr );
// Cleanup any we did create
while ( *ppKeyColors )
{
pCurKeyColor = ((KeywordAndColor *)*ppKeyColors)->next;
if ( ((KeywordAndColor *)*ppKeyColors)->szKeyword )
free( ((KeywordAndColor *)*ppKeyColors)->szKeyword );
free( (KeywordAndColor *)*ppKeyColors );
*ppKeyColors = pCurKeyColor;
}
return;
}
// Store keyword(s)
memcpy( (PVOID)pCurKeyColor->szKeyword, (PVOID)pBegin, pEnd-pBegin+1 );
pCurKeyColor->szKeyword[pEnd-pBegin+1] = '\0';
pBegin = pEnd + 1;
// Get color information
if ( GetColorFromBuffer( &pBegin,
(char *)(buffer + dwBytesRead),
&usForeColor,
FALSE ) )
{
// Check if there is a comma following
while ( pBegin < buffer + dwBytesRead &&
*pBegin != ',' &&
*pBegin != '\r' ) pBegin++;
if ( *pBegin == ',' )
{
pBegin++;
if ( GetColorFromBuffer( &pBegin,
(char *)(buffer + dwBytesRead),
&usBackColor,
TRUE ) )
goto noError;
}
else
{
// Default to current background color
usBackColor = 0xffff;
goto noError;
}
}
// ERROR
fprintf( stderr, "Invalid color information for: %s\n", pCurKeyColor->szKeyword );
// We will leave any previous entries but delete this one
pNextKeyColor = *ppKeyColors;
if ( pNextKeyColor == pCurKeyColor )
{
free( pCurKeyColor );
*ppKeyColors = NULL;
}
else
{
while ( pCurKeyColor != pNextKeyColor->next )
pNextKeyColor = pNextKeyColor->next;
free ( pCurKeyColor );
pNextKeyColor->next = NULL;
}
return;
noError:
// Store color information
if ( usBackColor == 0xffff )
pCurKeyColor->color = 0xfff0 |
(usForeColor & 0x0f);
else
pCurKeyColor->color = ((usBackColor << 4) & 0x00f0) |
(usForeColor & 0x0f );
}
}
BOOL
GetColorFromBuffer(
char **ppBuffer,
char *pBufferInvalid,
WORD *color,
BOOL bStayOnLine
)
{
char *pBegin,
*pEnd,
temp;
pBegin = *ppBuffer;
if ( bStayOnLine )
{
// Skip to the next character (on this line)
while ( pBegin < pBufferInvalid &&
!isalnum( (int)*pBegin ) &&
*pBegin != '\r' ) pBegin++;
}
else
{
// Skip to next character (in buffer)
while ( pBegin < pBufferInvalid &&
!isalnum( (int)*pBegin ) ) pBegin++;
}
if ( pBegin >= pBufferInvalid ||
*pBegin == '\r' )
return FALSE;
// Read in color
pEnd = pBegin + 1;
while ( isalnum( (int)*pEnd ) &&
*pEnd != ',' ) pEnd++;
temp = *pEnd;
*pEnd = '\0';
*color = GetColorNum( pBegin );
*pEnd = temp;
// Use same valid color check as used for foreground/background
if ( *color == 0xffff )
return FALSE;
// Move the pointer we were given to next unread portion
*ppBuffer = pEnd;
return TRUE;
}
BOOL
GetNextConnectInfo(
char** SrvName,
char** PipeName
)
{
char *s;
static char szServerName[64];
static char szPipeName[32];
int StringLen;
try
{
ZeroMemory(szServerName,64);
ZeroMemory(szPipeName,32);
SetConsoleTitle("Remote - Prompting for next Connection");
fputs("Debugger machine (server): ", stdout);
fflush(stdout);
if (!fgets(szServerName, sizeof(szServerName), stdin)) {
return FALSE;
}
StringLen = strlen(szServerName);
if (!StringLen || (!feof(stdin) && szServerName[StringLen-1] != '\n')) {
return FALSE;
}
if (szServerName[StringLen-1] == '\n') {
if (StringLen == 1) {
return (FALSE);
}
szServerName[StringLen-1] = '\0';
}
if (szServerName[0] == COMMANDCHAR &&
(szServerName[1] == 'q' || szServerName[1] == 'Q')
)
{
return(FALSE);
}
if (s = strchr( szServerName, ' ' )) {
*s++ = '\0';
while (*s == ' ') {
s += 1;
}
*PipeName=strcpy(szPipeName, s);
fputs(szPipeName, stdout);
fflush(stdout);
}
if (strlen(szPipeName) == 0) {
fputs("Target machine (pipe) : ", stdout);
fflush(stdout);
if (!fgets(szPipeName, sizeof(szPipeName), stdin)) {
return FALSE;
}
StringLen = strlen(szPipeName);
if (!StringLen || (!feof(stdin) && szPipeName[StringLen-1] != '\n')) {
return FALSE;
}
if (szPipeName[StringLen-1] == '\n') {
szPipeName[StringLen-1] = '\0';
}
}
if (s = strchr(szPipeName, ' ')) {
*s++ = '\0';
}
if (szPipeName[0] == COMMANDCHAR &&
(szPipeName[1] == 'q' || szPipeName[1] == 'Q')
)
{
return(FALSE);
}
fputs("\n\n", stdout);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
return(FALSE); // Ignore exceptions
}
*SrvName = szServerName;
*PipeName = szPipeName;
return(TRUE);
}
/*************************************************************/
VOID
Errormsg(
char* str
)
{
printf("Error (%d) - %s\n",GetLastError(),str);
}
/*************************************************************/
BOOL
IsKdString(
char* string
)
{
char* start;
//
// some heuristic for uninvented yet platforms
// if the first word has "kd" in it ok
//
if( ((start = strstr(string, "kd")) != NULL)
|| ((start = strstr(string, "dbg")) != NULL)
|| ((start = strstr(string, "remoteds")) != NULL)
|| ((start = strstr(string, "ntsd")) != NULL)
|| ((start = strstr(string, "cdb")) != NULL) )
{
// is it in the first word?
while(--start > string)
{
if((*start == ' ') || (*start == '\t'))
{
while(--start > string)
if((*start != '\t') && (*start != ' '))
return(FALSE);
}
}
return TRUE;
}
return(FALSE);
}
//
// WriteFileSynch is a synchronous WriteFile for overlapped
// file handles. As a special case, two-pipe client operation
// sets fAsyncPipe FALSE and this routine then passes NULL
// for lpOverlapped.
//
BOOL
FASTCALL
WriteFileSynch(
HANDLE hFile,
LPVOID lpBuffer,
DWORD cbWrite,
LPDWORD lpNumberOfBytesWritten,
DWORD dwFileOffset,
LPOVERLAPPED lpO
)
{
BOOL Success;
lpO->OffsetHigh = 0;
lpO->Offset = dwFileOffset;
Success =
WriteFile(
hFile,
lpBuffer,
cbWrite,
lpNumberOfBytesWritten,
fAsyncPipe ? lpO : NULL
);
if ( ! Success ) {
if (ERROR_IO_PENDING == GetLastError()) {
Success =
GetOverlappedResult(
hFile,
lpO,
lpNumberOfBytesWritten,
TRUE
);
}
}
return Success;
}
BOOL
FASTCALL
ReadFileSynch(
HANDLE hFile,
LPVOID lpBuffer,
DWORD cbRead,
LPDWORD lpNumberOfBytesRead,
DWORD dwFileOffset,
LPOVERLAPPED lpO
)
{
BOOL Success;
lpO->OffsetHigh = 0;
lpO->Offset = dwFileOffset;
Success =
ReadFile(
hFile,
lpBuffer,
cbRead,
lpNumberOfBytesRead,
fAsyncPipe ? lpO : NULL
);
if ( ! Success ) {
if (ERROR_IO_PENDING == GetLastError()) {
Success =
GetOverlappedResult(
hFile,
lpO,
lpNumberOfBytesRead,
TRUE
);
}
}
return Success;
}
BOOL
FASTCALL
WriteConsoleWithColor(
HANDLE MyStdOut,
char *buffer,
DWORD cbBuffer,
CWCDATA *persist
)
{
DWORD cbWrite,
cbFill;
WORD color;
BOOL bAltColor,
bNewLine,
bCanColor = FALSE;
char *pCurLine,
*pEndOfLine,
*pPrevLine,
*pTemp;
CONSOLE_SCREEN_BUFFER_INFO conBufferInfo;
if ( persist->bLineContinues )
bNewLine = FALSE;
else
bNewLine = TRUE;
// Split buffer into individual lines
pCurLine = buffer;
while ( pCurLine < buffer + cbBuffer )
{
// Get console information
bCanColor = GetConsoleScreenBufferInfo( MyStdOut, &conBufferInfo );
// Find end of current line
pEndOfLine = pCurLine;
// Print out any beginning newlines/CR's -- this will avoid
// coloring large blocks of nothing associated with keywords
while ( pEndOfLine < buffer + cbBuffer &&
( *pEndOfLine == '\r' ||
*pEndOfLine == '\n' ) )
{
// New line
if ( !bNewLine )
{
bNewLine = TRUE;
// If this was a continuation line -- end it
if ( persist->bLineContinues )
{
persist->bLineContinues = FALSE;
// Check if we just ended a line that couldn't be parsed
// because of its size -- if so output warning
if ( persist->bLineTooLarge )
DisplayWarning( LINE_TOO_LONG );
// Otherwise check for keyword(s)
// and color if appropriate
else if ( bCanColor &&
pColorLine( persist->sLine,
persist->cbCurPos + 1,
conBufferInfo.wAttributes,
&color ) )
{
// If we were unable to get the cursor position when
// the line started we won't be able to color it now,
// but because we aren't printing any warning elsewhere
// if we can't get console info, we will just quietly
// not output color here
if ( 0xFF != persist->cLineBegin.X ||
0xFF != persist->cLineBegin.Y )
{
// Color in beginning portion of line (actually all of
// line up to current point gets colored to reduce
// calculations)
FillConsoleOutputAttribute( MyStdOut,
color,
( (conBufferInfo.dwCursorPosition.Y -
persist->cLineBegin.Y + 1) *
(conBufferInfo.srWindow.Right -
conBufferInfo.srWindow.Left) ),
persist->cLineBegin,
&cbFill );
}
}
}
}
pEndOfLine++;
}
// Print newline characters if some were found
if ( pEndOfLine > pCurLine )
{
if ( ! WriteFile(MyStdOut, pCurLine, (DWORD)(pEndOfLine - pCurLine), &cbWrite, NULL) )
{
// Bail out
return FALSE;
}
// Move line pointer
pCurLine = pEndOfLine;
}
// Get the line
while ( pEndOfLine < buffer + cbBuffer &&
*pEndOfLine != '\r' &&
*pEndOfLine != '\n' ) pEndOfLine++;
// If we got characters we are in a line
// Check it for keywords or add it to
// a continuation line and/or print it
if ( pEndOfLine > pCurLine )
{
bNewLine = FALSE;
// Point to last character
pEndOfLine--;
// Check for current console information
if ( !bCanColor )
{
// Couldn't get information -- handle might
// be redirected. Don't change colors
bAltColor = FALSE;
}
else if ( persist->bLineContinues )
{
// See if we have enough room to construct this new line
if ( !persist->bLineTooLarge &&
(DWORD)(pEndOfLine - pCurLine + 1) >=
(persist->cbLine - persist->cbCurPos) )
{
// Attempt to build a bigger buffer
pTemp = realloc( (PVOID)persist->sLine,
persist->cbLine + (pEndOfLine - pCurLine + 1) );
if ( NULL == pTemp )
{
persist->bLineTooLarge = TRUE;
}
else
{
persist->sLine = pTemp;
persist->cbLine += (DWORD)(pEndOfLine - pCurLine + 1);
}
}
// Add this piece to the line
if ( !persist->bLineTooLarge )
{
// Add new piece to line
memcpy( (PVOID)(persist->sLine + persist->cbCurPos + 1),
(PVOID)pCurLine,
(pEndOfLine - pCurLine + 1) );
// Point at new end of line
persist->cbCurPos += (DWORD)(pEndOfLine - pCurLine + 1);
}
// Don't color this line portion
bAltColor = FALSE;
}
// Check if line needs colored unless this is going
// to be a continued line (last line in buffer and
// does not end with a newline). We do not want
// to determine the color of the line until we
// have the complete thing
else if ( (char *)(pEndOfLine + 1) < (char *)(buffer + cbBuffer) )
{
// Parse line for keywords that will cause
// this line to show up in a different color
bAltColor = pColorLine( pCurLine,
(DWORD)(pEndOfLine - pCurLine + 1),
conBufferInfo.wAttributes,
&color );
}
else
{
bAltColor = FALSE;
}
if ( bAltColor )
{
// Change color for output of this line
SetConsoleTextAttribute( MyStdOut, color );
}
if ( ! WriteFile(MyStdOut, pCurLine, (DWORD)(pEndOfLine - pCurLine + 1), &cbWrite, NULL))
{
if ( bAltColor )
{
SetConsoleTextAttribute( MyStdOut, conBufferInfo.wAttributes );
}
// Bail out
return FALSE;
}
// Restore default colors if necessary
if ( bAltColor )
{
SetConsoleTextAttribute( MyStdOut, conBufferInfo.wAttributes );
}
// Point to the next line, saving off this line
// in case we need to store it in a continuation
// line
pPrevLine = pCurLine;
pCurLine = pEndOfLine + 1;
} // End only check line if there is one
}
// If the buffer did not end with a CR, and we are
// not already in a continuation, remember this line
if ( !bNewLine &&
pPrevLine <= pEndOfLine &&
!persist->bLineContinues )
{
persist->bLineContinues = TRUE;
persist->bLineTooLarge = FALSE;
if ( bCanColor )
persist->cLineBegin = conBufferInfo.dwCursorPosition;
else // Signal we were unable to obtain cursor location
{
persist->cLineBegin.X = 0xFF;
persist->cLineBegin.Y = 0xFF;
}
// See if we have enough room to construct this new line
if ( (DWORD)(pEndOfLine - pPrevLine + 1) >= persist->cbLine )
{
// Attempt to build a bigger buffer
pTemp = realloc( (PVOID)persist->sLine,
persist->cbLine + (pEndOfLine - pPrevLine + 1) );
if ( NULL == pTemp )
{
persist->bLineTooLarge = TRUE;
}
else
{
persist->sLine = pTemp;
persist->cbLine = (DWORD)(pEndOfLine - pPrevLine + 1);
}
}
// Store the beginning of the line
if ( !persist->bLineTooLarge )
{
// Add new piece to line
memcpy( (PVOID)persist->sLine,
(PVOID)pPrevLine,
(pEndOfLine - pPrevLine + 1) );
// Point at new end of line
persist->cbCurPos = (DWORD)(pEndOfLine - pPrevLine);
}
}
// Success
return TRUE;
}