SRVAD.C

#include <windows.h> 
#include <stdio.h>
#include <string.h>
#include "Remote.h"
#include "Server.h"

//
// This module uses mailslots to broadcast the existence of
// this remote server to allow a form of browsing for
// remote server instances. This is disabled in the
// customer version of remote.exe, and can be disabled
// in the internal version using the /v- switch to
// remote /s.
//
// remoteds.c implements a listener that allows searching.
//

#define INITIAL_SLEEP_PERIOD (35 * 1000) // 35 seconds before first
#define INITIAL_AD_RATE (10 * 60 * 1000) // 10 minutes between 1 & 2,
#define MAXIMUM_AD_RATE (120 * 60 * 1000) // doubling until 120 minutes max


OVERLAPPED olMailslot;
HANDLE hAdTimer = INVALID_HANDLE_VALUE;
HANDLE hMailslot = INVALID_HANDLE_VALUE;
DWORD dwTimerInterval; // milliseconds
BOOL bSynchAdOnly;
BOOL bSendingToMailslot;
char szMailslotName[64]; // netbios names are short
char szSend[1024];


#define MAX_MAILSLOT_SPEWS 2
DWORD dwMailslotErrors;


VOID
InitAd(
BOOL IsAdvertise
)
{
DWORD cb;
PWKSTA_INFO_101 pwki101;
LARGE_INTEGER DueTime;

if (IsAdvertise) {

// Unless Win32s or Win9x support named pipe servers...

ASSERT(OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);

// Problems with overlapped writes to a mailslot sometimes
// cause remote.exe to zombie on exit on NT4, undebuggable
// and unkillable because of an abandoned RDR1 IRP which
// never completes.
//
// So on NT4 we only send messages at startup and shutdown
// and send them synchronously using a nonoverlapped handle.
//

bSynchAdOnly = (OsVersionInfo.dwMajorVersion <= 4);

//
// Get currently active computername and browser/mailslot
// domain/workgroup using one call to NetWkstaGetInfo.
// This is unicode-only, we'll use wsprintf's %ls to
// convert to 8-bit characters.
//
// remoteds.exe needs to be run on a workstation that is
// part of the domain or workgroup of the same name,
// and be in broadcast range, to receive our sends.
//

if (pfnNetWkstaGetInfo(NULL, 101, (LPBYTE *) &pwki101)) {
printf("REMOTE: unable to get computer/domain name, not advertising.\n");
return;
}

wsprintf(
szMailslotName,
"\\\\%ls\\MAILSLOT\\REMOTE\\DEBUGGERS",
pwki101->wki101_langroup
);

wsprintf(
szSend,
"%ls\t%d\t%s\t%s",
pwki101->wki101_computername,
GetCurrentProcessId(),
PipeName,
ChildCmd
);

pfnNetApiBufferFree(pwki101);
pwki101 = NULL;

//
// Broadcast mailslots are limited to 400 message bytes
//

szSend[399] = 0;

if (bSynchAdOnly) {

hMailslot =
CreateFile(
szMailslotName,
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL
);

if ( ! WriteFile(
hMailslot,
szSend,
strlen(szSend) + 1,
&cb,
NULL
)) {

printf("REMOTE: WriteFile Failed on mailslot, error %d\n", GetLastError());
}

} else { // we can do async mailslot I/O

//
// Create a waitable timer and set it to fire first in
// INITIAL_SLEEP_PERIOD milliseconds by calling the
// completion routine AdvertiseTimerFired. It will
// be given an inital period of INITIAL_AD_RATE ms.
//

hAdTimer =
pfnCreateWaitableTimer(
NULL, // security
FALSE, // bManualReset, we want auto-reset
NULL // unnamed
);

DueTime.QuadPart = Int32x32To64(INITIAL_SLEEP_PERIOD, -10000);
dwTimerInterval = INITIAL_AD_RATE;

pfnSetWaitableTimer(
hAdTimer,
&DueTime,
dwTimerInterval,
AdvertiseTimerFired,
0, // arg to compl. rtn
TRUE
);

}
}
}


