Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1069 lines
31 KiB

  1. ///////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright(C) 1997-1998 Microsoft Corporation all rights reserved.
  4. //
  5. // Module: sdo.cpp
  6. //
  7. // Project: Everest
  8. //
  9. // Description: IAS Server Data Object Definition
  10. //
  11. // Author: TLP 1/23/98
  12. //
  13. // When Who What
  14. // ---- --- ----
  15. // 2/28/98 TLP Prepare for IDataStore2
  16. //
  17. ///////////////////////////////////////////////////////////////////////////
  18. #include "stdafx.h"
  19. #include <ias.h>
  20. #include "sdo.h"
  21. #include "sdohelperfuncs.h"
  22. #include "sdofactory.h"
  23. ////////////////////////////////////////////////////////////////////////////
  24. // CSdo Class Implementation
  25. /////////////////////////////////////////////////////////////////////////////
  26. ////////////////////////////////////////////////////////////////////////////
  27. // SDO CONSTRUCTOR/DESTRUCTOR
  28. /////////////////////////////////////////////////////////////////////////////
  29. //////////////////////////////////////////////////////////////////////////////
  30. CSdo::CSdo()
  31. : m_pParent(NULL),
  32. m_pDSObject(NULL),
  33. m_fSdoInitialized(FALSE),
  34. m_fPersistOnApply(FALSE),
  35. m_fIsPersisted(FALSE)
  36. {
  37. InternalAddRef();
  38. }
  39. //////////////////////////////////////////////////////////////////////////////
  40. CSdo::~CSdo()
  41. {
  42. InternalShutdown();
  43. }
  44. ////////////////////////////////////////////////////////////////////////////
  45. // ISdo INTERFACE IMPLEMENTATION
  46. ////////////////////////////////////////////////////////////////////////////
  47. /////////////////////////////////////////////////////////////////////////////
  48. STDMETHODIMP CSdo::GetPropertyInfo(LONG Id, IUnknown** ppSdoPropertyInfo)
  49. {
  50. CSdoLock theLock(*this);
  51. _ASSERT( m_fSdoInitialized );
  52. if ( ! m_fSdoInitialized )
  53. return E_FAIL;
  54. _ASSERT( NULL != ppSdoPropertyInfo );
  55. if ( NULL == ppSdoPropertyInfo )
  56. return E_POINTER;
  57. HRESULT hr = S_OK;
  58. try
  59. {
  60. PropertyMapIterator p = m_PropertyMap.find(Id);
  61. if ( p == m_PropertyMap.end() )
  62. {
  63. IASTracePrintf("Error in SDO - GetProperty() - Property with ID = %d could not be found...", Id);
  64. hr = DISP_E_MEMBERNOTFOUND;
  65. }
  66. else
  67. {
  68. (*ppSdoPropertyInfo = ((*p).second)->GetPropertyInfo())->AddRef();
  69. }
  70. }
  71. catch(_com_error theComError)
  72. {
  73. IASTracePrintf("Error in SDO - GetPropertyInfo() - Caught COM exception...");
  74. hr = theComError.Error();
  75. }
  76. catch (...)
  77. {
  78. IASTracePrintf("Error in SDO - GetPropertyInfo() - Caught unknown exception...");
  79. hr = E_FAIL;
  80. }
  81. return hr;
  82. }
  83. /////////////////////////////////////////////////////////////////////////////
  84. STDMETHODIMP CSdo::GetProperty(LONG Id, VARIANT *pValue)
  85. {
  86. CSdoLock theLock(*this);
  87. _ASSERT( m_fSdoInitialized );
  88. if ( ! m_fSdoInitialized )
  89. return E_FAIL;
  90. // Check function parameters
  91. //
  92. _ASSERT( NULL != pValue );
  93. if ( NULL == pValue )
  94. return E_POINTER;
  95. HRESULT hr = E_FAIL;
  96. try
  97. {
  98. if ( PROPERTY_SDO_DATASTORE_NAME != Id )
  99. {
  100. PropertyMapIterator p = m_PropertyMap.find(Id);
  101. if ( p == m_PropertyMap.end() )
  102. {
  103. IASTracePrintf("Error in SDO - GetProperty() - Property with ID = %d could not be found...", Id);
  104. hr = DISP_E_MEMBERNOTFOUND;
  105. }
  106. else
  107. {
  108. hr = InitializeProperty(Id); // Defer property initialization until property is requeted.
  109. if ( SUCCEEDED(hr) )
  110. hr = ((*p).second)->GetValue(pValue);
  111. }
  112. }
  113. else
  114. {
  115. hr = GetDatastoreName(pValue);
  116. }
  117. }
  118. catch (...)
  119. {
  120. IASTracePrintf("Error in SDO - GetProperty() - Caught unknown exception...");
  121. hr = E_FAIL;
  122. }
  123. return hr;
  124. }
  125. /////////////////////////////////////////////////////////////////////////////
  126. STDMETHODIMP CSdo::PutProperty(LONG Id, VARIANT * pValue)
  127. {
  128. CSdoLock theLock(*this);
  129. _ASSERT( m_fSdoInitialized );
  130. if ( ! m_fSdoInitialized )
  131. return E_FAIL;
  132. // Check function parameters
  133. //
  134. _ASSERT( NULL != pValue );
  135. if ( NULL == pValue )
  136. return E_POINTER;
  137. HRESULT hr = E_FAIL;
  138. try
  139. {
  140. PropertyMapIterator p = m_PropertyMap.find(Id);
  141. if ( p == m_PropertyMap.end() )
  142. {
  143. IASTracePrintf("Error in SDO - PutProperty() - Property with ID = %d could not be found...", Id);
  144. hr = DISP_E_MEMBERNOTFOUND;
  145. }
  146. else
  147. {
  148. if ( ((*p).second)->GetFlags() & SDO_PROPERTY_READ_ONLY )
  149. {
  150. IASTracePrintf("SDO Property Error - Validate() - Tried to change a read only property...");
  151. }
  152. else
  153. {
  154. hr = ValidateProperty((*p).second, pValue);
  155. if ( SUCCEEDED(hr) )
  156. {
  157. if ( PROPERTY_SDO_NAME == ((*p).second)->GetId() )
  158. {
  159. if ( m_pParent )
  160. {
  161. if ( lstrcmpi(V_BSTR(((*p).second)->GetValue()),V_BSTR(pValue)) )
  162. {
  163. VARIANT_BOOL boolVal;
  164. hr = m_pParent->IsNameUnique(V_BSTR(pValue), &boolVal);
  165. if ( SUCCEEDED(hr) )
  166. {
  167. if ( VARIANT_TRUE == boolVal )
  168. hr = ((*p).second)->PutValue(pValue);
  169. else
  170. hr = E_INVALIDARG;
  171. }
  172. }
  173. else
  174. {
  175. hr = ((*p).second)->PutValue(pValue);
  176. }
  177. }
  178. }
  179. else
  180. {
  181. hr = ((*p).second)->PutValue(pValue);
  182. }
  183. }
  184. }
  185. }
  186. }
  187. catch(_com_error theComError)
  188. {
  189. IASTracePrintf("Error in SDO - PutProperty() - Caught COM exception...");
  190. hr = theComError.Error();
  191. }
  192. catch (...)
  193. {
  194. IASTracePrintf("Error in SDO - GetProperty() - Caught unknown exception...");
  195. hr = E_FAIL;
  196. }
  197. return hr;
  198. }
  199. /////////////////////////////////////////////////////////////////////////////
  200. STDMETHODIMP CSdo::ResetProperty(LONG Id)
  201. {
  202. CSdoLock theLock(*this);
  203. _ASSERT( m_fSdoInitialized );
  204. if ( ! m_fSdoInitialized )
  205. return E_FAIL;
  206. HRESULT hr = E_FAIL;
  207. try
  208. {
  209. PropertyMapIterator p = m_PropertyMap.find(Id);
  210. if ( p == m_PropertyMap.end() )
  211. {
  212. IASTracePrintf("Error in SDO - ResetProperty() - Property with ID = %d could not be found...", Id);
  213. hr = DISP_E_MEMBERNOTFOUND;
  214. }
  215. else
  216. {
  217. // Reset the property to its default value (if defined)
  218. //
  219. if ( ((*p).second)->GetFlags() & SDO_PROPERTY_HAS_DEFAULT )
  220. {
  221. ((*p).second)->Reset();
  222. ((*p).second)->SetUpdateValue();
  223. }
  224. else
  225. {
  226. IASTracePrintf("Error in SDO - ResetProperty() - Property with ID = %d does not have a default value...", Id);
  227. hr = E_INVALIDARG;
  228. }
  229. }
  230. }
  231. catch(_com_error theComError)
  232. {
  233. IASTracePrintf("Error in SDO - ResetProperty() - Caught COM exception...");
  234. hr = theComError.Error();
  235. }
  236. catch (...)
  237. {
  238. IASTracePrintf("Error in SDO - ResetProperty() - Caught unknown exception...");
  239. hr = E_FAIL;
  240. }
  241. return hr;
  242. }
  243. /////////////////////////////////////////////////////////////////////////////
  244. STDMETHODIMP CSdo::Apply()
  245. {
  246. CSdoLock theLock(*this);
  247. _ASSERT( m_fSdoInitialized );
  248. if ( ! m_fSdoInitialized )
  249. return E_FAIL;
  250. HRESULT hr = S_OK;
  251. try
  252. {
  253. if ( m_fPersistOnApply )
  254. hr = Save();
  255. }
  256. catch(_com_error theComError)
  257. {
  258. IASTracePrintf("Error in SDO - Apply() - Caught COM exception...");
  259. hr = theComError.Error();
  260. }
  261. catch (...)
  262. {
  263. IASTracePrintf("Error in SDO - Apply() - Caught unknown exception...");
  264. hr = E_FAIL;
  265. }
  266. return hr;
  267. }
  268. /////////////////////////////////////////////////////////////////////////////
  269. STDMETHODIMP CSdo::Restore()
  270. {
  271. CSdoLock theLock(*this);
  272. _ASSERT( m_fSdoInitialized );
  273. if ( ! m_fSdoInitialized )
  274. return E_FAIL;
  275. HRESULT hr = S_OK;
  276. try
  277. {
  278. if ( m_fPersistOnApply )
  279. {
  280. // Just return S_OK if we've never persisted the object
  281. //
  282. if ( m_fIsPersisted )
  283. {
  284. // Load the SDO properties from the persistent store
  285. //
  286. hr = Load();
  287. }
  288. }
  289. }
  290. catch(_com_error theComError)
  291. {
  292. IASTracePrintf("Error in SDO - Restore() - Caught COM exception...");
  293. hr = theComError.Error();
  294. }
  295. catch (...)
  296. {
  297. IASTracePrintf("Error in SDO - Restore() - Caught unknown exception...");
  298. hr = E_FAIL;
  299. }
  300. return hr;
  301. }
  302. /////////////////////////////////////////////////////////////////////////////
  303. STDMETHODIMP CSdo::get__NewEnum(IUnknown** ppEnumPropertyInfo)
  304. {
  305. CSdoLock theLock(*this);
  306. _ASSERT( m_fSdoInitialized );
  307. if ( ! m_fSdoInitialized )
  308. return E_FAIL;
  309. _ASSERT( NULL != ppEnumPropertyInfo );
  310. if ( NULL == ppEnumPropertyInfo )
  311. return E_POINTER;
  312. HRESULT hr = E_FAIL;
  313. EnumVARIANT* newEnum = NULL;
  314. try
  315. {
  316. vector<_variant_t> properties;
  317. VARIANT property;
  318. VariantInit(&property);
  319. PropertyMapIterator p = m_PropertyMap.begin();
  320. while ( p != m_PropertyMap.end() )
  321. {
  322. V_VT(&property) = VT_DISPATCH;
  323. V_DISPATCH(&property) = dynamic_cast<IDispatch*>(((*p).second)->GetPropertyInfo());
  324. properties.push_back(property);
  325. p++;
  326. }
  327. newEnum = new (std::nothrow) CComObject<EnumVARIANT>;
  328. if ( newEnum == NULL )
  329. {
  330. IASTracePrintf("Error in SDO - get__NewEnum() - Out of memory...");
  331. return E_OUTOFMEMORY;
  332. }
  333. hr = newEnum->Init(
  334. properties.begin(),
  335. properties.end(),
  336. static_cast<IUnknown*>(this),
  337. AtlFlagCopy
  338. );
  339. if ( SUCCEEDED(hr) )
  340. {
  341. (*ppEnumPropertyInfo = newEnum)->AddRef();
  342. return S_OK;
  343. }
  344. }
  345. catch(...)
  346. {
  347. IASTracePrintf("Error in SDO - get__NewEnum() - Caught unknown exception...");
  348. hr = E_FAIL;
  349. }
  350. if ( newEnum )
  351. delete newEnum;
  352. return hr;
  353. }
  354. //////////////////////////////////////////////////////////////////////////////
  355. // SDO Base Class Functions
  356. //////////////////////////////////////////////////////////////////////////////
  357. //////////////////////////////////////////////////////////////////////////////
  358. HRESULT CSdo::InternalInitialize(
  359. /*[in]*/ LPCWSTR lpszSdoName,
  360. /*[in]*/ LPCWSTR lpszSdoProgId,
  361. /*[in]*/ ISdoMachine* pAttachedMachine,
  362. /*[in]*/ IDataStoreObject* pDSObject,
  363. /*[in]*/ ISdoCollection* pParent,
  364. /*[in]*/ bool fInitNew
  365. )
  366. {
  367. // Check precondtions
  368. //
  369. _ASSERT( NULL != lpszSdoProgId && NULL != pAttachedMachine );
  370. HRESULT hr = S_OK;
  371. if ( ! m_fSdoInitialized )
  372. {
  373. try
  374. {
  375. // Get the SDO schema class for lpszSdoClassId
  376. //
  377. CComPtr<IUnknown> pUnknown;
  378. CComPtr<ISdoSchema> pSdoSchema;
  379. hr = pAttachedMachine->GetSDOSchema(&pUnknown);
  380. if ( FAILED(hr) )
  381. throw _com_error(hr);
  382. hr = pUnknown->QueryInterface(IID_ISdoSchema, (void**)&pSdoSchema);
  383. if ( FAILED(hr) )
  384. throw _com_error(hr);
  385. pUnknown.Release();
  386. _bstr_t classId = lpszSdoProgId;
  387. hr = pSdoSchema->GetClass(classId, &pUnknown);
  388. if ( FAILED(hr) )
  389. throw _com_error(hr);
  390. CComPtr<ISdoClassInfo> pSdoClassInfo;
  391. hr = pUnknown->QueryInterface(IID_ISdoClassInfo, (void**)&pSdoClassInfo);
  392. if ( FAILED(hr) )
  393. throw _com_error(hr);
  394. // Initialize the SDO's properties from the schema class
  395. //
  396. AllocateProperties(pSdoClassInfo);
  397. // Set the SDO's class
  398. //
  399. PropertyMapIterator p = m_PropertyMap.find(PROPERTY_SDO_CLASS);
  400. _ASSERT( p != m_PropertyMap.end() );
  401. _variant_t vtClass = ::GetDataStoreClass(lpszSdoProgId);
  402. ((*p).second)->PutValue(&vtClass);
  403. // Set the SDO's name (if provided)
  404. //
  405. if ( lpszSdoName )
  406. {
  407. _variant_t vtName = lpszSdoName;
  408. hr = PutPropertyInternal(PROPERTY_SDO_NAME, &vtName);
  409. if ( FAILED(hr) )
  410. throw _com_error(hr);
  411. }
  412. // Save a reference to the parent object
  413. //
  414. if ( pParent )
  415. {
  416. m_pParent = pParent;
  417. // m_pParent->AddRef(); Weak reference for now
  418. }
  419. // Save a reference to the data store object used to persist this objects state
  420. //
  421. if ( pDSObject )
  422. {
  423. m_pDSObject = pDSObject;
  424. m_pDSObject->AddRef();
  425. m_fPersistOnApply = TRUE;
  426. }
  427. hr = FinalInitialize(fInitNew, pAttachedMachine);
  428. if ( FAILED(hr) )
  429. throw _com_error(hr);
  430. // Set the SDO's state to "initialized"
  431. //
  432. m_fSdoInitialized = TRUE;
  433. }
  434. catch(_com_error theError)
  435. {
  436. IASTracePrintf("Error in SDO - InternalInitialize() - Caught com_error exception...");
  437. InternalShutdown();
  438. hr = theError.Error();
  439. }
  440. catch(...)
  441. {
  442. IASTracePrintf("Error in SDO - InternalInitialize() - Caught unknown exception...");
  443. InternalShutdown();
  444. hr = E_FAIL;
  445. }
  446. }
  447. return hr;
  448. }
  449. //////////////////////////////////////////////////////////////////////////
  450. HRESULT CSdo::InternalInitialize(
  451. /*[in]*/ LPCWSTR lpszSdoName,
  452. /*[in]*/ LPCWSTR lpszSdoProgId,
  453. /*[in]*/ ISdoSchema* pSdoSchema,
  454. /*[in]*/ IDataStoreObject* pDSObject,
  455. /*[in]*/ ISdoCollection* pParent,
  456. /*[in]*/ bool fInitNew
  457. )
  458. {
  459. // Check precondtions
  460. //
  461. _ASSERT( NULL != lpszSdoProgId && NULL != pSdoSchema );
  462. HRESULT hr = S_OK;
  463. if ( ! m_fSdoInitialized )
  464. {
  465. try
  466. {
  467. // Get the SDO schema class for lpszSdoClassId
  468. //
  469. CComPtr<IUnknown> pUnknown;
  470. _bstr_t classId = lpszSdoProgId;
  471. hr = pSdoSchema->GetClass(classId, &pUnknown);
  472. if ( FAILED(hr) )
  473. throw _com_error(hr);
  474. CComPtr<ISdoClassInfo> pSdoClassInfo;
  475. hr = pUnknown->QueryInterface(IID_ISdoClassInfo, (void**)&pSdoClassInfo);
  476. if ( FAILED(hr) )
  477. throw _com_error(hr);
  478. // Initialize the SDO's properties from the schema class
  479. //
  480. AllocateProperties(pSdoClassInfo);
  481. // Set the SDO's class
  482. //
  483. PropertyMapIterator p = m_PropertyMap.find(PROPERTY_SDO_CLASS);
  484. _ASSERT( p != m_PropertyMap.end() );
  485. _variant_t vtClass = ::GetDataStoreClass(lpszSdoProgId);
  486. ((*p).second)->PutValue(&vtClass);
  487. // Set the SDO's name (if provided)
  488. //
  489. if ( lpszSdoName )
  490. {
  491. _variant_t vtName = lpszSdoName;
  492. hr = PutPropertyInternal(PROPERTY_SDO_NAME, &vtName);
  493. if ( FAILED(hr) )
  494. throw _com_error(hr);
  495. }
  496. // Save a reference to the parent object
  497. //
  498. if ( pParent )
  499. {
  500. m_pParent = pParent;
  501. // m_pParent->AddRef(); Weak reference for now...
  502. }
  503. // Save a reference to the data store object used to persist this objects state
  504. //
  505. if ( pDSObject )
  506. {
  507. m_pDSObject = pDSObject;
  508. m_pDSObject->AddRef();
  509. m_fPersistOnApply = TRUE;
  510. }
  511. hr = FinalInitialize(fInitNew, NULL);
  512. if ( FAILED(hr) )
  513. throw _com_error(hr);
  514. // Set the SDO's state to "initialized"
  515. //
  516. m_fSdoInitialized = TRUE;
  517. }
  518. catch(_com_error theError)
  519. {
  520. IASTracePrintf("Error in SDO - InternalInitialize() - Caught com_error exception...");
  521. InternalShutdown();
  522. hr = theError.Error();
  523. }
  524. catch(...)
  525. {
  526. IASTracePrintf("Error in SDO - InternalInitialize() - Caught unknown exception...");
  527. InternalShutdown();
  528. hr = E_FAIL;
  529. }
  530. }
  531. return hr;
  532. }
  533. //////////////////////////////////////////////////////////////////////////////
  534. HRESULT CSdo::FinalInitialize(
  535. /*[in]*/ bool fInitNew,
  536. /*[in]*/ ISdoMachine* pAttachedMachine
  537. )
  538. {
  539. if ( fInitNew )
  540. return S_OK;
  541. else
  542. return LoadProperties();
  543. }
  544. //////////////////////////////////////////////////////////////////////////////
  545. void CSdo::InternalShutdown()
  546. {
  547. if ( m_pParent )
  548. {
  549. // m_pParent->Release(); Weak reference for now...
  550. m_pParent = NULL;
  551. }
  552. if ( m_pDSObject )
  553. {
  554. m_pDSObject->Release();
  555. m_pDSObject = NULL;
  556. }
  557. FreeProperties();
  558. m_fSdoInitialized = FALSE;
  559. }
  560. ////////////////////////////////////////////////////////////////////////////
  561. void CSdo::AllocateProperties(
  562. /*[in]*/ ISdoClassInfo* pSdoClassInfo
  563. ) throw (_com_error)
  564. {
  565. HRESULT hr = E_FAIL;
  566. SDO_TRACE_VERBOSE_1("Allocating properties for the SDO at $%p...",this);
  567. do
  568. {
  569. CComPtr<IEnumVARIANT> pPropertyEnum;
  570. hr = ::SDOGetClassPropertyEnumerator(PROPERTY_SET_REQUIRED, pSdoClassInfo, &pPropertyEnum);
  571. if ( FAILED(hr) )
  572. {
  573. IASTracePrintf("Error in SDO - AllocateProperties() - Could not get required property enumerator failed...");
  574. throw _com_error(hr);
  575. }
  576. CComPtr<ISdoPropertyInfo> pSdoPropertyInfo;
  577. hr = ::SDONextPropertyFromClass(pPropertyEnum, &pSdoPropertyInfo);
  578. while ( S_OK == hr )
  579. {
  580. {
  581. auto_ptr<SDOPROPERTY> pProperty (new CSdoProperty(pSdoPropertyInfo, SDO_PROPERTY_MANDATORY));
  582. pair<PropertyMapIterator, bool> thePair = m_PropertyMap.insert(PropertyMap::value_type(pProperty->GetId(), pProperty.get()));
  583. if ( false == thePair.second )
  584. throw _com_error(E_FAIL);
  585. pProperty.release();
  586. SDO_TRACE_VERBOSE_3("Allocated property '%ls' of type %d for the SDO at $%p ", pProperty->GetName(), pProperty->GetType(), this);
  587. }
  588. pSdoPropertyInfo.Release();
  589. hr = ::SDONextPropertyFromClass(pPropertyEnum, &pSdoPropertyInfo);
  590. }
  591. if ( S_FALSE == hr )
  592. {
  593. pPropertyEnum.Release();
  594. hr = ::SDOGetClassPropertyEnumerator(PROPERTY_SET_OPTIONAL, pSdoClassInfo, &pPropertyEnum);
  595. if ( FAILED(hr) )
  596. {
  597. IASTracePrintf("Error in SDO - AllocateProperties() - Could not get optional property enumerator failed...");
  598. throw _com_error(hr);
  599. }
  600. hr = ::SDONextPropertyFromClass(pPropertyEnum, &pSdoPropertyInfo);
  601. while ( S_OK == hr )
  602. {
  603. {
  604. auto_ptr<SDOPROPERTY> pProperty (new CSdoProperty(pSdoPropertyInfo));
  605. pair<PropertyMapIterator, bool> thePair = m_PropertyMap.insert(PropertyMap::value_type(pProperty->GetId(), pProperty.get()));
  606. if ( false == thePair.second )
  607. throw _com_error(E_FAIL);
  608. pProperty.release();
  609. SDO_TRACE_VERBOSE_3("Allocated property '%ls' of type %d for the SDO at $%p ", pProperty->GetName(), pProperty->GetType(), this);
  610. }
  611. pSdoPropertyInfo.Release();
  612. hr = ::SDONextPropertyFromClass(pPropertyEnum, &pSdoPropertyInfo);
  613. }
  614. if ( S_FALSE != hr )
  615. throw _com_error(hr);
  616. }
  617. else
  618. {
  619. throw _com_error(hr);
  620. }
  621. } while ( FALSE );
  622. }
  623. ////////////////////////////////////////////////////////////////////////////
  624. void CSdo::FreeProperties(void)
  625. {
  626. PropertyMapIterator p;
  627. SDO_TRACE_VERBOSE_1("Releasing properties for the SDO at $%p...",this);
  628. // Delete the properties we've allocated
  629. //
  630. p = m_PropertyMap.begin();
  631. while ( p != m_PropertyMap.end() )
  632. {
  633. SDO_TRACE_VERBOSE_3("Released property '%ls' of type %d from the SDO at $%p...",((*p).second)->GetName(),((*p).second)->GetType(), this);
  634. delete (*p).second; // Invokes ~CSdoProperty()
  635. p = m_PropertyMap.erase(p);
  636. }
  637. }
  638. //////////////////////////////////////////////////////////////////////////////
  639. HRESULT CSdo::LoadProperties()
  640. {
  641. HRESULT hr = S_OK;
  642. // Check preconditions
  643. //
  644. _ASSERT ( NULL != m_pDSObject );
  645. SDO_TRACE_VERBOSE_1("Loading properties for the SDO at $%p...",this);
  646. // The state of the object before the LoadProperties() operation
  647. // should be preserved in the event of a load failure. Thus, if
  648. // any single property fails to load then the entire load
  649. // operation fails and the state of the object remains unchanged.
  650. PropertyMapIterator p = m_PropertyMap.begin();
  651. while ( p != m_PropertyMap.end() )
  652. {
  653. // Load only persistent properties
  654. //
  655. if ( ! ( ((*p).second)->GetFlags() & SDO_PROPERTY_NO_PERSIST ) )
  656. {
  657. // Get the property value from the data store object
  658. //
  659. if ( ((*p).second)->GetFlags() & SDO_PROPERTY_MULTIVALUED )
  660. hr = m_pDSObject->GetValueEx(((*p).second)->GetName(), ((*p).second)->GetUpdateValue());
  661. else
  662. hr = m_pDSObject->GetValue(((*p).second)->GetName(), ((*p).second)->GetUpdateValue());
  663. if ( SUCCEEDED(hr) )
  664. {
  665. SDO_TRACE_VERBOSE_3("Loaded property '%ls' of type %d for the SDO at $%p...", ((*p).second)->GetName(), ((*p).second)->GetType(), this);
  666. }
  667. else
  668. {
  669. // If a mandatory property fails to load and we don't have a default value for it
  670. // then we have an error condition
  671. //
  672. if ( ((*p).second)->GetFlags() & SDO_PROPERTY_MANDATORY )
  673. {
  674. if ( ((*p).second)->GetFlags() & SDO_PROPERTY_HAS_DEFAULT )
  675. {
  676. SDO_TRACE_VERBOSE_1("SDO - LoadProperties() - GetValue('%ls') failed...",((*p).second)->GetName());
  677. }
  678. else
  679. {
  680. IASTracePrintf("Error in SDO - LoadProperties() - Mandatory property '%ls' failed to load...", ((*p).second)->GetName());
  681. break;
  682. }
  683. }
  684. else
  685. {
  686. SDO_TRACE_VERBOSE_1("SDO - LoadProperties() - GetValue('%ls') failed...",((*p).second)->GetName());
  687. }
  688. ((*p).second)->Reset();
  689. hr = S_OK;
  690. }
  691. }
  692. p++;
  693. }
  694. // Use the newly loaded values and flag the object as
  695. // persisted so that it can be restored via ISdo::Restore()
  696. //
  697. if ( SUCCEEDED(hr) )
  698. {
  699. p = m_PropertyMap.begin();
  700. while ( p != m_PropertyMap.end() )
  701. {
  702. if ( ! (((*p).second)->GetFlags() & SDO_PROPERTY_NO_PERSIST) )
  703. ((*p).second)->SetUpdateValue();
  704. p++;
  705. }
  706. m_fIsPersisted = TRUE;
  707. }
  708. else
  709. {
  710. while ( p != m_PropertyMap.begin() )
  711. {
  712. if ( ! (((*p).second)->GetFlags() & SDO_PROPERTY_NO_PERSIST) )
  713. VariantClear(((*p).second)->GetUpdateValue());
  714. p--;
  715. }
  716. }
  717. return hr;
  718. }
  719. //////////////////////////////////////////////////////////////////////////////
  720. HRESULT CSdo::SaveProperties()
  721. {
  722. HRESULT hr = S_OK;
  723. // Check preconditions
  724. //
  725. _ASSERT ( NULL != m_pDSObject );
  726. SDO_TRACE_VERBOSE_1("Saving properties for the SDO at $%p...",this);
  727. // Put the SDO property values into the underlying data store
  728. //
  729. PropertyMapIterator p = m_PropertyMap.begin();
  730. while ( p != m_PropertyMap.end() )
  731. {
  732. // Make sure we're supposed to persist this property
  733. //
  734. if ( ! ( ((*p).second)->GetFlags() & SDO_PROPERTY_NO_PERSIST) )
  735. {
  736. // Empty properties don't get persisted
  737. //
  738. if ( VT_EMPTY == V_VT(((*p).second)->GetValue()) )
  739. {
  740. // Mandatory properties cannot be empty
  741. //
  742. if ( ((*p).second)->GetFlags() & SDO_PROPERTY_MANDATORY )
  743. {
  744. _ASSERT(FALSE); // Contractual Error (precondition violation)
  745. hr = E_FAIL;
  746. break;
  747. }
  748. }
  749. // Persist the property
  750. //
  751. hr = m_pDSObject->PutValue(((*p).second)->GetName(), ((*p).second)->GetValue());
  752. if ( FAILED(hr) )
  753. {
  754. IASTracePrintf("Error in SDO - SaveProperties() - Could not persist SDO changes because PutValue() failed for property '%ls'...", ((*p).second)->GetName());
  755. break;
  756. }
  757. SDO_TRACE_VERBOSE_3("Saved property '%ls' of type %d from the SDO at $%p...", ((*p).second)->GetName(), ((*p).second)->GetType(), this);
  758. }
  759. p++;
  760. }
  761. if ( SUCCEEDED(hr) )
  762. {
  763. // Now persist the changes
  764. //
  765. hr = m_pDSObject->Update();
  766. if ( SUCCEEDED(hr) )
  767. {
  768. // Flag the object as persisted so that it can be restored via ISdo::Restore()
  769. //
  770. m_fIsPersisted = TRUE;
  771. }
  772. else
  773. {
  774. IASTracePrintf("Error in SDO - SaveProperties() - Could not persist the SDO changes because Update() failed...");
  775. }
  776. }
  777. return hr;
  778. }
  779. //////////////////////////////////////////////////////////////////////////
  780. HRESULT CSdo::GetPropertyInternal(
  781. /*[in]*/ LONG lPropertyId,
  782. /*[in]*/ VARIANT* pValue
  783. ) throw()
  784. {
  785. HRESULT hr = E_FAIL;
  786. PropertyMapIterator p = m_PropertyMap.find(lPropertyId);
  787. _ASSERT( p != m_PropertyMap.end() );
  788. if ( p != m_PropertyMap.end() )
  789. {
  790. hr = ((*p).second)->GetValue(pValue);
  791. _ASSERT( SUCCEEDED(hr) );
  792. if ( FAILED(hr) )
  793. IASTracePrintf("Error in SDO - GetPropertyInternal() - GetValue() failed...\n");
  794. }
  795. else
  796. {
  797. IASTracePrintf("Error in SDO - GetPropertyInternal() - Invalid property Id...\n");
  798. }
  799. return hr;
  800. }
  801. //////////////////////////////////////////////////////////////////////////
  802. HRESULT CSdo::PutPropertyInternal(
  803. /*[in]*/ LONG lPropertyId,
  804. /*[in]*/ VARIANT* pValue
  805. ) throw()
  806. {
  807. HRESULT hr = E_FAIL;
  808. PropertyMapIterator p = m_PropertyMap.find(lPropertyId);
  809. _ASSERT( p != m_PropertyMap.end() );
  810. if ( p != m_PropertyMap.end() )
  811. {
  812. hr = ((*p).second)->PutValue(pValue);
  813. _ASSERT( SUCCEEDED(hr) );
  814. if ( FAILED(hr) )
  815. IASTracePrintf("Error in SDO - PutPropertyInternal() - PutValue() failed...\n");
  816. }
  817. else
  818. {
  819. IASTracePrintf("Error in SDO - PutPropertyInternal() - Invalid property Id...\n");
  820. }
  821. return hr;
  822. }
  823. //////////////////////////////////////////////////////////////////////////
  824. HRESULT CSdo::ChangePropertyDefaultInternal(
  825. /*[in]*/ LONG lPropertyId,
  826. /*[in]*/ VARIANT* pValue
  827. ) throw()
  828. {
  829. HRESULT hr = E_FAIL;
  830. PropertyMapIterator p = m_PropertyMap.find(lPropertyId);
  831. _ASSERT( p != m_PropertyMap.end() );
  832. if ( p != m_PropertyMap.end() )
  833. {
  834. hr = ((*p).second)->PutDefault(pValue);
  835. _ASSERT( SUCCEEDED(hr) );
  836. if ( FAILED(hr) )
  837. IASTracePrintf("Error in SDO - ChangePropertyDefault() - PutDefault() failed...\n");
  838. }
  839. else
  840. {
  841. IASTracePrintf("Error in SDO - ChangePropertyDefault() - Invalid property Id...\n");
  842. }
  843. return hr;
  844. }
  845. //////////////////////////////////////////////////////////////////////////////
  846. HRESULT CSdo::InitializeCollection(
  847. LONG CollectionPropertyId,
  848. LPCWSTR lpszCreateClassId,
  849. ISdoMachine* pSdoMachine,
  850. IDataStoreContainer* pDSContainer,
  851. size_t maxSize
  852. ) throw ()
  853. {
  854. ISdoCollection* pSdoCollection = ::MakeSDOCollection(
  855. lpszCreateClassId,
  856. pSdoMachine,
  857. pDSContainer,
  858. maxSize
  859. );
  860. if ( NULL == pSdoCollection )
  861. {
  862. IASTracePrintf("Error in SDO - InitializeCollection() - MakeSDOCollection failed...");
  863. return E_FAIL;
  864. }
  865. _variant_t vtDispatch;
  866. V_VT(&vtDispatch) = VT_DISPATCH;
  867. HRESULT hr = pSdoCollection->QueryInterface(IID_IDispatch, (void**)&vtDispatch.pdispVal);
  868. pSdoCollection->Release();
  869. if ( FAILED(hr) )
  870. {
  871. IASTracePrintf("Error in SDO - InitializeCollection() - QueryInterface(IDispatch) failed...");
  872. return hr;
  873. }
  874. hr = PutPropertyInternal(CollectionPropertyId, &vtDispatch);
  875. return hr;
  876. }
  877. //////////////////////////////////////////////////////////////////////////////
  878. HRESULT CSdo::Load(void)
  879. {
  880. return LoadProperties();
  881. }
  882. //////////////////////////////////////////////////////////////////////////////
  883. HRESULT CSdo::Save(void)
  884. {
  885. return SaveProperties();
  886. }
  887. //////////////////////////////////////////////////////////////////////////
  888. void CSdo::NoPersist(void)
  889. {
  890. if ( m_pDSObject )
  891. {
  892. m_pDSObject->Release();
  893. m_pDSObject = NULL;
  894. m_fPersistOnApply = FALSE;
  895. }
  896. }
  897. //////////////////////////////////////////////////////////////////////////
  898. HRESULT CSdo::ValidateProperty(
  899. /*[in]*/ PSDOPROPERTY pProperty,
  900. /*[in]*/ VARIANT* pValue
  901. )
  902. {
  903. return pProperty->Validate(pValue);
  904. }
  905. //////////////////////////////////////////////////////////////////////////
  906. HRESULT CSdo::GetDatastoreName(VARIANT* pDSName)
  907. {
  908. HRESULT hr = DISP_E_MEMBERNOTFOUND;
  909. if ( m_pDSObject )
  910. {
  911. BSTR bstrDSName;
  912. hr = m_pDSObject->get_Name(&bstrDSName);
  913. if ( SUCCEEDED(hr) )
  914. {
  915. VariantInit(pDSName);
  916. V_VT(pDSName) = VT_BSTR;
  917. V_BSTR(pDSName) = bstrDSName;
  918. }
  919. else
  920. {
  921. IASTracePrintf("Error in SDO - GetDatastoreName() - get_Name() failed...");
  922. }
  923. }
  924. return hr;
  925. }