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.

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