Leaked source code of windows server 2003
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.

3299 lines
107 KiB

  1. /*++
  2. Microsoft Windows NT RPC Name Service
  3. Copyright (C) Microsoft Corporation, 1995 - 1999
  4. Module Name:
  5. objects.hxx
  6. Abstract:
  7. This file contains the definitions of all basic classes used in the server,
  8. excluding the data structure classes and classes used for network interactions.
  9. Author:
  10. Satish Thatte (SatishT) 08/21/95 Created all the code below except where
  11. otherwise indicated.
  12. --*/
  13. /* For every operation with a dynamic object, memory
  14. management should be a part of the description and
  15. specification for every parameter. Fix that along
  16. with other documentation.
  17. */
  18. #ifndef _OBJECTS_HXX_
  19. #define _OBJECTS_HXX_
  20. class CGUID;
  21. class CInterface;
  22. struct CBVWrapper;
  23. class CServerEntry;
  24. class CNonLocalServerEntry;
  25. class CFullServerEntry;
  26. class CInterfaceIndex;
  27. struct CMailSlotReplyItem;
  28. class CServerLookupHandle;
  29. class CServerObjectInqHandle;
  30. typedef TIIterator<CGUID> TGuidIterator;
  31. // The following enumeration is the the type of entry the object is.
  32. enum EntryType {
  33. ServerEntryType,
  34. GroupEntryType,
  35. ProfileEntryType,
  36. NonLocalServerEntryType,
  37. FullServerEntryType,
  38. MemberEntryType,
  39. AnyEntryType
  40. };
  41. /*++
  42. Class Definition:
  43. CUnsigned32
  44. Abstract:
  45. This is the unsigned number wrapper class.
  46. --*/
  47. class CUnsigned32 : public IOrderedItem {
  48. protected:
  49. DWORD dwVal;
  50. public:
  51. CUnsigned32() {
  52. dwVal = 0;
  53. }
  54. CUnsigned32( const DWORD dw ) {
  55. dwVal = dw;
  56. }
  57. operator DWORD() { return dwVal; }
  58. virtual int compare( const IOrderedItem& O ) {
  59. const CUnsigned32& arg = (CUnsigned32&) O;
  60. return dwVal > arg.dwVal ? 1 : (dwVal == arg.dwVal ? 0 : -1);
  61. }
  62. };
  63. /*++
  64. Class Definition:
  65. CStringW
  66. Abstract:
  67. This is the unicode string wrapper class.
  68. Note that string comparison is case insensitive.
  69. --*/
  70. class CStringW : public IOrderedItem {
  71. protected:
  72. STRING_T pszVal;
  73. public:
  74. int length() { return wcslen(pszVal); }
  75. int isEmptyString() {
  76. return (pszVal == NULL) || (_wcsicmp(pszVal,TEXT("")) == 0);
  77. }
  78. static STRING_T copyString(
  79. CONST_STRING_T str
  80. )
  81. {
  82. STRING_T result = new WCHAR [(wcslen(str)+1)*sizeof(WCHAR)];
  83. wcscpy(result,str);
  84. return result;
  85. }
  86. static STRING_T copyMIDLstring( // for use in out RPC parameters
  87. // which are deallocated by stubs
  88. CONST_STRING_T str
  89. )
  90. {
  91. STRING_T result = (STRING_T) midl_user_allocate((wcslen(str)+1)*sizeof(WCHAR));
  92. wcscpy(result,str);
  93. return result;
  94. }
  95. STRING_T copyAsString() {
  96. return copyString(pszVal);
  97. }
  98. STRING_T copyAsMIDLstring() { // for use in out RPC parameters
  99. // which are deallocated by stubs
  100. return copyMIDLstring(pszVal);
  101. }
  102. CStringW() {
  103. pszVal = NULL;
  104. }
  105. CStringW( CONST_STRING_T p ) {
  106. pszVal = copyString(p);
  107. }
  108. CStringW& operator=( const CStringW& str ) {
  109. delete [] pszVal;
  110. pszVal = copyString(str.pszVal);
  111. return *this;
  112. }
  113. CStringW( const CStringW& str ) {
  114. pszVal = copyString(str.pszVal);
  115. }
  116. virtual ~CStringW() // base class destructor should be virtual
  117. {
  118. delete [] pszVal;
  119. }
  120. operator STRING_T() { return pszVal; }
  121. virtual int compare( const IOrderedItem& O ) {
  122. const CStringW& S = (CStringW&) O;
  123. return _wcsicmp(pszVal,S.pszVal);
  124. }
  125. };
  126. typedef TCGuardedSkipList<CStringW> TGSLString;
  127. typedef TCGuardedSkipListIterator<CStringW> TGSLStringIter;
  128. typedef TCSafeSkipList<CStringW> TSSLString;
  129. typedef TCSafeSkipListIterator<CStringW> TSSLStringIter;
  130. typedef TCSafeLinkList<CStringW> TSLLString;
  131. typedef TCSafeLinkListIterator<CStringW> TSLLStringIter;
  132. /*++
  133. Class Definition:
  134. CGUID
  135. Abstract:
  136. This is the GUID wrapper class.
  137. --*/
  138. class CGUID : public IOrderedItem {
  139. GUID rep;
  140. public:
  141. CGUID() {
  142. memset(&rep,0,sizeof(rep));
  143. }
  144. CGUID( const GUID& g ) : rep(g) {}
  145. virtual int compare(const IOrderedItem& C ) {
  146. CGUID& S = (CGUID&) C;
  147. return memcmp(&rep, &(S.rep),sizeof(rep));
  148. }
  149. GUID myGUID() { return rep; }
  150. BOOL IsNil() {
  151. RPC_STATUS dummyStatus;
  152. return UuidIsNil(&rep,&dummyStatus);
  153. }
  154. CStringW* ConvertToString();
  155. };
  156. typedef TCSafeSkipListIterator<CGUID> TSSLGuidIterator;
  157. /*++
  158. Class Definition:
  159. CGUIDVersion
  160. Abstract:
  161. This is the RPC_SYNTAX_IDENTIFIER wrapper class.
  162. --*/
  163. class CGUIDVersion : public IOrderedItem {
  164. protected:
  165. struct CidAndVersion { // this is just a readability aid for
  166. // the implementation of isCompatibleGV
  167. CGUID id;
  168. unsigned short major;
  169. unsigned short minor;
  170. CidAndVersion (const RPC_SYNTAX_IDENTIFIER& in) : id(in.SyntaxGUID) {
  171. major = in.SyntaxVersion.MajorVersion;
  172. minor = in.SyntaxVersion.MinorVersion;
  173. }
  174. CidAndVersion() {
  175. memset(&id,0,sizeof(GUID));
  176. major = minor = 0;
  177. }
  178. };
  179. RPC_SYNTAX_IDENTIFIER idAndVersion;
  180. public:
  181. CGUIDVersion( const RPC_SYNTAX_IDENTIFIER& g ) {
  182. idAndVersion = g;
  183. }
  184. CGUIDVersion() {memset(&idAndVersion, 0, sizeof(idAndVersion));} // NULL case
  185. RPC_SYNTAX_IDENTIFIER myIdAndVersion() { return idAndVersion; }
  186. operator RPC_SYNTAX_IDENTIFIER() { return idAndVersion; }
  187. GUID myGUID() { return idAndVersion.SyntaxGUID; }
  188. virtual int compare(const IOrderedItem& C ) {
  189. const CGUIDVersion& S = (CGUIDVersion&) C;
  190. return memcmp(&idAndVersion, &S.idAndVersion, sizeof(RPC_SYNTAX_IDENTIFIER));
  191. }
  192. int isMatching(const CGUIDVersion& other, UNSIGNED32 vers_option);
  193. int isCompatibleGV(const CGUIDVersion& other) {
  194. return isMatching(other,RPC_C_VERS_COMPATIBLE);
  195. }
  196. };
  197. /*++
  198. Class Definition:
  199. CMailSlotReplyItem
  200. Abstract:
  201. This is the class of items to be marshalled into mailslot reply buffers.
  202. The class, and especially the marshalling code, is dictated largely by
  203. compatibility requirements for the old locator.
  204. Everything in a CMailSlotReplyItem object is borrowed from some
  205. other object and is therefore not freed upon destruction.
  206. The primary operation is "marshall".
  207. --*/
  208. struct CMailSlotReplyItem : public IDataItem {
  209. /* these are the items needed to marshall a reply packet */
  210. RPC_SYNTAX_IDENTIFIER Interface;
  211. RPC_SYNTAX_IDENTIFIER XferSyntax;
  212. STRING_T binding;
  213. STRING_T entryName;
  214. TCSafeSkipList<CGUID> *pObjectList;
  215. /* the marshall operation returns the number of bytes written to the buffer */
  216. DWORD Marshall(char * pcBuffer, long lBufferSize);
  217. };
  218. typedef TIIterator<CMailSlotReplyItem> TMSRIIterator;
  219. typedef TCSafeLinkList<CMailSlotReplyItem> TMSRILinkList;
  220. typedef TCSafeLinkListIterator<CMailSlotReplyItem> TMSRILinkListIterator;
  221. /*++
  222. Class Definition:
  223. CBVWrapper
  224. Abstract:
  225. This is a very thin wrapper for NSI_BINDING_VECTOR_T to make the
  226. latter usable with linked lists (by inheriting from IDataItem).
  227. --*/
  228. struct CBVWrapper : public IDataItem {
  229. NSI_BINDING_VECTOR_T *pBVT;
  230. CBVWrapper(NSI_BINDING_VECTOR_T *p) {
  231. pBVT = p;
  232. }
  233. void rundown();
  234. };
  235. typedef TIIterator<CBVWrapper> TBVIterator;
  236. typedef TCSafeLinkList<CBVWrapper> TBVSafeLinkList;
  237. typedef TCSafeLinkListIterator<CBVWrapper> TBVSafeLinkListIterator;
  238. /*++
  239. Class Definition:
  240. CNSBinding
  241. Abstract:
  242. A thin wrapper for NSI_BINDING_T. Note that the strings in a NSI_BINDING_T used
  243. to initialize a CNSBinding object are not copied, only the pointers are copied.
  244. --*/
  245. class CNSBinding : public CStringW
  246. {
  247. NSI_BINDING_T rep;
  248. public:
  249. CNSBinding( // this is a little crude, but hey..
  250. NSI_BINDING_T& binding
  251. ) : rep(binding)
  252. {
  253. pszVal = catenate(
  254. binding.string,
  255. binding.entry_name
  256. );
  257. }
  258. operator NSI_BINDING_T()
  259. {
  260. return rep;
  261. }
  262. void
  263. copyBinding(NSI_BINDING_T& result)
  264. {
  265. result.string = CStringW::copyMIDLstring(rep.string);
  266. result.entry_name = CStringW::copyMIDLstring(rep.entry_name);
  267. result.entry_name_syntax = rep.entry_name_syntax;
  268. }
  269. };
  270. /*++
  271. Class Definition:
  272. CBindingVector
  273. Abstract:
  274. Used mainly to keep vectors of binding handles. Iterators returning
  275. vectors of handles is what most NS handles are in essence.
  276. --*/
  277. class CBindingVector : public TCSafeSkipList<CStringW>
  278. {
  279. CServerEntry *pMyEntry; // the entry this belongs to
  280. public:
  281. CBindingVector(NSI_SERVER_BINDING_VECTOR_T*, CServerEntry*);
  282. CBindingVector(CServerEntry *pEntry)
  283. : pMyEntry(pEntry)
  284. {
  285. }
  286. ~CBindingVector() { // must destroy binding strings stored here
  287. wipeOut();
  288. }
  289. int merge(NSI_SERVER_BINDING_VECTOR_T* pHandles);
  290. TBVSafeLinkList * formObjBVT(
  291. TSLLString * pLLobjectStrings,
  292. long ulVS // max BV size
  293. );
  294. SkipStatus insertBindingHandle(STRING_T bindingHandle) {
  295. CStringW *pTemp = new CStringW(bindingHandle);
  296. return insert(pTemp);
  297. }
  298. // so that this can be marshalled when a reply has to
  299. // be sent to broadcast requests.
  300. TMSRILinkList *msriList(
  301. CInterface *pIf,
  302. TCSafeSkipList<CGUID>* psslObjList
  303. );
  304. // remove from the binding vector the bindings that
  305. // are common to another binding vector. this is used
  306. // again for backward compatibility to remove common
  307. // binding vector from old locator.
  308. // returns false if the binding vector is emptied.
  309. // this function assumes that these are called for
  310. // the same entry names.
  311. BOOL purgeCommonEntries(CBindingVector *src)
  312. {
  313. ULONG sz, i;
  314. CStringW *pBinding1, *pBinding2;
  315. TCSafeSkipListIterator<CStringW> pBindingIterator(*this);
  316. sz = size();
  317. for (i = 0; i < sz; i++)
  318. {
  319. pBinding1 = pBindingIterator.next();
  320. pBinding2 = src->find(pBinding1);
  321. if (pBinding2)
  322. remove(pBinding2);
  323. }
  324. if (size())
  325. return FALSE;
  326. else
  327. return TRUE;
  328. }
  329. };
  330. /*++
  331. Class Definition:
  332. CInterface
  333. Abstract:
  334. An interface and its vector of binding handles.
  335. The interface can be searched for, using the GUIDVersion
  336. comparison operator.
  337. The major caveat is that we essentially ignore transfer syntax.
  338. According to DCE, there should be a separate entry for each
  339. interface/transfer syntax combination. We assume that NDR is
  340. always used.
  341. --*/
  342. class CInterface : public CGUIDVersion {
  343. friend class CServerEntry;
  344. private:
  345. CServerEntry * m_pMyEntry;
  346. CGUIDVersion transferSyntax;
  347. CBindingVector * pBVhandles;
  348. int mergeHandles(NSI_SERVER_BINDING_VECTOR_T* pHandles) {
  349. return pBVhandles->merge(pHandles);
  350. }
  351. public:
  352. // constructor for entries from the client
  353. // directly.
  354. CInterface(
  355. NSI_INTERFACE_ID_T * lpInf,
  356. NSI_SERVER_BINDING_VECTOR_T *BindingVector,
  357. CServerEntry *pMyEntry
  358. );
  359. // constructor for entries from the DS.
  360. CInterface(
  361. CServerEntry * pMyEntry,
  362. HANDLE hDSObject,
  363. ADS_SEARCH_HANDLE hSearchHandle,
  364. HRESULT * phr);
  365. RPC_SYNTAX_IDENTIFIER xferSyntaxIdAndVersion() {
  366. return transferSyntax.myIdAndVersion();
  367. }
  368. /* self is the same or a more recent MINOR version for both
  369. interface and transfer syntax IDs */
  370. int isCompatibleWith(
  371. CGUIDVersion * pInterfaceID,
  372. CGUIDVersion * pTransferID
  373. )
  374. {
  375. return (!pInterfaceID || this->isCompatibleGV(*pInterfaceID))
  376. && (!pTransferID || transferSyntax.isCompatibleGV(*pTransferID));
  377. }
  378. ~CInterface() {
  379. delete pBVhandles;
  380. }
  381. BOOL purgeCommonEntries(CInterface *src)
  382. {
  383. return pBVhandles->purgeCommonEntries(src->pBVhandles);
  384. }
  385. // adding this entry to the DS.
  386. HRESULT AddToDS();
  387. HRESULT DeleteFromDS();
  388. };
  389. /*++
  390. Class Definition:
  391. CEntryName
  392. Abstract:
  393. This class encapsulates knowledge about RPC name service entry names.
  394. Data Members:
  395. CStringW (base) -- the name string in its original form
  396. DomainName -- the name of the Domain, without any punctuation
  397. EntryName -- the name of the entry, without any /.: or /... prefix
  398. and also without a domain name at the beginning
  399. --*/
  400. class CEntryName : public CStringW {
  401. protected:
  402. CStringW *pswDomainName;
  403. CStringW *pswEntryName;
  404. CStringW *pswRpcContainerDN;
  405. CStringW *pswDomainNameDns;
  406. public:
  407. CEntryName(CONST_STRING_T fullName); // disassembling constructor
  408. CEntryName( // assembling constructor
  409. CONST_STRING_T domainName,
  410. CONST_STRING_T entryName
  411. );
  412. CEntryName::CEntryName( // assembling constructor for DS
  413. CONST_STRING_T RpcContainerDN,
  414. CONST_STRING_T domainNameDns, // if NULL, assume relative name
  415. DWORD type,
  416. CONST_STRING_T entryName
  417. );
  418. CEntryName()
  419. {
  420. pswDomainName = NULL;
  421. pswEntryName = NULL;
  422. pswRpcContainerDN = NULL;
  423. pswDomainNameDns = NULL;
  424. }
  425. CEntryName& operator=( const CEntryName& EntryName ) {
  426. *(CStringW *)(this) = *((CStringW *)&EntryName);
  427. delete pswDomainName;
  428. delete pswEntryName;
  429. delete pswRpcContainerDN;
  430. delete pswDomainNameDns;
  431. if (EntryName.pswDomainName)
  432. pswDomainName = new CStringW(*EntryName.pswDomainName);
  433. else
  434. pswDomainName = NULL;
  435. if (EntryName.pswEntryName)
  436. pswEntryName = new CStringW(*EntryName.pswEntryName);
  437. else
  438. pswEntryName = NULL;
  439. if (EntryName.pswRpcContainerDN)
  440. pswRpcContainerDN = new CStringW(*EntryName.pswRpcContainerDN);
  441. else
  442. pswRpcContainerDN = NULL;
  443. if (EntryName.pswDomainNameDns)
  444. pswDomainNameDns = new CStringW(*EntryName.pswDomainNameDns);
  445. else
  446. pswDomainNameDns = NULL;
  447. return *this;
  448. }
  449. virtual ~CEntryName(); // base class destructor should be virtual
  450. CStringW* getDomainName();
  451. CStringW* getDomainNameDns();
  452. CStringW* getEntryName()
  453. {
  454. return pswEntryName;
  455. }
  456. void changeToLocalName()
  457. {
  458. delete pswDomainName;
  459. pswDomainName = NULL;
  460. pswDomainNameDns = NULL;
  461. delete [] pszVal;
  462. pszVal = catenate(RelativePrefix,*pswEntryName);
  463. }
  464. STRING_T copyGlobalName();
  465. STRING_T copyCurrentName()
  466. {
  467. return copyString(getCurrentName());
  468. }
  469. STRING_T getFullDNAlloc();
  470. STRING_T getFullDNWithDomainAlloc();
  471. CStringW *getRpcContainer();
  472. STRING_T getCurrentName()
  473. /* this is mainly for use by CEntry objects. for CEntryName objects, automatic
  474. conversion through the inherited STRING_T operator is used instead */
  475. {
  476. return pszVal;
  477. }
  478. int isLocal();
  479. };
  480. typedef TIIterator<CEntryName> TEntryNameIterator;
  481. /*++
  482. Class Definition:
  483. CContextHandle
  484. Abstract:
  485. This is the base interface for all context handles. It is needed
  486. because, for RPC, there is a single NSI_NS_HANDLE_T context handle type,
  487. and there has to be a single entry point for the rundown process.
  488. A virtual destructor is needed for the same reason.
  489. Note that CContextHandle is not an abstract class.
  490. --*/
  491. class CContextHandle {
  492. public:
  493. ULONG ulCacheMax; // max age of a cached item that is acceptable
  494. // *at lookup time* (this is important)
  495. ULONG myLocatorCount; // Locator that I am corresp. to.
  496. ULONG ulCreationTime; // when I was created
  497. virtual void lookupIfNecessary() {} // redo the lookup which created this handle
  498. virtual void setExpiryAge(ULONG newMax) {
  499. ULONG ulOldMax = ulCacheMax;
  500. ulCacheMax = newMax;
  501. if (ulCacheMax < ulOldMax) lookupIfNecessary();
  502. }
  503. virtual void rundown() {}
  504. CContextHandle() {
  505. ulCreationTime = CurrentTime();
  506. myLocatorCount = LocatorCount; // global locator object that this corresponds
  507. // to.
  508. }
  509. virtual ~CContextHandle() {}
  510. };
  511. /*++
  512. Template Class Definition:
  513. CNSHandle
  514. Abstract:
  515. This template defines the basic nature of an NS handle.
  516. It is instantiated into abstract base classes such as
  517. CObjectInqHandle and CLookupHandle, and is also used in
  518. the definition of other templates such as CCompleteHandle
  519. which abstract general properties of classes of handles.
  520. --*/
  521. template <class ItemType>
  522. struct CNSHandle : public CContextHandle
  523. {
  524. public:
  525. ULONG StatusCode;
  526. virtual void lookupIfNecessary() = 0; // redo the lookup which created this handle
  527. virtual ItemType * next() = 0; // primary iterative operation
  528. virtual int finished() = 0; // test for end of iterator
  529. virtual void rundown() = 0; // inherited and still pure virtual
  530. CNSHandle() { StatusCode = NSI_S_OK; }
  531. virtual ULONG getStatus() { return StatusCode; }
  532. virtual ~CNSHandle() {}
  533. };
  534. /*++
  535. Class Definition:
  536. CObjectInqHandle
  537. Abstract:
  538. This is the class for object lookup handles.
  539. The primary operation on a handle is "next" which is inherited
  540. from the TIIterator template interface (instantiated as TGuidIterator
  541. which returns CGUID objects). However, it also needs an additional
  542. operation for the locator-to-locator case where an entire vector of
  543. object UUIDs is returned instead of just one UUID at a time.
  544. --*/
  545. typedef CNSHandle<GUID> CObjectInqHandle;
  546. /*++
  547. Class Definition:
  548. CRemoteObjectInqHandle
  549. Abstract:
  550. This is the common object inquiry handle class for remote entries. Handles based
  551. on nonlocal entries, master locators and broadcast are derived from it. Note that
  552. the connection between a remote handle and a specific entry is very tenuous.
  553. We don't even assume that the entry object(s) the handle was derived from will
  554. exist as long as the handle does. In case of a new lookup being forced (because
  555. handle is too stale -- this happens only with the RpcNsHandleSetExpAge API), we
  556. expect to start all over again from scratch.
  557. --*/
  558. class CRemoteObjectInqHandle : public CObjectInqHandle {
  559. protected:
  560. NSI_UUID_VECTOR_P_T pUuidVector;
  561. ULONG ulIndex;
  562. CEntryName * penEntryName;
  563. ULONG ulEntryNameSyntax;
  564. /* A flag to delay initialization until the first call on next */
  565. BOOL fNotInitialized;
  566. public:
  567. #if DBG
  568. static ULONG ulHandleCount;
  569. ULONG ulHandleNo;
  570. #endif
  571. CRemoteObjectInqHandle(
  572. STRING_T szName,
  573. ULONG ulCacheAge
  574. )
  575. {
  576. DBGOUT(MEM2, "CRemoteObjectInqHandle#" << (ulHandleNo = ++ulHandleCount)
  577. << " Created at" << CurrentTime() << "\n\n");
  578. penEntryName = szName ? new CEntryName(szName) : NULL;
  579. ulEntryNameSyntax = RPC_C_NS_SYNTAX_DCE;
  580. ulIndex = 0;
  581. fNotInitialized = TRUE;
  582. pUuidVector = NULL;
  583. ulCacheMax = ulCacheAge;
  584. }
  585. virtual ~CRemoteObjectInqHandle()
  586. {
  587. DBGOUT(MEM2, "CRemoteObjectInqHandle#" << (ulHandleCount--,ulHandleNo)
  588. << " Destroyed at" << CurrentTime() << "\n\n");
  589. rundown();
  590. delete penEntryName;
  591. penEntryName = NULL;
  592. }
  593. virtual void initialize() = 0;
  594. virtual void lookupIfNecessary()
  595. /*
  596. Note that this does not reinitialize the handle
  597. -- that is deferred until a "next" or "finished" call
  598. */
  599. {
  600. DBGOUT(MEM1,"lookupIfNecessary called for a remote handle\n\n");
  601. if (CurrentTime() - ulCreationTime > ulCacheMax) rundown();
  602. }
  603. /* The rundown method should be extended in a subclass if objects of the subclass
  604. hold additional resources connected with the current contents of the handle (as
  605. opposed to lookup parameters). For additional lookup parameters, a destructor
  606. should be provided instead. */
  607. void rundown()
  608. {
  609. if (pUuidVector)
  610. {
  611. for (; ulIndex < pUuidVector->count; ulIndex++)
  612. midl_user_free(pUuidVector->uuid[ulIndex]);
  613. midl_user_free(pUuidVector);
  614. pUuidVector = NULL;
  615. }
  616. fNotInitialized = TRUE;
  617. }
  618. virtual GUID* next() {
  619. if (fNotInitialized) initialize();
  620. if (finished()) return NULL;
  621. GUID* result = pUuidVector->uuid[ulIndex];
  622. pUuidVector->uuid[ulIndex] = NULL;
  623. ulIndex++;
  624. return result;
  625. }
  626. virtual BOOL finished() {
  627. if (fNotInitialized) initialize();
  628. return StatusCode || !pUuidVector || (ulIndex >= pUuidVector->count);
  629. }
  630. };
  631. /*++
  632. Class Definition:
  633. CNetObjectInqHandle
  634. Abstract:
  635. This is the common object inquiry handle class for network-based object inquiry.
  636. Since net object inquiry is now "lazy" (net is accessed only if needed), we need
  637. a lazy handle which initializes itself according to the old pattern of
  638. "use master if you can, broadcast if you must".
  639. --*/
  640. class CNetObjectInqHandle : public CRemoteObjectInqHandle {
  641. CRemoteObjectInqHandle *pRealHandle;
  642. virtual void initialize();
  643. public:
  644. ULONG getStatus() { return pRealHandle->StatusCode; }
  645. virtual void rundown()
  646. {
  647. if (pRealHandle)
  648. {
  649. pRealHandle->rundown();
  650. delete pRealHandle;
  651. pRealHandle = NULL;
  652. }
  653. fNotInitialized = TRUE;
  654. }
  655. CNetObjectInqHandle(
  656. STRING_T EntryName,
  657. unsigned long ulCacheAge
  658. ) :
  659. CRemoteObjectInqHandle(
  660. EntryName,
  661. ulCacheAge
  662. )
  663. {
  664. pRealHandle = NULL;
  665. fNotInitialized = TRUE;
  666. }
  667. ~CNetObjectInqHandle()
  668. {
  669. rundown();
  670. }
  671. GUID *next() {
  672. if (fNotInitialized) initialize();
  673. return pRealHandle->next();
  674. }
  675. int finished() {
  676. if (fNotInitialized) initialize();
  677. return pRealHandle->finished();
  678. }
  679. };
  680. /*++
  681. Class Definition:
  682. CLookupHandle
  683. Abstract:
  684. This is the base class for BV lookup handles. Actual handles
  685. belong to derived classes corresponding to entry types.
  686. The primary operation on a handle is "next" which is inherited
  687. from the TIIterator template interface (instantiated as TBVIterator).
  688. There is the possibility that a longlived client will fail to
  689. release a lookup handle, causing an effective leak of resources,
  690. but we won't deal with that in the current version.
  691. --*/
  692. typedef CNSHandle<NSI_BINDING_VECTOR_T> CLookupHandle;
  693. /*++
  694. Class Definition:
  695. CNullLookupHandle
  696. Abstract:
  697. This is used when a lookup handle is required but there is nothing
  698. to look up. Always returns NULL.
  699. --*/
  700. class CNullLookupHandle : public CLookupHandle
  701. {
  702. public:
  703. virtual void lookupIfNecessary() {}
  704. virtual NSI_BINDING_VECTOR_T * next() { return NULL; }
  705. virtual int finished() { return TRUE; }
  706. virtual void rundown() {}
  707. };
  708. /*++
  709. Class Definition:
  710. CMailSlotReplyHandle
  711. Abstract:
  712. This is the base class for handles which provide items for constructing
  713. mailslot reply buffers. Actual handles belong to derived classes
  714. corresponding to entry types.
  715. The primary operation on a handle is "next" which is inherited
  716. from the TIIterator template interface (instantiated as TMSRIIterator).
  717. --*/
  718. class CMailSlotReplyHandle : public TMSRIIterator {
  719. public:
  720. virtual ~CMailSlotReplyHandle() {}
  721. };
  722. /*++
  723. Class Definition:
  724. CEntry
  725. Abstract:
  726. The base Entry class for the internal cache. Even though this is an abstract
  727. class due to the unspecified loopup member, the class is not a pure
  728. interface (it has a constructor), hence the C rather than I prefix in the name.
  729. Note that CEntry has only constant data members.
  730. --*/
  731. class CEntry : public CEntryName {
  732. const EntryType type;
  733. public:
  734. const unsigned long ulEntryNameSyntax;
  735. CEntry(
  736. CONST_STRING_T pszStr,
  737. const EntryType& e,
  738. const unsigned long ulSyntax = RPC_C_NS_SYNTAX_DCE
  739. )
  740. : CEntryName( pszStr ),
  741. ulEntryNameSyntax(ulSyntax),
  742. type(e)
  743. {}
  744. CEntry(
  745. CONST_STRING_T pszRpcContainerDN,
  746. CONST_STRING_T pszDomainNameDns,
  747. DWORD Domaintype,
  748. CONST_STRING_T pszEntryName,
  749. const EntryType& e,
  750. const unsigned long ulSyntax = RPC_C_NS_SYNTAX_DCE
  751. )
  752. : CEntryName( pszRpcContainerDN, pszDomainNameDns, Domaintype, pszEntryName ),
  753. ulEntryNameSyntax(ulSyntax),
  754. type(e)
  755. {}
  756. virtual ~CEntry() {}
  757. EntryType getType() { return type; }
  758. BOOL isNonLocalType() {
  759. switch (type) {
  760. case NonLocalServerEntryType: return TRUE;
  761. default: return FALSE;
  762. }
  763. }
  764. virtual void flush() {} // useful for cache flushing, for instance
  765. virtual BOOL isCurrent(ULONG) { return TRUE; } // QUESTION: again cache oriented
  766. // need CNonLocalEntryMixin for these?
  767. virtual BOOL isEmpty() = 0;
  768. virtual CLookupHandle * lookup(
  769. CGUIDVersion * pGVInterface,
  770. CGUIDVersion * pGVTransferSyntax,
  771. CGUID * pIDobject,
  772. unsigned long ulVectorSize,
  773. unsigned long ulCacheAge
  774. ) = 0;
  775. virtual CObjectInqHandle * objectInquiry(
  776. unsigned long ulCacheAge
  777. ) = 0;
  778. virtual CMailSlotReplyHandle * MailSlotLookup(
  779. CGUIDVersion * pGVInterface,
  780. CGUID * pIDobject
  781. ) = 0;
  782. virtual HRESULT DeleteFromDS() {return S_OK;};
  783. // this method is added so that this can be called
  784. // for nsi_delete irresp. of the kind of entry. should
  785. // be redefined in all the entries that have to be deleted.
  786. };
  787. typedef TCGuardedSkipList<CFullServerEntry> TGSLEntryList;
  788. typedef TCGuardedSkipListIterator<CEntry> TGSLEntryListIterator;
  789. typedef TCSafeSkipList<CEntry> TSSLEntryList;
  790. typedef TCSafeSkipListIterator<CEntry> TSSLEntryListIterator;
  791. typedef TCSafeLinkList<CEntry> TSLLEntryList;
  792. typedef TCSafeLinkListIterator<CEntry> TSLLEntryListIterator;
  793. typedef TISkipList<CEntry> TEntrySkipList;
  794. typedef TIIterator<CEntry> TEntryIterator;
  795. /*++
  796. Class Definition:
  797. CRemoteLookupHandle
  798. Abstract:
  799. This is the common lookup handle class for remote entries. Handles based on
  800. NonLocal entries, master locators and broadcast are derived from it. Note that
  801. the connection between a remote handle and a specific entry is very tenuous.
  802. We don't even assume that the entry object(s) the handle was derived from will
  803. exist as long as the handle does. In case of a renewal lookup (lookupIfNecessary())
  804. being forced, we expect to start all over again from scratch.
  805. This handle, like all NS handles, relies on the fact that it is accessed
  806. as a client handle by the client side, and hence the RPC run-time
  807. automatically serializes its use.
  808. --*/
  809. class CRemoteLookupHandle : public CLookupHandle {
  810. protected:
  811. /* caching parameters */
  812. UNSIGNED32 u32EntryNameSyntax;
  813. CEntryName * penEntryName;
  814. CGUIDVersion * pgvInterface;
  815. CGUIDVersion * pgvTransferSyntax;
  816. CGUID * pidObject;
  817. ULONG ulVS;
  818. /* List of temporary entries created as a cache local to this
  819. handle by fetchNext. Must keep it for proper disposal
  820. after its use is finished. This is only used in net
  821. handles -- CMasterLookupHandle and CBroadcastLookupHandle
  822. */
  823. TSSLEntryList *psslNewCache;
  824. /* a lookup handle based on prefetched info */
  825. CLookupHandle *plhFetched;
  826. /* A flag to delay initialization until the first call on next */
  827. BOOL fNotInitialized;
  828. public:
  829. #if DBG
  830. static ULONG ulHandleCount;
  831. ULONG ulHandleNo;
  832. #endif
  833. CRemoteLookupHandle(
  834. UNSIGNED32 EntryNameSyntax,
  835. STRING_T EntryName,
  836. CGUIDVersion * pGVInterface,
  837. CGUIDVersion * pGVTransferSyntax,
  838. CGUID * pIDobject,
  839. unsigned long ulVectorSize,
  840. unsigned long ulCacheAge
  841. );
  842. virtual void initialize() = 0;
  843. /* The rundown method should be extended in a subclass if objects of the subclass
  844. hold additional resources connected with the current contents of the handle (as
  845. opposed to lookup parameters). See CMasterLookupHandle::rundown for an example.
  846. For additional lookup parameters, a destructor should be provided instead.
  847. */
  848. virtual void rundown()
  849. {
  850. if (plhFetched) {
  851. plhFetched->rundown();
  852. delete plhFetched;
  853. plhFetched = NULL;
  854. }
  855. if (psslNewCache) {
  856. psslNewCache->wipeOut();
  857. delete psslNewCache;
  858. psslNewCache = NULL;
  859. }
  860. fNotInitialized = TRUE;
  861. }
  862. virtual ~CRemoteLookupHandle() {
  863. DBGOUT(MEM2, "RemoteLookupHandle#" << (ulHandleCount--,ulHandleNo)
  864. << " Destroyed at" << CurrentTime() << "\n\n");
  865. rundown();
  866. delete pgvInterface;
  867. delete pgvTransferSyntax;
  868. delete pidObject;
  869. delete penEntryName;
  870. }
  871. virtual void setExpiryAge(ULONG newMax) {
  872. ULONG ulOldMax = ulCacheMax;
  873. DBGOUT(TRACE, "Setting the expiry age to " << newMax << "\n");
  874. DBGOUT(TRACE, "The old expiry age is " << ulOldMax << "\n");
  875. ulCacheMax = newMax;
  876. if (plhFetched) plhFetched->setExpiryAge(newMax);
  877. if (ulCacheMax < ulOldMax) lookupIfNecessary();
  878. }
  879. virtual void lookupIfNecessary() // standard behavior is:
  880. /*
  881. Note that this does not reinitialize the handle
  882. -- that is deferred until a "next" or "finished" call
  883. */
  884. {
  885. DBGOUT(TRACE, "Calling lookupifnecessary in remotelookupHandle\n");
  886. if (CurrentTime() - ulCreationTime > ulCacheMax) rundown();
  887. }
  888. virtual int finished() { // default behavior
  889. if (fNotInitialized) initialize();
  890. return !plhFetched || plhFetched->finished();
  891. }
  892. virtual NSI_BINDING_VECTOR_T *next() { // default behavior
  893. if (fNotInitialized) initialize();
  894. return plhFetched ? plhFetched->next() : NULL;
  895. }
  896. };
  897. /*++
  898. Class Definition:
  899. CNetLookupHandle
  900. Abstract:
  901. This is the common lookup handle class for network-based lookup.
  902. Since net lookup is now "lazy" (net is accessed only if needed), we need
  903. a lazy handle which initializes itself according to the old pattern of
  904. "use master if you can, broadcast if you must".
  905. --*/
  906. class CNetLookupHandle : public CRemoteLookupHandle {
  907. CRemoteLookupHandle *pRealHandle;
  908. virtual void initialize();
  909. #if DBG
  910. static ULONG ulNetLookupHandleCount;
  911. static ULONG ulNetLookupHandleNo;
  912. ULONG ulHandleNo;
  913. #endif
  914. public:
  915. ULONG getStatus() { return pRealHandle->StatusCode; }
  916. virtual void rundown()
  917. {
  918. DBGOUT(TRACE,"CNetLookupHandle::rundown called for Handle#" << ulHandleNo << "\n\n");
  919. if (pRealHandle)
  920. {
  921. pRealHandle->rundown();
  922. delete pRealHandle;
  923. pRealHandle = NULL;
  924. }
  925. fNotInitialized = TRUE;
  926. }
  927. CNetLookupHandle(
  928. UNSIGNED32 EntryNameSyntax,
  929. STRING_T EntryName,
  930. CGUIDVersion * pGVInterface,
  931. CGUIDVersion * pGVTransferSyntax,
  932. CGUID * pIDobject,
  933. unsigned long ulVectorSize,
  934. unsigned long ulCacheAge
  935. ) :
  936. CRemoteLookupHandle(
  937. EntryNameSyntax,
  938. EntryName,
  939. pGVInterface,
  940. pGVTransferSyntax,
  941. pIDobject,
  942. ulVectorSize,
  943. ulCacheAge
  944. )
  945. {
  946. pRealHandle = NULL;
  947. fNotInitialized = TRUE;
  948. #if DBG
  949. ulNetLookupHandleCount++;
  950. ulHandleNo = ++ulNetLookupHandleNo;
  951. #endif
  952. }
  953. ~CNetLookupHandle()
  954. {
  955. rundown();
  956. #if DBG
  957. ulNetLookupHandleCount--;
  958. #endif
  959. }
  960. NSI_BINDING_VECTOR_T *next() {
  961. DBGOUT(TRACE,"CNetLookupHandle::next called for Handle#" << ulHandleNo << "\n\n");
  962. if (fNotInitialized) initialize();
  963. return pRealHandle->next();
  964. }
  965. int finished() {
  966. DBGOUT(TRACE,"CNetLookupHandle::finished called for Handle#" << ulHandleNo << "\n\n");
  967. if (fNotInitialized) initialize();
  968. return pRealHandle->finished();
  969. }
  970. };
  971. /*++
  972. Class Definition:
  973. CDSLookupHandle
  974. Abstract:
  975. DS lookup handle. It is lazy and gets the data only when next is called.
  976. --*/
  977. class CDSLookupHandle : public CLookupHandle {
  978. BOOL fNotInitialized;
  979. UNSIGNED32 u32EntryNameSyntax;
  980. CEntryName * penEntryName;
  981. CGUIDVersion * pgvInterface;
  982. CGUIDVersion * pgvTransferSyntax;
  983. CGUID * pidObject;
  984. ULONG ulVS;
  985. void initialize();
  986. CLookupHandle *pRealHandle;
  987. CEntry *pEntry;
  988. #if DBG
  989. static ULONG ulDSLookupHandleCount;
  990. static ULONG ulDSLookupHandleNo;
  991. ULONG ulHandleNo;
  992. #endif
  993. public:
  994. virtual void rundown()
  995. {
  996. DBGOUT(TRACE,"CDSLookupHandle::rundown called for Handle#" << ulHandleNo << "\n\n");
  997. if (pRealHandle)
  998. {
  999. pRealHandle->rundown();
  1000. delete pRealHandle;
  1001. pRealHandle = NULL;
  1002. }
  1003. delete pEntry;
  1004. fNotInitialized = TRUE;
  1005. }
  1006. CDSLookupHandle(
  1007. UNSIGNED32 EntryNameSyntax,
  1008. STRING_T EntryName,
  1009. CGUIDVersion * pGVInterface,
  1010. CGUIDVersion * pGVTransferSyntax,
  1011. CGUID * pIDobject,
  1012. unsigned long ulVectorSize,
  1013. unsigned long ulCacheAge
  1014. )
  1015. {
  1016. DBGOUT(MEM2, "DSLookupHandle#" << (ulHandleNo = ++ulDSLookupHandleCount)
  1017. << " Created at" << CurrentTime() << "\n\n");
  1018. u32EntryNameSyntax = EntryNameSyntax;
  1019. penEntryName = EntryName ? new CEntryName(EntryName) : NULL;
  1020. pgvInterface = pGVInterface ? new CGUIDVersion(*pGVInterface) : NULL;
  1021. pgvTransferSyntax = pGVTransferSyntax ?
  1022. new CGUIDVersion(*pGVTransferSyntax) :
  1023. NULL;
  1024. pidObject = pIDobject ? new CGUID(*pIDobject) : NULL;
  1025. ulVS = ulVectorSize;
  1026. fNotInitialized = TRUE;
  1027. pEntry = NULL;
  1028. pRealHandle = NULL;
  1029. #if DBG
  1030. ulHandleNo = ++ulDSLookupHandleNo;
  1031. #endif
  1032. }
  1033. ~CDSLookupHandle()
  1034. {
  1035. rundown();
  1036. #if DBG
  1037. ulDSLookupHandleCount--;
  1038. #endif
  1039. }
  1040. void lookupIfNecessary() {};
  1041. NSI_BINDING_VECTOR_T *next() {
  1042. DBGOUT(TRACE,"CDSLookupHandle::next called for Handle#" << ulHandleNo << "\n\n");
  1043. if (fNotInitialized)
  1044. initialize();
  1045. if (pRealHandle)
  1046. return pRealHandle->next();
  1047. else
  1048. return NULL;
  1049. }
  1050. int finished() {
  1051. DBGOUT(TRACE,"CDSLookupHandle::finished called for Handle#" << ulHandleNo << "\n\n");
  1052. if (fNotInitialized) initialize();
  1053. return pRealHandle?pRealHandle->finished():TRUE;
  1054. }
  1055. int FoundInDS()
  1056. {
  1057. if (fNotInitialized) initialize();
  1058. return (pRealHandle?TRUE:FALSE);
  1059. }
  1060. };
  1061. /*++
  1062. Class Definition:
  1063. CServerObjectInqHandle
  1064. Abstract:
  1065. This is the object inquiry handle class for local (owned) server entries.
  1066. Since NS handles are used as context handles in RPC calls, the RPC runtime
  1067. guarantees serialization and we do not need to use critical sections explicitly.
  1068. --*/
  1069. class CServerObjectInqHandle : public CObjectInqHandle {
  1070. TGuidIterator *pcgIterSource;
  1071. public:
  1072. CServerObjectInqHandle(
  1073. TGuidIterator *pHandle,
  1074. ULONG cacheMax = 0
  1075. ) : pcgIterSource(pHandle)
  1076. {
  1077. ulCacheMax = cacheMax;
  1078. }
  1079. GUID *next();
  1080. virtual void lookupIfNecessary() {} // never redo lookup for local info
  1081. int finished() {
  1082. return pcgIterSource->finished();
  1083. }
  1084. virtual ~CServerObjectInqHandle() {
  1085. rundown();
  1086. }
  1087. virtual void rundown();
  1088. };
  1089. /*++
  1090. Class Definition:
  1091. CServerEntry
  1092. Abstract:
  1093. The specific Entry class for entries with binding and object attributes.
  1094. --*/
  1095. class CServerEntry : public CEntry {
  1096. protected:
  1097. TCSafeSkipList<CGUID> ObjectList; // object attribute
  1098. TCSafeSkipList<CInterface> InterfaceList; // binding attribute
  1099. TSLLString*
  1100. CServerEntry::formObjectStrings(
  1101. CGUID* pIDobject
  1102. );
  1103. public:
  1104. // constructors for different kind of lookups in DS.
  1105. CServerEntry(CONST_STRING_T pszStr, ADS_ATTR_INFO *pAttr, DWORD cAttr,
  1106. HANDLE hDSObject, HRESULT *phr);
  1107. CServerEntry(CONST_STRING_T pszRpcContainerDN, CONST_STRING_T pszDomainName, CONST_STRING_T pszEntryName,
  1108. HANDLE hDSObject, ADS_SEARCH_HANDLE hSearchHandle, HRESULT *phr);
  1109. CServerEntry(CONST_STRING_T pszStr)
  1110. : CEntry(pszStr, ServerEntryType)
  1111. {}
  1112. CServerEntry(CONST_STRING_T pszStr, const EntryType type)
  1113. : CEntry(pszStr, type)
  1114. {
  1115. }
  1116. virtual void flush(); // inherited from CEntry
  1117. virtual BOOL isEmpty() {
  1118. CriticalReader me(rwEntryGuard);
  1119. return (ObjectList.size() == 0) && (InterfaceList.size() == 0);
  1120. }
  1121. virtual ~CServerEntry() { // NonLocal version could be derived from it
  1122. flush();
  1123. }
  1124. virtual int addObjects(NSI_UUID_VECTOR_P_T ObjectVector);
  1125. virtual int removeObjects(
  1126. NSI_UUID_VECTOR_P_T ObjectVector,
  1127. int& fRemovedAll
  1128. );
  1129. virtual int addToInterface(
  1130. NSI_INTERFACE_ID_T *,
  1131. NSI_SERVER_BINDING_VECTOR_T *,
  1132. CInterfaceIndex *
  1133. );
  1134. virtual int addInterfaceToDS(
  1135. NSI_INTERFACE_ID_T *,
  1136. NSI_SERVER_BINDING_VECTOR_T *
  1137. );
  1138. virtual int removeInterfaces(
  1139. NSI_IF_ID_P_T Interface,
  1140. UNSIGNED32 VersOption,
  1141. CInterfaceIndex *
  1142. );
  1143. virtual int removeInterfacesFromDS(
  1144. NSI_IF_ID_P_T Interface,
  1145. UNSIGNED32 VersOption
  1146. );
  1147. int add_to_entry(
  1148. IN NSI_INTERFACE_ID_T * Interface,
  1149. IN NSI_SERVER_BINDING_VECTOR_T * BindingVector,
  1150. IN NSI_UUID_VECTOR_P_T ObjectVector,
  1151. CInterfaceIndex *,
  1152. BOOL fCache
  1153. );
  1154. int remove_from_entry(
  1155. IN NSI_IF_ID_P_T Interface,
  1156. IN UNSIGNED32 VersOption,
  1157. IN NSI_UUID_VECTOR_P_T ObjectVector,
  1158. CInterfaceIndex * IfIndex
  1159. );
  1160. int
  1161. add_changes_to_DS(
  1162. IN NSI_INTERFACE_ID_T * Interface,
  1163. IN NSI_SERVER_BINDING_VECTOR_T * BindingVector,
  1164. IN NSI_UUID_VECTOR_P_T ObjectVector,
  1165. BOOL fNewEntry,
  1166. BOOL fIgnoreErrors
  1167. );
  1168. int remove_changes_from_DS(
  1169. IN NSI_IF_ID_P_T Interface,
  1170. IN UNSIGNED32 VersOption,
  1171. IN NSI_UUID_VECTOR_P_T ObjectVector,
  1172. BOOL fIgnoreErrors
  1173. );
  1174. int memberObject(CGUID *obj) {
  1175. CriticalReader me(rwEntryGuard);
  1176. return ObjectList.find(obj) != NULL;
  1177. }
  1178. virtual CLookupHandle * lookup(
  1179. CGUIDVersion * pGVInterface,
  1180. CGUIDVersion * pGVTransferSyntax,
  1181. CGUID * pIDobject,
  1182. unsigned long ulVectorSize,
  1183. unsigned long ulCacheAge // ignored in this case
  1184. );
  1185. virtual CObjectInqHandle * objectInquiry(
  1186. unsigned long ulCacheAge
  1187. );
  1188. virtual CMailSlotReplyHandle * MailSlotLookup(
  1189. CGUIDVersion * pGVInterface,
  1190. CGUID * pIDobject
  1191. );
  1192. HRESULT AddToDS();
  1193. HRESULT DeleteFromDS();
  1194. BOOL purgeCommonEntries(CServerEntry *src)
  1195. {
  1196. int i, j, sz = ObjectList.size(), sz1;
  1197. CGUID *pguid1, *pguid2;
  1198. TSSLGuidIterator piter(ObjectList);
  1199. TCSafeSkipListIterator<CInterface> pint1Iterator(InterfaceList);
  1200. CInterface *pint1, *pint2;
  1201. for (i = 0; i < sz; i++)
  1202. {
  1203. pguid2 = piter.next();
  1204. pguid1 = (src->ObjectList).find(pguid2);
  1205. if (pguid1)
  1206. {
  1207. ObjectList.remove(pguid1);
  1208. }
  1209. }
  1210. sz = InterfaceList.size();
  1211. sz1 = (src->InterfaceList).size();
  1212. for (i = 0; i < sz; i++)
  1213. {
  1214. TCSafeSkipListIterator<CInterface> pint2Iterator(src->InterfaceList);
  1215. pint1 = pint1Iterator.next();
  1216. for (j = 0; j < sz1; j++)
  1217. {
  1218. pint2 = pint2Iterator.next();
  1219. if ((pint1) && (pint2))
  1220. if (pint1->purgeCommonEntries(pint2))
  1221. {
  1222. InterfaceList.remove(pint1);
  1223. delete pint1;
  1224. }
  1225. }
  1226. }
  1227. if (InterfaceList.size())
  1228. return FALSE;
  1229. else
  1230. return TRUE;
  1231. }
  1232. };
  1233. /*++
  1234. Class Definition:
  1235. CNonLocalServerEntry
  1236. Abstract:
  1237. A variation on CServerEntry with modifications to reflect the fact that the
  1238. info is NonLocal rather than owned by the locator, including a notion of being
  1239. current based on the earliest caching time of any info in the entry. Note that
  1240. info may be added incrementally at various times.
  1241. --*/
  1242. class CNonLocalServerEntry : public CServerEntry {
  1243. ULONG ulCacheTime;
  1244. public:
  1245. int fHasNonLocalInfo;
  1246. virtual BOOL isCurrent(ULONG ulTolerance);
  1247. CNonLocalServerEntry(
  1248. CONST_STRING_T pszStr
  1249. )
  1250. : CServerEntry(pszStr,NonLocalServerEntryType)
  1251. {
  1252. fHasNonLocalInfo = FALSE;
  1253. ulCacheTime = 0;
  1254. }
  1255. virtual void flush()
  1256. {
  1257. CServerEntry::flush();
  1258. CriticalWriter me(rwNonLocalEntryGuard);
  1259. DBGOUT(OBJECT, "\nFlushing CNonLocalServerEntry\n");
  1260. DBGOUT(OBJECT, "EntryName = " << getCurrentName() << WNL);
  1261. DBGOUT(OBJECT, "This entry has a ulCacheTime = " << ulCacheTime << "\n\n");
  1262. fHasNonLocalInfo = FALSE;
  1263. }
  1264. int addObjects(NSI_UUID_VECTOR_P_T ObjectVector) {
  1265. {
  1266. CriticalWriter me(rwNonLocalEntryGuard);
  1267. if (!fHasNonLocalInfo) {
  1268. ulCacheTime = CurrentTime();
  1269. fHasNonLocalInfo = TRUE;
  1270. }
  1271. else {
  1272. DBGOUT(OBJECT, "\nPerforming addObjects on a nonempty entry\n");
  1273. DBGOUT(OBJECT, "EntryName = " << getCurrentName() << WNL);
  1274. DBGOUT(OBJECT, "This entry has a ulCacheTime = " << ulCacheTime << WNL);
  1275. DBGOUT(OBJECT, "Current Time = " << CurrentTime() << "\n\n");
  1276. DBGOUT(OBJECT, "The Objects:\n" << ObjectVector);
  1277. }
  1278. }
  1279. return CServerEntry::addObjects(ObjectVector);
  1280. }
  1281. int addToInterface(
  1282. NSI_INTERFACE_ID_T * pInf,
  1283. NSI_SERVER_BINDING_VECTOR_T * pBVT,
  1284. CInterfaceIndex * pIndex
  1285. )
  1286. {
  1287. {
  1288. CriticalWriter me(rwNonLocalEntryGuard);
  1289. if (!fHasNonLocalInfo) {
  1290. ulCacheTime = CurrentTime();
  1291. fHasNonLocalInfo = TRUE;
  1292. }
  1293. else {
  1294. DBGOUT(OBJECT, "\nPerforming addToInterface on a nonempty entry\n");
  1295. DBGOUT(OBJECT, "EntryName = " << getCurrentName() << WNL);
  1296. DBGOUT(OBJECT, "This entry has a ulCacheTime = " << ulCacheTime << WNL);
  1297. DBGOUT(OBJECT, "Current Time = " << CurrentTime() << WNL << WNL);
  1298. DBGOUT(OBJECT, "The Bindings:\n" << pBVT);
  1299. }
  1300. }
  1301. return CServerEntry::addToInterface(pInf, pBVT, pIndex);
  1302. }
  1303. int removeObjects( // shouldn't happen to a NonLocal entry
  1304. NSI_UUID_VECTOR_P_T ObjectVector,
  1305. int& fRemovedAll
  1306. )
  1307. {
  1308. Raise(NSI_S_ENTRY_NOT_FOUND);
  1309. /* the following just keeps the compiler happy */
  1310. return FALSE;
  1311. }
  1312. virtual CObjectInqHandle * objectInquiry(
  1313. unsigned long ulCacheAge
  1314. );
  1315. int removeInterfaces( // shouldn't happen to a NonLocal entry
  1316. NSI_IF_ID_P_T Interface,
  1317. UNSIGNED32 VersOption,
  1318. CInterfaceIndex &
  1319. )
  1320. {
  1321. Raise(NSI_S_ENTRY_NOT_FOUND);
  1322. /* the following just keeps the compiler happy */
  1323. return FALSE;
  1324. }
  1325. virtual CLookupHandle * lookup(
  1326. CGUIDVersion * pGVInterface,
  1327. CGUIDVersion * pGVTransferSyntax,
  1328. CGUID * pIDobject,
  1329. unsigned long ulVectorSize,
  1330. unsigned long ulCacheAge
  1331. );
  1332. virtual CMailSlotReplyHandle * MailSlotLookup(
  1333. CGUIDVersion * pGVInterface,
  1334. CGUID * pIDobject
  1335. )
  1336. // NonLocal info is not returned in response to a broadcast, hence
  1337. {
  1338. return NULL;
  1339. }
  1340. };
  1341. /*++
  1342. Class Definition:
  1343. CFullServerEntry
  1344. Abstract:
  1345. This class is used to account for the fact that direct exports to
  1346. the same server entry may be made on two different machines.
  1347. As a result, the information in a server entry is partly nonlocal
  1348. remote handles and partly locally exported handles. Two kinds of
  1349. server entries within itself.
  1350. --*/
  1351. class CFullServerEntry : public CEntry {
  1352. BOOL fNetLookupDone;
  1353. void flushCacheIfNecessary(ULONG ulTolerance);
  1354. CServerEntry *pLocalEntry;
  1355. CNonLocalServerEntry *pNonLocalEntry;
  1356. public:
  1357. CServerEntry *getLocal() {
  1358. CriticalReader me(rwFullEntryGuard);
  1359. return pLocalEntry;
  1360. }
  1361. CNonLocalServerEntry *getNonLocal() {
  1362. CriticalReader me(rwFullEntryGuard);
  1363. return pNonLocalEntry;
  1364. }
  1365. CFullServerEntry(
  1366. CONST_STRING_T pszName
  1367. )
  1368. :CEntry(
  1369. pszName,
  1370. FullServerEntryType
  1371. )
  1372. {
  1373. pLocalEntry = new CServerEntry(pszName);
  1374. pNonLocalEntry = new CNonLocalServerEntry(pszName);
  1375. fNetLookupDone = FALSE;
  1376. }
  1377. virtual ~CFullServerEntry() {
  1378. delete pLocalEntry;
  1379. delete pNonLocalEntry;
  1380. }
  1381. virtual BOOL isEmpty() {
  1382. CriticalReader me(rwFullEntryGuard);
  1383. return pLocalEntry->isEmpty() && pNonLocalEntry->isEmpty();
  1384. }
  1385. virtual CLookupHandle * lookup(
  1386. CGUIDVersion * pGVInterface,
  1387. CGUIDVersion * pGVTransferSyntax,
  1388. CGUID * pIDobject,
  1389. unsigned long ulVectorSize,
  1390. unsigned long ulCacheAge
  1391. );
  1392. virtual CObjectInqHandle * objectInquiry(
  1393. unsigned long ulCacheAge
  1394. );
  1395. virtual CMailSlotReplyHandle * MailSlotLookup(
  1396. CGUIDVersion * pGVInterface,
  1397. CGUID * pIDobject
  1398. );
  1399. };
  1400. /*++
  1401. Class Definition:
  1402. CNonLocalServerObjectInqHandle
  1403. Abstract:
  1404. This is the object inquiry handle class for NonLocal server entries.
  1405. The only difference from a local CServerObjectInqHandle is
  1406. the functionality added by CRemoteObjectInqHandle.
  1407. --*/
  1408. class CNonLocalServerObjectInqHandle : public CRemoteObjectInqHandle {
  1409. void initialize();
  1410. public:
  1411. CNonLocalServerObjectInqHandle(
  1412. STRING_T pszName,
  1413. ULONG ulCacheAge
  1414. );
  1415. };
  1416. class CGroupInqHandle;
  1417. /*++
  1418. Class Definition:
  1419. CGroupEntry
  1420. Abstract:
  1421. --*/
  1422. class CGroupEntry : public CEntry {
  1423. protected:
  1424. TCSafeSkipList<CEntryName> GroupList;
  1425. public:
  1426. CGroupEntry(const STRING_T pszStr, ADS_ATTR_INFO *pAttr,
  1427. DWORD cAttr, HANDLE hDSObject,
  1428. HRESULT *phr);
  1429. CGroupEntry(const STRING_T pszStr)
  1430. : CEntry(pszStr, GroupEntryType)
  1431. {}
  1432. CGroupInqHandle * GroupMbrInquiry();
  1433. void AddMember(
  1434. STRING_T pEntryName
  1435. )
  1436. {
  1437. HRESULT hr = S_OK;
  1438. // First parse the name anyway
  1439. CEntryName *pName = new CEntryName(pEntryName);
  1440. // Now see if we have it already
  1441. if (GroupList.insert(pName) == Duplicate)
  1442. {
  1443. delete pName;
  1444. }
  1445. else
  1446. {
  1447. hr = AddToDS();
  1448. if (FAILED(hr)) {
  1449. DWORD dwErr = RemapErrorCode(hr);
  1450. if (dwErr == NSI_S_INTERNAL_ERROR)
  1451. Raise(NSI_S_GRP_ELT_NOT_ADDED);
  1452. else
  1453. Raise(dwErr);
  1454. }
  1455. }
  1456. }
  1457. void RemoveMember(
  1458. STRING_T pEntryName
  1459. )
  1460. {
  1461. HRESULT hr = S_OK;
  1462. if (GroupList.remove(&CEntryName(pEntryName)))
  1463. hr = AddToDS();
  1464. if (FAILED(hr)) {
  1465. DWORD dwErr = RemapErrorCode(hr);
  1466. if (dwErr == NSI_S_INTERNAL_ERROR)
  1467. Raise(NSI_S_GRP_ELT_NOT_REMOVED);
  1468. else
  1469. Raise(dwErr);
  1470. }
  1471. }
  1472. virtual BOOL isEmpty() { return GroupList.size() == 0; }
  1473. virtual CLookupHandle * lookup(
  1474. CGUIDVersion * pGVInterface,
  1475. CGUIDVersion * pGVTransferSyntax,
  1476. CGUID * pIDobject,
  1477. unsigned long ulVectorSize,
  1478. unsigned long ulCacheAge
  1479. );
  1480. virtual CObjectInqHandle * objectInquiry(
  1481. unsigned long ulCacheAge
  1482. )
  1483. {
  1484. // We don't support object attributes in group entries
  1485. return NULL;
  1486. }
  1487. virtual CMailSlotReplyHandle * MailSlotLookup(
  1488. CGUIDVersion * pGVInterface,
  1489. CGUID * pIDobject
  1490. )
  1491. {
  1492. // Group entries don't participate in legacy mechanisms
  1493. return NULL;
  1494. }
  1495. HRESULT AddToDS();
  1496. HRESULT DeleteFromDS();
  1497. };
  1498. /*++
  1499. Class Definition:
  1500. CGroupInqHandle
  1501. Abstract:
  1502. This is the handle class for enumerating group entries via the
  1503. RpcNsGroupMbrInq set of APIs.
  1504. --*/
  1505. class CGroupInqHandle : public CNSHandle<WCHAR>
  1506. {
  1507. TEntryNameIterator *pNameIter;
  1508. CGroupEntry *pmyGroup;
  1509. public:
  1510. // redo the lookup which created this handle
  1511. virtual void lookupIfNecessary() {}
  1512. virtual STRING_T next()
  1513. {
  1514. CEntryName* pName = pNameIter->next();
  1515. STRING_T result = NULL;
  1516. if (pName)
  1517. {
  1518. result = pName->copyAsMIDLstring();
  1519. }
  1520. return result;
  1521. }
  1522. virtual int finished()
  1523. {
  1524. return pNameIter->finished();
  1525. }
  1526. virtual void rundown()
  1527. {
  1528. delete pNameIter;
  1529. pNameIter = NULL;
  1530. delete pmyGroup;
  1531. pmyGroup = NULL;
  1532. }
  1533. CGroupInqHandle(TEntryNameIterator *pIter, CGroupEntry *pGroup)
  1534. : pNameIter(pIter),
  1535. pmyGroup(pGroup)
  1536. {}
  1537. virtual ~CGroupInqHandle()
  1538. {
  1539. rundown();
  1540. }
  1541. };
  1542. /*++
  1543. Class Definition:
  1544. CProfileKey
  1545. Abstract:
  1546. Inherits from CGUIDVersion which represents
  1547. the interface ID for the element, and CEntryName.
  1548. Name comparison takes priority over interface comparison.
  1549. --*/
  1550. struct CProfileKey : public IOrderedItem
  1551. {
  1552. CGUIDVersion Interface;
  1553. CEntryName EntryName;
  1554. CProfileKey(
  1555. RPC_SYNTAX_IDENTIFIER * pInterface,
  1556. STRING_T pEntryName
  1557. )
  1558. :
  1559. EntryName(pEntryName)
  1560. {
  1561. if (pInterface != NULL)
  1562. {
  1563. // call the copy constructor
  1564. Interface = CGUIDVersion(*pInterface);
  1565. }
  1566. else
  1567. {
  1568. RPC_SYNTAX_IDENTIFIER * pnewInterface = new RPC_SYNTAX_IDENTIFIER;
  1569. memset(pnewInterface, 0, sizeof(RPC_SYNTAX_IDENTIFIER));
  1570. Interface = CGUIDVersion(*pnewInterface);
  1571. delete pnewInterface;
  1572. // create an interface with all zeroes.
  1573. }
  1574. }
  1575. CProfileKey()
  1576. {};
  1577. virtual int compare(const IOrderedItem& other)
  1578. {
  1579. CProfileKey& otherKey = (CProfileKey&) other;
  1580. BOOL nameComp = EntryName.compare(otherKey.EntryName);
  1581. BOOL interfaceComp = Interface.compare(otherKey.Interface);
  1582. return nameComp == 0 ? interfaceComp : nameComp;
  1583. }
  1584. BOOL matches(
  1585. CEntryName *pEntryName,
  1586. CGUIDVersion* pInterface,
  1587. UNSIGNED32 vers_option
  1588. )
  1589. {
  1590. BOOL fNameMatches = pEntryName ? EntryName == *pEntryName : TRUE;
  1591. BOOL fInterfaceMatches = pInterface
  1592. ? Interface.isMatching(*pInterface,vers_option)
  1593. : TRUE;
  1594. return fNameMatches && fInterfaceMatches;
  1595. }
  1596. };
  1597. class CProfileEntry;
  1598. /*++
  1599. Class Definition:
  1600. CProfileElement
  1601. Abstract:
  1602. Inherits from CGUIDVersion which represents
  1603. the interface ID for the element
  1604. --*/
  1605. struct CProfileElement : public CProfileKey {
  1606. CProfileElement(
  1607. RPC_SYNTAX_IDENTIFIER * pInterface,
  1608. STRING_T pEntryName,
  1609. DWORD dwPriority,
  1610. STRING_T pszAnnotation,
  1611. CProfileEntry * pMyEntry
  1612. )
  1613. : CProfileKey(pInterface,pEntryName),
  1614. dwPriority(dwPriority),
  1615. pszAnnotation(pszAnnotation),
  1616. m_pMyEntry(pMyEntry)
  1617. {
  1618. }
  1619. // constructor for the DS lookup
  1620. CProfileElement(
  1621. CProfileEntry * pMyEntry,
  1622. HANDLE hDSObject,
  1623. ADS_SEARCH_HANDLE hSearchHandle,
  1624. HRESULT * phr
  1625. );
  1626. ~CProfileElement()
  1627. {
  1628. }
  1629. DWORD dwPriority;
  1630. BOOL fIsDefault;
  1631. CStringW pszAnnotation;
  1632. CProfileEntry * m_pMyEntry;
  1633. HRESULT AddToDS();
  1634. HRESULT DeleteFromDS();
  1635. };
  1636. /*++
  1637. Class Definition:
  1638. CProfileSet
  1639. Abstract:
  1640. A set of profile elements of the same priority.
  1641. --*/
  1642. class CProfileSet : public CUnsigned32, // the priority
  1643. public TCSafeLinkList<CProfileElement>
  1644. {
  1645. public:
  1646. CProfileSet(CProfileElement *pElt) : CUnsigned32(pElt->dwPriority)
  1647. {
  1648. insert(pElt);
  1649. }
  1650. };
  1651. class CProfileInqHandle;
  1652. /*++
  1653. Class Definition:
  1654. CProfileEntry
  1655. Abstract:
  1656. --*/
  1657. class CProfileEntry : public CEntry {
  1658. protected:
  1659. CProfileElement * pDefaultElt;
  1660. TCSafeSkipList<CProfileSet> ProfileList; // A skiplist of profile element lists
  1661. // ordered by priority
  1662. TCSafeSkipList<CProfileElement> EltList; // A skiplist of individual elements
  1663. // ordered by entry name
  1664. public:
  1665. CProfileEntry(const STRING_T pszStr, ADS_ATTR_INFO *pAttr,
  1666. DWORD cAttr, HANDLE hDSObject, HRESULT *phr);
  1667. CProfileEntry(const STRING_T pszStr)
  1668. : CEntry(pszStr, ProfileEntryType),
  1669. pDefaultElt(NULL)
  1670. {
  1671. }
  1672. ~CProfileEntry()
  1673. {
  1674. }
  1675. CProfileInqHandle * ProfileEltInquiry(
  1676. DWORD inquiry_type,
  1677. NSI_IF_ID_P_T if_id,
  1678. DWORD vers_option,
  1679. STRING_T member_name
  1680. );
  1681. void AddElement(
  1682. RPC_SYNTAX_IDENTIFIER * pInterface,
  1683. STRING_T pEntryName,
  1684. DWORD dwPriority,
  1685. STRING_T pszAnnotation
  1686. );
  1687. void RemoveElement(
  1688. RPC_SYNTAX_IDENTIFIER * pInterface,
  1689. STRING_T pEntryName
  1690. )
  1691. {
  1692. HRESULT hr = S_OK;
  1693. if (pInterface == NULL)
  1694. {
  1695. if (pDefaultElt)
  1696. {
  1697. hr = pDefaultElt->DeleteFromDS();
  1698. if (FAILED(hr)) {
  1699. DWORD dwErr = RemapErrorCode(hr);
  1700. if (dwErr == NSI_S_INTERNAL_ERROR)
  1701. Raise(NSI_S_PRF_ELT_NOT_REMOVED);
  1702. else
  1703. Raise(dwErr);
  1704. }
  1705. delete pDefaultElt;
  1706. pDefaultElt = NULL;
  1707. return;
  1708. }
  1709. else
  1710. return;
  1711. }
  1712. CProfileElement *pElt = EltList.remove(&CProfileKey(pInterface,pEntryName));
  1713. if (pElt != 0)
  1714. {
  1715. hr = pElt->DeleteFromDS();
  1716. if (FAILED(hr)) {
  1717. DWORD dwErr = RemapErrorCode(hr);
  1718. if (dwErr == NSI_S_INTERNAL_ERROR)
  1719. Raise(NSI_S_PRF_ELT_NOT_REMOVED);
  1720. else
  1721. Raise(dwErr);
  1722. }
  1723. // we actually have it, so remove it from the profile lists
  1724. CProfileSet *pSet = ProfileList.find(&CUnsigned32(pElt->dwPriority));
  1725. ASSERT(pSet, "Inconsistent Profile Entry\n");
  1726. BOOL fRemoved = pSet->remove(pElt);
  1727. ASSERT(fRemoved, "Inconsistent Profile Entry\n");
  1728. if (pSet->size() == 0)
  1729. {
  1730. ProfileList.remove(pSet);
  1731. }
  1732. }
  1733. }
  1734. virtual BOOL isEmpty()
  1735. {
  1736. return EltList.size() == 0 && pDefaultElt == NULL;
  1737. }
  1738. virtual CLookupHandle * lookup(
  1739. CGUIDVersion * pGVInterface,
  1740. CGUIDVersion * pGVTransferSyntax,
  1741. CGUID * pIDobject,
  1742. unsigned long ulVectorSize,
  1743. unsigned long ulCacheAge
  1744. );
  1745. virtual CObjectInqHandle * objectInquiry(
  1746. unsigned long ulCacheAge
  1747. )
  1748. {
  1749. // We don't support object attributes in profile entries
  1750. return NULL;
  1751. }
  1752. virtual CMailSlotReplyHandle * MailSlotLookup(
  1753. CGUIDVersion * pGVInterface,
  1754. CGUID * pIDobject
  1755. )
  1756. {
  1757. // Profile entries don't participate in legacy mechanisms
  1758. return NULL;
  1759. }
  1760. HRESULT AddToDS();
  1761. HRESULT DeleteFromDS();
  1762. };
  1763. /*++
  1764. Class Definition:
  1765. CProfileInqHandle
  1766. Abstract:
  1767. This is the handle class for enumerating profile entries via the
  1768. RpcNsProfileEltInq set of APIs.
  1769. --*/
  1770. class CProfileInqHandle : public CNSHandle<CProfileElement>
  1771. {
  1772. TIIterator<CProfileElement> *pEltIter;
  1773. CProfileEntry *pmyProfile;
  1774. public:
  1775. // redo the lookup which created this handle
  1776. virtual void lookupIfNecessary() {}
  1777. virtual CProfileElement * next()
  1778. {
  1779. return pEltIter->next();
  1780. }
  1781. virtual int finished()
  1782. {
  1783. return pEltIter->finished();
  1784. }
  1785. virtual void rundown()
  1786. {
  1787. delete pEltIter;
  1788. pEltIter = NULL;
  1789. delete pmyProfile;
  1790. pmyProfile = NULL;
  1791. }
  1792. CProfileInqHandle(TIIterator<CProfileElement> *pIter, CProfileEntry *pProfile)
  1793. : pEltIter(pIter),
  1794. pmyProfile(pProfile)
  1795. {}
  1796. virtual ~CProfileInqHandle()
  1797. {
  1798. rundown();
  1799. }
  1800. };
  1801. // entry type and the name is used for comparison.
  1802. // this kind of entry is used in maintaining the
  1803. // visited list in the group lookup handle.
  1804. class CVisitedEntry : public IOrderedItem {
  1805. protected:
  1806. CStringW * m_pname;
  1807. EntryType m_type;
  1808. public:
  1809. CVisitedEntry(CStringW name, EntryType type) {
  1810. m_pname = new CStringW(name);
  1811. m_type = type;
  1812. }
  1813. ~CVisitedEntry() {
  1814. delete m_pname;
  1815. }
  1816. virtual int compare( const IOrderedItem& O )
  1817. {
  1818. const CVisitedEntry& arg = (CVisitedEntry&) O;
  1819. int namecompare = m_pname->compare(*(arg.m_pname));
  1820. int ret;
  1821. if (namecompare == 0)
  1822. ret = ((arg.m_type < m_type)? 1 :
  1823. ((arg.m_type == m_type)? 0 : -1));
  1824. else
  1825. ret = namecompare;
  1826. DBGOUT(TRACE, "!! Types are " << arg.m_type << m_type << "\n");
  1827. DBGOUT(TRACE, "!! Comparison returns" << ret << "\n");
  1828. return ret;
  1829. }
  1830. };
  1831. typedef TCSafeSkipList<CVisitedEntry> TSSLVisitedList;
  1832. /*++
  1833. Class Definition:
  1834. CMemberEntry
  1835. Abstract:
  1836. The Entry class for group and profile lookup. Since we only have names
  1837. in group and profile entries, when a lookup handle is constructed, we don't
  1838. have any guarantee that there are real entries corresponding to those names.
  1839. We therefore have this shell class that materializes the real entry when a
  1840. lookup is performed on it. This also serves as the logical point for
  1841. circularity detection and avoidance in group/profile lookup.
  1842. --*/
  1843. class CMemberEntry : public CEntry {
  1844. CEntry *pRealEntry;
  1845. TSSLVisitedList *pVisitedEntries;
  1846. void materialize(); // get the real entry now
  1847. public:
  1848. CMemberEntry(const STRING_T pszStr)
  1849. : CEntry(pszStr, MemberEntryType)
  1850. {}
  1851. ~CMemberEntry()
  1852. {
  1853. if (pRealEntry)
  1854. delete pRealEntry;
  1855. }
  1856. void setVisitedEntries(TSSLVisitedList *pVisited)
  1857. {
  1858. pVisitedEntries = pVisited;
  1859. }
  1860. virtual BOOL isEmpty()
  1861. {
  1862. materialize();
  1863. return pRealEntry ? pRealEntry->isEmpty() : TRUE;
  1864. }
  1865. virtual CLookupHandle * lookup(
  1866. CGUIDVersion * pGVInterface,
  1867. CGUIDVersion * pGVTransferSyntax,
  1868. CGUID * pIDobject,
  1869. unsigned long ulVectorSize,
  1870. unsigned long ulCacheAge
  1871. );
  1872. virtual CObjectInqHandle * objectInquiry(
  1873. unsigned long ulCacheAge
  1874. )
  1875. {
  1876. materialize();
  1877. return pRealEntry
  1878. ? pRealEntry->objectInquiry(
  1879. ulCacheAge
  1880. )
  1881. : NULL;
  1882. }
  1883. virtual CMailSlotReplyHandle * MailSlotLookup(
  1884. CGUIDVersion * pGVInterface,
  1885. CGUID * pIDobject
  1886. )
  1887. {
  1888. // this functionality is not available for hypothetical entries
  1889. return NULL;
  1890. }
  1891. };
  1892. /*++
  1893. Class Definition:
  1894. CServerLookupHandle
  1895. Abstract:
  1896. This is the binding lookup handle class for local (owned) server entries.
  1897. Since NS handles are used as context handles in RPC calls, the RPC runtime
  1898. guarantees serialization and we do not need to use critical sections explicitly.
  1899. --*/
  1900. class CServerLookupHandle : public CLookupHandle {
  1901. unsigned long ulVectorSize;
  1902. TBVIterator *pBVIterator;
  1903. public:
  1904. CServerLookupHandle(
  1905. TBVSafeLinkList * pBVLL
  1906. );
  1907. virtual ~CServerLookupHandle() {
  1908. rundown();
  1909. }
  1910. virtual void lookupIfNecessary() {} // never redo lookup for local info
  1911. NSI_BINDING_VECTOR_T *next()
  1912. {
  1913. if (pBVIterator->finished())
  1914. return NULL;
  1915. CBVWrapper *pBVW = pBVIterator->next();
  1916. NSI_BINDING_VECTOR_T *pResult = pBVW->pBVT; // unwrap
  1917. delete pBVW; // throw away wrapper
  1918. return pResult;
  1919. }
  1920. int finished() {
  1921. return pBVIterator->finished();
  1922. }
  1923. virtual void rundown();
  1924. };
  1925. /*++
  1926. Class Definition:
  1927. CNonLocalServerLookupHandle
  1928. Abstract:
  1929. This is the lookup handle class for NonLocal server entries.
  1930. The only difference from a local CServerLookupHandle is
  1931. the functionality added by CRemoteLookupHandle.
  1932. --*/
  1933. class CNonLocalServerLookupHandle : public CRemoteLookupHandle {
  1934. void initialize();
  1935. public:
  1936. CNonLocalServerLookupHandle(
  1937. STRING_T pszName,
  1938. CGUIDVersion *pGVInterface,
  1939. CGUIDVersion *pGVTransferSyntax,
  1940. CGUID *pIDobject,
  1941. ULONG ulVectorSize,
  1942. ULONG ulCacheAge
  1943. );
  1944. };
  1945. /*++
  1946. Class Definition:
  1947. CGroupLookupHandle
  1948. Abstract:
  1949. This is the lookup handle class for group entries and other groups.
  1950. Its primary use currently is to produce handles for null-entry
  1951. lookups where information from multiple entries needs to be collected.
  1952. --*/
  1953. class CGroupLookupHandle : public CLookupHandle {
  1954. protected:
  1955. /* search parameters */
  1956. CGUIDVersion * pGVInterface;
  1957. CGUIDVersion * pGVTransferSyntax;
  1958. CGUID * pIDobject;
  1959. unsigned long ulVectorSize;
  1960. BOOL fUnusedHandle;
  1961. BOOL fRootHandle;
  1962. /* Iterator for entries in the group -- please use a guarded kind! */
  1963. TEntryIterator *pEIterator;
  1964. /* handle for the currently active entry */
  1965. CLookupHandle * pCurrentHandle;
  1966. /* SkipList of all entries visited so far -- circularity avoidance */
  1967. TSSLVisitedList *pVisitedEntries;
  1968. void advanceCurrentHandle(); // look for next nonempty entry handle
  1969. public:
  1970. CGroupLookupHandle(
  1971. TEntryIterator * pEI,
  1972. CGUIDVersion * pGVInterface,
  1973. CGUIDVersion * pGVTransferSyntax,
  1974. CGUID * pIDobject,
  1975. unsigned long ulVectorSize,
  1976. unsigned long ulCacheAge
  1977. );
  1978. virtual ~CGroupLookupHandle() {
  1979. rundown();
  1980. delete pEIterator;
  1981. delete pGVInterface;
  1982. delete pGVTransferSyntax;
  1983. delete pIDobject;
  1984. if (fRootHandle)
  1985. {
  1986. pVisitedEntries->wipeOut();
  1987. delete pVisitedEntries;
  1988. }
  1989. }
  1990. virtual void lookupIfNecessary() {}
  1991. NSI_BINDING_VECTOR_T *next(
  1992. );
  1993. int finished();
  1994. virtual void rundown()
  1995. {
  1996. if (pCurrentHandle)
  1997. {
  1998. pCurrentHandle->rundown();
  1999. delete pCurrentHandle;
  2000. pCurrentHandle = NULL;
  2001. }
  2002. }
  2003. void setVisitedEntries(TSSLVisitedList *pVisited)
  2004. {
  2005. // this overrides the setting of this variable
  2006. // in the constructor
  2007. delete pVisitedEntries;
  2008. DBGOUT(TRACE, "Setting Visited Entries\n");
  2009. pVisitedEntries = pVisited;
  2010. // this also implies that this is a group handle in a larger
  2011. // group/profile lookup, hence does not own the visited
  2012. // entries list, which will therefore not be deleted in the dtor
  2013. fRootHandle = FALSE;
  2014. }
  2015. };
  2016. /*++
  2017. Class Definition:
  2018. CIndexLookupHandle
  2019. Abstract:
  2020. This is a specialization of the group handle class for Index lookup.
  2021. The only difference is an implementation of lookupIfNecessary().
  2022. --*/
  2023. class CIndexLookupHandle : public CGroupLookupHandle {
  2024. public:
  2025. CIndexLookupHandle(
  2026. CGUIDVersion * pGVInterface,
  2027. CGUIDVersion * pGVTransferSyntax,
  2028. CGUID * pIDobject,
  2029. unsigned long ulVectorSize,
  2030. unsigned long ulCacheAge
  2031. );
  2032. virtual void lookupIfNecessary();
  2033. };
  2034. /*++
  2035. Template Class Definition:
  2036. CCompleteHandle
  2037. Abstract:
  2038. The complete handle template implements the idea that a top level NS handle
  2039. typically is heterogeneous -- it contains info that is a) owned b) NonLocal
  2040. and c) just captured from the net. The behavior of such a handle is
  2041. independent of the nature of the data being looked up, hence the template.
  2042. --*/
  2043. template <class ItemType>
  2044. class CCompleteHandle : public CNSHandle<ItemType> {
  2045. /* these three handles are owned by this object and therefore
  2046. destroyed when it is deleted */
  2047. CNSHandle<ItemType> * pLocalHandle;
  2048. CNSHandle<ItemType> * pNonLocalHandle;
  2049. CNSHandle<ItemType> * pNetHandle;
  2050. BOOL fCacheIsValid;
  2051. public:
  2052. #if DBG
  2053. static ULONG ulHandleCount;
  2054. static ULONG ulHandleNo;
  2055. ULONG ulMyHandleNo;
  2056. #endif
  2057. ULONG netStatus() { return pNetHandle->getStatus(); }
  2058. CCompleteHandle(
  2059. CNSHandle<ItemType> * pLocal,
  2060. CNSHandle<ItemType> * pNonLocal,
  2061. CNSHandle<ItemType> * pNet,
  2062. ULONG ulCacheAge
  2063. )
  2064. {
  2065. #if DBG
  2066. ulHandleCount++;
  2067. ulHandleNo++;
  2068. ulMyHandleNo = ulHandleNo;
  2069. #endif
  2070. DBGOUT(MEM1, "CompleteHandle#" << ulMyHandleNo << " Created at"
  2071. << CurrentTime() << "\n\n");
  2072. fCacheIsValid = FALSE;
  2073. pLocalHandle = pLocal;
  2074. pNonLocalHandle = pNonLocal;
  2075. pNetHandle = pNet;
  2076. setExpiryAge(ulCacheAge);
  2077. // By checking if there is any info at all, we force
  2078. // initialization of remote handles if necessary
  2079. finished();
  2080. }
  2081. ~CCompleteHandle() {
  2082. DBGOUT(MEM1, "CompleteHandle#" << (ulHandleCount--,ulMyHandleNo) << " Destroyed at"
  2083. << CurrentTime() << "\n\n");
  2084. rundown();
  2085. }
  2086. /* setExpiryAge on component handles should accomplish the needful */
  2087. virtual void lookupIfNecessary() {}
  2088. virtual void rundown();
  2089. virtual void setExpiryAge(
  2090. ULONG ulCacheAge
  2091. )
  2092. {
  2093. ulCacheMax = ulCacheAge;
  2094. if (pLocalHandle) pLocalHandle->setExpiryAge(ulCacheAge);
  2095. if (pNonLocalHandle) pNonLocalHandle->setExpiryAge(ulCacheAge);
  2096. if (pNetHandle) pNetHandle->setExpiryAge(ulCacheAge);
  2097. }
  2098. ItemType *next();
  2099. int finished();
  2100. };
  2101. #if DBG
  2102. template <class ItemType>
  2103. ULONG
  2104. CCompleteHandle<ItemType>::ulHandleCount = 0;
  2105. template <class ItemType>
  2106. ULONG
  2107. CCompleteHandle<ItemType>::ulHandleNo = 0;
  2108. #endif
  2109. template <class ItemType>
  2110. void
  2111. CCompleteHandle<ItemType>::rundown()
  2112. {
  2113. if (pLocalHandle) pLocalHandle->rundown();
  2114. if (pNonLocalHandle) pNonLocalHandle->rundown();
  2115. if (pNetHandle) pNetHandle->rundown();
  2116. if (pLocalHandle) delete pLocalHandle;
  2117. if (pNonLocalHandle) delete pNonLocalHandle;
  2118. if (pNetHandle) delete pNetHandle;
  2119. pLocalHandle = NULL;
  2120. pNonLocalHandle = NULL;
  2121. pNetHandle = NULL;
  2122. }
  2123. template <class ItemType>
  2124. ItemType *
  2125. CCompleteHandle<ItemType>::next()
  2126. {
  2127. DBGOUT(BROADCAST, "\n*****Entering CCompleteHandle**Next**\n");
  2128. if (pLocalHandle) {
  2129. if (!pLocalHandle->finished()) {
  2130. DBGOUT(BROADCAST, "From Local Entry\n");
  2131. return pLocalHandle->next();
  2132. }
  2133. else {
  2134. delete pLocalHandle;
  2135. pLocalHandle = NULL;
  2136. }
  2137. }
  2138. if (pNonLocalHandle) {
  2139. if (!pNonLocalHandle->finished()) {
  2140. DBGOUT(BROADCAST, "From NonLocal Entry\n");
  2141. fCacheIsValid = TRUE;
  2142. return pNonLocalHandle->next();
  2143. }
  2144. else {
  2145. delete pNonLocalHandle;
  2146. pNonLocalHandle = NULL;
  2147. }
  2148. }
  2149. // Go over the wire only if we do not have a valid cache..
  2150. if ((!fCacheIsValid) && (pNetHandle)) {
  2151. if (!pNetHandle->finished()) {
  2152. DBGOUT(BROADCAST, "From NetHandle Entry\n");
  2153. return pNetHandle->next();
  2154. }
  2155. else {
  2156. delete pNetHandle;
  2157. pNetHandle = NULL;
  2158. }
  2159. }
  2160. DBGOUT(BROADCAST, "Returning NULL\n");
  2161. return NULL;
  2162. }
  2163. template <class ItemType>
  2164. int
  2165. CCompleteHandle<ItemType>::finished()
  2166. {
  2167. return (pLocalHandle ? pLocalHandle->finished() : TRUE) &&
  2168. (pNonLocalHandle ? pNonLocalHandle->finished() : TRUE) &&
  2169. (pNetHandle ? pNetHandle->finished() : TRUE);
  2170. }
  2171. /*++
  2172. This is a wrapper class that wraps the CCompleteHandle and stores
  2173. the prev binding that was returned to the client in case of a locator-to-
  2174. locator lookup.
  2175. This is called only in I_ns_lookup api functions.
  2176. --*/
  2177. class CLocToLocCompleteHandle : public CContextHandle
  2178. {
  2179. CNSBinding *prevBinding;
  2180. public:
  2181. CCompleteHandle<NSI_BINDING_VECTOR_T> *pcompleteHandle;
  2182. CLocToLocCompleteHandle(
  2183. CCompleteHandle<NSI_BINDING_VECTOR_T> *pcompleteHandleFound)
  2184. :pcompleteHandle(pcompleteHandleFound)
  2185. {
  2186. prevBinding = NULL;
  2187. }
  2188. ~CLocToLocCompleteHandle()
  2189. {
  2190. if (prevBinding)
  2191. delete prevBinding;
  2192. if (pcompleteHandle)
  2193. delete pcompleteHandle;
  2194. }
  2195. void StripObjectsFromAndCompress(
  2196. NSI_BINDING_VECTOR_P_T * BindingVectorOut);
  2197. void rundown()
  2198. {
  2199. DBGOUT(TRACE, "Called Rundown on LocToLoc Handle\n");
  2200. if (pcompleteHandle)
  2201. pcompleteHandle->rundown();
  2202. pcompleteHandle = NULL;
  2203. if (prevBinding)
  2204. delete prevBinding;
  2205. prevBinding = NULL;
  2206. }
  2207. };
  2208. /*++
  2209. Class Definition:
  2210. CInterfaceIndex
  2211. Abstract:
  2212. This class defines an entire interface index in the locator.
  2213. It is like a pseudo entry, but hasn't been formatted that way.
  2214. The form of the lookup method suggests it.
  2215. --*/
  2216. class Locator;
  2217. class CInterfaceIndex {
  2218. struct CInterfaceIndexEntry : public CGUID { // private class
  2219. TCSafeSkipList<CStringW> PossibleEntries;
  2220. CInterfaceIndexEntry(CGUID& guid) : CGUID(guid)
  2221. {}
  2222. ~CInterfaceIndexEntry() {
  2223. PossibleEntries.wipeOut();
  2224. }
  2225. void insert(
  2226. CServerEntry * pSElocation) {
  2227. CStringW *psw = new CStringW(*pSElocation);
  2228. if (Duplicate == PossibleEntries.insert(psw))
  2229. delete psw;
  2230. }
  2231. void remove(CServerEntry * pSElocation) {
  2232. CStringW * deletedItem =
  2233. PossibleEntries.remove(pSElocation);
  2234. // the item had better be there!
  2235. // ASSERT(deletedItem, "Interface Index Corrupted\n");
  2236. }
  2237. };
  2238. CReadWriteSection rwLock;
  2239. TCSafeSkipList<CInterfaceIndexEntry> InterfaceEntries;
  2240. /* the null index contains all entries in EntryList */
  2241. CInterfaceIndexEntry *pNullIndex;
  2242. Locator *pMyLocator;
  2243. public:
  2244. CInterfaceIndex(
  2245. Locator *myL
  2246. )
  2247. {
  2248. CGUID nullGUID; // inits as null UUID thru default constructor
  2249. pNullIndex = new CInterfaceIndexEntry(nullGUID);
  2250. pMyLocator = myL;
  2251. }
  2252. ~CInterfaceIndex() {
  2253. InterfaceEntries.wipeOut();
  2254. delete pNullIndex;
  2255. }
  2256. void insert(
  2257. CServerEntry * pSElocation,
  2258. CInterface * pInf);
  2259. void remove(
  2260. CServerEntry * pSElocation,
  2261. CInterface * pInf);
  2262. void removeServerEntry(CServerEntry *pSElocation);
  2263. TSLLEntryList * lookup(
  2264. CGUIDVersion * pGVInterface
  2265. );
  2266. };
  2267. CEntry *GetEntryFromDS(UNSIGNED32 EntryNameSyntax, STRING_T pszEntryName);
  2268. // in dsedit.cxx
  2269. /*++
  2270. Class Definition:
  2271. CDSNullLookupHandle
  2272. Abstract:
  2273. DS lookup handle. It is lazy and gets the data only when next is called.
  2274. Null Entry Lookup: All the server entries with the object uuid
  2275. will be enumerated and the interfaces will be looked at one by one for
  2276. the correct interface id.
  2277. Very similar to the group lookup.
  2278. --*/
  2279. class CDSNullLookupHandle : public CLookupHandle {
  2280. protected:
  2281. /* search parameters */
  2282. CGUIDVersion * pGVInterface;
  2283. CGUIDVersion * pGVTransferSyntax;
  2284. CGUID * pIDobject;
  2285. unsigned long ulVectorSize;
  2286. BOOL fUnusedHandle;
  2287. CDSQry * pDSQry;
  2288. BOOL fNotInitialized;
  2289. /* handle for the currently active entry */
  2290. CLookupHandle * pCurrentHandle;
  2291. void advanceCurrentHandle(); // look for next nonempty entry handle
  2292. virtual void initialize();
  2293. #if DBG
  2294. ULONG ulDSNullLookupHandleCount;
  2295. static ULONG ulDSNullLookupHandleNo;
  2296. ULONG ulHandleNo;
  2297. #endif
  2298. public:
  2299. virtual void rundown()
  2300. {
  2301. DBGOUT(TRACE,"CDSNullLookupHandle::rundown called for Handle#" << ulHandleNo << "\n\n");
  2302. if (pCurrentHandle)
  2303. {
  2304. pCurrentHandle->rundown();
  2305. delete pCurrentHandle;
  2306. pCurrentHandle = NULL;
  2307. }
  2308. fNotInitialized = TRUE;
  2309. }
  2310. CDSNullLookupHandle(
  2311. CGUIDVersion * pGVInterface,
  2312. CGUIDVersion * pGVTransferSyntax,
  2313. CGUID * pIDobject,
  2314. unsigned long ulVectorSize,
  2315. unsigned long ulCacheAge
  2316. );
  2317. ~CDSNullLookupHandle()
  2318. {
  2319. rundown();
  2320. #if DBG
  2321. ulDSNullLookupHandleCount--;
  2322. #endif
  2323. delete pGVInterface;
  2324. delete pGVTransferSyntax;
  2325. delete pIDobject;
  2326. delete pDSQry;
  2327. }
  2328. NSI_BINDING_VECTOR_T *next();
  2329. int finished();
  2330. void lookupIfNecessary() {};
  2331. };
  2332. #pragma hdrstop
  2333. #endif // _OBJECTS_HXX_