home *** CD-ROM | disk | FTP | other *** search
-
- /******************************************************************************\
- * This is a part of the Microsoft Source Code Samples.
- * Copyright 1995 - 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.
- \******************************************************************************/
-
- //
- // remoteds.c, a "directory service" for the limited job of
- // finding remote.exe servers on the same domain/workgroup.
- //
- // Dave Hart written summer 1997.
- //
- // Copyright 1997 Microsoft Corp.
- //
- //
- // A handy way to use this program is under remote on a single
- // or a few machines:
- //
- // remote /s remoteds FindRemote
- //
- // Clients connect with remote /c machinename FindRemote
- //
- // Only remote.exe's running debuggers or with /V+ are visible
- // via remoteds, as with remote /q.
- //
- // Remote clients notify remoteds using mailslots, see srvad.c.
- //
- //
-
- #include <windows.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <process.h>
-
- typedef char RECEIVEBUF[1024];
-
- typedef struct tagSERVERENTRY {
- int nPID; // zero PID means unused slot
- union {
- FILETIME FileTime;
- LARGE_INTEGER liTime;
- };
- char *pszMachine;
- char *pszPipe;
- char *pszChildCmd;
- } SERVERENTRY;
-
- #define TABLE_INITIAL_ALLOC 1 // 128 // beginning table size
- #define TABLE_ALLOC_DELTA 1 // 16 // grows by this many units
-
- HANDLE hTableHeap;
- SERVERENTRY *Table;
- int nTableSize;
- int nTableHiWater; // highest used slot so far
- CRITICAL_SECTION csTable;
-
- char szPrompt[] = "remote server search> ";
-
-
-
- unsigned WINAPI InteractThread(void * UnusedParm);
- unsigned WINAPI CleanupThread(void * UnusedParm);
- VOID __fastcall UpdateTimeStamp(LPFILETIME lpFileTime);
- VOID __fastcall ReallocTable(int nNewTableSize);
-
-
- int
- main(
- int argc,
- char **argv
- )
- {
- char * pszMailslot = "\\\\.\\MAILSLOT\\REMOTE\\DEBUGGERS";
- HANDLE hMailslot;
- BOOL b;
- HANDLE hThread;
- DWORD dwTID;
- char * pszMachine;
- int cchMachine;
- char * pszPID;
- int nPID;
- char * pszPipe;
- int cchPipe;
- char * pszChildCmd;
- int i;
- int nFirstAvailable;
- BOOL fStopping;
- BOOL fFound;
- int cb;
- char * pchStrings;
- char * pch;
- DWORD cbRead;
- DWORD iBuf;
- DWORD rgcbBuf[2];
- RECEIVEBUF rgBuf[2];
- RECEIVEBUF szBuf;
- char szRemoteCmd[512];
-
- InitializeCriticalSection(&csTable);
-
- ReallocTable(TABLE_INITIAL_ALLOC);
-
- hMailslot =
- CreateMailslot(
- pszMailslot,
- 0,
- MAILSLOT_WAIT_FOREVER,
- NULL
- );
-
- if (INVALID_HANDLE_VALUE == hMailslot) {
-
- DWORD dwErr = GetLastError();
-
- if (ERROR_ALREADY_EXISTS == dwErr) {
- printf("Cannot receive on %s,\n"
- "is remoteds or rdsrelay already running on this machine?\n",
- pszMailslot);
- } else {
- printf("CreateMailslot(%s) failed error %d\n",
- pszMailslot,
- dwErr);
- }
- return 2;
- }
-
-
- hThread = (HANDLE) _beginthreadex(
- NULL,
- 0,
- InteractThread,
- NULL,
- 0,
- &dwTID
- );
-
- if ( ! hThread) {
- printf("Can't start InteractThread %d\n", GetLastError());
- return 3;
- }
-
- CloseHandle(hThread);
-
- hThread = (HANDLE) _beginthreadex(
- NULL,
- 0,
- CleanupThread,
- NULL,
- 0,
- &dwTID
- );
-
-
- if ( ! hThread) {
- printf("Can't start CleanupThread %d\n", GetLastError());
- return 3;
- }
-
- CloseHandle(hThread);
-
-
- //
- // loop reading and processing mailslot messsages
- //
-
- iBuf = 0;
- ZeroMemory(rgcbBuf, sizeof(rgcbBuf));
- ZeroMemory(rgBuf, sizeof(rgBuf));
-
- while(TRUE)
- {
- b = ReadFile(
- hMailslot,
- rgBuf[ iBuf ],
- sizeof(rgBuf[ iBuf ]) - 1, // so I can null terminate if needed
- &rgcbBuf[ iBuf ],
- NULL
- );
-
- if ( ! b) {
- printf("ReadFile(hMailslot) failed error %d\n", GetLastError());
- return 4;
- }
-
- //
- // It's the nature of mailslots and multiple transports
- // that we'll get the identical message several times in
- // quick succession. Don't waste time searching the table
- // for these duplicates.
- //
-
- if ( rgcbBuf[0] == rgcbBuf[1] &&
- ! memcmp(rgBuf[0], rgBuf[1], rgcbBuf[0])) {
-
- continue; // duplicate
- }
-
- //
- // Make a working copy into szBuf/cbRead that we can
- // modify so the original buffer is available for
- // detecting received duplicates.
- //
-
- cbRead = rgcbBuf[ iBuf ];
- CopyMemory(szBuf, rgBuf[ iBuf ], cbRead);
-
- //
- // Toggle buffers for the next read.
- //
-
- iBuf = !iBuf;
-
- if (szBuf[ cbRead - 1 ]) {
- printf("Received string not null terminated.\n");
- szBuf[cbRead] = 0;
- }
-
- pszMachine = szBuf;
-
- pch = strchr(szBuf, '\t');
-
- if (!pch) {
- printf("Received string no 1st tab\n");
- continue;
- }
- *pch = '\0';
-
- pszPID = ++pch;
-
- pch = strchr(pch, '\t');
-
- if (!pch) {
- printf("Received string no 2nd tab\n");
- continue;
- }
- *pch = '\0';
-
- pszPipe = ++pch;
-
- pch = strchr(pch, '\t');
-
- if (!pch) {
- printf("Received string no 3nd tab\n");
- continue;
- }
- *pch = '\0';
-
- pszChildCmd = ++pch;
-
- //
- // If it ends with ^B it's going away.
- //
-
- pch = strchr(pch, '\x2');
-
- if (pch) {
- *pch = 0;
- fStopping = TRUE;
- } else {
- fStopping = FALSE;
- }
-
-
- nPID = strtol(pszPID, NULL, 10);
- _strlwr(pszMachine);
- _strlwr(pszPipe);
-
- if (fStopping) {
-
- //
- // display the ending remote's info
- //
-
- sprintf(szRemoteCmd, "remote /c %s %s", pszMachine, pszPipe);
- printf("\r%-36s %-20s [stop]\n%s", szRemoteCmd, pszChildCmd, szPrompt);
- fflush(stdout);
- }
-
- EnterCriticalSection(&csTable);
-
- nFirstAvailable = -1;
-
- for (i = 0, fFound = FALSE;
- i <= nTableHiWater;
- i++) {
-
- if (-1 == nFirstAvailable && 0 == Table[i].nPID) {
- nFirstAvailable = i;
- }
-
- if (Table[i].nPID == nPID &&
- ! strcmp(Table[i].pszMachine, pszMachine) &&
- ! strcmp(Table[i].pszPipe, pszPipe)) {
-
- fFound = TRUE;
- break;
- }
- }
-
-
- if (fFound) {
-
- if (fStopping) {
-
- //
- // Remove it from the table
- //
-
- free(Table[i].pszMachine);
- ZeroMemory(&Table[i], sizeof(Table[i]));
-
- if (nTableHiWater == i) {
- nTableHiWater--;
- }
-
- } else { // starting
-
- // printf("Found at slot %d\n", i);
- // timestamp is updated below
- }
-
- } else if ( ! fStopping) {
-
- //
- // we have a new entry, display it
- //
-
- sprintf(szRemoteCmd, "remote /c %s %s", pszMachine, pszPipe);
- printf("\r%-36s %-20s [start]\n%s", szRemoteCmd, pszChildCmd, szPrompt);
- fflush(stdout);
-
- //
- // Does it fit in the table or do we need to grow it?
- //
-
- if (-1 == nFirstAvailable) {
-
- if (++nTableHiWater >= nTableSize) {
- ReallocTable(nTableSize + TABLE_ALLOC_DELTA);
- }
-
- i = nTableHiWater;
-
- } else {
-
- i = nFirstAvailable;
- }
-
-
- //
- // Fill in a server entry in table, if we can
- // allocate memory for the strings.
- //
-
- cb = (cchMachine = strlen(pszMachine) + 1) +
- (cchPipe = strlen(pszPipe) + 1) +
- ( strlen(pszChildCmd) + 1);
-
- pchStrings = malloc(cb);
-
- if (pchStrings) {
-
- Table[i].nPID = nPID;
- UpdateTimeStamp(&Table[i].FileTime);
-
- Table[i].pszMachine = pchStrings;
- strcpy(Table[i].pszMachine, pszMachine);
-
- Table[i].pszPipe = Table[i].pszMachine + cchMachine;
- strcpy(Table[i].pszPipe, pszPipe);
-
- Table[i].pszChildCmd = Table[i].pszPipe + cchPipe;
- strcpy(Table[i].pszChildCmd, pszChildCmd);
- }
-
- }
-
- UpdateTimeStamp(&Table[i].FileTime);
-
- LeaveCriticalSection(&csTable);
-
- } // while (TRUE)
-
- return 0; // never executed
- }
-
-
- //
- // InteractThread lets the user query the list of remote servers.
- //
-
- unsigned WINAPI InteractThread(void * UnusedParm)
- {
- char szQuery[1024];
- char szLowerQuery[1024];
- char szRemoteCmd[400];
- int i;
- BOOL fAll;
-
- Help:
- printf("Enter a string to search for, a machine or pipe name or command.\n");
- printf("Enter * to list all remote servers.\n");
- printf("Exit with ^B.\n");
-
- while (TRUE) {
-
- fputs(szPrompt, stdout);
- fflush(stdout);
- gets(szQuery);
- _strlwr( strcpy(szLowerQuery, szQuery) );
-
- if (!strlen(szLowerQuery) ||
- !strcmp(szLowerQuery, "?") ||
- !strcmp(szLowerQuery, "h") ||
- !strcmp(szLowerQuery, "help")) {
-
- goto Help;
- }
-
- if (2 == szLowerQuery[0]) { // ^B
-
- ExitProcess(0);
- }
-
- fAll = ! strcmp(szLowerQuery, "*");
-
- EnterCriticalSection(&csTable);
-
- for (i = 0; i <= nTableHiWater; i++) {
- if (Table[i].nPID) {
- if (fAll ||
- strstr(Table[i].pszMachine, szLowerQuery) ||
- strstr(Table[i].pszPipe, szLowerQuery) ||
- strstr(Table[i].pszChildCmd, szLowerQuery)) {
-
- sprintf(szRemoteCmd, "remote /c %s %s", Table[i].pszMachine, Table[i].pszPipe);
- printf("%-40s %s\n", szRemoteCmd, Table[i].pszChildCmd);
- }
- }
- }
-
- LeaveCriticalSection(&csTable);
-
- }
-
- return 0; // never executed
- }
-
-
- //
- // CleanupThread scavenges for old entries and frees them.
- // remote /s sends a broadcast at least every 2 hours.
- // We get some of them. Age out entries after 12 hours.
- //
-
- unsigned WINAPI CleanupThread(void * UnusedParm)
- {
- LARGE_INTEGER liNow;
- LARGE_INTEGER liTimeout;
- int i;
- char szRemoteCmd[400];
-
- liTimeout.QuadPart = (LONGLONG)10000000 * 60 * 60 * 12; // 12 hours
-
- while (TRUE) {
-
- Sleep(15 * 60 * 1000); // 10 minutes
-
- UpdateTimeStamp((LPFILETIME)&liNow);
-
- EnterCriticalSection(&csTable);
-
- for (i = nTableHiWater; i >= 0; i--) {
-
- if (Table[i].nPID) {
-
- if (liNow.QuadPart - Table[i].liTime.QuadPart > liTimeout.QuadPart) {
-
- //
- // display the ending remote's info
- //
-
- sprintf(szRemoteCmd, "remote /c %s %s", Table[i].pszMachine, Table[i].pszPipe);
- printf("\r%-36s %-20s [aged out]\n%s", szRemoteCmd, Table[i].pszChildCmd, szPrompt);
- fflush(stdout);
-
- free(Table[i].pszMachine);
- ZeroMemory(&Table[i], sizeof(Table[i]));
-
- if (nTableHiWater == i) {
- nTableHiWater--;
- }
- }
-
- }
-
- }
-
- LeaveCriticalSection(&csTable);
- }
-
- return 0; // never executed
- }
-
-
- VOID __fastcall UpdateTimeStamp(LPFILETIME lpFileTime)
- {
- SYSTEMTIME SystemTime;
-
- GetSystemTime(&SystemTime);
- SystemTimeToFileTime(&SystemTime, lpFileTime);
- }
-
-
- VOID __fastcall ReallocTable(int nNewTableSize)
- {
- SERVERENTRY *pTableSave = Table;
-
- EnterCriticalSection(&csTable);
-
- nTableSize = nNewTableSize;
-
- if ( ! hTableHeap) {
-
- hTableHeap = HeapCreate(
- HEAP_NO_SERIALIZE,
- (TABLE_INITIAL_ALLOC + 1) * sizeof(Table[0]), // size
- 50000 * sizeof(Table[0]) // max
- );
- Table = HeapAlloc(
- hTableHeap,
- HEAP_ZERO_MEMORY,
- nTableSize * sizeof(Table[0])
- );
- } else {
-
- Table = HeapReAlloc(
- hTableHeap,
- HEAP_ZERO_MEMORY,
- Table,
- nTableSize * sizeof(Table[0])
- );
- }
-
- if (!Table) {
- printf("\nremoteds: Out of memory allocating remote server table\n");
- exit(ERROR_NOT_ENOUGH_MEMORY);
- }
-
-
- LeaveCriticalSection(&csTable);
-
- if (Table != pTableSave && pTableSave) {
- printf("\nremoteds: remote server table moved in HeapRealloc from %x to %x.\n", pTableSave, Table);
- fflush(stdout);
- }
- }
-