mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
485 lines
17 KiB
485 lines
17 KiB
//+------------------------------------------------------------------------
|
|
//
|
|
// File: ipidtbl.hxx
|
|
//
|
|
// Contents: MID (machine identifier) table.
|
|
// OXID (object exporter identifier) table.
|
|
// IPID (interface pointer identifier) table.
|
|
//
|
|
// Classes: CMIDTable
|
|
// COXIDTable
|
|
// CIPIDTable
|
|
//
|
|
// History: 02-Feb-95 Rickhi Created
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
#ifndef _IPIDTBL_HXX_
|
|
#define _IPIDTBL_HXX_
|
|
|
|
#include <pgalloc.hxx> // CPageAllocator
|
|
#include <lclor.h> // local OXID resolver interface
|
|
#include <remoteu.hxx> // CRemoteUnknown
|
|
#include <locks.hxx> // ASSERT_LOCK_HELD
|
|
#include <hash.hxx> // CStringHashTable
|
|
|
|
|
|
// forward declarations
|
|
class CRpcChannelBuffer;
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// This structure defines an Entry in the MID table. There is one MID
|
|
// table for the entire process. There is one MIDEntry per machine that
|
|
// the current process is talking to (including one for the local machine).
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
typedef struct tagMIDEntry
|
|
{
|
|
SStringHashNode Node; // hash chain and key
|
|
MID mid; // machine identifier
|
|
LONG cRefs; // count of IPIDs using this OXIDEntry
|
|
DWORD dwFlags; // state flags
|
|
} MIDEntry;
|
|
|
|
// MID Table constants. MIDS_PER_PAGE is the number of MIDEntries
|
|
// in one page of the page allocator.
|
|
|
|
#define MIDS_PER_PAGE 5
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// class: CMIDTable
|
|
//
|
|
// Synopsis: Table of Machine IDs (MIDs) and associated information.
|
|
//
|
|
// History: 05-Jan-96 Rickhi Created
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
class CMIDTable
|
|
{
|
|
public:
|
|
void Initialize(); // initialize table
|
|
void Cleanup(); // cleanup table
|
|
|
|
HRESULT FindOrCreateMIDEntry(REFMID rmid,
|
|
DUALSTRINGARRAY *psaResolver,
|
|
MIDEntry **ppMIDEntry);
|
|
|
|
MIDEntry *LookupMID(DUALSTRINGARRAY *psaResolver, DWORD *pdwHash);
|
|
|
|
void ReleaseEntry(MIDEntry *pMIDEntry);
|
|
|
|
private:
|
|
HRESULT AddMIDEntry(REFMID rmid,
|
|
DWORD dwHash,
|
|
DUALSTRINGARRAY *psaResolver,
|
|
MIDEntry **ppMIDEntry);
|
|
|
|
static CStringHashTable _HashTbl; // hash table for MIDEntries
|
|
static CPageAllocator _palloc; // page based allocator
|
|
};
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// This structure defines an Entry in the OXID table. There is one OXID
|
|
// table for the entire process. There is one OXIDEntry per apartment.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
typedef struct tagOXIDEntry
|
|
{
|
|
struct tagOXIDEntry *pPrev; // previous entry on inuse list
|
|
struct tagOXIDEntry *pNext; // next entry on free/inuse list
|
|
DWORD dwPid; // process id of server
|
|
DWORD dwTid; // thread id of server
|
|
MOXID moxid; // object exporter identifier + machine id
|
|
IPID ipidRundown;// IPID of IRundown and Remote Unknown
|
|
DWORD dwFlags; // state flags
|
|
handle_t hServerSTA; // rpc binding handle of server
|
|
handle_t hServerMTA; // rpc binding handle of server
|
|
MIDEntry *pMIDEntry; // MIDEntry for machine where server lives
|
|
IRemUnknown *pRUSTA; // STA model proxy for Remote Unknown
|
|
IRemUnknown *pRUMTA; // MTA model proxy for Remote Unknown
|
|
LONG cRefs; // count of IPIDs using this OXIDEntry
|
|
LONG cWaiters; // count of threads waiting for OIDs
|
|
HANDLE hComplete; // set when last outstanding call completes
|
|
LONG cCalls; // number of calls dispatched
|
|
LONG cResolverRef;//References to resolver
|
|
DWORD dwPad; // keep structure 16 byte aligned
|
|
} OXIDEntry;
|
|
|
|
// bit flags for dwFlags of OXIDEntry
|
|
typedef enum tagOXIDFLAGS
|
|
{
|
|
OXIDF_REGISTERED = 0x1, // oxid is registered with Resolver
|
|
OXIDF_MACHINE_LOCAL = 0x2, // oxid is local to this machine
|
|
OXIDF_STOPPED = 0x4, // thread can no longer receive calls
|
|
OXIDF_PENDINGRELEASE = 0x8, // oxid entry is already being released
|
|
OXIDF_MSWMSG = 0x10, // use mswmsg transport
|
|
OXIDF_REGISTERINGOIDS= 0x20, // a thread is busy registering OIDs
|
|
OXIDF_MTASERVER = 0x40 // the server is an MTA apartment.
|
|
} OXIDFLAGS;
|
|
|
|
// Parameter to FindOrCreateOXIDEntry
|
|
typedef enum tagFOCOXID
|
|
{
|
|
FOCOXID_REF = 1, // Got reference from resolver
|
|
FOCOXID_NOREF = 2 // No reference from resolver
|
|
} FOCOXID;
|
|
|
|
// OXID Table constants.
|
|
#define OXIDS_PER_PAGE 10
|
|
#define OXIDTBL_MAXEXPIRED 5 // max number of expired entries to keep
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// class: COXIDTable
|
|
//
|
|
// Synopsis: Maintains a table of OXIDs and associated information
|
|
//
|
|
// History: 02-Feb-95 Rickhi Created
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
class COXIDTable
|
|
{
|
|
public:
|
|
HRESULT AddEntry(REFOXID roxid, OXID_INFO *poxidInfo,
|
|
MIDEntry *pMIDEntry, OXIDEntry **ppEntry);
|
|
|
|
void ReleaseEntry(OXIDEntry *pEntry);
|
|
|
|
HRESULT GetLocalEntry(OXIDEntry **ppEntry);
|
|
void ReleaseLocalSTAEntry(void);
|
|
void ReleaseLocalMTAEntry(void);
|
|
OXIDEntry *LookupOXID(REFOXID roxid, REFMID rmid);
|
|
|
|
HRESULT GetRemUnk(OXIDEntry *pOXIDEntry, IRemUnknown **ppRemUnk);
|
|
|
|
void Initialize(); // initialize table
|
|
void Cleanup(); // cleanup table
|
|
void FreeExpiredEntries(DWORD dwTime);
|
|
void ValidateOXID();
|
|
void FreeCleanupEntries();
|
|
DWORD NumOxidsToRemove();
|
|
void GetOxidsToRemove( OXID_REF *pRef, DWORD *pNum );
|
|
|
|
private:
|
|
|
|
void ExpireEntry(OXIDEntry *pEntry);
|
|
OXIDEntry *SearchList(REFMOXID rmoxid, OXIDEntry *pStart);
|
|
HRESULT MakeRemUnk(OXIDEntry *pOXIDEntry);
|
|
void AssertListsEmpty(void);
|
|
|
|
static DWORD _cExpired; // count of expired entries
|
|
static OXIDEntry _InUseHead; // head of InUse list.
|
|
static OXIDEntry _ExpireHead; // head of Expire list.
|
|
static OXIDEntry _CleanupHead; // head of Cleanup list.
|
|
|
|
static CPageAllocator _palloc; // page alloctor
|
|
|
|
// PERFWORK: could save space since only the first two entries of
|
|
// the InUseHead and ExpireHead are used (the list ptrs) and hence
|
|
// dont need whole OXIDEntries here.
|
|
};
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: COXIDTbl::ValidateOXID, public
|
|
//
|
|
// Synopsis: Asserts that no OXIDEntries have trashed window handles.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
inline void COXIDTable::ValidateOXID()
|
|
{
|
|
#if DBG==1
|
|
LOCK
|
|
|
|
// Check all entries in use.
|
|
OXIDEntry *pCurr = _InUseHead.pNext;
|
|
while (pCurr != &_InUseHead)
|
|
{
|
|
Win4Assert( pCurr->hServerSTA != (void *) 0xC000001C );
|
|
Win4Assert( pCurr->hServerMTA != (void *) 0xC000001C );
|
|
pCurr = pCurr->pNext;
|
|
}
|
|
UNLOCK
|
|
#endif
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: COXIDTbl::AssertListsEmpty, public
|
|
//
|
|
// Synopsis: Asserts that no OXIDEntries are in use
|
|
//
|
|
// History: 19-Apr-96 Rickhi Created
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
inline void COXIDTable::AssertListsEmpty(void)
|
|
{
|
|
// Assert that there are no entries in the InUse or Expired lists.
|
|
Win4Assert(_InUseHead.pNext == &_InUseHead);
|
|
Win4Assert(_InUseHead.pPrev == &_InUseHead);
|
|
Win4Assert(_ExpireHead.pNext == &_ExpireHead);
|
|
Win4Assert(_ExpireHead.pPrev == &_ExpireHead);
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// This structure defines an Entry in the IPID table. There is one
|
|
// IPID table for the entire process. It holds IPIDs from local objects
|
|
// as well as remote objects.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
typedef struct tagIPIDEntry
|
|
{
|
|
struct tagIPIDEntry *pNextOID; // next IPIDEntry for same object
|
|
DWORD dwFlags; // flags (see IPIDFLAGS)
|
|
ULONG cStrongRefs; // strong reference count
|
|
ULONG cWeakRefs; // weak reference count
|
|
ULONG cPrivateRefs;// private reference count
|
|
CRpcChannelBuffer *pChnl; // channel pointer
|
|
IUnknown *pStub; // proxy or stub pointer
|
|
OXIDEntry *pOXIDEntry; // ptr to OXIDEntry in OXID Table
|
|
IPID ipid; // interface pointer identifier
|
|
IID iid; // interface iid
|
|
void *pv; // real interface pointer
|
|
DWORD pad[3]; // round size to modulus 16
|
|
} IPIDEntry;
|
|
|
|
// bit flags for dwFlags of IPIDEntry
|
|
typedef enum tagIPIDFLAGS
|
|
{
|
|
IPIDF_CONNECTING = 0x1, // ipid is being connected
|
|
IPIDF_DISCONNECTED = 0x2, // ipid is disconnected
|
|
IPIDF_SERVERENTRY = 0x4, // SERVER IPID vs CLIENT IPID
|
|
IPIDF_NOPING = 0x8, // dont need to ping the server or release
|
|
IPIDF_COPY = 0x10, // copy for security only
|
|
IPIDF_VACANT = 0x80, // entry is vacant (ie available to reuse)
|
|
IPIDF_NONNDRSTUB = 0x100, // stub does not use NDR marshaling
|
|
IPIDF_NONNDRPROXY = 0x200, // proxy does not use NDR marshaling
|
|
IPIDF_NOTIFYACT = 0x400 // notify activation on marshal/release
|
|
} IPIDFLAGS;
|
|
|
|
|
|
// IPID Table constants. IPIDS_PER_PAGE is the number of IPIDEntries
|
|
// in one page of the page allocator.
|
|
|
|
#define IPIDS_PER_PAGE 50
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// class: CIPIDTbl
|
|
//
|
|
// Synopsis: Maintains a table of IPIDs and associated information
|
|
//
|
|
// History: 02-Feb-95 Rickhi Created
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
class CIPIDTable
|
|
{
|
|
public:
|
|
IPIDEntry *LookupIPID(REFIPID ripid); // find entry in the table with
|
|
// the matching ipid
|
|
|
|
IPIDEntry *FirstFree(void);
|
|
void ReleaseEntryList(IPIDEntry *pFirst, IPIDEntry *pLast);
|
|
IPIDEntry *GetEntryPtr(LONG iEntry);
|
|
LONG GetEntryIndex(IPIDEntry *pEntry);
|
|
|
|
#if DBG==1
|
|
void AssertValid(void) {;}
|
|
void ValidateIPIDEntry(IPIDEntry *pEntry, BOOL fServerSide,
|
|
CRpcChannelBuffer *pChnl);
|
|
#else
|
|
void AssertValid(void) {;}
|
|
void ValidateIPIDEntry(IPIDEntry *pEntry, BOOL fServerSide,
|
|
CRpcChannelBuffer *pChnl) {;}
|
|
#endif
|
|
|
|
void Initialize(); // initialize table
|
|
void Cleanup(); // cleanup table
|
|
|
|
private:
|
|
static CPageAllocator _palloc; // page alloctor
|
|
};
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Global Externals
|
|
//
|
|
//+------------------------------------------------------------------------
|
|
|
|
extern CMIDTable gMIDTbl; // global table, defined in ipidtbl.cxx
|
|
extern COXIDTable gOXIDTbl; // global table, defined in ipidtbl.cxx
|
|
extern CIPIDTable gIPIDTbl; // global table, defined in ipidtbl.cxx
|
|
extern MIDEntry *gpLocalMIDEntry; // ptr to MIDEntry for current process
|
|
extern OXIDEntry *gpMTAOXIDEntry; // ptr to local OXIDEntry in MTA
|
|
extern DUALSTRINGARRAY *gpsaLocalResolver; // bindings for local OXID resolver.
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function Prototypes
|
|
//
|
|
//+------------------------------------------------------------------------
|
|
|
|
HRESULT GetLocalMIDEntry(MIDEntry **ppMIDEntry);
|
|
OXIDEntry *GetLocalOXIDEntry();
|
|
void SetLocalOXIDEntry(OXIDEntry *pOXIDEntry);
|
|
void DecOXIDRefCnt(OXIDEntry *pEntry);
|
|
void DecMIDRefCnt(MIDEntry *pEntry);
|
|
|
|
HRESULT FindOrCreateOXIDEntry(REFOXID roxid,
|
|
OXID_INFO &oxidInfo,
|
|
FOCOXID eReferenced,
|
|
DUALSTRINGARRAY *psaResolver,
|
|
REFMID rmid,
|
|
MIDEntry *pMIDEntry,
|
|
OXIDEntry **ppOXIDEntry);
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CIPIDTbl::FirstFree, public
|
|
//
|
|
// Synopsis: Finds the first available entry in the table and returns
|
|
// its index. Returns -1 if no space is available and it
|
|
// cant grow the list.
|
|
//
|
|
// History: 02-Feb-95 Rickhi Created
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
inline IPIDEntry *CIPIDTable::FirstFree()
|
|
{
|
|
return (IPIDEntry *) _palloc.AllocEntry();
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CIPIDTbl::GetEntryIndex, public
|
|
//
|
|
// Synopsis: Converts an entry ptr into an entry index
|
|
//
|
|
// History: 02-Feb-95 Rickhi Created
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
inline LONG CIPIDTable::GetEntryIndex(IPIDEntry *pIPIDEntry)
|
|
{
|
|
return _palloc.GetEntryIndex((PageEntry *)pIPIDEntry);
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Member: CIPIDTbl::GetEntryPtr, public
|
|
//
|
|
// Synopsis: Converts an entry index into an entry pointer
|
|
//
|
|
// History: 02-Feb-95 Rickhi Created
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
inline IPIDEntry *CIPIDTable::GetEntryPtr(LONG index)
|
|
{
|
|
return (IPIDEntry *) _palloc.GetEntryPtr(index);
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function: IncOXIDRefCnt, public
|
|
//
|
|
// Synopsis: increment the number of references to the OXIDEntry
|
|
//
|
|
// History: 02-Feb-95 Rickhi Created
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
inline void IncOXIDRefCnt(OXIDEntry *pEntry)
|
|
{
|
|
Win4Assert(pEntry);
|
|
ASSERT_LOCK_HELD
|
|
|
|
ComDebOut((DEB_OXID,
|
|
"IncOXIDRefCnt pEntry:%x cRefs[%x]\n", pEntry, pEntry->cRefs+1));
|
|
|
|
pEntry->cRefs++;
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function: IncMIDRefCnt, public
|
|
//
|
|
// Synopsis: increment the number of references to the MIDEntry
|
|
//
|
|
// History: 05-Janb-96 Rickhi Created
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
inline void IncMIDRefCnt(MIDEntry *pEntry)
|
|
{
|
|
Win4Assert(pEntry);
|
|
ASSERT_LOCK_HELD
|
|
|
|
ComDebOut((DEB_OXID,
|
|
"IncMIDRefCnt pEntry:%x cRefs[%x]\n", pEntry, pEntry->cRefs+1));
|
|
|
|
pEntry->cRefs++;
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function: MOXIDFromOXIDAndMID, public
|
|
//
|
|
// Synopsis: creates a MOXID (machine and object exporter ID) from
|
|
// the individual OXID and MID components
|
|
//
|
|
// History: 05-Janb-96 Rickhi Created
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
inline void MOXIDFromOXIDAndMID(REFOXID roxid, REFMID rmid, MOXID *pmoxid)
|
|
{
|
|
BYTE *pb = (BYTE *)pmoxid;
|
|
memcpy(pb, &roxid, sizeof(OXID));
|
|
memcpy(pb+8, &rmid, sizeof(MID));
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function: OXIDFromMOXID, public
|
|
//
|
|
// Synopsis: extracts the OXID from a MOXID (machine and OXID)
|
|
//
|
|
// History: 05-Jan-96 Rickhi Created
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
inline void OXIDFromMOXID(REFMOXID rmoxid, OXID *poxid)
|
|
{
|
|
memcpy(poxid, (BYTE *)&rmoxid, sizeof(OXID));
|
|
}
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function: MIDFromMOXID, public
|
|
//
|
|
// Synopsis: extracts the MID from a MOXID (machine and OXID)
|
|
//
|
|
// History: 05-Jan-96 Rickhi Created
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
inline void MIDFromMOXID(REFMOXID rmoxid, OXID *pmid)
|
|
{
|
|
memcpy(pmid, ((BYTE *)&rmoxid)+8, sizeof(MID));
|
|
}
|
|
|
|
// OID + MID versions of the above routines.
|
|
|
|
#define MOIDFromOIDAndMID MOXIDFromOXIDAndMID
|
|
#define OIDFromMOID OXIDFromMOXID
|
|
#define MIDFromMOID MIDFromMOXID
|
|
|
|
#endif // _IPIDTBL_HXX_
|