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