mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2131 lines
41 KiB
2131 lines
41 KiB
/*++
|
|
|
|
Microsoft Windows NT RPC Name Service
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
objects.hxx
|
|
|
|
Abstract:
|
|
|
|
This file contains the definitions of all basic classes used in the server,
|
|
excluding the data structure classes and classes used for network interactions.
|
|
|
|
Author:
|
|
|
|
Satish Thatte (SatishT) 08/21/95 Created all the code below except where
|
|
otherwise indicated.
|
|
|
|
--*/
|
|
|
|
/* BUGBUG: For every operation with a dynamic object, memory
|
|
management should be a part of the description and
|
|
specification for every parameter. Fix that along
|
|
with other documentation.
|
|
*/
|
|
|
|
#ifndef _OBJECTS_
|
|
#define _OBJECTS_
|
|
|
|
#include <memory.h>
|
|
#include <globals.hxx>
|
|
#include <locquery.h>
|
|
|
|
class CGUID;
|
|
class CInterface;
|
|
struct CBVWrapper;
|
|
class CServerEntry;
|
|
class CCacheServerEntry;
|
|
class CFullServerEntry;
|
|
class CInterfaceIndex;
|
|
struct CMailSlotReplyItem;
|
|
class CServerLookupHandle;
|
|
class CServerObjectInqHandle;
|
|
|
|
typedef TIIterator<CGUID> TGuidIterator;
|
|
|
|
|
|
// The following enumeration is the the type of entry the object is.
|
|
|
|
enum EntryType {
|
|
|
|
ServerEntryType,
|
|
GroupEntryType,
|
|
ProfileEntryType,
|
|
CacheServerEntryType,
|
|
FullServerEntryType
|
|
};
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CStringW
|
|
|
|
Abstract:
|
|
|
|
This is the unicode string wrapper class.
|
|
|
|
Note that string comparison is case insensitive.
|
|
|
|
--*/
|
|
|
|
class CStringW : public IOrderedItem {
|
|
|
|
protected:
|
|
|
|
STRING_T pszVal;
|
|
|
|
public:
|
|
|
|
int length() { return wcslen(pszVal); }
|
|
|
|
int isEmptyString() {
|
|
return (pszVal == NULL) || (_wcsicmp(pszVal,TEXT("")) == 0);
|
|
}
|
|
|
|
static STRING_T copyString(
|
|
CONST_STRING_T str
|
|
)
|
|
{
|
|
STRING_T result = new WCHAR [(wcslen(str)+1)*sizeof(WCHAR)];
|
|
wcscpy(result,str);
|
|
return result;
|
|
}
|
|
|
|
static STRING_T copyMIDLstring( // for use in out RPC parameters
|
|
// which are deallocated by stubs
|
|
CONST_STRING_T str
|
|
)
|
|
{
|
|
STRING_T result = (STRING_T) midl_user_allocate((wcslen(str)+1)*sizeof(WCHAR));
|
|
wcscpy(result,str);
|
|
return result;
|
|
}
|
|
|
|
STRING_T copyAsString() {
|
|
return copyString(pszVal);
|
|
}
|
|
|
|
STRING_T copyAsMIDLstring() { // for use in out RPC parameters
|
|
// which are deallocated by stubs
|
|
return copyMIDLstring(pszVal);
|
|
}
|
|
|
|
CStringW() {
|
|
pszVal = NULL;
|
|
}
|
|
|
|
CStringW( CONST_STRING_T p ) {
|
|
pszVal = copyString(p);
|
|
}
|
|
|
|
|
|
CStringW& operator=( const CStringW& str ) {
|
|
delete [] pszVal;
|
|
pszVal = copyString(str.pszVal);
|
|
return *this;
|
|
}
|
|
|
|
CStringW( const CStringW& str ) {
|
|
pszVal = copyString(str.pszVal);
|
|
}
|
|
|
|
|
|
virtual ~CStringW() // base class destructor should be virtual
|
|
{
|
|
delete [] pszVal;
|
|
}
|
|
|
|
operator STRING_T() { return pszVal; }
|
|
|
|
virtual int compare( const IOrderedItem& O ) {
|
|
const CStringW& S = (CStringW&) O;
|
|
return _wcsicmp(pszVal,S.pszVal);
|
|
}
|
|
};
|
|
|
|
|
|
typedef TCGuardedSkipList<CStringW> TGSLString;
|
|
typedef TCGuardedSkipListIterator<CStringW> TGSLStringIter;
|
|
typedef TCSafeSkipList<CStringW> TSSLString;
|
|
typedef TCSafeSkipListIterator<CStringW> TSSLStringIter;
|
|
typedef TCSafeLinkList<CStringW> TSLLString;
|
|
typedef TCSafeLinkListIterator<CStringW> TSLLStringIter;
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CGUID
|
|
|
|
Abstract:
|
|
|
|
This is the GUID wrapper class.
|
|
|
|
--*/
|
|
|
|
class CGUID : public IOrderedItem {
|
|
|
|
GUID rep;
|
|
|
|
public:
|
|
|
|
CGUID() {
|
|
memset(&rep,0,sizeof(rep));
|
|
}
|
|
|
|
CGUID( const GUID& g ) : rep(g) {}
|
|
|
|
virtual int compare(const IOrderedItem& C ) {
|
|
CGUID& S = (CGUID&) C;
|
|
return memcmp(&rep, &(S.rep),sizeof(rep));
|
|
}
|
|
|
|
GUID myGUID() { return rep; }
|
|
|
|
BOOL IsNil() {
|
|
|
|
RPC_STATUS dummyStatus;
|
|
|
|
return UuidIsNil(&rep,&dummyStatus);
|
|
}
|
|
|
|
CStringW* ConvertToString();
|
|
};
|
|
|
|
typedef TCSafeSkipListIterator<CGUID> TSSLGuidIterator;
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CGUIDVersion
|
|
|
|
Abstract:
|
|
|
|
This is the RPC_SYNTAX_IDENTIFIER wrapper class.
|
|
|
|
--*/
|
|
|
|
|
|
class CGUIDVersion : public IOrderedItem {
|
|
|
|
protected:
|
|
|
|
struct CidAndVersion { // this is just a readability aid for
|
|
// the implementation of isCompatibleGV
|
|
CGUID id;
|
|
unsigned short major;
|
|
unsigned short minor;
|
|
|
|
CidAndVersion (const RPC_SYNTAX_IDENTIFIER& in) : id(in.SyntaxGUID) {
|
|
major = in.SyntaxVersion.MajorVersion;
|
|
minor = in.SyntaxVersion.MinorVersion;
|
|
}
|
|
|
|
CidAndVersion() {
|
|
memset(&id,0,sizeof(GUID));
|
|
major = minor = 0;
|
|
}
|
|
};
|
|
|
|
RPC_SYNTAX_IDENTIFIER idAndVersion;
|
|
|
|
public:
|
|
|
|
CGUIDVersion( const RPC_SYNTAX_IDENTIFIER& g ) {
|
|
idAndVersion = g;
|
|
}
|
|
|
|
CGUIDVersion() {} // NULL case
|
|
|
|
RPC_SYNTAX_IDENTIFIER myIdAndVersion() { return idAndVersion; }
|
|
|
|
operator RPC_SYNTAX_IDENTIFIER() { return idAndVersion; }
|
|
|
|
GUID myGUID() { return idAndVersion.SyntaxGUID; }
|
|
|
|
virtual int compare(const IOrderedItem& C ) {
|
|
const CGUIDVersion& S = (CGUIDVersion&) C;
|
|
return memcmp(&idAndVersion, &S.idAndVersion, sizeof(RPC_SYNTAX_IDENTIFIER));
|
|
}
|
|
|
|
int isMatching(const CGUIDVersion& other, UNSIGNED32 vers_option);
|
|
|
|
int isCompatibleGV(const CGUIDVersion& other) {
|
|
return isMatching(other,RPC_C_VERS_COMPATIBLE);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CMailSlotReplyItem
|
|
|
|
Abstract:
|
|
|
|
This is the class of items to be marshalled into mailslot reply buffers.
|
|
The class, and especially the marshalling code, is dictated largely by
|
|
compatibility requirements for the old locator.
|
|
|
|
Everything in a CMailSlotReplyItem object is borrowed from some
|
|
other object and is therefore not freed upon destruction.
|
|
|
|
The primary operation is "marshall".
|
|
|
|
--*/
|
|
|
|
struct CMailSlotReplyItem : public IDataItem {
|
|
|
|
/* these are the items needed to marshall a reply packet */
|
|
|
|
RPC_SYNTAX_IDENTIFIER Interface;
|
|
RPC_SYNTAX_IDENTIFIER XferSyntax;
|
|
STRING_T binding;
|
|
STRING_T entryName;
|
|
TCSafeSkipList<CGUID> *pObjectList;
|
|
|
|
/* the marshall operation returns the number of bytes written to the buffer */
|
|
|
|
DWORD Marshall(char * pcBuffer, long lBufferSize);
|
|
|
|
};
|
|
|
|
|
|
typedef TIIterator<CMailSlotReplyItem> TMSRIIterator;
|
|
typedef TCSafeLinkList<CMailSlotReplyItem> TMSRILinkList;
|
|
typedef TCSafeLinkListIterator<CMailSlotReplyItem> TMSRILinkListIterator;
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CBVWrapper
|
|
|
|
Abstract:
|
|
|
|
This is a very thin wrapper for NSI_BINDING_VECTOR_T to make the
|
|
latter usable with linked lists (by inheriting from IDataItem).
|
|
|
|
--*/
|
|
|
|
struct CBVWrapper : public IDataItem {
|
|
NSI_BINDING_VECTOR_T *pBVT;
|
|
|
|
CBVWrapper(NSI_BINDING_VECTOR_T *p) {
|
|
pBVT = p;
|
|
}
|
|
|
|
void rundown();
|
|
|
|
// BUGBUG: should there be a destructor as a matter of principle?
|
|
};
|
|
|
|
|
|
|
|
typedef TIIterator<CBVWrapper> TBVIterator;
|
|
typedef TCSafeLinkList<CBVWrapper> TBVSafeLinkList;
|
|
typedef TCSafeLinkListIterator<CBVWrapper> TBVSafeLinkListIterator;
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CNSBinding
|
|
|
|
Abstract:
|
|
|
|
A thin wrapper for NSI_BINDING_T. Note that the strings in a NSI_BINDING_T used
|
|
to initialize a CNSBinding object are not copied, only the pointers are copied.
|
|
|
|
--*/
|
|
|
|
class CNSBinding : public CStringW
|
|
{
|
|
NSI_BINDING_T rep;
|
|
|
|
public:
|
|
|
|
CNSBinding( // this is a little crude, but hey..
|
|
NSI_BINDING_T& binding
|
|
)
|
|
:
|
|
rep(binding)
|
|
{
|
|
pszVal = catenate(
|
|
binding.string,
|
|
binding.entry_name
|
|
);
|
|
}
|
|
|
|
operator NSI_BINDING_T()
|
|
{
|
|
return rep;
|
|
}
|
|
|
|
void
|
|
copyBinding(NSI_BINDING_T& result)
|
|
{
|
|
result.string = CStringW::copyMIDLstring(rep.string);
|
|
result.entry_name = CStringW::copyMIDLstring(rep.entry_name);
|
|
result.entry_name_syntax = rep.entry_name_syntax;
|
|
}
|
|
};
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CBindingVector
|
|
|
|
Abstract:
|
|
|
|
Used mainly to keep vectors of binding handles. Iterators returning
|
|
vectors of handles is what most NS handles are in essence.
|
|
|
|
--*/
|
|
|
|
class CBindingVector : private TCSafeSkipList<CStringW>
|
|
|
|
{
|
|
CServerEntry *pMyEntry; // the entry this belongs to
|
|
|
|
public:
|
|
|
|
CBindingVector(NSI_SERVER_BINDING_VECTOR_T*, CServerEntry*);
|
|
|
|
~CBindingVector() { // must destroy binding strings stored here
|
|
wipeOut();
|
|
}
|
|
|
|
int merge(NSI_SERVER_BINDING_VECTOR_T* pHandles);
|
|
|
|
TBVSafeLinkList * formObjBVT(
|
|
TSLLString * pLLobjectStrings,
|
|
long ulVS // max BV size
|
|
);
|
|
|
|
SkipStatus insertBindingHandle(STRING_T bindingHandle) {
|
|
CStringW *pTemp = new CStringW(bindingHandle);
|
|
return insert(pTemp);
|
|
}
|
|
|
|
TMSRILinkList *msriList(
|
|
CInterface *pIf,
|
|
TCSafeSkipList<CGUID>* psslObjList
|
|
);
|
|
};
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CInterface
|
|
|
|
Abstract:
|
|
|
|
An interface and its vector of binding handles.
|
|
The interface can be searched for, using the GUIDVersion
|
|
comparison operator.
|
|
|
|
The major caveat is that we essentially ignore transfer syntax.
|
|
According to DCE, there should be a separate entry for each
|
|
interface/transfer syntax combination. We assume that NDR is
|
|
always used.
|
|
|
|
--*/
|
|
|
|
class CInterface : public CGUIDVersion {
|
|
|
|
friend class CServerEntry;
|
|
|
|
private:
|
|
|
|
CGUIDVersion transferSyntax;
|
|
CBindingVector *pBVhandles;
|
|
|
|
int mergeHandles(NSI_SERVER_BINDING_VECTOR_T* pHandles) {
|
|
return pBVhandles->merge(pHandles);
|
|
}
|
|
|
|
public:
|
|
|
|
CInterface(
|
|
NSI_INTERFACE_ID_T * lpInf,
|
|
NSI_SERVER_BINDING_VECTOR_T *BindingVector,
|
|
CServerEntry *pMyEntry
|
|
);
|
|
|
|
RPC_SYNTAX_IDENTIFIER xferSyntaxIdAndVersion() {
|
|
return transferSyntax.myIdAndVersion();
|
|
}
|
|
|
|
/* self is the same or a more recent MINOR version for both
|
|
interface and transfer syntax IDs */
|
|
|
|
int isCompatibleWith(
|
|
CGUIDVersion *pInterfaceID,
|
|
CGUIDVersion *pTransferID
|
|
)
|
|
{
|
|
return (!pInterfaceID || this->isCompatibleGV(*pInterfaceID))
|
|
&& (!pTransferID || transferSyntax.isCompatibleGV(*pTransferID));
|
|
}
|
|
|
|
~CInterface() {
|
|
delete pBVhandles;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CEntryName
|
|
|
|
Abstract:
|
|
|
|
This class encapsulates knowledge about RPC name service entry names.
|
|
|
|
Data Members:
|
|
|
|
CStringW (base) -- the name string in its original form
|
|
|
|
DomainName -- the name of the Domain, without any punctuation
|
|
|
|
EntryName -- the name of the entry, without any /.: or /... prefix
|
|
and also without a domain name at the beginning
|
|
|
|
--*/
|
|
|
|
class CEntryName : public CStringW {
|
|
|
|
protected:
|
|
|
|
CStringW *pswDomainName;
|
|
CStringW *pswEntryName;
|
|
|
|
public:
|
|
|
|
CEntryName(CONST_STRING_T fullName); // disassembling constructor
|
|
|
|
CEntryName( // assembling constructor
|
|
CONST_STRING_T domainName,
|
|
CONST_STRING_T entryName
|
|
);
|
|
|
|
virtual ~CEntryName(); // base class destructor should be virtual
|
|
|
|
CStringW* getDomainName()
|
|
{
|
|
return pswDomainName;
|
|
}
|
|
|
|
CStringW* getEntryName()
|
|
{
|
|
return pswEntryName;
|
|
}
|
|
|
|
void changeToLocalName()
|
|
{
|
|
delete pswDomainName;
|
|
pswDomainName = NULL;
|
|
delete [] pszVal;
|
|
pszVal = catenate(RelativePrefix,*pswEntryName);
|
|
}
|
|
|
|
STRING_T copyGlobalName();
|
|
|
|
STRING_T copyCurrentName()
|
|
{
|
|
return copyString(getCurrentName());
|
|
}
|
|
|
|
STRING_T getCurrentName()
|
|
|
|
/* this is mainly for use by CEntry objects. for CEntryName objects, automatic
|
|
conversion through the inherited STRING_T operator is used instead */
|
|
{
|
|
return pszVal;
|
|
}
|
|
|
|
int isLocal();
|
|
};
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CContextHandle
|
|
|
|
Abstract:
|
|
|
|
This is the base interface for all context handles. It is needed
|
|
because, for RPC, there is a single NSI_NS_HANDLE_T context handle type,
|
|
and there has to be a single entry point for the rundown process.
|
|
A virtual destructor is needed for the same reason.
|
|
|
|
Note that CContextHandle is not an abstract class.
|
|
|
|
--*/
|
|
|
|
|
|
class CContextHandle {
|
|
|
|
public:
|
|
|
|
ULONG ulCacheMax; // max age of a cached item that is acceptable
|
|
// *at lookup time* (this is important)
|
|
|
|
ULONG ulCreationTime; // when I was created
|
|
|
|
virtual void lookupIfNecessary() {} // redo the lookup which created this handle
|
|
|
|
virtual void setExpiryAge(ULONG newMax) {
|
|
ULONG ulOldMax = ulCacheMax;
|
|
ulCacheMax = newMax;
|
|
if (ulCacheMax < ulOldMax) lookupIfNecessary();
|
|
}
|
|
|
|
virtual void rundown() {}
|
|
|
|
CContextHandle() {
|
|
ulCreationTime = CurrentTime();
|
|
}
|
|
|
|
virtual ~CContextHandle() {}
|
|
};
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Template Class Definition:
|
|
|
|
CNSHandle
|
|
|
|
Abstract:
|
|
|
|
This template defines the basic nature of an NS handle.
|
|
It is instantiated into abstract base classes such as
|
|
CObjectInqHandle and CLookupHandle, and is also used in
|
|
the definition of other templates such as CCompleteHandle
|
|
which abstract general properties of classes of handles.
|
|
|
|
--*/
|
|
|
|
|
|
template <class ItemType>
|
|
struct CNSHandle : public CContextHandle
|
|
{
|
|
public:
|
|
|
|
ULONG StatusCode;
|
|
|
|
virtual void lookupIfNecessary() = 0; // redo the lookup which created this handle
|
|
|
|
virtual ItemType * next() = 0; // primary iterative operation
|
|
|
|
virtual int finished() = 0; // test for end of iterator
|
|
|
|
virtual void rundown() = 0; // inherited and still pure virtual
|
|
|
|
CNSHandle() { StatusCode = NSI_S_OK; }
|
|
|
|
virtual ULONG getStatus() { return StatusCode; }
|
|
|
|
virtual ~CNSHandle() {}
|
|
};
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CObjectInqHandle
|
|
|
|
Abstract:
|
|
|
|
This is the class for object lookup handles.
|
|
|
|
The primary operation on a handle is "next" which is inherited
|
|
from the TIIterator template interface (instantiated as TGuidIterator
|
|
which returns CGUID objects). However, it also needs an additional
|
|
operation for the locator-to-locator case where an entire vector of
|
|
object UUIDs is returned instead of just one UUID at a time.
|
|
|
|
--*/
|
|
|
|
|
|
typedef CNSHandle<GUID> CObjectInqHandle;
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CRemoteObjectInqHandle
|
|
|
|
Abstract:
|
|
|
|
This is the common object inquiry handle class for remote entries. Handles based
|
|
on cached entries, master locators and broadcast are derived from it. Note that
|
|
the connection between a remote handle and a specific entry is very tenuous.
|
|
We don't even assume that the entry object(s) the handle was derived from will
|
|
exist as long as the handle does. In case of a new lookup being forced (because
|
|
handle is too stale -- this happens only with the RpcNsHandleSetExpAge API), we
|
|
expect to start all over again from scratch.
|
|
|
|
|
|
--*/
|
|
|
|
|
|
class CRemoteObjectInqHandle : public CObjectInqHandle {
|
|
|
|
protected:
|
|
|
|
NSI_UUID_VECTOR_P_T pUuidVector;
|
|
ULONG ulIndex;
|
|
|
|
CEntryName * penEntryName;
|
|
ULONG ulEntryNameSyntax;
|
|
|
|
/* A flag to delay initialization until the first call on next */
|
|
|
|
BOOL fNotInitialized;
|
|
|
|
public:
|
|
|
|
#if DBG
|
|
static ULONG ulHandleCount;
|
|
ULONG ulHandleNo;
|
|
#endif
|
|
|
|
CRemoteObjectInqHandle(
|
|
STRING_T szName,
|
|
ULONG ulCacheAge
|
|
)
|
|
{
|
|
DBGOUT(MEM2, "CRemoteObjectInqHandle#" << (ulHandleNo = ++ulHandleCount)
|
|
<< " Created at" << CurrentTime() << "\n\n");
|
|
|
|
penEntryName = szName ? new CEntryName(szName) : NULL;
|
|
ulEntryNameSyntax = RPC_C_NS_SYNTAX_DCE;
|
|
ulIndex = 0;
|
|
fNotInitialized = TRUE;
|
|
pUuidVector = NULL;
|
|
ulCacheMax = ulCacheAge;
|
|
}
|
|
|
|
virtual ~CRemoteObjectInqHandle()
|
|
{
|
|
DBGOUT(MEM2, "CRemoteObjectInqHandle#" << (ulHandleCount--,ulHandleNo)
|
|
<< " Destroyed at" << CurrentTime() << "\n\n");
|
|
|
|
rundown();
|
|
|
|
delete penEntryName;
|
|
penEntryName = NULL;
|
|
}
|
|
|
|
virtual void initialize() = 0;
|
|
|
|
virtual void lookupIfNecessary()
|
|
/*
|
|
Note that this does not reinitialize the handle
|
|
-- that is deferred until a "next" or "finished" call
|
|
*/
|
|
{
|
|
DBGOUT(MEM1,"lookupIfNecessary called for a remote handle\n\n");
|
|
|
|
if (CurrentTime() - ulCreationTime > ulCacheMax) rundown();
|
|
}
|
|
|
|
/* The rundown method should be extended in a subclass if objects of the subclass
|
|
hold additional resources connected with the current contents of the handle (as
|
|
opposed to lookup parameters). For additional lookup parameters, a destructor
|
|
should be provided instead. */
|
|
|
|
void rundown()
|
|
{
|
|
if (pUuidVector)
|
|
{
|
|
for (; ulIndex < pUuidVector->count; ulIndex++)
|
|
midl_user_free(pUuidVector->uuid[ulIndex]);
|
|
|
|
midl_user_free(pUuidVector);
|
|
pUuidVector = NULL;
|
|
}
|
|
|
|
fNotInitialized = TRUE;
|
|
}
|
|
|
|
virtual GUID* next() {
|
|
|
|
if (fNotInitialized) initialize();
|
|
|
|
if (finished()) return NULL;
|
|
|
|
GUID* result = pUuidVector->uuid[ulIndex];
|
|
|
|
pUuidVector->uuid[ulIndex] = NULL;
|
|
|
|
ulIndex++;
|
|
|
|
return result;
|
|
}
|
|
|
|
virtual BOOL finished() {
|
|
if (fNotInitialized) initialize();
|
|
return StatusCode || !pUuidVector || (ulIndex >= pUuidVector->count);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CNetObjectInqHandle
|
|
|
|
Abstract:
|
|
|
|
This is the common object inquiry handle class for network-based object inquiry.
|
|
|
|
Since net object inquiry is now "lazy" (net is accessed only if needed), we need
|
|
a lazy handle which initializes itself according to the old pattern of
|
|
"use master if you can, broadcast if you must".
|
|
|
|
--*/
|
|
|
|
class CNetObjectInqHandle : public CRemoteObjectInqHandle {
|
|
|
|
CRemoteObjectInqHandle *pRealHandle;
|
|
|
|
virtual void initialize();
|
|
|
|
public:
|
|
|
|
ULONG getStatus() { return pRealHandle->StatusCode; }
|
|
|
|
virtual void rundown()
|
|
{
|
|
if (pRealHandle)
|
|
{
|
|
pRealHandle->rundown();
|
|
delete pRealHandle;
|
|
pRealHandle = NULL;
|
|
}
|
|
|
|
fNotInitialized = TRUE;
|
|
}
|
|
|
|
CNetObjectInqHandle(
|
|
STRING_T EntryName,
|
|
unsigned long ulCacheAge
|
|
) :
|
|
CRemoteObjectInqHandle(
|
|
EntryName,
|
|
ulCacheAge
|
|
)
|
|
{
|
|
pRealHandle = NULL;
|
|
fNotInitialized = TRUE;
|
|
}
|
|
|
|
~CNetObjectInqHandle()
|
|
{
|
|
rundown();
|
|
}
|
|
|
|
GUID *next() {
|
|
if (fNotInitialized) initialize();
|
|
return pRealHandle->next();
|
|
}
|
|
|
|
int finished() {
|
|
if (fNotInitialized) initialize();
|
|
return pRealHandle->finished();
|
|
}
|
|
};
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CLookupHandle
|
|
|
|
Abstract:
|
|
|
|
This is the base class for BV lookup handles. Actual handles
|
|
belong to derived classes corresponding to entry types.
|
|
|
|
The primary operation on a handle is "next" which is inherited
|
|
from the TIIterator template interface (instantiated as TBVIterator).
|
|
|
|
There is the possibility that a longlived client will fail to
|
|
release a lookup handle, causing an effective leak of resources,
|
|
but we won't deal with that in the current version.
|
|
|
|
--*/
|
|
|
|
typedef CNSHandle<NSI_BINDING_VECTOR_T> CLookupHandle;
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CMailSlotReplyHandle
|
|
|
|
Abstract:
|
|
|
|
This is the base class for handles which provide items for constructing
|
|
mailslot reply buffers. Actual handles belong to derived classes
|
|
corresponding to entry types.
|
|
|
|
The primary operation on a handle is "next" which is inherited
|
|
from the TIIterator template interface (instantiated as TMSRIIterator).
|
|
|
|
--*/
|
|
|
|
class CMailSlotReplyHandle : public TMSRIIterator {
|
|
|
|
public:
|
|
|
|
virtual ~CMailSlotReplyHandle() {}
|
|
};
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CEntry
|
|
|
|
Abstract:
|
|
|
|
The base Entry class for the internal cache. Even though this is an abstract
|
|
class due to the unspecified loopup member, the class is not a pure
|
|
interface (it has a constructor), hence the C rather than I prefix in the name.
|
|
|
|
Note that CEntry has only constant data members.
|
|
|
|
--*/
|
|
|
|
class CEntry : public CEntryName {
|
|
|
|
const EntryType type;
|
|
|
|
public:
|
|
|
|
const unsigned long ulEntryNameSyntax;
|
|
|
|
CEntry(
|
|
CONST_STRING_T pszStr,
|
|
const EntryType& e,
|
|
const unsigned long ulSyntax = RPC_C_NS_SYNTAX_DCE
|
|
)
|
|
: CEntryName( pszStr ),
|
|
ulEntryNameSyntax(ulSyntax),
|
|
type(e)
|
|
{}
|
|
|
|
|
|
virtual ~CEntry() {}
|
|
|
|
EntryType getType() { return type; }
|
|
|
|
BOOL isCacheType() {
|
|
switch (type) {
|
|
case CacheServerEntryType: return TRUE;
|
|
default: return FALSE;
|
|
}
|
|
}
|
|
|
|
virtual void flush() {} // useful for cache flushing, for instance
|
|
|
|
virtual BOOL isCurrent(ULONG) { return TRUE; } // QUESTION: again cache oriented
|
|
// need CCacheEntryMixin for these?
|
|
|
|
virtual BOOL isEmpty() = 0;
|
|
|
|
virtual CLookupHandle * lookup(
|
|
CGUIDVersion * pGVInterface,
|
|
CGUIDVersion * pGVTransferSyntax,
|
|
CGUID * pIDobject,
|
|
unsigned long ulVectorSize,
|
|
unsigned long ulCacheAge
|
|
) = 0;
|
|
|
|
virtual CObjectInqHandle * objectInquiry(
|
|
unsigned long ulCacheAge
|
|
) = 0;
|
|
|
|
virtual CMailSlotReplyHandle * MailSlotLookup(
|
|
CGUIDVersion * pGVInterface,
|
|
CGUID * pIDobject
|
|
) = 0;
|
|
};
|
|
|
|
|
|
typedef TCGuardedSkipList<CEntry> TGSLEntryList;
|
|
typedef TCGuardedSkipListIterator<CEntry> TGSLEntryListIterator;
|
|
typedef TCSafeSkipList<CEntry> TSSLEntryList;
|
|
typedef TCSafeSkipListIterator<CEntry> TSSLEntryListIterator;
|
|
typedef TCSafeLinkList<CEntry> TSLLEntryList;
|
|
typedef TCSafeLinkListIterator<CEntry> TSLLEntryListIterator;
|
|
typedef TISkipList<CEntry> TEntrySkipList;
|
|
|
|
typedef TIIterator<CEntry> TEntryIterator;
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CRemoteLookupHandle
|
|
|
|
Abstract:
|
|
|
|
This is the common lookup handle class for remote entries. Handles based on
|
|
cached entries, master locators and broadcast are derived from it. Note that
|
|
the connection between a remote handle and a specific entry is very tenuous.
|
|
We don't even assume that the entry object(s) the handle was derived from will
|
|
exist as long as the handle does. In case of a renewal lookup (lookupIfNecessary())
|
|
being forced, we expect to start all over again from scratch.
|
|
|
|
This handle, like all NS handles, relies on the fact that it is accessed
|
|
as a client handle by the client side, and hence the RPC run-time
|
|
automatically serializes its use.
|
|
|
|
--*/
|
|
|
|
class CRemoteLookupHandle : public CLookupHandle {
|
|
|
|
protected:
|
|
|
|
/* caching parameters */
|
|
|
|
UNSIGNED32 u32EntryNameSyntax;
|
|
CEntryName * penEntryName;
|
|
CGUIDVersion * pgvInterface;
|
|
CGUIDVersion * pgvTransferSyntax;
|
|
CGUID * pidObject;
|
|
ULONG ulVS;
|
|
|
|
/* List of temporary entries created as a cache local to this
|
|
handle by fetchNext. Must keep it for proper disposal
|
|
after its use is finished. This is only used in net
|
|
handles -- CMasterLookupHandle and CBroadcastLookupHandle
|
|
*/
|
|
|
|
TSSLEntryList *psslNewCache;
|
|
|
|
/* a lookup handle based on prefetched info */
|
|
|
|
CLookupHandle *plhFetched;
|
|
|
|
/* A flag to delay initialization until the first call on next */
|
|
|
|
BOOL fNotInitialized;
|
|
|
|
public:
|
|
|
|
#if DBG
|
|
static ULONG ulHandleCount;
|
|
ULONG ulHandleNo;
|
|
#endif
|
|
|
|
CRemoteLookupHandle(
|
|
UNSIGNED32 EntryNameSyntax,
|
|
STRING_T EntryName,
|
|
CGUIDVersion * pGVInterface,
|
|
CGUIDVersion * pGVTransferSyntax,
|
|
CGUID * pIDobject,
|
|
unsigned long ulVectorSize,
|
|
unsigned long ulCacheAge
|
|
);
|
|
|
|
virtual void initialize() = 0;
|
|
|
|
/* The rundown method should be extended in a subclass if objects of the subclass
|
|
hold additional resources connected with the current contents of the handle (as
|
|
opposed to lookup parameters). See CMasterLookupHandle::rundown for an example.
|
|
For additional lookup parameters, a destructor should be provided instead.
|
|
*/
|
|
|
|
virtual void rundown()
|
|
{
|
|
if (plhFetched) {
|
|
plhFetched->rundown();
|
|
delete plhFetched;
|
|
plhFetched = NULL;
|
|
}
|
|
|
|
if (psslNewCache) {
|
|
psslNewCache->wipeOut();
|
|
delete psslNewCache;
|
|
psslNewCache = NULL;
|
|
}
|
|
|
|
fNotInitialized = TRUE;
|
|
}
|
|
|
|
virtual ~CRemoteLookupHandle() {
|
|
|
|
DBGOUT(MEM2, "RemoteLookupHandle#" << (ulHandleCount--,ulHandleNo)
|
|
<< " Destroyed at" << CurrentTime() << "\n\n");
|
|
|
|
rundown();
|
|
|
|
delete pgvInterface;
|
|
delete pgvTransferSyntax;
|
|
delete pidObject;
|
|
delete penEntryName;
|
|
}
|
|
|
|
virtual void setExpiryAge(ULONG newMax) {
|
|
ULONG ulOldMax = ulCacheMax;
|
|
ulCacheMax = newMax;
|
|
if (plhFetched) plhFetched->setExpiryAge(newMax);
|
|
if (ulCacheMax < ulOldMax) lookupIfNecessary();
|
|
}
|
|
|
|
virtual void lookupIfNecessary() // standard behavior is:
|
|
/*
|
|
Note that this does not reinitialize the handle
|
|
-- that is deferred until a "next" or "finished" call
|
|
*/
|
|
{
|
|
if (CurrentTime() - ulCreationTime > ulCacheMax) rundown();
|
|
}
|
|
|
|
virtual int finished() { // default behavior
|
|
if (fNotInitialized) initialize();
|
|
return !plhFetched || plhFetched->finished();
|
|
}
|
|
|
|
virtual NSI_BINDING_VECTOR_T *next() { // default behavior
|
|
if (fNotInitialized) initialize();
|
|
return plhFetched ? plhFetched->next() : NULL;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CNetLookupHandle
|
|
|
|
Abstract:
|
|
|
|
This is the common lookup handle class for network-based lookup.
|
|
|
|
Since net lookup is now "lazy" (net is accessed only if needed), we need
|
|
a lazy handle which initializes itself according to the old pattern of
|
|
"use master if you can, broadcast if you must".
|
|
|
|
--*/
|
|
|
|
class CNetLookupHandle : public CRemoteLookupHandle {
|
|
|
|
CRemoteLookupHandle *pRealHandle;
|
|
|
|
virtual void initialize();
|
|
|
|
#if DBG
|
|
static ULONG ulNetLookupHandleCount;
|
|
static ULONG ulNetLookupHandleNo;
|
|
ULONG ulHandleNo;
|
|
#endif
|
|
|
|
public:
|
|
|
|
ULONG getStatus() { return pRealHandle->StatusCode; }
|
|
|
|
virtual void rundown()
|
|
{
|
|
DBGOUT(TRACE,"CNetLookupHandle::rundown called for Handle#" << ulHandleNo << "\n\n");
|
|
if (pRealHandle)
|
|
{
|
|
pRealHandle->rundown();
|
|
delete pRealHandle;
|
|
pRealHandle = NULL;
|
|
}
|
|
|
|
fNotInitialized = TRUE;
|
|
}
|
|
|
|
CNetLookupHandle(
|
|
UNSIGNED32 EntryNameSyntax,
|
|
STRING_T EntryName,
|
|
CGUIDVersion * pGVInterface,
|
|
CGUIDVersion * pGVTransferSyntax,
|
|
CGUID * pIDobject,
|
|
unsigned long ulVectorSize,
|
|
unsigned long ulCacheAge
|
|
) :
|
|
CRemoteLookupHandle(
|
|
EntryNameSyntax,
|
|
EntryName,
|
|
pGVInterface,
|
|
pGVTransferSyntax,
|
|
pIDobject,
|
|
ulVectorSize,
|
|
ulCacheAge
|
|
)
|
|
{
|
|
pRealHandle = NULL;
|
|
fNotInitialized = TRUE;
|
|
#if DBG
|
|
ulNetLookupHandleCount++;
|
|
ulHandleNo = ++ulNetLookupHandleNo;
|
|
#endif
|
|
}
|
|
|
|
~CNetLookupHandle()
|
|
{
|
|
rundown();
|
|
#if DBG
|
|
ulNetLookupHandleCount--;
|
|
#endif
|
|
}
|
|
|
|
NSI_BINDING_VECTOR_T *next() {
|
|
DBGOUT(TRACE,"CNetLookupHandle::next called for Handle#" << ulHandleNo << "\n\n");
|
|
if (fNotInitialized) initialize();
|
|
return pRealHandle->next();
|
|
}
|
|
|
|
int finished() {
|
|
DBGOUT(TRACE,"CNetLookupHandle::finished called for Handle#" << ulHandleNo << "\n\n");
|
|
if (fNotInitialized) initialize();
|
|
return pRealHandle->finished();
|
|
}
|
|
};
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CServerObjectInqHandle
|
|
|
|
Abstract:
|
|
|
|
This is the object inquiry handle class for local (owned) server entries.
|
|
|
|
Since NS handles are used as context handles in RPC calls, the RPC runtime
|
|
guarantees serialization and we do not need to use critical sections explicitly.
|
|
|
|
--*/
|
|
|
|
class CServerObjectInqHandle : public CObjectInqHandle {
|
|
|
|
TGuidIterator *pcgIterSource;
|
|
|
|
public:
|
|
|
|
CServerObjectInqHandle(
|
|
TGuidIterator *pHandle,
|
|
ULONG cacheMax = 0
|
|
) : pcgIterSource(pHandle)
|
|
{
|
|
ulCacheMax = cacheMax;
|
|
}
|
|
|
|
GUID *next();
|
|
|
|
virtual void lookupIfNecessary() {} // never redo lookup for local info
|
|
|
|
int finished() {
|
|
return pcgIterSource->finished();
|
|
}
|
|
|
|
virtual ~CServerObjectInqHandle() {
|
|
rundown();
|
|
}
|
|
|
|
virtual void rundown();
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CServerEntry
|
|
|
|
Abstract:
|
|
|
|
The specific Entry class for entries with binding and object attributes.
|
|
|
|
--*/
|
|
|
|
class CServerEntry : public CEntry {
|
|
|
|
protected:
|
|
|
|
TCSafeSkipList<CGUID> ObjectList; // object attribute
|
|
TCSafeSkipList<CInterface> InterfaceList; // binding attribute
|
|
|
|
TSLLString*
|
|
CServerEntry::formObjectStrings(
|
|
CGUID* pIDobject
|
|
);
|
|
|
|
public:
|
|
|
|
CServerEntry(CONST_STRING_T pszStr)
|
|
: CEntry(pszStr, ServerEntryType) {}
|
|
|
|
CServerEntry(CONST_STRING_T pszStr, const EntryType type)
|
|
: CEntry(pszStr, type) {}
|
|
|
|
virtual void flush(); // inherited from CEntry
|
|
|
|
virtual BOOL isEmpty() {
|
|
CriticalReader me(rwEntryGuard);
|
|
return (ObjectList.size() == 0) && (InterfaceList.size() == 0);
|
|
}
|
|
|
|
virtual ~CServerEntry() { // cache version could be derived from it
|
|
flush();
|
|
}
|
|
|
|
virtual int addObjects(NSI_UUID_VECTOR_P_T ObjectVector);
|
|
|
|
virtual int removeObjects(
|
|
NSI_UUID_VECTOR_P_T ObjectVector,
|
|
int& fRemovedAll
|
|
);
|
|
|
|
virtual int addToInterface(
|
|
NSI_INTERFACE_ID_T *,
|
|
NSI_SERVER_BINDING_VECTOR_T *,
|
|
CInterfaceIndex *
|
|
);
|
|
|
|
virtual int removeInterfaces(
|
|
NSI_IF_ID_P_T Interface,
|
|
UNSIGNED32 VersOption,
|
|
CInterfaceIndex *
|
|
);
|
|
|
|
int memberObject(CGUID *obj) {
|
|
CriticalReader me(rwEntryGuard);
|
|
return ObjectList.find(obj) != NULL;
|
|
}
|
|
|
|
virtual CLookupHandle * lookup(
|
|
CGUIDVersion * pGVInterface,
|
|
CGUIDVersion * pGVTransferSyntax,
|
|
CGUID * pIDobject,
|
|
unsigned long ulVectorSize,
|
|
unsigned long ulCacheAge // ignored in this case
|
|
);
|
|
|
|
virtual CObjectInqHandle * objectInquiry(
|
|
unsigned long ulCacheAge
|
|
);
|
|
|
|
virtual CMailSlotReplyHandle * MailSlotLookup(
|
|
CGUIDVersion * pGVInterface,
|
|
CGUID * pIDobject
|
|
);
|
|
};
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CCacheServerEntry
|
|
|
|
Abstract:
|
|
|
|
A variation on CServerEntry with modifications to reflect the fact that the
|
|
info is cached rather than owned by the locator, including a notion of being
|
|
current based on the earliest caching time of any info in the entry. Note that
|
|
info may be added incrementally at various times.
|
|
|
|
|
|
--*/
|
|
|
|
class CCacheServerEntry : public CServerEntry {
|
|
|
|
ULONG ulCacheTime;
|
|
int fHasCachedInfo;
|
|
|
|
public:
|
|
|
|
virtual BOOL isCurrent(ULONG ulTolerance);
|
|
|
|
CCacheServerEntry(
|
|
CONST_STRING_T pszStr
|
|
)
|
|
: CServerEntry(pszStr,CacheServerEntryType)
|
|
{
|
|
fHasCachedInfo = FALSE;
|
|
ulCacheTime = 0;
|
|
}
|
|
|
|
virtual void flush()
|
|
{
|
|
CServerEntry::flush();
|
|
|
|
CriticalWriter me(rwCacheEntryGuard);
|
|
|
|
DBGOUT(OBJECT, "\nFlushing CCacheServerEntry\n");
|
|
DBGOUT(OBJECT, "EntryName = " << getCurrentName() << WNL);
|
|
DBGOUT(OBJECT, "This entry has a ulCacheTime = " << ulCacheTime << "\n\n");
|
|
|
|
fHasCachedInfo = FALSE;
|
|
}
|
|
|
|
|
|
|
|
int addObjects(NSI_UUID_VECTOR_P_T ObjectVector) {
|
|
|
|
{
|
|
CriticalWriter me(rwCacheEntryGuard);
|
|
|
|
if (!fHasCachedInfo) {
|
|
ulCacheTime = CurrentTime();
|
|
fHasCachedInfo = TRUE;
|
|
}
|
|
|
|
else {
|
|
DBGOUT(OBJECT, "\nPerforming addObjects on a nonempty entry\n");
|
|
DBGOUT(OBJECT, "EntryName = " << getCurrentName() << WNL);
|
|
DBGOUT(OBJECT, "This entry has a ulCacheTime = " << ulCacheTime << WNL);
|
|
DBGOUT(OBJECT, "Current Time = " << CurrentTime() << "\n\n");
|
|
DBGOUT(OBJECT, "The Objects:\n" << ObjectVector);
|
|
}
|
|
}
|
|
|
|
return CServerEntry::addObjects(ObjectVector);
|
|
}
|
|
|
|
int addToInterface(
|
|
NSI_INTERFACE_ID_T *pInf,
|
|
NSI_SERVER_BINDING_VECTOR_T *pBVT,
|
|
CInterfaceIndex *pIndex
|
|
)
|
|
{
|
|
{
|
|
CriticalWriter me(rwCacheEntryGuard);
|
|
|
|
if (!fHasCachedInfo) {
|
|
ulCacheTime = CurrentTime();
|
|
fHasCachedInfo = TRUE;
|
|
}
|
|
|
|
else {
|
|
DBGOUT(OBJECT, "\nPerforming addToInterface on a nonempty entry\n");
|
|
DBGOUT(OBJECT, "EntryName = " << getCurrentName() << WNL);
|
|
DBGOUT(OBJECT, "This entry has a ulCacheTime = " << ulCacheTime << WNL);
|
|
DBGOUT(OBJECT, "Current Time = " << CurrentTime() << WNL << WNL);
|
|
DBGOUT(OBJECT, "The Bindings:\n" << pBVT);
|
|
}
|
|
}
|
|
|
|
return CServerEntry::addToInterface(pInf,pBVT,pIndex);
|
|
}
|
|
|
|
int removeObjects( // shouldn't happen to a cached entry
|
|
NSI_UUID_VECTOR_P_T ObjectVector,
|
|
int& fRemovedAll
|
|
)
|
|
{
|
|
Raise(NSI_S_ENTRY_NOT_FOUND);
|
|
|
|
/* the following just keeps the compiler happy */
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
virtual CObjectInqHandle * objectInquiry(
|
|
unsigned long ulCacheAge
|
|
);
|
|
|
|
int removeInterfaces( // shouldn't happen to a cached entry
|
|
NSI_IF_ID_P_T Interface,
|
|
UNSIGNED32 VersOption,
|
|
CInterfaceIndex &
|
|
)
|
|
{
|
|
Raise(NSI_S_ENTRY_NOT_FOUND);
|
|
|
|
/* the following just keeps the compiler happy */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
virtual CLookupHandle * lookup(
|
|
CGUIDVersion * pGVInterface,
|
|
CGUIDVersion * pGVTransferSyntax,
|
|
CGUID * pIDobject,
|
|
unsigned long ulVectorSize,
|
|
unsigned long ulCacheAge
|
|
);
|
|
|
|
virtual CMailSlotReplyHandle * MailSlotLookup(
|
|
CGUIDVersion * pGVInterface,
|
|
CGUID * pIDobject
|
|
)
|
|
|
|
// Cached info is not returned in response to a broadcast, hence
|
|
|
|
{
|
|
return NULL;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CFullServerEntry
|
|
|
|
Abstract:
|
|
|
|
This class is used to account for the fact that direct exports to
|
|
the same server entry may be made on two different machines.
|
|
As a result, the information in a server entry is partly cached
|
|
remote handles and partly locally exported handles. This is a
|
|
temporary situation until we have a persistent global database.
|
|
Therefore this struct does the minimal necessary to tide us over
|
|
until then. In particular, it is not a real server entry, but
|
|
exposes two kinds of server entries within itself.
|
|
|
|
--*/
|
|
|
|
class CFullServerEntry : public CEntry {
|
|
|
|
BOOL fNetLookupDone;
|
|
|
|
void flushCacheIfNecessary(ULONG ulTolerance);
|
|
|
|
CServerEntry *pLocalEntry;
|
|
CCacheServerEntry *pCachedEntry;
|
|
|
|
public:
|
|
|
|
CServerEntry *getLocal() {
|
|
CriticalReader me(rwFullEntryGuard);
|
|
return pLocalEntry;
|
|
}
|
|
|
|
CCacheServerEntry *getCache() {
|
|
CriticalReader me(rwFullEntryGuard);
|
|
return pCachedEntry;
|
|
}
|
|
|
|
CFullServerEntry(
|
|
CONST_STRING_T pszName
|
|
)
|
|
:CEntry(
|
|
pszName,
|
|
FullServerEntryType
|
|
)
|
|
{
|
|
pLocalEntry = new CServerEntry(pszName);
|
|
pCachedEntry = new CCacheServerEntry(pszName);
|
|
|
|
fNetLookupDone = FALSE;
|
|
}
|
|
|
|
virtual ~CFullServerEntry() {
|
|
delete pLocalEntry;
|
|
delete pCachedEntry;
|
|
}
|
|
|
|
virtual BOOL isEmpty() {
|
|
CriticalReader me(rwFullEntryGuard);
|
|
return pLocalEntry->isEmpty() && pCachedEntry->isEmpty();
|
|
}
|
|
|
|
virtual CLookupHandle * lookup(
|
|
CGUIDVersion * pGVInterface,
|
|
CGUIDVersion * pGVTransferSyntax,
|
|
CGUID * pIDobject,
|
|
unsigned long ulVectorSize,
|
|
unsigned long ulCacheAge
|
|
);
|
|
|
|
virtual CObjectInqHandle * objectInquiry(
|
|
unsigned long ulCacheAge
|
|
);
|
|
|
|
virtual CMailSlotReplyHandle * MailSlotLookup(
|
|
CGUIDVersion * pGVInterface,
|
|
CGUID * pIDobject
|
|
);
|
|
};
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CCacheServerObjectInqHandle
|
|
|
|
Abstract:
|
|
|
|
This is the object inquiry handle class for cached server entries.
|
|
|
|
The only difference from a local CServerObjectInqHandle is
|
|
the functionality added by CRemoteObjectInqHandle.
|
|
|
|
--*/
|
|
|
|
class CCacheServerObjectInqHandle : public CRemoteObjectInqHandle {
|
|
|
|
void initialize();
|
|
|
|
public:
|
|
|
|
CCacheServerObjectInqHandle(
|
|
STRING_T pszName,
|
|
ULONG ulCacheAge
|
|
);
|
|
};
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CGroupEntry
|
|
|
|
Abstract:
|
|
|
|
A stub for future extension.
|
|
|
|
--*/
|
|
|
|
class CGroupEntry : public CEntry {
|
|
|
|
protected:
|
|
|
|
TCSafeSkipList<CStringW> GroupList;
|
|
|
|
public:
|
|
|
|
CGroupEntry(const STRING_T pszStr)
|
|
: CEntry(pszStr, GroupEntryType) {}
|
|
};
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CProfileEntry
|
|
|
|
Abstract:
|
|
|
|
A stub for future extension.
|
|
|
|
--*/
|
|
|
|
class CProfileEntry : public CEntry {
|
|
|
|
public:
|
|
|
|
CProfileEntry(const STRING_T pszStr)
|
|
: CEntry(pszStr, ProfileEntryType) {}
|
|
};
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CServerLookupHandle
|
|
|
|
Abstract:
|
|
|
|
This is the binding lookup handle class for local (owned) server entries.
|
|
|
|
Since NS handles are used as context handles in RPC calls, the RPC runtime
|
|
guarantees serialization and we do not need to use critical sections explicitly.
|
|
|
|
--*/
|
|
|
|
class CServerLookupHandle : public CLookupHandle {
|
|
|
|
unsigned long ulVectorSize;
|
|
|
|
TBVIterator *pBVIterator;
|
|
|
|
public:
|
|
|
|
CServerLookupHandle(
|
|
TBVSafeLinkList * pBVLL
|
|
);
|
|
|
|
virtual ~CServerLookupHandle() {
|
|
rundown();
|
|
}
|
|
|
|
virtual void lookupIfNecessary() {} // never redo lookup for local info
|
|
|
|
NSI_BINDING_VECTOR_T *next() {
|
|
CBVWrapper *pBVW = pBVIterator->next();
|
|
NSI_BINDING_VECTOR_T *pResult = pBVW->pBVT; // unwrap
|
|
delete pBVW; // throw away wrapper
|
|
return pResult;
|
|
}
|
|
|
|
int finished() {
|
|
return pBVIterator->finished();
|
|
}
|
|
|
|
virtual void rundown();
|
|
};
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CCacheServerLookupHandle
|
|
|
|
Abstract:
|
|
|
|
This is the lookup handle class for cached server entries.
|
|
|
|
The only difference from a local CServerLookupHandle is
|
|
the functionality added by CRemoteLookupHandle.
|
|
|
|
--*/
|
|
|
|
class CCacheServerLookupHandle : public CRemoteLookupHandle {
|
|
|
|
void initialize();
|
|
|
|
public:
|
|
|
|
CCacheServerLookupHandle(
|
|
STRING_T pszName,
|
|
CGUIDVersion *pGVInterface,
|
|
CGUIDVersion *pGVTransferSyntax,
|
|
CGUID *pIDobject,
|
|
ULONG ulVectorSize,
|
|
ULONG ulCacheAge
|
|
);
|
|
};
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CGroupLookupHandle
|
|
|
|
Abstract:
|
|
|
|
This is the lookup handle class for group entries and other groups.
|
|
Its primary use currently is to produce handles for null-entry
|
|
lookups where information from multiple entries needs to be collected.
|
|
|
|
--*/
|
|
|
|
class CGroupLookupHandle : public CLookupHandle {
|
|
|
|
protected:
|
|
|
|
/* search parameters */
|
|
|
|
CGUIDVersion * pGVInterface;
|
|
CGUIDVersion * pGVTransferSyntax;
|
|
CGUID * pIDobject;
|
|
unsigned long ulVectorSize;
|
|
|
|
/* Iterator for entries in the group -- please use a guarded kind! */
|
|
|
|
TEntryIterator *pEIterator;
|
|
|
|
/* handle for the currently active entry */
|
|
|
|
CLookupHandle * pCurrentHandle;
|
|
|
|
void advanceCurrentHandle(); // look for next nonempty entry handle
|
|
|
|
public:
|
|
|
|
CGroupLookupHandle(
|
|
TEntryIterator * pEI,
|
|
CGUIDVersion * pGVInterface,
|
|
CGUIDVersion * pGVTransferSyntax,
|
|
CGUID * pIDobject,
|
|
unsigned long ulVectorSize,
|
|
unsigned long ulCacheAge
|
|
);
|
|
|
|
virtual ~CGroupLookupHandle() {
|
|
rundown();
|
|
|
|
delete pEIterator;
|
|
delete pGVInterface;
|
|
delete pGVTransferSyntax;
|
|
delete pIDobject;
|
|
}
|
|
|
|
virtual void lookupIfNecessary() {}
|
|
|
|
NSI_BINDING_VECTOR_T *next(
|
|
);
|
|
|
|
int finished();
|
|
|
|
virtual void rundown()
|
|
{
|
|
if (pCurrentHandle)
|
|
{
|
|
pCurrentHandle->rundown();
|
|
delete pCurrentHandle;
|
|
pCurrentHandle = NULL;
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CIndexLookupHandle
|
|
|
|
Abstract:
|
|
|
|
This is a specialization of the group handle class for Index lookup.
|
|
The only difference is an implementation of lookupIfNecessary().
|
|
|
|
--*/
|
|
|
|
class CIndexLookupHandle : public CGroupLookupHandle {
|
|
|
|
public:
|
|
|
|
CIndexLookupHandle(
|
|
CGUIDVersion * pGVInterface,
|
|
CGUIDVersion * pGVTransferSyntax,
|
|
CGUID * pIDobject,
|
|
unsigned long ulVectorSize,
|
|
unsigned long ulCacheAge
|
|
);
|
|
|
|
virtual void lookupIfNecessary();
|
|
|
|
};
|
|
|
|
|
|
/*++
|
|
|
|
Template Class Definition:
|
|
|
|
CCompleteHandle
|
|
|
|
Abstract:
|
|
|
|
The complete handle template implements the idea that a top level NS handle
|
|
typically is heterogeneous -- it contains info that is a) owned b) cached
|
|
and c) just captured from the net. The behavior of such a handle is
|
|
independent of the nature of the data being looked up, hence the template.
|
|
|
|
--*/
|
|
|
|
template <class ItemType>
|
|
class CCompleteHandle : public CNSHandle<ItemType> {
|
|
|
|
/* these three handles are owned by this object and therefore
|
|
destroyed when it is deleted */
|
|
|
|
CNSHandle<ItemType> * pLocalHandle;
|
|
CNSHandle<ItemType> * pCacheHandle;
|
|
CNSHandle<ItemType> * pNetHandle;
|
|
|
|
public:
|
|
|
|
#if DBG
|
|
static ULONG ulHandleCount;
|
|
static ULONG ulHandleNo;
|
|
ULONG ulMyHandleNo;
|
|
#endif
|
|
|
|
ULONG netStatus() { return pNetHandle->getStatus(); }
|
|
|
|
CCompleteHandle(
|
|
CNSHandle<ItemType> * pLocal,
|
|
CNSHandle<ItemType> * pCache,
|
|
CNSHandle<ItemType> * pNet,
|
|
ULONG ulCacheAge
|
|
)
|
|
{
|
|
|
|
#if DBG
|
|
ulHandleCount++;
|
|
ulHandleNo++;
|
|
ulMyHandleNo = ulHandleNo;
|
|
#endif
|
|
DBGOUT(MEM1, "CompleteHandle#" << ulMyHandleNo << " Created at"
|
|
<< CurrentTime() << "\n\n");
|
|
|
|
pLocalHandle = pLocal;
|
|
pCacheHandle = pCache;
|
|
pNetHandle = pNet;
|
|
setExpiryAge(ulCacheAge);
|
|
|
|
// By checking if there is any info at all, we force
|
|
// initialization of remote handles if necessary
|
|
finished();
|
|
|
|
}
|
|
|
|
~CCompleteHandle() {
|
|
|
|
DBGOUT(MEM1, "CompleteHandle#" << (ulHandleCount--,ulMyHandleNo) << " Destroyed at"
|
|
<< CurrentTime() << "\n\n");
|
|
|
|
|
|
rundown();
|
|
}
|
|
|
|
/* setExpiryAge on component handles should accomplish the needful */
|
|
|
|
virtual void lookupIfNecessary() {}
|
|
|
|
virtual void rundown();
|
|
|
|
virtual void setExpiryAge(
|
|
ULONG ulCacheAge
|
|
)
|
|
{
|
|
ulCacheMax = ulCacheAge;
|
|
if (pLocalHandle) pLocalHandle->setExpiryAge(ulCacheAge);
|
|
if (pCacheHandle) pCacheHandle->setExpiryAge(ulCacheAge);
|
|
if (pNetHandle) pNetHandle->setExpiryAge(ulCacheAge);
|
|
}
|
|
|
|
ItemType *next();
|
|
|
|
int finished();
|
|
};
|
|
|
|
|
|
template <class ItemType>
|
|
ULONG
|
|
CCompleteHandle<ItemType>::ulHandleCount = 0;
|
|
|
|
|
|
template <class ItemType>
|
|
ULONG
|
|
CCompleteHandle<ItemType>::ulHandleNo = 0;
|
|
|
|
|
|
template <class ItemType>
|
|
void
|
|
CCompleteHandle<ItemType>::rundown()
|
|
{
|
|
if (pLocalHandle) pLocalHandle->rundown();
|
|
if (pCacheHandle) pCacheHandle->rundown();
|
|
if (pNetHandle) pNetHandle->rundown();
|
|
|
|
delete pLocalHandle;
|
|
delete pCacheHandle;
|
|
delete pNetHandle;
|
|
|
|
pLocalHandle = NULL;
|
|
pCacheHandle = NULL;
|
|
pNetHandle = NULL;
|
|
}
|
|
|
|
|
|
template <class ItemType>
|
|
ItemType *
|
|
CCompleteHandle<ItemType>::next()
|
|
{
|
|
if (pLocalHandle)
|
|
if (!pLocalHandle->finished())
|
|
return pLocalHandle->next();
|
|
else {
|
|
delete pLocalHandle;
|
|
pLocalHandle = NULL;
|
|
}
|
|
|
|
if (pCacheHandle)
|
|
if (!pCacheHandle->finished())
|
|
return pCacheHandle->next();
|
|
else {
|
|
delete pCacheHandle;
|
|
pCacheHandle = NULL;
|
|
}
|
|
|
|
if (pNetHandle)
|
|
if (!pNetHandle->finished())
|
|
return pNetHandle->next();
|
|
else {
|
|
delete pNetHandle;
|
|
pNetHandle = NULL;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
template <class ItemType>
|
|
int
|
|
CCompleteHandle<ItemType>::finished()
|
|
{
|
|
return (pLocalHandle ? pLocalHandle->finished() : TRUE) &&
|
|
(pCacheHandle ? pCacheHandle->finished() : TRUE) &&
|
|
(pNetHandle ? pNetHandle->finished() : TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Class Definition:
|
|
|
|
CInterfaceIndex
|
|
|
|
Abstract:
|
|
|
|
This class defines an entire interface index in the locator.
|
|
It is like a pseudo entry, but hasn't been formatted that way.
|
|
The form of the lookup method suggests it.
|
|
|
|
--*/
|
|
|
|
class Locator;
|
|
|
|
class CInterfaceIndex {
|
|
|
|
struct CInterfaceIndexEntry : public CGUID { // private class
|
|
|
|
TCSafeSkipList<CStringW> PossibleEntries;
|
|
|
|
CInterfaceIndexEntry(CGUID& guid) : CGUID(guid)
|
|
{}
|
|
|
|
~CInterfaceIndexEntry() {
|
|
PossibleEntries.wipeOut();
|
|
}
|
|
|
|
void insert(
|
|
CServerEntry * pSElocation) {
|
|
|
|
CStringW *psw = new CStringW(*pSElocation);
|
|
|
|
if (Duplicate == PossibleEntries.insert(psw))
|
|
delete psw;
|
|
}
|
|
|
|
void remove(CServerEntry * pSElocation) {
|
|
|
|
CStringW * deletedItem =
|
|
PossibleEntries.remove(pSElocation);
|
|
|
|
// the item had better be there!
|
|
|
|
ASSERT(deletedItem, "Interface Index Corrupted\n");
|
|
}
|
|
};
|
|
|
|
CReadWriteSection rwLock;
|
|
|
|
TCSafeSkipList<CInterfaceIndexEntry> InterfaceEntries;
|
|
|
|
/* the null index contains all entries in EntryList */
|
|
|
|
CInterfaceIndexEntry *pNullIndex;
|
|
|
|
Locator *pMyLocator;
|
|
|
|
public:
|
|
|
|
CInterfaceIndex(
|
|
Locator *myL
|
|
)
|
|
{
|
|
CGUID nullGUID; // inits as null UUID thru default constructor
|
|
pNullIndex = new CInterfaceIndexEntry(nullGUID);
|
|
pMyLocator = myL;
|
|
}
|
|
|
|
~CInterfaceIndex() {
|
|
InterfaceEntries.wipeOut();
|
|
delete pNullIndex;
|
|
}
|
|
|
|
void insert(
|
|
CServerEntry * pSElocation,
|
|
CInterface * pInf);
|
|
|
|
void remove(
|
|
CServerEntry * pSElocation,
|
|
CInterface * pInf);
|
|
|
|
TSLLEntryList * lookup(
|
|
CGUIDVersion * pGVInterface
|
|
);
|
|
|
|
};
|
|
|
|
|
|
#endif // _OBJECTS_
|