REMOTEDS.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:14k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /******************************************************************************
  2. *       This is a part of the Microsoft Source Code Samples. 
  3. *       Copyright 1995 - 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. // remoteds.c, a "directory service" for the limited job of
  12. // finding remote.exe servers on the same domain/workgroup.
  13. //
  14. // Dave Hart written summer 1997.
  15. //
  16. // Copyright 1997 Microsoft Corp.
  17. //
  18. //
  19. // A handy way to use this program is under remote on a single
  20. // or a few machines:
  21. //
  22. //    remote /s remoteds FindRemote
  23. //
  24. // Clients connect with remote /c machinename FindRemote
  25. //
  26. // Only remote.exe's running debuggers or with /V+ are visible
  27. // via remoteds, as with remote /q.
  28. //
  29. // Remote clients notify remoteds using mailslots, see srvad.c.
  30. //
  31. //
  32. #include <windows.h>
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include <stdlib.h>
  36. #include <process.h>
  37. typedef char RECEIVEBUF[1024];
  38. typedef struct tagSERVERENTRY {
  39.     int     nPID;                   // zero PID means unused slot
  40.     union {
  41.         FILETIME FileTime;
  42.         LARGE_INTEGER liTime;
  43.     };
  44.     char   *pszMachine;
  45.     char   *pszPipe;
  46.     char   *pszChildCmd;
  47. } SERVERENTRY;
  48. #define TABLE_INITIAL_ALLOC 1 // 128       // beginning table size
  49. #define TABLE_ALLOC_DELTA   1 // 16        // grows by this many units
  50. HANDLE       hTableHeap;
  51. SERVERENTRY *Table;
  52. int          nTableSize;
  53. int          nTableHiWater;          // highest used slot so far
  54. CRITICAL_SECTION csTable;
  55. char szPrompt[] = "remote server search> ";
  56. unsigned WINAPI     InteractThread(void * UnusedParm);
  57. unsigned WINAPI     CleanupThread(void * UnusedParm);
  58. VOID     __fastcall UpdateTimeStamp(LPFILETIME lpFileTime);
  59. VOID     __fastcall ReallocTable(int nNewTableSize);
  60. int
  61. main(
  62.     int argc,
  63.     char **argv
  64.     )
  65. {
  66.     char *      pszMailslot = "\\.\MAILSLOT\REMOTE\DEBUGGERS";
  67.     HANDLE      hMailslot;
  68.     BOOL        b;
  69.     HANDLE      hThread;
  70.     DWORD       dwTID;
  71.     char *      pszMachine;
  72.     int         cchMachine;
  73.     char *      pszPID;
  74.     int         nPID;
  75.     char *      pszPipe;
  76.     int         cchPipe;
  77.     char *      pszChildCmd;
  78.     int         i;
  79.     int         nFirstAvailable;
  80.     BOOL        fStopping;
  81.     BOOL        fFound;
  82.     int         cb;
  83.     char *      pchStrings;
  84.     char *      pch;
  85.     DWORD       cbRead;
  86.     DWORD       iBuf;
  87.     DWORD       rgcbBuf[2];
  88.     RECEIVEBUF  rgBuf[2];
  89.     RECEIVEBUF  szBuf;
  90.     char        szRemoteCmd[512];
  91.     InitializeCriticalSection(&csTable);
  92.     ReallocTable(TABLE_INITIAL_ALLOC);
  93.     hMailslot =
  94.         CreateMailslot(
  95.             pszMailslot,
  96.             0,
  97.             MAILSLOT_WAIT_FOREVER,
  98.             NULL
  99.             );
  100.     if (INVALID_HANDLE_VALUE == hMailslot) {
  101.         DWORD dwErr = GetLastError();
  102.         if (ERROR_ALREADY_EXISTS == dwErr) {
  103.             printf("Cannot receive on %s,n"
  104.                    "is remoteds or rdsrelay already running on this machine?n",
  105.                    pszMailslot);
  106.         } else {
  107.             printf("CreateMailslot(%s) failed error %dn",
  108.                     pszMailslot,
  109.                     dwErr);
  110.         }
  111.         return 2;
  112.     }
  113.     hThread = (HANDLE) _beginthreadex(
  114.                                       NULL,
  115.                                       0,
  116.                                       InteractThread,
  117.                                       NULL,
  118.                                       0,
  119.                                       &dwTID
  120.                                      );
  121.     if ( ! hThread) {
  122.         printf("Can't start InteractThread %dn", GetLastError());
  123.         return 3;
  124.     }
  125.     CloseHandle(hThread);
  126.     hThread = (HANDLE) _beginthreadex(
  127.                                       NULL,
  128.                                       0,
  129.                                       CleanupThread,
  130.                                       NULL,
  131.                                       0,
  132.                                       &dwTID
  133.                                      );
  134.     if ( ! hThread) {
  135.         printf("Can't start CleanupThread %dn", GetLastError());
  136.         return 3;
  137.     }
  138.     CloseHandle(hThread);
  139.     //
  140.     // loop reading and processing mailslot messsages
  141.     //
  142.     iBuf = 0;
  143.     ZeroMemory(rgcbBuf, sizeof(rgcbBuf));
  144.     ZeroMemory(rgBuf, sizeof(rgBuf));
  145.     while(TRUE)
  146.     {
  147.         b = ReadFile(
  148.                 hMailslot,
  149.                 rgBuf[ iBuf ],
  150.                 sizeof(rgBuf[ iBuf ]) - 1,  // so I can null terminate if needed
  151.                 &rgcbBuf[ iBuf ],
  152.                 NULL
  153.                 );
  154.         if ( ! b) {
  155.             printf("ReadFile(hMailslot) failed error %dn", GetLastError());
  156.             return 4;
  157.         }
  158.         //
  159.         // It's the nature of mailslots and multiple transports
  160.         // that we'll get the identical message several times in
  161.         // quick succession.  Don't waste time searching the table
  162.         // for these duplicates.
  163.         //
  164.         if ( rgcbBuf[0] == rgcbBuf[1] &&
  165.              ! memcmp(rgBuf[0], rgBuf[1], rgcbBuf[0])) {
  166.             continue;               // duplicate
  167.         }
  168.         //
  169.         // Make a working copy into szBuf/cbRead that we can
  170.         // modify so the original buffer is available for
  171.         // detecting received duplicates.
  172.         //
  173.         cbRead = rgcbBuf[ iBuf ];
  174.         CopyMemory(szBuf, rgBuf[ iBuf ], cbRead);
  175.         //
  176.         // Toggle buffers for the next read.
  177.         //
  178.         iBuf = !iBuf;
  179.         if (szBuf[ cbRead - 1 ]) {
  180.             printf("Received string not null terminated.n");
  181.             szBuf[cbRead] = 0;
  182.         }
  183.         pszMachine = szBuf;
  184.         pch = strchr(szBuf, 't');
  185.         if (!pch) {
  186.             printf("Received string no 1st tabn");
  187.             continue;
  188.         }
  189.         *pch = '';
  190.         pszPID = ++pch;
  191.         pch = strchr(pch, 't');
  192.         if (!pch) {
  193.             printf("Received string no 2nd tabn");
  194.             continue;
  195.         }
  196.         *pch = '';
  197.         pszPipe = ++pch;
  198.         pch = strchr(pch, 't');
  199.         if (!pch) {
  200.             printf("Received string no 3nd tabn");
  201.             continue;
  202.         }
  203.         *pch = '';
  204.         pszChildCmd = ++pch;
  205.         //
  206.         // If it ends with ^B it's going away.
  207.         //
  208.         pch = strchr(pch, 'x2');
  209.         if (pch) {
  210.             *pch = 0;
  211.             fStopping = TRUE;
  212.         } else {
  213.             fStopping = FALSE;
  214.         }
  215.         nPID = strtol(pszPID, NULL, 10);
  216.         _strlwr(pszMachine);
  217.         _strlwr(pszPipe);
  218.         if (fStopping) {
  219.             //
  220.             // display the ending remote's info
  221.             //
  222.             sprintf(szRemoteCmd, "remote /c %s %s", pszMachine, pszPipe);
  223.             printf("r%-36s %-20s   [stop]n%s", szRemoteCmd, pszChildCmd, szPrompt);
  224.             fflush(stdout);
  225.         }
  226.         EnterCriticalSection(&csTable);
  227.         nFirstAvailable = -1;
  228.         for (i = 0, fFound = FALSE;
  229.              i <= nTableHiWater;
  230.              i++) {
  231.             if (-1 == nFirstAvailable && 0 == Table[i].nPID) {
  232.                 nFirstAvailable = i;
  233.             }
  234.             if (Table[i].nPID == nPID &&
  235.                 ! strcmp(Table[i].pszMachine, pszMachine) &&
  236.                 ! strcmp(Table[i].pszPipe, pszPipe)) {
  237.                 fFound = TRUE;
  238.                 break;
  239.             }
  240.         }
  241.         if (fFound) {
  242.             if (fStopping) {
  243.                 //
  244.                 // Remove it from the table
  245.                 //
  246.                 free(Table[i].pszMachine);
  247.                 ZeroMemory(&Table[i], sizeof(Table[i]));
  248.                 if (nTableHiWater == i) {
  249.                     nTableHiWater--;
  250.                 }
  251.             } else { // starting
  252.                 // printf("Found at slot %dn", i);
  253.                 // timestamp is updated below
  254.             }
  255.         } else if ( ! fStopping) {
  256.             //
  257.             // we have a new entry, display it
  258.             //
  259.             sprintf(szRemoteCmd, "remote /c %s %s", pszMachine, pszPipe);
  260.             printf("r%-36s %-20s   [start]n%s", szRemoteCmd, pszChildCmd, szPrompt);
  261.             fflush(stdout);
  262.             //
  263.             // Does it fit in the table or do we need to grow it?
  264.             //
  265.             if (-1 == nFirstAvailable) {
  266.                 if (++nTableHiWater >= nTableSize) {
  267.                     ReallocTable(nTableSize + TABLE_ALLOC_DELTA);
  268.                 }
  269.                 i = nTableHiWater;
  270.             } else {
  271.                 i = nFirstAvailable;
  272.             }
  273.             //
  274.             // Fill in a server entry in table, if we can
  275.             // allocate memory for the strings.
  276.             //
  277.             cb = (cchMachine  = strlen(pszMachine) + 1) +
  278.                  (cchPipe     = strlen(pszPipe) + 1) +
  279.                  (              strlen(pszChildCmd) + 1);
  280.             pchStrings = malloc(cb);
  281.             if (pchStrings) {
  282.                 Table[i].nPID = nPID;
  283.                 UpdateTimeStamp(&Table[i].FileTime);
  284.                 Table[i].pszMachine = pchStrings;
  285.                 strcpy(Table[i].pszMachine, pszMachine);
  286.                 Table[i].pszPipe = Table[i].pszMachine + cchMachine;
  287.                 strcpy(Table[i].pszPipe, pszPipe);
  288.                 Table[i].pszChildCmd = Table[i].pszPipe + cchPipe;
  289.                 strcpy(Table[i].pszChildCmd, pszChildCmd);
  290.             }
  291.         }
  292.         UpdateTimeStamp(&Table[i].FileTime);
  293.         LeaveCriticalSection(&csTable);
  294.     }   // while (TRUE)
  295.     return 0;    // never executed
  296. }
  297. //
  298. // InteractThread lets the user query the list of remote servers.
  299. //
  300. unsigned WINAPI InteractThread(void * UnusedParm)
  301. {
  302.     char szQuery[1024];
  303.     char szLowerQuery[1024];
  304.     char szRemoteCmd[400];
  305.     int  i;
  306.     BOOL fAll;
  307.  Help:
  308.     printf("Enter a string to search for, a machine or pipe name or command.n");
  309.     printf("Enter * to list all remote servers.n");
  310.     printf("Exit with ^B.n");
  311.     while (TRUE) {
  312.         fputs(szPrompt, stdout);
  313.         fflush(stdout);
  314.         gets(szQuery);
  315.         _strlwr( strcpy(szLowerQuery, szQuery) );
  316.         if (!strlen(szLowerQuery) ||
  317.             !strcmp(szLowerQuery, "?") ||
  318.             !strcmp(szLowerQuery, "h") ||
  319.             !strcmp(szLowerQuery, "help")) {
  320.             goto Help;
  321.         }
  322.         if (2 == szLowerQuery[0]) {           // ^B
  323.             ExitProcess(0);
  324.         }
  325.         fAll = ! strcmp(szLowerQuery, "*");
  326.         EnterCriticalSection(&csTable);
  327.         for (i = 0; i <= nTableHiWater; i++) {
  328.             if (Table[i].nPID) {
  329.                 if (fAll ||
  330.                     strstr(Table[i].pszMachine, szLowerQuery) ||
  331.                     strstr(Table[i].pszPipe, szLowerQuery) ||
  332.                     strstr(Table[i].pszChildCmd, szLowerQuery)) {
  333.                     sprintf(szRemoteCmd, "remote /c %s %s", Table[i].pszMachine, Table[i].pszPipe);
  334.                     printf("%-40s %sn", szRemoteCmd, Table[i].pszChildCmd);
  335.                 }
  336.             }
  337.         }
  338.         LeaveCriticalSection(&csTable);
  339.     }
  340.     return 0;    // never executed
  341. }
  342. //
  343. // CleanupThread scavenges for old entries and frees them.
  344. // remote /s sends a broadcast at least every 2 hours.
  345. // We get some of them.  Age out entries after 12 hours.
  346. //
  347. unsigned WINAPI CleanupThread(void * UnusedParm)
  348. {
  349.     LARGE_INTEGER liNow;
  350.     LARGE_INTEGER liTimeout;
  351.     int i;
  352.     char szRemoteCmd[400];
  353.     liTimeout.QuadPart = (LONGLONG)10000000 * 60 * 60 * 12;  // 12 hours
  354.     while (TRUE) {
  355.         Sleep(15 * 60 * 1000);    // 10 minutes
  356.         UpdateTimeStamp((LPFILETIME)&liNow);
  357.         EnterCriticalSection(&csTable);
  358.         for (i = nTableHiWater; i >= 0; i--) {
  359.             if (Table[i].nPID) {
  360.                 if (liNow.QuadPart - Table[i].liTime.QuadPart > liTimeout.QuadPart) {
  361.                     //
  362.                     // display the ending remote's info
  363.                     //
  364.                     sprintf(szRemoteCmd, "remote /c %s %s", Table[i].pszMachine, Table[i].pszPipe);
  365.                     printf("r%-36s %-20s   [aged out]n%s", szRemoteCmd, Table[i].pszChildCmd, szPrompt);
  366.                     fflush(stdout);
  367.                     free(Table[i].pszMachine);
  368.                     ZeroMemory(&Table[i], sizeof(Table[i]));
  369.                     if (nTableHiWater == i) {
  370.                         nTableHiWater--;
  371.                     }
  372.                 }
  373.             }
  374.         }
  375.         LeaveCriticalSection(&csTable);
  376.     }
  377.     return 0;    // never executed
  378. }
  379. VOID __fastcall UpdateTimeStamp(LPFILETIME lpFileTime)
  380. {
  381.     SYSTEMTIME SystemTime;
  382.     GetSystemTime(&SystemTime);
  383.     SystemTimeToFileTime(&SystemTime, lpFileTime);
  384. }
  385. VOID __fastcall ReallocTable(int nNewTableSize)
  386. {
  387.     SERVERENTRY *pTableSave = Table;
  388.     EnterCriticalSection(&csTable);
  389.     nTableSize = nNewTableSize;
  390.     if ( ! hTableHeap) {
  391.         hTableHeap = HeapCreate(
  392.                          HEAP_NO_SERIALIZE,
  393.                          (TABLE_INITIAL_ALLOC + 1) * sizeof(Table[0]),  // size
  394.                          50000 * sizeof(Table[0])                       // max
  395.                          );
  396.         Table = HeapAlloc(
  397.                     hTableHeap,
  398.                     HEAP_ZERO_MEMORY,
  399.                     nTableSize * sizeof(Table[0])
  400.                     );
  401.     } else {
  402.         Table = HeapReAlloc(
  403.                     hTableHeap,
  404.                     HEAP_ZERO_MEMORY,
  405.                     Table,
  406.                     nTableSize * sizeof(Table[0])
  407.                     );
  408.     }
  409.     if (!Table) {
  410.         printf("nremoteds: Out of memory allocating remote server tablen");
  411.         exit(ERROR_NOT_ENOUGH_MEMORY);
  412.     }
  413.     LeaveCriticalSection(&csTable);
  414.     if (Table != pTableSave && pTableSave) {
  415.         printf("nremoteds:  remote server table moved in HeapRealloc from %x to %x.n", pTableSave, Table);
  416.         fflush(stdout);
  417.     }
  418. }