Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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