|
|
/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
pipedata.hxx
Abstract:
Encapsulation of message passing over named pipes.
IPM_MESSAGEs are delivered messages from the other side of the pipe IPM_MESSAGE_ACCEPTORs is the interface clients of this API must implement
IPM_MESSAGE_PIPE is the creation, deletion, and write interface for this API
Threading: It is valid to call the API on any thread Callbacks can occur on an NT thread, or on the thread that was calling into the API.
Author:
Jeffrey Wall (jeffwall) 9/12/2001
Revision History:
--*/
#ifndef _PIPEDATA_HXX_
#define _PIPEDATA_HXX_
//
// When starting in backward compatibility mode, we use a well known pipe name
//
#define WEB_ADMIN_SERVICE_INETINFO_PIPENAME L"\\\\.\\pipe\\iisipm14acf167-60fe-4c1d-8563-f209abaa8f4b"
enum IPM_WP_SHUTDOWN_MSG;
//
// IPM opcodes
//
// **********************************
// These must be kept in synch with the METADATA for the opcodes below.
// **********************************
//
enum IPM_OPCODE { IPM_OP_MINIMUM = 0, IPM_OP_PING, IPM_OP_PING_REPLY, IPM_OP_WORKER_REQUESTS_SHUTDOWN, IPM_OP_SHUTDOWN, IPM_OP_REQUEST_COUNTERS, IPM_OP_SEND_COUNTERS, IPM_OP_PERIODIC_PROCESS_RESTART_PERIOD_IN_MINUTES, IPM_OP_PERIODIC_PROCESS_RESTART_MEMORY_USAGE_IN_KB, IPM_OP_PERIODIC_PROCESS_RESTART_SCHEDULE, IPM_OP_GETPID, IPM_OP_HRESULT, IPM_OP_MAXIMUM };
struct IPM_OPCODE_METADATA { size_t sizeMaximumAndRequiredSize; BOOL fServerSideExpectsThisMessage; };
IPM_OPCODE_METADATA IPM_OP_DATA_SIZE [] = { { 0, FALSE }, //IPM_OP_MINIMUM
{ 0, FALSE }, //IPM_OP_PING
{ 0, TRUE }, //IPM_OP_PING_REPLY
{ sizeof(IPM_WP_SHUTDOWN_MSG), TRUE }, //IPM_OP_WORKER_REQUESTS_SHUTDOWN
{ sizeof(BOOL), FALSE }, // IPM_OP_SHUTDOWN
{ 0, FALSE }, //IPM_OP_REQUEST_COUNTERS
{ MAXLONG, TRUE }, //IPM_OP_SEND_COUNTERS
{ sizeof(DWORD), FALSE }, //IPM_OP_PERIODIC_PROCESS_RESTART_PERIOD_IN_MINUTES
{ 2 * sizeof(DWORD), FALSE }, //IPM_OP_PERIODIC_PROCESS_RESTART_MEMORY_USAGE_IN_KB
{ MAXLONG, FALSE }, //IPM_OP_PERIODIC_PROCESS_RESTART_SCHEDULE
{ sizeof(DWORD), TRUE }, //IPM_OP_GETPID
{ sizeof(HRESULT), TRUE }, //IPM_OP_HRESULT
{ 0, FALSE } //IPM_OP_MAXIMUM
};
//
// Data sent on a IPM_OP_WORKER_REQUESTS_SHUTDOWN message, to give the
// reason for the message.
//
enum IPM_WP_SHUTDOWN_MSG { IPM_WP_MINIMUM = 0, IPM_WP_RESTART_COUNT_REACHED, IPM_WP_IDLE_TIME_REACHED, IPM_WP_RESTART_SCHEDULED_TIME_REACHED, IPM_WP_RESTART_ELAPSED_TIME_REACHED, IPM_WP_RESTART_VIRTUAL_MEMORY_LIMIT_REACHED, IPM_WP_RESTART_ISAPI_REQUESTED_RECYCLE, IPM_WP_RESTART_PRIVATE_BYTES_LIMIT_REACHED, IPM_WP_MAXIMUM };
//
// forward declarations and export directives
//
class dllexp IPM_MESSAGE_PIPE; class IPM_MESSAGE_IMP;
//
// There is one implementation of this interface (IPM_MESSAGE_IMP)
//
// The implementation is not exposed here because it has many more
// public methods (ex: SetData) that are not needed by MESSAGE_ACCEPTORs
// and serve only to confuse the data abstraction being exposed.
//
class IPM_MESSAGE { public: //
// returns the IPM_OPCODE associated with this message
//
virtual IPM_OPCODE GetOpcode() const = 0;
//
// returns the data length of the message
//
virtual DWORD GetDataLen() const = 0;
//
// returns a pointer to the data of the message
//
virtual const BYTE * GetData() const = 0; }; // IPM_MESSAGE
//
// Users of this pipe mechanism are required to implement this interface
// to receive pipe event callbacks.
//
// These callbacks will occur on NT Thread Pool threads, or sometimes
// on the same thread that was used in a call to any MESSAGE_PIPE
// instance
//
class IPM_MESSAGE_ACCEPTOR { public: //
// Called when an IPM_MESSAGE is received on the pipe
//
virtual VOID AcceptMessage(IN CONST IPM_MESSAGE * pMessage) = 0;
//
// Called when the pipe is ready to read and write data
//
virtual VOID PipeConnected() = 0;
//
// Called when the pipe is no longer connected
//
virtual VOID PipeDisconnected(IN HRESULT Error) = 0;
//
// Called when an invalid message has arrived from the other side of the pipe
//
virtual VOID PipeMessageInvalid() = 0; }; // IPM_MESSAGE_ACCEPTOR
//
// interface to pipe mechanism.
//
class IPM_MESSAGE_PIPE { private: IPM_MESSAGE_PIPE(); ~IPM_MESSAGE_PIPE(); public:
// Create returns a IPM_MESSAGE_PIPE for use
static HRESULT CreateIpmMessagePipe(IPM_MESSAGE_ACCEPTOR * pAcceptor, // callback class
LPCWSTR pszPipeName, // name of pipe
BOOL fServerSide, // TRUE for CreateNamedPipe, FALSE for CreateFile
PSECURITY_ATTRIBUTES pSa, // security attributes to apply to pipe
IPM_MESSAGE_PIPE ** ppPipe); // outgoing pipe
// Destroy disconnects the IPM_MESSAGE_PIPE, blocks until all work is finished, and deletes the IPM_MESSAGE_PIPE
VOID DestroyIpmMessagePipe(); // WriteMessage places a message on the pipe
HRESULT WriteMessage(IPM_OPCODE opcode, DWORD dwDataLen, LPVOID pbData);
//
// The following functions are not for public consumption.
// If you abuse them, I'll take them away.
//
BOOL IsValid();
VOID IpmMessageCreated(IPM_MESSAGE_IMP *); VOID IpmMessageDeleted(IPM_MESSAGE_IMP *);
// Register wait callback function
static VOID CALLBACK MessagePipeCompletion(LPVOID pvoid, BOOLEAN TimerOrWaitFired);
private: DWORD m_dwSignature;
// handle to NT pipe
HANDLE m_hPipe;
// callback pointer
IPM_MESSAGE_ACCEPTOR * m_pAcceptor;
// TRUE if CreateNamedPipe was called, otherwise FALSE;
BOOL m_fServerSide; // count of # of outstanding messages
LONG m_cMessages;
// list of outstanding messages
LIST_ENTRY m_listHead;
//
// synchronization for list
//
CRITICAL_SECTION m_critSec;
//
// to be able to tell if initialization of critsec completed successfully
//
BOOL m_fCritSecInitialized;
//
// Saved failed disconnect hresult, just in case
// the hresult can't be communicated immediately.
//
HRESULT m_hrDisconnect;
//
// Number of outstanding current users of the m_pAcceptor variable
//
ULONG m_cAcceptorUseCount;
// safely increment m_cAcceptorUseCount
VOID IncrementAcceptorInUse();
// safely decrement m_cAcceptorUseCount and if appropriate, call NotifyPipeDisconnected
VOID DecrementAcceptorInUse(); // Issue a read for a given size
HRESULT ReadMessage(DWORD dwReadSize);
// Notify the IPM_MESSAGE_ACCEPTOR exactly once that an error has occurred
VOID NotifyPipeDisconnected(HRESULT hrError); }; // IPM_MESSAGE_PIPE
#endif // _PIPEDATA_HXX_
|