/******************************************************************************\
* 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.
\******************************************************************************/
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
Server.h
Abstract:
The server component of Remote, rewritten using
ReadFileEx/WriteFileEx completion routines.
Author:
Dave Hart 30 May 1997
Environment:
Console App. User mode.
Revision History:
--*/
#include <lm.h> // needed for NET_API_STATUS below
#if !defined(SERVER_H_NOEXTERN)
#define SRVEXTERN extern
#else
#define SRVEXTERN
#endif
#if DBG
DWORD Trace; // bits set in here trigger trace printfs
#define TR_SESSION (0x01)
#define TR_CHILD (0x02)
#define TR_SHAKE (0x04)
#define TR_CONNECT (0x08)
#define TR_QUERY (0x10)
#define TR_COPYPIPE (0x20)
#endif
#if DBG
#define TRACE(tracebit, printfargs) \
((Trace & (TR_##tracebit) \
? (printf printfargs, fflush(stdout), 0) \
: 0))
#else
#define TRACE(tracebit, printfargs) (0)
#endif
#if defined(ASSERT)
#undef ASSERT
#endif
#if DBG
#define ASSERT(exp) ((exp) || (ErrorExit("Assertion failed in " __FILE__ ": " #exp ),0))
#else
#define ASSERT(exp) (0)
#endif
//
// Size of transfer buffers
//
#define BUFFSIZE (4 * 1024)
//
// ServerFlags bit values in REMOTE_CLIENT below
//
#define SFLG_CLOSING 0x01
#define SFLG_HANDSHAKING 0x02
#define SFLG_READINGCOMMAND 0x04
#define SFLG_LOCAL 0x08
#define SFLG_VALID \
(SFLG_CLOSING | \
SFLG_HANDSHAKING | \
SFLG_READINGCOMMAND | \
SFLG_LOCAL)
//
// Per-client state
//
typedef struct tagREMOTE_CLIENT {
LIST_ENTRY Links;
DWORD dwID; // 1, 2, ...
DWORD ServerFlags;
DWORD Flag; //from Client's ClientToServerFlag
DWORD cbWrite; //zero if no read temp/write client ops pending
HANDLE PipeReadH; //Client sends its StdIn through this
HANDLE PipeWriteH; //Client gets its StdOut through this
DWORD dwFilePos; //offset of temp file where next read begins
OVERLAPPED ReadOverlapped;
OVERLAPPED WriteOverlapped;
HANDLE rSaveFile; //Sessions read handle to SaveFile
DWORD cbReadTempBuffer;
DWORD cbWriteBuffer;
DWORD cbCommandBuffer;
char HexAsciiId[8]; // dwID as 8 hex chars -- no terminator
char Name[HOSTNAMELEN]; //Name of client Machine;
char UserName[16]; //Name of user on client machine.
BYTE ReadBuffer[BUFFSIZE];
BYTE ReadTempBuffer[BUFFSIZE];
BYTE WriteBuffer[BUFFSIZE];
BYTE CommandBuffer[BUFFSIZE];
} REMOTE_CLIENT, *PREMOTE_CLIENT;
//
// Client lists, see srvlist.c
//
SRVEXTERN LIST_ENTRY HandshakingListHead;
SRVEXTERN CRITICAL_SECTION csHandshakingList;
SRVEXTERN LIST_ENTRY ClientListHead;
SRVEXTERN CRITICAL_SECTION csClientList;
SRVEXTERN LIST_ENTRY ClosingClientListHead;
SRVEXTERN CRITICAL_SECTION csClosingClientList;
SRVEXTERN DWORD dwNextClientID;
SRVEXTERN LPSTR pszPipeName;
SRVEXTERN HANDLE ChldProc;
SRVEXTERN DWORD pidChild;
SRVEXTERN HANDLE hWriteChildStdIn;
SRVEXTERN BOOL bShuttingDownServer;
SRVEXTERN HANDLE hHeap;
SRVEXTERN volatile DWORD cPendingCtrlCEvents;
SRVEXTERN OSVERSIONINFO OsVersionInfo;
// File containing all that was output by child process.
// Each connection opens a handle to this file
// and sends its contents through PipeWriteH.
SRVEXTERN HANDLE hWriteTempFile;
SRVEXTERN char SaveFileName[64]; //Name of above file - all new sessions need
//
// Generic "wide-open" security descriptor as well
// as the possibly-restricted pipe SD.
//
SRVEXTERN SECURITY_DESCRIPTOR sdPublic;
SRVEXTERN SECURITY_ATTRIBUTES saPublic;
SRVEXTERN SECURITY_ATTRIBUTES saPipe;
//
// To minimize client "all pipe instances are busy" errors,
// we wait on connection to several instances of the IN pipe,
// the sole pipe used by single-pipe clients. Because of the
// requirement to support two-pipe clients (old software as
// well as new software on Win95), we cannot easily create
// and wait for connection on several instances of the OUT pipe.
// This is because two-pipe clients connect to both pipes before
// handshaking commences, and they connect to OUT first. If we
// had several OUT pipe instances waiting, when an IN pipe was
// connected by the two-pipe client, we wouldn't know which of
// the possibly several connected OUT pipe instances to pair
// it with. With only one OUT pipe, at IN connect time we need
// to distinguish two-pipe from one-pipe clients so a one-pipe
// client doesn't sneak in between the OUT and IN connects of
// a two-pipe client and wrongly be paired with the OUT pipe.
// To do so we look at the first byte of the initial write
// from the client (of the computername and magic value), if
// it's a question mark we know we have a new client and won't
// accidentally link it to a connected OUT instance.
//
#define CONNECT_COUNT 3
SRVEXTERN DWORD cConnectIns;
SRVEXTERN OVERLAPPED rgolConnectIn[CONNECT_COUNT];
SRVEXTERN HANDLE rghPipeIn[CONNECT_COUNT];
SRVEXTERN OVERLAPPED olConnectOut;
SRVEXTERN BOOL bOutPipeConnected;
SRVEXTERN HANDLE hPipeOut;
SRVEXTERN HANDLE hConnectOutTimer;
//
// Indexes into rghWait array for multiple-wait
//
#define WAITIDX_CHILD_PROCESS 0
#define WAITIDX_READ_STDIN_DONE 1
#define WAITIDX_QUERYSRV_WAIT 2
#define WAITIDX_PER_PIPE_EVENT 3
#define WAITIDX_CONNECT_OUT 4
#define WAITIDX_CONNECT_IN_BASE 5
#define MAX_WAIT_HANDLES (WAITIDX_CONNECT_IN_BASE + CONNECT_COUNT)
SRVEXTERN HANDLE rghWait[MAX_WAIT_HANDLES];
SRVEXTERN OVERLAPPED ReadChildOverlapped;
SRVEXTERN HANDLE hReadChildOutput;
SRVEXTERN BYTE ReadChildBuffer[BUFFSIZE];
SRVEXTERN PREMOTE_CLIENT pLocalClient;
typedef struct tagCOPYPIPE {
HANDLE hRead;
HANDLE hWrite;
} COPYPIPE, *PCOPYPIPE;
SRVEXTERN COPYPIPE rgCopyPipe[2];
SRVEXTERN volatile DWORD dwWriteFilePointer; // used by SrvCtrlHand (thread)
SRVEXTERN OVERLAPPED QueryOverlapped;
SRVEXTERN HANDLE hQPipe;
SRVEXTERN OVERLAPPED olMainThread;
BOOL
APIENTRY
MyCreatePipeEx(
OUT LPHANDLE lpReadPipe,
OUT LPHANDLE lpWritePipe,
IN LPSECURITY_ATTRIBUTES lpPipeAttributes,
IN DWORD nSize,
DWORD dwReadMode,
DWORD dwWriteMode
);
DWORD
WINAPI
CopyPipeToPipe(
LPVOID lpCopyPipeData
);
DWORD
WINAPI
CopyStdInToPipe(
LPVOID lpCopyPipeData
);
VOID
FASTCALL
StartSession(
PREMOTE_CLIENT pClient
);
VOID
FASTCALL
StartLocalSession(
VOID
);
VOID
FASTCALL
StartReadClientInput(
PREMOTE_CLIENT pClient
);
VOID
WINAPI
ReadClientInputCompleted(
DWORD dwError,
DWORD cbRead,
LPOVERLAPPED lpO
);
VOID
WINAPI
WriteChildStdInCompleted(
DWORD dwError,
DWORD cbWritten,
LPOVERLAPPED lpO
);
#define OUT_PIPE -1
VOID
FASTCALL
CreatePipeAndIssueConnect(
int nIndex // IN pipe index or OUT_PIPE
);
VOID
FASTCALL
HandleOutPipeConnected(
VOID
);
VOID
APIENTRY
ConnectOutTimerFired(
LPVOID pArg,
DWORD dwTimerLo,
DWORD dwTimerHi
);
VOID
FASTCALL
HandleInPipeConnected(
int nIndex
);
VOID
FASTCALL
HandshakeWithRemoteClient(
PREMOTE_CLIENT pClient
);
VOID
FASTCALL
StartChildOutPipeRead(
VOID
);
VOID
WINAPI
ReadChildOutputCompleted(
DWORD dwError,
DWORD cbRead,
LPOVERLAPPED lpO
);
VOID
WINAPI
WriteTempFileCompleted(
DWORD dwError,
DWORD cbWritten,
LPOVERLAPPED lpO
);
VOID
FASTCALL
StartServerToClientFlow(
VOID
);
VOID
FASTCALL
StartReadTempFile(
PREMOTE_CLIENT pClient
);
VOID
WINAPI
ReadTempFileCompleted(
DWORD dwError,
DWORD cbRead,
LPOVERLAPPED lpO
);
VOID
FASTCALL
StartWriteSessionOutput(
PREMOTE_CLIENT pClient
);
BOOL
FASTCALL
WriteSessionOutputCompletedCommon(
PREMOTE_CLIENT pClient,
DWORD dwError,
DWORD cbWritten,
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
VOID
WINAPI
WriteSessionOutputCompletedWriteNext(
DWORD dwError,
DWORD cbWritten,
LPOVERLAPPED lpO
);
VOID
WINAPI
WriteSessionOutputCompletedReadNext(
DWORD dwError,
DWORD cbWritten,
LPOVERLAPPED lpO
);
VOID
FASTCALL
HandshakeWithRemoteClient(
PREMOTE_CLIENT pClient
);
VOID
WINAPI
ReadClientNameCompleted(
DWORD dwError,
DWORD cbRead,
LPOVERLAPPED lpO
);
VOID
WINAPI
WriteServerReplyCompleted(
DWORD dwError,
DWORD cbWritten,
LPOVERLAPPED lpO
);
VOID
WINAPI
ReadClientStartupInfoSizeCompleted(
DWORD dwError,
DWORD cbRead,
LPOVERLAPPED lpO
);
VOID
WINAPI
ReadClientStartupInfoCompleted(
DWORD dwError,
DWORD cbRead,
LPOVERLAPPED lpO
);
PCHAR
GetFormattedTime(
BOOL bDate
);
HANDLE
ForkChildProcess( // Creates a new process
char *cmd, // Redirects its stdin,stdout
PHANDLE in, // and stderr - returns the
PHANDLE out // corresponding pipe ends.
);
BOOL
FilterCommand( //Filters input from client
REMOTE_CLIENT *cl, //for commands intended for REMOTE
char *buff,
int dread
);
BOOL
WINAPI
SrvCtrlHand(
DWORD event
);
DWORD
WINAPI
SendStatus(
LPVOID lpSendStatusParm
);
DWORD
WINAPI
ShowPopup(
void *vpArg
);
VOID
RemoveInpMark(
char* Buff,
DWORD Size
);
VOID
CloseClient(
REMOTE_CLIENT *Client
);
PSECURITY_DESCRIPTOR
FormatSecurityDescriptor(
CHAR * * DenyNames,
DWORD DenyCount,
CHAR * * Names,
DWORD Count
);
BOOL
FASTCALL
HandleSessionError(
PREMOTE_CLIENT pClient,
DWORD dwError
);
VOID
FASTCALL
CleanupTempFiles(
PSZ pszTempDir
);
VOID
FASTCALL
SetupSecurityDescriptors(
VOID
);
VOID
FASTCALL
RuntimeLinkAPIs(
VOID
);
VOID
FASTCALL
InitializeClientLists(
VOID
);
VOID
FASTCALL
AddClientToHandshakingList(
PREMOTE_CLIENT pClient
);
VOID
FASTCALL
MoveClientToNormalList(
PREMOTE_CLIENT pClient
);
VOID
FASTCALL
MoveClientToClosingList(
PREMOTE_CLIENT pClient
);
PREMOTE_CLIENT
FASTCALL
RemoveFirstClientFromClosingList(
VOID
);
VOID
InitAd(
BOOL IsAdvertise
);
VOID
ShutAd(
BOOL IsAdvertise
);
VOID
APIENTRY
AdvertiseTimerFired(
LPVOID pArg,
DWORD dwTimerLo,
DWORD dwTimerHi
);
VOID
WINAPI
WriteMailslotCompleted(
DWORD dwError,
DWORD cbWritten,
LPOVERLAPPED lpO
);
VOID
FASTCALL
InitializeQueryServer(
VOID
);
VOID
FASTCALL
QueryWaitCompleted(
VOID
);
VOID
FASTCALL
StartServingQueryPipe(
VOID
);
DWORD
WINAPI
QueryHandlerThread(
LPVOID lpUnused
);
BOOL
CALLBACK
EnumWindowProc(
HWND hWnd,
LPARAM lParam
);
//
// Declare pointers to runtime-linked functions
//
HANDLE
(WINAPI *pfnCreateWaitableTimer)(
LPSECURITY_ATTRIBUTES lpTimerAttributes,
BOOL bManualReset,
LPCSTR lpTimerName
);
BOOL
(WINAPI *pfnSetWaitableTimer)(
HANDLE hTimer,
const LARGE_INTEGER *lpDueTime,
LONG lPeriod,
PTIMERAPCROUTINE pfnCompletionRoutine,
LPVOID lpArgToCompletionRoutine,
BOOL fResume
);
BOOL
(WINAPI *pfnCancelWaitableTimer)(
HANDLE hTimer
);
BOOL
(WINAPI *pfnCancelIo)(
HANDLE hFile
);
#define CANCELIO(hFile) (pfnCancelIo) ? ( pfnCancelIo(hFile) ) : 0;
NET_API_STATUS
(NET_API_FUNCTION *pfnNetWkstaGetInfo)(
IN LPTSTR servername OPTIONAL,
IN DWORD level,
OUT LPBYTE *bufptr
);
NET_API_STATUS
(NET_API_FUNCTION *pfnNetApiBufferFree)(
IN LPVOID Buffer
);