/******************************************************************************\ * 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 // 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[MAX_PATH]; //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 );