/*++ Copyright (C) Microsoft Corporation, 2000 Module Name: SContext.hxx Abstract: Class definitions for the server side context handles. Author: Kamen Moutafov [KamenM] Revision History: KamenM Sep 2000 Created --*/ #if _MSC_VER >= 1200 #pragma once #endif #ifndef __SCONTEXT_HXX_ #define __SCONTEXT_HXX_ class ServerContextHandle { public: ServerContextHandle ( IN void *CtxGuard ) { // leave ContextChain uninitialized for now UserContext = NULL; UserRunDown = NULL; this->CtxGuard = CtxGuard; RpcpMemorySet(&WireContext, 0, sizeof(WIRE_CONTEXT)); OwnerSID = NULL; ReferenceCount = 1; Flags = ContextPendingAlloc; DeadlockTag = 0; } inline void AddReference ( void ) { long LocalRefCount; ASSERT(ReferenceCount >= 0); LocalRefCount = InterlockedIncrement(&ReferenceCount); LogEvent(SU_CTXHANDLE, EV_INC, this, 0, LocalRefCount, 1, 0); } inline long RemoveReference ( void ) { long LocalRefCount; LocalRefCount = InterlockedDecrement(&ReferenceCount); LogEvent(SU_CTXHANDLE, EV_DEC, this, 0, LocalRefCount, 1, 0); ASSERT(LocalRefCount >= 0); return LocalRefCount; } LIST_ENTRY ContextChain; // entry for the context chain void *UserContext; // context for the user NDR_RUNDOWN UserRunDown; // user routine to call void *CtxGuard; WIRE_CONTEXT WireContext; // a context handle is not locked until it is put into ContextCompletedAlloc // state and inserted into the collection. SWMRLock Lock; PSID OwnerSID; // Not protected. Use interlocks. There is one lifetime reference, // and one or more usage reference. Two paths may clear the lifetime // reference - the rundown and the marshall path. Both have the lock // and need to check for the deleted flag to avoid the case where both // take the lifetime reference // Whenever the lifetime reference is taken away, the object must be // removed from the collection so that no new code picks it up long ReferenceCount; // All contexts in the collection must have the ContextCompletedAlloc // flag. Since by the time they enter the collection, this flags // is constant, no synchronization discipline are necessary for this // flag static const long ContextPendingAlloc = 0; static const long ContextCompletedAlloc = 1; static const long ContextAllocState = 1; // Set in the rundown and marshall paths. Checked in the // the marshall path. All those paths // set it/check it under the protection of the // collection lock. If this flag is set, the context is already // removed, and the lifetime reference is taken away - don't remove // it and don't take the lifetime reference // The opposite is also true - if the context handle is in the // collection, this flag must not be set static const long ContextRemovedFromCollection = 2; static const long ContextRemovedFromCollectionMask = 2; // Set in the rundown path. Checked whenever the refcount drops // to 0. In both cases protected by the collection lock static const long ContextNeedsRundown = 4; static const long ContextNeedsRundownMask = 4; // the first time newly created context is marshalled, this flag // is raised. The first time it is unmarshalled, it is taken down // This allows us to figure out which contexts have been created, // but not returned to the client in case marshalling fails and treat // them appropriately. Set in the marshalling path. Checked in the // unmarshall path. In both cases this is done under the protection // of the lock static const long ContextNewlyCreated = 8; static const long ContextNewlyCreatedMask = 8; // can be ContextDeleted, ContextPendingAlloc/ContextCompletedAlloc, // ContextNeedsRundown, ContextNewlyCreated // Protected by the collection lock for all context handles inserted // in the collection. No protection needed for the others as no // multithreaded access is possible unsigned long Flags; // When multiple Context handles are active in a call, the possibility // of cross-call deadlock exists. This field is used to detect possible // deadlocks when unmarshalling a context handle. The routines AquireDeadlockProtection // and ReleaseDeadlockProtection use this value to detect possible deadlock, // see those routines for an explanation of the algorithm. volatile long DeadlockTag; }; #endif // __SCONTEXT_HXX