Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1379 lines
29 KiB

/*++
Microsoft Windows NT RPC Name Service
Copyright (c) 1995 Microsoft Corporation
Module Name:
objects.cxx
Abstract:
This file contains the implementations for non inline member functions
of all basic classes used 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.
--*/
#include <objects.hxx>
#include <api.hxx>
#include <var.hxx>
/*********** CGUID Methods **********/
CStringW*
CGUID::ConvertToString() {
STRING_T pszResult;
RPC_STATUS Status = UuidToString(
&rep,
&pszResult
);
if (Status == RPC_S_OK) {
CStringW * pswResult = new CStringW(pszResult);
RpcStringFree(&pszResult);
return pswResult;
}
else Raise(NSI_S_OUT_OF_MEMORY);
/* NOTE: the following is a dummy statement to get past the compiler. */
return NULL;
}
/*********** CGUIDVersion Methods **********/
int
CGUIDVersion::isMatching(const CGUIDVersion& o, UNSIGNED32 vers_option) {
/* vers_option decides how we match -- this is useful in,
for instance, RpcNsMgmtBindingUnexport */
CidAndVersion self(idAndVersion);
CidAndVersion other(o.idAndVersion);
if (self.id != other.id) return FALSE; // id must match
switch (vers_option) {
case RPC_C_VERS_ALL:
return TRUE;
case RPC_C_VERS_COMPATIBLE:
return (self.major == other.major) &&
(self.minor >= other.minor);
case RPC_C_VERS_EXACT:
return (self.major == other.major) &&
(self.minor == other.minor);
case RPC_C_VERS_MAJOR_ONLY:
return self.major == other.major;
case RPC_C_VERS_UPTO:
return (self.major < other.major) ||
((self.major == other.major) && (self.minor <= other.minor));
default:
Raise(NSI_S_INVALID_VERS_OPTION);
}
/* the following is a dummy statement to get past the compiler */
return NULL;
}
/*********** CBVWrapper Methods **********/
void
CBVWrapper::rundown()
{
if (pBVT)
{
for (ULONG i = 0; i < pBVT->count;i++) {
midl_user_free(pBVT->binding[i].string);
midl_user_free(pBVT->binding[i].entry_name);
}
midl_user_free(pBVT);
pBVT = NULL;
}
}
/*********** CBindingVector Methods **********/
CBindingVector::CBindingVector(
NSI_SERVER_BINDING_VECTOR_T *pbvtInVector,
CServerEntry *pEntry
)
: pMyEntry(pEntry)
{
merge(pbvtInVector);
}
int
CBindingVector::merge(
NSI_SERVER_BINDING_VECTOR_T* pHandles
)
/*++
Routine Description:
Add new binding handles to the vector.
Arguments:
pHandles - vector of allegedly new handles
Returns:
TRUE, FALSE
Remarks:
We first strip any object part present in the handle strings.
The return value FALSE signifies that there were no new binding handles.
--*/
{
int fChanges = FALSE;
CStringW *pTemp;
for (ULONG i = 0; i < pHandles->count; i++) {
NSI_STRING_BINDING_T szNextHandle = pHandles->string[i];
NSI_STRING_BINDING_T szFinalHandle = NULL;
/* first strip any object part from binding handle */
if (szNextHandle) szFinalHandle = makeBindingStringWithObject(szNextHandle,NULL);
if (szFinalHandle) {
pTemp = new CStringW(szFinalHandle);
RpcStringFree(&szFinalHandle);
if (Duplicate == insert(pTemp)) delete pTemp;
else fChanges = TRUE;
}
}
return fChanges;
}
TBVSafeLinkList *
CBindingVector::formObjBVT(
TSLLString * pLLobjectStrings,
long ulVS // max BV size
)
/*++
Routine Description:
Makes a copy of this CBindingVector in list-of-vector form replacing the
object IDs in those bindings which contain a different object and
adding the object ID to those which contain none.
Arguments:
pLLobjectStrings - the linked list of possible object ID strings
ulVS - limit on the size of the vector to be returned
Returns:
binding vector
--*/
{
long ulBVtotal = size() * max(pLLobjectStrings->size(),1);
TBVSafeLinkList * pbvsll = new TBVSafeLinkList;
long ulBVcount;
NSI_BINDING_VECTOR_T * pbvtCurrentVector;
// preform a list of all the vectors we will fill later
// better keep all counts signed for safety in comparison
for (ulBVcount = min(ulBVtotal,ulVS);
ulBVcount;
ulBVtotal -= ulBVcount, ulBVcount = min(ulBVtotal,ulVS)
)
{
pbvtCurrentVector =
(NSI_BINDING_VECTOR_T *)
midl_user_allocate(sizeof(UNSIGNED32) + sizeof(NSI_BINDING_T)*ulBVcount);
pbvtCurrentVector->count = ulBVcount;
pbvsll->insert(new CBVWrapper(pbvtCurrentVector));
}
TBVSafeLinkListIterator BViter(*pbvsll);
pbvtCurrentVector = BViter.next()->pBVT;
ulBVcount = pbvtCurrentVector->count;
TSLLStringIter ObjIter(*pLLobjectStrings);
long i = 0;
BOOL fNoneMade = TRUE; // must make at least one binding string for each
// binding even if there are no object strings
for (CStringW * pswObject = ObjIter.next();
pswObject || fNoneMade;
pswObject = ObjIter.next())
{
fNoneMade = FALSE; // made one now
TCSafeSkipListIterator<CStringW> BindingIter(*this);
for ( CStringW * pswBinding = BindingIter.next();
pswBinding;
pswBinding = BindingIter.next(), i++
)
{
STRING_T szObject;
if (pswObject) szObject = *pswObject;
else szObject = NULL;
STRING_T tempBinding =
makeBindingStringWithObject(
*pswBinding, // current binding string
szObject
);
if (i == ulBVcount) { // current vector full
// start the next one
pbvtCurrentVector = BViter.next()->pBVT;
ulBVcount = pbvtCurrentVector->count;
i = 0;
}
pbvtCurrentVector->binding[i].string = CStringW::copyMIDLstring(
tempBinding
);
pbvtCurrentVector->binding[i].entry_name = pMyEntry->copyAsMIDLstring();
pbvtCurrentVector->binding[i].entry_name_syntax = pMyEntry->ulEntryNameSyntax;
RpcStringFree(&tempBinding); // comes from a different pool
}
}
return pbvsll;
}
/*********** CEntryName Methods **********/
CEntryName::CEntryName(
CONST_STRING_T fullName
) // disassembling constructor
: CStringW(fullName)
// This constructor makes a local name if it can, and is the one that should
// be used whenever possible
{
// Enforce the correct format of the name.
parseEntryName(fullName,pswDomainName,pswEntryName);
if (isLocal()) changeToLocalName();
}
CEntryName::CEntryName( // assembling constructor
CONST_STRING_T domainName, // if NULL, assume relative name
CONST_STRING_T entryName
)
{
pswDomainName = domainName ? new CStringW(domainName) : NULL;
pswEntryName = new CStringW(entryName);
pszVal = NULL;
if (isLocal()) changeToLocalName();
else pszVal = copyGlobalName();
}
CEntryName::~CEntryName() {
delete pswDomainName;
delete pswEntryName;
}
STRING_T
CEntryName::copyGlobalName() {
CStringW * pswDomain = pswDomainName ? pswDomainName : myRpcLocator->getDomainName();
if (!pswDomain) Raise(NSI_S_INTERNAL_ERROR);
return makeGlobalName(*pswDomain,*pswEntryName);
}
int
CEntryName::isLocal() {
return !pswDomainName || (*pswDomainName == *myRpcLocator->getDomainName());
}
/*********** CInterface Methods **********/
CInterface::CInterface(
NSI_INTERFACE_ID_T * lpInf,
NSI_SERVER_BINDING_VECTOR_T *BindingVector,
CServerEntry *pMyEntry
)
: CGUIDVersion(lpInf->Interface),
transferSyntax(lpInf->TransferSyntax)
{
pBVhandles = new CBindingVector(BindingVector,pMyEntry);
}
/*********** CServerEntry Methods **********/
void
CServerEntry::flush() {
CriticalWriter me(rwEntryGuard);
DBGOUT(OBJECT, ObjectList.size() << " Objects Flushed\n");
DBGOUT(OBJECT, InterfaceList.size() << " Interfaces Flushed\n\n");
ObjectList.wipeOut();
InterfaceList.wipeOut();
}
int CServerEntry::addObjects(
NSI_UUID_VECTOR_P_T objectVector
)
{
CGUID *lpObject;
int fChanges = FALSE;
CriticalWriter me(rwEntryGuard);
for (unsigned long i = 0; i < objectVector->count; i++) {
lpObject = new CGUID(*(objectVector->uuid[i]));
if (Duplicate == ObjectList.insert(lpObject)) delete lpObject;
else fChanges = TRUE;
}
return fChanges;
}
int CServerEntry::removeObjects(
NSI_UUID_VECTOR_P_T objectVector,
int& fRemovedAll
)
{
int fChanges = FALSE;
fRemovedAll = TRUE;
CGUID *pRemovedObject;
CriticalWriter me(rwEntryGuard);
for (unsigned long i = 0; i < objectVector->count; i++) {
CGUID Object(*objectVector->uuid[i]);
if (pRemovedObject = ObjectList.remove(&Object)) {
fChanges = TRUE;
delete pRemovedObject;
}
else fRemovedAll = FALSE;
}
return fChanges;
}
int CServerEntry::addToInterface(
NSI_INTERFACE_ID_T *lpInf,
NSI_SERVER_BINDING_VECTOR_T *lpBindingVector,
CInterfaceIndex* IfIndex
)
/*++
Routine Description:
Add new binding handles to the given interface and
insert as a new interface if necessary.
Arguments:
lpInf - Interface
lpBindingVector - Vector of string bindings to add
IfIndex - the interface index to insert a new interface into (besides self)
Returns:
TRUE or FALSE
Remarks:
The return value signifies whether the binding handles were new
or the interface was new, i.e., whether the entry was actually updated.
FALSE means no change.
--*/
{
CInterface *pTargetInterface;
int fChanges = FALSE;
CriticalWriter me(rwEntryGuard);
pTargetInterface = InterfaceList.find(&CGUIDVersion(lpInf->Interface));
if (pTargetInterface)
fChanges = pTargetInterface->mergeHandles(lpBindingVector);
else {
pTargetInterface = new CInterface(lpInf,lpBindingVector,this);
InterfaceList.insert(pTargetInterface);
IfIndex->insert(this,pTargetInterface);
fChanges = TRUE;
}
return fChanges;
}
int CServerEntry::removeInterfaces(
NSI_IF_ID_P_T lpInf,
UNSIGNED32 VersOption,
CInterfaceIndex* IfIndex
)
/*++
Routine Description:
Remove all matching interfaces from the entry.
Arguments:
lpInf - Base Interface Spec
VersOption - Compatibility spec that decides which interfaces
match the base spec, and should be removed
IfIndex - the interface index to remove interfaces from (besides self)
Returns:
TRUE, FALSE
Remarks:
The return value signifies whether any interfaces were removed.
--*/
{
int fChanges = FALSE;
CriticalWriter me(rwEntryGuard);
CGUIDVersion baseIf(*lpInf);
TCSafeSkipListIterator<CInterface> IfIter(InterfaceList);
for (CInterface *pIf = IfIter.next(); pIf != NULL; pIf = IfIter.next())
if (pIf->isMatching(baseIf,VersOption)) {
InterfaceList.remove(pIf);
IfIndex->remove(this,pIf);
delete pIf;
fChanges = TRUE;
}
return fChanges;
}
TSLLString*
CServerEntry::formObjectStrings(
CGUID * pIDobject
)
/*++
Method Description:
We form a list of object UUID strings. The list is empty if there is
no OID involved (the client specified none and the entry contains none).
The list contains only the string form of pIDobject if pIDobject is not
NULL, and contains all UUIDs in the entry in string form otherwise.
This is a private method, and must be called only within a reader guard.
--*/
{
TSLLString * pLLobjectStrings = new TSLLString;
if (pIDobject) pLLobjectStrings->insert(pIDobject->ConvertToString());
else
{
TCSafeSkipListIterator<CGUID> ObjIter(ObjectList);
for (CGUID *pID = ObjIter.next(); pID != NULL; pID = ObjIter.next())
pLLobjectStrings->insert(pID->ConvertToString());
}
return pLLobjectStrings;
}
CLookupHandle *
CServerEntry::lookup(
CGUIDVersion * pGVInterface,
CGUIDVersion * pGVTransferSyntax,
CGUID * pIDobject,
unsigned long ulVectorSize,
unsigned long ulCacheAge // ignored in this case
)
/*++
Method Description: CServerEntry::lookup
lookup an entry and form a linked list of binding vectors corresponding
to the interface and object specification given, then wrap it in a
lookup handle to make it ready for iteration.
Arguments:
pGVInterface - Interface (and version)
pGVTransferSyntax - Transfer syntax (ignored)
pIDobject - object UUID we want
ulVectorSize - max size of BVs to be sent
Returns:
a lookup handle
Remarks:
--*/
{
if (pIDobject && !memberObject(pIDobject)) // object not found
return new CServerLookupHandle( // return empty handle
new TBVSafeLinkList
);
/* better to put this after the memberObject call, which itself uses
a lock on rwEntryGuard, although also as a reader */
CriticalReader me(rwEntryGuard);
// Object OK, now find compatible interfaces
TCSafeSkipListIterator<CInterface> IfIter(InterfaceList);
TBVSafeLinkList * pBVLLbindings = new TBVSafeLinkList;
TSLLString * pLLobjectStrings = formObjectStrings(pIDobject);
for (CInterface *pIf = IfIter.next(); pIf != NULL; pIf = IfIter.next())
if (!pGVInterface ||
pIf->isCompatibleWith(pGVInterface,pGVTransferSyntax)
)
{
/* we randomize the BV list by randomly using either push or enque
to insert each BV into the list -- this is accomplished by using
randomized initialization of the pointer-to-member-function "put"
NOTE: put should be an intrinsic on Linked Lists -- and
used in formObjBVT
void (TBVSafeLinkList::*put)(NSI_BINDING_VECTOR_T*);
put = ((rand() % 2) ? TBVSafeLinkList::push : TBVSafeLinkList::enque);
*/
TBVSafeLinkList * pbvList =
pIf->pBVhandles->formObjBVT(
pLLobjectStrings,
ulVectorSize
);
pBVLLbindings->catenate(*pbvList);
delete pbvList;
}
/* finally, run down the object strings before returning the handle */
TCSafeLinkListIterator<CStringW> runDownIter(*pLLobjectStrings);
for (CStringW * psw = runDownIter.next(); psw; psw = runDownIter.next())
delete psw;
delete pLLobjectStrings;
return new CServerLookupHandle(
pBVLLbindings
);
}
/* BUGBUG: A CServerObjectInqHandle created by the following seems to be leaked in the
master (PDC) locator in CT test#511, perhaps only when the test fails, which it does
when the client locator is new and the server locator is old -- needs investigation */
CObjectInqHandle *
CServerEntry::objectInquiry(
unsigned long ulCacheAge
)
{
CriticalReader me(rwEntryGuard);
TCSafeSkipListIterator<CGUID> ssli(ObjectList);
TCSafeSkipList<CGUID> *pssl = new TCSafeSkipList<CGUID>;
for (CGUID* pguid = ssli.next(); pguid; pguid = ssli.next())
{
CGUID * pGuidCopy = new CGUID(*pguid);
pssl->insert(pGuidCopy);
}
TSSLGuidIterator *pGuidIter = new TSSLGuidIterator(*pssl);
delete pssl;
return new CServerObjectInqHandle(
pGuidIter,
ulCacheAge
);
}
/*********** CRemoteLookupHandle Methods **********/
#if DBG
ULONG CRemoteLookupHandle::ulHandleCount = 0;
ULONG CRemoteObjectInqHandle::ulHandleCount = 0;
#endif
CRemoteLookupHandle::CRemoteLookupHandle(
UNSIGNED32 EntryNameSyntax,
STRING_T EntryName,
CGUIDVersion * pGVInterface,
CGUIDVersion * pGVTransferSyntax,
CGUID * pIDobject,
unsigned long ulVectorSize,
unsigned long ulCacheAge
)
{
DBGOUT(MEM2, "RemoteLookupHandle#" << (ulHandleNo = ++ulHandleCount)
<< " Created at" << CurrentTime() << "\n\n");
u32EntryNameSyntax = EntryNameSyntax;
penEntryName = EntryName ? new CEntryName(EntryName) : NULL;
pgvInterface = pGVInterface ? new CGUIDVersion(*pGVInterface) : NULL;
pgvTransferSyntax = pGVTransferSyntax ?
new CGUIDVersion(*pGVTransferSyntax) :
NULL;
pidObject = pIDobject ? new CGUID(*pIDobject) : NULL;
ulVS = ulVectorSize;
ulCacheMax = ulCacheAge;
fNotInitialized = TRUE;
plhFetched = NULL;
psslNewCache = NULL;
}
/*********** CNetLookupHandle Methods **********/
#if DBG
ULONG CNetLookupHandle::ulNetLookupHandleCount = 0;
ULONG CNetLookupHandle::ulNetLookupHandleNo = 0;
#endif
void
CNetLookupHandle::initialize()
{
STRING_T szEntryName;
if (penEntryName) szEntryName = *penEntryName;
else szEntryName = NULL;
DBGOUT(TRACE,"CNetLookupHandle::initialize called for Handle#" << ulHandleNo << "\n\n");
if (!myRpcLocator->IsInMasterRole())
{
pRealHandle = new CMasterLookupHandle(
u32EntryNameSyntax,
szEntryName,
pgvInterface,
pgvTransferSyntax,
pidObject,
ulVS,
ulCacheMax
);
// force initialization to make sure connection to master is OK
pRealHandle->initialize();
}
if (myRpcLocator->IsInMasterRole() ||
(!IsNormalCode(pRealHandle->StatusCode) && myRpcLocator->IsInBackupRole())
)
{
if (myRpcLocator->IsInWorkgroup()) // we are in a workgroup, so become masterful
myRpcLocator->becomeMasterLocator();
if (pRealHandle) delete pRealHandle;
pRealHandle = new CBroadcastLookupHandle(
u32EntryNameSyntax,
szEntryName,
pgvInterface,
pgvTransferSyntax,
pidObject,
ulVS,
ulCacheMax
);
}
fNotInitialized = FALSE;
}
/*********** CNetObjectInqHandle Methods **********/
void
CNetObjectInqHandle::initialize()
{
if (!myRpcLocator->IsInMasterRole())
{
pRealHandle = new CMasterObjectInqHandle(
*penEntryName,
ulCacheMax
);
// force initialization to make sure connection to master is OK
pRealHandle->initialize();
}
if (myRpcLocator->IsInMasterRole() ||
(!IsNormalCode(pRealHandle->StatusCode) && myRpcLocator->IsInBackupRole())
)
{
if (myRpcLocator->IsInWorkgroup()) // we are in a workgroup, so become masterful
myRpcLocator->becomeMasterLocator();
if (pRealHandle) delete pRealHandle;
pRealHandle = new CBroadcastObjectInqHandle(
*penEntryName,
ulCacheMax
);
}
}
/*********** CServerLookupHandle Methods **********/
void
CServerLookupHandle::rundown() {
CBVWrapper *pbvw;
if (pBVIterator)
{
for (pbvw = pBVIterator->next(); pbvw; pbvw = pBVIterator->next()) {
pbvw->rundown();
delete pbvw;
}
delete pBVIterator;
pBVIterator = NULL;
}
}
CServerLookupHandle::CServerLookupHandle(
TBVSafeLinkList * pBVLL
)
{
pBVIterator = new TBVSafeLinkListIterator(*pBVLL);
/* it seems bizarre to do the following, but reference counting and
the fDeleteData flag in Link objects ensure that nothing is
destroyed prematurely. This just sets things up so that objects
are automatically deleted as they are used up. Note that the BV objects
themselves are freed automatically by the stub as they are passed back.
Unused BV objects will be reclaimed by rundown/done using middle_user_free.
*/
delete pBVLL;
}
/*********** CServerObjectInqHandle Methods **********/
void
CServerObjectInqHandle::rundown()
{
if (pcgIterSource)
{
for (CGUID* pg = pcgIterSource->next(); pg; pg = pcgIterSource->next())
delete pg;
delete pcgIterSource;
pcgIterSource = NULL;
}
}
GUID *
CServerObjectInqHandle::next() {
CGUID* pg = pcgIterSource->next();
GUID * result = NULL;
if (pg) {
result = (GUID*) midl_user_allocate(sizeof(GUID));
*result = pg->myGUID();
delete pg;
}
return result;
}
/*********** CCacheServerEntry Methods **********/
BOOL
CCacheServerEntry::isCurrent(ULONG ulTolerance) {
CriticalReader me(rwCacheEntryGuard);
return fHasCachedInfo && IsStillCurrent(ulCacheTime,ulTolerance);
}
CLookupHandle *
CCacheServerEntry::lookup(
CGUIDVersion * pGVInterface,
CGUIDVersion * pGVTransferSyntax,
CGUID * pIDobject,
unsigned long ulVectorSize,
unsigned long ulCacheAge
)
{
CriticalReader me(rwCacheEntryGuard);
return new CCacheServerLookupHandle(
getCurrentName(),
pGVInterface,
pGVTransferSyntax,
pIDobject,
ulVectorSize,
ulCacheAge
);
}
CObjectInqHandle *
CCacheServerEntry::objectInquiry(
unsigned long ulCacheAge
)
{
CriticalReader me(rwCacheEntryGuard);
return new CCacheServerObjectInqHandle(
getCurrentName(),
ulCacheAge
);
}
/*********** CFullServerEntry Methods **********/
void
CFullServerEntry::flushCacheIfNecessary(ULONG ulTolerance)
{
CriticalReader me(rwFullEntryGuard);
if (!pCachedEntry->isCurrent(ulTolerance))
{
pCachedEntry->flush();
/*
Note that the "flushing" may be spurious -- it may happen
because the cached entry has no cached info.
*/
}
}
CLookupHandle *
CFullServerEntry::lookup(
CGUIDVersion * pGVInterface,
CGUIDVersion * pGVTransferSyntax,
CGUID * pIDobject,
unsigned long ulVectorSize,
unsigned long ulCacheAge
)
{
CriticalReader me(rwFullEntryGuard);
CLookupHandle *
pLocalHandle = pLocalEntry->lookup(
pGVInterface,
pGVTransferSyntax,
pIDobject,
ulVectorSize,
ulCacheAge
);
flushCacheIfNecessary(ulCacheAge);
/* it is important to do the cache lookup before the net lookup so as
to avoid duplication in the results returned. If the net lookup uses
a broadcast handle, the initialization will create both a private and a
public cache (the former to avoid duplication), and the latter will be
picked up by cache lookup if it is done later.
*/
CLookupHandle *
pCacheHandle = pCachedEntry->lookup(
pGVInterface,
pGVTransferSyntax,
pIDobject,
ulVectorSize,
ulCacheAge
);
CLookupHandle *
pNetHandle = myRpcLocator->NetLookup(
RPC_C_NS_SYNTAX_DCE,
getCurrentName(),
pGVInterface,
pGVTransferSyntax,
pIDobject,
ulVectorSize,
ulCacheAge
);
return new CCompleteHandle<NSI_BINDING_VECTOR_T>(
pLocalHandle,
pCacheHandle,
pNetHandle,
ulCacheAge
);
}
CObjectInqHandle *
CFullServerEntry::objectInquiry(
unsigned long ulCacheAge
)
{
CriticalReader me(rwFullEntryGuard);
CObjectInqHandle *
pLocalHandle = pLocalEntry->objectInquiry(
ulCacheAge
);
CObjectInqHandle *
pCacheHandle = pCachedEntry->objectInquiry(
ulCacheAge
);
CObjectInqHandle *
pNetHandle = myRpcLocator->NetObjectInquiry(
RPC_C_NS_SYNTAX_DCE,
getCurrentName()
);
return new CCompleteHandle<GUID>(
pLocalHandle,
pCacheHandle,
pNetHandle,
ulCacheAge
);
}
/*********** CCacheServerLookupHandle Methods **********/
void
CCacheServerLookupHandle::initialize()
{
CEntry *pE = myRpcLocator->getEntry(RPC_C_NS_SYNTAX_DCE,*penEntryName,NULL);
CCacheServerEntry *pEntry;
if (pE->getType() == FullServerEntryType)
pEntry = ((CFullServerEntry*)pE)->getCache();
else if (pE->getType() == CacheServerEntryType)
pEntry = (CCacheServerEntry*)pE;
else pEntry = NULL;
if (pEntry) plhFetched = pEntry->CServerEntry::lookup(
pgvInterface,
pgvTransferSyntax,
pidObject,
ulVS,
ulCacheMax
);
else plhFetched = NULL;
ulCreationTime = CurrentTime();
fNotInitialized = FALSE;
}
CCacheServerLookupHandle::CCacheServerLookupHandle(
STRING_T szEntryName,
CGUIDVersion *pGVInterface,
CGUIDVersion *pGVTransferSyntax,
CGUID *pIDobject,
ULONG ulVectorSize,
ULONG ulCacheAge
)
: CRemoteLookupHandle(
RPC_C_NS_SYNTAX_DCE,
szEntryName,
pGVInterface,
pGVTransferSyntax,
pIDobject,
ulVectorSize,
ulCacheAge
)
{
}
/*********** CCacheServerObjectInqHandle Methods **********/
void
CCacheServerObjectInqHandle::initialize()
{
ulIndex = 0;
CCacheServerEntry *pEntry;
// get the cached entry again because it may have expired, been deleted and replaced
CEntry *pE = myRpcLocator->getEntry(RPC_C_NS_SYNTAX_DCE,*penEntryName,NULL);
if (pE->getType() == FullServerEntryType)
pEntry = ((CFullServerEntry*)pE)->getCache();
else if (pE->getType() == CacheServerEntryType)
pEntry = (CCacheServerEntry*)pE;
else pEntry = NULL;
if (pEntry) {
CObjectInqHandle *pTempHandle = pEntry->CServerEntry::objectInquiry(ulCacheMax);
pUuidVector = getVector(pTempHandle);
delete pTempHandle;
}
else pUuidVector = NULL;
ulCreationTime = CurrentTime();
fNotInitialized = FALSE;
}
CCacheServerObjectInqHandle::CCacheServerObjectInqHandle(
STRING_T szEntryName,
ULONG ulCacheAge
)
: CRemoteObjectInqHandle(szEntryName,ulCacheAge)
{
}
/***************** CGroupLookupHandle Methods *****************/
CGroupLookupHandle::CGroupLookupHandle(
TEntryIterator * pEI,
CGUIDVersion * pGVInf,
CGUIDVersion * pGVXferSyntax,
CGUID * pIDobj,
unsigned long ulVectSize,
unsigned long ulCacheAge
)
{
ulCacheMax = ulCacheAge;
pGVInterface = pGVInf ? new CGUIDVersion(*pGVInf) : NULL;
pGVTransferSyntax = pGVXferSyntax ? new CGUIDVersion(*pGVXferSyntax) : NULL;
pIDobject = pIDobj ? new CGUID(*pIDobj) : NULL;
ulVectorSize = ulVectSize;
pCurrentHandle = NULL;
pEIterator = pEI;
advanceCurrentHandle();
}
void
CGroupLookupHandle::advanceCurrentHandle()
{
delete pCurrentHandle;
pCurrentHandle = NULL;
for (CEntry *pCurEntry = pEIterator->next(); pCurEntry; pCurEntry = pEIterator->next())
{
pCurrentHandle = pCurEntry->lookup( // INVARIANT: lookup returns non-NULL
pGVInterface,
pGVTransferSyntax,
pIDobject,
ulVectorSize,
ulCacheMax
);
ASSERT(pCurrentHandle,"advanceCurrentHandle got NULL handle\n");
pCurrentHandle->setExpiryAge(ulCacheMax);
if (!pCurrentHandle->finished()) break;
else {
delete pCurrentHandle;
pCurrentHandle = NULL;
}
}
}
NSI_BINDING_VECTOR_T *
CGroupLookupHandle::next()
{
if (pCurrentHandle && pCurrentHandle->finished())
advanceCurrentHandle();
if (!pCurrentHandle) return NULL; // no more entries
else return pCurrentHandle->next();
}
int
CGroupLookupHandle::finished()
{
if (pCurrentHandle && pCurrentHandle->finished())
advanceCurrentHandle();
if (!pCurrentHandle) return TRUE; // no more entries
else return FALSE;
}
/***************** CIndexLookupHandle Methods *****************/
void
CIndexLookupHandle::lookupIfNecessary() { // client unhappy, start all over again
rundown();
delete pEIterator;
pEIterator = myRpcLocator->IndexLookup(pGVInterface);
advanceCurrentHandle();
}
CIndexLookupHandle::CIndexLookupHandle(
CGUIDVersion * pGVInf,
CGUIDVersion * pGVXferSyntax,
CGUID * pIDobj,
unsigned long ulVectSize,
unsigned long ulCacheAge
)
: CGroupLookupHandle(
myRpcLocator->IndexLookup(pGVInf),
pGVInf,
pGVXferSyntax,
pIDobj,
ulVectSize,
ulCacheAge
)
{}
/***************** CInterfaceIndex Methods *****************/
void
CInterfaceIndex::insert(
CServerEntry * pSElocation,
CInterface * pInf)
/*++
Routine Description:
Insert an interface into the interface index. The interface is either new
or has had some new binding handles inserted in it. In the latter case,
we do not need to reinsert it.
Arguments:
pSElocation - The server entry where the interface occurs
pInf - The new or changed interface
Returns:
nothing
--*/
{
CGUID InfID(pInf->myGUID());
CriticalWriter me(rwLock); // acquires writer lock
CInterfaceIndexEntry *pCurrentIndex =
InterfaceEntries.find(&InfID);
if (!pCurrentIndex) {
pCurrentIndex = new CInterfaceIndexEntry(InfID);
InterfaceEntries.insert(pCurrentIndex);
}
pCurrentIndex->insert(pSElocation);
pNullIndex->insert(pSElocation);
}
void
CInterfaceIndex::remove(
CServerEntry * pSElocation,
CInterface * pInf)
/*++
Routine Description:
Remove an interface from the interface index.
Arguments:
pSElocation - The server entry where the interface occurs
pInf - The new or changed interface
Returns:
nothing
Remarks:
Currently, this routine does nothing since we don't know when ALL
interfaces with a given GUID have been removed from an entry.
This is harmless since it only means that we may search such an entry
uselessly for this interface -- a performance problem only.
--*/
{
}
TSLLEntryList *
CInterfaceIndex::lookup(
CGUIDVersion * pGVInterface
)
{
TSLLEntryList * pTrialEntries = new TSLLEntryList;
CInterfaceIndexEntry *pIndex = NULL;
CriticalReader me(rwLock);
if (!pGVInterface) pIndex = pNullIndex;
else {
CGUID InfID(pGVInterface->myGUID());
pIndex = InterfaceEntries.find(&InfID);
}
if (pIndex) {
TCSafeSkipListIterator<CStringW> iter(pIndex->PossibleEntries);
/* the reason for splitting full entries and separately inserting cache
and local entries below is to avoid net lookup for these these
entries. Since Index lookup is used exclusively for default
entry lookup, there is a separate net component to it already.
*/
for (CStringW *pName = iter.next(); pName; pName = iter.next()) {
CEntry * pEntry = pMyLocator->findEntry(pName);
/* NOTE: only full server entries are indexed */
CFullServerEntry *pfse = (CFullServerEntry *) pEntry;
if (pfse) {
ASSERT(pfse->getType() == FullServerEntryType,
"Wrong entry type in interface index\n"
);
pTrialEntries->insert(pfse->getLocal());
pTrialEntries->insert(pfse->getCache());
}
}
}
return pTrialEntries;
}