|
|
#include <precomp.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 (NetWkstaGetInfo(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 );
NetApiBufferFree(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 (hMailslot != INVALID_HANDLE_VALUE) { if ( ! WriteFile( hMailslot, szSend, strlen(szSend) + 1, &cb, NULL )) { printf("REMOTE: WriteFile Failed on mailslot, error %d\n", GetLastError()); } } else { printf("REMOTE: Failed to create 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 = CreateWaitableTimer( NULL, // security
FALSE, // bManualReset, we want auto-reset
NULL // unnamed
); if (hAdTimer == NULL) { hAdTimer = INVALID_HANDLE_VALUE; } else {
DueTime.QuadPart = Int32x32To64(INITIAL_SLEEP_PERIOD, -10000); dwTimerInterval = INITIAL_AD_RATE;
SetWaitableTimer( 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) {
CancelWaitableTimer(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) {
SetWaitableTimer( hAdTimer, &DueTime, dwTimerInterval, AdvertiseTimerFired, 0, // arg to compl. rtn
TRUE ); } } }
|