VOID
ShutAd(
BOOL IsAdvertise
)
{
DWORD cb;
BOOL b;

if (IsAdvertise) {

if (INVALID_HANDLE_VALUE != hAdTimer) {

pfnCancelWaitableTimer(hAdTimer);
CloseHandle(hAdTimer);
hAdTimer = INVALID_HANDLE_VALUE;
}

if (INVALID_HANDLE_VALUE != hMailslot &&
! bSendingToMailslot) {

//
// Tell any listening remoteds's we're
// outta here. Do this by tacking on
// a ^B at the end of the string (as
// in Bye).
//

strcat(szSend, "\x2");


if (bSynchAdOnly) { // overlapped handle or not?
b = WriteFile(
hMailslot,
szSend,
strlen(szSend) + 1,
&cb,
NULL
);
} else {
b = WriteFileSynch(
hMailslot,
szSend,
strlen(szSend) + 1,
&cb,
0,
&olMainThread
);
}

if ( ! b ) {

printf("REMOTE: WriteFile Failed on mailslot, error %d\n", GetLastError());
}

}

if (INVALID_HANDLE_VALUE != hMailslot) {

printf("\rREMOTE: closing mailslot... ");
fflush(stdout);
CloseHandle(hMailslot);
hMailslot = INVALID_HANDLE_VALUE;
printf("\r \r");
fflush(stdout);
}
}
}


VOID
APIENTRY
AdvertiseTimerFired(
LPVOID pArg,
DWORD dwTimerLo,
DWORD dwTimerHi
)
{
UNREFERENCED_PARAMETER( pArg );
UNREFERENCED_PARAMETER( dwTimerLo );
UNREFERENCED_PARAMETER( dwTimerHi );


if (INVALID_HANDLE_VALUE == hMailslot) {

hMailslot =
CreateFile(
szMailslotName,
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
);
}

if (INVALID_HANDLE_VALUE != hMailslot) {

ZeroMemory(&olMailslot, sizeof(olMailslot));

bSendingToMailslot = TRUE;

if ( ! WriteFileEx(
hMailslot,
szSend,
strlen(szSend) + 1,
&olMailslot,
WriteMailslotCompleted
)) {

bSendingToMailslot = FALSE;

if (++dwMailslotErrors <= MAX_MAILSLOT_SPEWS) {

DWORD dwError;
char szErrorText[512];

dwError = GetLastError();

FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwError,
0,
szErrorText,
sizeof szErrorText,
NULL
);

//
// FormatMessage has put a newline at the end of szErrorText
//

printf(
"REMOTE: Advertisement failed, mailslot error %d:\n%s",
dwError,
szErrorText
);
}

//
// Try reopening the mailslot next time, can't hurt.
//

CloseHandle(hMailslot);
hMailslot = INVALID_HANDLE_VALUE;
}
}
}


VOID
WINAPI
WriteMailslotCompleted(
DWORD dwError,
DWORD cbWritten,
LPOVERLAPPED lpO
)
{
LARGE_INTEGER DueTime;

bSendingToMailslot = FALSE;

if (dwError ||
(strlen(szSend) + 1) != cbWritten) {

if (++dwMailslotErrors <= MAX_MAILSLOT_SPEWS) {
printf("REMOTE: write failed on mailslot, error %d cb %d (s/b %d)\n",
dwError, cbWritten, (strlen(szSend) + 1));
}
return;
}

//
// If we succeeded in writing the mailslot, double the timer interval
// up to the limit.
//

if (dwTimerInterval < MAXIMUM_AD_RATE) {

dwTimerInterval = max(dwTimerInterval * 2, MAXIMUM_AD_RATE);

DueTime.QuadPart = Int32x32To64(dwTimerInterval, -10000);

if (INVALID_HANDLE_VALUE != hAdTimer) {

pfnSetWaitableTimer(
hAdTimer,
&DueTime,
dwTimerInterval,
AdvertiseTimerFired,
0, // arg to compl. rtn
TRUE
);
}
}
}