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.

2576 lines
69 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. The methods are
  9. // encapsulated in one object. This object holds a pointer to
  10. // the inner unknown of the corresponding WinNT object.
  11. // The methods of IUmiContainer are also implemented on this
  12. // same object, but will only be used if the underlying WinNT
  13. // object is a container.
  14. //
  15. // History: 03-06-00 SivaramR Created.
  16. //
  17. //----------------------------------------------------------------------------
  18. #include "winnt.hxx"
  19. //----------------------------------------------------------------------------
  20. // Function: CUmiObject
  21. //
  22. // Synopsis: Constructor. Initializes member variable.
  23. //
  24. // Arguments: None
  25. //
  26. // Returns: Nothing
  27. //
  28. // Modifies: Nothing
  29. //
  30. //----------------------------------------------------------------------------
  31. CUmiObject::CUmiObject(void)
  32. {
  33. m_pIntfProps = NULL;
  34. m_pObjProps = NULL;
  35. m_pUnkInner = NULL;
  36. m_pIADs = NULL;
  37. m_pIADsContainer = NULL;
  38. m_ulErrorStatus = 0;
  39. m_pCoreObj = NULL;
  40. m_pExtMgr = NULL;
  41. m_fOuterUnkSet = FALSE;
  42. m_pPropCache = NULL;
  43. m_fRefreshDone = FALSE;
  44. }
  45. //----------------------------------------------------------------------------
  46. // Function: ~CUmiObject
  47. //
  48. // Synopsis: Destructor. Frees member variables.
  49. //
  50. // Arguments: None
  51. //
  52. // Returns: Nothing
  53. //
  54. // Modifies: Nothing
  55. //
  56. //----------------------------------------------------------------------------
  57. CUmiObject::~CUmiObject(void)
  58. {
  59. if(m_pIntfProps != NULL)
  60. m_pIntfProps->Release();
  61. if(m_pObjProps != NULL)
  62. delete m_pObjProps;
  63. if(m_pUnkInner != NULL)
  64. m_pUnkInner->Release();
  65. //
  66. // m_pIADs and m_pIADsContainer may now delegate to an outer unknown if
  67. // if the ADSI object has been aggregated in GetObjectByCLSID
  68. // subsequent to creation. Hence, we should not call Release() on either
  69. // of these pointers. Instead, call Release() on m_pUnkInner since this
  70. // is guaranteed to be a pointer to the non-delegating IUnknown.
  71. //
  72. if(m_pIADsContainer != NULL)
  73. m_pUnkInner->Release();
  74. if(m_pIADs != NULL)
  75. m_pUnkInner->Release();
  76. if(m_pPropCache != NULL)
  77. delete m_pPropCache;
  78. }
  79. //----------------------------------------------------------------------------
  80. // Function: FInit
  81. //
  82. // Synopsis: Initializes UMI object.
  83. //
  84. // Arguments:
  85. //
  86. // Credentials Credentials stored in the underlying WinNT object
  87. // pSchema Pointer to schema for this object
  88. // dwSchemaSize Size of schema array
  89. // pPropCache Pointer to property cache for this object
  90. // pUnkInner Pointer to inner unknown of underlying WinNT object
  91. // pExtMgr Pointer to extension manager of underlying WinNT object
  92. // pCoreObj Pointer to the core object of underlying WinNT object
  93. // pClassInfo Pointer to class information if this object is a class object.
  94. // NULL otherwise.
  95. //
  96. // Returns: S_OK on success. Error code otherwise.
  97. //
  98. // Modifies: Nothing
  99. //
  100. //----------------------------------------------------------------------------
  101. HRESULT CUmiObject::FInit(
  102. CWinNTCredentials& Credentials,
  103. PPROPERTYINFO pSchema,
  104. DWORD dwSchemaSize,
  105. CPropertyCache *pPropertyCache,
  106. IUnknown *pUnkInner,
  107. CADsExtMgr *pExtMgr,
  108. CCoreADsObject *pCoreObj,
  109. CLASSINFO *pClassInfo
  110. )
  111. {
  112. HRESULT hr = S_OK;
  113. CUmiPropList *pIntfProps = NULL;
  114. ADsAssert(pCoreObj != NULL); // extension manager may be NULL for some
  115. // WinNT objects
  116. if(pPropertyCache != NULL) {
  117. // some WinNT objects don't have a property cache associated with them.
  118. // Namespace and schema objects are examples. For these, we might
  119. // create a proeprty cache in the 'else' clause below. Otherwise, we
  120. // return UMI_E_NOTIMPL from IUmiPropList methods since m_pObjProps will be
  121. // NULL for these objects.
  122. ADsAssert( (pSchema != NULL) && (dwSchemaSize > 0) &&
  123. (pUnkInner != NULL) );
  124. // Initialize property list for object properties
  125. m_pObjProps = new CUmiPropList(pSchema, dwSchemaSize);
  126. if(NULL == m_pObjProps)
  127. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  128. hr = m_pObjProps->FInit(pPropertyCache, NULL);
  129. BAIL_ON_FAILURE(hr);
  130. }
  131. else if(pSchema != NULL) {
  132. // Property, class, schema and syntax objects do not have a cache
  133. // associated with them. But, they support a number of properties through
  134. // IDispatch. We want to expose these through UMI. So create a property
  135. // cache and populate it with these read-only properties. Thus,
  136. // m_pObjProps will be NULL only for namespace objects.
  137. ADsAssert( (pUnkInner != NULL) && (dwSchemaSize > 0) );
  138. hr = CreateObjectProperties(
  139. pSchema,
  140. dwSchemaSize,
  141. pUnkInner,
  142. pCoreObj
  143. );
  144. BAIL_ON_FAILURE(hr);
  145. }
  146. // Initialize property list for interface properties
  147. pIntfProps = new CUmiPropList(ObjClass, g_dwObjClassSize);
  148. if(NULL == pIntfProps)
  149. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  150. hr = pIntfProps->FInit(NULL, g_UmiObjUnImplProps);
  151. BAIL_ON_FAILURE(hr);
  152. hr = pIntfProps->QueryInterface(
  153. IID_IUmiPropList,
  154. (void **) &m_pIntfProps
  155. );
  156. BAIL_ON_FAILURE(hr);
  157. // DECLARE_STD_REFCOUNTING initializes the refcount to 1. Call Release()
  158. // on the created object, so that releasing the interface pointer will
  159. // free the object.
  160. pIntfProps->Release();
  161. m_pUnkInner = pUnkInner;
  162. // Get pointers to IADs and IADsContainer interfaces on WinNT object
  163. hr = m_pUnkInner->QueryInterface(
  164. IID_IADsContainer,
  165. (void **) &m_pIADsContainer
  166. );
  167. if(FAILED(hr))
  168. m_pIADsContainer = NULL;
  169. hr = m_pUnkInner->QueryInterface(
  170. IID_IADs,
  171. (void **) &m_pIADs
  172. );
  173. if(FAILED(hr))
  174. m_pIADs = NULL;
  175. else {
  176. hr = pIntfProps->SetStandardProperties(m_pIADs, pCoreObj);
  177. BAIL_ON_FAILURE(hr);
  178. }
  179. pIntfProps->SetClassInfo(pClassInfo);
  180. // set the property count in the interface property cache
  181. hr = pIntfProps->SetPropertyCount(dwSchemaSize);
  182. BAIL_ON_FAILURE(hr);
  183. m_pExtMgr = pExtMgr;
  184. m_pCoreObj = pCoreObj;
  185. m_pCreds = &Credentials;
  186. RRETURN(S_OK);
  187. error:
  188. if(m_pObjProps != NULL)
  189. delete m_pObjProps;
  190. if(m_pIntfProps != NULL)
  191. m_pIntfProps->Release();
  192. else if(pIntfProps != NULL)
  193. delete pIntfProps;
  194. if(m_pIADsContainer != NULL)
  195. m_pIADsContainer->Release();
  196. if(m_pIADs != NULL)
  197. m_pIADs->Release();
  198. // make sure destructor doesn't free these again
  199. m_pObjProps = NULL;
  200. m_pIntfProps = NULL;
  201. m_pIADsContainer = NULL;
  202. m_pIADs = NULL;
  203. m_pUnkInner = NULL;
  204. RRETURN(hr);
  205. }
  206. //----------------------------------------------------------------------------
  207. // Function: CreateObjectProperties
  208. //
  209. // Synopsis: Creates a property cache and populates it with the properties
  210. // supported on the WinNT object's IDispatch interface. This is
  211. // used to expose properties on property, class and syntax objects
  212. // through UMI.
  213. //
  214. // Arguments:
  215. //
  216. // pSchema Pointer to schema for this object
  217. // dwSchemaSize Size of schema array
  218. // pUnkInner Pointer to inner unknown of underlying WinNT object
  219. // pCoreObj Pointer to the core object of the WinNT object
  220. //
  221. // Returns: S_OK on success. Error code otherwise.
  222. //
  223. // Modifies: Nothing
  224. //
  225. //----------------------------------------------------------------------------
  226. HRESULT CUmiObject::CreateObjectProperties(
  227. PPROPERTYINFO pSchema,
  228. DWORD dwSchemaSize,
  229. IUnknown *pUnkInner,
  230. CCoreADsObject *pCoreObj
  231. )
  232. {
  233. HRESULT hr = S_OK;
  234. IDispatch *pDispatch = NULL;
  235. DWORD dwIndex = 0;
  236. DISPID DispId;
  237. DISPPARAMS DispParams = {NULL, NULL, 0, 0};
  238. VARIANT var;
  239. CPropertyCache *pPropCache = NULL;
  240. ADsAssert( (pSchema != NULL) && (dwSchemaSize > 0) &&
  241. (pUnkInner != NULL) && (pCoreObj != NULL) );
  242. hr = CPropertyCache::createpropertycache(
  243. pSchema,
  244. dwSchemaSize,
  245. pCoreObj,
  246. &pPropCache);
  247. BAIL_ON_FAILURE(hr);
  248. hr = pUnkInner->QueryInterface(
  249. IID_IDispatch,
  250. (void **) &pDispatch
  251. );
  252. BAIL_ON_FAILURE(hr);
  253. for(dwIndex = 0; dwIndex < dwSchemaSize; dwIndex++) {
  254. hr = pDispatch->GetIDsOfNames(
  255. IID_NULL,
  256. &pSchema[dwIndex].szPropertyName,
  257. 1,
  258. LOCALE_SYSTEM_DEFAULT,
  259. &DispId
  260. );
  261. BAIL_ON_FAILURE(hr);
  262. hr = pDispatch->Invoke(
  263. DispId,
  264. IID_NULL,
  265. LOCALE_SYSTEM_DEFAULT,
  266. DISPATCH_PROPERTYGET,
  267. &DispParams,
  268. &var,
  269. NULL,
  270. NULL
  271. );
  272. BAIL_ON_FAILURE(hr);
  273. hr = GenericPutPropertyManager(
  274. pPropCache,
  275. pSchema,
  276. dwSchemaSize,
  277. pSchema[dwIndex].szPropertyName,
  278. var,
  279. FALSE
  280. );
  281. VariantClear(&var);
  282. // If there is a multivalued ADSI interface property that has no values
  283. // (such as MandatoryProperties/Containment on a schema object), the
  284. // call to Invoke above returns a variant which has a safearray with
  285. // 0 elements in it. The call to GenericPutPropertyManager will fail
  286. // with E_ADS_BAD_PARAMETER in this case. In this case, don't store
  287. // anything in the property cache for this property. Trying to fetch
  288. // it later will return UMI_E_NOT_FOUND.
  289. if(hr != E_ADS_BAD_PARAMETER)
  290. BAIL_ON_FAILURE(hr);
  291. }
  292. // Mark all properties as "not modified", since the client really hasn't
  293. // updated the cache, though we have.
  294. pPropCache->ClearModifiedFlags();
  295. // Initialize property list for object properties
  296. m_pObjProps = new CUmiPropList(pSchema, dwSchemaSize);
  297. if(NULL == m_pObjProps)
  298. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  299. hr = m_pObjProps->FInit(pPropCache, NULL);
  300. BAIL_ON_FAILURE(hr);
  301. m_pPropCache = pPropCache;
  302. pDispatch->Release();
  303. RRETURN(S_OK);
  304. error:
  305. if(pPropCache != NULL)
  306. delete pPropCache;
  307. if(pDispatch != NULL)
  308. pDispatch->Release();
  309. if(m_pObjProps != NULL) {
  310. delete m_pObjProps;
  311. m_pObjProps = NULL;
  312. }
  313. RRETURN(hr);
  314. }
  315. //----------------------------------------------------------------------------
  316. // Function: QueryInterface
  317. //
  318. // Synopsis: Implements QI for the UMI object.
  319. //
  320. // Arguments
  321. //
  322. // iid interface requested
  323. // ppInterface Returns pointer to interface requested. NULL if interface
  324. // is not supported.
  325. //
  326. // Returns: S_OK on success. Error code otherwise.
  327. //
  328. // Modifies: *ppInterface to return interface pointer
  329. //
  330. //----------------------------------------------------------------------------
  331. STDMETHODIMP CUmiObject::QueryInterface(
  332. REFIID iid,
  333. LPVOID *ppInterface
  334. )
  335. {
  336. HRESULT hr = S_OK;
  337. IUnknown *pTmpIntfPtr = NULL;
  338. if(NULL == ppInterface)
  339. RRETURN(E_INVALIDARG);
  340. *ppInterface = NULL;
  341. if(IsEqualIID(iid, IID_IUnknown))
  342. *ppInterface = (IUmiObject *) this;
  343. else if(IsEqualIID(iid, IID_IUmiObject))
  344. *ppInterface = (IUmiObject *) this;
  345. else if(IsEqualIID(iid, IID_IUmiContainer)) {
  346. // check if underlying WinNT object is a container
  347. if(m_pIADsContainer != NULL)
  348. *ppInterface = (IUmiContainer *) this;
  349. else
  350. RRETURN(E_NOINTERFACE);
  351. }
  352. else if(IsEqualIID(iid, IID_IUmiBaseObject))
  353. *ppInterface = (IUmiBaseObject *) this;
  354. else if(IsEqualIID(iid, IID_IUmiPropList))
  355. *ppInterface = (IUmiPropList *) this;
  356. else if(IsEqualIID(iid, IID_IUmiCustomInterfaceFactory))
  357. *ppInterface = (IUmiCustomInterfaceFactory *) this;
  358. else if(IsEqualIID(iid, IID_IUmiADSIPrivate))
  359. *ppInterface = (IUmiADSIPrivate *) this;
  360. else
  361. RRETURN(E_NOINTERFACE);
  362. AddRef();
  363. RRETURN(S_OK);
  364. }
  365. //----------------------------------------------------------------------------
  366. // Function: Clone
  367. //
  368. // Synopsis: Implements IUmiObject::Clone. Creates a new uncommitted object
  369. // and copies over all properties from the source to destination.
  370. // The source may be Refresh()ed if necessary.
  371. //
  372. // Arguments
  373. //
  374. // uFlags Flags for Clone(). Must be 0 for now.
  375. // riid Interface ID requested on the cloned object
  376. // pCopy Returns interface pointer requested
  377. //
  378. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  379. //
  380. // Modifies: *pCopy to return the interface requested.
  381. //
  382. //----------------------------------------------------------------------------
  383. STDMETHODIMP CUmiObject::Clone(
  384. ULONG uFlags,
  385. REFIID riid,
  386. LPVOID *pCopy
  387. )
  388. {
  389. HRESULT hr = UMI_S_NO_ERROR;
  390. BSTR bstrADsPath = NULL, bstrParent = NULL;
  391. BSTR bstrClass = NULL, bstrName = NULL;
  392. IUnknown *pUnknown = NULL, *pUnkParent = NULL;
  393. IDispatch *pDispatch = NULL;
  394. IADsContainer *pIADsCont = NULL;
  395. IUmiObject *pUmiObj = NULL;
  396. IUmiADSIPrivate *pUmiPrivate = NULL;
  397. SetLastStatus(0);
  398. if(uFlags != 0)
  399. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  400. if(NULL == pCopy)
  401. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  402. if( (NULL == m_pCoreObj) || (NULL == m_pIADs) )
  403. // shouldn't happen, but just being paranoid
  404. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  405. *pCopy = NULL;
  406. if(ADS_OBJECT_BOUND == m_pCoreObj->GetObjectState()) {
  407. // object exists on server
  408. if(FALSE == m_fRefreshDone) {
  409. hr = m_pCoreObj->ImplicitGetInfo();
  410. BAIL_ON_FAILURE(hr);
  411. }
  412. hr = m_pIADs->get_ADsPath(&bstrADsPath);
  413. BAIL_ON_FAILURE(hr);
  414. m_pCreds->SetUmiFlag();
  415. hr = GetObject(
  416. bstrADsPath,
  417. (LPVOID *) &pUnknown,
  418. *m_pCreds
  419. );
  420. m_pCreds->ResetUmiFlag();
  421. BAIL_ON_FAILURE(hr);
  422. hr = pUnknown->QueryInterface(IID_IUmiObject, (LPVOID *) &pUmiObj);
  423. BAIL_ON_FAILURE(hr);
  424. }
  425. else if(ADS_OBJECT_UNBOUND == m_pCoreObj->GetObjectState()) {
  426. // object not yet committed to server. We don't have to refresh the
  427. // cache since the object is not yet committed. Get the parent container
  428. // and call Create() on it.
  429. hr = m_pIADs->get_Parent(&bstrParent);
  430. BAIL_ON_FAILURE(hr);
  431. m_pCreds->SetUmiFlag();
  432. hr = GetObject(
  433. bstrParent,
  434. (LPVOID *) &pUnkParent,
  435. *m_pCreds
  436. );
  437. m_pCreds->ResetUmiFlag();
  438. BAIL_ON_FAILURE(hr);
  439. hr = pUnkParent->QueryInterface(
  440. IID_IUmiADSIPrivate,
  441. (LPVOID *) &pUmiPrivate
  442. );
  443. BAIL_ON_FAILURE(hr);
  444. hr = pUmiPrivate->GetContainer((void **) &pIADsCont);
  445. BAIL_ON_FAILURE(hr);
  446. ADsAssert(pIADsCont != NULL);
  447. // get the class and name of this object
  448. hr = m_pIADs->get_Class(&bstrClass);
  449. BAIL_ON_FAILURE(hr);
  450. hr = m_pIADs->get_Name(&bstrName);
  451. BAIL_ON_FAILURE(hr);
  452. pUmiPrivate->SetUmiFlag();
  453. // now Create() the cloned object
  454. hr = pIADsCont->Create(
  455. bstrClass,
  456. bstrName,
  457. &pDispatch
  458. );
  459. pUmiPrivate->ResetUmiFlag();
  460. BAIL_ON_FAILURE(hr);
  461. hr = pDispatch->QueryInterface(IID_IUmiObject, (LPVOID *) &pUmiObj);
  462. BAIL_ON_FAILURE(hr);
  463. }
  464. else // unknown state, shouldn't happen.
  465. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  466. // copy over the attributes in the property cache
  467. hr = CopyPropCache(pUmiObj, (IUmiObject *) this);
  468. BAIL_ON_FAILURE(hr);
  469. hr = pUmiObj->QueryInterface(riid, pCopy);
  470. BAIL_ON_FAILURE(hr);
  471. error:
  472. if(bstrADsPath != NULL)
  473. SysFreeString(bstrADsPath);
  474. if(bstrParent != NULL)
  475. SysFreeString(bstrParent);
  476. if(bstrClass != NULL)
  477. SysFreeString(bstrClass);
  478. if(bstrName != NULL)
  479. SysFreeString(bstrName);
  480. if(pUnknown != NULL)
  481. pUnknown->Release();
  482. if(pUnkParent != NULL)
  483. pUnkParent->Release();
  484. if(pDispatch != NULL)
  485. pDispatch->Release();
  486. if(pIADsCont != NULL)
  487. pIADsCont->Release();
  488. if(pUmiObj != NULL)
  489. pUmiObj->Release();
  490. if(pUmiPrivate != NULL)
  491. pUmiPrivate->Release();
  492. if(FAILED(hr))
  493. SetLastStatus(hr);
  494. RRETURN(MapHrToUmiError(hr));
  495. }
  496. //----------------------------------------------------------------------------
  497. // Function: CopyPropCache
  498. //
  499. // Synopsis: Copies the cache of one IUmiObject to another IUmiObject.
  500. //
  501. // Arguments
  502. //
  503. // pDest IUmiObject interface pointer of destination
  504. // pSrc IUmiObject interface pointer of source
  505. //
  506. // Returns: UMI_S_NO_ERROR on success. Error code otherwise
  507. //
  508. // Modifies: Nothing
  509. //
  510. //----------------------------------------------------------------------------
  511. HRESULT CUmiObject::CopyPropCache(
  512. IUmiObject *pDest,
  513. IUmiObject *pSrc
  514. )
  515. {
  516. HRESULT hr = UMI_S_NO_ERROR;
  517. ULONG ulIndex = 0, ulPutFlag = 0;
  518. LPWSTR pszPropName = NULL;
  519. UMI_PROPERTY_VALUES *pUmiPropNames = NULL, *pUmiProp = NULL;
  520. ADsAssert( (pDest != NULL) && (pSrc != NULL) );
  521. // get the names of the properties in cache.
  522. hr = pSrc->GetProps(
  523. NULL,
  524. 0,
  525. UMI_FLAG_GETPROPS_NAMES,
  526. &pUmiPropNames
  527. );
  528. BAIL_ON_FAILURE(hr);
  529. // copy over each property
  530. for(ulIndex = 0; ulIndex < pUmiPropNames->uCount; ulIndex++) {
  531. pszPropName = pUmiPropNames->pPropArray[ulIndex].pszPropertyName;
  532. if(NULL == pszPropName)
  533. // shouldn't happen, just being paranoid.
  534. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  535. hr = pSrc->Get(
  536. pszPropName,
  537. UMI_FLAG_PROVIDER_CACHE,
  538. &pUmiProp
  539. );
  540. BAIL_ON_FAILURE(hr);
  541. // if the property was updated in cache, we need to mark it as updated
  542. // in the destination object's cache also. Otherwise, mark the
  543. // property as clean in the destination object's cache.
  544. if(UMI_OPERATION_UPDATE == pUmiProp->pPropArray->uOperationType)
  545. ulPutFlag = 0;
  546. else
  547. ulPutFlag = UMI_INTERNAL_FLAG_MARK_AS_CLEAN;
  548. pUmiProp->pPropArray->uOperationType = UMI_OPERATION_UPDATE;
  549. hr = pDest->Put(
  550. pszPropName,
  551. ulPutFlag,
  552. pUmiProp
  553. );
  554. BAIL_ON_FAILURE(hr);
  555. pSrc->FreeMemory(0, pUmiProp);
  556. pUmiProp = NULL;
  557. }
  558. pSrc->FreeMemory(0, pUmiPropNames);
  559. error:
  560. if(FAILED(hr)) {
  561. if(pUmiProp != NULL)
  562. pSrc->FreeMemory(0, pUmiProp);
  563. if(pUmiPropNames != NULL)
  564. pSrc->FreeMemory(0, pUmiPropNames);
  565. }
  566. RRETURN(hr);
  567. }
  568. //----------------------------------------------------------------------------
  569. // Function: Refresh
  570. //
  571. // Synopsis: Implements IUmiObject::Refresh. Calls GetInfo on WinNT
  572. // object to refresh the cache. GetInfoEx is implemented by
  573. // just calling GetInfo in the WinNT provider.
  574. //
  575. // Arguments
  576. //
  577. // uFlags Flags for Refresh. Must be 0 for now.
  578. // uNameCount Number of attributes to refresh
  579. // pszNames Names of attributes to refresh
  580. //
  581. // Returns: UMI_S_NO_ERROR on success. Error code otherwise
  582. //
  583. // Modifies: Nothing
  584. //
  585. //----------------------------------------------------------------------------
  586. HRESULT CUmiObject::Refresh(
  587. ULONG uFlags,
  588. ULONG uNameCount,
  589. LPWSTR *pszNames
  590. )
  591. {
  592. ULONG i = 0;
  593. HRESULT hr = UMI_S_NO_ERROR;
  594. SetLastStatus(0);
  595. if( (uFlags != UMI_FLAG_REFRESH_ALL) &&
  596. (uFlags != UMI_FLAG_REFRESH_PARTIAL) )
  597. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  598. if( ((NULL == pszNames) && (uNameCount != 0)) ||
  599. ((pszNames != NULL) && (0 == uNameCount)) )
  600. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  601. // ensure all attributes are valid
  602. for(i = 0; i < uNameCount; i++)
  603. if(NULL == pszNames[i])
  604. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  605. if(UMI_FLAG_REFRESH_PARTIAL == uFlags) {
  606. // do an implicit GetInfo on the WinNT object
  607. if(NULL == m_pCoreObj)
  608. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  609. if(uNameCount != 0) {
  610. // can't specify UMI_FLAG_REFRESH_PARTIAL and attribute names
  611. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  612. }
  613. hr = m_pCoreObj->ImplicitGetInfo();
  614. BAIL_ON_FAILURE(hr);
  615. }
  616. else {
  617. if(NULL == m_pIADs)
  618. // shouldn't happen, but just being paranoid
  619. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  620. hr = m_pIADs->GetInfo();
  621. BAIL_ON_FAILURE(hr);
  622. }
  623. m_fRefreshDone = TRUE;
  624. error:
  625. if(FAILED(hr))
  626. SetLastStatus(hr);
  627. RRETURN(MapHrToUmiError(hr));
  628. }
  629. //----------------------------------------------------------------------------
  630. // Function: Commit
  631. //
  632. // Synopsis: Implements IUmiObject::Commit. Calls SetInfo on WinNT
  633. // object to commit changes made to the cache.
  634. //
  635. // Arguments
  636. //
  637. // uFlags Flags for Refresh.
  638. //
  639. // Returns: UMI_S_NO_ERROR on success. Error code otherwise
  640. //
  641. // Modifies: Nothing
  642. //
  643. //----------------------------------------------------------------------------
  644. HRESULT CUmiObject::Commit(ULONG uFlags)
  645. {
  646. HRESULT hr = UMI_S_NO_ERROR;
  647. SetLastStatus(0);
  648. // CIMOM always calls with UMI_DONT_COMMIT_SECURITY_DESCRIPTOR set. Ignore
  649. // this flag as it is not meaningful on WinNT.
  650. if( (uFlags != 0) && (uFlags != UMI_DONT_COMMIT_SECURITY_DESCRIPTOR) )
  651. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  652. if(NULL == m_pIADs)
  653. // shouldn't happen, but just being paranoid
  654. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  655. hr = m_pIADs->SetInfo();
  656. BAIL_ON_FAILURE(hr);
  657. error:
  658. if(FAILED(hr))
  659. SetLastStatus(hr);
  660. RRETURN(MapHrToUmiError(hr));
  661. }
  662. //----------------------------------------------------------------------------
  663. // IUmiPropList methods
  664. //
  665. // These are implemented by invoking the corresponding method in the
  666. // CUmiPropList object that implements object properties. For a description
  667. // of these methods, refer to cumiprop.cxx
  668. //
  669. //----------------------------------------------------------------------------
  670. HRESULT CUmiObject::Put(
  671. LPCWSTR pszName,
  672. ULONG uFlags,
  673. UMI_PROPERTY_VALUES *pProp
  674. )
  675. {
  676. HRESULT hr = UMI_S_NO_ERROR;
  677. ULONG ulStatus = 0;
  678. IID iid;
  679. SetLastStatus(0);
  680. if(NULL == m_pObjProps) {
  681. SetLastStatus(UMI_E_NOTIMPL);
  682. RRETURN(UMI_E_NOTIMPL);
  683. }
  684. hr = m_pObjProps->Put(
  685. pszName,
  686. uFlags,
  687. pProp
  688. );
  689. if(FAILED(hr)) {
  690. m_pObjProps->GetLastStatus( // ignore error return
  691. 0,
  692. &ulStatus,
  693. iid,
  694. NULL
  695. );
  696. SetLastStatus(ulStatus);
  697. }
  698. RRETURN(MapHrToUmiError(hr));
  699. }
  700. HRESULT CUmiObject::Get(
  701. LPCWSTR pszName,
  702. ULONG uFlags,
  703. UMI_PROPERTY_VALUES **ppProp
  704. )
  705. {
  706. HRESULT hr = UMI_S_NO_ERROR;
  707. ULONG ulStatus = 0;
  708. IID iid;
  709. SetLastStatus(0);
  710. if(NULL == m_pObjProps) {
  711. SetLastStatus(UMI_E_NOTIMPL);
  712. RRETURN(UMI_E_NOTIMPL);
  713. }
  714. hr = m_pObjProps->Get(
  715. pszName,
  716. uFlags,
  717. ppProp
  718. );
  719. if(FAILED(hr)) {
  720. m_pObjProps->GetLastStatus( // ignore error return
  721. 0,
  722. &ulStatus,
  723. iid,
  724. NULL
  725. );
  726. SetLastStatus(ulStatus);
  727. }
  728. RRETURN(MapHrToUmiError(hr));
  729. }
  730. HRESULT CUmiObject::GetAs(
  731. LPCWSTR pszName,
  732. ULONG uFlags,
  733. ULONG uCoercionType,
  734. UMI_PROPERTY_VALUES **ppProp
  735. )
  736. {
  737. HRESULT hr = UMI_S_NO_ERROR;
  738. ULONG ulStatus = 0;
  739. IID iid;
  740. SetLastStatus(0);
  741. if(NULL == m_pObjProps) {
  742. SetLastStatus(UMI_E_NOTIMPL);
  743. RRETURN(UMI_E_NOTIMPL);
  744. }
  745. hr = m_pObjProps->GetAs(
  746. pszName,
  747. uFlags,
  748. uCoercionType,
  749. ppProp
  750. );
  751. if(FAILED(hr)) {
  752. m_pObjProps->GetLastStatus( // ignore error return
  753. 0,
  754. &ulStatus,
  755. iid,
  756. NULL
  757. );
  758. SetLastStatus(ulStatus);
  759. }
  760. RRETURN(MapHrToUmiError(hr));
  761. }
  762. HRESULT CUmiObject::FreeMemory(
  763. ULONG uReserved,
  764. LPVOID pMem
  765. )
  766. {
  767. HRESULT hr = UMI_S_NO_ERROR;
  768. ULONG ulStatus = 0;
  769. IID iid;
  770. SetLastStatus(0);
  771. if(NULL == m_pObjProps) {
  772. SetLastStatus(UMI_E_NOTIMPL);
  773. RRETURN(UMI_E_NOTIMPL);
  774. }
  775. hr = m_pObjProps->FreeMemory(
  776. uReserved,
  777. pMem
  778. );
  779. if(FAILED(hr)) {
  780. m_pObjProps->GetLastStatus( // ignore error return
  781. 0,
  782. &ulStatus,
  783. iid,
  784. NULL
  785. );
  786. SetLastStatus(ulStatus);
  787. }
  788. RRETURN(MapHrToUmiError(hr));
  789. }
  790. HRESULT CUmiObject::GetAt(
  791. LPCWSTR pszName,
  792. ULONG uFlags,
  793. ULONG uBufferLength,
  794. LPVOID pExistingMem
  795. )
  796. {
  797. HRESULT hr = UMI_S_NO_ERROR;
  798. ULONG ulStatus = 0;
  799. IID iid;
  800. SetLastStatus(0);
  801. if(NULL == m_pObjProps) {
  802. SetLastStatus(UMI_E_NOTIMPL);
  803. RRETURN(UMI_E_NOTIMPL);
  804. }
  805. hr = m_pObjProps->GetAt(
  806. pszName,
  807. uFlags,
  808. uBufferLength,
  809. pExistingMem
  810. );
  811. if(FAILED(hr)) {
  812. m_pObjProps->GetLastStatus( // ignore error return
  813. 0,
  814. &ulStatus,
  815. iid,
  816. NULL
  817. );
  818. SetLastStatus(ulStatus);
  819. }
  820. RRETURN(MapHrToUmiError(hr));
  821. }
  822. HRESULT CUmiObject::GetProps(
  823. LPCWSTR *pszNames,
  824. ULONG uNameCount,
  825. ULONG uFlags,
  826. UMI_PROPERTY_VALUES **pProps
  827. )
  828. {
  829. HRESULT hr = UMI_S_NO_ERROR;
  830. ULONG ulStatus = 0;
  831. IID iid;
  832. SetLastStatus(0);
  833. if(NULL == m_pObjProps) {
  834. SetLastStatus(UMI_E_NOTIMPL);
  835. RRETURN(UMI_E_NOTIMPL);
  836. }
  837. hr = m_pObjProps->GetProps(
  838. pszNames,
  839. uNameCount,
  840. uFlags,
  841. pProps
  842. );
  843. if(FAILED(hr)) {
  844. m_pObjProps->GetLastStatus( // ignore error return
  845. 0,
  846. &ulStatus,
  847. iid,
  848. NULL
  849. );
  850. SetLastStatus(ulStatus);
  851. }
  852. RRETURN(MapHrToUmiError(hr));
  853. }
  854. HRESULT CUmiObject::PutProps(
  855. LPCWSTR *pszNames,
  856. ULONG uNameCount,
  857. ULONG uFlags,
  858. UMI_PROPERTY_VALUES *pProps
  859. )
  860. {
  861. HRESULT hr = UMI_S_NO_ERROR;
  862. ULONG ulStatus = 0;
  863. IID iid;
  864. SetLastStatus(0);
  865. if(NULL == m_pObjProps) {
  866. SetLastStatus(UMI_E_NOTIMPL);
  867. RRETURN(UMI_E_NOTIMPL);
  868. }
  869. hr = m_pObjProps->PutProps(
  870. pszNames,
  871. uNameCount,
  872. uFlags,
  873. pProps
  874. );
  875. if(FAILED(hr)) {
  876. m_pObjProps->GetLastStatus( // ignore error return
  877. 0,
  878. &ulStatus,
  879. iid,
  880. NULL
  881. );
  882. SetLastStatus(ulStatus);
  883. }
  884. RRETURN(MapHrToUmiError(hr));
  885. }
  886. HRESULT CUmiObject::PutFrom(
  887. LPCWSTR pszName,
  888. ULONG uFlags,
  889. ULONG uBufferLength,
  890. LPVOID pExistingMem
  891. )
  892. {
  893. HRESULT hr = UMI_S_NO_ERROR;
  894. ULONG ulStatus = 0;
  895. IID iid;
  896. SetLastStatus(0);
  897. if(NULL == m_pObjProps) {
  898. SetLastStatus(UMI_E_NOTIMPL);
  899. RRETURN(UMI_E_NOTIMPL);
  900. }
  901. hr = m_pObjProps->PutFrom(
  902. pszName,
  903. uFlags,
  904. uBufferLength,
  905. pExistingMem
  906. );
  907. if(FAILED(hr)) {
  908. m_pObjProps->GetLastStatus( // ignore error return
  909. 0,
  910. &ulStatus,
  911. iid,
  912. NULL
  913. );
  914. SetLastStatus(ulStatus);
  915. }
  916. RRETURN(MapHrToUmiError(hr));
  917. }
  918. HRESULT CUmiObject::Delete(
  919. LPCWSTR pszName,
  920. ULONG uFlags
  921. )
  922. {
  923. HRESULT hr = UMI_S_NO_ERROR;
  924. ULONG ulStatus = 0;
  925. IID iid;
  926. SetLastStatus(0);
  927. if(NULL == m_pObjProps) {
  928. SetLastStatus(UMI_E_NOTIMPL);
  929. RRETURN(UMI_E_NOTIMPL);
  930. }
  931. hr = m_pObjProps->Delete(
  932. pszName,
  933. uFlags
  934. );
  935. if(FAILED(hr)) {
  936. m_pObjProps->GetLastStatus( // ignore error return
  937. 0,
  938. &ulStatus,
  939. iid,
  940. NULL
  941. );
  942. SetLastStatus(ulStatus);
  943. }
  944. RRETURN(MapHrToUmiError(hr));
  945. }
  946. //----------------------------------------------------------------------------
  947. // Function: GetLastStatus
  948. //
  949. // Synopsis: Returns status or error code from the last operation. Currently
  950. // only numeric status is returned i.e, no error objects are
  951. // returned. Implements IUmiBaseObject::GetLastStatus().
  952. //
  953. // Arguments:
  954. //
  955. // uFlags Reserved. Must be 0 for now.
  956. // puSpecificStatus Returns status code
  957. // riid IID requested. Ignored currently.
  958. // pStatusObj Returns interface requested. Always returns NULL currently.
  959. //
  960. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  961. //
  962. // Modifies: *puSpecificStatus to return status code.
  963. //
  964. //----------------------------------------------------------------------------
  965. HRESULT CUmiObject::GetLastStatus(
  966. ULONG uFlags,
  967. ULONG *puSpecificStatus,
  968. REFIID riid,
  969. LPVOID *pStatusObj
  970. )
  971. {
  972. if(pStatusObj != NULL)
  973. *pStatusObj = NULL;
  974. if(puSpecificStatus != NULL)
  975. *puSpecificStatus = 0;
  976. if(uFlags != 0)
  977. RRETURN(UMI_E_INVALID_FLAGS);
  978. if(NULL == puSpecificStatus)
  979. RRETURN(UMI_E_INVALIDARG);
  980. *puSpecificStatus = m_ulErrorStatus;
  981. RRETURN(UMI_S_NO_ERROR);
  982. }
  983. //----------------------------------------------------------------------------
  984. // Function: SetLastStatus
  985. //
  986. // Synopsis: Sets the status of the last operation.
  987. //
  988. // Arguments:
  989. //
  990. // ulStatus Status to be set
  991. //
  992. // Returns: Nothing
  993. //
  994. // Modifies: Nothing
  995. //
  996. //----------------------------------------------------------------------------
  997. void CUmiObject::SetLastStatus(ULONG ulStatus)
  998. {
  999. m_ulErrorStatus = ulStatus;
  1000. return;
  1001. }
  1002. //----------------------------------------------------------------------------
  1003. // Function: GetInterfacePropList
  1004. //
  1005. // Synopsis: Returns a pointer to the interface property list implementation
  1006. // for the connection object. Implements
  1007. // IUmiBaseObject::GetInterfacePropList().
  1008. //
  1009. // Arguments:
  1010. //
  1011. // uFlags Reserved. Must be 0 for now.
  1012. // pPropList Returns pointer to IUmiPropertyList interface
  1013. //
  1014. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  1015. //
  1016. // Modifies: *pPropList to return interface pointer
  1017. //
  1018. //----------------------------------------------------------------------------
  1019. HRESULT CUmiObject::GetInterfacePropList(
  1020. ULONG uFlags,
  1021. IUmiPropList **pPropList
  1022. )
  1023. {
  1024. HRESULT hr = UMI_S_NO_ERROR;
  1025. SetLastStatus(0);
  1026. if(uFlags != 0)
  1027. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  1028. if(NULL == pPropList)
  1029. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  1030. ADsAssert(m_pIntfProps != NULL);
  1031. hr = m_pIntfProps->QueryInterface(IID_IUmiPropList, (void **) pPropList);
  1032. error:
  1033. if(FAILED(hr))
  1034. SetLastStatus(hr);
  1035. RRETURN(MapHrToUmiError(hr));
  1036. }
  1037. //----------------------------------------------------------------------------
  1038. // Function: IsRelativePath
  1039. //
  1040. // Synopsis: Checks if a path is relative or absolute
  1041. //
  1042. // Arguments:
  1043. //
  1044. // pURL IUmiURL interface containing the path
  1045. //
  1046. // Returns: TRUE if the path is relative, FALSE otherwise
  1047. //
  1048. // Modifies: Nothing
  1049. //
  1050. //----------------------------------------------------------------------------
  1051. BOOL CUmiObject::IsRelativePath(IUmiURL *pURL)
  1052. {
  1053. HRESULT hr = S_OK;
  1054. ULONGLONG PathType = 0;
  1055. ADsAssert(pURL != NULL);
  1056. hr = pURL->GetPathInfo(
  1057. 0,
  1058. &PathType
  1059. );
  1060. BAIL_ON_FAILURE(hr);
  1061. if(PathType & UMIPATH_INFO_RELATIVE_PATH)
  1062. RRETURN(TRUE);
  1063. else
  1064. RRETURN(FALSE);
  1065. error:
  1066. RRETURN(FALSE);
  1067. }
  1068. //----------------------------------------------------------------------------
  1069. // Function: GetClassAndPath
  1070. //
  1071. // Synopsis: Obtains the class name and path from a relative UMI path.
  1072. // The class name and value are mandatory. The key is optional.
  1073. //
  1074. // Arguments:
  1075. //
  1076. // pszPath String containing the path
  1077. // ppszClass Returns string containing the class name
  1078. // ppszPath Returns string containing the path
  1079. //
  1080. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  1081. //
  1082. // Modifies: *ppszClass and *ppszPath
  1083. //
  1084. //----------------------------------------------------------------------------
  1085. HRESULT CUmiObject::GetClassAndPath(
  1086. LPWSTR pszPath,
  1087. LPWSTR *ppszClass,
  1088. LPWSTR *ppszPath
  1089. )
  1090. {
  1091. HRESULT hr = UMI_S_NO_ERROR;
  1092. WCHAR *pSeparator = NULL, *pValSeparator = NULL;
  1093. ADsAssert( (pszPath != NULL) && (ppszClass != NULL) &&
  1094. (ppszPath != NULL) );
  1095. *ppszClass = NULL;
  1096. *ppszPath = NULL;
  1097. // look for the '=' in the relative path
  1098. if(NULL == (pValSeparator = wcschr(pszPath, VALUE_SEPARATOR)))
  1099. BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH);
  1100. *pValSeparator = L'\0';
  1101. *ppszPath = AllocADsStr(pValSeparator+1);
  1102. if(NULL == *ppszPath)
  1103. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  1104. if(NULL == (pSeparator = wcschr(pszPath, CLASS_SEPARATOR))) {
  1105. // path does not have a key in it
  1106. *ppszClass = AllocADsStr(pszPath);
  1107. if(NULL == *ppszClass)
  1108. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  1109. }
  1110. else {
  1111. // path has a key. Make sure it is "Name".
  1112. *pSeparator = L'\0';
  1113. if(_wcsicmp(pSeparator+1, WINNT_KEY_NAME))
  1114. BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH);
  1115. *ppszClass = AllocADsStr(pszPath);
  1116. if(NULL == *ppszClass)
  1117. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  1118. }
  1119. RRETURN(UMI_S_NO_ERROR);
  1120. error:
  1121. if(*ppszPath != NULL)
  1122. FreeADsStr(*ppszPath);
  1123. if(*ppszClass != NULL)
  1124. FreeADsStr(*ppszClass);
  1125. *ppszPath = *ppszClass = NULL;
  1126. RRETURN(hr);
  1127. }
  1128. //----------------------------------------------------------------------------
  1129. // Function: Open
  1130. //
  1131. // Synopsis: Opens the object specified by a URL. URL has to be a relative
  1132. // UMI path. Implements IUmiContainer::Open().
  1133. //
  1134. // Arguments:
  1135. //
  1136. // pURL Pointer to an IUmiURL interface
  1137. // uFlags Reserved. Must be 0 for now.
  1138. // TargetIID Interface requested
  1139. // ppInterface Returns pointer to interface requested
  1140. //
  1141. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  1142. //
  1143. // Modifies: *ppInterface to return interface pointer
  1144. //
  1145. //----------------------------------------------------------------------------
  1146. STDMETHODIMP CUmiObject::Open(
  1147. IUmiURL *pURL,
  1148. ULONG uFlags,
  1149. REFIID TargetIID,
  1150. LPVOID *ppInterface
  1151. )
  1152. {
  1153. BOOL fIsRelPath = FALSE;
  1154. HRESULT hr = UMI_S_NO_ERROR;
  1155. WCHAR pszUrl[MAX_URL+1];
  1156. WCHAR *pszLongUrl = pszUrl;
  1157. ULONG ulUrlLen = MAX_URL;
  1158. WCHAR *pszClass = NULL, *pszPath = NULL;
  1159. IDispatch *pIDispatch = NULL;
  1160. SetLastStatus(0);
  1161. if(uFlags != 0)
  1162. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  1163. if( (NULL == pURL) || (NULL == ppInterface) )
  1164. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  1165. if(NULL == m_pIADsContainer)
  1166. // shouldn't happen, but just in case...
  1167. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  1168. // Get the path from the URL
  1169. hr = pURL->Get(0, &ulUrlLen, pszUrl);
  1170. if(WBEM_E_BUFFER_TOO_SMALL == hr) {
  1171. // need to allocate more memory for URL
  1172. pszLongUrl = (WCHAR *) AllocADsMem(ulUrlLen * sizeof(WCHAR));
  1173. if(NULL == pszLongUrl)
  1174. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  1175. hr = pURL->Get(0, &ulUrlLen, pszLongUrl);
  1176. }
  1177. BAIL_ON_FAILURE(hr);
  1178. // Check if the path is relative or absolute
  1179. fIsRelPath = IsRelativePath(pURL);
  1180. if(TRUE == fIsRelPath) {
  1181. // check if the caller specified the class as part of the path
  1182. hr = GetClassAndPath(pszLongUrl, &pszClass, &pszPath);
  1183. BAIL_ON_FAILURE(hr);
  1184. m_pCreds->SetUmiFlag();
  1185. hr = m_pIADsContainer->GetObject(
  1186. pszClass,
  1187. pszPath,
  1188. &pIDispatch
  1189. );
  1190. m_pCreds->ResetUmiFlag();
  1191. BAIL_ON_FAILURE(hr);
  1192. hr = pIDispatch->QueryInterface(
  1193. TargetIID,
  1194. ppInterface
  1195. );
  1196. BAIL_ON_FAILURE(hr);
  1197. } // if(TRUE == fIsRelPath
  1198. else {
  1199. BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH);
  1200. }
  1201. error:
  1202. if(pIDispatch != NULL)
  1203. pIDispatch->Release();
  1204. if(pszClass != NULL)
  1205. FreeADsMem(pszClass);
  1206. if(pszPath != NULL)
  1207. FreeADsMem(pszPath);
  1208. if(pszLongUrl != pszUrl)
  1209. FreeADsMem(pszLongUrl);
  1210. if(FAILED(hr))
  1211. SetLastStatus(hr);
  1212. RRETURN(MapHrToUmiError(hr));
  1213. }
  1214. //----------------------------------------------------------------------------
  1215. // Function: PutObject
  1216. //
  1217. // Synopsis: Commits an object into the container. Not implemented currently.
  1218. // Implements IUmiContainer::Put().
  1219. //
  1220. // Arguments:
  1221. //
  1222. // uFlags Reserved. Must be 0 for now.
  1223. // TargetIID IID of nterface pointer sent in
  1224. // pInterface Interface pointer sent in
  1225. //
  1226. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  1227. //
  1228. // Modifies: *ppInterface to return interface pointer
  1229. //
  1230. //----------------------------------------------------------------------------
  1231. STDMETHODIMP CUmiObject::PutObject(
  1232. ULONG uFlags,
  1233. REFIID TargetIID,
  1234. LPVOID pInterface
  1235. )
  1236. {
  1237. SetLastStatus(UMI_E_NOTIMPL);
  1238. RRETURN(UMI_E_NOTIMPL);
  1239. }
  1240. //----------------------------------------------------------------------------
  1241. // Function: DeleteObject
  1242. //
  1243. // Synopsis: Deletes the object specified by the relative UMI path.
  1244. // Implements IUmiContainer::Delete().
  1245. //
  1246. // Arguments:
  1247. //
  1248. // pURL Pointer to an IUmiURL interface
  1249. // uFlags Reserved. Must be 0 for now.
  1250. //
  1251. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  1252. //
  1253. // Modifies: Nothing
  1254. //
  1255. //----------------------------------------------------------------------------
  1256. STDMETHODIMP CUmiObject::DeleteObject(
  1257. IUmiURL *pURL,
  1258. ULONG uFlags
  1259. )
  1260. {
  1261. ULONG ulUrlLen = MAX_URL;
  1262. WCHAR pszUrl[MAX_URL+1], *pszClass = NULL, *pszPath = NULL;
  1263. WCHAR *pszLongUrl = pszUrl;
  1264. BOOL fIsRelPath = FALSE;
  1265. HRESULT hr = UMI_S_NO_ERROR;
  1266. SetLastStatus(0);
  1267. if(uFlags != 0)
  1268. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  1269. if(NULL == pURL)
  1270. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  1271. if(NULL == m_pIADsContainer)
  1272. // shouldn't happen, but just in case...
  1273. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  1274. // Get the path from the URL
  1275. hr = pURL->Get(0, &ulUrlLen, pszUrl);
  1276. if(WBEM_E_BUFFER_TOO_SMALL == hr) {
  1277. // need to allocate more memory for URL
  1278. pszLongUrl = (WCHAR *) AllocADsMem(ulUrlLen * sizeof(WCHAR));
  1279. if(NULL == pszLongUrl)
  1280. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  1281. hr = pURL->Get(0, &ulUrlLen, pszLongUrl);
  1282. }
  1283. BAIL_ON_FAILURE(hr);
  1284. // Check if the path is relative or absolute
  1285. fIsRelPath = IsRelativePath(pURL);
  1286. if(TRUE == fIsRelPath) {
  1287. // check if the caller specified the class as part of the path
  1288. hr = GetClassAndPath(pszLongUrl, &pszClass, &pszPath);
  1289. BAIL_ON_FAILURE(hr);
  1290. m_pCreds->SetUmiFlag();
  1291. hr = m_pIADsContainer->Delete(
  1292. pszClass,
  1293. pszPath
  1294. );
  1295. m_pCreds->ResetUmiFlag();
  1296. BAIL_ON_FAILURE(hr);
  1297. } // if(TRUE == fIsRelPath
  1298. else {
  1299. BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH);
  1300. }
  1301. error:
  1302. if(pszClass != NULL)
  1303. FreeADsMem(pszClass);
  1304. if(pszPath != NULL)
  1305. FreeADsMem(pszPath);
  1306. if(pszLongUrl != pszUrl)
  1307. FreeADsMem(pszLongUrl);
  1308. if(FAILED(hr))
  1309. SetLastStatus(hr);
  1310. RRETURN(MapHrToUmiError(hr));
  1311. }
  1312. //----------------------------------------------------------------------------
  1313. // Function: Create
  1314. //
  1315. // Synopsis: Creates the object specified by the relative UMI path.
  1316. // Implements IUmiContainer::Create().
  1317. //
  1318. // Arguments:
  1319. //
  1320. // pURL Pointer to an IUmiURL interface
  1321. // uFlags Reserved. Must be 0 for now.
  1322. // ppNewObj Returns pointer to IUmiObject interface on new object
  1323. //
  1324. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  1325. //
  1326. // Modifies: *pNewObject to return the IUmiObject interface
  1327. //
  1328. //----------------------------------------------------------------------------
  1329. STDMETHODIMP CUmiObject::Create(
  1330. IUmiURL *pURL,
  1331. ULONG uFlags,
  1332. IUmiObject **ppNewObj
  1333. )
  1334. {
  1335. ULONG ulUrlLen = MAX_URL;
  1336. WCHAR pszUrl[MAX_URL+1], *pszClass = NULL, *pszPath = NULL;
  1337. WCHAR *pszLongUrl = pszUrl;
  1338. BOOL fIsRelPath = FALSE;
  1339. HRESULT hr = UMI_S_NO_ERROR;
  1340. IDispatch *pIDispatch = NULL;
  1341. SetLastStatus(0);
  1342. if(uFlags != 0)
  1343. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  1344. if( (NULL == pURL) || (NULL == ppNewObj) )
  1345. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  1346. if(NULL == m_pIADsContainer)
  1347. // shouldn't happen, but just in case...
  1348. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  1349. // Get the path from the URL
  1350. hr = pURL->Get(0, &ulUrlLen, pszUrl);
  1351. if(WBEM_E_BUFFER_TOO_SMALL == hr) {
  1352. // need to allocate more memory for URL
  1353. pszLongUrl = (WCHAR *) AllocADsMem(ulUrlLen * sizeof(WCHAR));
  1354. if(NULL == pszLongUrl)
  1355. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  1356. hr = pURL->Get(0, &ulUrlLen, pszLongUrl);
  1357. }
  1358. BAIL_ON_FAILURE(hr);
  1359. // Check if the path is relative or absolute
  1360. fIsRelPath = IsRelativePath(pURL);
  1361. if(TRUE == fIsRelPath) {
  1362. // check if the caller specified the class as part of the path
  1363. hr = GetClassAndPath(pszLongUrl, &pszClass, &pszPath);
  1364. BAIL_ON_FAILURE(hr);
  1365. m_pCreds->SetUmiFlag();
  1366. hr = m_pIADsContainer->Create(
  1367. pszClass,
  1368. pszPath,
  1369. &pIDispatch
  1370. );
  1371. m_pCreds->ResetUmiFlag();
  1372. BAIL_ON_FAILURE(hr);
  1373. hr = pIDispatch->QueryInterface(
  1374. IID_IUmiObject,
  1375. (void **) ppNewObj
  1376. );
  1377. BAIL_ON_FAILURE(hr);
  1378. } // if(TRUE == fIsRelPath
  1379. else {
  1380. BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH);
  1381. }
  1382. error:
  1383. if(pIDispatch != NULL)
  1384. pIDispatch->Release();
  1385. if(pszClass != NULL)
  1386. FreeADsMem(pszClass);
  1387. if(pszPath != NULL)
  1388. FreeADsMem(pszPath);
  1389. if(pszLongUrl != pszUrl)
  1390. FreeADsMem(pszLongUrl);
  1391. if(FAILED(hr))
  1392. SetLastStatus(hr);
  1393. RRETURN(MapHrToUmiError(hr));
  1394. }
  1395. //----------------------------------------------------------------------------
  1396. // Function: Move
  1397. //
  1398. // Synopsis: Moves a specified object into the container. Implements
  1399. // IUmiContainer::Move().
  1400. //
  1401. // Arguments:
  1402. //
  1403. // uFlags Reserved. Must be 0 for now.
  1404. // pOldURL URL of the object to be moved
  1405. // pNewURL New URL of the object within the container. If NULL, the new
  1406. // name will be the same as the old one.
  1407. //
  1408. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  1409. //
  1410. // Modifies: Nothing
  1411. //
  1412. //----------------------------------------------------------------------------
  1413. STDMETHODIMP CUmiObject::Move(
  1414. ULONG uFlags,
  1415. IUmiURL *pOldURL,
  1416. IUmiURL *pNewURL
  1417. )
  1418. {
  1419. ULONG ulUrlLen = MAX_URL;
  1420. WCHAR pszNewUrl[MAX_URL+1], pszOldUrl[MAX_URL+1];
  1421. WCHAR *pszLongNewUrl = pszNewUrl, *pszLongOldUrl = pszOldUrl;
  1422. WCHAR *pszDstPath = NULL, *pszTmpStr = NULL;
  1423. WCHAR *pszClass = NULL;
  1424. BOOL fIsRelPath = FALSE;
  1425. IDispatch *pIDispatch = NULL;
  1426. HRESULT hr = UMI_S_NO_ERROR;
  1427. ULONGLONG PathType = 0;
  1428. WCHAR *pSeparator = NULL;
  1429. DWORD dwNumComponents = 0, dwIndex = 0;
  1430. LPWSTR *ppszClasses = NULL;
  1431. SetLastStatus(0);
  1432. if(uFlags != 0)
  1433. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  1434. if(NULL == pOldURL)
  1435. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  1436. if(NULL == m_pIADsContainer)
  1437. // shouldn't happen, but just in case...
  1438. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  1439. // Get the path from the URL
  1440. if(pNewURL != NULL) {
  1441. hr = pNewURL->Get(0, &ulUrlLen, pszNewUrl);
  1442. if(WBEM_E_BUFFER_TOO_SMALL == hr) {
  1443. // need to allocate more memory for URL
  1444. pszLongNewUrl = (WCHAR *) AllocADsMem(ulUrlLen * sizeof(WCHAR));
  1445. if(NULL == pszLongNewUrl)
  1446. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  1447. hr = pNewURL->Get(0, &ulUrlLen, pszLongNewUrl);
  1448. }
  1449. BAIL_ON_FAILURE(hr);
  1450. // Check if the path is relative or absolute
  1451. fIsRelPath = IsRelativePath(pNewURL);
  1452. }
  1453. else {
  1454. fIsRelPath = TRUE;
  1455. pszDstPath = NULL;
  1456. }
  1457. // check if old path is native or UMI path
  1458. hr = pOldURL->GetPathInfo(0, &PathType);
  1459. BAIL_ON_FAILURE(hr);
  1460. if(PathType & UMIPATH_INFO_NATIVE_STRING) {
  1461. // Get the native path from the URL
  1462. ulUrlLen = MAX_URL;
  1463. hr = pOldURL->Get(0, &ulUrlLen, pszOldUrl);
  1464. if(WBEM_E_BUFFER_TOO_SMALL == hr) {
  1465. // need to allocate more memory for URL
  1466. pszLongOldUrl = (WCHAR *) AllocADsMem(ulUrlLen * sizeof(WCHAR));
  1467. if(NULL == pszLongOldUrl)
  1468. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  1469. hr = pOldURL->Get(0, &ulUrlLen, pszLongOldUrl);
  1470. }
  1471. BAIL_ON_FAILURE(hr);
  1472. }
  1473. else {
  1474. // assume UMI path if not native
  1475. hr = UmiToWinNTPath(
  1476. pOldURL,
  1477. &pszLongOldUrl,
  1478. &dwNumComponents,
  1479. &ppszClasses
  1480. );
  1481. BAIL_ON_FAILURE(hr);
  1482. // check to ensure that the UMI path had the expected object classes
  1483. hr = CheckClasses(dwNumComponents, ppszClasses);
  1484. BAIL_ON_FAILURE(hr);
  1485. }
  1486. if(TRUE == fIsRelPath) {
  1487. if(pNewURL != NULL) {
  1488. hr = GetClassAndPath(pszLongNewUrl, &pszClass, &pszDstPath);
  1489. BAIL_ON_FAILURE(hr);
  1490. // Make sure that if the old path had a class specified in the path,
  1491. // then the new path also if of the same class
  1492. if(NULL == (pSeparator = wcschr(pszLongOldUrl,
  1493. NATIVE_CLASS_SEPARATOR))) {
  1494. // no class specified in the old path. Must have been a native path.
  1495. // Append class to old path.
  1496. pszTmpStr = (WCHAR *) AllocADsMem(
  1497. (wcslen(pszLongOldUrl)+MAX_CLASS) *
  1498. sizeof(WCHAR) );
  1499. if(NULL == pszTmpStr)
  1500. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  1501. wcscpy(pszTmpStr, pszLongOldUrl);
  1502. wcscat(pszTmpStr, L",");
  1503. wcscat(pszTmpStr, pszClass);
  1504. if(pszLongOldUrl != pszOldUrl)
  1505. FreeADsMem(pszLongOldUrl);
  1506. pszLongOldUrl = pszTmpStr;
  1507. }
  1508. else {
  1509. // old path already had a class in it
  1510. if(_wcsicmp(pSeparator+1, pszClass))
  1511. BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH);
  1512. }
  1513. } // if(pNewUrl != NULL)
  1514. m_pCreds->SetUmiFlag();
  1515. hr = m_pIADsContainer->MoveHere(
  1516. pszLongOldUrl,
  1517. pszDstPath,
  1518. &pIDispatch
  1519. );
  1520. m_pCreds->ResetUmiFlag();
  1521. BAIL_ON_FAILURE(hr);
  1522. } // if(TRUE == fIsRelPath)
  1523. else {
  1524. BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH);
  1525. }
  1526. error:
  1527. if(pIDispatch != NULL)
  1528. pIDispatch->Release();
  1529. if(pszLongOldUrl != pszOldUrl)
  1530. FreeADsMem(pszLongOldUrl);
  1531. if(pszLongNewUrl != pszNewUrl)
  1532. FreeADsMem(pszLongNewUrl);
  1533. if(pszClass != NULL)
  1534. FreeADsStr(pszClass);
  1535. if(pszDstPath != NULL)
  1536. FreeADsStr(pszDstPath);
  1537. if(ppszClasses != NULL) {
  1538. for(dwIndex = 0; dwIndex < dwNumComponents; dwIndex++) {
  1539. if(ppszClasses[dwIndex] != NULL)
  1540. FreeADsStr(ppszClasses[dwIndex]);
  1541. }
  1542. FreeADsMem(ppszClasses);
  1543. }
  1544. if(FAILED(hr))
  1545. SetLastStatus(hr);
  1546. RRETURN(MapHrToUmiError(hr));
  1547. }
  1548. //----------------------------------------------------------------------------
  1549. // Function: CreateEnum
  1550. //
  1551. // Synopsis: Creates an enumerator within a container. The enumerator is
  1552. // a IUmiCursor interface pointer. The caller can optionally set
  1553. // a filter on the cursor and then enumerate the contents of the
  1554. // container. The actual enumeration of the container does
  1555. // not happen in this function. It is deferred to the point
  1556. // when the cursor is used to enumerate the results.
  1557. //
  1558. // Arguments:
  1559. //
  1560. // pszEnumContext Not used. Must be NULL.
  1561. // uFlags Reserved. Must be 0 for now.
  1562. // TargetIID Interface requested. Has to be IUmiCursor.
  1563. // ppInterface Returns the IUmiCursor interface pointer
  1564. //
  1565. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  1566. //
  1567. // Modifies: *ppInterface to return the IUmiCursor interface
  1568. //
  1569. //----------------------------------------------------------------------------
  1570. STDMETHODIMP CUmiObject::CreateEnum(
  1571. IUmiURL *pszEnumContext,
  1572. ULONG uFlags,
  1573. REFIID TargetIID,
  1574. LPVOID *ppInterface
  1575. )
  1576. {
  1577. HRESULT hr = UMI_S_NO_ERROR;
  1578. IUnknown *pEnumerator = NULL;
  1579. SetLastStatus(0);
  1580. if(uFlags != 0)
  1581. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  1582. if( (pszEnumContext != NULL) || (NULL == ppInterface) )
  1583. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  1584. if(!IsEqualIID(IID_IUmiCursor, TargetIID))
  1585. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  1586. *ppInterface = NULL;
  1587. if(NULL == m_pIADsContainer)
  1588. // shouldn't happen, but just in case...
  1589. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  1590. hr = CUmiCursor::CreateCursor(m_pCreds, m_pUnkInner, TargetIID,
  1591. ppInterface);
  1592. BAIL_ON_FAILURE(hr);
  1593. error:
  1594. if(FAILED(hr))
  1595. SetLastStatus(hr);
  1596. RRETURN(MapHrToUmiError(hr));
  1597. }
  1598. //----------------------------------------------------------------------------
  1599. // Function: ExecQuery
  1600. //
  1601. // Synopsis: Executes a query in a container. Not implemented on WinNT.
  1602. // Implements IUmiContainer::ExecQuery().
  1603. //
  1604. // Arguments:
  1605. //
  1606. // pQuery IUmiQuery interface containing the query
  1607. // uFlags Reserved. Must be 0 for now.
  1608. // TargetIID Interface requested
  1609. // ppInterface Returns pointer to interface requested
  1610. //
  1611. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  1612. //
  1613. // Modifies: *ppInterface to return interface pointer
  1614. //
  1615. //----------------------------------------------------------------------------
  1616. STDMETHODIMP CUmiObject::ExecQuery(
  1617. IUmiQuery *pQuery,
  1618. ULONG uFlags,
  1619. REFIID TargetIID,
  1620. LPVOID *ppInterface
  1621. )
  1622. {
  1623. SetLastStatus(UMI_E_NOTIMPL);
  1624. RRETURN(UMI_E_NOTIMPL);
  1625. }
  1626. //----------------------------------------------------------------------------
  1627. // Function: GetCLSIDForIID
  1628. //
  1629. // Synopsis: Returns the CLSID corresponding to a given interface IID. If
  1630. // the interface is one of the interfaces implemented by the
  1631. // underlying WinNT object, then CLSID_WinNTObject is returned.
  1632. // If the IID is one of the interfaces implemented by an
  1633. // extension object, then the extension's CLSID is returned.
  1634. // Implements IUmiCustomInterfaceFactory::GetCLSIDForIID.
  1635. //
  1636. // Arguments:
  1637. //
  1638. // riid Interface ID for which we want to find the CLSID
  1639. // lFlags Reserved. Must be 0.
  1640. // pCLSID Returns the CLSID corresponding to the IID.
  1641. //
  1642. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  1643. //
  1644. // Modifies: *pCLSID to return CLSID.
  1645. //
  1646. //----------------------------------------------------------------------------
  1647. STDMETHODIMP CUmiObject::GetCLSIDForIID(
  1648. REFIID riid,
  1649. long lFlags,
  1650. CLSID *pCLSID
  1651. )
  1652. {
  1653. HRESULT hr = S_OK;
  1654. IUnknown *pUnknown = NULL;
  1655. SetLastStatus(0);
  1656. if( (lFlags != 0) || (NULL == pCLSID) )
  1657. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  1658. if(m_pExtMgr != NULL) {
  1659. // check if there is any extension which supports this IID
  1660. hr = m_pExtMgr->GetCLSIDForIID(
  1661. riid,
  1662. lFlags,
  1663. pCLSID
  1664. );
  1665. if(SUCCEEDED(hr))
  1666. RRETURN(UMI_S_NO_ERROR);
  1667. }
  1668. // check if the underlying WinNT object supports this IID
  1669. hr = m_pUnkInner->QueryInterface(riid, (void **) &pUnknown);
  1670. if(SUCCEEDED(hr)) {
  1671. pUnknown->Release();
  1672. memcpy(pCLSID, &CLSID_WinNTObject, sizeof(GUID));
  1673. RRETURN(UMI_S_NO_ERROR);
  1674. }
  1675. error:
  1676. if(FAILED(hr))
  1677. SetLastStatus(hr);
  1678. RRETURN(MapHrToUmiError(hr));
  1679. }
  1680. //----------------------------------------------------------------------------
  1681. // Function: GetObjectByCLSID
  1682. //
  1683. // Synopsis: Returns a pointer to a requested interface on the object
  1684. // specified by a CLSID. The object specified by the CLSID is
  1685. // aggregated by the specified outer unknown. The interface
  1686. // returned is a non-delegating interface on the object.
  1687. // Implements IUmiCustomInterfaceFactory::GetObjectByCLSID.
  1688. //
  1689. // Arguments:
  1690. //
  1691. // clsid CLSID of object on which interface should be obtained
  1692. // pUnkOuter Aggregating outer unknown.
  1693. // dwClsContext Context for running executable code.
  1694. // riid Interface requested. Has to be IID_IUnknown.
  1695. // lFlags Reserved. Must be 0.
  1696. // ppInterface Returns requested interface
  1697. //
  1698. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  1699. //
  1700. // Modifies: *ppInterface to return requested interface
  1701. //
  1702. //----------------------------------------------------------------------------
  1703. STDMETHODIMP CUmiObject::GetObjectByCLSID(
  1704. CLSID clsid,
  1705. IUnknown *pUnkOuter,
  1706. DWORD dwClsContext,
  1707. REFIID riid,
  1708. long lFlags,
  1709. void **ppInterface
  1710. )
  1711. {
  1712. HRESULT hr = S_OK;
  1713. IUnknown *pCurOuterUnk = NULL;
  1714. SetLastStatus(0);
  1715. if( (lFlags != 0) || (NULL == pUnkOuter) || (NULL == ppInterface) ||
  1716. (dwClsContext != CLSCTX_INPROC_SERVER) )
  1717. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  1718. // ensure outer unknown specified is same as what is on the WinNT object
  1719. if(TRUE == m_fOuterUnkSet) {
  1720. pCurOuterUnk = m_pCoreObj->GetOuterUnknown();
  1721. if(pCurOuterUnk != pUnkOuter)
  1722. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  1723. }
  1724. // Interface requested has to be IID_IUnknown if there is an outer unknown
  1725. if (!IsEqualIID(riid, IID_IUnknown))
  1726. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  1727. if(!IsEqualCLSID(clsid, CLSID_WinNTObject)) {
  1728. // has to be a CLSID of an extension object
  1729. if(m_pExtMgr != NULL) {
  1730. hr = m_pExtMgr->GetObjectByCLSID(
  1731. clsid,
  1732. pUnkOuter,
  1733. riid,
  1734. ppInterface
  1735. );
  1736. BAIL_ON_FAILURE(hr);
  1737. // successfully got the interface
  1738. m_pCoreObj->SetOuterUnknown(pUnkOuter);
  1739. m_fOuterUnkSet = TRUE;
  1740. RRETURN(UMI_S_NO_ERROR);
  1741. }
  1742. else
  1743. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG); // bad CLSID
  1744. }
  1745. // CLSID == CLSID_WinNTObject. This has to be an interface on the
  1746. // underlying WinNT object.
  1747. m_pCoreObj->SetOuterUnknown(pUnkOuter);
  1748. m_fOuterUnkSet = TRUE;
  1749. *ppInterface = m_pUnkInner;
  1750. m_pUnkInner->AddRef();
  1751. RRETURN(UMI_S_NO_ERROR);
  1752. error:
  1753. if(FAILED(hr))
  1754. SetLastStatus(hr);
  1755. RRETURN(MapHrToUmiError(hr));
  1756. }
  1757. //----------------------------------------------------------------------------
  1758. // Function: GetCLSIDForNames
  1759. //
  1760. // Synopsis: Returns the CLSID of the object that supports a specified
  1761. // method/property. Also returns DISPIDs for the property/method.
  1762. // Implements IUmiCustomInterfaceFactory::GetCLSIDForNames.
  1763. //
  1764. // Arguments:
  1765. //
  1766. // rgszNames Names to be mapped
  1767. // cNames Number of names to be mapped
  1768. // lcid Locale in which to interpret the names
  1769. // rgDispId Returns DISPID
  1770. // lFlags Reserved. Must be 0.
  1771. // pCLSID Returns CLSID of object which supports this property/method.
  1772. //
  1773. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  1774. //
  1775. // Modifies: *pCLSID to return the CLSID.
  1776. // *rgDispId to return the DISPIDs.
  1777. //
  1778. //----------------------------------------------------------------------------
  1779. STDMETHODIMP CUmiObject::GetCLSIDForNames(
  1780. LPOLESTR *rgszNames,
  1781. UINT cNames,
  1782. LCID lcid,
  1783. DISPID *rgDispId,
  1784. long lFlags,
  1785. CLSID *pCLSID
  1786. )
  1787. {
  1788. HRESULT hr = S_OK;
  1789. IDispatch *pDispatch = NULL;
  1790. SetLastStatus(0);
  1791. if( (lFlags != 0) || (NULL == pCLSID) )
  1792. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  1793. if(0 == cNames)
  1794. RRETURN(UMI_S_NO_ERROR);
  1795. if( (NULL == rgszNames) || (NULL == rgDispId) )
  1796. RRETURN(UMI_S_NO_ERROR);
  1797. if(m_pExtMgr != NULL) {
  1798. // check if there is any extension which supports this IID
  1799. hr = m_pExtMgr->GetCLSIDForNames(
  1800. rgszNames,
  1801. cNames,
  1802. lcid,
  1803. rgDispId,
  1804. lFlags,
  1805. pCLSID
  1806. );
  1807. if(SUCCEEDED(hr))
  1808. // successfully got the CLSID and DISPIDs
  1809. RRETURN(UMI_S_NO_ERROR);
  1810. }
  1811. // check if the underlying WinNT object supports this name
  1812. hr = m_pUnkInner->QueryInterface(IID_IDispatch, (void **) &pDispatch);
  1813. if(FAILED(hr))
  1814. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  1815. hr = pDispatch->GetIDsOfNames(
  1816. IID_NULL,
  1817. rgszNames,
  1818. cNames,
  1819. lcid,
  1820. rgDispId
  1821. );
  1822. if(SUCCEEDED(hr)) {
  1823. pDispatch->Release();
  1824. memcpy(pCLSID, &CLSID_WinNTObject, sizeof(GUID));
  1825. RRETURN(UMI_S_NO_ERROR);
  1826. }
  1827. error:
  1828. if(pDispatch != NULL)
  1829. pDispatch->Release();
  1830. if(FAILED(hr))
  1831. SetLastStatus(hr);
  1832. RRETURN(MapHrToUmiError(hr));
  1833. }
  1834. //----------------------------------------------------------------------------
  1835. // Function: GetContainer
  1836. //
  1837. // Synopsis: Returns a pointer to the IADsContainer interface of the
  1838. // underlying WinNT object. Used as a backdoor to get access to
  1839. // the WinNT object from a UMI object. Implements
  1840. // IUmiADSIPrivate::GetContainer().
  1841. //
  1842. // Arguments:
  1843. //
  1844. // ppContainer Returns pointer to IADsContainer interface on WinNT object
  1845. //
  1846. // Returns: S_OK on success. Error code otherwise.
  1847. //
  1848. // Modifies: *ppContainer to return the IADsContainer interface pointer.
  1849. //
  1850. //----------------------------------------------------------------------------
  1851. STDMETHODIMP CUmiObject::GetContainer(void **ppContainer)
  1852. {
  1853. if(NULL == ppContainer)
  1854. RRETURN(UMI_E_INVALIDARG);
  1855. *ppContainer = (void *) m_pIADsContainer;
  1856. if(m_pIADsContainer != NULL)
  1857. m_pIADsContainer->AddRef();
  1858. RRETURN(S_OK);
  1859. }
  1860. //----------------------------------------------------------------------------
  1861. // Function: CopyTo
  1862. //
  1863. // Synopsis: Creates an uncommitted copy of an object at the location
  1864. // specified by a URL. This is the same as Clone except that
  1865. // the new object has a different path than the old one. If the
  1866. // cache is dirty in teh source object, then the destination will
  1867. // also end up with a dirty cache.
  1868. //
  1869. // Update: This method will not be supported for now.
  1870. //
  1871. // Arguments:
  1872. //
  1873. // uFlags Flags for CopyTo. Must be 0 for now.
  1874. // pURL Destination path (native or UMI)
  1875. // riid Interface requested from new object
  1876. // pCopy Returns interface requested
  1877. //
  1878. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  1879. //
  1880. // Modifies: *pCopy to return requested interface pointer
  1881. //
  1882. //----------------------------------------------------------------------------
  1883. STDMETHODIMP CUmiObject::CopyTo(
  1884. ULONG uFlags,
  1885. IUmiURL *pURL,
  1886. REFIID riid,
  1887. LPVOID *pCopy
  1888. )
  1889. {
  1890. HRESULT hr = UMI_S_NO_ERROR;
  1891. ULONGLONG PathType = 0;
  1892. WCHAR pszUrl[MAX_URL+1];
  1893. WCHAR *pszLongUrl = pszUrl;
  1894. ULONG ulUrlLen = MAX_URL;
  1895. LPWSTR RelName = NULL;
  1896. BSTR bstrClass = NULL;
  1897. IUnknown *pUnkParent = NULL;
  1898. IADsContainer *pIADsCont = NULL;
  1899. IDispatch *pDispatch = NULL;
  1900. IUmiObject *pUmiObj = NULL;
  1901. IUmiADSIPrivate *pUmiPrivate = NULL;
  1902. OBJECTINFO ObjectInfo;
  1903. POBJECTINFO pObjectInfo = NULL;
  1904. CLexer Lexer(NULL);
  1905. DWORD dwNumComponents = 0, dwIndex = 0, dwCoreIndex = 0;
  1906. LPWSTR *ppszClasses = NULL;
  1907. CCoreADsObject *pCoreObj = NULL;
  1908. SetLastStatus(UMI_E_NOTIMPL);
  1909. RRETURN(UMI_E_NOTIMPL);
  1910. SetLastStatus(0);
  1911. if(uFlags != 0)
  1912. BAIL_ON_FAILURE(hr = UMI_E_INVALID_FLAGS);
  1913. if( (NULL == pCopy) || (NULL == pURL) )
  1914. BAIL_ON_FAILURE(hr = UMI_E_INVALIDARG);
  1915. if( (NULL == m_pCoreObj) || (NULL == m_pIADs) )
  1916. // shouldn't happen, but just being paranoid
  1917. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  1918. *pCopy = NULL;
  1919. // check if this is a native path or UMI path
  1920. hr = pURL->GetPathInfo(0, &PathType);
  1921. BAIL_ON_FAILURE(hr);
  1922. if(PathType & UMIPATH_INFO_NATIVE_STRING) {
  1923. // Get the native path from the URL
  1924. hr = pURL->Get(0, &ulUrlLen, pszUrl);
  1925. if(WBEM_E_BUFFER_TOO_SMALL == hr) {
  1926. // need to allocate more memory for URL
  1927. pszLongUrl = (WCHAR *) AllocADsMem(ulUrlLen * sizeof(WCHAR));
  1928. if(NULL == pszLongUrl)
  1929. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  1930. hr = pURL->Get(0, &ulUrlLen, pszLongUrl);
  1931. }
  1932. BAIL_ON_FAILURE(hr);
  1933. }
  1934. else {
  1935. // assume UMI path if not native
  1936. hr = UmiToWinNTPath(
  1937. pURL,
  1938. &pszLongUrl,
  1939. &dwNumComponents,
  1940. &ppszClasses
  1941. );
  1942. BAIL_ON_FAILURE(hr);
  1943. }
  1944. // get the native path of the parent and the relative name of new object
  1945. Lexer.SetBuffer(pszLongUrl);
  1946. pObjectInfo = &ObjectInfo;
  1947. memset(pObjectInfo, 0, sizeof(OBJECTINFO));
  1948. hr = Object(&Lexer, pObjectInfo);
  1949. if(FAILED(hr)) {
  1950. pObjectInfo = NULL; // so we don't attempt to free object info later
  1951. goto error;
  1952. }
  1953. hr = BuildParent(pObjectInfo, pszLongUrl);
  1954. BAIL_ON_FAILURE(hr);
  1955. if(pObjectInfo->NumComponents != 0)
  1956. RelName =
  1957. pObjectInfo->DisplayComponentArray[pObjectInfo->NumComponents - 1];
  1958. else
  1959. // can't have a parent for such a path
  1960. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  1961. // Decrement number of components since we are dealing with the parent
  1962. dwNumComponents--;
  1963. hr = GetObject(
  1964. pszLongUrl,
  1965. (LPVOID *) &pUnkParent,
  1966. *m_pCreds
  1967. );
  1968. BAIL_ON_FAILURE(hr);
  1969. hr = pUnkParent->QueryInterface(
  1970. IID_IUmiADSIPrivate,
  1971. (LPVOID *) &pUmiPrivate
  1972. );
  1973. BAIL_ON_FAILURE(hr);
  1974. hr = pUmiPrivate->GetCoreObject((void **) &pCoreObj);
  1975. BAIL_ON_FAILURE(hr);
  1976. // walk the list of classes in reverse order. Reason for reverse order
  1977. // is that the WinNT provider may tack on an additional component to
  1978. // the ADsPath stored in the core object. For example,
  1979. // Open("WinNT://ntdsdc1") would return an ADsPath of
  1980. // "WinNT://ntdev/ntdsdc1".
  1981. if(dwNumComponents > 0) {
  1982. dwCoreIndex = pCoreObj->_dwNumComponents - 1;
  1983. for(dwIndex = dwNumComponents - 1; ((long) dwIndex) >= 0; dwIndex--) {
  1984. if( _wcsicmp(
  1985. ppszClasses[dwIndex],
  1986. pCoreObj->_CompClasses[dwCoreIndex]) ) {
  1987. BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH);
  1988. }
  1989. dwCoreIndex--;
  1990. }
  1991. }
  1992. hr = pUmiPrivate->GetContainer((void **) &pIADsCont);
  1993. BAIL_ON_FAILURE(hr);
  1994. if(NULL == pIADsCont)
  1995. // parent object is not a container
  1996. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  1997. // get the class of this object
  1998. hr = m_pIADs->get_Class(&bstrClass);
  1999. BAIL_ON_FAILURE(hr);
  2000. // make sure that the destination path mentioned the same class
  2001. if(_wcsicmp(bstrClass, ppszClasses[dwNumComponents]))
  2002. BAIL_ON_FAILURE(hr = UMI_E_INVALID_PATH);
  2003. // now Create() the new object
  2004. hr = pIADsCont->Create(
  2005. bstrClass,
  2006. RelName,
  2007. &pDispatch
  2008. );
  2009. if(E_NOTIMPL == hr) // parent is namespace object
  2010. hr = UMI_E_FAIL;
  2011. BAIL_ON_FAILURE(hr);
  2012. hr = pDispatch->QueryInterface(IID_IUmiObject, (LPVOID *) &pUmiObj);
  2013. BAIL_ON_FAILURE(hr);
  2014. // if the source object is bound, refresh it if required
  2015. if(ADS_OBJECT_BOUND == m_pCoreObj->GetObjectState()) {
  2016. // object exists on server
  2017. if(FALSE == m_fRefreshDone) {
  2018. hr = m_pCoreObj->ImplicitGetInfo();
  2019. BAIL_ON_FAILURE(hr);
  2020. }
  2021. }
  2022. // copy over the attributes in the property cache
  2023. hr = CopyPropCache(pUmiObj, (IUmiObject *) this);
  2024. BAIL_ON_FAILURE(hr);
  2025. hr = pUmiObj->QueryInterface(riid, pCopy);
  2026. BAIL_ON_FAILURE(hr);
  2027. error:
  2028. if( (pszLongUrl != NULL) && (pszLongUrl != pszUrl) )
  2029. FreeADsMem(pszLongUrl);
  2030. if(bstrClass != NULL)
  2031. SysFreeString(bstrClass);
  2032. if(pUnkParent != NULL)
  2033. pUnkParent->Release();
  2034. if(pIADsCont != NULL)
  2035. pIADsCont->Release();
  2036. if(pUmiObj != NULL)
  2037. pUmiObj->Release();
  2038. if(pUmiPrivate != NULL)
  2039. pUmiPrivate->Release();
  2040. if(pDispatch != NULL)
  2041. pDispatch->Release();
  2042. if(pObjectInfo != NULL)
  2043. FreeObjectInfo(&ObjectInfo, TRUE);
  2044. if(ppszClasses != NULL) {
  2045. for(dwIndex = 0; dwIndex < dwNumComponents; dwIndex++) {
  2046. if(ppszClasses[dwIndex] != NULL)
  2047. FreeADsStr(ppszClasses[dwIndex]);
  2048. }
  2049. FreeADsMem(ppszClasses);
  2050. }
  2051. if(FAILED(hr))
  2052. SetLastStatus(hr);
  2053. RRETURN(MapHrToUmiError(hr));
  2054. }
  2055. //----------------------------------------------------------------------------
  2056. // Function: GetCoreObject
  2057. //
  2058. // Synopsis: Returns a pointer to the core object of the
  2059. // underlying WinNT object. Used as a backdoor to get access to
  2060. // the WinNT core object from a UMI object. Implements
  2061. // IUmiADSIPrivate::GetCoreObject().
  2062. //
  2063. // Arguments:
  2064. //
  2065. // ppCoreObj Returns pointer to core object of WinNT object
  2066. //
  2067. // Returns: S_OK on success. Error code otherwise.
  2068. //
  2069. // Modifies: *ppCoreObj to return the core object pointer.
  2070. //
  2071. //----------------------------------------------------------------------------
  2072. STDMETHODIMP CUmiObject::GetCoreObject(void **ppCoreObj)
  2073. {
  2074. if(NULL == ppCoreObj)
  2075. RRETURN(UMI_E_INVALIDARG);
  2076. *ppCoreObj = NULL;
  2077. if(NULL == m_pCoreObj)
  2078. // shouldn't happen. Just being paranoid.
  2079. RRETURN(UMI_E_FAIL);
  2080. *ppCoreObj = (void *) m_pCoreObj;
  2081. RRETURN(S_OK);
  2082. }
  2083. //----------------------------------------------------------------------------
  2084. // Function: CheckClasses
  2085. //
  2086. // Synopsis: Checks that the classes specified in the UMI path passed to
  2087. // Move are valid. Need a separate function for this because UMI
  2088. // doesn't actually retrieve the object that is to be moved - it
  2089. // is handled internally within ADSI. So, we need to check the
  2090. // classes before calling into ADSI. We make use of the fact that
  2091. // the WinNT provider only supports moving user and group objects.
  2092. //
  2093. // Arguments:
  2094. //
  2095. // dwNumComponents Number of components in the UMI path
  2096. // ppszClasses Class of each component
  2097. //
  2098. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  2099. //
  2100. // Modifies: Nothing
  2101. //
  2102. //----------------------------------------------------------------------------
  2103. HRESULT CUmiObject::CheckClasses(
  2104. DWORD dwNumComponents,
  2105. LPWSTR *ppszClasses
  2106. )
  2107. {
  2108. if(NULL == ppszClasses)
  2109. RRETURN(UMI_E_INVALIDARG);
  2110. if( (dwNumComponents != 2) && (dwNumComponents != 3) )
  2111. RRETURN(UMI_E_INVALIDARG);
  2112. // can only move users or groups
  2113. if( _wcsicmp(ppszClasses[dwNumComponents - 1], USER_CLASS_NAME) &&
  2114. _wcsicmp(ppszClasses[dwNumComponents - 1], GROUP_CLASS_NAME) )
  2115. RRETURN(UMI_E_INVALIDARG);
  2116. if(2 == dwNumComponents) {
  2117. if( _wcsicmp(ppszClasses[0], DOMAIN_CLASS_NAME) &&
  2118. _wcsicmp(ppszClasses[0], COMPUTER_CLASS_NAME) )
  2119. RRETURN(UMI_E_INVALIDARG);
  2120. }
  2121. if(3 == dwNumComponents) {
  2122. if( _wcsicmp(ppszClasses[0], DOMAIN_CLASS_NAME) ||
  2123. _wcsicmp(ppszClasses[1], COMPUTER_CLASS_NAME) )
  2124. RRETURN(UMI_E_INVALIDARG);
  2125. }
  2126. RRETURN(S_OK);
  2127. }