2025-04-27 07:49:33 -04:00

413 lines
8.0 KiB
C++

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
oxid.hxx
Abstract:
COxid objects represent OXIDs which are in use by processes on this machine.
These always contain a pointer to a process object and a ping set.
Author:
Satish Thatte [SatishT]
Revision History:
SatishT 02-07-96 Merged and simplified Client and Server Oxid classes
--*/
#ifndef __OXID_HXX
#define __OXID_HXX
class COxid; // forward decl
//
// The following package is given to a rundown thread when it is created.
// The pSelf pointer is used to do actual rundowns of owned Oids.
// The flag fKeepRunning is used by the owner COxid to signal the
// thread to stop running when the COxid dies.
//
struct SRundownThreadInfo
{
COxid *pSelf;
BOOL fKeepRunning;
};
struct COxidInfo
{
OXID_INFO _oxidInfo; // bindings pointer is defunct
CDSA _dsaBindings; // bindings are kept separately
COxidInfo(const OXID_INFO& OxidInfo)
: _oxidInfo(OxidInfo),
_dsaBindings(OxidInfo.psa) // bindings are process-wide, except for remote OXIDs
{}
operator OXID_INFO()
{
_oxidInfo.psa = _dsaBindings;
return _oxidInfo;
}
ORSTATUS Assign(const OXID_INFO& Info);
};
class CId2Key : public ISearchKey
{
public:
CId2Key(const ID id1, const ID id2) : _id1(id1), _id2(id2) { }
virtual DWORD
Hash()
{
return( (DWORD)_id2 ^ (*((DWORD *)&_id2 + 1))
^ (DWORD)_id1 ^ (*((DWORD *)&_id1 + 1)) );
}
virtual BOOL
Compare(ISearchKey &tk)
{
CId2Key &idk = (CId2Key &)tk;
return(idk._id2 == _id2
&& idk._id1 == _id1);
}
ID Id1()
{
return _id1;
}
ID Id2()
{
return _id2;
}
protected:
ID _id1,_id2;
};
class COid : public CTableElement, public CTime // the time of last release, implicitly
// set to creation time by constructor
/*++
Class Description:
Each instance of this class represents an OID registered
by a client or a server on this machine.
Members:
_pOxid - A pointer to the OXID to which this OID belongs.
We own a reference.
--*/
{
private :
COxid * _pOxid;
CId2Key _Key;
// declare the members needed for a page static allocator
DECL_PAGE_ALLOCATOR
public :
COid(
COxid *pOxid,
OID Oid
);
~COid();
// declare the page-allocator-based new and delete operators
DECL_NEW_AND_DELETE
COid():_Key(0,0){}
operator ISearchKey&() // this allows us to be a ISearchKey as well
{
return _Key;
}
virtual DWORD Release()
{
SetNow(); // timestamp the release
return CReferencedObject::Release();
}
OXID GetOID()
{
return _Key.Id1();
}
BOOL OkToRundown();
void Rundown();
COxid *GetOxid()
{
return(_pOxid);
}
};
DEFINE_TABLE(COid)
DEFINE_LIST(COid)
class COxid : public CTableElement
/*++
Class Description:
Each instance of this class represents an OXID (i.e., an apartment).
Each OXID is owned,
referenced, by the owning process and the OIDs registered by
that process for this OXID.
Members:
_pProcess - Pointer to the process instance which owns this oxid.
_info - Info registered by the process for this oxid.
_pMid - Pointer to the machine ID for this OXID, we
own a reference.
_fApartment - Server is aparment model if non-zero
_fRunning - Process has not released this oxid if non-zero.
--*/
{
friend class CProcess;
friend class COid;
private:
CProcess *_pProcess;
COxidInfo _info;
CMid *_pMid;
CId2Key _Key;
USHORT _protseq;
BOOL _fApartment;
BOOL _fRunning;
BOOL _fLocal;
union
{
struct
{
DWORD _dwTimeStamp;
} _remote;
struct
{
BOOL _fRundownThreadStarted;
HANDLE _hRundownThread;
BOOL *_pfRundownThreadKeepRunning;
} _local;
} _optional;
COidTable _MyOids;
// declare the members needed for a page static allocator
DECL_PAGE_ALLOCATOR
public:
COxid(
OXID Oxid, // constructor for remote OXIDs
CMid *pMid,
USHORT wProtseq,
OXID_INFO &OxidInfo
);
COxid( // constructor for local OXIDs
CProcess *pProcess,
OXID_INFO &OxidInfo,
BOOL fApartment
);
~COxid();
// declare the page-allocator-based new and delete operators
DECL_NEW_AND_DELETE
operator ISearchKey&() // this allows us to be a ISearchKey as well
{
return _Key;
}
DWORD GetTid()
{
return(_info._oxidInfo.dwTid);
}
BOOL IsRunning()
{
return(_fRunning);
}
BOOL IsLocal()
{
return(_fLocal);
}
BOOL IsApartment()
{
return(_fApartment);
}
MID GetMID()
{
return _Key.Id2();
}
OXID GetOXID()
{
return _Key.Id1();
}
CMid *GetMid()
{
return _pMid;
}
CProcess *GetProcess()
{
return _pProcess;
}
SETID GetSetid();
ORSTATUS
COxid::UpdateInfo(OXID_INFO *pInfo)
{
ASSERT(pInfo);
return _info.Assign(*pInfo);
}
ORSTATUS GetInfo(
OUT OXID_INFO *
);
ORSTATUS GetRemoteInfo(
IN USHORT cClientProtseqs,
IN USHORT *aClientProtseqs,
IN USHORT cInstalledProtseqs,
IN USHORT *aInstalledProtseqs,
OUT OXID_INFO *pInfo
);
void RundownOids(USHORT cOids,
OID aOids[],
BYTE aStatus[]);
ORSTATUS LazyUseProtseq(USHORT, USHORT[]);
void StopRunning();
ORSTATUS StartRundownThreadIfNecessary();
ORSTATUS StopRundownThreadIfNecessary();
ORSTATUS StopTimerIfNecessary(); // must be called by owner thread
ORSTATUS OwnOid(COid *pOid);
COid * DisownOid(COid *pOid);
void ReleaseAllOids();
BOOL HasExpired();
private:
friend VOID CALLBACK RundownTimerProc(
HWND hwnd, // handle of window for timer messages
UINT uMsg, // WM_TIMER message
UINT idEvent, // timer identifier
DWORD dwTime // current system time
);
friend DWORD _stdcall RundownThread(void *pRundownInfo);
friend DWORD _stdcall PingThread(void);
void RundownOidsIfNecessary(IRundown *);
};
DEFINE_TABLE(COxid)
DEFINE_LIST(COxid)
//
// decl for rundown thread function -- the parameter is the rundown info
//
DWORD _stdcall RundownThread(void *pRundownInfo);
//
// Inline COid methods which depend on COxid methods
//
inline
COid::COid(
COxid *pOxid,
OID Oid = AllocateId() // default applies to local Oids
) :
_Key(Oid,pOxid->GetMID()),
_pOxid(pOxid)
{
ASSERT(_pOxid);
_pOxid->Reference();
}
inline
COid::~COid()
{
#if DBG
// This object has already been removed from gpOidTable
// However, the same OID/MID may have been subsequently
// unmarshalled and inserted again into gpOidTable.
// So we use pointer identity to make sure this
// object is not still in the table.
COid *pt = gpOidTable->Lookup(*this);
ASSERT(pt != this && "Oid object still in global table during destruct");
#endif
ASSERT(_pOxid);
_pOxid->Release();
}
#endif // __OXID_HXX