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

567 lines
17 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (C) Microsoft Corporation
  4. //
  5. // Module Name:
  6. //
  7. // IASAttrList.cpp
  8. //
  9. //Abstract:
  10. //
  11. // Implementation of the CIASAttrList class.
  12. // CIASAttrList: a list of IIASAttributeInfo interface pointers
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. #include "precompiled.h"
  16. #include "IasAttrList.h"
  17. #include "iasdebug.h"
  18. #include "SafeArray.h"
  19. #include "vendors.h"
  20. //////////////////////////////////////////////////////////////////////
  21. // Construction/Destruction
  22. //////////////////////////////////////////////////////////////////////
  23. CIASAttrList::CIASAttrList()
  24. {
  25. TRACE_FUNCTION("CIASAttrList::CIASAttrList");
  26. m_fInitialized = FALSE;
  27. }
  28. CIASAttrList::~CIASAttrList()
  29. {
  30. TRACE_FUNCTION("CIASAttrList::~CIASAttrList");
  31. }
  32. //+---------------------------------------------------------------------------
  33. //
  34. // Function: CIASAttrList::CreateAttribute
  35. //
  36. // Synopsis: Create and initialize an IIASAttributeInfo object
  37. //
  38. // Arguments: pIDictionary - Dictionary pointer
  39. // AttrId - Attribute id
  40. // tszAttrName - attribute name
  41. //
  42. //
  43. // Returns: IIASAttributeInfo* - a pointer to the newly created attribute object
  44. // NULL if anything fails
  45. //
  46. // History: Created Header byao 3/20/98 11:16:07 AM
  47. //
  48. //+---------------------------------------------------------------------------
  49. IIASAttributeInfo* CIASAttrList::CreateAttribute( ISdoDictionaryOld* pIDictionary,
  50. ATTRIBUTEID AttrId,
  51. LPTSTR tszAttrName
  52. )
  53. {
  54. TRACE_FUNCTION("CIASAttrList::CreateAttribute");
  55. //
  56. // create a safearray to get the attribuet information
  57. //
  58. CSafeArray<DWORD, VT_I4> InfoIds = Dim(4);
  59. InfoIds.Lock();
  60. InfoIds[0] = SYNTAX;
  61. InfoIds[1] = RESTRICTIONS;
  62. InfoIds[2] = VENDORID;
  63. InfoIds[3] = DESCRIPTION;
  64. InfoIds.Unlock();
  65. CComVariant vInfoIds, vInfoValues;
  66. SAFEARRAY sa = (SAFEARRAY)InfoIds;
  67. V_VT(&vInfoIds) = VT_ARRAY;
  68. V_ARRAY(&vInfoIds) = &sa;
  69. // get the attribuet info
  70. HRESULT hr = S_OK;
  71. hr = pIDictionary->GetAttributeInfo(AttrId, &vInfoIds, &vInfoValues);
  72. if ( FAILED(hr) )
  73. {
  74. ErrorTrace(ERROR_NAPMMC_IASATTR,"GetAttributeInfo() failed, err = %x", hr);
  75. ShowErrorDialog(NULL
  76. , IDS_ERROR_SDO_ERROR_GETATTRINFO
  77. , NULL
  78. , hr
  79. );
  80. return NULL;
  81. }
  82. _ASSERTE(V_VT(&vInfoValues) == (VT_ARRAY|VT_VARIANT) );
  83. CSafeArray<CComVariant, VT_VARIANT> InfoValues = V_ARRAY(&vInfoValues);
  84. InfoValues.Lock();
  85. ATTRIBUTESYNTAX asSyntax= (ATTRIBUTESYNTAX) V_I4(&InfoValues[0]);
  86. DWORD dwRestriction = V_I4(&InfoValues[1]);
  87. DWORD dwVendorId = V_I4(&InfoValues[2]);
  88. CComBSTR bstrDescription= V_BSTR(&InfoValues[3]);
  89. InfoValues.Unlock();
  90. //
  91. // check whether tszDESC could be NULL -- this happens when there's no
  92. // description for this attribute.
  93. //
  94. if ( ! bstrDescription )
  95. {
  96. bstrDescription = L" ";
  97. }
  98. // create the attribute ONLY if it can be in a profile or a condition
  99. const DWORD flags = ALLOWEDINCONDITION | ALLOWEDINPROFILE |
  100. ALLOWEDINPROXYCONDITION | ALLOWEDINPROXYPROFILE;
  101. if (!( dwRestriction & flags ))
  102. {
  103. // don't create this attribute 'cause it's useless for us
  104. return NULL;
  105. }
  106. CComPtr<IIASAttributeInfo> spIASAttributeInfo;
  107. try
  108. {
  109. HRESULT hr;
  110. // Decide which kind of AttributeInfo object we will need to pass attribute
  111. // info around in -- enumerable attributes are a special case and need to
  112. // support the IIASEnumerableAttributeInfo interface.
  113. if ( asSyntax == IAS_SYNTAX_ENUMERATOR )
  114. {
  115. hr = CoCreateInstance( CLSID_IASEnumerableAttributeInfo, NULL, CLSCTX_INPROC_SERVER, IID_IIASAttributeInfo, (LPVOID *) &spIASAttributeInfo );
  116. }
  117. else
  118. {
  119. hr = CoCreateInstance( CLSID_IASAttributeInfo, NULL, CLSCTX_INPROC_SERVER, IID_IIASAttributeInfo, (LPVOID *) &spIASAttributeInfo );
  120. }
  121. if( FAILED(hr) ) return NULL;
  122. // Determine the prog ID for the editor which should be used to edit
  123. // this attribute. Make a decision based on attribute ID and/or syntax.
  124. CComBSTR bstrEditorProgID;
  125. if ( AttrId == RADIUS_ATTRIBUTE_VENDOR_SPECIFIC )
  126. {
  127. bstrEditorProgID = L"IAS.VendorSpecificAttributeEditor";
  128. }
  129. else if( (AttrId == MS_ATTRIBUTE_QUARANTINE_IPFILTER) ||
  130. (AttrId == MS_ATTRIBUTE_FILTER) )
  131. {
  132. bstrEditorProgID = L"IAS.IPFilterAttributeEditor";
  133. }
  134. else
  135. {
  136. switch(asSyntax)
  137. {
  138. case IAS_SYNTAX_ENUMERATOR:
  139. {
  140. bstrEditorProgID = L"IAS.EnumerableAttributeEditor";
  141. break;
  142. }
  143. case IAS_SYNTAX_INETADDR:
  144. {
  145. bstrEditorProgID = L"IAS.IPAttributeEditor";
  146. break;
  147. }
  148. case IAS_SYNTAX_BOOLEAN:
  149. {
  150. bstrEditorProgID = L"IAS.BooleanAttributeEditor";
  151. break;
  152. }
  153. default:
  154. {
  155. bstrEditorProgID = L"IAS.StringAttributeEditor";
  156. }
  157. }
  158. }
  159. // Store the editor Prog ID in the attribute info object.
  160. hr = spIASAttributeInfo->put_EditorProgID( bstrEditorProgID );
  161. if( FAILED( hr ) ) throw hr;
  162. // Store the rest of the attribute information.
  163. hr = spIASAttributeInfo->put_AttributeID(AttrId);
  164. if( FAILED( hr ) ) throw hr;
  165. hr = spIASAttributeInfo->put_AttributeSyntax(asSyntax);
  166. if( FAILED( hr ) ) throw hr;
  167. hr = spIASAttributeInfo->put_AttributeRestriction(dwRestriction);
  168. if( FAILED( hr ) ) throw hr;
  169. hr = spIASAttributeInfo->put_VendorID(dwVendorId);
  170. if( FAILED( hr ) ) throw hr;
  171. hr = spIASAttributeInfo->put_AttributeDescription( bstrDescription );
  172. if( FAILED( hr ) ) throw hr;
  173. CComBSTR bstrName = tszAttrName;
  174. hr = spIASAttributeInfo->put_AttributeName( bstrName );
  175. if( FAILED( hr ) ) throw hr;
  176. // Now get the vendor name and store in the attribute.
  177. CComBSTR bstrVendorName;
  178. CComPtr<IIASNASVendors> spIASNASVendors;
  179. hr = CoCreateInstance( CLSID_IASNASVendors, NULL, CLSCTX_INPROC_SERVER, IID_IIASNASVendors, (LPVOID *) &spIASNASVendors );
  180. if( SUCCEEDED(hr) )
  181. {
  182. LONG lIndex;
  183. hr = spIASNASVendors->get_VendorIDToOrdinal(dwVendorId, &lIndex);
  184. if( S_OK == hr )
  185. {
  186. hr = spIASNASVendors->get_VendorName( lIndex, &bstrVendorName );
  187. }
  188. else
  189. hr = ::MakeVendorNameFromVendorID(dwVendorId, &bstrVendorName );
  190. }
  191. // Note: If any of the above calls to the Vendor object failed,
  192. // we will keep going, using a NULL vendor name.
  193. hr = spIASAttributeInfo->put_VendorName( bstrVendorName );
  194. if( FAILED( hr ) ) throw hr;
  195. // Now store an string form describing the attribute syntax.
  196. CComBSTR bstrSyntax;
  197. // ISSUE: Should these all have been localized or are they some kind
  198. // of RADIUS RFC standard? I think they should have been loaded from resources.
  199. switch(asSyntax)
  200. {
  201. case IAS_SYNTAX_BOOLEAN : bstrSyntax = L"Boolean"; break;
  202. case IAS_SYNTAX_INTEGER : bstrSyntax = L"Integer"; break;
  203. case IAS_SYNTAX_ENUMERATOR : bstrSyntax = L"Enumerator"; break;
  204. case IAS_SYNTAX_INETADDR : bstrSyntax = L"InetAddr"; break;
  205. case IAS_SYNTAX_STRING : bstrSyntax = L"String"; break;
  206. case IAS_SYNTAX_OCTETSTRING : bstrSyntax = L"OctetString"; break;
  207. case IAS_SYNTAX_UTCTIME : bstrSyntax = L"UTCTime"; break;
  208. case IAS_SYNTAX_PROVIDERSPECIFIC : bstrSyntax = L"ProviderSpecific"; break;
  209. case IAS_SYNTAX_UNSIGNEDINTEGER : bstrSyntax = L"UnsignedInteger"; break;
  210. default : bstrSyntax = L"Unknown Type"; break;
  211. }
  212. hr = spIASAttributeInfo->put_SyntaxString( bstrSyntax );
  213. if( FAILED(hr) ) throw hr;
  214. }
  215. catch (...)
  216. {
  217. _ASSERTE( FALSE );
  218. ErrorTrace(ERROR_NAPMMC_IASATTRLIST, "Can't create the attribute ,err = %x", GetLastError());
  219. return NULL;
  220. }
  221. // clean up -- we don't need to clean up vInfoIds. It's deleted by ~CSafeArray()
  222. // VariantClear(&vInfoValues);
  223. //
  224. // 3) get the value list for this attribute, if it's enumerator
  225. //
  226. if ( asSyntax == IAS_SYNTAX_ENUMERATOR )
  227. {
  228. // get the enumerable list for this attribute
  229. CComVariant varValueIds, varValueNames;
  230. hr = pIDictionary->EnumAttributeValues(AttrId,
  231. &varValueIds,
  232. &varValueNames);
  233. if ( SUCCEEDED(hr) )
  234. {
  235. _ASSERTE(V_VT(&varValueNames) == (VT_ARRAY|VT_VARIANT) );
  236. _ASSERTE(V_VT(&varValueIds) & (VT_ARRAY|VT_I4) );
  237. // Up above, if the attribute was enumerable, we created
  238. // an attribute info object which implements the IIASEnumerableAttributeInfo
  239. // interface. We query for this interface now
  240. // and load all the enumerates from pAttr into that
  241. // interface of the shema attribute.
  242. CComQIPtr< IIASEnumerableAttributeInfo, &IID_IIASEnumerableAttributeInfo > spIASEnumerableAttributeInfo( spIASAttributeInfo );
  243. if( ! spIASEnumerableAttributeInfo ) return NULL;
  244. // Make sure that the list of enumerates in consistent.
  245. // There should be a 1-1 correspondence between ID's and description strings.
  246. //ISSUE: todo _ASSERTE( lSize == pAttr->m_arrValueIdList.GetSize() );
  247. // get the safearray data
  248. CSafeArray<CComVariant, VT_VARIANT> ValueIds = V_ARRAY(&varValueIds);
  249. CSafeArray<CComVariant, VT_VARIANT> ValueNames = V_ARRAY(&varValueNames);
  250. ValueIds.Lock();
  251. ValueNames.Lock();
  252. int iSize = ValueIds.Elements();
  253. for (int iValueIndex=0; iValueIndex < iSize; iValueIndex++)
  254. {
  255. // ISSUE: Make sure this deep copies the name.
  256. CComBSTR bstrValueName = V_BSTR(&ValueNames[iValueIndex]);
  257. hr = spIASEnumerableAttributeInfo->AddEnumerateDescription( bstrValueName );
  258. if( FAILED( hr ) ) return NULL;
  259. VARIANT * pVar = &ValueIds[iValueIndex];
  260. long lID = V_I4( pVar );
  261. hr = spIASEnumerableAttributeInfo->AddEnumerateID( lID );
  262. if( FAILED( hr ) ) return NULL;
  263. }
  264. ValueIds.Unlock();
  265. ValueNames.Unlock();
  266. }
  267. else
  268. {
  269. // can't get the list.
  270. //todo: need any action here?
  271. hr = S_OK;
  272. }
  273. }
  274. // Note: We have a bit of a RefCounting issue here.
  275. // As soon as we leave this function, desstructor for CComPtr
  276. // will be called, Release'ing the IIASAttributeInfo interface.
  277. // This will happen before the CComPtr on the other side has
  278. // had a chance to AddRef it.
  279. // As a temporary hack, we AddRef here and release on the other side.
  280. spIASAttributeInfo.p->AddRef();
  281. return spIASAttributeInfo.p;
  282. }
  283. //+---------------------------------------------------------------------------
  284. //
  285. // Function: Init
  286. //
  287. // Class: CIASAttrList
  288. //
  289. // Synopsis: Populate the condition attribute list. Do nothing
  290. // if the list is already populated
  291. //
  292. // Arguments: [in]ISdo *pIDictionarySdo: dictionary sdo
  293. //
  294. // Returns: HRESULT -
  295. //
  296. // History: Created Header byao 2/16/98 4:57:07 PM
  297. //
  298. //+---------------------------------------------------------------------------
  299. HRESULT CIASAttrList::Init(ISdoDictionaryOld *pIDictionarySdo)
  300. {
  301. TRACE_FUNCTION("CIASAttrList::Init");
  302. _ASSERTE( pIDictionarySdo != NULL );
  303. if (m_fInitialized)
  304. {
  305. //
  306. // the list has already been populated -- do nothing
  307. //
  308. return S_OK;
  309. }
  310. // The push_back call below can throw an exception.
  311. try
  312. {
  313. //
  314. // Get all the attributes that can be used in a condition
  315. //
  316. int iIndex;
  317. HRESULT hr = S_OK;
  318. CComVariant vNames;
  319. CComVariant vIds;
  320. hr = pIDictionarySdo -> EnumAttributes(&vIds, &vNames);
  321. if ( FAILED(hr) )
  322. {
  323. ErrorTrace(ERROR_NAPMMC_IASATTRLIST, "EnumAttributes() failed, err = %x", hr);
  324. ShowErrorDialog(NULL
  325. , IDS_ERROR_SDO_ERROR_ENUMATTR
  326. , NULL
  327. , hr
  328. );
  329. return hr;
  330. }
  331. _ASSERTE(V_VT(&vIds) == (VT_ARRAY|VT_I4) );
  332. _ASSERTE(V_VT(&vNames) == (VT_ARRAY|VT_VARIANT) );
  333. CSafeArray<DWORD, VT_I4> AttrIds = V_ARRAY(&vIds);
  334. CSafeArray<CComVariant, VT_VARIANT> AttrNames = V_ARRAY(&vNames);
  335. AttrIds.Lock();
  336. AttrNames.Lock();
  337. for (iIndex = 0; iIndex < AttrIds.Elements(); iIndex++)
  338. {
  339. // create an attribute object
  340. DebugTrace(DEBUG_NAPMMC_IASATTRLIST, "Creating an attribute, name = %ws", V_BSTR(&AttrNames[iIndex]) );
  341. _ASSERTE( V_BSTR(&AttrNames[iIndex]) );
  342. CComPtr<IIASAttributeInfo> spAttributeInfo = CreateAttribute(pIDictionarySdo,
  343. (ATTRIBUTEID)AttrIds[iIndex],
  344. V_BSTR(&AttrNames[iIndex])
  345. );
  346. if ( ! spAttributeInfo )
  347. {
  348. continue; // create the next attribute
  349. }
  350. // See note in CreateAttribute for why we Release here.
  351. spAttributeInfo.p->Release();
  352. m_AttrList.push_back(spAttributeInfo);
  353. } // for
  354. AttrIds.Unlock();
  355. AttrNames.Unlock();
  356. m_fInitialized = TRUE;
  357. }
  358. catch(...)
  359. {
  360. return E_FAIL;
  361. }
  362. return S_OK;
  363. }
  364. //+---------------------------------------------------------------------------
  365. //
  366. // Function: GetSize
  367. //
  368. // Class: CIASAttrList
  369. //
  370. // Synopsis: get the number of elements in the condition attribute list
  371. //
  372. // Arguments: None
  373. //
  374. // Returns: DWORD - list length
  375. //
  376. // History: Created Header byao 2/16/98 8:11:17 PM
  377. //
  378. //+---------------------------------------------------------------------------
  379. DWORD CIASAttrList::size() const
  380. {
  381. if (!m_fInitialized)
  382. {
  383. ::MessageBox(NULL,L"populate the list first!", L"", MB_OK);
  384. return E_NOTIMPL;
  385. }
  386. else
  387. {
  388. return m_AttrList.size();
  389. }
  390. }
  391. //+---------------------------------------------------------------------------
  392. //
  393. // Function: operator[]
  394. //
  395. // Class: CIASAttrList
  396. //
  397. // Synopsis: get the condition attribute pointer at index [nIndex]
  398. //
  399. // Arguments: int nIndex - index
  400. //
  401. // Returns: IIASAttributeInfo* : pointer to a condition attribute object
  402. //
  403. // History: Created Header byao 2/16/98 8:16:37 PM
  404. //
  405. //+---------------------------------------------------------------------------
  406. IIASAttributeInfo* CIASAttrList:: operator[] (int nIndex) const
  407. {
  408. if (!m_fInitialized)
  409. {
  410. ::MessageBox(NULL,L"populate the list first!", L"", MB_OK);
  411. return NULL;
  412. }
  413. else
  414. {
  415. _ASSERTE(nIndex >= 0 && nIndex < m_AttrList.size());
  416. return m_AttrList[nIndex].p;
  417. }
  418. }
  419. //+---------------------------------------------------------------------------
  420. //
  421. // Function: GetAt()
  422. //
  423. // Class: CIASAttrList
  424. //
  425. // Synopsis: get the condition attribute pointer at nIndex
  426. //
  427. // Arguments: int nIndex - index
  428. //
  429. // Returns: IIASAttributeInfo* : pointer to a condition attribute object
  430. //
  431. // History: Created Header byao 2/16/98 8:16:37 PM
  432. //
  433. //+---------------------------------------------------------------------------
  434. IIASAttributeInfo* CIASAttrList:: GetAt(int nIndex) const
  435. {
  436. TRACE_FUNCTION("CIASAttrList::GetAt");
  437. if (!m_fInitialized)
  438. {
  439. ErrorTrace(ERROR_NAPMMC_IASATTRLIST, "The list is NOT initialized!");
  440. return NULL;
  441. }
  442. else
  443. {
  444. _ASSERTE(nIndex >= 0 && nIndex < m_AttrList.size());
  445. return m_AttrList[nIndex].p;
  446. }
  447. }
  448. //+---------------------------------------------------------------------------
  449. //
  450. // Function: CIASAttrList::Find
  451. //
  452. // Synopsis: Find an attribute based on attribute ID
  453. //
  454. // Arguments: ATTRIBUTEID AttrId - attribute id
  455. //
  456. // Returns: int - index in the list
  457. //
  458. // History: Created Header 2/22/98 1:52:36 AM
  459. //
  460. //+---------------------------------------------------------------------------
  461. int CIASAttrList::Find(ATTRIBUTEID AttrId)
  462. {
  463. int iIndex;
  464. // The operator [] below can throw exceptions.
  465. try
  466. {
  467. for (iIndex=0; iIndex<m_AttrList.size(); iIndex++)
  468. {
  469. ATTRIBUTEID id;
  470. m_AttrList[iIndex]->get_AttributeID( &id );
  471. if( id == AttrId )
  472. {
  473. // found
  474. return iIndex;
  475. }
  476. }
  477. }
  478. catch(...)
  479. {
  480. // Just catch the exception -- we'll return -1 below.
  481. }
  482. // not found
  483. return -1;
  484. }