657 lines
12 KiB
C
657 lines
12 KiB
C
|
|
/******************************************************************************\
|
|
* 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[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
|
|
);
|