/*++ Copyright (c) 1995-96 Microsoft Corporation Module Name: ssets.hxx Abstract: CServerSet objects represent sets of CServerOids which are owned by a particular client. The same CServerOids may appear in a large number of sets. CServerSets are mangaged by an instance of the CServerSetTable class. This object (pServerSets) can be used to allocate (exclusive lock) and lookup (shared lock) sets. It can also be used (shared lock) by the worker thread to rundowns old CServerSet's. Author: Mario Goertzel [MarioGo] Revision History: MarioGo 02-27-95 Bits 'n pieces MarioGo 04-04-95 Split client and server. MarioGo 01-06-96 Locally unique Ids, added new management class --*/ #ifndef __SSET_HXX #define __SSET_HXX class CServerSet /*++ Class Description: Each instance for this class represtents a set of oids which are being used by a particular client. This client may or may not be making secure calls to this objext resolver. If the calls are secure, the SID of the client is remembered and compared during any operation changing the contents of the set. Members: _timeout - The time at which this set should rundown. _blistOids - List of pointers to all the CServerOids in this set. _psid - Security ID of the client. NULL for non-secure set. _sequence - The sequence number of the last good ping. Used to avoid problems with multiple execution since pings are idempotent. _period - Power of two multipler for timeout period. Not implemented. _psid - Pointer to the sid of the client or NULL. _fLocal - (need 1 bit) non-zero if the client is on this machine. --*/ { private: CTime _timeout; PSID _psid; CBList _blistOids; USHORT _sequence; USHORT _pings; USHORT _fLocal:8; // free bits // Free USHORT BOOL ValidateObjects(BOOL fShared); public: CServerSet(USHORT sequence, PSID psid, BOOL fLocal) : _blistOids(8), _sequence(sequence - 1), _psid(psid), _fLocal((USHORT) fLocal) { _timeout += BaseTimeoutInterval; // * factor } ~CServerSet() { #if DBG CTime now; ASSERT(now > _timeout); #endif if (!_fLocal) { ASSERT(gpPingSetQuotaManager); gpPingSetQuotaManager->ManageQuotaForUser(_psid, FALSE); } delete _psid; } BOOL Ping(BOOL fShared) { _timeout.SetNow(); _timeout += BaseTimeoutInterval; // * factor _pings++; if (_pings % BaseNumberOfPings == 0) { return(ValidateObjects(fShared)); } return(fShared); } BOOL CheckAndUpdateSequenceNumber(USHORT sequence) { // note: this handles overflow cases, too. USHORT diff = sequence - _sequence; if (diff && diff <= BaseNumberOfPings) { _sequence = sequence; return(TRUE); } return(FALSE); } BOOL CheckSecurity(HANDLE hRpc) { // Local calls are secure if (0 == hRpc) { ASSERT(0 == _psid ); return(TRUE); } // No security on the set if (0 == _psid) { return(TRUE); } BOOL f; RPC_STATUS status; HANDLE hT; status = RpcImpersonateClient(hRpc); if (status == RPC_S_OK) { f = OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_QUERY, TRUE, &hT); if (!f) { return(FALSE); } } else { #if DBG SetLastError(status); #endif return(FALSE); } ULONG needed = DEBUG_MIN(1, 24); PTOKEN_USER ptu; do { ptu = (PTOKEN_USER)alloca(needed); ASSERT(ptu); f = GetTokenInformation(hT, TokenUser, (PBYTE)ptu, needed, &needed); } while( FALSE == f && GetLastError() == ERROR_INSUFFICIENT_BUFFER); CloseHandle(hT); if (FALSE != f) { ASSERT(needed > sizeof(SID)); f = EqualSid(_psid, ptu->User.Sid); return(f); } return(FALSE); } ORSTATUS AddObject(OID &oid); void RemoveObject(OID &oid); BOOL ShouldRundown() { CTime now; return(now > _timeout); } BOOL Rundown(); }; class CServerSetTable /*++ Class Description: Management class for allocating and looking up CServerSets. Each set is associated with an ID which is made up of an index and a sequence number. The index is used to index into _pElements and the sequence number is used to avoid problems with old set ID and a new server. Members: _pElements - An array (size _cMax) of IndexElement structures IndexElement- _sequence - A sequence number used to detect invalid referneces to a slot which has rundown and been realloc'd. _pSet - A pointer to the actual CServerSet. If the slot is free it is 0x80000000 & index of next free slot. _cMax - The number of slots in _pElements. _cAllocated - The number of slots in use. _iFirstFree - (Hint) A starting place of where to look when trying to insert. No elements < _iFirstFree are free. _iRundown - Index of the rundown checker. It is written to with a shared lock held. This is okay. --*/ { struct IndexElement { DWORD _sequence; CServerSet *_pSet; }; public: CServerSetTable(ORSTATUS &status) : _cMax(DEBUG_MIN(16,4)), _cAllocated(0), _iFirstFree(0), _iRundown(0) { _pElements = new IndexElement[_cMax]; if (!_pElements) { status = OR_NOMEM; } else { OrMemorySet(_pElements, 0, sizeof(IndexElement) * _cMax); status = OR_OK; } } CServerSet *Allocate(IN USHORT sequence, IN PSID psid, IN BOOL fLocal, OUT ID &setid); CServerSet *Lookup(IN ID setid); DWORD Size() { return(_cAllocated); } // Used for set cleanup by worker and SimplePing. ID CheckForRundowns(); BOOL RundownSetIfNeeded(SETID id); void PingAllSets(); private: IndexElement *_pElements; DWORD _cMax; DWORD _cAllocated; DWORD _iFirstFree; DWORD _iRundown; }; #endif // __SSET_HXX