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.

1761 lines
58 KiB

  1. //
  2. // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
  3. //
  4. // ***************************************************************************
  5. //
  6. // Original Author: Rajesh Rao
  7. //
  8. // $Author: rajeshr $
  9. // $Date: 6/11/98 4:43p $
  10. // $Workfile:ldapprov.cpp $
  11. //
  12. // $Modtime: 6/11/98 11:21a $
  13. // $Revision: 1 $
  14. // $Nokeywords: $
  15. //
  16. //
  17. // Description: Contains implementation of the DS LDAP Class Provider class.
  18. //
  19. //***************************************************************************
  20. #include "precomp.h"
  21. /////////////////////////////////////////
  22. // Initialize the static members
  23. /////////////////////////////////////////
  24. CLDAPCache *CLDAPClassProvider :: s_pLDAPCache = NULL;
  25. DWORD CLDAPClassProvider::dwClassProviderCount = 0;
  26. BSTR CLDAPClassProvider:: LDAP_BASE_CLASS_STR = NULL;
  27. BSTR CLDAPClassProvider:: LDAP_CLASS_PROVIDER_NAME = NULL;
  28. BSTR CLDAPClassProvider:: LDAP_INSTANCE_PROVIDER_NAME = NULL;
  29. // Names of the LDAP class attributes
  30. BSTR CLDAPClassProvider :: COMMON_NAME_ATTR_BSTR = NULL;
  31. BSTR CLDAPClassProvider :: LDAP_DISPLAY_NAME_ATTR_BSTR = NULL;
  32. BSTR CLDAPClassProvider :: GOVERNS_ID_ATTR_BSTR = NULL;
  33. BSTR CLDAPClassProvider :: SCHEMA_ID_GUID_ATTR_BSTR = NULL;
  34. BSTR CLDAPClassProvider :: MAPI_DISPLAY_TYPE_ATTR_BSTR = NULL;
  35. BSTR CLDAPClassProvider :: RDN_ATT_ID_ATTR_BSTR = NULL;
  36. BSTR CLDAPClassProvider :: SYSTEM_MUST_CONTAIN_ATTR_BSTR = NULL;
  37. BSTR CLDAPClassProvider :: MUST_CONTAIN_ATTR_BSTR = NULL;
  38. BSTR CLDAPClassProvider :: SYSTEM_MAY_CONTAIN_ATTR_BSTR = NULL;
  39. BSTR CLDAPClassProvider :: MAY_CONTAIN_ATTR_BSTR = NULL;
  40. BSTR CLDAPClassProvider :: SYSTEM_POSS_SUPERIORS_ATTR_BSTR = NULL;
  41. BSTR CLDAPClassProvider :: POSS_SUPERIORS_ATTR_BSTR = NULL;
  42. BSTR CLDAPClassProvider :: SYSTEM_AUXILIARY_CLASS_ATTR_BSTR = NULL;
  43. BSTR CLDAPClassProvider :: AUXILIARY_CLASS_ATTR_BSTR = NULL;
  44. BSTR CLDAPClassProvider :: DEFAULT_SECURITY_DESCRP_ATTR_BSTR= NULL;
  45. BSTR CLDAPClassProvider :: OBJECT_CLASS_CATEGORY_ATTR_BSTR = NULL;
  46. BSTR CLDAPClassProvider :: SYSTEM_ONLY_ATTR_BSTR = NULL;
  47. BSTR CLDAPClassProvider :: NT_SECURITY_DESCRIPTOR_ATTR_BSTR = NULL;
  48. BSTR CLDAPClassProvider :: DEFAULT_OBJECTCATEGORY_ATTR_BSTR = NULL;
  49. // Names of the LDAP property attributes
  50. BSTR CLDAPClassProvider :: ATTRIBUTE_SYNTAX_ATTR_BSTR = NULL;
  51. BSTR CLDAPClassProvider :: ATTRIBUTE_ID_ATTR_BSTR = NULL;
  52. BSTR CLDAPClassProvider :: MAPI_ID_ATTR_BSTR = NULL;
  53. BSTR CLDAPClassProvider :: OM_SYNTAX_ATTR_BSTR = NULL;
  54. BSTR CLDAPClassProvider :: RANGE_LOWER_ATTR_BSTR = NULL;
  55. BSTR CLDAPClassProvider :: RANGE_UPPER_ATTR_BSTR = NULL;
  56. // Qualifiers for embedded objects
  57. BSTR CLDAPClassProvider :: CIMTYPE_STR = NULL;
  58. BSTR CLDAPClassProvider :: EMBED_UINT8ARRAY = NULL;
  59. BSTR CLDAPClassProvider :: EMBED_DN_WITH_STRING = NULL;
  60. BSTR CLDAPClassProvider :: EMBED_DN_WITH_BINARY = NULL;
  61. // Default Qualifier Flavour
  62. LONG CLDAPClassProvider :: DEFAULT_QUALIFIER_FLAVOUR = WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE | WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS | WBEM_FLAVOR_OVERRIDABLE ;
  63. // Names of WBEM Class Qualifiers
  64. BSTR CLDAPClassProvider:: DYNAMIC_BSTR = NULL;
  65. BSTR CLDAPClassProvider:: PROVIDER_BSTR = NULL;
  66. BSTR CLDAPClassProvider:: ABSTRACT_BSTR = NULL;
  67. // Names of WBEM Property Qualifiers
  68. BSTR CLDAPClassProvider :: SYSTEM_BSTR = NULL;
  69. BSTR CLDAPClassProvider :: NOT_NULL_BSTR = NULL;
  70. BSTR CLDAPClassProvider :: INDEXED_BSTR = NULL;
  71. // Names of WBEM properties
  72. BSTR CLDAPClassProvider :: DYNASTY_BSTR = NULL;
  73. //***************************************************************************
  74. //
  75. // CLDAPClassProvider::CLDAPClassProvider
  76. // CLDAPClassProvider::~CLDAPClassProvider
  77. //
  78. // Constructor Parameters:
  79. // None
  80. //***************************************************************************
  81. CLDAPClassProvider :: CLDAPClassProvider ()
  82. : CDSClassProvider()
  83. {
  84. // Initialize the search preferences often used
  85. m_searchInfo1.dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  86. m_searchInfo1.vValue.Integer = ADS_SCOPE_ONELEVEL;
  87. m_searchInfo1.dwStatus = ADS_STATUS_S_OK;
  88. m_pLDAPBaseClass = NULL;
  89. dwClassProviderCount++;
  90. }
  91. CLDAPClassProvider::~CLDAPClassProvider ()
  92. {
  93. g_pLogObject->WriteW( L"CLDAPClassProvider :: ~CLDAPClassProvider() Called\r\n");
  94. dwClassProviderCount --;
  95. if(m_pLDAPBaseClass)
  96. m_pLDAPBaseClass->Release();
  97. }
  98. //***************************************************************************
  99. //
  100. // CLDAPClassProvider::Initialize
  101. //
  102. // Purpose:
  103. // As defined by the IWbemProviderInit interface
  104. //
  105. // Parameters:
  106. // As defined by IWbemProviderInit interface
  107. //
  108. // Return Value: The COM status value indicating the status of the request
  109. //***************************************************************************
  110. HRESULT CLDAPClassProvider :: Initialize(
  111. LPWSTR wszUser,
  112. LONG lFlags,
  113. LPWSTR wszNamespace,
  114. LPWSTR wszLocale,
  115. IWbemServices __RPC_FAR *pNamespace,
  116. IWbemContext __RPC_FAR *pCtx,
  117. IWbemProviderInitSink __RPC_FAR *pInitSink)
  118. {
  119. // Validate the arguments
  120. if( pNamespace == NULL || lFlags != 0 )
  121. {
  122. g_pLogObject->WriteW( L"CLDAPClassProvider :: Argument validation FAILED\r\n");
  123. pInitSink->SetStatus(WBEM_E_FAILED, 0);
  124. return WBEM_S_NO_ERROR;
  125. }
  126. g_pLogObject->WriteW( L"CLDAPClassProvider :: Initialize() Called\r\n");
  127. // Store the IWbemServices pointer for future use
  128. m_IWbemServices = pNamespace;
  129. m_IWbemServices->AddRef();
  130. // Do LDAP Provider initialization
  131. if(!InitializeLDAPProvider(pCtx))
  132. {
  133. g_pLogObject->WriteW( L"CLDAPClassProvider :: InitializeLDAPProvider FAILED\r\n");
  134. m_IWbemServices->Release();
  135. m_IWbemServices = NULL;
  136. // Do not set the status to failed for purposes of installation (MOFCOMP fails!)
  137. // Instead return a success but set an internal status value to FALSE
  138. // All operations should return FAILED if this internal status value is set to FALSE
  139. m_bInitializedSuccessfully = FALSE;
  140. }
  141. else
  142. m_bInitializedSuccessfully = TRUE;
  143. pInitSink->SetStatus(WBEM_S_INITIALIZED, 0);
  144. return WBEM_S_NO_ERROR;
  145. }
  146. //***************************************************************************
  147. //
  148. // CLDAPClassProvider::InitializeLDAPProvider
  149. //
  150. // Purpose: A helper function to do the ADSI LDAP provider specific initialization.
  151. //
  152. // Parameters:
  153. // pCtx The context object used in this call initialization
  154. //
  155. // Return Value: TRUE if the function successfully finishes the initializaion. FALSE
  156. // otherwise
  157. //***************************************************************************
  158. BOOLEAN CLDAPClassProvider :: InitializeLDAPProvider(IWbemContext *pCtx)
  159. {
  160. // Get the static classes used by the LDAP provider
  161. HRESULT result = WBEM_E_FAILED;
  162. if(SUCCEEDED(result = m_IWbemServices->GetObject(LDAP_BASE_CLASS_STR, 0, pCtx, &m_pLDAPBaseClass, NULL)))
  163. {
  164. result = (s_pLDAPCache->IsInitialized())? S_OK : E_FAIL;
  165. }
  166. else
  167. g_pLogObject->WriteW( L"CLDAPClassProvider :: InitializeLDAPProvider GetObject on base LDAP class FAILED : %x\r\n", result);
  168. return SUCCEEDED(result);
  169. }
  170. //***************************************************************************
  171. //
  172. // CLDAPClassProvider::GetADSIClass
  173. //
  174. // Purpose : To Create a CADSIClass from an ADSI classSchema object
  175. // Parameters:
  176. // lpszWBEMClassName : The WBEM Name of the class to be fetched.
  177. // ppADSIClass : The address where the pointer to the CADSIClass will be stored.
  178. // It is the caller's responsibility to Release() the object when done with it
  179. //
  180. // Return Value: The COM status value indicating the status of the request.
  181. //***************************************************************************
  182. HRESULT CLDAPClassProvider :: GetADSIClass(LPCWSTR lpszADSIClassName, CADSIClass **ppADSIClass)
  183. {
  184. // Convert the WBEM Class Name to LDAP
  185. LPWSTR lpszWBEMClassName = CLDAPHelper::MangleLDAPNameToWBEM(lpszADSIClassName);
  186. HRESULT result = s_pLDAPCache->GetClass(lpszWBEMClassName, lpszADSIClassName, ppADSIClass);
  187. delete[] lpszWBEMClassName;
  188. return result;
  189. }
  190. //***************************************************************************
  191. //
  192. // CLDAPClassProvider::GetADSIProperty
  193. //
  194. // Purpose : To create an CADSIProperty object from an LDAP AttributeSchema object
  195. // Parameters:
  196. // lpszPropertyName : The LDAPDisplayName of the LDAP property to be fetched.
  197. // ppADSIProperty : The address where the pointer to the IDirectoryObject interface will be stored
  198. // It is the caller's responsibility to Release() the interface when done with it
  199. //
  200. // Return Value: The COM status value indicating the status of the request
  201. //***************************************************************************
  202. HRESULT CLDAPClassProvider :: GetADSIProperty(LPCWSTR lpszPropertyName, CADSIProperty **ppADSIProperty)
  203. {
  204. HRESULT hRes = WBEM_S_NO_ERROR;
  205. if ( ppADSIProperty )
  206. {
  207. if ( SUCCEEDED ( hRes = s_pLDAPCache->GetProperty(lpszPropertyName, ppADSIProperty, FALSE) ) )
  208. {
  209. if ( NULL == *ppADSIProperty )
  210. {
  211. hRes = WBEM_S_FALSE;
  212. }
  213. }
  214. }
  215. else
  216. {
  217. hRes = WBEM_E_INVALID_PARAMETER;
  218. }
  219. return hRes;
  220. }
  221. //***************************************************************************
  222. //
  223. // CLDAPClassProvider::GetWBEMBaseClassName
  224. //
  225. // Purpose : Returns the name of the class that is the base class of all classes
  226. // provided by this provider.
  227. //
  228. // Parameters:
  229. // None
  230. //
  231. // Return Value: The name of the base class. NULL if such a class doesnt exist.
  232. //***************************************************************************
  233. const BSTR CLDAPClassProvider :: GetWBEMBaseClassName()
  234. {
  235. return LDAP_BASE_CLASS_STR;
  236. }
  237. //***************************************************************************
  238. //
  239. // CLDAPClassProvider::GetWBEMBaseClass
  240. //
  241. // Purpose : Returns a pointer to the class that is the base class of all classes
  242. // provided by this provider.
  243. //
  244. // Parameters:
  245. // None
  246. //
  247. // Return Value: The IWbemClassObject pointer to the base class. It is the duty of
  248. // user to release the class when done with using it.
  249. //***************************************************************************
  250. IWbemClassObject * CLDAPClassProvider :: GetWBEMBaseClass()
  251. {
  252. m_pLDAPBaseClass->AddRef();
  253. return m_pLDAPBaseClass;
  254. }
  255. //***************************************************************************
  256. //
  257. // CLDAPClassProvider::GetWBEMProviderName
  258. //
  259. // Purpose : Returns the name of the provider. This should be the same as the
  260. // value of the field Name in the __Win32Provider instance used for registration
  261. // of the provider
  262. //
  263. // Parameters:
  264. // None
  265. //
  266. // Return Value: The name of the provider
  267. //***************************************************************************
  268. const BSTR CLDAPClassProvider :: GetWBEMProviderName()
  269. {
  270. return LDAP_CLASS_PROVIDER_NAME;
  271. }
  272. //***************************************************************************
  273. //
  274. // CLDAPClassProvider::IsUnProvidedClass
  275. //
  276. // Purpose : See header
  277. //***************************************************************************
  278. BOOLEAN CLDAPClassProvider :: IsUnProvidedClass(LPCWSTR lpszClassName)
  279. {
  280. // CHeck if it is one of the static classes
  281. if(_wcsicmp(lpszClassName, LDAP_BASE_CLASS_STR) == 0 ||
  282. _wcsicmp(lpszClassName, UINT8ARRAY_CLASS) == 0 ||
  283. _wcsicmp(lpszClassName, DN_WITH_STRING_CLASS) == 0 ||
  284. _wcsicmp(lpszClassName, DN_WITH_BINARY_CLASS) == 0 ||
  285. _wcsicmp(lpszClassName, ROOTDSE_CLASS) == 0 ||
  286. _wcsicmp(lpszClassName, CLASS_ASSOCIATION_CLASS) == 0 ||
  287. _wcsicmp(lpszClassName, DN_ASSOCIATION_CLASS) == 0 ||
  288. _wcsicmp(lpszClassName, DN_CLASS) == 0 ||
  289. _wcsicmp(lpszClassName, INSTANCE_ASSOCIATION_CLASS) == 0)
  290. return TRUE;
  291. // Next check if it has appropriate profixes
  292. if(_wcsnicmp(lpszClassName, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX_LENGTH) == 0 ||
  293. _wcsnicmp(lpszClassName, LDAP_CLASS_NAME_PREFIX, LDAP_CLASS_NAME_PREFIX_LENGTH) == 0 )
  294. {
  295. return FALSE;
  296. }
  297. return TRUE;
  298. }
  299. //***************************************************************************
  300. //
  301. // CLDAPClassProvider::GetClassFromADSI
  302. //
  303. // Purpose : To return the IDirectoryObject interface on the schema container
  304. //
  305. // Parameters:
  306. // lpszClassName : The WBEM Name of the class to be retreived
  307. // pCtx : A pointer to the context object that was used in this call. This
  308. // may be used by this function to make calls to CIMOM
  309. // ppWbemClass : The resulting WBEM Class. This has to be released once the
  310. // user is done with it.
  311. //
  312. //
  313. // Return Value: The COM result representing the status.
  314. //***************************************************************************
  315. HRESULT CLDAPClassProvider :: GetClassFromADSI(
  316. LPCWSTR lpszWbemClassName,
  317. IWbemContext *pCtx,
  318. IWbemClassObject ** ppWbemClass
  319. )
  320. {
  321. HRESULT result = E_FAIL;
  322. BOOLEAN bArtificialClass = FALSE;
  323. BOOLEAN bAbstractDSClass = FALSE;
  324. LPWSTR lpszADSIClassName = NULL;
  325. // First check if this is one our "artificial" classes. All "aritificial" classes start with "ads_".
  326. // All non artificial classes start with "ds_"
  327. if(!(lpszADSIClassName = CLDAPHelper::UnmangleWBEMNameToLDAP(lpszWbemClassName)))
  328. {
  329. *ppWbemClass = NULL;
  330. return result;
  331. }
  332. if(_wcsnicmp(lpszWbemClassName, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX_LENGTH) == 0)
  333. bArtificialClass = TRUE;
  334. CADSIClass *pADSIClass = NULL;
  335. CADSIClass *pADSIParentClass = NULL;
  336. try
  337. {
  338. if(SUCCEEDED(result = GetADSIClass(lpszADSIClassName, &pADSIClass)))
  339. {
  340. pADSIClass->SetWBEMClassName(lpszWbemClassName);
  341. // It is an abstract class is the ADSI class type is Abstract or Auxiliary
  342. if(pADSIClass->GetObjectClassCategory() == 2 || pADSIClass->GetObjectClassCategory() == 3)
  343. bAbstractDSClass = TRUE;
  344. int iCaseNumber = 0;
  345. // if the WBEM class name starts with "ADS_" and the DS class is abstract, then this is an error
  346. if(bArtificialClass && bAbstractDSClass)
  347. result = WBEM_E_NOT_FOUND;
  348. else
  349. {
  350. // Special case for "top" since the DS returns top as the superclass of top
  351. if(_wcsicmp(lpszWbemClassName, TOP_CLASS) == 0)
  352. iCaseNumber = 1;
  353. else
  354. {
  355. if(pADSIClass->GetSuperClassLDAPName())
  356. {
  357. // If this is an artificial class
  358. // Then
  359. // Get the ParentDS Class
  360. // If the ParentDSClass is abstract
  361. // Then
  362. // WMI Parent class is the non-artificial class. Case 2
  363. // Else
  364. // WMI Parent class is artificial. Case 3
  365. // Else
  366. // If the Current DS Class is abstract
  367. // Then
  368. // WMI Parent is non-artificial. Case 4
  369. // Else
  370. // WMI Parent is artificial. Case 5
  371. //
  372. if(bArtificialClass)
  373. {
  374. // Get the parent DS Class
  375. if(SUCCEEDED(result = GetADSIClass(pADSIClass->GetSuperClassLDAPName(), &pADSIParentClass)))
  376. {
  377. if(pADSIParentClass->GetObjectClassCategory() == 2 || pADSIParentClass->GetObjectClassCategory() == 3)
  378. {
  379. iCaseNumber = 2;
  380. }
  381. else
  382. {
  383. iCaseNumber = 3;
  384. }
  385. }
  386. }
  387. else
  388. {
  389. if(bAbstractDSClass)
  390. {
  391. iCaseNumber = 4;
  392. }
  393. else
  394. {
  395. iCaseNumber = 5;
  396. }
  397. }
  398. }
  399. else
  400. iCaseNumber = 1;
  401. }
  402. // Map the ADSI class to a WBEM Class
  403. if(iCaseNumber != 0 && SUCCEEDED(result = CreateWBEMClass(pADSIClass, iCaseNumber, ppWbemClass, pCtx)))
  404. {
  405. }
  406. else
  407. {
  408. result = WBEM_E_FAILED;
  409. g_pLogObject->WriteW(L"CLDAPClassProvider :: GetClassFromADSI() : CreateWBEMClass FAILED: %x for %s\r\n", result, lpszWbemClassName);
  410. }
  411. }
  412. // Free the parent ADSI class
  413. if(pADSIParentClass)
  414. {
  415. pADSIParentClass->Release();
  416. pADSIParentClass = NULL;
  417. }
  418. // Free the ADSI Class
  419. if ( pADSIClass )
  420. {
  421. pADSIClass->Release();
  422. pADSIClass = NULL;
  423. }
  424. }
  425. else
  426. g_pLogObject->WriteW( L"CLDAPClassProvider :: GetClassFromADSI() GetADSIClass FAILED : %x for %s\r\n", result, lpszWbemClassName);
  427. }
  428. catch ( ... )
  429. {
  430. // Free the parent ADSI class
  431. if ( pADSIParentClass )
  432. {
  433. pADSIParentClass->Release();
  434. pADSIParentClass = NULL;
  435. }
  436. // Free the ADSI Class
  437. if ( pADSIClass )
  438. {
  439. pADSIClass->Release();
  440. pADSIClass = NULL;
  441. }
  442. delete [] lpszADSIClassName;
  443. throw;
  444. }
  445. delete [] lpszADSIClassName;
  446. return result;
  447. }
  448. //***************************************************************************
  449. //
  450. // CLDAPClassProvider::CreateWBEMClass
  451. //
  452. // Purpose: Creates WBEM Class corresponding an ADSI Class
  453. //
  454. // Parameters:
  455. // pADSIClass : A pointer to a CADSI class object that is to be mapped to WBEM.
  456. // ppWbemClass : The WBEM class object retrieved. This is created by this function.
  457. // The caller should release it when done
  458. // pCtx : The context object that was used in this provider call
  459. //
  460. // Return Value: The COM value representing the return status
  461. //
  462. //***************************************************************************
  463. HRESULT CLDAPClassProvider :: CreateWBEMClass (CADSIClass *pADSIClass, int iCaseNumber, IWbemClassObject **ppWbemClass, IWbemContext *pCtx)
  464. {
  465. HRESULT result;
  466. *ppWbemClass = NULL;
  467. // Create the WBEM class and Map the class qualifiers
  468. if( SUCCEEDED(result = MapClassSystemProperties(pADSIClass, iCaseNumber, ppWbemClass, pCtx) ) )
  469. {
  470. // Now that ppWbemClass has been allocated, we need to deallocate it if the return value of this function
  471. // is not a success
  472. //=======================================================================================================
  473. if(iCaseNumber == 5)
  474. {
  475. // Nothing more to do except add the "provider" qualifier
  476. IWbemQualifierSet *pQualifierSet = NULL;
  477. if(SUCCEEDED(result = (*ppWbemClass)->GetQualifierSet(&pQualifierSet)))
  478. {
  479. result = CWBEMHelper::PutBSTRQualifier(pQualifierSet, PROVIDER_BSTR, LDAP_INSTANCE_PROVIDER_NAME, DEFAULT_QUALIFIER_FLAVOUR, FALSE);
  480. pQualifierSet->Release();
  481. }
  482. }
  483. else
  484. {
  485. if( SUCCEEDED(result = MapClassQualifiersToWBEM(pADSIClass, iCaseNumber, *ppWbemClass, pCtx) ) )
  486. {
  487. // Map the class properties
  488. if( SUCCEEDED(result = MapClassPropertiesToWBEM(pADSIClass, *ppWbemClass, pCtx) ) )
  489. {
  490. }
  491. else
  492. g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateWBEMClass() MapClassPropertiesToWBEM FAILED : %x for %s\r\n", result, pADSIClass->GetWBEMClassName());
  493. }
  494. else
  495. g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateWBEMClass() MapClassQualifiersToWBEM FAILED : %x for %s\r\n", result, pADSIClass->GetWBEMClassName());
  496. }
  497. }
  498. else
  499. g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateWBEMClass() MapClassSystemProperties FAILED : %x for %s\r\n", result, pADSIClass->GetWBEMClassName());
  500. if(!SUCCEEDED(result))
  501. {
  502. if(*ppWbemClass)
  503. {
  504. (*ppWbemClass)->Release();
  505. *ppWbemClass = NULL;
  506. }
  507. }
  508. return result;
  509. }
  510. //***************************************************************************
  511. //
  512. // CLDAPClassProvider::MapClassSystemProperties
  513. //
  514. // Purpose: Creates an appropriately derived WBEM class and names it (__CLASS)
  515. //
  516. // Parameters:
  517. // pADSIClass : The ADSI class that is being mapped
  518. // ppWbemClass : The WBEM class object retrieved. This is created by this function.
  519. // The caller should release it when done
  520. // pCtx : The context object that was used in this provider call
  521. //
  522. // Return Value: The COM value representing the return status
  523. //
  524. //***************************************************************************
  525. HRESULT CLDAPClassProvider :: MapClassSystemProperties(CADSIClass *pADSIClass, int iCaseNumber, IWbemClassObject **ppWbemClass, IWbemContext *pCtx)
  526. {
  527. HRESULT result = WBEM_S_NO_ERROR;
  528. LPCWSTR lpszClassName = pADSIClass->GetWBEMClassName();
  529. // Create the WBEM class first.
  530. // This process depends on whether the ADSI class is derived from
  531. // another ADSI class or not.
  532. // If so, that base class has to be retrieved and the derived class
  533. // to be spawned from that.
  534. // If not, then the function GetWBEMBaseClass() is called and the class
  535. // being mapped is derived from that class
  536. IWbemClassObject *pBaseClass = NULL;
  537. if(iCaseNumber == 1)
  538. {
  539. pBaseClass = GetWBEMBaseClass();
  540. }
  541. else
  542. {
  543. LPWSTR lpszWBEMParentClassName = NULL;
  544. switch(iCaseNumber)
  545. {
  546. case 1:
  547. {
  548. pBaseClass = GetWBEMBaseClass();
  549. break;
  550. }
  551. case 2:
  552. case 4:
  553. {
  554. lpszWBEMParentClassName = CLDAPHelper::MangleLDAPNameToWBEM(pADSIClass->GetSuperClassLDAPName(), FALSE);
  555. break;
  556. }
  557. case 3:
  558. {
  559. lpszWBEMParentClassName = CLDAPHelper::MangleLDAPNameToWBEM(pADSIClass->GetSuperClassLDAPName(), TRUE);
  560. break;
  561. }
  562. case 5:
  563. {
  564. lpszWBEMParentClassName = CLDAPHelper::MangleLDAPNameToWBEM(pADSIClass->GetADSIClassName(), TRUE);
  565. break;
  566. }
  567. default:
  568. {
  569. result = WBEM_E_FAILED;
  570. break;
  571. }
  572. }
  573. if(SUCCEEDED(result))
  574. {
  575. BSTR strWBEMParentClass = SysAllocString(lpszWBEMParentClassName);
  576. delete [] lpszWBEMParentClassName;
  577. // Get the parent WBEM Class
  578. if(FAILED(result = m_IWbemServices->GetObject(strWBEMParentClass, 0, pCtx, &pBaseClass, NULL)))
  579. g_pLogObject->WriteW( L"CLDAPClassProvider :: MapClassSystemProperties() GetObject on ADSI base class FAILED : %x for %s\r\n", result, strWBEMParentClass);
  580. SysFreeString(strWBEMParentClass);
  581. }
  582. }
  583. if(FAILED(result) || pBaseClass == NULL)
  584. return result;
  585. // Spawn the derived class
  586. result = pBaseClass->SpawnDerivedClass(0, ppWbemClass);
  587. pBaseClass->Release();
  588. if(SUCCEEDED(result))
  589. {
  590. // Create the __CLASS property
  591. // Make sure the case of the letters is not mixed up
  592. SanitizedClassName((LPWSTR)lpszClassName);
  593. if(SUCCEEDED(result = CWBEMHelper::PutBSTRProperty(*ppWbemClass, CLASS_STR, SysAllocString(lpszClassName), TRUE)))
  594. {
  595. }
  596. else
  597. g_pLogObject->WriteW( L"CLDAPClassProvider :: MapClassSystemProperties() on __CLASS FAILED : %x for %s\r\n", result, lpszClassName);
  598. }
  599. else
  600. g_pLogObject->WriteW( L"CLDAPClassProvider :: MapClassSystemProperties() SpawnDerived on WBEM base class FAILED : %x for %s\r\n", result, lpszClassName);
  601. return result;
  602. }
  603. //***************************************************************************
  604. //
  605. // CLDAPClassProvider :: MapClassQualifiersToWBEM
  606. //
  607. // Purpose: Creates the class qualifiers for a WBEM class from the ADSI class
  608. //
  609. // Parameters:
  610. // pADSIClass : The LDAP class that is being mapped
  611. // pWbemClass : The WBEM class object being created. T
  612. // pCtx : The context object that was used in this provider call
  613. //
  614. // Return Value: The COM value representing the return status
  615. //
  616. //***************************************************************************
  617. HRESULT CLDAPClassProvider :: MapClassQualifiersToWBEM(CADSIClass *pADSIClass, int iCaseNumber, IWbemClassObject *pWbemClass, IWbemContext *pCtx)
  618. {
  619. IWbemQualifierSet *pQualifierSet = NULL;
  620. HRESULT result = pWbemClass->GetQualifierSet(&pQualifierSet);
  621. LPCWSTR lpszTemp;
  622. BOOLEAN bIsAbstract = FALSE;
  623. // Map each of the LDAP class attributes to WBEM class qualifiers/properties
  624. if(SUCCEEDED(result))
  625. {
  626. result = CWBEMHelper::PutI4Qualifier(pQualifierSet, OBJECT_CLASS_CATEGORY_ATTR_BSTR, pADSIClass->GetObjectClassCategory(), DEFAULT_QUALIFIER_FLAVOUR);
  627. // It is an abstract class is the ADSI class type is Abstract or Auxiliary
  628. if(SUCCEEDED(result) && (pADSIClass->GetObjectClassCategory() == 2 || pADSIClass->GetObjectClassCategory() == 3) )
  629. {
  630. bIsAbstract = TRUE;
  631. result = CWBEMHelper::PutBOOLQualifier(pQualifierSet, ABSTRACT_BSTR, VARIANT_TRUE, WBEM_FLAVOR_OVERRIDABLE);
  632. }
  633. else if (iCaseNumber == 2 || iCaseNumber == 3)
  634. {
  635. bIsAbstract = TRUE;
  636. result = CWBEMHelper::PutBOOLQualifier(pQualifierSet, ABSTRACT_BSTR, VARIANT_TRUE, WBEM_FLAVOR_OVERRIDABLE);
  637. }
  638. }
  639. if(SUCCEEDED(result))
  640. result = CWBEMHelper::PutBOOLQualifier(pQualifierSet, DYNAMIC_BSTR, VARIANT_TRUE, DEFAULT_QUALIFIER_FLAVOUR);
  641. // provider qualifier is put only for non-abstract classes
  642. if(!bIsAbstract && SUCCEEDED(result))
  643. result = CWBEMHelper::PutBSTRQualifier(pQualifierSet, PROVIDER_BSTR, LDAP_INSTANCE_PROVIDER_NAME, DEFAULT_QUALIFIER_FLAVOUR, FALSE);
  644. if(SUCCEEDED(result))
  645. result = CWBEMHelper::PutBSTRQualifier(pQualifierSet, COMMON_NAME_ATTR_BSTR, SysAllocString(pADSIClass->GetCommonName()), DEFAULT_QUALIFIER_FLAVOUR);
  646. if(SUCCEEDED(result))
  647. result = CWBEMHelper::PutBSTRQualifier(pQualifierSet, LDAP_DISPLAY_NAME_ATTR_BSTR, SysAllocString(pADSIClass->GetName()), DEFAULT_QUALIFIER_FLAVOUR);
  648. if(SUCCEEDED(result))
  649. result = CWBEMHelper::PutBSTRQualifier(pQualifierSet, GOVERNS_ID_ATTR_BSTR, SysAllocString(pADSIClass->GetGovernsID()), DEFAULT_QUALIFIER_FLAVOUR);
  650. // Do not map this, since this is not exposed thru the schema-management snapin
  651. /*
  652. if(SUCCEEDED(result))
  653. {
  654. const LPBYTE pValues = pADSIClass->GetSchemaIDGUID(&dwTemp);
  655. result = CWBEMHelper::PutUint8ArrayQualifier(pQualifierSet, SCHEMA_ID_GUID_ATTR_BSTR, pValues, dwTemp, DEFAULT_QUALIFIER_FLAVOUR);
  656. }
  657. */
  658. if(SUCCEEDED(result) && (lpszTemp = pADSIClass->GetDefaultSecurityDescriptor()))
  659. result = CWBEMHelper::PutBSTRQualifier(pQualifierSet, DEFAULT_SECURITY_DESCRP_ATTR_BSTR, SysAllocString(lpszTemp), DEFAULT_QUALIFIER_FLAVOUR);
  660. if(SUCCEEDED(result))
  661. result = CWBEMHelper::PutBOOLQualifier(pQualifierSet, SYSTEM_ONLY_ATTR_BSTR, pADSIClass->GetSystemOnly(), DEFAULT_QUALIFIER_FLAVOUR);
  662. /*
  663. if(SUCCEEDED(result))
  664. {
  665. const LPBYTE pValues = pADSIClass->GetNTSecurityDescriptor(&dwTemp);
  666. result = CWBEMHelper::PutUint8ArrayQualifier(pQualifierSet, NT_SECURITY_DESCRIPTOR_ATTR_BSTR, pValues, dwTemp, DEFAULT_QUALIFIER_FLAVOUR);
  667. }
  668. */
  669. if(SUCCEEDED(result))
  670. result = CWBEMHelper::PutBSTRQualifier(pQualifierSet, DEFAULT_OBJECTCATEGORY_ATTR_BSTR, SysAllocString(pADSIClass->GetDefaultObjectCategory()), DEFAULT_QUALIFIER_FLAVOUR);
  671. pQualifierSet->Release();
  672. return result;
  673. }
  674. //***************************************************************************
  675. //
  676. // CLDAPClassProvider :: MapClassPropertiesToWBEM
  677. //
  678. // Purpose: Creates the class properties for a WBEM class from the ADSI class
  679. //
  680. // Parameters:
  681. // pADSIClass : The LDAP class that is being mapped
  682. // pWbemClass : The WBEM class object being created.
  683. // pCtx : The context object that was used in this provider call
  684. //
  685. // Return Value: The COM value representing the return status
  686. //
  687. //***************************************************************************
  688. HRESULT CLDAPClassProvider :: MapClassPropertiesToWBEM(CADSIClass *pADSIClass, IWbemClassObject *pWbemClass, IWbemContext *pCtx)
  689. {
  690. HRESULT result = S_OK;
  691. //////////////////////////////////////////////////
  692. // Go thru the set of Auxiliary Classes
  693. //////////////////////////////////////////////////
  694. DWORD dwCount = 0;
  695. LPCWSTR *lppszPropertyList = pADSIClass->GetAuxiliaryClasses(&dwCount);
  696. CADSIClass *pNextClass = NULL;
  697. if(dwCount)
  698. {
  699. for(DWORD dwNextClass=0; dwNextClass<dwCount; dwNextClass++)
  700. {
  701. LPWSTR lpszWBEMClassName = CLDAPHelper::MangleLDAPNameToWBEM(lppszPropertyList[dwNextClass]);
  702. try
  703. {
  704. if(SUCCEEDED(result = s_pLDAPCache->GetClass(lpszWBEMClassName, lppszPropertyList[dwNextClass], &pNextClass)))
  705. {
  706. if(SUCCEEDED(result = MapClassPropertiesToWBEM(pNextClass, pWbemClass, pCtx)))
  707. {
  708. }
  709. pNextClass->Release();
  710. pNextClass = NULL;
  711. }
  712. }
  713. catch ( ... )
  714. {
  715. if ( pNextClass )
  716. {
  717. pNextClass->Release ();
  718. pNextClass = NULL;
  719. }
  720. delete [] lpszWBEMClassName;
  721. throw;
  722. }
  723. delete [] lpszWBEMClassName;
  724. }
  725. }
  726. if(FAILED(result))
  727. return result;
  728. //////////////////////////////////////////////////
  729. // Go thru the set of System Auxiliary Classes
  730. //////////////////////////////////////////////////
  731. dwCount = 0;
  732. lppszPropertyList = pADSIClass->GetSystemAuxiliaryClasses(&dwCount);
  733. pNextClass = NULL;
  734. if(dwCount)
  735. {
  736. for(DWORD dwNextClass=0; dwNextClass<dwCount; dwNextClass++)
  737. {
  738. LPWSTR lpszWBEMClassName = CLDAPHelper::MangleLDAPNameToWBEM(lppszPropertyList[dwNextClass]);
  739. try
  740. {
  741. if(SUCCEEDED(result = s_pLDAPCache->GetClass(lpszWBEMClassName, lppszPropertyList[dwNextClass], &pNextClass)))
  742. {
  743. if(SUCCEEDED(result = MapClassPropertiesToWBEM(pNextClass, pWbemClass, pCtx)))
  744. {
  745. }
  746. pNextClass->Release();
  747. pNextClass = NULL;
  748. }
  749. }
  750. catch ( ... )
  751. {
  752. if ( pNextClass )
  753. {
  754. pNextClass->Release ();
  755. pNextClass = NULL;
  756. }
  757. delete [] lpszWBEMClassName;
  758. throw;
  759. }
  760. delete [] lpszWBEMClassName;
  761. }
  762. }
  763. if(FAILED(result))
  764. return result;
  765. //////////////////////////////////////////////////
  766. // Go thru the set of System May Contains
  767. //////////////////////////////////////////////////
  768. dwCount = 0;
  769. lppszPropertyList = pADSIClass->GetSystemMayContains(&dwCount);
  770. if(SUCCEEDED(result = MapPropertyListToWBEM(pWbemClass, lppszPropertyList, dwCount, TRUE, FALSE)))
  771. {
  772. //////////////////////////////////////////////////
  773. // Go thru the set of May Contains
  774. //////////////////////////////////////////////////
  775. dwCount = 0;
  776. lppszPropertyList = pADSIClass->GetMayContains(&dwCount);
  777. if(SUCCEEDED(result = MapPropertyListToWBEM(pWbemClass, lppszPropertyList, dwCount, FALSE, FALSE)))
  778. {
  779. //////////////////////////////////////////////////
  780. // Go thru the set of System Must Contains
  781. //////////////////////////////////////////////////
  782. dwCount = 0;
  783. lppszPropertyList = pADSIClass->GetSystemMustContains(&dwCount);
  784. if(SUCCEEDED(result = MapPropertyListToWBEM(pWbemClass, lppszPropertyList, dwCount, TRUE, TRUE)))
  785. {
  786. //////////////////////////////////////////////////
  787. // Go thru the set of Must Contains
  788. //////////////////////////////////////////////////
  789. dwCount = 0;
  790. lppszPropertyList = pADSIClass->GetMustContains(&dwCount);
  791. if(SUCCEEDED(result = MapPropertyListToWBEM(pWbemClass, lppszPropertyList, dwCount, FALSE, TRUE)))
  792. {
  793. } // MapPropertyListToWBEM
  794. } // MapPropertyListToWBEM
  795. } // MapPropertyListToWBEM
  796. } // MapPropertyListToWBEM
  797. // Do not map any other properties, if failed
  798. if(FAILED(result))
  799. return result;
  800. // Map the RDN property as indexed
  801. LPWSTR lpszRDNAttribute = NULL;
  802. lpszRDNAttribute = CLDAPHelper::MangleLDAPNameToWBEM(pADSIClass->GetRDNAttribute());
  803. if(lpszRDNAttribute)
  804. {
  805. BSTR strRDNAttribute = SysAllocString(lpszRDNAttribute);
  806. IWbemQualifierSet *pQualifierSet = NULL;
  807. if(SUCCEEDED(result = pWbemClass->GetPropertyQualifierSet(strRDNAttribute, &pQualifierSet)))
  808. {
  809. IWbemQualifierSet *pClassQualifiers = NULL;
  810. if(SUCCEEDED(result = pWbemClass->GetQualifierSet(&pClassQualifiers)))
  811. {
  812. // ALso put a qualifier on the class that indicates that this is the RDNAttId
  813. if(SUCCEEDED(result = CWBEMHelper::PutBSTRQualifier(pClassQualifiers, RDN_ATT_ID_ATTR_BSTR, SysAllocString(pADSIClass->GetRDNAttribute()), DEFAULT_QUALIFIER_FLAVOUR, TRUE)))
  814. {
  815. if(SUCCEEDED(result = CWBEMHelper::PutBOOLQualifier(pQualifierSet, INDEXED_BSTR, VARIANT_TRUE, DEFAULT_QUALIFIER_FLAVOUR)))
  816. {
  817. }
  818. // It is fine if this property has already been designated as indexed in the base class
  819. else if (result == WBEM_E_OVERRIDE_NOT_ALLOWED)
  820. result = S_OK;
  821. }
  822. pClassQualifiers->Release();
  823. }
  824. // Release the Qualifer Set
  825. pQualifierSet->Release();
  826. }
  827. SysFreeString(strRDNAttribute);
  828. }
  829. delete [] lpszRDNAttribute;
  830. return result;
  831. }
  832. //***************************************************************************
  833. //
  834. // CLDAPClassProvider :: MapPropertyListToWBEM
  835. //
  836. // Purpose: Maps a list of class properties for a WBEM class from the ADSI class
  837. //
  838. // Parameters:
  839. // pWbemClass : The WBEM class object being created.
  840. // lppszPropertyList : A list of propery names
  841. // dwCOunt : The number of items in the above list
  842. // bMapSystemQualifier : Whether the "system" qualifier should be mapped
  843. // bMapNotNullQualifier: Whether the "notNull" qualifier should be mapped
  844. //
  845. // Return Value: The COM value representing the return status
  846. //
  847. //***************************************************************************
  848. HRESULT CLDAPClassProvider :: MapPropertyListToWBEM(IWbemClassObject *pWbemClass,
  849. LPCWSTR *lppszPropertyList,
  850. DWORD dwCount,
  851. BOOLEAN bMapSystemQualifier,
  852. BOOLEAN bMapNotNullQualifier)
  853. {
  854. HRESULT result = S_OK;
  855. CADSIProperty *pNextProperty;
  856. IWbemQualifierSet *pQualifierSet;
  857. if(dwCount)
  858. {
  859. for(DWORD dwNextProperty=0; dwNextProperty<dwCount; dwNextProperty++)
  860. {
  861. // Get the property from the cache. The name of the property will be the LDAP name
  862. if(SUCCEEDED(result = s_pLDAPCache->GetProperty(lppszPropertyList[dwNextProperty], &pNextProperty, FALSE)))
  863. {
  864. if ( pNextProperty )
  865. {
  866. // Map the basic property
  867. if(SUCCEEDED(result = CreateWBEMProperty(pWbemClass, &pQualifierSet, pNextProperty)))
  868. {
  869. // Map the "system" qualifier
  870. if(bMapSystemQualifier && SUCCEEDED(result = CWBEMHelper::PutBOOLQualifier(pQualifierSet, SYSTEM_BSTR, VARIANT_TRUE, DEFAULT_QUALIFIER_FLAVOUR)))
  871. {
  872. }
  873. // Map the "not_null" qualifier
  874. if(bMapNotNullQualifier && SUCCEEDED(result = CWBEMHelper::PutBOOLQualifier(pQualifierSet, NOT_NULL_BSTR, VARIANT_TRUE, DEFAULT_QUALIFIER_FLAVOUR)))
  875. {
  876. }
  877. // Release the qualifier set
  878. pQualifierSet->Release();
  879. }
  880. // Release the property
  881. pNextProperty->Release();
  882. }
  883. }
  884. // Do not map any other properties
  885. if(FAILED(result))
  886. break;
  887. }
  888. }
  889. return result;
  890. }
  891. //***************************************************************************
  892. //
  893. // CLDAPClassProvider :: CreateWBEMProperty
  894. //
  895. // Purpose: Creates a WBEM property from an LDAP property
  896. //
  897. // Parameters:
  898. // pWbemClass : The WBEM class in which the property is created
  899. // ppQualiferSet : The address of the pointer to IWbemQualiferSet where the qualifier set
  900. // of this property will be placed
  901. // pADSIProperty : The ADSI Property object that is being mapped to the property being created
  902. //
  903. // Return Value: The COM value representing the return status
  904. //
  905. //***************************************************************************
  906. HRESULT CLDAPClassProvider :: CreateWBEMProperty(IWbemClassObject *pWbemClass, IWbemQualifierSet **ppQualifierSet, CADSIProperty *pADSIProperty)
  907. {
  908. HRESULT result = E_FAIL;
  909. // Get all the attributes of the ADSI class
  910. LPCWSTR lpszSyntaxOid = pADSIProperty->GetSyntaxOID();
  911. BSTR strCimTypeQualifier = NULL;
  912. // Note that strCimTypeQualifier is not allocated in this call, so it is not freed.
  913. CIMTYPE theCimType = MapLDAPSyntaxToWBEM(pADSIProperty, &strCimTypeQualifier);
  914. if(lpszSyntaxOid)
  915. {
  916. // Create the property
  917. BSTR strPropertyName = SysAllocString(pADSIProperty->GetWBEMPropertyName());
  918. if(SUCCEEDED(result = pWbemClass->Put(strPropertyName, 0, NULL, theCimType)))
  919. {
  920. // Get the Qualifier Set in ppQualifierSet
  921. if(SUCCEEDED(result = pWbemClass->GetPropertyQualifierSet(strPropertyName, ppQualifierSet)))
  922. {
  923. // Map the property attributes to WBEM qualifiers
  924. if(SUCCEEDED(result = CWBEMHelper::PutBSTRQualifier(*ppQualifierSet,
  925. ATTRIBUTE_SYNTAX_ATTR_BSTR,
  926. SysAllocString(lpszSyntaxOid),
  927. DEFAULT_QUALIFIER_FLAVOUR)))
  928. {
  929. /* Commented to reduce size of classes
  930. if(SUCCEEDED(result = CWBEMHelper::PutBSTRQualifier(*ppQualifierSet,
  931. ATTRIBUTE_ID_ATTR_BSTR,
  932. SysAllocString(pADSIProperty->GetAttributeID()),
  933. DEFAULT_QUALIFIER_FLAVOUR)))
  934. {
  935. */
  936. if(SUCCEEDED(result = CWBEMHelper::PutBSTRQualifier(*ppQualifierSet,
  937. COMMON_NAME_ATTR_BSTR,
  938. SysAllocString(pADSIProperty->GetCommonName()),
  939. DEFAULT_QUALIFIER_FLAVOUR)))
  940. {
  941. /* Commented to reduce size of classes
  942. if(SUCCEEDED(result = CWBEMHelper::PutI4Qualifier(*ppQualifierSet,
  943. MAPI_ID_ATTR_BSTR,
  944. pADSIProperty->GetMAPI_ID(),
  945. DEFAULT_QUALIFIER_FLAVOUR)))
  946. {
  947. if(SUCCEEDED(result = CWBEMHelper::PutI4Qualifier(*ppQualifierSet,
  948. OM_SYNTAX_ATTR_BSTR,
  949. pADSIProperty->GetOMSyntax(),
  950. DEFAULT_QUALIFIER_FLAVOUR)))
  951. {
  952. if(pADSIProperty->IsSystemOnly())
  953. {
  954. if(SUCCEEDED(result = CWBEMHelper::PutBOOLQualifier(*ppQualifierSet,
  955. SYSTEM_ONLY_ATTR_BSTR,
  956. VARIANT_TRUE,
  957. DEFAULT_QUALIFIER_FLAVOUR)))
  958. {
  959. }
  960. }
  961. */
  962. // If this is an embedded property, then use the cimType qualifier on the property
  963. if(strCimTypeQualifier)
  964. {
  965. result = CWBEMHelper::PutBSTRQualifier(*ppQualifierSet,
  966. CIMTYPE_STR,
  967. strCimTypeQualifier,
  968. DEFAULT_QUALIFIER_FLAVOUR, FALSE);
  969. }
  970. if(SUCCEEDED(result) && pADSIProperty->GetSearchFlags() == 1)
  971. {
  972. if(SUCCEEDED(result = CWBEMHelper::PutBOOLQualifier(*ppQualifierSet,
  973. INDEXED_BSTR,
  974. VARIANT_TRUE,
  975. DEFAULT_QUALIFIER_FLAVOUR)))
  976. {
  977. }
  978. else if (result == WBEM_E_OVERRIDE_NOT_ALLOWED)
  979. result = S_OK;
  980. }
  981. }
  982. /*
  983. }
  984. }
  985. }
  986. */
  987. }
  988. }
  989. else
  990. g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateWBEMProperty FAILED to get qualifier set for %s", pADSIProperty->GetADSIPropertyName());
  991. }
  992. else
  993. g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateWBEMProperty FAILED to put property : %s", pADSIProperty->GetADSIPropertyName());
  994. SysFreeString(strPropertyName);
  995. }
  996. else
  997. {
  998. g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateWBEMProperty FAILED to get Syntax OID property for %s", pADSIProperty->GetADSIPropertyName());
  999. result = E_FAIL;
  1000. }
  1001. return result;
  1002. }
  1003. //***************************************************************************
  1004. //
  1005. // CLDAPClassProvider :: MapLDAPSyntaxToWBEM
  1006. //
  1007. // Purpose: See Header
  1008. //
  1009. //***************************************************************************
  1010. CIMTYPE CLDAPClassProvider :: MapLDAPSyntaxToWBEM(CADSIProperty *pADSIProperty, BSTR *pstrCimTypeQualifier)
  1011. {
  1012. *pstrCimTypeQualifier = NULL;
  1013. LPCWSTR lpszSyntaxOid = pADSIProperty->GetSyntaxOID();
  1014. CIMTYPE retValue = (pADSIProperty->IsMultiValued())? CIM_FLAG_ARRAY : 0;
  1015. if(wcscmp(lpszSyntaxOid, UNICODE_STRING_OID) == 0)
  1016. return retValue | CIM_STRING;
  1017. else if(wcscmp(lpszSyntaxOid, INTEGER_OID) == 0)
  1018. return retValue | CIM_SINT32;
  1019. else if(wcscmp(lpszSyntaxOid, LARGE_INTEGER_OID) == 0)
  1020. return retValue | CIM_SINT64;
  1021. else if(wcscmp(lpszSyntaxOid, BOOLEAN_OID) == 0)
  1022. return retValue | CIM_BOOLEAN;
  1023. else if(wcscmp(lpszSyntaxOid, OBJECT_IDENTIFIER_OID) == 0)
  1024. return retValue | CIM_STRING;
  1025. else if(wcscmp(lpszSyntaxOid, DISTINGUISHED_NAME_OID) == 0)
  1026. return retValue | CIM_STRING;
  1027. else if(wcscmp(lpszSyntaxOid, CASE_SENSITIVE_STRING_OID) == 0)
  1028. return retValue | CIM_STRING;
  1029. else if(wcscmp(lpszSyntaxOid, CASE_INSENSITIVE_STRING_OID) == 0)
  1030. return retValue | CIM_STRING;
  1031. else if(wcscmp(lpszSyntaxOid, PRINT_CASE_STRING_OID) == 0)
  1032. return retValue | CIM_STRING;
  1033. else if(wcscmp(lpszSyntaxOid, OCTET_STRING_OID) == 0)
  1034. {
  1035. *pstrCimTypeQualifier = EMBED_UINT8ARRAY;
  1036. return retValue | CIM_OBJECT;
  1037. }
  1038. else if(wcscmp(lpszSyntaxOid, NUMERIC_STRING_OID) == 0)
  1039. return retValue | CIM_STRING;
  1040. else if(wcscmp(lpszSyntaxOid, PRINT_CASE_STRING_OID) == 0)
  1041. return retValue | CIM_STRING;
  1042. else if(wcscmp(lpszSyntaxOid, DN_WITH_BINARY_OID) == 0)
  1043. {
  1044. // DN_With_Binary and OR_Name have the same syntax oid.
  1045. // They are differentiated base on the value of the OMObjectClass value
  1046. if(pADSIProperty->IsORName())
  1047. return retValue | CIM_STRING;
  1048. else // It is DN_With_Binary
  1049. {
  1050. *pstrCimTypeQualifier = EMBED_DN_WITH_BINARY;
  1051. return retValue | CIM_OBJECT;
  1052. }
  1053. }
  1054. else if(wcscmp(lpszSyntaxOid, NT_SECURITY_DESCRIPTOR_OID) == 0)
  1055. {
  1056. *pstrCimTypeQualifier = EMBED_UINT8ARRAY;
  1057. return retValue | CIM_OBJECT;
  1058. }
  1059. else if(wcscmp(lpszSyntaxOid, PRESENTATION_ADDRESS_OID) == 0)
  1060. {
  1061. *pstrCimTypeQualifier = EMBED_UINT8ARRAY;
  1062. return retValue | CIM_OBJECT;
  1063. }
  1064. else if(wcscmp(lpszSyntaxOid, DN_WITH_STRING_OID) == 0)
  1065. {
  1066. *pstrCimTypeQualifier = EMBED_DN_WITH_BINARY;
  1067. return retValue | CIM_OBJECT;
  1068. }
  1069. else if(wcscmp(lpszSyntaxOid, SID_OID) == 0)
  1070. {
  1071. *pstrCimTypeQualifier = EMBED_UINT8ARRAY;
  1072. return retValue | CIM_OBJECT;
  1073. }
  1074. else if(wcscmp(lpszSyntaxOid, TIME_OID) == 0)
  1075. return retValue | CIM_DATETIME;
  1076. else
  1077. {
  1078. g_pLogObject->WriteW( L"CLDAPClassProvider :: MapLDAPSyntaxToWBEM FAILED to map syntax for OID: %s\r\n", lpszSyntaxOid);
  1079. return retValue | CIM_STRING;
  1080. }
  1081. }
  1082. //***************************************************************************
  1083. //
  1084. // CLDAPClassProvider :: CreateClassEnumAsync
  1085. //
  1086. // Purpose: Enumerates the classes
  1087. //
  1088. // Parameters:
  1089. // Standard parmaters as described by the IWbemServices interface
  1090. //
  1091. //
  1092. // Return Value: As described by the IWbemServices interface
  1093. //
  1094. //***************************************************************************
  1095. HRESULT CLDAPClassProvider :: CreateClassEnumAsync(
  1096. /* [in] */ const BSTR strSuperclass,
  1097. /* [in] */ long lFlags,
  1098. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  1099. /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
  1100. {
  1101. if(!m_bInitializedSuccessfully)
  1102. {
  1103. g_pLogObject->WriteW( L"CLDAPClassProvider :: Initialization status is FAILED, hence returning failure\r\n");
  1104. return WBEM_E_FAILED;
  1105. }
  1106. g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() called for %s SuperClass and %s \r\n",
  1107. ((strSuperclass)? strSuperclass : L" "), ((lFlags & WBEM_FLAG_SHALLOW)? L"SHALLOW" : L"DEEP"));
  1108. // Impersonate the client
  1109. //=======================
  1110. HRESULT result = WBEM_E_FAILED;
  1111. if(!SUCCEEDED(result = WbemCoImpersonateClient()))
  1112. {
  1113. g_pLogObject->WriteW( L"CDSClassProvider :: CreateClassEnumAsync() CoImpersonate FAILED for %s with %x\r\n", strSuperclass, result);
  1114. return WBEM_E_FAILED;
  1115. }
  1116. try
  1117. {
  1118. BSTR strTheSuperClass = strSuperclass;
  1119. // CIMOM seems to give the strSuperClass as NULL sometimes and as "" sometimes. Make it unambiguous
  1120. if(!strTheSuperClass || wcscmp(strTheSuperClass, L"") == 0)
  1121. {
  1122. if( lFlags & WBEM_FLAG_SHALLOW)
  1123. {
  1124. // Nothing to be done since we do not provide cany classes that fit this
  1125. strTheSuperClass = NULL;
  1126. result = S_OK;
  1127. }
  1128. else
  1129. {
  1130. strTheSuperClass = LDAP_BASE_CLASS_STR; // Recursive enumeration handled below
  1131. }
  1132. }
  1133. // Take the special cases first
  1134. // 1. Where the strSuperClass is LDAP_BASE_CLASS_STR and lFlags is Shallow
  1135. // Nothing to be returned here, since we are not supplying the LDAP_BASE_CLASS_STR
  1136. // which is statically supplied.
  1137. //=======================================================================
  1138. if(strTheSuperClass && _wcsicmp(strTheSuperClass, LDAP_BASE_CLASS_STR) == 0 )
  1139. {
  1140. // First the TOP class needs to be returned
  1141. IWbemClassObject *pReturnObject = NULL;
  1142. if(SUCCEEDED(result = GetClassFromCacheOrADSI(TOP_CLASS, &pReturnObject, pCtx)))
  1143. {
  1144. result = pResponseHandler->Indicate(1, &pReturnObject);
  1145. pReturnObject->Release();
  1146. if(SUCCEEDED(result))
  1147. {
  1148. if( lFlags & WBEM_FLAG_SHALLOW) // Notheing more to be done
  1149. {
  1150. }
  1151. else // We've to return all the sub classes of top too, recursively
  1152. {
  1153. if(SUCCEEDED(result = HandleRecursiveEnumeration(TOP_CLASS, pCtx, pResponseHandler)))
  1154. {
  1155. g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() Recursive enumeration for %s succeeded\r\n", strTheSuperClass);
  1156. }
  1157. else
  1158. {
  1159. g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() Recursive enumeration for %s FAILED\r\n", strTheSuperClass);
  1160. }
  1161. }
  1162. }
  1163. else
  1164. g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() Recursive enumeration for %s was CANCELLED\r\n", strTheSuperClass);
  1165. }
  1166. }
  1167. // 2. Where the superClass is specified
  1168. //=======================================================================
  1169. else if(strTheSuperClass)
  1170. {
  1171. // Optimize the operation by seeing if it is one of the static classes and
  1172. // its name does not start with "ADS_" or "DS_". Then we dont know anything about it
  1173. //============================================================================
  1174. if(IsUnProvidedClass(strTheSuperClass))
  1175. {
  1176. result = S_OK;
  1177. }
  1178. else
  1179. {
  1180. BOOLEAN bArtificialClass = FALSE;
  1181. // First check if this is one our "artificial" classes. All "aritificial" classes start with "ads_".
  1182. // All non artificial classes start with "ds_"
  1183. if(_wcsnicmp(strTheSuperClass, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX_LENGTH) == 0)
  1184. bArtificialClass = TRUE;
  1185. // When the search is shallow
  1186. if( lFlags & WBEM_FLAG_SHALLOW)
  1187. {
  1188. // The ADSI classes
  1189. LPWSTR *ppADSIClasses = NULL;
  1190. // The number of ADSI classes
  1191. DWORD dwNumClasses = 0;
  1192. try
  1193. {
  1194. if(SUCCEEDED(result = GetOneLevelDeep(strTheSuperClass, bArtificialClass, &ppADSIClasses, &dwNumClasses, pCtx)))
  1195. {
  1196. // Interact with CIMOM
  1197. //=====================
  1198. if(SUCCEEDED(result = WrapUpEnumeration(ppADSIClasses, dwNumClasses, pCtx, pResponseHandler)))
  1199. {
  1200. }
  1201. // Release the list of ADSI classes and its contents
  1202. //==================================================
  1203. for(DWORD j=0; j<dwNumClasses; j++)
  1204. {
  1205. delete [] ppADSIClasses[j];
  1206. ppADSIClasses[j] = NULL;
  1207. }
  1208. delete[] ppADSIClasses;
  1209. ppADSIClasses = NULL;
  1210. }
  1211. }
  1212. catch ( ... )
  1213. {
  1214. if ( ppADSIClasses )
  1215. {
  1216. for ( DWORD j=0; j<dwNumClasses; j++ )
  1217. {
  1218. delete [] ppADSIClasses[j];
  1219. ppADSIClasses[j] = NULL;
  1220. }
  1221. delete[] ppADSIClasses;
  1222. ppADSIClasses = NULL;
  1223. }
  1224. throw;
  1225. }
  1226. }
  1227. else // the search is deep
  1228. {
  1229. if(SUCCEEDED(result = HandleRecursiveEnumeration(strTheSuperClass, pCtx, pResponseHandler)))
  1230. {
  1231. g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() Recursive enumeration for %s succeeded\r\n", strTheSuperClass);
  1232. }
  1233. else
  1234. {
  1235. g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() Recursive enumeration for %s FAILED\r\n", strTheSuperClass);
  1236. }
  1237. }
  1238. }
  1239. }
  1240. if(SUCCEEDED(result))
  1241. {
  1242. pResponseHandler->SetStatus(WBEM_STATUS_COMPLETE, WBEM_S_NO_ERROR, NULL, NULL);
  1243. g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() Non-Recursive enumeration succeeded\r\n");
  1244. }
  1245. else
  1246. {
  1247. pResponseHandler->SetStatus(WBEM_STATUS_COMPLETE, WBEM_E_FAILED, NULL, NULL);
  1248. g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() Non-Recursive enumeration FAILED for superclass %s \r\n", strTheSuperClass);
  1249. }
  1250. }
  1251. catch(Heap_Exception e_HE)
  1252. {
  1253. pResponseHandler->SetStatus(WBEM_STATUS_COMPLETE , WBEM_E_OUT_OF_MEMORY, NULL, NULL);
  1254. }
  1255. return WBEM_S_NO_ERROR;
  1256. }
  1257. //***************************************************************************
  1258. //
  1259. // CLDAPClassProvider :: GetOneLevelDeep
  1260. //
  1261. // Purpose: Enumerates the sub classes of a superclass non-recursively
  1262. //
  1263. // Parameters:
  1264. //
  1265. // lpszSuperClass : The super class name
  1266. // pResponseHandler : The interface where the resulting classes are put
  1267. //
  1268. //
  1269. // Return Value: As described by the IWbemServices interface
  1270. //
  1271. //***************************************************************************
  1272. HRESULT CLDAPClassProvider :: GetOneLevelDeep(
  1273. LPCWSTR lpszWBEMSuperclass,
  1274. BOOLEAN bArtificialClass,
  1275. LPWSTR ** pppADSIClasses,
  1276. DWORD *pdwNumClasses,
  1277. IWbemContext *pCtx)
  1278. {
  1279. // The ADSI classes
  1280. *pppADSIClasses = NULL;
  1281. // The number of ADSI classes
  1282. *pdwNumClasses = 0;
  1283. HRESULT result = WBEM_E_FAILED;
  1284. // See if the super class
  1285. IWbemClassObject *pSuperClass = NULL;
  1286. if(!SUCCEEDED(result = GetClassFromCacheOrADSI(lpszWBEMSuperclass, &pSuperClass, pCtx)))
  1287. {
  1288. return WBEM_E_NOT_FOUND;
  1289. }
  1290. pSuperClass->Release();
  1291. // If the WBEM class is concrete, we dont need to do anything
  1292. if (SUCCEEDED(result = IsConcreteClass(lpszWBEMSuperclass, pCtx)))
  1293. {
  1294. if(result == S_OK)
  1295. return S_OK;
  1296. }
  1297. else
  1298. return result;
  1299. // See the cache first
  1300. //====================
  1301. CEnumInfo *pEnumInfo = NULL;
  1302. try
  1303. {
  1304. if(SUCCEEDED(result = s_pWbemCache->GetEnumInfo(lpszWBEMSuperclass, &pEnumInfo)))
  1305. {
  1306. CNamesList *pNamesList = pEnumInfo->GetSubClassNames();
  1307. *pdwNumClasses = pNamesList->GetAllNames(pppADSIClasses);
  1308. pEnumInfo->Release();
  1309. pEnumInfo = NULL;
  1310. }
  1311. else // Go to ADSI
  1312. //============
  1313. {
  1314. // The following are the possibilities now"
  1315. // 1. The Class starts with "ADS_". It is abstract by definition. All its sub-classes except one are abstract,artificial.
  1316. // 2. The Class starts with "DS_" and it is abstract. It being concrete is ruled out since it was handled at the
  1317. // top of this function
  1318. // Get all the ADSI classes
  1319. if(SUCCEEDED(result = s_pLDAPCache->EnumerateClasses(
  1320. lpszWBEMSuperclass,
  1321. FALSE,
  1322. pppADSIClasses,
  1323. pdwNumClasses,
  1324. bArtificialClass)))
  1325. {
  1326. // Create a list of names for holding the subclasses
  1327. CNamesList *pNewList = new CNamesList;
  1328. LPWSTR pszWBEMName = NULL;
  1329. try
  1330. {
  1331. // The First case in the 2 cases above
  1332. if(bArtificialClass)
  1333. {
  1334. // The first element is just the super class without the A
  1335. // Example if the super class is "ADS_User", the first element is DS_user
  1336. pNewList->AddName((*pppADSIClasses)[0]);
  1337. // Start from the secodn element
  1338. for(DWORD i=1; i<*pdwNumClasses; i++)
  1339. {
  1340. // Convert names to WBEM And add them to the new list
  1341. pszWBEMName = CLDAPHelper::MangleLDAPNameToWBEM((*pppADSIClasses)[i], TRUE);
  1342. pNewList->AddName(pszWBEMName);
  1343. delete [] (*pppADSIClasses)[i];
  1344. (*pppADSIClasses)[i] = pszWBEMName;
  1345. }
  1346. }
  1347. else // The Second case
  1348. {
  1349. for(DWORD i=0; i<*pdwNumClasses; i++)
  1350. {
  1351. // Convert names to WBEM And add them to the new list
  1352. pszWBEMName = CLDAPHelper::MangleLDAPNameToWBEM((*pppADSIClasses)[i], FALSE);
  1353. LPWSTR pszRealClassName = NULL;
  1354. if(SUCCEEDED(result = IsConcreteClass(pszWBEMName, pCtx)))
  1355. {
  1356. if(result == S_OK)
  1357. {
  1358. pszRealClassName = CLDAPHelper::MangleLDAPNameToWBEM((*pppADSIClasses)[i], TRUE);
  1359. delete[] pszWBEMName;
  1360. pNewList->AddName(pszRealClassName);
  1361. delete [] (*pppADSIClasses)[i];
  1362. (*pppADSIClasses)[i] = pszRealClassName;
  1363. }
  1364. else
  1365. {
  1366. pNewList->AddName(pszWBEMName);
  1367. delete [] (*pppADSIClasses)[i];
  1368. (*pppADSIClasses)[i] = pszWBEMName;
  1369. }
  1370. }
  1371. else
  1372. g_pLogObject->WriteW( L"CLDAPClassProvider :: GetOneLevelDeep() UNKNOWN FAILED for %s \r\n", lpszWBEMSuperclass);
  1373. }
  1374. }
  1375. }
  1376. catch ( ... )
  1377. {
  1378. if ( pNewList )
  1379. {
  1380. delete pNewList;
  1381. pNewList = NULL;
  1382. }
  1383. throw;
  1384. }
  1385. // Add the new EnumInfo to the Enum cache
  1386. pEnumInfo = new CEnumInfo(lpszWBEMSuperclass, pNewList);
  1387. s_pWbemCache->AddEnumInfo(pEnumInfo);
  1388. pEnumInfo->Release();
  1389. pEnumInfo = NULL;
  1390. }
  1391. else
  1392. g_pLogObject->WriteW( L"CLDAPClassProvider :: CreateClassEnumAsync() GetOneLevelDeep() FAILED for %s \r\n", lpszWBEMSuperclass);
  1393. }
  1394. }
  1395. catch ( ... )
  1396. {
  1397. if ( pEnumInfo )
  1398. {
  1399. pEnumInfo->Release();
  1400. pEnumInfo = NULL;
  1401. }
  1402. throw;
  1403. }
  1404. return result;
  1405. }
  1406. //***************************************************************************
  1407. //
  1408. // CLDAPClassProvider :: HandleRecursiveEnumeration
  1409. //
  1410. // Purpose: Enumerates the sub classes of a superclass recursively
  1411. //
  1412. // Parameters:
  1413. //
  1414. // lpszSuperClass : The super class name
  1415. // pResponseHandler : The interface where the resulting classes are put
  1416. //
  1417. //
  1418. // Return Value: As described by the IWbemServices interface
  1419. //
  1420. //***************************************************************************
  1421. HRESULT CLDAPClassProvider :: HandleRecursiveEnumeration(
  1422. LPCWSTR lpszWBEMSuperclass,
  1423. IWbemContext *pCtx,
  1424. IWbemObjectSink *pResponseHandler)
  1425. {
  1426. g_pLogObject->WriteW( L"CLDAPClassProvider :: HandleRecursiveEnumeration() called for %s SuperClass \r\n",
  1427. ((lpszWBEMSuperclass)? lpszWBEMSuperclass : L" "));
  1428. HRESULT result = E_FAIL;
  1429. // The ADSI classes
  1430. LPWSTR *ppADSIClasses = NULL;
  1431. // The number of ADSI classes
  1432. DWORD dwNumClasses = 0;
  1433. // First check if this is one our "artificial" classes. All "aritificial" classes start with "ads_".
  1434. // All non artificial classes start with "ds_"
  1435. BOOLEAN bArtificialClass = FALSE;
  1436. if(_wcsnicmp(lpszWBEMSuperclass, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX_LENGTH) == 0)
  1437. bArtificialClass = TRUE;
  1438. if(SUCCEEDED(result = GetOneLevelDeep(lpszWBEMSuperclass, bArtificialClass, &ppADSIClasses, &dwNumClasses, pCtx)))
  1439. {
  1440. // Interact with CIMOM
  1441. //=====================
  1442. if(FAILED(result = WrapUpEnumeration(ppADSIClasses, dwNumClasses, pCtx, pResponseHandler)))
  1443. g_pLogObject->WriteW( L"CLDAPClassProvider :: HandleRecursiveEnumeration() WrapUpEnumeration() for Superclass %s FAILED with %x \r\n",
  1444. ((lpszWBEMSuperclass)? lpszWBEMSuperclass : L" "), result);
  1445. else
  1446. {
  1447. // Go thru the list of ADSI classes and its contents and Enumerate into them too
  1448. for(DWORD j=0; j<dwNumClasses; j++)
  1449. {
  1450. if(FAILED(result = HandleRecursiveEnumeration(ppADSIClasses[j], pCtx, pResponseHandler)))
  1451. break;
  1452. }
  1453. }
  1454. // Go thru the list of ADSI classes and release them
  1455. for(DWORD j=0; j<dwNumClasses; j++)
  1456. delete [] ppADSIClasses[j];
  1457. delete[] ppADSIClasses;
  1458. }
  1459. return result;
  1460. }
  1461. //***************************************************************************
  1462. //
  1463. // CLDAPClassProvider :: WrapUpEnumeration
  1464. //
  1465. // Purpose: Creates WBEM classes from ADSI classes and Indicates them to CIMOM
  1466. //
  1467. // Parameters:
  1468. //
  1469. // lpszSuperClass : The super class name
  1470. // pResponseHandler : The interface where the resulting classes are put
  1471. //
  1472. //
  1473. // Return Value: As described by the IWbemServices interface
  1474. //
  1475. //***************************************************************************
  1476. HRESULT CLDAPClassProvider :: WrapUpEnumeration(
  1477. LPWSTR *ppADSIClasses,
  1478. DWORD dwNumClasses,
  1479. IWbemContext *pCtx,
  1480. IWbemObjectSink *pResponseHandler)
  1481. {
  1482. // The WBEM Class objects created
  1483. IWbemClassObject **ppReturnWbemClassObjects = NULL;
  1484. // The number of WBEM class objects that were successfully created
  1485. DWORD i=0;
  1486. DWORD j=0;
  1487. HRESULT result = S_OK;
  1488. if(dwNumClasses != 0)
  1489. {
  1490. // Allocate an array of IWbemClassObject pointers
  1491. ppReturnWbemClassObjects = NULL;
  1492. if(ppReturnWbemClassObjects = new IWbemClassObject *[dwNumClasses])
  1493. {
  1494. for(i=0; i<dwNumClasses; i++)
  1495. {
  1496. // Get the class
  1497. if(!SUCCEEDED(result = GetClassFromCacheOrADSI(ppADSIClasses[i], ppReturnWbemClassObjects + i, pCtx)))
  1498. {
  1499. g_pLogObject->WriteW( L"CLDAPClassProvider :: WrapUpEnumeration() GetClassFromCacheOrADSI() FAILED with %x \r\n", result);
  1500. break;
  1501. }
  1502. }
  1503. }
  1504. else
  1505. result = E_OUTOFMEMORY;
  1506. }
  1507. // Indicate(), but do not SetStatus()
  1508. if(SUCCEEDED(result))
  1509. {
  1510. // result = pResponseHandler->Indicate(i, ppReturnWbemClassObjects);
  1511. ////////////////////////////////////
  1512. //
  1513. // Break it up into 4 objects at a time - JUST FOR TESTING AGAINST BUG 39838
  1514. //
  1515. DWORD dwMaxObjectsAtATime = 4;
  1516. j = 0;
  1517. while ( j<i )
  1518. {
  1519. DWORD dwThisIndicationsCount = ((i-j) > dwMaxObjectsAtATime)? dwMaxObjectsAtATime : (i-j);
  1520. if(FAILED(result = pResponseHandler->Indicate(dwThisIndicationsCount, ppReturnWbemClassObjects + j)))
  1521. {
  1522. g_pLogObject->WriteW( L"CLDAPClassProvider :: WrapUpEnumeration() Indicate() FAILED with %x \r\n", result);
  1523. break;
  1524. }
  1525. j+= dwThisIndicationsCount;
  1526. }
  1527. }
  1528. else
  1529. g_pLogObject->WriteW( L"CLDAPClassProvider :: HandleRecursiveEnumeration() WrapUpEnumeration() FAILED with %x \r\n", result);
  1530. // Delete the list of WBEM Classes and its contents.
  1531. for(j=0; j<i; j++)
  1532. (ppReturnWbemClassObjects[j])->Release();
  1533. delete[] ppReturnWbemClassObjects;
  1534. return result;
  1535. }
  1536. //***************************************************************************
  1537. //
  1538. // CLDAPClassProvider :: IsConcreteClass
  1539. //
  1540. // Purpose: Find out whether a WBEM class is concrete.
  1541. //
  1542. // Parameters:
  1543. //
  1544. // pszWBEMName : The class name
  1545. //
  1546. //
  1547. // Return Value: As described by the IWbemServices interface
  1548. //
  1549. //***************************************************************************
  1550. HRESULT CLDAPClassProvider :: IsConcreteClass(
  1551. LPCWSTR pszWBEMName,
  1552. IWbemContext *pCtx)
  1553. {
  1554. // The call to IsConcreteClass is optimized if the class is artificial,
  1555. // since all artificial classes are non-concrete
  1556. if(_wcsnicmp(pszWBEMName, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX, LDAP_ARTIFICIAL_CLASS_NAME_PREFIX_LENGTH) == 0)
  1557. return S_FALSE;
  1558. IWbemClassObject *pWbemClass = NULL;
  1559. HRESULT result = E_FAIL;
  1560. if(SUCCEEDED(GetClassFromCacheOrADSI(pszWBEMName, &pWbemClass, pCtx)))
  1561. {
  1562. IWbemQualifierSet *pQualifierSet = NULL;
  1563. if(SUCCEEDED(result = pWbemClass->GetQualifierSet(&pQualifierSet)))
  1564. {
  1565. VARIANT_BOOL bAbstract = VARIANT_FALSE;
  1566. if(SUCCEEDED(CWBEMHelper::GetBOOLQualifier(pQualifierSet, ABSTRACT_BSTR, &bAbstract, NULL)))
  1567. {
  1568. if(bAbstract == VARIANT_TRUE)
  1569. result = S_FALSE;
  1570. else
  1571. result = S_OK;
  1572. }
  1573. pQualifierSet->Release();
  1574. }
  1575. pWbemClass->Release();
  1576. }
  1577. return result;
  1578. }
  1579. void CLDAPClassProvider :: SanitizedClassName(LPWSTR lpszClassName)
  1580. {
  1581. while(*lpszClassName)
  1582. {
  1583. *lpszClassName = towlower(*lpszClassName);
  1584. lpszClassName++;
  1585. }
  1586. }