Source code of Windows XP (NT5)
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.

2552 lines
63 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: cumiobj.cxx
  7. //
  8. // Contents: Contains the implementation of IUmiObject/Container methods.
  9. // Methods are encapsulated in one object but this object holds
  10. // a pointer to the inner unknown of the corresponding LDAP
  11. // object. The methods of IUmiContainer are also implemented on
  12. // this object, but will only be used if the underlying object
  13. // is a container.
  14. //
  15. // History: 03-06-00 SivaramR Created.
  16. // 04-07-00 AjayR modified for LDAP Provider.
  17. //
  18. //----------------------------------------------------------------------------
  19. #include "ldap.hxx"
  20. //+---------------------------------------------------------------------------
  21. // Function: CLDAPUmiObject::CLDAPUmiObject
  22. //
  23. // Synopsis: Constructor
  24. //
  25. // Arguments: None
  26. //
  27. // Returns: N/A
  28. //
  29. // Modifies: N/A
  30. //
  31. //----------------------------------------------------------------------------
  32. CLDAPUmiObject::CLDAPUmiObject():
  33. _pPropMgr(NULL),
  34. _pIntfPropMgr(NULL),
  35. _pUnkInner(NULL),
  36. _pIADs(NULL),
  37. _pIADsContainer(NULL),
  38. _ulErrorStatus(0),
  39. _pCoreObj(NULL),
  40. _pExtMgr(NULL),
  41. _fOuterUnkSet(FALSE)
  42. {
  43. }
  44. //+---------------------------------------------------------------------------
  45. // Function: CLDAPUmiObject::~CLDAPUmiObject
  46. //
  47. // Synopsis: Destructor
  48. //
  49. // Arguments: None
  50. //
  51. // Returns: N/A
  52. //
  53. // Modifies: N/A
  54. //
  55. //----------------------------------------------------------------------------
  56. CLDAPUmiObject::~CLDAPUmiObject(void)
  57. {
  58. if (_pIntfPropMgr) {
  59. delete _pIntfPropMgr;
  60. }
  61. if (_pPropMgr) {
  62. delete _pPropMgr;
  63. }
  64. if (_pUnkInner) {
  65. _pUnkInner->Release();
  66. }
  67. if (_pIADsContainer) {
  68. _pIADsContainer->Release();
  69. }
  70. if (_pIADs) {
  71. _pIADs->Release();
  72. }
  73. //
  74. // We specifically do not release these as they are all just ptrs
  75. // _pCreds, _pszLDAPServer, _pszLDAPDn, _pLdapHandle.
  76. //
  77. }
  78. //+---------------------------------------------------------------------------
  79. // Function: CLDAPUmiObject::AllocateLDAPUmiObject --- Static constructor.
  80. //
  81. // Synopsis: Static contstructor routine.
  82. //
  83. // Arguments: intfPropTable- Schema information for interface properties.
  84. // pPropCache - Pointer to property cache (shared with IADs).
  85. // pUnkInner - Pointer to inner unknown of underlying obj.
  86. // pExtMgr - Pointer to extension manager of object.
  87. // pCoreObj - Pointer to the core object of underlying object.
  88. // ppUmiObj - Return value.
  89. //
  90. // Returns: S_OK on success. Error code otherwise.
  91. //
  92. // Modifies: *ppUmObj to point to newly created object.
  93. //
  94. //----------------------------------------------------------------------------
  95. HRESULT
  96. CLDAPUmiObject::CreateLDAPUmiObject(
  97. INTF_PROP_DATA intfPropTable[],
  98. CPropertyCache *pPropertyCache,
  99. IUnknown *pUnkInner,
  100. CCoreADsObject *pCoreObj,
  101. IADs *pIADs,
  102. CCredentials *pCreds,
  103. CLDAPUmiObject **ppUmiObj,
  104. DWORD dwPort, // defaulted to -1
  105. PADSLDP pLdapHandle, // defaulted to NULL
  106. LPWSTR pszServerName, // defaulted to NULL
  107. LPWSTR pszLDAPDn, // defaulted to NULL
  108. CADsExtMgr *pExtMgr // defaulted to NULL
  109. )
  110. {
  111. HRESULT hr = S_OK;
  112. CLDAPUmiObject *pUmiObject = NULL;
  113. CPropertyManager *pPropMgr = NULL;
  114. CPropertyManager *pIntfPropMgr = NULL;
  115. //
  116. // This always has to be there, the extension manager will not
  117. // be there for RootDSE and schema realted objects.
  118. //
  119. ADsAssert(pCoreObj);
  120. pUmiObject = new CLDAPUmiObject();
  121. if (!pUmiObject) {
  122. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  123. }
  124. //
  125. // Property cache is not supported on the schema container object alone.
  126. // There will be no support for the propList methods for this object.
  127. //
  128. if (pPropertyCache) {
  129. //
  130. // Has to be valid if we have a property cache.
  131. //
  132. ADsAssert(pUnkInner);
  133. //
  134. // Need the standard property manager for Get/Put support.
  135. //
  136. hr = CPropertyManager::CreatePropertyManager(
  137. pIADs,
  138. (IUmiObject *) pUmiObject,
  139. pPropertyCache,
  140. pCreds,
  141. pszServerName,
  142. &pPropMgr
  143. );
  144. BAIL_ON_FAILURE(hr);
  145. }
  146. if (intfPropTable) {
  147. hr = CPropertyManager::CreatePropertyManager(
  148. (IUmiObject *) pUmiObject,
  149. pUnkInner, // should support IADs.
  150. pCreds,
  151. intfPropTable,
  152. &pIntfPropMgr
  153. );
  154. BAIL_ON_FAILURE(hr);
  155. }
  156. //
  157. // At this point failures are not catastrophic so we can prepare
  158. // the object for return.
  159. //
  160. pUmiObject->_pUnkInner = pUnkInner;
  161. pUmiObject->_pIADs = pIADs;
  162. pUmiObject->_pExtMgr = pExtMgr;
  163. pUmiObject->_pCoreObj = pCoreObj;
  164. pUmiObject->_pCreds = pCreds;
  165. pUmiObject->_pPropMgr = pPropMgr;
  166. pUmiObject->_pIntfPropMgr = pIntfPropMgr;
  167. pUmiObject->_pszLDAPServer = pszServerName;
  168. pUmiObject->_pszLDAPDn = pszLDAPDn;
  169. pUmiObject->_pLdapHandle = pLdapHandle;
  170. pUmiObject->_dwPort = dwPort;
  171. //
  172. // Addref cause we release this in the destructor.
  173. //
  174. pIADs->AddRef();
  175. //
  176. // Get IADsContainer ptr if applicable - can ignore failures.
  177. //
  178. hr = pUnkInner->QueryInterface(
  179. IID_IADsContainer,
  180. (void **) &(pUmiObject->_pIADsContainer)
  181. );
  182. *ppUmiObj = pUmiObject;
  183. RRETURN(S_OK);
  184. error:
  185. if (pUmiObject) {
  186. delete pUmiObject;
  187. }
  188. if (pPropMgr) {
  189. delete pPropMgr;
  190. }
  191. if (pIntfPropMgr) {
  192. delete pIntfPropMgr;
  193. }
  194. RRETURN(hr);
  195. }
  196. //+---------------------------------------------------------------------------
  197. // Function: CLDAPUmiObject::QueryInterface --- IUnknown support.
  198. //
  199. // Synopsis: Standard query interface method.
  200. //
  201. // Arguments: iid - Interface requested.
  202. // ppInterface - Return pointer to interface requested.
  203. //
  204. // Returns: S_OK on success. Error code otherwise.
  205. //
  206. // Modifies: *ppInterface to return interface pointer.
  207. //
  208. //----------------------------------------------------------------------------
  209. STDMETHODIMP
  210. CLDAPUmiObject::QueryInterface(
  211. REFIID iid,
  212. LPVOID *ppInterface
  213. )
  214. {
  215. HRESULT hr = S_OK;
  216. IUnknown *pTmpIntfPtr = NULL;
  217. SetLastStatus(0);
  218. if (!ppInterface) {
  219. RRETURN(E_INVALIDARG);
  220. }
  221. *ppInterface = NULL;
  222. if (IsEqualIID(iid, IID_IUnknown)) {
  223. *ppInterface = (IUmiObject *) this;
  224. }
  225. else if (IsEqualIID(iid, IID_IUmiPropList)) {
  226. *ppInterface = (IUmiObject *) this;
  227. }
  228. else if (IsEqualIID(iid, IID_IUmiBaseObject)) {
  229. *ppInterface = (IUmiObject *) this;
  230. }
  231. else if (IsEqualIID(iid, IID_IUmiObject)) {
  232. *ppInterface = (IUmiObject *) this;
  233. }
  234. else if (IsEqualIID(iid, IID_IUmiContainer)) {
  235. //
  236. // Check if underlying LDAP object is a container.
  237. //
  238. if (_pIADsContainer != NULL) {
  239. *ppInterface = (IUmiContainer *) this;
  240. }
  241. else {
  242. RRETURN(E_NOINTERFACE);
  243. }
  244. }
  245. else if (IsEqualIID(iid, IID_IUmiCustomInterfaceFactory)) {
  246. *ppInterface = (IUmiCustomInterfaceFactory *) this;
  247. }
  248. else if (IsEqualIID(iid, IID_IADsObjOptPrivate)) {
  249. if (_pLdapHandle) {
  250. *ppInterface = (IADsObjOptPrivate*) this;
  251. }
  252. else {
  253. RRETURN(E_NOINTERFACE);
  254. }
  255. }
  256. else {
  257. RRETURN(E_NOINTERFACE);
  258. }
  259. AddRef();
  260. RRETURN(S_OK);
  261. }
  262. //+---------------------------------------------------------------------------
  263. // Function: CLDAPUmiObject::Clone --- IUmiObject support.
  264. //
  265. // Synopsis: Clones this object. Note that this will do an implicit
  266. // refresh if one has not already been done on the object before
  267. // copying all the attributes. The new object has a state that a
  268. // bound state (rather than unbound).
  269. //
  270. // Arguments: uFlags --- Must be 0 for now.
  271. // riid --- IID requested on the clone.
  272. // pCopy --- The return ptr for the cloned object.
  273. //
  274. // Returns: S_OK or appropriate error code.
  275. //
  276. // Modifies: pCopy to be updated with new UmiObject ptr on success.
  277. //
  278. //----------------------------------------------------------------------------
  279. STDMETHODIMP
  280. CLDAPUmiObject::Clone(
  281. ULONG uFlags,
  282. REFIID riid,
  283. LPVOID *pCopy
  284. )
  285. {
  286. HRESULT hr = S_OK;
  287. CCredentials Creds;
  288. BSTR bstrPath = NULL;
  289. BSTR bstrClass = NULL;
  290. LPWSTR pszParent = NULL, pszCommonName = NULL;
  291. IUmiObject *pUmiObj = NULL;
  292. IUmiObject *pDestUmiObj = NULL;
  293. DWORD dwAuthFlags = 0;
  294. SetLastStatus(0);
  295. //
  296. // We cannot clone objects that do not have an underlying IADs ptr.
  297. //
  298. if (!_pIADs) {
  299. BAIL_ON_FAILURE(hr = E_FAIL);
  300. }
  301. if (_pCreds) {
  302. Creds = *_pCreds;
  303. }
  304. //
  305. // Need to tag on the ADS_FAST_BIND to prevent the call from
  306. // going on the wire.
  307. //
  308. dwAuthFlags = Creds.GetAuthFlags();
  309. Creds.SetAuthFlags(dwAuthFlags | ADS_FAST_BIND);
  310. //
  311. // Need to call Refresh with the internal flag. Note that using this
  312. // flag means that we will go on the wire only if we have to.
  313. //
  314. hr = this->Refresh(
  315. ADSI_INTERNAL_FLAG_GETINFO_AS_NEEDED,
  316. NULL,
  317. NULL
  318. );
  319. BAIL_ON_FAILURE(hr);
  320. //
  321. // Next we need to get the destination object.
  322. //
  323. hr = _pIADs->get_ADsPath(&bstrPath);
  324. BAIL_ON_FAILURE(hr);
  325. if (_pCoreObj->GetObjectState() == ADS_OBJECT_UNBOUND) {
  326. //
  327. // In this case we need to Create the target object.
  328. // The parent path, the common name and the class are needed.
  329. //
  330. hr = BuildADsParentPath(
  331. bstrPath,
  332. &pszParent,
  333. &pszCommonName
  334. );
  335. BAIL_ON_FAILURE(hr);
  336. hr = _pIADs->get_Class(&bstrClass);
  337. BAIL_ON_FAILURE(hr);
  338. hr = CLDAPGenObject::CreateGenericObject(
  339. pszParent,
  340. pszCommonName,
  341. bstrClass,
  342. Creds,
  343. ADS_OBJECT_UNBOUND,
  344. riid, // this is ignored
  345. (void **) &pUmiObj
  346. );
  347. BAIL_ON_FAILURE(hr);
  348. }
  349. else {
  350. //
  351. // In this case we bind to the object.
  352. //
  353. hr = GetObject(bstrPath, Creds, (void **)&pUmiObj);
  354. BAIL_ON_FAILURE(hr);
  355. }
  356. pUmiObj->QueryInterface(IID_IUmiObject, (void **) &pDestUmiObj);
  357. BAIL_ON_FAILURE(hr);
  358. //
  359. // Now we can call the helper to copy the attributes over.
  360. //
  361. hr = this->CopyToHelper(
  362. (IUmiObject*) this,
  363. pDestUmiObj,
  364. 0,
  365. FALSE, // do not mark as update
  366. FALSE // do not copy intf props
  367. );
  368. BAIL_ON_FAILURE(hr);
  369. //
  370. // Update return value as this means copy was succesful.
  371. //
  372. *pCopy = pDestUmiObj;
  373. error:
  374. if (FAILED(hr)) {
  375. if (!_ulErrorStatus) {
  376. SetLastStatus(hr);
  377. }
  378. hr = MapHrToUmiError(hr);
  379. if (pDestUmiObj) {
  380. pDestUmiObj->Release();
  381. }
  382. }
  383. if (bstrPath) {
  384. SysFreeString(bstrPath);
  385. }
  386. if (bstrClass) {
  387. SysFreeString(bstrClass);
  388. }
  389. if (pszParent) {
  390. FreeADsStr(pszParent);
  391. }
  392. if (pszCommonName) {
  393. FreeADsStr(pszCommonName);
  394. }
  395. if (pUmiObj) {
  396. pUmiObj->Release();
  397. }
  398. RRETURN(hr);
  399. }
  400. //+---------------------------------------------------------------------------
  401. // Function: CLDAPUmiObject::CopyTo --- IUmiObject support.
  402. //
  403. // Synopsis: Copies the object to the new destination.Note that this will
  404. // do an implicit refresh if one has not already been done on the
  405. // object before copying all the attributes. The new objecst state
  406. // is unbound, and the new object will be created on the destination
  407. // directory only when Commit is called. If any of the properties on
  408. // the object being copied are marked as updated/dirty then the call
  409. // will fail.
  410. //
  411. // Arguments: uFlags --- Must be 0 for now.
  412. // pURL --- Url pointing to the destination.
  413. // riid --- IID requested on the clone.
  414. // pCopy --- The return ptr for the copied object.
  415. //
  416. // Returns: S_OK or appropriate error code.
  417. //
  418. // Modifies: pCopy to be updated with new UmiObject ptr on success.
  419. //
  420. //----------------------------------------------------------------------------
  421. STDMETHODIMP
  422. CLDAPUmiObject::CopyTo(
  423. IN ULONG uFlags,
  424. IN IUmiURL *pURL,
  425. IN REFIID riid,
  426. OUT LPVOID *pCopy
  427. )
  428. {
  429. HRESULT hr = S_OK;
  430. CCredentials Creds;
  431. BSTR bstrClass = NULL;
  432. LPWSTR pszLdapPath = NULL;
  433. LPWSTR pszParent = NULL, pszCommonName = NULL;
  434. IUmiObject *pUmiObj = NULL;
  435. IUmiObject *pUmiDestObj = NULL;
  436. DWORD dwAuthFlags = 0;
  437. SetLastStatus(0);
  438. RRETURN(E_NOTIMPL);
  439. //*******************************************************/
  440. // This code is not used currently. /
  441. //*******************************************************/
  442. //
  443. // Has to be 0.
  444. //
  445. if (uFlags) {
  446. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  447. }
  448. //
  449. // All these need to be valid.
  450. //
  451. if (!pURL
  452. || !pCopy
  453. || (riid != IID_IUmiObject)
  454. ) {
  455. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  456. }
  457. //
  458. // We cannot copy objects that do not have an underlying IADs ptr.
  459. //
  460. if (!_pIADs) {
  461. BAIL_ON_FAILURE(hr = E_FAIL);
  462. }
  463. if (_pCreds) {
  464. Creds = *_pCreds;
  465. }
  466. //
  467. // Need to call Refresh with the internal flag. Note that using this
  468. // flag means that we will go on the wire only if we have to.
  469. //
  470. hr = this->Refresh(
  471. ADSI_INTERNAL_FLAG_GETINFO_AS_NEEDED,
  472. NULL,
  473. NULL
  474. );
  475. BAIL_ON_FAILURE(hr);
  476. hr = _pIADs->get_Class(&bstrClass);
  477. BAIL_ON_FAILURE(hr);
  478. //
  479. // Now we need to convert the UmiPath to LDAPPath that we can use.
  480. //
  481. hr = UrlToLDAPPath(
  482. pURL,
  483. &pszLdapPath
  484. );
  485. BAIL_ON_FAILURE(hr);
  486. //
  487. // We need to split path to parent and common name.
  488. //
  489. hr = BuildADsParentPath(
  490. pszLdapPath,
  491. &pszParent,
  492. &pszCommonName
  493. );
  494. BAIL_ON_FAILURE(hr);
  495. hr = CLDAPGenObject::CreateGenericObject(
  496. pszParent,
  497. pszCommonName,
  498. bstrClass,
  499. Creds,
  500. ADS_OBJECT_UNBOUND,
  501. riid, // this is ignored
  502. (void **) &pUmiObj
  503. );
  504. BAIL_ON_FAILURE(hr);
  505. hr = pUmiObj->QueryInterface(riid, (void **) &pUmiDestObj);
  506. BAIL_ON_FAILURE(hr);
  507. //
  508. // Need to copy the attributes over now.
  509. //
  510. hr = this->CopyToHelper(
  511. this,
  512. pUmiDestObj,
  513. 0,
  514. TRUE, // means fail call if property status is not 0
  515. FALSE // do not copy intf props.
  516. );
  517. BAIL_ON_FAILURE(hr);
  518. *pCopy = pUmiDestObj;
  519. error:
  520. if (pszLdapPath) {
  521. FreeADsStr(pszLdapPath);
  522. }
  523. if (pszParent) {
  524. FreeADsStr(pszParent);
  525. }
  526. if (pszCommonName) {
  527. FreeADsStr(pszCommonName);
  528. }
  529. if (pUmiObj) {
  530. pUmiObj->Release();
  531. }
  532. if (bstrClass) {
  533. SysFreeString(bstrClass);
  534. }
  535. if (FAILED(hr)) {
  536. if (!this->_ulErrorStatus) {
  537. SetLastError(hr);
  538. }
  539. if (pUmiDestObj) {
  540. pUmiDestObj->Release();
  541. }
  542. }
  543. RRETURN(hr);
  544. }
  545. //+---------------------------------------------------------------------------
  546. // Function: CLDAPUmiObject::Refresh --- IUmiObject support.
  547. //
  548. // Synopsis: Refreshes the properties of the object. This calls the
  549. // underlying LDAP object for the operation.
  550. //
  551. // Arguments: uFlags - UMI_FLAGS_REFERESH_ALL, PARTIAL supported
  552. // and ADSI internal flag to implicit GetInfo only
  553. // if one is needed (helps clone and copyto).
  554. // uNameCount - Number of attributes to refresh.
  555. // pszNames - Names of attributes to refresh.
  556. //
  557. // Returns: S_OK on success. Error code otherwise
  558. //
  559. // Modifies: Underlying property cache.
  560. //
  561. //----------------------------------------------------------------------------
  562. HRESULT CLDAPUmiObject::Refresh(
  563. ULONG uFlags,
  564. ULONG uNameCount,
  565. LPWSTR *pszNames
  566. )
  567. {
  568. ULONG i = 0;
  569. HRESULT hr = S_OK;
  570. BOOL fUseGetInfoEx = FALSE;
  571. DWORD dwGetInfoFlag = TRUE;
  572. SetLastStatus(0);
  573. //
  574. // Only all and partial and the special internal flag. Refresh
  575. // partial translates to an implicit getinfo in ADSI.
  576. //
  577. if ((uFlags != UMI_FLAG_REFRESH_ALL)
  578. && (uFlags != UMI_FLAG_REFRESH_PARTIAL)
  579. && (uFlags != ADSI_INTERNAL_FLAG_GETINFO_AS_NEEDED)
  580. ) {
  581. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  582. }
  583. if (uFlags == UMI_FLAG_REFRESH_PARTIAL) {
  584. //
  585. // Cannot specify list of names in this case.
  586. //
  587. if (uNameCount != 0) {
  588. BAIL_ON_FAILURE(hr = UMI_E_UNSUPPORTED_OPERATION);
  589. }
  590. dwGetInfoFlag = GETINFO_FLAG_IMPLICIT;
  591. }
  592. else if (uFlags == ADSI_INTERNAL_FLAG_GETINFO_AS_NEEDED) {
  593. dwGetInfoFlag = GETINFO_FLAG_IMPLICIT_AS_NEEDED;
  594. }
  595. if ((uFlags == UMI_FLAG_REFRESH_ALL) && (uNameCount != 0)) {
  596. fUseGetInfoEx = TRUE;
  597. }
  598. if (fUseGetInfoEx) {
  599. //
  600. // Build the variant array of strings.
  601. //
  602. VARIANT vVar;
  603. VariantInit(&vVar);
  604. //
  605. // Builds a variant array we can use in GetInfoEx
  606. //
  607. hr = ADsBuildVarArrayStr(
  608. pszNames,
  609. (DWORD)uNameCount,
  610. &vVar);
  611. BAIL_ON_FAILURE(hr);
  612. //
  613. // Call GetInfoEx to do the actual work.
  614. //
  615. hr = _pIADs->GetInfoEx(vVar, 0);
  616. VariantClear(&vVar);
  617. }
  618. else {
  619. hr = this->_pCoreObj->GetInfo(dwGetInfoFlag);
  620. //
  621. // Since schema and few others do not implement the implicit GetInfo.
  622. //
  623. if (FAILED(hr) && hr == E_NOTIMPL) {
  624. //
  625. // Should try just an ordinary GetInfo if applicable.
  626. //
  627. if (dwGetInfoFlag == GETINFO_FLAG_EXPLICIT) {
  628. hr = _pIADs->GetInfo();
  629. }
  630. }
  631. }
  632. BAIL_ON_FAILURE(hr);
  633. error:
  634. if (FAILED(hr)) {
  635. SetLastStatus(hr);
  636. hr = MapHrToUmiError(hr);
  637. }
  638. RRETURN(hr);
  639. }
  640. //+---------------------------------------------------------------------------
  641. // Function: CLDAPUmiObject::Commit --- IUmiObject support.
  642. //
  643. // Synopsis: Implements IUmiObject::Commit. Calls SetInfo on WinNT
  644. // object to commit changes made to the cache.
  645. //
  646. // Arguments: uFlags - Only 0 for now.
  647. //
  648. // Returns: S_OK on success. Error code otherwise
  649. //
  650. // Modifies: N/A.
  651. //
  652. //----------------------------------------------------------------------------
  653. STDMETHODIMP
  654. CLDAPUmiObject::Commit(ULONG uFlags)
  655. {
  656. HRESULT hr = S_OK;
  657. IADsObjOptPrivate *pPrivOpt = NULL;
  658. DWORD dwFlags;
  659. SetLastStatus(0);
  660. if (uFlags > UMI_DONT_COMMIT_SECURITY_DESCRIPTOR) {
  661. SetLastStatus(UMI_E_INVALID_FLAGS);
  662. RRETURN(UMI_E_INVALID_FLAGS);
  663. }
  664. //
  665. // If this is set do not commit security descriptor.
  666. //
  667. if (uFlags & UMI_DONT_COMMIT_SECURITY_DESCRIPTOR) {
  668. //
  669. // The prop manager has to do this cause it has the prop cache.
  670. //
  671. hr = _pPropMgr->DeleteSDIfPresent();
  672. BAIL_ON_FAILURE(hr);
  673. }
  674. if (uFlags & UMI_SECURITY_MASK) {
  675. //
  676. // Need to make sure that we update the SD
  677. // flags on the ADSI object if necessary.
  678. //
  679. if (!_pIADs) {
  680. BAIL_ON_FAILURE(hr = E_FAIL);
  681. }
  682. hr = _pIADs->QueryInterface(
  683. IID_IADsObjOptPrivate,
  684. (void **)&pPrivOpt
  685. );
  686. BAIL_ON_FAILURE(hr);
  687. dwFlags = uFlags & UMI_SECURITY_MASK;
  688. hr = pPrivOpt->SetOption(
  689. LDAP_SECURITY_MASK,
  690. (void *) &dwFlags
  691. );
  692. BAIL_ON_FAILURE(hr);
  693. }
  694. hr = _pIADs->SetInfo();
  695. BAIL_ON_FAILURE(hr);
  696. error:
  697. if (FAILED(hr)) {
  698. SetLastStatus(hr);
  699. hr = MapHrToUmiError(hr);
  700. }
  701. if (pPrivOpt) {
  702. pPrivOpt->Release();
  703. }
  704. RRETURN(hr);
  705. }
  706. //+---------------------------------------------------------------------------
  707. // IUmiPropList methods
  708. //
  709. // These are implemented by invoking the corresponding method in the
  710. // CUmiPropList object that implements object properties. For a description
  711. // of these methods, refer to cpropmgr.cxx
  712. //
  713. //----------------------------------------------------------------------------
  714. STDMETHODIMP
  715. CLDAPUmiObject::Put(
  716. LPCWSTR pszName,
  717. ULONG uFlags,
  718. UMI_PROPERTY_VALUES *pProp
  719. )
  720. {
  721. HRESULT hr = S_OK;
  722. ULONG ulStatus = 0;
  723. SetLastStatus(0);
  724. if (!_pPropMgr) {
  725. SetLastStatus(E_NOTIMPL);
  726. RRETURN(E_NOTIMPL);
  727. }
  728. hr = _pPropMgr->Put(
  729. pszName,
  730. uFlags,
  731. pProp
  732. );
  733. if (FAILED(hr)) {
  734. IID iid;
  735. //
  736. // Need to update the error status on this object.
  737. //
  738. _pPropMgr->GetLastStatus( // ignore error return
  739. 0,
  740. &ulStatus,
  741. iid,
  742. NULL
  743. );
  744. SetLastStatus(ulStatus);
  745. }
  746. RRETURN(hr);
  747. }
  748. STDMETHODIMP
  749. CLDAPUmiObject::Get(
  750. LPCWSTR pszName,
  751. ULONG uFlags,
  752. UMI_PROPERTY_VALUES **ppProp
  753. )
  754. {
  755. HRESULT hr = S_OK;
  756. ULONG ulStatus = 0;
  757. SetLastStatus(0);
  758. if (!_pPropMgr) {
  759. SetLastStatus(E_NOTIMPL);
  760. RRETURN(E_NOTIMPL);
  761. }
  762. hr = _pPropMgr->Get(
  763. pszName,
  764. uFlags,
  765. ppProp
  766. );
  767. if (FAILED(hr)) {
  768. //
  769. // Update error on this object appropriately.
  770. //
  771. IID iid;
  772. _pPropMgr->GetLastStatus(
  773. 0,
  774. &ulStatus,
  775. iid,
  776. NULL
  777. );
  778. SetLastStatus(ulStatus);
  779. }
  780. //
  781. // No need to map the error as the property manager would have
  782. // already done that for us.
  783. //
  784. RRETURN(hr);
  785. }
  786. STDMETHODIMP
  787. CLDAPUmiObject::GetAs(
  788. LPCWSTR pszName,
  789. ULONG uFlags,
  790. ULONG uCoercionType,
  791. UMI_PROPERTY_VALUES **ppProp
  792. )
  793. {
  794. HRESULT hr = S_OK;
  795. ULONG ulStatus = 0;
  796. SetLastStatus(0);
  797. if (!_pPropMgr) {
  798. SetLastStatus(E_NOTIMPL);
  799. RRETURN(E_NOTIMPL);
  800. }
  801. hr = _pPropMgr->GetAs(
  802. pszName,
  803. uFlags,
  804. uCoercionType,
  805. ppProp
  806. );
  807. if (FAILED(hr)) {
  808. //
  809. // Update error on this object appropriately.
  810. //
  811. IID iid;
  812. _pPropMgr->GetLastStatus( // ignore error return
  813. 0,
  814. &ulStatus,
  815. iid,
  816. NULL
  817. );
  818. SetLastStatus(ulStatus);
  819. }
  820. //
  821. // No need to map hr as property manager would have already done that.
  822. //
  823. RRETURN(hr);
  824. }
  825. STDMETHODIMP
  826. CLDAPUmiObject::FreeMemory(
  827. ULONG uReserved,
  828. LPVOID pMem
  829. )
  830. {
  831. HRESULT hr = S_OK;
  832. if (uReserved) {
  833. SetLastStatus(E_INVALIDARG);
  834. RRETURN(E_INVALIDARG);
  835. }
  836. hr = FreeUmiPropertyValues((PUMI_PROPERTY_VALUES) pMem);
  837. SetLastStatus(hr);
  838. RRETURN(hr);
  839. }
  840. STDMETHODIMP
  841. CLDAPUmiObject::GetAt(
  842. LPCWSTR pszName,
  843. ULONG uFlags,
  844. ULONG uBufferLength,
  845. LPVOID pExistingMem
  846. )
  847. {
  848. HRESULT hr = S_OK;
  849. ULONG ulStatus = 0;
  850. SetLastStatus(0);
  851. if (!_pPropMgr) {
  852. SetLastStatus(E_NOTIMPL);
  853. RRETURN(E_NOTIMPL);
  854. }
  855. hr = _pPropMgr->GetAt(
  856. pszName,
  857. uFlags,
  858. uBufferLength,
  859. pExistingMem
  860. );
  861. if (FAILED(hr)) {
  862. //
  863. // Update error on this object appropriately.
  864. //
  865. IID iid;
  866. _pPropMgr->GetLastStatus( // ignore error return
  867. 0,
  868. &ulStatus,
  869. iid,
  870. NULL
  871. );
  872. SetLastStatus(ulStatus);
  873. }
  874. RRETURN(hr);
  875. }
  876. STDMETHODIMP
  877. CLDAPUmiObject::GetProps(
  878. LPCWSTR *pszNames,
  879. ULONG uNameCount,
  880. ULONG uFlags,
  881. UMI_PROPERTY_VALUES **pProps
  882. )
  883. {
  884. HRESULT hr = S_OK;
  885. ULONG ulStatus = 0;
  886. SetLastStatus(0);
  887. if (!_pPropMgr) {
  888. SetLastStatus(E_NOTIMPL);
  889. RRETURN(E_NOTIMPL);
  890. }
  891. hr = _pPropMgr->GetProps(
  892. pszNames,
  893. uNameCount,
  894. uFlags,
  895. pProps
  896. );
  897. if (FAILED(hr)) {
  898. //
  899. // Update error on this object appropriately.
  900. //
  901. IID iid;
  902. _pPropMgr->GetLastStatus( // ignore error return
  903. 0,
  904. &ulStatus,
  905. iid,
  906. NULL
  907. );
  908. SetLastStatus(ulStatus);
  909. }
  910. RRETURN(hr);
  911. }
  912. STDMETHODIMP
  913. CLDAPUmiObject::PutProps(
  914. LPCWSTR *pszNames,
  915. ULONG uNameCount,
  916. ULONG uFlags,
  917. UMI_PROPERTY_VALUES *pProps
  918. )
  919. {
  920. HRESULT hr = S_OK;
  921. ULONG ulStatus = 0;
  922. SetLastStatus(0);
  923. if (!_pPropMgr) {
  924. SetLastStatus(E_NOTIMPL);
  925. RRETURN(E_NOTIMPL);
  926. }
  927. hr = _pPropMgr->PutProps(
  928. pszNames,
  929. uNameCount,
  930. uFlags,
  931. pProps
  932. );
  933. if (FAILED(hr)) {
  934. //
  935. // Update error on this object appropriately.
  936. //
  937. IID iid;
  938. _pPropMgr->GetLastStatus(
  939. 0,
  940. &ulStatus,
  941. iid,
  942. NULL
  943. );
  944. SetLastStatus(ulStatus);
  945. }
  946. RRETURN(hr);
  947. }
  948. HRESULT CLDAPUmiObject::PutFrom(
  949. LPCWSTR pszName,
  950. ULONG uFlags,
  951. ULONG uBufferLength,
  952. LPVOID pExistingMem
  953. )
  954. {
  955. HRESULT hr = S_OK;
  956. ULONG ulStatus = 0;
  957. SetLastStatus(0);
  958. if (!_pPropMgr) {
  959. SetLastStatus(E_NOTIMPL);
  960. RRETURN(E_NOTIMPL);
  961. }
  962. hr = _pPropMgr->PutFrom(
  963. pszName,
  964. uFlags,
  965. uBufferLength,
  966. pExistingMem
  967. );
  968. if (FAILED(hr)) {
  969. //
  970. // Update error on this object appropriately.
  971. //
  972. IID iid;
  973. _pPropMgr->GetLastStatus(
  974. 0,
  975. &ulStatus,
  976. iid,
  977. NULL
  978. );
  979. SetLastStatus(ulStatus);
  980. }
  981. RRETURN(hr);
  982. }
  983. STDMETHODIMP
  984. CLDAPUmiObject::Delete(
  985. LPCWSTR pszName,
  986. ULONG uFlags
  987. )
  988. {
  989. HRESULT hr = S_OK;
  990. ULONG ulStatus = 0;
  991. SetLastStatus(0);
  992. if (!_pPropMgr) {
  993. SetLastStatus(E_NOTIMPL);
  994. RRETURN(E_NOTIMPL);
  995. }
  996. hr = _pPropMgr->Delete(
  997. pszName,
  998. uFlags
  999. );
  1000. if (FAILED(hr)) {
  1001. //
  1002. // Update error on this object appropriately.
  1003. //
  1004. IID iid;
  1005. _pPropMgr->GetLastStatus( // ignore error return
  1006. 0,
  1007. &ulStatus,
  1008. iid,
  1009. NULL
  1010. );
  1011. SetLastStatus(ulStatus);
  1012. }
  1013. RRETURN(hr);
  1014. }
  1015. //+---------------------------------------------------------------------------
  1016. // Function: CLDAPUmiObject::GetLastStatus --- IUmiBaseObject support.
  1017. //
  1018. // Synopsis: Returns status or error code from the last operation. Currently
  1019. // only numeric status is returned i.e, no error objects are
  1020. // returned. Implements IUmiBaseObject::GetLastStatus().
  1021. //
  1022. // Arguments: uFlags - Reserved. Must be 0 for now.
  1023. // puSpecificStatus - Returns status code.
  1024. // riid - IID requested. Ignored currently.
  1025. // pStatusObj - Returns interface requested.
  1026. // Always returns NULL currently.
  1027. //
  1028. // Returns: S_OK on success. Error code otherwise.
  1029. //
  1030. // Modifies: *puSpecificStatus to return status code.
  1031. //
  1032. //----------------------------------------------------------------------------
  1033. STDMETHODIMP
  1034. CLDAPUmiObject::GetLastStatus(
  1035. ULONG uFlags,
  1036. ULONG *puSpecificStatus,
  1037. REFIID riid,
  1038. LPVOID *pStatusObj
  1039. )
  1040. {
  1041. if (pStatusObj) {
  1042. *pStatusObj = NULL;
  1043. }
  1044. if (puSpecificStatus) {
  1045. *puSpecificStatus = 0;
  1046. }
  1047. else {
  1048. RRETURN(E_INVALIDARG);
  1049. }
  1050. if (uFlags) {
  1051. RRETURN(UMI_E_INVALID_FLAGS);
  1052. }
  1053. *puSpecificStatus = _ulErrorStatus;
  1054. RRETURN(S_OK);
  1055. }
  1056. //+---------------------------------------------------------------------------
  1057. // Function: CLDAPUmiObject::GetInterfacePropList --- IUmiBaseObject method.
  1058. //
  1059. // Synopsis: Returns a pointer to the interface property list implementation
  1060. // for the connection object. Implements
  1061. // IUmiBaseObject::GetInterfacePropList().
  1062. //
  1063. // Arguments: uFlags - Reserved. Must be 0 for now.
  1064. // pPropList - Returns pointer to IUmiPropertyList interface
  1065. //
  1066. // Returns: S_OK on success. Error code otherwise.
  1067. //
  1068. // Modifies: *pPropList to return interface pointer
  1069. //
  1070. //----------------------------------------------------------------------------
  1071. STDMETHODIMP
  1072. CLDAPUmiObject::GetInterfacePropList(
  1073. ULONG uFlags,
  1074. IUmiPropList **pPropList
  1075. )
  1076. {
  1077. HRESULT hr = S_OK;
  1078. if (uFlags) {
  1079. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  1080. }
  1081. if (!pPropList) {
  1082. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1083. }
  1084. ADsAssert(_pIntfPropMgr);
  1085. //
  1086. // The refCounts are tricky here. When this operation is done,
  1087. // the ref on this object goes up by one, so you will need to
  1088. // releaserefs on the proplist in order to delete this object.
  1089. // This is to prevent the case of a proplist existing without
  1090. // the underlying object (ok for WinNT not for LDAP).
  1091. //
  1092. hr = _pIntfPropMgr->QueryInterface(IID_IUmiPropList, (void **) pPropList);
  1093. error:
  1094. if (FAILED(hr)) {
  1095. SetLastStatus(hr);
  1096. }
  1097. RRETURN(hr);
  1098. }
  1099. //+---------------------------------------------------------------------------
  1100. // Function: CLDAPUmiObject::SetLastStatus --- Internal helper routine.
  1101. //
  1102. // Synopsis: Sets the status of the last operation. If the status is one
  1103. // of the pre-defined error codes, then the status is just set to
  1104. // 0 since we are not adding any value by returning the same
  1105. // status as the error code.
  1106. //
  1107. // Arguments: ulStatus - Status to be set
  1108. //
  1109. // Returns: N/A.
  1110. //
  1111. // Modifies: ulStatus member variable.
  1112. //
  1113. //----------------------------------------------------------------------------
  1114. void
  1115. CLDAPUmiObject::SetLastStatus(ULONG ulStatus)
  1116. {
  1117. _ulErrorStatus = ulStatus;
  1118. return;
  1119. }
  1120. //+---------------------------------------------------------------------------
  1121. // Function: CLDAPUmiObject::Open --- IUmiContainer support.
  1122. //
  1123. // Synopsis: Opens the object specified by a URL. URL may be native LDAP
  1124. // path or any UMI path.
  1125. //
  1126. // Arguments: pURL - Pointer to an IUmiURL interface
  1127. // uFlags - Reserved. Must be 0 for now.
  1128. // TargetIID - Interface requested.
  1129. // ppInterface - Returns pointer to interface requested.
  1130. //
  1131. // Returns: S_OK on success. Error code otherwise.
  1132. //
  1133. // Modifies: *ppInterface to return interface pointer
  1134. //
  1135. //----------------------------------------------------------------------------
  1136. STDMETHODIMP
  1137. CLDAPUmiObject::Open(
  1138. IUmiURL *pURL,
  1139. ULONG uFlags,
  1140. REFIID TargetIID,
  1141. LPVOID *ppInterface
  1142. )
  1143. {
  1144. HRESULT hr;
  1145. LONG lGenus = UMI_GENUS_INSTANCE;
  1146. LPWSTR pszDN = NULL, pszClass = NULL;
  1147. IDispatch *pDispObj = NULL;
  1148. SetLastStatus(0);
  1149. //
  1150. // Get the class name and the dn from the url.
  1151. //
  1152. if (!pURL || !ppInterface) {
  1153. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1154. }
  1155. if (uFlags != 0) {
  1156. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  1157. }
  1158. //
  1159. // Helper will split the url txt to useful pieces.
  1160. //
  1161. hr = UrlToClassAndDn(pURL, &pszClass, &pszDN);
  1162. BAIL_ON_FAILURE(hr);
  1163. //
  1164. // At this point if this is a class instance == schema class object,
  1165. // then if the dn is of the format name="something", we should just
  1166. // pass in "something" to the IADsContainer::Open call.
  1167. //
  1168. if (pszClass
  1169. && *pszClass
  1170. && !_wcsicmp(pszClass, L"Class")) {
  1171. //
  1172. // Want to see if this is a class instance.
  1173. //
  1174. if (_pIntfPropMgr) {
  1175. hr = _pIntfPropMgr->GetLongProperty(L"__GENUS", &lGenus);
  1176. if (FAILED(hr)) {
  1177. //
  1178. // We will assume that this is not a class in this case.
  1179. //
  1180. hr = S_OK;
  1181. lGenus = UMI_GENUS_INSTANCE;
  1182. }
  1183. }
  1184. if (pszDN // should always be true
  1185. && lGenus == UMI_GENUS_CLASS
  1186. ) {
  1187. if (!_wcsnicmp(pszDN, L"name=", 5)) {
  1188. //
  1189. // Copy over the new name and replace pszDN with
  1190. // the new name.
  1191. //
  1192. LPWSTR pszReplace;
  1193. pszReplace = AllocADsStr(pszDN + 5);
  1194. if (!pszReplace) {
  1195. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  1196. }
  1197. if (pszDN) {
  1198. FreeADsStr(pszDN);
  1199. }
  1200. pszDN = pszReplace;
  1201. }
  1202. }
  1203. }
  1204. //
  1205. // Call the IADSContaienr::GetObject to do the remaining work.
  1206. //
  1207. hr = _pIADsContainer->GetObject(pszClass, pszDN, &pDispObj);
  1208. BAIL_ON_FAILURE(hr);
  1209. if (pszClass && *pszClass) {
  1210. //
  1211. // We need to compare the name cause, the GetObject code cannot
  1212. // do that for umi calls.
  1213. //
  1214. hr = VerifyIfClassMatches(
  1215. pszClass,
  1216. pDispObj,
  1217. lGenus
  1218. );
  1219. BAIL_ON_FAILURE(hr);
  1220. }
  1221. hr = pDispObj->QueryInterface(TargetIID, ppInterface);
  1222. BAIL_ON_FAILURE(hr);
  1223. error:
  1224. if (pDispObj) {
  1225. pDispObj->Release();
  1226. }
  1227. if (pszClass) {
  1228. FreeADsStr(pszClass);
  1229. }
  1230. if (pszDN) {
  1231. FreeADsStr(pszDN);
  1232. }
  1233. if (FAILED(hr)) {
  1234. SetLastStatus(hr);
  1235. hr = MapHrToUmiError(hr);
  1236. }
  1237. RRETURN(hr);
  1238. }
  1239. //+---------------------------------------------------------------------------
  1240. // Function: CLDAPUmiObject::Put --- IUmiContainer support.
  1241. //
  1242. // Synopsis: Commits an object into the container. Not implemented.
  1243. //
  1244. // Arguments: uFlags - Reserved. Must be 0 for now.
  1245. // TargetIID - IID of interface pointer requesed.
  1246. // pInterface - Output interface pointer.
  1247. //
  1248. // Returns: S_OK on success. Error code otherwise.
  1249. //
  1250. // Modifies: *ppInterface to return interface pointer
  1251. //
  1252. //----------------------------------------------------------------------------
  1253. STDMETHODIMP
  1254. CLDAPUmiObject::PutObject(
  1255. ULONG uFlags,
  1256. REFIID TargetIID,
  1257. LPVOID pInterface
  1258. )
  1259. {
  1260. SetLastStatus(E_NOTIMPL);
  1261. RRETURN(E_NOTIMPL);
  1262. }
  1263. //+---------------------------------------------------------------------------
  1264. // Function: CLDAPUmiObject::DeleteObject --- IUmiContainer support.
  1265. //
  1266. // Synopsis: Deletes the object specified by the URL. This calls the
  1267. // underlying container object to do the delete after preparing
  1268. // the arguments suitably. Note that if no class name is specified
  1269. // we will pass in NULL to the IADsContainer::Delete call.
  1270. //
  1271. // Arguments: pURL - Pointer to URL of object to delete (relative).
  1272. // uFlags - Reserved. Must be 0 for now.
  1273. //
  1274. // Returns: S_OK on success. Error code otherwise.
  1275. //
  1276. // Modifies: N/A.
  1277. //
  1278. //----------------------------------------------------------------------------
  1279. STDMETHODIMP
  1280. CLDAPUmiObject::DeleteObject(
  1281. IUmiURL *pURL,
  1282. ULONG uFlags
  1283. )
  1284. {
  1285. HRESULT hr;
  1286. LPWSTR pszClass = NULL, pszDN = NULL;
  1287. if (!pURL) {
  1288. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1289. }
  1290. if (uFlags != 0) {
  1291. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  1292. }
  1293. hr = UrlToClassAndDn(pURL, &pszClass, &pszDN);
  1294. BAIL_ON_FAILURE(hr);
  1295. //
  1296. // Call the IADsContainer::Delete entry point to do the work.
  1297. //
  1298. hr = _pIADsContainer->Delete(pszClass, pszDN);
  1299. error:
  1300. if (pszClass) {
  1301. FreeADsStr(pszClass);
  1302. }
  1303. if (pszDN) {
  1304. FreeADsStr(pszDN);
  1305. }
  1306. if (FAILED(hr)) {
  1307. SetLastStatus(hr);
  1308. hr = MapHrToUmiError(hr);
  1309. }
  1310. RRETURN(hr);
  1311. }
  1312. //+---------------------------------------------------------------------------
  1313. // Function: CLDAPUmiObject::Create --- IUmiContainer support.
  1314. //
  1315. // Synopsis: Creates the object specified by the URL. There always has
  1316. // to be a className for this operation to succeed. The newly
  1317. // created object is not yet on the directory, just local (need
  1318. // to call Commit to create it on the directory).
  1319. //
  1320. // Arguments: pURL - Pointer to URL of new object (relative).
  1321. // uFlags - Reserved. Must be 0 for now.
  1322. // ppNewObj - Return ptr for newly created object.
  1323. //
  1324. // Returns: S_OK on success. Error code otherwise.
  1325. //
  1326. // Modifies: *pNewObject to return the IUmiObject interface
  1327. //
  1328. //----------------------------------------------------------------------------
  1329. STDMETHODIMP
  1330. CLDAPUmiObject::Create(
  1331. IUmiURL *pURL,
  1332. ULONG uFlags,
  1333. IUmiObject **ppNewObj
  1334. )
  1335. {
  1336. HRESULT hr;
  1337. LPWSTR pszClass = NULL, pszDN = NULL;
  1338. IDispatch *pDispObj = NULL;
  1339. if (!pURL) {
  1340. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1341. }
  1342. if (uFlags != 0) {
  1343. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  1344. }
  1345. hr = UrlToClassAndDn(pURL, &pszClass, &pszDN);
  1346. BAIL_ON_FAILURE(hr);
  1347. hr = _pIADsContainer->Create(pszClass, pszDN, &pDispObj);
  1348. BAIL_ON_FAILURE(hr);
  1349. hr = ((IUnknown *)pDispObj)->QueryInterface(
  1350. IID_IUmiObject,
  1351. (void **) ppNewObj
  1352. );
  1353. error:
  1354. if (pDispObj) {
  1355. pDispObj->Release();
  1356. }
  1357. if (pszClass) {
  1358. FreeADsStr(pszClass);
  1359. }
  1360. if (pszDN) {
  1361. FreeADsStr(pszDN);
  1362. }
  1363. if (FAILED(hr)) {
  1364. SetLastStatus(hr);
  1365. hr = MapHrToUmiError(hr);
  1366. }
  1367. RRETURN(hr);
  1368. }
  1369. //+---------------------------------------------------------------------------
  1370. // Function: CLDAPUmiObject::Move --- IUmiContainer support.
  1371. //
  1372. // Synopsis: Moves a specified object into the container.
  1373. //
  1374. // Arguments: uFlags - Reserved. Must be 0 for now.
  1375. // pOldURL - URL of the object to be moved.
  1376. // pNewURL - New URL of the object within the container.
  1377. // If NULL, then no name change is needed.
  1378. //
  1379. // Returns: S_OK on success. Error code otherwise.
  1380. //
  1381. // Modifies: N/A.
  1382. //
  1383. //----------------------------------------------------------------------------
  1384. STDMETHODIMP
  1385. CLDAPUmiObject::Move(
  1386. ULONG uFlags,
  1387. IUmiURL *pOldURL,
  1388. IUmiURL *pNewURL
  1389. )
  1390. {
  1391. HRESULT hr;
  1392. LPWSTR pszOldPath = NULL, pszNewPath = NULL, pszClass = NULL;
  1393. ULONGLONG ullPathType = 0;
  1394. IDispatch *pDispObj = NULL;
  1395. if (!_pIADsContainer) {
  1396. BAIL_ON_FAILURE(hr = E_NOTIMPL);
  1397. }
  1398. if (!pOldURL) {
  1399. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1400. }
  1401. //
  1402. // What flags should we support here ?
  1403. //
  1404. if (uFlags) {
  1405. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  1406. }
  1407. hr = UrlToLDAPPath(
  1408. pOldURL,
  1409. &pszOldPath
  1410. );
  1411. BAIL_ON_FAILURE(hr);
  1412. if (pNewURL) {
  1413. //
  1414. // Update code based on the path type.
  1415. //
  1416. hr = pNewURL->GetPathInfo(0, &ullPathType);
  1417. BAIL_ON_FAILURE(hr);
  1418. if (ullPathType == UMIPATH_INFO_RELATIVE_PATH) {
  1419. hr = UrlToClassAndDn(
  1420. pNewURL,
  1421. &pszClass,
  1422. &pszNewPath
  1423. );
  1424. BAIL_ON_FAILURE(hr);
  1425. }
  1426. else {
  1427. //
  1428. // Does this even make sense on a move ???
  1429. //
  1430. hr = UrlToLDAPPath(
  1431. pNewURL,
  1432. &pszNewPath
  1433. );
  1434. BAIL_ON_FAILURE(hr);
  1435. }
  1436. }
  1437. //
  1438. // At this point both the new and old path will be set correctly.
  1439. //
  1440. hr = _pIADsContainer->MoveHere(
  1441. pszOldPath,
  1442. pszNewPath,
  1443. &pDispObj
  1444. );
  1445. BAIL_ON_FAILURE(hr);
  1446. error:
  1447. if (pszOldPath) {
  1448. FreeADsStr(pszOldPath);
  1449. }
  1450. if (pszNewPath) {
  1451. FreeADsStr(pszNewPath);
  1452. }
  1453. if (pszClass) {
  1454. FreeADsStr(pszClass);
  1455. }
  1456. if (pDispObj) {
  1457. pDispObj->Release();
  1458. }
  1459. if (FAILED(hr)) {
  1460. SetLastStatus(hr);
  1461. hr = MapHrToUmiError(hr);
  1462. }
  1463. RRETURN(hr);
  1464. }
  1465. //+---------------------------------------------------------------------------
  1466. // Function: CLDAPUmiObject::CreateEnum --- IUmiContainer support.
  1467. //
  1468. // Synopsis: Creates an enumerator within a container. The enumerator is
  1469. // an IUmiCursor interface pointer. The caller can optionally set
  1470. // a filter on the cursor and then enumerate the contents of the
  1471. // container. The actual enumeration of the container does
  1472. // not happen in this function. It is deferred to the point
  1473. // when the cursor is used to enumerate the results.
  1474. //
  1475. // Arguments: pszEnumContext - Not used. Must be NULL.
  1476. // uFlags - Reserved. Must be 0 for now.
  1477. // TargetIID - Interface requested on enum has to be
  1478. // IUmiCursor for now.
  1479. // ppInterface - Return value for new enurator.
  1480. //
  1481. // Returns: S_OK on success. Error code otherwise.
  1482. //
  1483. // Modifies: *ppInterface to return the IUmiCursor interface
  1484. //
  1485. //----------------------------------------------------------------------------
  1486. STDMETHODIMP
  1487. CLDAPUmiObject::CreateEnum(
  1488. IUmiURL *pszEnumContext,
  1489. ULONG uFlags,
  1490. REFIID TargetIID,
  1491. LPVOID *ppInterface
  1492. )
  1493. {
  1494. HRESULT hr;
  1495. SetLastStatus(0);
  1496. //
  1497. // Validate args.
  1498. //
  1499. if (pszEnumContext || uFlags) {
  1500. //
  1501. // We do not support contexts currently.
  1502. //
  1503. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1504. }
  1505. if (!(TargetIID == IID_IUmiCursor)) {
  1506. //
  1507. // Type of cursor we do not support.
  1508. //
  1509. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1510. }
  1511. hr = CUmiCursor::CreateCursor(
  1512. _pIADsContainer,
  1513. TargetIID,
  1514. ppInterface
  1515. );
  1516. error:
  1517. if (FAILED(hr)) {
  1518. SetLastStatus(hr);
  1519. hr = MapHrToUmiError(hr);
  1520. }
  1521. RRETURN(hr);
  1522. }
  1523. //+---------------------------------------------------------------------------
  1524. // Function: CLDAPUmiObject::ExecQuery --- IUmiContainer support.
  1525. //
  1526. // Synopsis: Executes a query on this container.
  1527. //
  1528. // Arguments: pQuery - Pointer to the query to execute.
  1529. // uFlags - Reserved. Must be 0 for now.
  1530. // TargetIID - Interface requested.
  1531. // ppInterface - Return value for the cursor requested.
  1532. //
  1533. // Returns: S_OK on success. Error code otherwise.
  1534. //
  1535. // Modifies: *ppInterface to return interface pointer
  1536. //
  1537. //----------------------------------------------------------------------------
  1538. STDMETHODIMP
  1539. CLDAPUmiObject::ExecQuery(
  1540. IUmiQuery *pQuery,
  1541. ULONG uFlags,
  1542. REFIID TargetIID,
  1543. LPVOID *ppResult
  1544. )
  1545. {
  1546. HRESULT hr = S_OK;
  1547. CLDAPConObject *pConnection = NULL;
  1548. BSTR bstrADsPath = NULL;
  1549. SetLastStatus(0);
  1550. if (!ppResult
  1551. || !pQuery
  1552. || !(TargetIID == IID_IUmiCursor)
  1553. ) {
  1554. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1555. }
  1556. *ppResult = NULL;
  1557. if (uFlags != 0) {
  1558. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  1559. }
  1560. hr = this->_pIADs->get_ADsPath(&bstrADsPath);
  1561. BAIL_ON_FAILURE(hr);
  1562. //
  1563. // We want to pre-process this query and verify that it is
  1564. // valid if this is a SQL/WQL style query. This is a little
  1565. // bit of double effort but provides a much easier usage
  1566. // paradigm.
  1567. //
  1568. hr = VerifyIfQueryIsValid(pQuery);
  1569. BAIL_ON_FAILURE(hr);
  1570. hr = CLDAPConObject::CreateConnectionObject(
  1571. &pConnection,
  1572. this->_pLdapHandle
  1573. );
  1574. BAIL_ON_FAILURE(hr);
  1575. hr = CUmiCursor::CreateCursor(
  1576. pQuery,
  1577. pConnection,
  1578. (IUmiObject *) this,
  1579. bstrADsPath,
  1580. _pszLDAPServer,
  1581. _pszLDAPDn,
  1582. *_pCreds,
  1583. _dwPort,
  1584. TargetIID,
  1585. ppResult
  1586. );
  1587. BAIL_ON_FAILURE(hr);
  1588. error :
  1589. if (FAILED(hr)) {
  1590. if (*ppResult) {
  1591. ((IUnknown*)(*ppResult))->Release();
  1592. }
  1593. SetLastStatus(hr);
  1594. hr = MapHrToUmiError(hr);
  1595. }
  1596. if (bstrADsPath) {
  1597. SysFreeString(bstrADsPath);
  1598. }
  1599. if (pConnection) {
  1600. pConnection->Release();
  1601. }
  1602. RRETURN(hr);
  1603. }
  1604. //+---------------------------------------------------------------------------
  1605. // Function: CLDAPUmiObject::GetCLSIDForIID --- ICustomInterfaceFactory.
  1606. //
  1607. // Synopsis: Returns the CLSID corresponding to a given interface IID. If
  1608. // the interface is one of the interfaces implemented by the
  1609. // underlying LDAP object, then CLSID_LDAPObject is returned.
  1610. // If the IID is one of the interfaces implemented by an
  1611. // extension object, then the extension's CLSID is returned.
  1612. //
  1613. // Arguments: riid - Interface ID for which we want to find the CLSID.
  1614. // lFlags - Reserved. Must be 0.
  1615. // pCLSID - Returns the CLSID corresponding to the IID.
  1616. //
  1617. // Returns: S_OK on success. Error code otherwise.
  1618. //
  1619. // Modifies: *pCLSID to return CLSID.
  1620. //
  1621. //----------------------------------------------------------------------------
  1622. STDMETHODIMP
  1623. CLDAPUmiObject::GetCLSIDForIID(
  1624. REFIID riid,
  1625. long lFlags,
  1626. CLSID *pCLSID
  1627. )
  1628. {
  1629. HRESULT hr = S_OK;
  1630. IUnknown *pUnknown = NULL;
  1631. SetLastStatus(0);
  1632. if ( (lFlags) || (!pCLSID) ) {
  1633. SetLastStatus(E_INVALIDARG);
  1634. RRETURN(E_INVALIDARG);
  1635. }
  1636. if (_pExtMgr) {
  1637. //
  1638. // Check if there is any extension that supports this IID.
  1639. //
  1640. hr = _pExtMgr->GetCLSIDForIID(
  1641. riid,
  1642. lFlags,
  1643. pCLSID
  1644. );
  1645. if (SUCCEEDED(hr)) {
  1646. RRETURN(S_OK);
  1647. }
  1648. }
  1649. //
  1650. // check if the underlying LDAP object supports this IID
  1651. //
  1652. hr = _pUnkInner->QueryInterface(riid, (void **) &pUnknown);
  1653. if (SUCCEEDED(hr)) {
  1654. pUnknown->Release();
  1655. memcpy(pCLSID, &CLSID_LDAPObject, sizeof(GUID));
  1656. RRETURN(S_OK);
  1657. }
  1658. if (FAILED(hr)) {
  1659. SetLastStatus(hr);
  1660. hr = MapHrToUmiError(hr);
  1661. }
  1662. RRETURN(hr);
  1663. }
  1664. //+---------------------------------------------------------------------------
  1665. // Function: GetObjectByCLSID --- IUmiCustomInterfaceFactory support.
  1666. //
  1667. // Synopsis: Returns a pointer to a requested interface on the object
  1668. // specified by a CLSID. The object specified by the CLSID is
  1669. // aggregated by the specified outer unknown. The interface
  1670. // returned is a non-delegating interface on the object.
  1671. //
  1672. // Arguments: clsid - CLSID of object supporting requested interface.
  1673. // pUnkOuter - Aggregating outer unknown.
  1674. // dwClsContext - Context for running executable code.
  1675. // riid - Interface requested.
  1676. // lFlags - Reserved. Must be 0.
  1677. // ppInterface - Returns requested interface.
  1678. //
  1679. // Returns: S_OK on success. Error code otherwise.
  1680. //
  1681. // Modifies: *ppInterface to return requested interface
  1682. //
  1683. //----------------------------------------------------------------------------
  1684. STDMETHODIMP
  1685. CLDAPUmiObject::GetObjectByCLSID(
  1686. CLSID clsid,
  1687. IUnknown *pUnkOuter,
  1688. DWORD dwClsContext,
  1689. REFIID riid,
  1690. long lFlags,
  1691. void **ppInterface
  1692. )
  1693. {
  1694. HRESULT hr = S_OK;
  1695. IUnknown *pCurOuterUnk = NULL;
  1696. SetLastStatus(0);
  1697. if ( (lFlags != 0)
  1698. || (!pUnkOuter)
  1699. || (!ppInterface)
  1700. || (dwClsContext != CLSCTX_INPROC_SERVER) )
  1701. {
  1702. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1703. }
  1704. //
  1705. // ensure outer unknown specified is same as what is on the LDAP object
  1706. //
  1707. if (_fOuterUnkSet) {
  1708. pCurOuterUnk = _pCoreObj->GetOuterUnknown();
  1709. if (pCurOuterUnk != pUnkOuter) {
  1710. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1711. }
  1712. }
  1713. //
  1714. // The interface requested has to be IUnknown if there is
  1715. // an outer uknown ptr.
  1716. //
  1717. if (!IsEqualIID(riid, IID_IUnknown)) {
  1718. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1719. }
  1720. if (!IsEqualCLSID(clsid, CLSID_LDAPObject)) {
  1721. //
  1722. // has to be a CLSID of an extension object
  1723. //
  1724. if (_pExtMgr) {
  1725. hr = _pExtMgr->GetObjectByCLSID(
  1726. clsid,
  1727. pUnkOuter,
  1728. riid,
  1729. ppInterface
  1730. );
  1731. BAIL_ON_FAILURE(hr);
  1732. //
  1733. // successfully got the interface
  1734. //
  1735. _pCoreObj->SetOuterUnknown(pUnkOuter);
  1736. _fOuterUnkSet = TRUE;
  1737. RRETURN(S_OK);
  1738. }
  1739. else {
  1740. BAIL_ON_FAILURE(hr = E_INVALIDARG); // bad CLSID
  1741. }
  1742. }
  1743. //
  1744. // CLSID == CLSID_LDAPObject. This has to be an interface on the
  1745. // underlying LDAP object. Check if the LDAP object supports this IID.
  1746. //
  1747. hr = _pUnkInner->QueryInterface(riid, ppInterface);
  1748. if (SUCCEEDED(hr)) {
  1749. //
  1750. // successfully got the interface
  1751. //
  1752. _pCoreObj->SetOuterUnknown(pUnkOuter);
  1753. _fOuterUnkSet = TRUE;
  1754. RRETURN(S_OK);
  1755. }
  1756. error:
  1757. if (FAILED(hr)) {
  1758. SetLastStatus(hr);
  1759. hr = MapHrToUmiError(hr);
  1760. }
  1761. RRETURN(hr);
  1762. }
  1763. //+---------------------------------------------------------------------------
  1764. // Function: GetCLSIDForNames --- ICustomInterfaceFactory support.
  1765. //
  1766. // Synopsis: Returns the CLSID of the object that supports a specified
  1767. // method/property. Also returns DISPIDs for the property/method.
  1768. //
  1769. // Arguments: rgszNames - Names to be mapped.
  1770. // cNames - Number of names to be mapped.
  1771. // lcid - Locale in which to interpret the names.
  1772. // rgDispId - Returns DISPID.
  1773. // lFlags - Reserved. Must be 0.
  1774. // pCLSID - Returns CLSID of object supporting this
  1775. // property/method.
  1776. //
  1777. // Returns: S_OK on success. Error code otherwise.
  1778. //
  1779. // Modifies: *pCLSID to return the CLSID.
  1780. // *rgDispId to return the DISPIDs.
  1781. //
  1782. //----------------------------------------------------------------------------
  1783. STDMETHODIMP
  1784. CLDAPUmiObject::GetCLSIDForNames(
  1785. LPOLESTR *rgszNames,
  1786. UINT cNames,
  1787. LCID lcid,
  1788. DISPID *rgDispId,
  1789. long lFlags,
  1790. CLSID *pCLSID
  1791. )
  1792. {
  1793. HRESULT hr = S_OK;
  1794. IDispatch *pDispatch = NULL;
  1795. SetLastStatus(0);
  1796. if ( (lFlags != 0) || (!pCLSID) ) {
  1797. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1798. }
  1799. if (cNames == 0) {
  1800. RRETURN(S_OK);
  1801. }
  1802. if ( (!rgszNames) || (!rgDispId) ) {
  1803. RRETURN(S_OK);
  1804. }
  1805. if (_pExtMgr) {
  1806. //
  1807. // check if there is any extension which supports this IID
  1808. //
  1809. hr = _pExtMgr->GetCLSIDForNames(
  1810. rgszNames,
  1811. cNames,
  1812. lcid,
  1813. rgDispId,
  1814. lFlags,
  1815. pCLSID
  1816. );
  1817. if (SUCCEEDED(hr)) {
  1818. //
  1819. // successfully got the CLSID and DISPIDs
  1820. //
  1821. RRETURN(S_OK);
  1822. }
  1823. }
  1824. //
  1825. // Check if the underlying LDAP object supports this name
  1826. //
  1827. hr = _pUnkInner->QueryInterface(IID_IDispatch, (void **) &pDispatch);
  1828. if (FAILED(hr)) {
  1829. BAIL_ON_FAILURE(hr = E_FAIL);
  1830. }
  1831. hr = pDispatch->GetIDsOfNames(
  1832. IID_NULL,
  1833. rgszNames,
  1834. cNames,
  1835. lcid,
  1836. rgDispId
  1837. );
  1838. if (SUCCEEDED(hr)) {
  1839. pDispatch->Release();
  1840. memcpy(pCLSID, &CLSID_LDAPObject, sizeof(GUID));
  1841. RRETURN(S_OK);
  1842. }
  1843. error:
  1844. if (pDispatch) {
  1845. pDispatch->Release();
  1846. }
  1847. if (FAILED(hr)) {
  1848. SetLastStatus(hr);
  1849. hr = MapHrToUmiError(hr);
  1850. }
  1851. RRETURN(hr);
  1852. }
  1853. //+---------------------------------------------------------------------------
  1854. // Function: GetOption --- IADsObjOptPrivate support.
  1855. //
  1856. // Synopsis: Private interface for internal use, this function is used to
  1857. // return the ldap handle if applicable.
  1858. //
  1859. // Arguments: dwOption - Option being read.
  1860. // pValue - Return pointer to hold value of option.
  1861. //
  1862. // Returns: S_OK on success. Error code otherwise.
  1863. //
  1864. // Modifies: pValue to return requested option.
  1865. //
  1866. //----------------------------------------------------------------------------
  1867. STDMETHODIMP
  1868. CLDAPUmiObject::GetOption(
  1869. DWORD dwOption,
  1870. void *pValue
  1871. )
  1872. {
  1873. if (dwOption != LDP_CACHE_ENTRY) {
  1874. RRETURN(E_FAIL);
  1875. }
  1876. else {
  1877. *((PADSLDP *) pValue) = _pLdapHandle;
  1878. RRETURN(S_OK);
  1879. }
  1880. }
  1881. //+---------------------------------------------------------------------------
  1882. // Function: SetOption --- IADsObjOptPrivate support.
  1883. //
  1884. // Synopsis: Private interface for internal use - NOTIMPL.
  1885. //
  1886. // Arguments: dwOption - Option being set
  1887. // pValue - Value of option being set.
  1888. //
  1889. // Returns: S_OK on success. Error code otherwise.
  1890. //
  1891. // Modifies: pValue to return requested option.
  1892. //
  1893. //----------------------------------------------------------------------------
  1894. STDMETHODIMP
  1895. CLDAPUmiObject::SetOption(
  1896. DWORD dwOption,
  1897. void *pValue
  1898. )
  1899. {
  1900. RRETURN(E_NOTIMPL);
  1901. }
  1902. //+---------------------------------------------------------------------------
  1903. // Function: CopyToHelper --- Helper routine protected scope.
  1904. //
  1905. // Synopsis: Copies the attributes on the source object over to the
  1906. // destination object.
  1907. //
  1908. // Arguments: pUmiObjSr --- Source object.
  1909. // pUmiObjDest --- Destination object to copy attributes to.
  1910. // uFlags --- Only 0 is supported currently.
  1911. // fMarkAsUpdate --- Flag indicating if we should mark the
  1912. // attributes on dest as update rather than 0.
  1913. // fCopyIntfProps --- Only false is supported currently.
  1914. //
  1915. // Returns: S_OK on success. Error code otherwise.
  1916. //
  1917. // Modifies: pUmiObjDest
  1918. //
  1919. //----------------------------------------------------------------------------
  1920. HRESULT
  1921. CLDAPUmiObject::CopyToHelper(
  1922. IUmiObject *pUmiSrcObj,
  1923. IUmiObject *pUmiDestObj,
  1924. ULONG uFlags,
  1925. BOOL fMarkAsUpdate, // default is TRUE
  1926. BOOL fCopyIntfProps // default is FALSE
  1927. )
  1928. {
  1929. HRESULT hr = S_OK;
  1930. ULONG ulLastError = S_OK;
  1931. PUMI_PROPERTY_VALUES pUmiPropValsList = NULL;
  1932. DWORD dwCount;
  1933. if (!pUmiSrcObj || !pUmiDestObj || uFlags) {
  1934. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1935. }
  1936. //
  1937. // We need to get the list of properties from the src object.
  1938. //
  1939. hr = pUmiSrcObj->GetProps(
  1940. NULL,
  1941. 0,
  1942. UMI_FLAG_GETPROPS_NAMES,
  1943. &pUmiPropValsList
  1944. );
  1945. BAIL_ON_FAILURE(hr);
  1946. for (dwCount = 0; dwCount < pUmiPropValsList->uCount; dwCount++) {
  1947. //
  1948. // We need to walk the list, get each properties name and then
  1949. // for each property get its values from the source and put them
  1950. // on the destination.
  1951. //
  1952. LPWSTR pszTempStr =
  1953. pUmiPropValsList->pPropArray[dwCount].pszPropertyName;
  1954. PUMI_PROPERTY_VALUES pCurProp = NULL;
  1955. if (!pszTempStr) {
  1956. //
  1957. // Name should never be NULL.
  1958. //
  1959. BAIL_ON_FAILURE(hr = E_FAIL);
  1960. }
  1961. //
  1962. // We need to add a check for the SD cause we want to copy that over
  1963. // as a binary blob to prevent unnecessary traffic.
  1964. //
  1965. // Should change the get to use the force flag once it is done.
  1966. //
  1967. hr = pUmiSrcObj->Get(
  1968. pszTempStr,
  1969. 0,
  1970. &pCurProp
  1971. );
  1972. if (FAILED(hr)) {
  1973. pUmiSrcObj->GetLastStatus(0, &ulLastError, IID_IUnknown, NULL);
  1974. BAIL_ON_FAILURE(hr);
  1975. }
  1976. hr = pUmiDestObj->Put(
  1977. pszTempStr,
  1978. 0x8000000,
  1979. pCurProp
  1980. );
  1981. //
  1982. // Irrespective of this operation success/failure we need to free
  1983. // the contents of pCurProp.
  1984. //
  1985. pUmiSrcObj->FreeMemory(0, (void *) pCurProp);
  1986. if (FAILED(hr)) {
  1987. pUmiDestObj->GetLastStatus(0, &ulLastError, IID_IUnknown, NULL);
  1988. BAIL_ON_FAILURE(hr);
  1989. }
  1990. } // for each property in the source object.
  1991. error:
  1992. if (pUmiPropValsList) {
  1993. pUmiSrcObj->FreeMemory(0, (void *) pUmiPropValsList);
  1994. }
  1995. if (FAILED(hr)) {
  1996. if (ulLastError) {
  1997. SetLastStatus(ulLastError);
  1998. }
  1999. else {
  2000. SetLastStatus(hr);
  2001. }
  2002. hr = MapHrToUmiError(hr);
  2003. }
  2004. RRETURN(hr);
  2005. }
  2006. //+---------------------------------------------------------------------------
  2007. // Function: VerifyifQueryIsValid --- Helper routine protected scope.
  2008. //
  2009. // Synopsis: Copies the attributes on the source object over to the
  2010. // destination object.
  2011. //
  2012. // Arguments: pUmiQeury --- Query object to validate.
  2013. //
  2014. // Returns: S_OK on success. Error code from parser otherwise.
  2015. //
  2016. // Modifies: N/A.
  2017. //
  2018. //----------------------------------------------------------------------------
  2019. HRESULT
  2020. CLDAPUmiObject::VerifyIfQueryIsValid(
  2021. IUmiQuery *pUmiQuery
  2022. )
  2023. {
  2024. HRESULT hr = S_OK;
  2025. ULONG ulLangBufSize = 100 * sizeof(WCHAR);
  2026. ULONG ulQueryBufSize = MAX_PATH * sizeof(WCHAR);
  2027. WCHAR pszLangBuf[100];
  2028. WCHAR szQueryText[MAX_PATH];
  2029. LPWSTR pszQueryText = szQueryText;
  2030. IWbemQuery *pQueryParser = NULL;
  2031. ULONG ulFeatures[] = {
  2032. WMIQ_LF1_BASIC_SELECT,
  2033. WMIQ_LF2_CLASS_NAME_IN_QUERY,
  2034. WMIQ_LF6_ORDER_BY,
  2035. WMIQ_LF24_UMI_EXTENSIONS
  2036. };
  2037. //
  2038. // We need to look at the query language if the language is SQL,
  2039. // then we need to go through and convert the SQL settings to
  2040. // properties on the intfPropList of the query.
  2041. //
  2042. hr = pUmiQuery->GetQuery(
  2043. &ulLangBufSize,
  2044. pszLangBuf,
  2045. &ulQueryBufSize,
  2046. pszQueryText
  2047. );
  2048. if (hr == E_OUTOFMEMORY ) {
  2049. //
  2050. // Means there was insufficient length in the buffers.
  2051. //
  2052. if (ulQueryBufSize > (MAX_PATH * sizeof(WCHAR))) {
  2053. pszQueryText = (LPWSTR) AllocADsMem(
  2054. ulQueryBufSize + sizeof(WCHAR)
  2055. );
  2056. if (pszQueryText) {
  2057. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  2058. }
  2059. }
  2060. hr = pUmiQuery->GetQuery(
  2061. &ulLangBufSize,
  2062. pszLangBuf,
  2063. &ulQueryBufSize,
  2064. pszQueryText
  2065. );
  2066. }
  2067. BAIL_ON_FAILURE(hr);
  2068. if (*pszLangBuf) {
  2069. if (!_wcsicmp(L"SQL", pszLangBuf)
  2070. || !_wcsicmp(L"WQL", pszLangBuf)
  2071. ) {
  2072. //
  2073. // Create the WBEM parser object and verify the query is valid.
  2074. //
  2075. hr = CoCreateInstance(
  2076. CLSID_WbemQuery,
  2077. NULL,
  2078. CLSCTX_INPROC_SERVER,
  2079. IID_IWbemQuery,
  2080. (LPVOID *) &pQueryParser
  2081. );
  2082. BAIL_ON_FAILURE(hr);
  2083. //
  2084. // Set the query into the parser and try and parse the query.
  2085. //
  2086. hr = pQueryParser->SetLanguageFeatures(
  2087. 0,
  2088. sizeof(ulFeatures)/sizeof(ULONG),
  2089. ulFeatures
  2090. );
  2091. BAIL_ON_FAILURE(hr);
  2092. hr = pQueryParser->Parse(L"SQL", pszQueryText, 0);
  2093. BAIL_ON_FAILURE(hr);
  2094. } // if the language is SQL
  2095. } // if the language has been set
  2096. else {
  2097. //
  2098. // No language ???.
  2099. //
  2100. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  2101. }
  2102. error:
  2103. if (FAILED(hr)) {
  2104. SetLastStatus(hr);
  2105. //
  2106. // For now do not map error as we want error from parser
  2107. // until such time as new error codes are added to umi.
  2108. // hr = MapHrToUmiError(hr);
  2109. }
  2110. if (pQueryParser) {
  2111. pQueryParser->Release();
  2112. }
  2113. if (pszQueryText && pszQueryText != szQueryText) {
  2114. FreeADsMem(pszQueryText);
  2115. }
  2116. return hr;
  2117. }
  2118. //+---------------------------------------------------------------------------
  2119. // Function: VerifyIfClassMatches --- Helper routine protected scope.
  2120. //
  2121. // Synopsis: Makes sure the class name of the object matches the class
  2122. // asked for.
  2123. //
  2124. // Arguments: pszClass --- Class requested.
  2125. // pUnk --- Ptr to IUnk of Umi Object.
  2126. // lGenus --- Is the parent a schema object or not ?
  2127. //
  2128. // Returns: S_OK on success. Any failure error code or E_INVALIDARG.
  2129. //
  2130. // Modifies: N/A.
  2131. //
  2132. //----------------------------------------------------------------------------
  2133. HRESULT
  2134. CLDAPUmiObject::VerifyIfClassMatches(
  2135. LPWSTR pszClass,
  2136. IUnknown * pUnk,
  2137. LONG lGenus
  2138. )
  2139. {
  2140. HRESULT hr = S_OK;
  2141. IUmiObject *pUmiObject = NULL;
  2142. IUmiPropList *pPropList = NULL;
  2143. UMI_PROPERTY_VALUES *pPropVals = NULL;
  2144. //
  2145. // For now the schema will always succeed cause we have no
  2146. // way to verify the parent class. We will fail the GetObject
  2147. // calls on the schema objects with bad paths.
  2148. //
  2149. if (lGenus == UMI_GENUS_CLASS) {
  2150. RRETURN(hr);
  2151. }
  2152. //
  2153. // Get hold of the IUmiObject and then the proplist from it.
  2154. //
  2155. hr = pUnk->QueryInterface(
  2156. IID_IUmiObject,
  2157. (void **) &pUmiObject
  2158. );
  2159. BAIL_ON_FAILURE(hr);
  2160. hr = pUmiObject->GetInterfacePropList(
  2161. 0,
  2162. &pPropList
  2163. );
  2164. BAIL_ON_FAILURE(hr);
  2165. hr = pPropList->Get(L"__CLASS", 0, &pPropVals);
  2166. BAIL_ON_FAILURE(hr);
  2167. //
  2168. // Should have one value that we need to compare
  2169. //
  2170. if (!pPropVals
  2171. || (pPropVals->uCount != 1)
  2172. || !pPropVals->pPropArray
  2173. || !pPropVals->pPropArray[0].pUmiValue
  2174. || !pPropVals->pPropArray[0].pUmiValue->pszStrValue
  2175. || !pPropVals->pPropArray[0].pUmiValue->pszStrValue[0]
  2176. ) {
  2177. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  2178. }
  2179. //
  2180. // Failure if the names do not match.
  2181. //
  2182. if (_wcsicmp(
  2183. pPropVals->pPropArray[0].pUmiValue->pszStrValue[0],
  2184. pszClass
  2185. )
  2186. ) {
  2187. hr = E_INVALIDARG;
  2188. }
  2189. error:
  2190. if (pUmiObject) {
  2191. pUmiObject->Release();
  2192. }
  2193. if (pPropList) {
  2194. pPropList->Release();
  2195. }
  2196. if (pPropVals) {
  2197. FreeMemory(0, (void*)pPropVals);
  2198. }
  2199. RRETURN(hr);
  2200. }