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.

507 lines
12 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. ProfileSchema.cpp
  5. Abstract:
  6. Implementation of profile schema lookup
  7. Usage:
  8. Author:
  9. Max Metral (mmetral) 15-Dec-1998
  10. Revision History:
  11. 15-Dec-1998 mmetral
  12. Created.
  13. --*/
  14. #include "stdafx.h"
  15. #include "ProfileSchema.h"
  16. #include "BstrDebug.h"
  17. #include <winsock2.h> // u_short, u_long, ntohs, ntohl
  18. CProfileSchema::CProfileSchema()
  19. : m_isOk(FALSE), m_szReason(L"Uninitialized"),
  20. m_numAtts(0), m_atts(NULL), m_sizes(NULL), m_refs(0),
  21. m_readOnly(NULL), m_indexes("ProfileSchema",LK_DFLT_MAXLOAD,LK_SMALL_TABLESIZE,0),
  22. m_maskPos(-1)
  23. {
  24. }
  25. CProfileSchema::~CProfileSchema()
  26. {
  27. if (m_atts != NULL)
  28. delete[] m_atts;
  29. if (m_sizes != NULL)
  30. delete[] m_sizes;
  31. if (m_readOnly != NULL)
  32. delete[] m_readOnly;
  33. if (m_indexes.Size() > 0)
  34. {
  35. LK_RETCODE lkrc;
  36. const RAWBSTR2INT& htConst = m_indexes;
  37. RAWBSTR2INT::CConstIterator itconst;
  38. for (lkrc = htConst.InitializeIterator(&itconst) ;
  39. lkrc == LK_SUCCESS ;
  40. lkrc = htConst.IncrementIterator(&itconst))
  41. {
  42. FREE_BSTR(itconst.Key());
  43. }
  44. htConst.CloseIterator(&itconst);
  45. m_indexes.Clear();
  46. }
  47. }
  48. BOOL CProfileSchema::Read(MSXML::IXMLElementPtr &root)
  49. {
  50. BOOL bResult = FALSE;
  51. int cAtts = 0, i;
  52. MSXML::IXMLElementCollectionPtr atts;
  53. MSXML::IXMLElementPtr pElt;
  54. VARIANT iAtts;
  55. // Type identifiers
  56. _bstr_t btText(L"text"), btChar(L"char"), btByte(L"byte");
  57. _bstr_t btWord(L"word"), btLong(L"long"), btDate(L"date");;
  58. _bstr_t name(L"name"), type(L"type"), size(L"size"), acc(L"access");
  59. try
  60. {
  61. // Ok, now iterate over attributes
  62. atts = root->children;
  63. cAtts = atts->length;
  64. if (cAtts <= 0)
  65. {
  66. _com_issue_error(E_FAIL);
  67. }
  68. if (m_atts)
  69. {
  70. delete[] m_atts;
  71. m_atts = NULL;
  72. }
  73. if (m_sizes)
  74. {
  75. delete[] m_sizes;
  76. m_sizes = NULL;
  77. }
  78. if (m_readOnly)
  79. {
  80. delete[] m_readOnly;
  81. m_readOnly = NULL;
  82. }
  83. if (m_indexes.Size() == 0)
  84. {
  85. LK_RETCODE lkrc;
  86. const RAWBSTR2INT& htConst = m_indexes;
  87. RAWBSTR2INT::CConstIterator itconst;
  88. for (lkrc = htConst.InitializeIterator(&itconst) ;
  89. lkrc == LK_SUCCESS ;
  90. lkrc = htConst.IncrementIterator(&itconst))
  91. {
  92. FREE_BSTR(itconst.Key());
  93. }
  94. htConst.CloseIterator(&itconst);
  95. m_indexes.Clear();
  96. }
  97. m_atts = new AttrType[cAtts];
  98. m_sizes = new short[cAtts];
  99. m_readOnly = new BYTE[cAtts];
  100. m_numAtts = cAtts;
  101. VariantInit(&iAtts);
  102. iAtts.vt = VT_I4;
  103. for (iAtts.lVal = 0; iAtts.lVal < cAtts; iAtts.lVal++)
  104. {
  105. i = iAtts.lVal;
  106. m_readOnly[i] = 0;
  107. pElt = atts->item(iAtts);
  108. _bstr_t aType = pElt->getAttribute(type);
  109. _bstr_t aName = pElt->getAttribute(name);
  110. _bstr_t aAccess = pElt->getAttribute(acc);
  111. if (aAccess.length() > 0 && !_wcsicmp(aAccess, L"ro"))
  112. {
  113. m_readOnly[i] = 1;
  114. }
  115. // [DARRENAN] Don't add empty names to the list. This is so we can deprecate the use
  116. // of certain attributes w/o removing their position in the schema. First example
  117. // of this is inetaccess.
  118. if(aName.length() != 0)
  119. {
  120. BSTR aNameCopy = ALLOC_BSTR(aName);
  121. if (!aNameCopy)
  122. _com_issue_error(E_OUTOFMEMORY);
  123. RAWBSTR2INT::ValueType *pMapVal = new RAWBSTR2INT::ValueType(aNameCopy, i);
  124. if (!pMapVal || LK_SUCCESS != m_indexes.InsertRecord(pMapVal))
  125. _com_issue_error(E_FAIL);
  126. }
  127. if (aType == btText)
  128. {
  129. m_atts[i] = tText;
  130. m_sizes[i]= -1;
  131. }
  132. else if (aType == btChar)
  133. {
  134. m_atts[i] = tChar;
  135. m_sizes[i]= _wtoi(_bstr_t(pElt->getAttribute(size)))*8;
  136. }
  137. else if (aType == btByte)
  138. {
  139. m_atts[i] = tByte;
  140. m_sizes[i]= 8;
  141. }
  142. else if (aType == btWord)
  143. {
  144. m_atts[i] = tWord;
  145. m_sizes[i]= 16;
  146. }
  147. else if (aType == btLong)
  148. {
  149. m_atts[i] = tLong;
  150. m_sizes[i] = 32;
  151. }
  152. else if (aType == btDate)
  153. {
  154. m_atts[i] = tDate;
  155. m_sizes[i] = 32;
  156. }
  157. else
  158. _com_issue_error(E_FAIL);
  159. }
  160. bResult = TRUE;
  161. }
  162. catch (_com_error &e)
  163. {
  164. //
  165. // PASSPORTLOG is empty. Do nothing here.
  166. //
  167. if (m_atts)
  168. {
  169. delete[] m_atts;
  170. m_atts = NULL;
  171. }
  172. if (m_sizes)
  173. {
  174. delete[] m_sizes;
  175. m_sizes = NULL;
  176. }
  177. if (m_readOnly)
  178. {
  179. delete[] m_readOnly;
  180. m_readOnly = NULL;
  181. }
  182. bResult = m_isOk = FALSE;
  183. }
  184. return bResult;
  185. }
  186. BOOL CProfileSchema::ReadFromArray(UINT numAttributes, LPTSTR names[], AttrType types[], short sizes[], BYTE readOnly[])
  187. {
  188. BOOL bAbnormal = FALSE;
  189. if (m_atts)
  190. {
  191. delete[] m_atts;
  192. m_atts = NULL;
  193. }
  194. if (m_sizes)
  195. {
  196. delete[] m_sizes;
  197. m_sizes = NULL;
  198. }
  199. if (m_readOnly)
  200. {
  201. delete[] m_readOnly;
  202. m_readOnly = NULL;
  203. }
  204. if (m_indexes.Size() == 0)
  205. {
  206. LK_RETCODE lkrc;
  207. const RAWBSTR2INT& htConst = m_indexes;
  208. RAWBSTR2INT::CConstIterator itconst;
  209. for (lkrc = htConst.InitializeIterator(&itconst) ;
  210. lkrc == LK_SUCCESS ;
  211. lkrc = htConst.IncrementIterator(&itconst))
  212. {
  213. FREE_BSTR(itconst.Key());
  214. }
  215. htConst.CloseIterator(&itconst);
  216. m_indexes.Clear();
  217. }
  218. if (!numAttributes) {
  219. return FALSE;
  220. }
  221. m_numAtts = numAttributes;
  222. m_atts = new AttrType[m_numAtts];
  223. m_sizes = new short[m_numAtts];
  224. m_readOnly = new BYTE[m_numAtts];
  225. if (!m_atts || !m_sizes || !m_readOnly) {
  226. if (m_atts)
  227. {
  228. delete[] m_atts;
  229. m_atts = NULL;
  230. }
  231. if (m_sizes)
  232. {
  233. delete[] m_sizes;
  234. m_sizes = NULL;
  235. }
  236. if (m_readOnly)
  237. {
  238. delete[] m_readOnly;
  239. m_readOnly = NULL;
  240. }
  241. return FALSE;
  242. }
  243. try{
  244. for (UINT i = 0; i < m_numAtts; i++)
  245. {
  246. BSTR copy = ALLOC_BSTR((LPCWSTR) names[i]);
  247. if (!copy){
  248. bAbnormal = TRUE;
  249. }
  250. RAWBSTR2INT::ValueType *pMapVal = new RAWBSTR2INT::ValueType(copy, i);
  251. if (!pMapVal || m_indexes.InsertRecord(pMapVal) != LK_SUCCESS)
  252. {
  253. bAbnormal = TRUE;
  254. }
  255. m_atts[i] = types[i];
  256. // BUGBUG we shouldn't copy directly if it's a type we KNOW the size of
  257. // should be a switch here
  258. m_sizes[i] = sizes[i];
  259. if (readOnly)
  260. m_readOnly[i] = readOnly[i];
  261. else
  262. m_readOnly[i] = 0;
  263. }
  264. }
  265. catch (...)
  266. {
  267. //
  268. // We could get exception if names[i] and etc. is invalid.
  269. // Maybe, I am too cautious. Index server shows this routine is only
  270. // called in InitAuthSchema() and InitSecureSchema(). This extra cautious
  271. // step might not be too bad for passport code :-)
  272. //
  273. if (m_atts)
  274. {
  275. delete[] m_atts;
  276. m_atts = NULL;
  277. }
  278. if (m_sizes)
  279. {
  280. delete[] m_sizes;
  281. m_sizes = NULL;
  282. }
  283. if (m_readOnly)
  284. {
  285. delete[] m_readOnly;
  286. m_readOnly = NULL;
  287. }
  288. bAbnormal = TRUE;
  289. }
  290. if (!bAbnormal) {
  291. m_isOk = true;
  292. }
  293. return !bAbnormal;
  294. }
  295. int CProfileSchema::GetBitSize(UINT index) const
  296. {
  297. if (index > m_numAtts)
  298. return 0;
  299. return m_sizes[index];
  300. }
  301. int CProfileSchema::GetByteSize(UINT index) const
  302. {
  303. if (index > m_numAtts)
  304. return 0;
  305. if (m_sizes[index] != -1)
  306. return m_sizes[index]/8;
  307. else
  308. return -1;
  309. }
  310. CProfileSchema::AttrType CProfileSchema::GetType(UINT index) const
  311. {
  312. if (index > m_numAtts)
  313. return AttrType::tInvalid;
  314. return m_atts[index];
  315. }
  316. BOOL CProfileSchema::IsReadOnly(UINT index) const
  317. {
  318. if (index > m_numAtts)
  319. return TRUE;
  320. return m_readOnly[index] != 0;
  321. }
  322. int CProfileSchema::GetIndexByName(BSTR name) const
  323. {
  324. const RAWBSTR2INT& htConst = m_indexes;
  325. const RAWBSTR2INT::ValueType *pOut = NULL;
  326. if (LK_SUCCESS == m_indexes.FindKey(name, &pOut) && pOut != NULL)
  327. {
  328. int o = pOut->m_v;
  329. m_indexes.AddRefRecord(pOut, -1);
  330. return o;
  331. }
  332. else
  333. return -1;
  334. }
  335. BSTR CProfileSchema::GetNameByIndex(int index) const
  336. {
  337. LK_RETCODE lkrc;
  338. const RAWBSTR2INT& htConst = m_indexes;
  339. RAWBSTR2INT::CConstIterator it;
  340. for (lkrc = htConst.InitializeIterator(&it) ;
  341. lkrc == LK_SUCCESS ;
  342. lkrc = htConst.IncrementIterator(&it))
  343. {
  344. if (it.Record()->m_v == index)
  345. {
  346. BSTR r = it.Key();
  347. htConst.CloseIterator(&it);
  348. return r;
  349. }
  350. }
  351. htConst.CloseIterator(&it);
  352. return NULL;
  353. }
  354. HRESULT CProfileSchema::parseProfile(LPSTR raw, UINT size, UINT *positions, UINT *bitFlagPositions, DWORD* pdwAttris)
  355. {
  356. // Read the raw blob according to the schema, and output the positions of
  357. // each element
  358. UINT i, spot = 0, curBits = 0, thisSize;
  359. // they have to be good memory
  360. if (IsBadWritePtr(positions, m_numAtts * sizeof(UINT))) return E_INVALIDARG;
  361. if (IsBadWritePtr(bitFlagPositions, m_numAtts * sizeof(UINT))) return E_INVALIDARG;
  362. if (!pdwAttris) return E_INVALIDARG;
  363. // initialize the arrays
  364. for (i = 0; i < m_numAtts; i++)
  365. {
  366. *(positions + i) = INVALID_POS; // position of -1 is not defined
  367. *(bitFlagPositions + i) = 0; // bit flag position of 0, is to start from begining
  368. }
  369. // number of attributes - init 0
  370. *pdwAttris = 0;
  371. for (i = 0; i < m_numAtts && spot < size; i++)
  372. {
  373. //
  374. // increment attrib cnt moved at the end. Added a check
  375. // that the new attrib size fits in the buf len
  376. //
  377. positions[i] = spot;
  378. thisSize = GetByteSize(i);
  379. if (thisSize && curBits)
  380. {
  381. // Make sure the padding lines up on a boundary
  382. if ((curBits + m_sizes[i])%8)
  383. {
  384. // Something wrong, can't align on non-byte boundaries
  385. return E_INVALIDARG;
  386. }
  387. spot += ((curBits+m_sizes[i])/8);
  388. }
  389. UINT iRemain = size - spot; // # of byte left to parse
  390. if (thisSize == 0xFFFFFFFF) // String
  391. {
  392. if(iRemain < sizeof(u_short)) return E_INVALIDARG;
  393. iRemain -= sizeof(u_short);
  394. //
  395. // due to IA64 alignment faults this memcpy needs to be performed
  396. //
  397. u_short sz;
  398. memcpy((PBYTE)&sz, raw+spot, sizeof(sz));
  399. sz = ntohs(sz);
  400. if(iRemain < sz) return E_INVALIDARG;
  401. spot += sizeof(u_short)+sz;
  402. }
  403. else if (thisSize != 0)
  404. {
  405. if(iRemain < thisSize) return E_INVALIDARG;
  406. spot += thisSize; // Simple, just a fixed length
  407. }
  408. else // Bit field
  409. {
  410. curBits += m_sizes[i];
  411. // If this is a pad, this field is irrelevant anyway,
  412. // otherwise, it's one bit long
  413. bitFlagPositions[i] = curBits;
  414. while (curBits >= 8)
  415. {
  416. spot ++;
  417. curBits -= 8;
  418. }
  419. }
  420. if (spot <= size)
  421. (*pdwAttris)++;
  422. }
  423. if (i == 0)
  424. return S_FALSE;
  425. else
  426. return S_OK;
  427. }
  428. CProfileSchema* CProfileSchema::AddRef()
  429. {
  430. InterlockedIncrement(&m_refs);
  431. return this;
  432. }
  433. void CProfileSchema::Release()
  434. {
  435. InterlockedDecrement(&m_refs);
  436. if (m_refs == 0)
  437. delete this;
  438. }