home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / winnt / remote / srvad.c < prev    next >
C/C++ Source or Header  |  1997-10-09  |  10KB  |  357 lines

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include "Remote.h"
  5. #include "Server.h"
  6.  
  7. //
  8. // This module uses mailslots to broadcast the existence of
  9. // this remote server to allow a form of browsing for
  10. // remote server instances.  This is disabled in the
  11. // customer version of remote.exe, and can be disabled
  12. // in the internal version using the /v- switch to
  13. // remote /s.
  14. //
  15. // remoteds.c implements a listener that allows searching.
  16. //
  17.  
  18. #define  INITIAL_SLEEP_PERIOD (35 * 1000)          // 35 seconds before first
  19. #define  INITIAL_AD_RATE      (10 * 60 * 1000)     // 10 minutes between 1 & 2,
  20. #define  MAXIMUM_AD_RATE      (120 * 60 * 1000)    // doubling until 120 minutes max
  21.  
  22.  
  23. OVERLAPPED olMailslot;
  24. HANDLE     hAdTimer = INVALID_HANDLE_VALUE;
  25. HANDLE     hMailslot = INVALID_HANDLE_VALUE;
  26. DWORD      dwTimerInterval;      // milliseconds
  27. BOOL       bSynchAdOnly;
  28. BOOL       bSendingToMailslot;
  29. char       szMailslotName[64];    // netbios names are short
  30. char       szSend[1024];
  31.  
  32.  
  33. #define MAX_MAILSLOT_SPEWS 2
  34. DWORD      dwMailslotErrors;
  35.  
  36.  
  37. VOID
  38. InitAd(
  39.    BOOL IsAdvertise
  40.    )
  41. {
  42.     DWORD           cb;
  43.     PWKSTA_INFO_101 pwki101;
  44.     LARGE_INTEGER   DueTime;
  45.  
  46.     if (IsAdvertise) {
  47.  
  48.         // Unless Win32s or Win9x support named pipe servers...
  49.  
  50.         ASSERT(OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
  51.  
  52.         // Problems with overlapped writes to a mailslot sometimes
  53.         // cause remote.exe to zombie on exit on NT4, undebuggable
  54.         // and unkillable because of an abandoned RDR1 IRP which
  55.         // never completes.
  56.         //
  57.         // So on NT4 we only send messages at startup and shutdown
  58.         // and send them synchronously using a nonoverlapped handle.
  59.         //
  60.  
  61.         bSynchAdOnly = (OsVersionInfo.dwMajorVersion <= 4);
  62.  
  63.         //
  64.         // Get currently active computername and browser/mailslot
  65.         // domain/workgroup using one call to NetWkstaGetInfo.
  66.         // This is unicode-only, we'll use wsprintf's %ls to
  67.         // convert to 8-bit characters.
  68.         //
  69.         // remoteds.exe needs to be run on a workstation that is
  70.         // part of the domain or workgroup of the same name,
  71.         // and be in broadcast range, to receive our sends.
  72.         //
  73.  
  74.         if (pfnNetWkstaGetInfo(NULL, 101, (LPBYTE *) &pwki101)) {
  75.             printf("REMOTE: unable to get computer/domain name, not advertising.\n");
  76.             return;
  77.         }
  78.  
  79.         wsprintf(
  80.             szMailslotName,
  81.             "\\\\%ls\\MAILSLOT\\REMOTE\\DEBUGGERS",
  82.             pwki101->wki101_langroup
  83.             );
  84.  
  85.         wsprintf(
  86.             szSend,
  87.             "%ls\t%d\t%s\t%s",
  88.             pwki101->wki101_computername,
  89.             GetCurrentProcessId(),
  90.             PipeName,
  91.             ChildCmd
  92.             );
  93.  
  94.         pfnNetApiBufferFree(pwki101);
  95.         pwki101 = NULL;
  96.  
  97.         //
  98.         // Broadcast mailslots are limited to 400 message bytes
  99.         //
  100.  
  101.         szSend[399] = 0;
  102.  
  103.         if (bSynchAdOnly) {
  104.  
  105.             hMailslot =
  106.                 CreateFile(
  107.                     szMailslotName,
  108.                     GENERIC_WRITE,
  109.                     FILE_SHARE_WRITE,
  110.                     NULL,
  111.                     OPEN_EXISTING,
  112.                     0,
  113.                     NULL
  114.                     );
  115.  
  116.             if ( ! WriteFile(
  117.                        hMailslot,
  118.                        szSend,
  119.                        strlen(szSend) + 1,
  120.                        &cb,
  121.                        NULL
  122.                        )) {
  123.  
  124.                 printf("REMOTE: WriteFile Failed on mailslot, error %d\n", GetLastError());
  125.             }
  126.  
  127.         } else {  // we can do async mailslot I/O
  128.  
  129.             //
  130.             // Create a waitable timer and set it to fire first in
  131.             // INITIAL_SLEEP_PERIOD milliseconds by calling the
  132.             // completion routine AdvertiseTimerFired.  It will
  133.             // be given an inital period of INITIAL_AD_RATE ms.
  134.             //
  135.  
  136.             hAdTimer =
  137.                 pfnCreateWaitableTimer(
  138.                     NULL,               // security
  139.                     FALSE,              // bManualReset, we want auto-reset
  140.                     NULL                // unnamed
  141.                     );
  142.  
  143.             DueTime.QuadPart = Int32x32To64(INITIAL_SLEEP_PERIOD, -10000);
  144.             dwTimerInterval = INITIAL_AD_RATE;
  145.  
  146.             pfnSetWaitableTimer(
  147.                 hAdTimer,
  148.                 &DueTime,
  149.                 dwTimerInterval,
  150.                 AdvertiseTimerFired,
  151.                 0,                     // arg to compl. rtn
  152.                 TRUE
  153.                 );
  154.  
  155.         }
  156.     }
  157. }
  158.  
  159.  
  160. VOID
  161. ShutAd(
  162.    BOOL IsAdvertise
  163.    )
  164. {
  165.     DWORD cb;
  166.     BOOL  b;
  167.  
  168.     if (IsAdvertise) {
  169.  
  170.         if (INVALID_HANDLE_VALUE != hAdTimer) {
  171.  
  172.             pfnCancelWaitableTimer(hAdTimer);
  173.             CloseHandle(hAdTimer);
  174.             hAdTimer = INVALID_HANDLE_VALUE;
  175.         }
  176.  
  177.         if (INVALID_HANDLE_VALUE != hMailslot &&
  178.             ! bSendingToMailslot) {
  179.  
  180.             //
  181.             // Tell any listening remoteds's we're
  182.             // outta here.  Do this by tacking on
  183.             // a ^B at the end of the string (as
  184.             // in Bye).
  185.             //
  186.  
  187.             strcat(szSend, "\x2");
  188.  
  189.  
  190.             if (bSynchAdOnly) {   // overlapped handle or not?
  191.                 b = WriteFile(
  192.                         hMailslot,
  193.                         szSend,
  194.                         strlen(szSend) + 1,
  195.                         &cb,
  196.                         NULL
  197.                         );
  198.             } else {
  199.                 b = WriteFileSynch(
  200.                         hMailslot,
  201.                         szSend,
  202.                         strlen(szSend) + 1,
  203.                         &cb,
  204.                         0,
  205.                         &olMainThread
  206.                         );
  207.             }
  208.  
  209.             if ( ! b ) {
  210.  
  211.                 printf("REMOTE: WriteFile Failed on mailslot, error %d\n", GetLastError());
  212.             }
  213.  
  214.         }
  215.  
  216.         if (INVALID_HANDLE_VALUE != hMailslot) {
  217.  
  218.             printf("\rREMOTE: closing mailslot...       ");
  219.             fflush(stdout);
  220.             CloseHandle(hMailslot);
  221.             hMailslot = INVALID_HANDLE_VALUE;
  222.             printf("\r                                  \r");
  223.             fflush(stdout);
  224.         }
  225.     }
  226. }
  227.  
  228.  
  229. VOID
  230. APIENTRY
  231. AdvertiseTimerFired(
  232.     LPVOID pArg,
  233.     DWORD  dwTimerLo,
  234.     DWORD  dwTimerHi
  235.     )
  236. {
  237.     UNREFERENCED_PARAMETER( pArg );
  238.     UNREFERENCED_PARAMETER( dwTimerLo );
  239.     UNREFERENCED_PARAMETER( dwTimerHi );
  240.  
  241.  
  242.     if (INVALID_HANDLE_VALUE == hMailslot) {
  243.  
  244.         hMailslot =
  245.             CreateFile(
  246.                 szMailslotName,
  247.                 GENERIC_WRITE,
  248.                 FILE_SHARE_WRITE,
  249.                 NULL,
  250.                 OPEN_EXISTING,
  251.                 FILE_FLAG_OVERLAPPED,
  252.                 NULL
  253.                 );
  254.     }
  255.  
  256.     if (INVALID_HANDLE_VALUE != hMailslot) {
  257.  
  258.         ZeroMemory(&olMailslot, sizeof(olMailslot));
  259.  
  260.         bSendingToMailslot = TRUE;
  261.  
  262.         if ( ! WriteFileEx(
  263.                    hMailslot,
  264.                    szSend,
  265.                    strlen(szSend) + 1,
  266.                    &olMailslot,
  267.                    WriteMailslotCompleted
  268.                    )) {
  269.  
  270.             bSendingToMailslot = FALSE;
  271.  
  272.             if (++dwMailslotErrors <= MAX_MAILSLOT_SPEWS) {
  273.  
  274.                 DWORD dwError;
  275.                 char szErrorText[512];
  276.  
  277.                 dwError = GetLastError();
  278.  
  279.                 FormatMessage(
  280.                     FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  281.                     NULL,
  282.                     dwError,
  283.                     0,
  284.                     szErrorText,
  285.                     sizeof szErrorText,
  286.                     NULL
  287.                     );
  288.  
  289.                 //
  290.                 // FormatMessage has put a newline at the end of szErrorText
  291.                 //
  292.  
  293.                 printf(
  294.                     "REMOTE: Advertisement failed, mailslot error %d:\n%s",
  295.                     dwError,
  296.                     szErrorText
  297.                     );
  298.             }
  299.  
  300.             //
  301.             // Try reopening the mailslot next time, can't hurt.
  302.             //
  303.  
  304.             CloseHandle(hMailslot);
  305.             hMailslot = INVALID_HANDLE_VALUE;
  306.         }
  307.     }
  308. }
  309.  
  310.  
  311. VOID
  312. WINAPI
  313. WriteMailslotCompleted(
  314.     DWORD dwError,
  315.     DWORD cbWritten,
  316.     LPOVERLAPPED lpO
  317.     )
  318. {
  319.     LARGE_INTEGER DueTime;
  320.  
  321.     bSendingToMailslot = FALSE;
  322.  
  323.     if (dwError ||
  324.         (strlen(szSend) + 1) != cbWritten) {
  325.  
  326.             if (++dwMailslotErrors <= MAX_MAILSLOT_SPEWS) {
  327.                 printf("REMOTE: write failed on mailslot, error %d cb %d (s/b %d)\n",
  328.                     dwError, cbWritten, (strlen(szSend) + 1));
  329.             }
  330.         return;
  331.     }
  332.  
  333.     //
  334.     // If we succeeded in writing the mailslot, double the timer interval
  335.     // up to the limit.
  336.     //
  337.  
  338.     if (dwTimerInterval < MAXIMUM_AD_RATE) {
  339.  
  340.         dwTimerInterval = max(dwTimerInterval * 2, MAXIMUM_AD_RATE);
  341.  
  342.         DueTime.QuadPart = Int32x32To64(dwTimerInterval, -10000);
  343.  
  344.         if (INVALID_HANDLE_VALUE != hAdTimer) {
  345.  
  346.             pfnSetWaitableTimer(
  347.                 hAdTimer,
  348.                 &DueTime,
  349.                 dwTimerInterval,
  350.                 AdvertiseTimerFired,
  351.                 0,                     // arg to compl. rtn
  352.                 TRUE
  353.                 );
  354.         }
  355.     }
  356. }
  357.