Source code of Windows XP (NT5)
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.

1477 lines
39 KiB

  1. /******************************************************************************\
  2. * This is a part of the Microsoft Source Code Samples.
  3. * Copyright 1993 - 1997 Microsoft Corporation.
  4. * All rights reserved.
  5. * This source code is only intended as a supplement to
  6. * Microsoft Development Tools and/or WinHelp documentation.
  7. * See these sources for detailed information regarding the
  8. * Microsoft samples programs.
  9. \******************************************************************************/
  10. /*++
  11. Copyright 1993 - 1997 Microsoft Corporation
  12. Module Name:
  13. Remote.c
  14. Abstract:
  15. This module contains the main() entry point for Remote.
  16. Calls the Server or the Client depending on the first parameter.
  17. Author:
  18. Rajivendra Nath 2-Jan-1993
  19. Environment:
  20. Console App. User mode.
  21. Revision History:
  22. --*/
  23. #include <windows.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include "Remote.h"
  27. char HostName[HOSTNAMELEN];
  28. char* ChildCmd;
  29. char* PipeName;
  30. char* ServerName;
  31. char * DaclNames[ MAX_DACL_NAMES ];
  32. DWORD DaclNameCount = 0;
  33. char * DaclDenyNames[ MAX_DACL_NAMES ];
  34. DWORD DaclDenyNameCount = 0 ;
  35. HANDLE MyStdOut;
  36. HANDLE hAttachedProcess = INVALID_HANDLE_VALUE;
  37. HANDLE hAttachedWriteChildStdIn = INVALID_HANDLE_VALUE;
  38. HANDLE hAttachedReadChildStdOut = INVALID_HANDLE_VALUE;
  39. BOOL IsAdvertise;
  40. DWORD ClientToServerFlag;
  41. BOOL bForceTwoPipes;
  42. typedef struct _tagKeywordAndColor
  43. {
  44. char *szKeyword;
  45. WORD color;
  46. struct _tagKeywordAndColor *next;
  47. } KeywordAndColor;
  48. KeywordAndColor *pKeyColors;
  49. char* ColorList[]={"black" ,"blue" ,"green" ,"cyan" ,"red" ,"purple" ,"yellow" ,"white",
  50. "lblack","lblue","lgreen","lcyan","lred","lpurple","lyellow","lwhite"};
  51. typedef enum { LINE_TOO_LONG } WARNING_MESSAGE;
  52. VOID
  53. DisplayWarning(
  54. WARNING_MESSAGE warn
  55. );
  56. WORD
  57. GetColorNum(
  58. char* color
  59. );
  60. VOID
  61. SetColor(
  62. WORD attr
  63. );
  64. BOOL
  65. GetColorFromBuffer(
  66. char **ppBuffer,
  67. char *pBufferInvalid,
  68. WORD *color,
  69. BOOL bStayOnLine
  70. );
  71. VOID
  72. AssocKeysAndColors(
  73. KeywordAndColor **ppKeyAndColors,
  74. char *szFileName
  75. );
  76. BOOL
  77. GetNextConnectInfo(
  78. char** SrvName,
  79. char** PipeName
  80. );
  81. CONSOLE_SCREEN_BUFFER_INFO csbiOriginal;
  82. int
  83. __cdecl
  84. main(
  85. int argc,
  86. char** argv
  87. )
  88. {
  89. WORD RunType; // Server or Client end of Remote
  90. DWORD len=HOSTNAMELEN;
  91. int i, FirstArg;
  92. char sTitle[120]; // New Title
  93. char orgTitle[200]; // Old Title
  94. BOOL bPromptForArgs=FALSE; // Is /P option
  95. WORD wAttrib; // Console Attributes
  96. int privacy; // Allows exposing or hidng sessions to remote /q
  97. BOOL Deny ;
  98. GetComputerName((LPTSTR)HostName,&len);
  99. MyStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
  100. if (GetConsoleScreenBufferInfo(MyStdOut,&csbiOriginal)) {
  101. wAttrib = csbiOriginal.wAttributes;
  102. if (!GetConsoleTitle(orgTitle,sizeof(orgTitle))) {
  103. orgTitle[0] = 0;
  104. }
  105. } else {
  106. //
  107. // either stdout is a pipe, or it wasn't opened for
  108. // GENERIC_READ along with GENERIC_WRITE, in which
  109. // case our color manipulations will work so we need
  110. // to pick default colors.
  111. //
  112. wAttrib = FOREGROUND_GREEN |
  113. FOREGROUND_INTENSITY;
  114. orgTitle[0] = 0;
  115. }
  116. privacy = PRIVACY_DEFAULT;
  117. pKeyColors = NULL;
  118. //
  119. // Parameter Processing
  120. //
  121. // For Server:
  122. // Remote /S <Executable> <PipeName> [Optional Params]
  123. //
  124. // For Client:
  125. // Remote /C <Server Name> <PipeName> [Optional Params]
  126. // or
  127. // Remote /P
  128. // This will loop continously prompting for different
  129. // Servers and Pipename
  130. if ((argc<2)||((argv[1][0]!='/')&&(argv[1][0]!='-')))
  131. {
  132. DisplayServerHlp();
  133. DisplayClientHlp();
  134. return(1);
  135. }
  136. switch(argv[1][1])
  137. {
  138. case 'c':
  139. case 'C':
  140. //
  141. // Is Client End of Remote
  142. //
  143. if ((argc<4)||((argv[1][0]!='/')&&(argv[1][0]!='-')))
  144. {
  145. DisplayServerHlp();
  146. DisplayClientHlp();
  147. return(1);
  148. }
  149. ServerName=argv[2];
  150. PipeName=argv[3];
  151. FirstArg=4;
  152. RunType=RUNTYPE_CLIENT;
  153. break;
  154. case 'q':
  155. case 'Q':
  156. //
  157. // Query for possible conexions
  158. //
  159. if ((argc != 3)||((argv[1][0]!='/')&&(argv[1][0]!='-')))
  160. {
  161. DisplayServerHlp();
  162. DisplayClientHlp();
  163. return(1);
  164. }
  165. QueryRemotePipes(argv[2]); // Send ServerName as a param
  166. return(0);
  167. case 'p':
  168. case 'P':
  169. //
  170. // Is Client End of Remote
  171. //
  172. bPromptForArgs=TRUE;
  173. RunType=RUNTYPE_CLIENT;
  174. FirstArg=2;
  175. break;
  176. case 's':
  177. case 'S':
  178. //
  179. // Is Server End of Remote
  180. //
  181. if ((argc<4)||((argv[1][0]!='/')&&(argv[1][0]!='-')))
  182. {
  183. DisplayServerHlp();
  184. DisplayClientHlp();
  185. return(1);
  186. }
  187. ChildCmd=argv[2];
  188. PipeName=argv[3];
  189. FirstArg=4;
  190. RunType=REMOTE_SERVER;
  191. break;
  192. case 'a':
  193. case 'A':
  194. //
  195. // Is Server End of Remote Attaching to existing process.
  196. //
  197. if ((argc<7)||((argv[1][0]!='/')&&(argv[1][0]!='-')))
  198. {
  199. DisplayServerHlp();
  200. DisplayClientHlp();
  201. return(1);
  202. }
  203. hAttachedProcess = (HANDLE)IntToPtr(atoi(argv[2]));
  204. hAttachedWriteChildStdIn = (HANDLE)IntToPtr(atoi(argv[3]));
  205. hAttachedReadChildStdOut = (HANDLE)IntToPtr(atoi(argv[4]));
  206. ChildCmd=argv[5]; // for display only
  207. PipeName=argv[6];
  208. FirstArg=7;
  209. RunType = REMOTE_SERVER;
  210. privacy = PRIVACY_VISIBLE; // presumably ntsd/*kd
  211. break;
  212. default:
  213. DisplayServerHlp();
  214. DisplayClientHlp();
  215. return(1);
  216. }
  217. if (RunType==REMOTE_SERVER)
  218. {
  219. //
  220. // Base Name of Executable
  221. // For setting the title
  222. //
  223. char *tcmd=ChildCmd;
  224. while ((*tcmd!=' ') && (*tcmd!=0)) tcmd++;
  225. while ((tcmd > ChildCmd) && (*tcmd!='\\')) tcmd--;
  226. if (*tcmd=='\\') tcmd++;
  227. sprintf(sTitle,"%-41.40s [Remote /C %s \"%.30s\"]",tcmd,HostName,PipeName);
  228. }
  229. //
  230. //Process Common (Optional) Parameters
  231. //
  232. for (i=FirstArg;i<argc;i++)
  233. {
  234. if ((argv[i][0]!='/')&&(argv[i][0]!='-'))
  235. {
  236. printf("Invalid parameter %s:Ignoring\n",argv[i]);
  237. continue;
  238. }
  239. switch(argv[i][1])
  240. {
  241. case 'l': // Only Valid for client End
  242. case 'L': // Max Number of Lines to recieve from Server
  243. i++;
  244. if (i>=argc)
  245. {
  246. printf("Incomplete Param %s..Ignoring\n",argv[i-1]);
  247. break;
  248. }
  249. LinesToSend=(DWORD)atoi(argv[i])+1;
  250. break;
  251. case 't': // Title to be set instead of the default
  252. case 'T':
  253. i++;
  254. if (i>=argc)
  255. {
  256. printf("Incomplete Param %s..Ignoring\n",argv[i-1]);
  257. break;
  258. }
  259. sprintf(sTitle,"%s",argv[i]);
  260. break;
  261. case 'b': // Background color
  262. case 'B':
  263. i++;
  264. if (i>=argc)
  265. {
  266. printf("Incomplete Param %s..Ignoring\n",argv[i-1]);
  267. break;
  268. }
  269. {
  270. WORD col=GetColorNum(argv[i]);
  271. if (col!=0xffff)
  272. {
  273. wAttrib=col<<4|(wAttrib&0x000f);
  274. }
  275. break;
  276. }
  277. case 'f': // Foreground color
  278. case 'F':
  279. i++;
  280. if (i>=argc)
  281. {
  282. printf("Incomplete Param %s..Ignoring\n",argv[i-1]);
  283. break;
  284. }
  285. {
  286. WORD col=GetColorNum(argv[i]);
  287. if (col!=0xffff)
  288. {
  289. wAttrib=col|(wAttrib&0x00f0);
  290. }
  291. break;
  292. }
  293. case 'k': // Color "keyword" lines
  294. case 'K':
  295. i++;
  296. // Currently only support client-side coloring
  297. if (RunType==REMOTE_SERVER)
  298. {
  299. printf("%s invalid on server side..Ignoring\n",argv[i-1]);
  300. break;
  301. }
  302. else if (i>=argc)
  303. {
  304. printf("Incomplete Param %s..Ignoring\n",argv[i-1]);
  305. break;
  306. }
  307. else
  308. {
  309. AssocKeysAndColors( &pKeyColors, argv[i] );
  310. break;
  311. }
  312. case 'v':
  313. case 'V':
  314. privacy = PRIVACY_VISIBLE;
  315. break;
  316. case '-':
  317. if( (argv[i][2] == 'v')
  318. || (argv[i][2] == 'V'))
  319. privacy = PRIVACY_NOT_VISIBLE;
  320. else
  321. printf("Unknown Parameter=%s %s\n",argv[i-1],argv[i]);
  322. break;
  323. case 'q':
  324. case 'Q':
  325. ClientToServerFlag|=0x80000000;
  326. break;
  327. case 'u':
  328. case 'U':
  329. if ( (argv[i][2] == 'd') ||
  330. (argv[i][2] == 'D' ) )
  331. {
  332. Deny = TRUE ;
  333. }
  334. else
  335. {
  336. Deny = FALSE ;
  337. }
  338. i++ ;
  339. if ( i >= argc )
  340. {
  341. printf( "Incomplete Param %s..Ignoring\n", argv[i-1] );
  342. break;
  343. }
  344. if ( Deny )
  345. {
  346. if (DaclDenyNameCount == MAX_DACL_NAMES )
  347. {
  348. printf("Too many names specified (max %d). Ignoring user %s\n",
  349. MAX_DACL_NAMES, argv[i] );
  350. break;
  351. }
  352. DaclDenyNames[ DaclDenyNameCount++ ] = argv[i];
  353. }
  354. else
  355. {
  356. if (DaclNameCount == MAX_DACL_NAMES )
  357. {
  358. printf("Too many names specified (max %d). Ignoring user %s\n",
  359. MAX_DACL_NAMES, argv[i] );
  360. break;
  361. }
  362. DaclNames[ DaclNameCount++ ] = argv[i];
  363. }
  364. break;
  365. case '2':
  366. bForceTwoPipes = TRUE;
  367. break;
  368. default:
  369. printf("Unknown Parameter=%s %s\n",argv[i-1],argv[i]);
  370. break;
  371. }
  372. }
  373. //
  374. //Now Set various Parameters
  375. //
  376. //
  377. //Colors
  378. //
  379. SetColor(wAttrib);
  380. if (RunType==RUNTYPE_CLIENT)
  381. {
  382. BOOL done=FALSE;
  383. BOOL gotinfo;
  384. //
  385. // Set Client end defaults and start client
  386. //
  387. while(!done)
  388. {
  389. if (!bPromptForArgs ||
  390. (gotinfo = GetNextConnectInfo(&ServerName,&PipeName))
  391. )
  392. {
  393. sprintf(sTitle,"Remote /C %s \"%s\"",ServerName,PipeName);
  394. SetConsoleTitle(sTitle);
  395. //
  396. // Start Client (Client.C)
  397. //
  398. Client(ServerName,PipeName);
  399. }
  400. done = !bPromptForArgs || !gotinfo;
  401. }
  402. }
  403. if (RunType==REMOTE_SERVER)
  404. {
  405. if (privacy == PRIVACY_VISIBLE ||
  406. (privacy == PRIVACY_DEFAULT && IsKdString(ChildCmd))) {
  407. strcat(sTitle, " visible");
  408. IsAdvertise = TRUE;
  409. }
  410. SetConsoleTitle(sTitle);
  411. i = OverlappedServer(ChildCmd, PipeName);
  412. }
  413. //
  414. //Reset Colors
  415. //
  416. SetColor(csbiOriginal.wAttributes);
  417. SetConsoleTitle(orgTitle);
  418. return i;
  419. }
  420. /*************************************************************/
  421. VOID
  422. ErrorExit(
  423. char* str
  424. )
  425. {
  426. extern PSZ pszPipeName;
  427. DWORD dwErr;
  428. dwErr = GetLastError();
  429. printf("REMOTE error %d: %s\n", dwErr, str);
  430. #if DBG
  431. {
  432. char szMsg[1024];
  433. sprintf(szMsg, "REMOTE error %d: %s\n", dwErr, str);
  434. OutputDebugString(szMsg);
  435. if (pszPipeName) { // ad-hoc: if server
  436. if (IsDebuggerPresent()) {
  437. DebugBreak();
  438. }
  439. }
  440. }
  441. #endif
  442. exit(1);
  443. }
  444. /*************************************************************/
  445. VOID
  446. DisplayClientHlp()
  447. {
  448. printf("\n"
  449. " To Start the CLIENT end of REMOTE\n"
  450. " ---------------------------------\n"
  451. " Syntax : REMOTE /C <ServerName> \"<Unique Id>\" [Param]\n"
  452. " Example1: REMOTE /C %s imbroglio\n"
  453. " This would connect to a server session on %s with Id\n"
  454. " \"imbroglio\" if there is a REMOTE /S <\"Cmd\"> imbroglio\n"
  455. " running on %s.\n\n"
  456. " Example2: REMOTE /C %s \"name with spaces\"\n"
  457. " This would connect to a server session on %s with Id\n"
  458. " \"name with spaces\" if there is a REMOTE /S <\"Cmd\"> \"name with spaces\"\n"
  459. " running on %s.\n\n"
  460. " To Exit: %cQ (Leaves the Remote Server Running)\n"
  461. " [Param]: /L <# of Lines to Get>\n"
  462. " [Param]: /F <Foreground color eg blue, lred..>\n"
  463. " [Param]: /K <Set keywords and colors from file>\n"
  464. " [Param]: /B <Background color eg cyan, lwhite..>\n"
  465. "\n"
  466. " Keywords And Colors File Format\n"
  467. " -------------------------------\n"
  468. " <KEYWORDs - CASE INSENSITIVE>\n"
  469. " <FOREGROUND>[, <BACKGROUND>]\n"
  470. " ...\n"
  471. " EX:\n"
  472. " ERROR\n"
  473. " black, lred\n"
  474. " WARNING\n"
  475. " lblue\n"
  476. " COLOR THIS LINE\n"
  477. " lgreen\n"
  478. "\n"
  479. " To Query the visible sessions on a server\n"
  480. " -----------------------------------------\n"
  481. " Syntax: REMOTE /Q %s\n"
  482. " This would retrieve the available <Unique Id>s\n"
  483. " visible connections on the computer named %s.\n"
  484. "\n",
  485. HostName, HostName, HostName,
  486. HostName, HostName, HostName,
  487. COMMANDCHAR, HostName, HostName);
  488. }
  489. /*************************************************************/
  490. VOID
  491. DisplayServerHlp()
  492. {
  493. printf("\n"
  494. " To Start the SERVER end of REMOTE\n"
  495. " ---------------------------------\n"
  496. " Syntax : REMOTE /S <\"Cmd\"> <Unique Id> [Param]\n"
  497. " Example1: REMOTE /S \"i386kd -v\" imbroglio\n"
  498. " To interact with this \"Cmd\" from some other machine,\n"
  499. " start the client end using: REMOTE /C %s imbroglio\n\n"
  500. " Example2: REMOTE /S \"i386kd -v\" \"name with spaces\"\n"
  501. " start the client end using: REMOTE /C %s \"name with spaces\"\n\n"
  502. " To Exit: %cK \n"
  503. " [Param]: /F <Foreground color eg yellow, black..>\n"
  504. " [Param]: /B <Background color eg lblue, white..>\n"
  505. " [Param]: /U username or groupname\n"
  506. " specifies which users or groups may connect\n"
  507. " may be specified more than once, e.g\n"
  508. " /U user1 /U group2 /U user2\n"
  509. " [Param]: /UD username or groupname\n"
  510. " specifically denies access to that user or group\n"
  511. " [Param]: /V Makes this session visible to remote /Q\n"
  512. " [Param]: /-V Hides this session from remote /q (invisible)\n"
  513. " By default, if \"Cmd\" looks like a debugger,\n"
  514. " the session is visible, otherwise not\n"
  515. "\n",
  516. HostName, HostName, COMMANDCHAR);
  517. }
  518. VOID
  519. DisplayWarning(
  520. WARNING_MESSAGE warn
  521. )
  522. {
  523. switch ( warn )
  524. {
  525. case LINE_TOO_LONG:
  526. printf( "\n[REMOTE: WARNING: LINE TOO LONG TO PARSE FOR COLOR KEYWORDS]\n" );
  527. break;
  528. default:
  529. printf( "\n[REMOTE: WARNING: UNSPECIFIED PROBLEM COLORING LINE]\n" );
  530. }
  531. }
  532. WORD
  533. GetColorNum(
  534. char *color
  535. )
  536. {
  537. WORD i;
  538. _strlwr(color);
  539. for (i=0;i<16;i++)
  540. {
  541. if (strcmp(ColorList[i],color)==0)
  542. {
  543. return(i);
  544. }
  545. }
  546. return ((WORD)atoi(color));
  547. }
  548. VOID
  549. SetColor(
  550. WORD attr
  551. )
  552. {
  553. COORD origin={0,0};
  554. DWORD dwrite;
  555. FillConsoleOutputAttribute
  556. (
  557. MyStdOut,attr,csbiOriginal.dwSize.
  558. X*csbiOriginal.dwSize.Y,origin,&dwrite
  559. );
  560. SetConsoleTextAttribute(MyStdOut,attr);
  561. }
  562. BOOL
  563. pColorLine(
  564. char *sLine,
  565. int cbLine,
  566. WORD wDefaultColor,
  567. WORD *color
  568. )
  569. {
  570. KeywordAndColor *pCurKeyColor = NULL;
  571. char *pString1;
  572. int cbCmpString;
  573. pCurKeyColor = pKeyColors;
  574. while ( pCurKeyColor )
  575. {
  576. cbCmpString = strlen( pCurKeyColor->szKeyword );
  577. pString1 = sLine;
  578. // Need to do case-insensitive compare
  579. while ( pString1 <= sLine + cbLine - cbCmpString )
  580. {
  581. if ( !_memicmp( (PVOID)pString1,
  582. (PVOID)pCurKeyColor->szKeyword,
  583. cbCmpString ) )
  584. {
  585. *color = pCurKeyColor->color;
  586. // Check if we are to use default background color
  587. if ( (0xfff0 & *color) == 0xfff0 )
  588. *color = (wDefaultColor & 0x00f0) |
  589. (*color & 0x000f);
  590. return TRUE;
  591. }
  592. pString1++;
  593. }
  594. // Next keyword/color combination
  595. pCurKeyColor = pCurKeyColor->next;
  596. }
  597. return FALSE;
  598. }
  599. BOOL
  600. pWantColorLines(
  601. VOID
  602. )
  603. {
  604. return ( NULL != pKeyColors );
  605. }
  606. VOID
  607. AssocKeysAndColors(
  608. KeywordAndColor **ppKeyColors,
  609. char *szFileName
  610. )
  611. {
  612. char szPathName[_MAX_PATH],
  613. *szSimpleName;
  614. char *buffer,
  615. *pBegin,
  616. *pEnd;
  617. USHORT usForeColor,
  618. usBackColor;
  619. KeywordAndColor *pCurKeyColor,
  620. *pNextKeyColor;
  621. HANDLE hFile;
  622. WIN32_FIND_DATA wfdInfo;
  623. DWORD dwBytesRead;
  624. // Locate the specified file somewhere in the path
  625. if ( !SearchPath( NULL,
  626. szFileName,
  627. NULL,
  628. _MAX_PATH,
  629. szPathName,
  630. &szSimpleName ) )
  631. {
  632. fprintf( stderr, "Error locating keyword/color file \"%s\"!\n",
  633. szFileName );
  634. return;
  635. }
  636. // Get the size of the file so we can read all of it in
  637. hFile = FindFirstFile( szPathName, &wfdInfo );
  638. if ( INVALID_HANDLE_VALUE == hFile )
  639. {
  640. fprintf( stderr, "Error locating keyword/color file \"%s\"!\n",
  641. szPathName );
  642. return;
  643. }
  644. FindClose( hFile );
  645. hFile = INVALID_HANDLE_VALUE;
  646. if ( wfdInfo.nFileSizeLow < 5 ||
  647. wfdInfo.nFileSizeHigh )
  648. {
  649. fprintf( stderr, "Invalid keyword/color file: %s!\n",
  650. szPathName );
  651. return;
  652. }
  653. // Allocate memory to store file contents
  654. buffer = malloc( wfdInfo.nFileSizeLow );
  655. if ( NULL == buffer )
  656. {
  657. fprintf( stderr, "Error! Unable to allocate memory to read in keyword/color file!\n" );
  658. return;
  659. }
  660. // Attempt to open the given file-name
  661. hFile = CreateFile( szPathName,
  662. GENERIC_READ,
  663. FILE_SHARE_READ,
  664. NULL,
  665. OPEN_EXISTING,
  666. FILE_FLAG_SEQUENTIAL_SCAN,
  667. NULL );
  668. if ( INVALID_HANDLE_VALUE == hFile )
  669. {
  670. fprintf( stderr, "Error opening keyword/color file %s!\n",
  671. szPathName );
  672. return;
  673. }
  674. // Attempt to read in the contents of the file
  675. ReadFile( hFile,
  676. buffer,
  677. wfdInfo.nFileSizeLow,
  678. &dwBytesRead,
  679. NULL );
  680. CloseHandle( hFile );
  681. if ( dwBytesRead != wfdInfo.nFileSizeLow )
  682. {
  683. fprintf( stderr, "Error reading keyword/color file: %s!\n",
  684. szPathName );
  685. free( buffer );
  686. return;
  687. }
  688. // Parse contents of file, storing keyword(s) and color combinations
  689. pBegin = buffer;
  690. pCurKeyColor = NULL;
  691. while ( pBegin < buffer + dwBytesRead )
  692. {
  693. // Skip any newline/CR at beginning
  694. while ( pBegin < buffer + dwBytesRead &&
  695. ( *pBegin == '\r' ||
  696. *pBegin == '\n' ) ) pBegin++;
  697. if ( pBegin >= buffer + dwBytesRead )
  698. continue;
  699. pEnd = pBegin;
  700. while ( pEnd < buffer + dwBytesRead &&
  701. *pEnd != '\r' ) pEnd++;
  702. // point at last character
  703. pEnd--;
  704. // Add new KeywordAndColor member to list
  705. if ( NULL == pCurKeyColor )
  706. {
  707. *ppKeyColors = pCurKeyColor = malloc( sizeof( KeywordAndColor ) );
  708. }
  709. else
  710. {
  711. pCurKeyColor->next = malloc( sizeof( KeywordAndColor ) );
  712. pCurKeyColor = pCurKeyColor->next;
  713. }
  714. // Verify we allocated memory for another list member
  715. if ( NULL == pCurKeyColor )
  716. {
  717. fprintf( stderr, "Error allocating memory for keyword/color storage!\n" );
  718. // Cleanup any we did create
  719. while ( *ppKeyColors )
  720. {
  721. pCurKeyColor = ((KeywordAndColor *)*ppKeyColors)->next;
  722. if ( ((KeywordAndColor *)*ppKeyColors)->szKeyword )
  723. free( ((KeywordAndColor *)*ppKeyColors)->szKeyword );
  724. free( (KeywordAndColor *)*ppKeyColors );
  725. (KeywordAndColor *)*ppKeyColors = pCurKeyColor;
  726. }
  727. return;
  728. }
  729. // This is now the last member of the list
  730. pCurKeyColor->next = NULL;
  731. // Already have keyword(s) -- allocate room for it
  732. pCurKeyColor->szKeyword = malloc( pEnd - pBegin + 2 );
  733. if ( NULL == pCurKeyColor->szKeyword )
  734. {
  735. fprintf( stderr, "Error allocating memory for keyword/color storage!\n" );
  736. // Cleanup any we did create
  737. while ( *ppKeyColors )
  738. {
  739. pCurKeyColor = ((KeywordAndColor *)*ppKeyColors)->next;
  740. if ( ((KeywordAndColor *)*ppKeyColors)->szKeyword )
  741. free( ((KeywordAndColor *)*ppKeyColors)->szKeyword );
  742. free( (KeywordAndColor *)*ppKeyColors );
  743. *ppKeyColors = pCurKeyColor;
  744. }
  745. return;
  746. }
  747. // Store keyword(s)
  748. memcpy( (PVOID)pCurKeyColor->szKeyword, (PVOID)pBegin, pEnd-pBegin+1 );
  749. pCurKeyColor->szKeyword[pEnd-pBegin+1] = '\0';
  750. pBegin = pEnd + 1;
  751. // Get color information
  752. if ( GetColorFromBuffer( &pBegin,
  753. (char *)(buffer + dwBytesRead),
  754. &usForeColor,
  755. FALSE ) )
  756. {
  757. // Check if there is a comma following
  758. while ( pBegin < buffer + dwBytesRead &&
  759. *pBegin != ',' &&
  760. *pBegin != '\r' ) pBegin++;
  761. if ( *pBegin == ',' )
  762. {
  763. pBegin++;
  764. if ( GetColorFromBuffer( &pBegin,
  765. (char *)(buffer + dwBytesRead),
  766. &usBackColor,
  767. TRUE ) )
  768. goto noError;
  769. }
  770. else
  771. {
  772. // Default to current background color
  773. usBackColor = 0xffff;
  774. goto noError;
  775. }
  776. }
  777. // ERROR
  778. fprintf( stderr, "Invalid color information for: %s\n", pCurKeyColor->szKeyword );
  779. // We will leave any previous entries but delete this one
  780. pNextKeyColor = *ppKeyColors;
  781. if ( pNextKeyColor == pCurKeyColor )
  782. {
  783. free( pCurKeyColor );
  784. *ppKeyColors = NULL;
  785. }
  786. else
  787. {
  788. while ( pCurKeyColor != pNextKeyColor->next )
  789. pNextKeyColor = pNextKeyColor->next;
  790. free ( pCurKeyColor );
  791. pNextKeyColor->next = NULL;
  792. }
  793. return;
  794. noError:
  795. // Store color information
  796. if ( usBackColor == 0xffff )
  797. pCurKeyColor->color = 0xfff0 |
  798. (usForeColor & 0x0f);
  799. else
  800. pCurKeyColor->color = ((usBackColor << 4) & 0x00f0) |
  801. (usForeColor & 0x0f );
  802. }
  803. }
  804. BOOL
  805. GetColorFromBuffer(
  806. char **ppBuffer,
  807. char *pBufferInvalid,
  808. WORD *color,
  809. BOOL bStayOnLine
  810. )
  811. {
  812. char *pBegin,
  813. *pEnd,
  814. temp;
  815. pBegin = *ppBuffer;
  816. if ( bStayOnLine )
  817. {
  818. // Skip to the next character (on this line)
  819. while ( pBegin < pBufferInvalid &&
  820. !isalnum( (int)*pBegin ) &&
  821. *pBegin != '\r' ) pBegin++;
  822. }
  823. else
  824. {
  825. // Skip to next character (in buffer)
  826. while ( pBegin < pBufferInvalid &&
  827. !isalnum( (int)*pBegin ) ) pBegin++;
  828. }
  829. if ( pBegin >= pBufferInvalid ||
  830. *pBegin == '\r' )
  831. return FALSE;
  832. // Read in color
  833. pEnd = pBegin + 1;
  834. while ( isalnum( (int)*pEnd ) &&
  835. *pEnd != ',' ) pEnd++;
  836. temp = *pEnd;
  837. *pEnd = '\0';
  838. *color = GetColorNum( pBegin );
  839. *pEnd = temp;
  840. // Use same valid color check as used for foreground/background
  841. if ( *color == 0xffff )
  842. return FALSE;
  843. // Move the pointer we were given to next unread portion
  844. *ppBuffer = pEnd;
  845. return TRUE;
  846. }
  847. BOOL
  848. GetNextConnectInfo(
  849. char** SrvName,
  850. char** PipeName
  851. )
  852. {
  853. char *s;
  854. static char szServerName[64];
  855. static char szPipeName[32];
  856. try
  857. {
  858. ZeroMemory(szServerName,64);
  859. ZeroMemory(szPipeName,32);
  860. SetConsoleTitle("Remote - Prompting for next Connection");
  861. printf("Debugger machine (server): ");
  862. fflush(stdout);
  863. if (((*SrvName=gets(szServerName))==NULL)||
  864. (strlen(szServerName)==0))
  865. {
  866. return(FALSE);
  867. }
  868. if (szServerName[0] == COMMANDCHAR &&
  869. (szServerName[1] == 'q' || szServerName[1] == 'Q')
  870. )
  871. {
  872. return(FALSE);
  873. }
  874. if (s = strchr( szServerName, ' ' )) {
  875. *s++ = '\0';
  876. while (*s == ' ') {
  877. s += 1;
  878. }
  879. *PipeName=strcpy(szPipeName, s);
  880. printf(szPipeName);
  881. fflush(stdout);
  882. }
  883. if (strlen(szPipeName) == 0) {
  884. printf("Target machine (pipe) : ");
  885. fflush(stdout);
  886. if ((*PipeName=gets(szPipeName))==NULL)
  887. {
  888. return(FALSE);
  889. }
  890. }
  891. if (s = strchr(szPipeName, ' ')) {
  892. *s++ = '\0';
  893. }
  894. if (szPipeName[0] == COMMANDCHAR &&
  895. (szPipeName[1] == 'q' || szPipeName[1] == 'Q')
  896. )
  897. {
  898. return(FALSE);
  899. }
  900. printf("\n\n");
  901. }
  902. except(EXCEPTION_EXECUTE_HANDLER)
  903. {
  904. return(FALSE); // Ignore exceptions
  905. }
  906. return(TRUE);
  907. }
  908. /*************************************************************/
  909. VOID
  910. Errormsg(
  911. char* str
  912. )
  913. {
  914. printf("Error (%d) - %s\n",GetLastError(),str);
  915. }
  916. /*************************************************************/
  917. BOOL
  918. IsKdString(
  919. char* string
  920. )
  921. {
  922. char* start;
  923. //
  924. // some heuristic for uninvented yet platforms
  925. // if the first word has "kd" in it ok
  926. //
  927. if( ((start = strstr(string, "kd")) != NULL)
  928. || ((start = strstr(string, "dbg")) != NULL)
  929. || ((start = strstr(string, "remoteds")) != NULL)
  930. || ((start = strstr(string, "ntsd")) != NULL)
  931. || ((start = strstr(string, "cdb")) != NULL) )
  932. {
  933. // is it in the first word?
  934. while(--start > string)
  935. {
  936. if((*start == ' ') || (*start == '\t'))
  937. {
  938. while(--start > string)
  939. if((*start != '\t') || (*start != ' '))
  940. return(FALSE);
  941. }
  942. }
  943. return TRUE;
  944. }
  945. return(FALSE);
  946. }
  947. //
  948. // WriteFileSynch is a synchronous WriteFile for overlapped
  949. // file handles. As a special case, two-pipe client operation
  950. // sets fAsyncPipe FALSE and this routine then passes NULL
  951. // for lpOverlapped.
  952. //
  953. BOOL
  954. FASTCALL
  955. WriteFileSynch(
  956. HANDLE hFile,
  957. LPVOID lpBuffer,
  958. DWORD cbWrite,
  959. LPDWORD lpNumberOfBytesWritten,
  960. DWORD dwFileOffset,
  961. LPOVERLAPPED lpO
  962. )
  963. {
  964. BOOL Success;
  965. lpO->OffsetHigh = 0;
  966. lpO->Offset = dwFileOffset;
  967. Success =
  968. WriteFile(
  969. hFile,
  970. lpBuffer,
  971. cbWrite,
  972. lpNumberOfBytesWritten,
  973. fAsyncPipe ? lpO : NULL
  974. );
  975. if ( ! Success ) {
  976. if (ERROR_IO_PENDING == GetLastError()) {
  977. Success =
  978. GetOverlappedResult(
  979. hFile,
  980. lpO,
  981. lpNumberOfBytesWritten,
  982. TRUE
  983. );
  984. }
  985. }
  986. return Success;
  987. }
  988. BOOL
  989. FASTCALL
  990. ReadFileSynch(
  991. HANDLE hFile,
  992. LPVOID lpBuffer,
  993. DWORD cbRead,
  994. LPDWORD lpNumberOfBytesRead,
  995. DWORD dwFileOffset,
  996. LPOVERLAPPED lpO
  997. )
  998. {
  999. BOOL Success;
  1000. lpO->OffsetHigh = 0;
  1001. lpO->Offset = dwFileOffset;
  1002. Success =
  1003. ReadFile(
  1004. hFile,
  1005. lpBuffer,
  1006. cbRead,
  1007. lpNumberOfBytesRead,
  1008. fAsyncPipe ? lpO : NULL
  1009. );
  1010. if ( ! Success ) {
  1011. if (ERROR_IO_PENDING == GetLastError()) {
  1012. Success =
  1013. GetOverlappedResult(
  1014. hFile,
  1015. lpO,
  1016. lpNumberOfBytesRead,
  1017. TRUE
  1018. );
  1019. }
  1020. }
  1021. return Success;
  1022. }
  1023. BOOL
  1024. FASTCALL
  1025. WriteConsoleWithColor(
  1026. HANDLE MyStdOut,
  1027. char *buffer,
  1028. DWORD cbBuffer,
  1029. CWCDATA *persist
  1030. )
  1031. {
  1032. DWORD cbWrite,
  1033. cbFill;
  1034. WORD color;
  1035. BOOL bAltColor,
  1036. bNewLine,
  1037. bCanColor;
  1038. char *pCurLine,
  1039. *pEndOfLine,
  1040. *pPrevLine,
  1041. *pTemp;
  1042. CONSOLE_SCREEN_BUFFER_INFO conBufferInfo;
  1043. if ( persist->bLineContinues )
  1044. bNewLine = FALSE;
  1045. else
  1046. bNewLine = TRUE;
  1047. // Split buffer into individual lines
  1048. pCurLine = buffer;
  1049. while ( pCurLine < buffer + cbBuffer )
  1050. {
  1051. // Get console information
  1052. bCanColor = GetConsoleScreenBufferInfo( MyStdOut, &conBufferInfo );
  1053. // Find end of current line
  1054. pEndOfLine = pCurLine;
  1055. // Print out any beginning newlines/CR's -- this will avoid
  1056. // coloring large blocks of nothing associated with keywords
  1057. while ( pEndOfLine < buffer + cbBuffer &&
  1058. ( *pEndOfLine == '\r' ||
  1059. *pEndOfLine == '\n' ) )
  1060. {
  1061. // New line
  1062. if ( !bNewLine )
  1063. {
  1064. bNewLine = TRUE;
  1065. // If this was a continuation line -- end it
  1066. if ( persist->bLineContinues )
  1067. {
  1068. persist->bLineContinues = FALSE;
  1069. // Check if we just ended a line that couldn't be parsed
  1070. // because of its size -- if so output warning
  1071. if ( persist->bLineTooLarge )
  1072. DisplayWarning( LINE_TOO_LONG );
  1073. // Otherwise check for keyword(s)
  1074. // and color if appropriate
  1075. else if ( bCanColor &&
  1076. pColorLine( persist->sLine,
  1077. persist->cbCurPos + 1,
  1078. conBufferInfo.wAttributes,
  1079. &color ) )
  1080. {
  1081. // If we were unable to get the cursor position when
  1082. // the line started we won't be able to color it now,
  1083. // but because we aren't printing any warning elsewhere
  1084. // if we can't get console info, we will just quietly
  1085. // not output color here
  1086. if ( 0xFF != persist->cLineBegin.X ||
  1087. 0xFF != persist->cLineBegin.Y )
  1088. {
  1089. // Color in beginning portion of line (actually all of
  1090. // line up to current point gets colored to reduce
  1091. // calculations)
  1092. FillConsoleOutputAttribute( MyStdOut,
  1093. color,
  1094. ( (conBufferInfo.dwCursorPosition.Y -
  1095. persist->cLineBegin.Y + 1) *
  1096. (conBufferInfo.srWindow.Right -
  1097. conBufferInfo.srWindow.Left) ),
  1098. persist->cLineBegin,
  1099. &cbFill );
  1100. }
  1101. }
  1102. }
  1103. }
  1104. pEndOfLine++;
  1105. }
  1106. // Print newline characters if some were found
  1107. if ( pEndOfLine > pCurLine )
  1108. {
  1109. if ( ! WriteFile(MyStdOut, pCurLine, (DWORD)(pEndOfLine - pCurLine), &cbWrite, NULL) )
  1110. {
  1111. // Bail out
  1112. return FALSE;
  1113. }
  1114. // Move line pointer
  1115. pCurLine = pEndOfLine;
  1116. }
  1117. // Get the line
  1118. while ( pEndOfLine < buffer + cbBuffer &&
  1119. *pEndOfLine != '\r' &&
  1120. *pEndOfLine != '\n' ) pEndOfLine++;
  1121. // If we got characters we are in a line
  1122. // Check it for keywords or add it to
  1123. // a continuation line and/or print it
  1124. if ( pEndOfLine > pCurLine )
  1125. {
  1126. bNewLine = FALSE;
  1127. // Point to last character
  1128. pEndOfLine--;
  1129. // Check for current console information
  1130. if ( !bCanColor )
  1131. {
  1132. // Couldn't get information -- handle might
  1133. // be redirected. Don't change colors
  1134. bAltColor = FALSE;
  1135. }
  1136. else if ( persist->bLineContinues )
  1137. {
  1138. // See if we have enough room to construct this new line
  1139. if ( !persist->bLineTooLarge &&
  1140. (DWORD)(pEndOfLine - pCurLine + 1) >=
  1141. (persist->cbLine - persist->cbCurPos) )
  1142. {
  1143. // Attempt to build a bigger buffer
  1144. pTemp = realloc( (PVOID)persist->sLine,
  1145. persist->cbLine + (pEndOfLine - pCurLine + 1) );
  1146. if ( NULL == pTemp )
  1147. {
  1148. persist->bLineTooLarge = TRUE;
  1149. }
  1150. else
  1151. {
  1152. persist->sLine = pTemp;
  1153. persist->cbLine += (DWORD)(pEndOfLine - pCurLine + 1);
  1154. }
  1155. }
  1156. // Add this piece to the line
  1157. if ( !persist->bLineTooLarge )
  1158. {
  1159. // Add new piece to line
  1160. memcpy( (PVOID)(persist->sLine + persist->cbCurPos + 1),
  1161. (PVOID)pCurLine,
  1162. (pEndOfLine - pCurLine + 1) );
  1163. // Point at new end of line
  1164. persist->cbCurPos += (DWORD)(pEndOfLine - pCurLine + 1);
  1165. }
  1166. // Don't color this line portion
  1167. bAltColor = FALSE;
  1168. }
  1169. // Check if line needs colored unless this is going
  1170. // to be a continued line (last line in buffer and
  1171. // does not end with a newline). We do not want
  1172. // to determine the color of the line until we
  1173. // have the complete thing
  1174. else if ( (char *)(pEndOfLine + 1) < (char *)(buffer + cbBuffer) )
  1175. {
  1176. // Parse line for keywords that will cause
  1177. // this line to show up in a different color
  1178. bAltColor = pColorLine( pCurLine,
  1179. (DWORD)(pEndOfLine - pCurLine + 1),
  1180. conBufferInfo.wAttributes,
  1181. &color );
  1182. }
  1183. else
  1184. {
  1185. bAltColor = FALSE;
  1186. }
  1187. if ( bAltColor )
  1188. {
  1189. // Change color for output of this line
  1190. SetConsoleTextAttribute( MyStdOut, color );
  1191. }
  1192. if ( ! WriteFile(MyStdOut, pCurLine, (DWORD)(pEndOfLine - pCurLine + 1), &cbWrite, NULL))
  1193. {
  1194. if ( bAltColor )
  1195. {
  1196. SetConsoleTextAttribute( MyStdOut, conBufferInfo.wAttributes );
  1197. }
  1198. // Bail out
  1199. return FALSE;
  1200. }
  1201. // Restore default colors if necessary
  1202. if ( bAltColor )
  1203. {
  1204. SetConsoleTextAttribute( MyStdOut, conBufferInfo.wAttributes );
  1205. }
  1206. // Point to the next line, saving off this line
  1207. // in case we need to store it in a continuation
  1208. // line
  1209. pPrevLine = pCurLine;
  1210. pCurLine = pEndOfLine + 1;
  1211. } // End only check line if there is one
  1212. }
  1213. // If the buffer did not end with a CR, and we are
  1214. // not already in a continuation, remember this line
  1215. if ( !bNewLine &&
  1216. pPrevLine <= pEndOfLine &&
  1217. !persist->bLineContinues )
  1218. {
  1219. persist->bLineContinues = TRUE;
  1220. persist->bLineTooLarge = FALSE;
  1221. if ( bCanColor )
  1222. persist->cLineBegin = conBufferInfo.dwCursorPosition;
  1223. else // Signal we were unable to obtain cursor location
  1224. {
  1225. persist->cLineBegin.X = 0xFF;
  1226. persist->cLineBegin.Y = 0xFF;
  1227. }
  1228. // See if we have enough room to construct this new line
  1229. if ( (DWORD)(pEndOfLine - pPrevLine + 1) >= persist->cbLine )
  1230. {
  1231. // Attempt to build a bigger buffer
  1232. pTemp = realloc( (PVOID)persist->sLine,
  1233. persist->cbLine + (pEndOfLine - pPrevLine + 1) );
  1234. if ( NULL == pTemp )
  1235. {
  1236. persist->bLineTooLarge = TRUE;
  1237. }
  1238. else
  1239. {
  1240. persist->sLine = pTemp;
  1241. persist->cbLine = (DWORD)(pEndOfLine - pPrevLine + 1);
  1242. }
  1243. }
  1244. // Store the beginning of the line
  1245. if ( !persist->bLineTooLarge )
  1246. {
  1247. // Add new piece to line
  1248. memcpy( (PVOID)persist->sLine,
  1249. (PVOID)pPrevLine,
  1250. (pEndOfLine - pPrevLine + 1) );
  1251. // Point at new end of line
  1252. persist->cbCurPos = (DWORD)(pEndOfLine - pPrevLine);
  1253. }
  1254. }
  1255. // Success
  1256. return TRUE;
  1257. }