288 lines
7 KiB
C++
288 lines
7 KiB
C++
/*++
|
|
|
|
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
|
|
|