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.

1085 lines
30 KiB

  1. /**********************************************************************/
  2. /** Microsoft Passport **/
  3. /** Copyright(c) Microsoft Corporation, 1999 - 2001 **/
  4. /**********************************************************************/
  5. /*
  6. Profile.cpp
  7. FILE HISTORY:
  8. */
  9. // Profile.cpp : Implementation of CProfile
  10. #include "stdafx.h"
  11. #include <oleauto.h>
  12. #include "Passport.h"
  13. #include "Profile.h"
  14. // gmarks
  15. #include "Monitoring.h"
  16. /////////////////////////////////////////////////////////////////////////////
  17. // CProfile
  18. //===========================================================================
  19. //
  20. // CProfile
  21. //
  22. CProfile::CProfile() : m_raw(NULL), m_pos(NULL), m_bitPos(NULL),
  23. m_schemaName(NULL), m_valid(FALSE), m_updates(NULL), m_schema(NULL),
  24. m_versionAttributeIndex(-1), m_secure(FALSE)
  25. {
  26. }
  27. //===========================================================================
  28. //
  29. // ~CProfile
  30. //
  31. CProfile::~CProfile()
  32. {
  33. if (m_raw)
  34. FREE_BSTR(m_raw);
  35. if (m_pos)
  36. delete[] m_pos;
  37. if (m_bitPos)
  38. delete[] m_bitPos;
  39. if (m_schemaName)
  40. FREE_BSTR(m_schemaName);
  41. if (m_updates)
  42. {
  43. for (int i = 0; i < m_schema->Count(); i++)
  44. {
  45. if (m_updates[i])
  46. delete[] m_updates[i];
  47. }
  48. delete[] m_updates;
  49. }
  50. if (m_schema)
  51. m_schema->Release();
  52. }
  53. //===========================================================================
  54. //
  55. // InterfaceSupportsErrorInfo
  56. //
  57. STDMETHODIMP CProfile::InterfaceSupportsErrorInfo(REFIID riid)
  58. {
  59. static const IID* arr[] =
  60. {
  61. &IID_IPassportProfile,
  62. };
  63. for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
  64. {
  65. if (InlineIsEqualGUID(*arr[i],riid))
  66. return S_OK;
  67. }
  68. return S_FALSE;
  69. }
  70. //===========================================================================
  71. //
  72. // get_Attribute
  73. //
  74. STDMETHODIMP CProfile::get_Attribute(BSTR name, VARIANT *pVal)
  75. {
  76. VariantInit(pVal);
  77. if (!m_valid) return S_OK; // Already threw event somewhere else
  78. if (!m_schema)
  79. {
  80. AtlReportError(CLSID_Profile, PP_E_NOT_CONFIGUREDSTR,
  81. IID_IPassportProfile, PP_E_NOT_CONFIGURED);
  82. return PP_E_NOT_CONFIGURED;
  83. }
  84. if (!name) return E_INVALIDARG;
  85. if (!_wcsicmp(name, L"internalmembername"))
  86. {
  87. // return the internal name
  88. return get_ByIndex(MEMBERNAME_INDEX, pVal);
  89. }
  90. int index = m_schema->GetIndexByName(name);
  91. if (index >= 0)
  92. {
  93. if( index != MEMBERNAME_INDEX )
  94. {
  95. return get_ByIndex(index, pVal);
  96. }
  97. else
  98. {
  99. //
  100. // special case for MEMBERNAME, if this the name is
  101. // in the format of email, we will need do something here
  102. //
  103. HRESULT hr = get_ByIndex(MEMBERNAME_INDEX, pVal);
  104. if( S_OK == hr && VT_BSTR == pVal->vt )
  105. {
  106. int bstrLen = SysStringLen(pVal->bstrVal);
  107. int i = 0;
  108. int iChangePos = 0;
  109. int iTerminatePos = 0;
  110. for( i = 0; i < bstrLen; i++)
  111. {
  112. if( pVal->bstrVal[i] == L'%' )
  113. iChangePos = i;
  114. if( pVal->bstrVal[i] == L'@' )
  115. iTerminatePos = i;
  116. }
  117. //
  118. // for email format, we must have iChangePos < iTerminatePos
  119. // this code will convert "foo%[email protected]" into
  120. // "[email protected]"
  121. //
  122. if( iChangePos && iTerminatePos && iChangePos < iTerminatePos )
  123. {
  124. BSTR bstrTemp = pVal->bstrVal;
  125. pVal->bstrVal[iChangePos] = L'@';
  126. pVal->bstrVal[iTerminatePos] = L'\0';
  127. pVal->bstrVal = SysAllocString(pVal->bstrVal);
  128. if (NULL == pVal->bstrVal)
  129. return E_OUTOFMEMORY;
  130. SysFreeString(bstrTemp);
  131. }
  132. }
  133. return hr;
  134. }
  135. }
  136. else
  137. {
  138. AtlReportError(CLSID_Profile, PP_E_NO_SUCH_ATTRIBUTESTR,
  139. IID_IPassportProfile, PP_E_NO_SUCH_ATTRIBUTE);
  140. return PP_E_NO_SUCH_ATTRIBUTE;
  141. }
  142. return S_OK;
  143. }
  144. //===========================================================================
  145. //
  146. // put_Attribute
  147. //
  148. STDMETHODIMP CProfile::put_Attribute(BSTR name, VARIANT newVal)
  149. {
  150. PassportLog("CProfile::put_Attribute:\r\n");
  151. if(g_pPerf)
  152. {
  153. g_pPerf->incrementCounter(PM_PROFILEUPDATES_TOTAL);
  154. g_pPerf->incrementCounter(PM_PROFILEUPDATES_SEC);
  155. }
  156. else
  157. {
  158. _ASSERT(g_pPerf);
  159. }
  160. if (!m_valid) return S_OK; // Already threw event somewhere else
  161. if (!m_schema)
  162. {
  163. AtlReportError(CLSID_Profile, PP_E_NOT_CONFIGUREDSTR,
  164. IID_IPassportProfile, PP_E_NOT_CONFIGURED);
  165. return PP_E_NOT_CONFIGURED;
  166. }
  167. if (!name) return E_INVALIDARG;
  168. PassportLog(" %ws\r\n", name);
  169. int index = m_schema->GetIndexByName(name);
  170. if (index >= 0)
  171. return put_ByIndex(index, newVal);
  172. else
  173. {
  174. AtlReportError(CLSID_Profile, PP_E_NO_SUCH_ATTRIBUTESTR,
  175. IID_IPassportProfile, PP_E_NO_SUCH_ATTRIBUTE);
  176. return PP_E_NO_SUCH_ATTRIBUTE;
  177. }
  178. return S_OK;
  179. }
  180. //===========================================================================
  181. //
  182. // get_ByIndex
  183. //
  184. STDMETHODIMP CProfile::get_ByIndex(int index, VARIANT *pVal)
  185. {
  186. u_short slen;
  187. u_long llen;
  188. if(!pVal) return E_INVALIDARG;
  189. VariantInit(pVal);
  190. if (!m_valid) return S_OK;
  191. if (!m_schema)
  192. {
  193. AtlReportError(CLSID_Profile, PP_E_NOT_CONFIGUREDSTR,
  194. IID_IPassportProfile, PP_E_NOT_CONFIGURED);
  195. return PP_E_NOT_CONFIGURED;
  196. }
  197. if (m_pos[index] == INVALID_POS) return S_FALSE; // the return value is VT_EMPTY
  198. if (index >= m_schema->Count())
  199. {
  200. AtlReportError(CLSID_Profile, PP_E_NO_SUCH_ATTRIBUTESTR,
  201. IID_IPassportProfile, PP_E_NO_SUCH_ATTRIBUTE);
  202. return PP_E_NO_SUCH_ATTRIBUTE;
  203. }
  204. LPSTR raw = (LPSTR)m_raw;
  205. CProfileSchema::AttrType t = m_schema->GetType(index);
  206. switch (t)
  207. {
  208. case CProfileSchema::tText:
  209. {
  210. //
  211. // due to IA64 alignment faults this memcpy needs to be performed
  212. //
  213. memcpy((PBYTE)&slen, raw+m_pos[index], sizeof(slen));
  214. slen = ntohs(slen);
  215. pVal->vt = VT_BSTR;
  216. if (slen == 0)
  217. {
  218. pVal->bstrVal = ALLOC_AND_GIVEAWAY_BSTR_LEN(L"", 0);
  219. }
  220. else
  221. {
  222. int wlen = MultiByteToWideChar(CP_UTF8, 0,
  223. raw+m_pos[index]+sizeof(u_short),
  224. slen, NULL, 0);
  225. pVal->bstrVal = ALLOC_AND_GIVEAWAY_BSTR_LEN(NULL, wlen);
  226. if (NULL == pVal->bstrVal)
  227. return E_OUTOFMEMORY;
  228. MultiByteToWideChar(CP_UTF8, 0,
  229. raw+m_pos[index]+sizeof(u_short),
  230. slen, pVal->bstrVal, wlen);
  231. pVal->bstrVal[wlen] = L'\0';
  232. }
  233. }
  234. break;
  235. case CProfileSchema::tChar:
  236. {
  237. int wlen = MultiByteToWideChar(CP_UTF8, 0,
  238. raw+m_pos[index],
  239. m_schema->GetByteSize(index), NULL, 0);
  240. pVal->vt = VT_BSTR;
  241. pVal->bstrVal = ALLOC_AND_GIVEAWAY_BSTR_LEN(NULL, wlen);
  242. if (NULL == pVal->bstrVal)
  243. return E_OUTOFMEMORY;
  244. MultiByteToWideChar(CP_UTF8, 0,
  245. raw+m_pos[index],
  246. m_schema->GetByteSize(index), pVal->bstrVal, wlen);
  247. pVal->bstrVal[wlen] = L'\0';
  248. }
  249. break;
  250. case CProfileSchema::tByte:
  251. pVal->vt = VT_I2;
  252. pVal->iVal = *(BYTE*)(raw+m_pos[index]);
  253. break;
  254. case CProfileSchema::tWord:
  255. pVal->vt = VT_I2;
  256. //
  257. // due to IA64 alignment faults this memcpy needs to be performed
  258. //
  259. memcpy((PBYTE)&slen, raw+m_pos[index], sizeof(slen));
  260. pVal->iVal = ntohs(slen);
  261. break;
  262. case CProfileSchema::tLong:
  263. pVal->vt = VT_I4;
  264. //
  265. // due to IA64 alignment faults this memcpy needs to be performed
  266. //
  267. memcpy((PBYTE)&llen, raw+m_pos[index], sizeof(llen));
  268. pVal->lVal = ntohl(llen);
  269. break;
  270. case CProfileSchema::tDate:
  271. pVal->vt = VT_DATE;
  272. //
  273. // due to IA64 alignment faults this memcpy needs to be performed
  274. //
  275. memcpy((PBYTE)&llen, raw+m_pos[index], sizeof(llen));
  276. llen = ntohl(llen);
  277. VarDateFromI4(llen, &(pVal->date));
  278. break;
  279. default:
  280. AtlReportError(CLSID_Profile, PP_E_BAD_DATA_FORMATSTR,
  281. IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
  282. return PP_E_BAD_DATA_FORMAT;
  283. }
  284. return S_OK;
  285. }
  286. //===========================================================================
  287. //
  288. // put_ByIndex
  289. //
  290. STDMETHODIMP CProfile::put_ByIndex(int index, VARIANT newVal)
  291. {
  292. static int nEmailIndex, nFlagsIndex;
  293. if(nEmailIndex == 0)
  294. nEmailIndex = m_schema->GetIndexByName(L"preferredEmail");
  295. if(nFlagsIndex == 0)
  296. nFlagsIndex = m_schema->GetIndexByName(L"flags");
  297. if(g_pPerf)
  298. {
  299. g_pPerf->incrementCounter(PM_PROFILEUPDATES_TOTAL);
  300. g_pPerf->incrementCounter(PM_PROFILEUPDATES_SEC);
  301. }
  302. else
  303. {
  304. _ASSERT(g_pPerf);
  305. }
  306. if (!m_valid) return S_OK;
  307. if (!m_schema)
  308. {
  309. AtlReportError(CLSID_Profile, PP_E_NOT_CONFIGUREDSTR,
  310. IID_IPassportProfile, PP_E_NOT_CONFIGURED);
  311. return PP_E_NOT_CONFIGURED;
  312. }
  313. if (index >= m_schema->Count())
  314. {
  315. AtlReportError(CLSID_Profile, PP_E_NO_SUCH_ATTRIBUTESTR,
  316. IID_IPassportProfile, PP_E_NO_SUCH_ATTRIBUTE);
  317. return PP_E_NO_SUCH_ATTRIBUTE;
  318. }
  319. if (m_schema->IsReadOnly(index))
  320. {
  321. AtlReportError(CLSID_Profile, PP_E_READONLY_ATTRIBUTESTR,
  322. IID_IPassportProfile, PP_E_READONLY_ATTRIBUTE);
  323. return PP_E_READONLY_ATTRIBUTE;
  324. }
  325. // Now, if the update array doesn't exist, make it
  326. if (!m_updates)
  327. {
  328. m_updates = (void**) new void*[m_schema->Count()];
  329. if (!m_updates)
  330. return E_OUTOFMEMORY;
  331. memset(m_updates, 0, m_schema->Count()*sizeof(void*));
  332. }
  333. // What type is this attribute?
  334. CProfileSchema::AttrType t = m_schema->GetType(index);
  335. if (m_updates[index] != NULL)
  336. {
  337. delete[] m_updates[index];
  338. m_updates[index] = NULL;
  339. }
  340. _variant_t dest;
  341. // I don't really like that we have to alloc memory for each entry (even bits)
  342. // but this happens infrequently enough that I'm not too upset
  343. switch (t)
  344. {
  345. case CProfileSchema::tText:
  346. {
  347. // Convert to UTF-8, stuff it
  348. if (VariantChangeType(&dest, &newVal, 0, VT_BSTR) != S_OK)
  349. {
  350. AtlReportError(CLSID_Profile, PP_E_BDF_TOSTRCVT,
  351. IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
  352. return PP_E_BAD_DATA_FORMAT;
  353. }
  354. int wlen = WideCharToMultiByte(CP_UTF8, 0,
  355. dest.bstrVal, SysStringLen(dest.bstrVal),
  356. NULL, 0, NULL, NULL);
  357. if (wlen > 65536 || wlen < 0)
  358. {
  359. AtlReportError(CLSID_Profile, PP_E_BDF_STRTOLG,
  360. IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
  361. return PP_E_BAD_DATA_FORMAT;
  362. }
  363. if (wlen >= 0)
  364. {
  365. m_updates[index] = new char[sizeof(u_short)+wlen+1];
  366. if (NULL == m_updates[index])
  367. return E_OUTOFMEMORY;
  368. WideCharToMultiByte(CP_UTF8, 0, dest.bstrVal, SysStringLen(dest.bstrVal),
  369. ((char*)m_updates[index])+sizeof(u_short), wlen,
  370. NULL, NULL);
  371. *(u_short*)m_updates[index] = htons((u_short)wlen);
  372. ((char*)m_updates[index])[wlen+sizeof(u_short)] = '\0';
  373. }
  374. else
  375. {
  376. AtlReportError(CLSID_Profile, PP_E_BDF_NONULL,
  377. IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
  378. return PP_E_BAD_DATA_FORMAT;
  379. }
  380. }
  381. break;
  382. case CProfileSchema::tChar:
  383. {
  384. int atsize = m_schema->GetByteSize(index);
  385. // Create array, convert to UTF-8, stuff it
  386. m_updates[index] = new char[atsize];
  387. if (NULL == m_updates[index])
  388. return E_OUTOFMEMORY;
  389. // Convert to UTF-8, stuff it
  390. if (VariantChangeType(&dest, &newVal, 0, VT_BSTR) != S_OK)
  391. {
  392. AtlReportError(CLSID_Profile, PP_E_BDF_TOSTRCVT,
  393. IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
  394. return PP_E_BAD_DATA_FORMAT;
  395. }
  396. int res = WideCharToMultiByte(CP_UTF8, 0, dest.bstrVal, SysStringLen(dest.bstrVal),
  397. (char*)m_updates[index], atsize, NULL, NULL);
  398. if (res == 0)
  399. {
  400. delete[] m_updates[index];
  401. m_updates[index] = NULL;
  402. AtlReportError(CLSID_Profile, PP_E_BDF_STRTOLG,
  403. IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
  404. return PP_E_BAD_DATA_FORMAT;
  405. }
  406. }
  407. break;
  408. case CProfileSchema::tByte:
  409. // Alloc single byte, put value
  410. if (VariantChangeType(&dest, &newVal, 0, VT_UI1) != S_OK)
  411. {
  412. AtlReportError(CLSID_Profile, PP_E_BDF_TOBYTECVT,
  413. IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
  414. return PP_E_BAD_DATA_FORMAT;
  415. }
  416. m_updates[index] = new BYTE[1];
  417. if (NULL == m_updates[index])
  418. return E_OUTOFMEMORY;
  419. *(unsigned char*)(m_updates[index]) = dest.bVal;
  420. break;
  421. case CProfileSchema::tWord:
  422. // Alloc single word, put value
  423. if (VariantChangeType(&dest, &newVal, 0, VT_I2) != S_OK)
  424. {
  425. AtlReportError(CLSID_Profile, PP_E_BDF_TOSHORTCVT,
  426. IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
  427. return PP_E_BAD_DATA_FORMAT;
  428. }
  429. m_updates[index] = new u_short[1];
  430. if (NULL == m_updates[index])
  431. return E_OUTOFMEMORY;
  432. *(u_short*)m_updates[index] = htons(dest.iVal);
  433. break;
  434. case CProfileSchema::tLong:
  435. // Alloc single long, put value
  436. if (VariantChangeType(&dest, &newVal, 0, VT_I4) != S_OK)
  437. {
  438. AtlReportError(CLSID_Profile, PP_E_BDF_TOINTCVT,
  439. IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
  440. return PP_E_BAD_DATA_FORMAT;
  441. }
  442. m_updates[index] = new u_long[1];
  443. if (NULL == m_updates[index])
  444. return E_OUTOFMEMORY;
  445. *(u_long*)m_updates[index] = htonl(dest.lVal);
  446. break;
  447. case CProfileSchema::tDate:
  448. if (VariantChangeType(&dest, &newVal, 0, VT_DATE) != S_OK)
  449. {
  450. AtlReportError(CLSID_Profile, PP_E_BDF_TOINTCVT,
  451. IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
  452. return PP_E_BAD_DATA_FORMAT;
  453. }
  454. m_updates[index] = new u_long[1];
  455. if (NULL == m_updates[index])
  456. return E_OUTOFMEMORY;
  457. *(u_long*)m_updates[index] = htonl((u_long)dest.date);
  458. break;
  459. default:
  460. AtlReportError(CLSID_Profile, PP_E_BDF_CANTSET,
  461. IID_IPassportProfile, PP_E_BAD_DATA_FORMAT);
  462. return PP_E_BAD_DATA_FORMAT;
  463. }
  464. //DarrenAn Bug 2157 If they just updated their email, clear the validation bit in flags.
  465. if(index == nEmailIndex)
  466. {
  467. u_long ulTmp;
  468. if (m_updates[nFlagsIndex] != NULL)
  469. {
  470. delete[] m_updates[nFlagsIndex];
  471. }
  472. m_updates[nFlagsIndex] = new u_long[1];
  473. memcpy((PBYTE)&ulTmp, ((LPSTR)m_raw)+m_pos[nFlagsIndex], sizeof(ulTmp));
  474. *(u_long*)m_updates[nFlagsIndex] = htonl(ntohl(ulTmp) & 0xFFFFFFFE);
  475. }
  476. return S_OK;
  477. }
  478. //===========================================================================
  479. //
  480. // get_IsValid
  481. //
  482. STDMETHODIMP CProfile::get_IsValid(VARIANT_BOOL *pVal)
  483. {
  484. *pVal = m_valid ? VARIANT_TRUE : VARIANT_FALSE;
  485. PassportLog("CProfile::get_IsValid: %X\r\n", *pVal);
  486. return S_OK;
  487. }
  488. //===========================================================================
  489. //
  490. // get_SchemaName
  491. //
  492. STDMETHODIMP CProfile::get_SchemaName(BSTR *pVal)
  493. {
  494. *pVal = ALLOC_AND_GIVEAWAY_BSTR(m_schemaName);
  495. if (NULL == *pVal)
  496. return E_OUTOFMEMORY;
  497. PassportLog("CProfile::get_SchemaName: %ws\r\n", *pVal);
  498. return S_OK;
  499. }
  500. //===========================================================================
  501. //
  502. // put_SchemaName
  503. //
  504. STDMETHODIMP CProfile::put_SchemaName(BSTR newVal)
  505. {
  506. // fix: 5247 Profile Object not reseting Schema name
  507. return E_NOTIMPL;
  508. }
  509. //===========================================================================
  510. //
  511. // get_unencryptedProfile
  512. //
  513. STDMETHODIMP CProfile::get_unencryptedProfile(BSTR *pVal)
  514. {
  515. PassportLog("CProfile::get_unencryptedProfile: Enter:\r\n");
  516. // Take updates into account
  517. if (!pVal)
  518. return E_INVALIDARG;
  519. *pVal = NULL;
  520. if (!m_valid)
  521. return S_OK;
  522. if (!m_schema)
  523. {
  524. AtlReportError(CLSID_Profile, PP_E_NOT_CONFIGUREDSTR,
  525. IID_IPassportProfile, PP_E_NOT_CONFIGURED);
  526. return PP_E_NOT_CONFIGURED;
  527. }
  528. int size = 0, len;
  529. short i = 0;
  530. u_short Tmp;
  531. u_long ulTmp;
  532. LPSTR inraw = (LPSTR)m_raw;
  533. m_versionAttributeIndex = m_schema->GetIndexByName(L"profileVersion");
  534. // Pack up each value, first find out how much space we need
  535. for (; i < m_schema->Count(); i++)
  536. {
  537. CProfileSchema::AttrType t = m_schema->GetType(i);
  538. void* valPtr = NULL;
  539. if(m_pos[i] != INVALID_POS) valPtr = inraw+m_pos[i];
  540. if (m_updates && m_updates[i])
  541. valPtr = m_updates[i];
  542. // neither exists, end of the loop
  543. if (valPtr == NULL)
  544. {
  545. break;
  546. }
  547. switch (t)
  548. {
  549. case CProfileSchema::tText:
  550. // How long is the string
  551. memcpy((PBYTE)&Tmp, valPtr, sizeof(Tmp));
  552. size += (sizeof(u_short) + ntohs(Tmp));
  553. break;
  554. case CProfileSchema::tChar:
  555. size += m_schema->GetByteSize(i);
  556. break;
  557. case CProfileSchema::tByte:
  558. size += 1;
  559. break;
  560. case CProfileSchema::tWord:
  561. size += sizeof(u_short);
  562. break;
  563. case CProfileSchema::tLong:
  564. case CProfileSchema::tDate:
  565. size += sizeof(u_long);
  566. break;
  567. // no default case needed, it never will be non-null
  568. }
  569. }
  570. // Ok, now build it up...
  571. *pVal = ALLOC_BSTR_BYTE_LEN(NULL, size);
  572. if (NULL == *pVal)
  573. return E_OUTOFMEMORY;
  574. LPSTR raw = (LPSTR) *pVal;
  575. size = 0;
  576. for (i = 0; i < m_schema->Count(); i++)
  577. {
  578. void* valPtr = NULL;
  579. if(m_pos[i] != INVALID_POS) valPtr = inraw+m_pos[i];
  580. if (m_updates && m_updates[i])
  581. valPtr = m_updates[i];
  582. // neither exists, end of the loop
  583. if (valPtr == NULL) break;
  584. CProfileSchema::AttrType t = m_schema->GetType(i);
  585. switch (t)
  586. {
  587. case CProfileSchema::tText:
  588. // How long is the string
  589. memcpy((PBYTE)&Tmp, valPtr, sizeof(Tmp));
  590. len = ntohs(Tmp);
  591. memcpy(raw+size, (char*) valPtr, len+sizeof(u_short));
  592. size += len + sizeof(u_short);
  593. break;
  594. case CProfileSchema::tChar:
  595. memcpy(raw+size, (char*) valPtr, m_schema->GetByteSize(i));
  596. size += m_schema->GetByteSize(i);
  597. break;
  598. case CProfileSchema::tByte:
  599. *(raw+size) = *(BYTE*)valPtr;
  600. size += 1;
  601. break;
  602. case CProfileSchema::tWord:
  603. memcpy(raw+size, valPtr, sizeof(u_short));
  604. size += sizeof(u_short);
  605. break;
  606. case CProfileSchema::tLong:
  607. case CProfileSchema::tDate:
  608. if (m_versionAttributeIndex == i && m_updates && m_updates[i])
  609. {
  610. memcpy((PBYTE)&ulTmp, valPtr, sizeof(ulTmp));
  611. ulTmp = htonl(ntohl(ulTmp)+1);
  612. memcpy(raw+size, (PBYTE)&ulTmp, sizeof(ulTmp));
  613. }
  614. else
  615. {
  616. memcpy(raw+size, valPtr, sizeof(u_long));
  617. }
  618. size += sizeof(u_long);
  619. break;
  620. }
  621. }
  622. GIVEAWAY_BSTR(*pVal);
  623. PassportLog("CProfile::get_unencryptedProfile: Exit: %ws\r\n", *pVal);
  624. return S_OK;
  625. }
  626. //===========================================================================
  627. //
  628. // put_unencryptedProfile
  629. //
  630. STDMETHODIMP CProfile::put_unencryptedProfile(BSTR newVal)
  631. {
  632. PassportLog("CProfile::put_unencryptedProfile: Enter:\r\n");
  633. if (!g_config->isValid())
  634. {
  635. AtlReportError(CLSID_Profile, PP_E_NOT_CONFIGUREDSTR,
  636. IID_IPassportProfile, PP_E_NOT_CONFIGURED);
  637. return PP_E_NOT_CONFIGURED;
  638. }
  639. //
  640. // Clean up all state associated with the previous profile.
  641. //
  642. if (m_raw)
  643. {
  644. FREE_BSTR(m_raw);
  645. m_raw = NULL;
  646. }
  647. if (m_pos)
  648. {
  649. delete [] m_pos;
  650. m_pos = NULL;
  651. }
  652. if (m_bitPos)
  653. {
  654. delete [] m_bitPos;
  655. m_bitPos = NULL;
  656. }
  657. if (m_updates)
  658. {
  659. for (int i = 0; i < m_schema->Count(); i++)
  660. {
  661. if (m_updates[i])
  662. delete[] m_updates[i];
  663. }
  664. delete[] m_updates;
  665. m_updates = NULL;
  666. }
  667. if (!newVal)
  668. {
  669. m_valid = FALSE;
  670. return S_OK;
  671. }
  672. // BOY do you have to be careful here. If you don't
  673. // call BYTE version, it truncates at first pair of NULLs
  674. // we also need to expand beyond the key version byte
  675. DWORD dwByteLen = SysStringByteLen(newVal);
  676. if (dwByteLen > 2 && newVal[0] == SECURE_FLAG)
  677. {
  678. m_secure = TRUE;
  679. dwByteLen -= 2;
  680. m_raw = ALLOC_BSTR_BYTE_LEN((LPSTR)newVal + 2,
  681. dwByteLen);
  682. }
  683. else
  684. {
  685. m_secure = FALSE;
  686. m_raw = ALLOC_BSTR_BYTE_LEN((LPSTR)newVal,
  687. dwByteLen);
  688. }
  689. if (NULL == m_raw)
  690. {
  691. m_valid = FALSE;
  692. return E_OUTOFMEMORY;
  693. }
  694. PPTracePrintBlob(PPTRACE_RAW, "Profile:", (LPBYTE)newVal, dwByteLen, TRUE);
  695. parse(m_raw, dwByteLen);
  696. PassportLog("CProfile::get_unencryptedProfile: Exit:\r\n");
  697. return S_OK;
  698. }
  699. //===========================================================================
  700. //
  701. // parse
  702. //
  703. void CProfile::parse(
  704. LPCOLESTR raw,
  705. DWORD dwByteLen
  706. )
  707. {
  708. // How many attributes?
  709. DWORD cAtts = 0;
  710. CNexusConfig* cnc = g_config->checkoutNexusConfig();
  711. if (NULL == cnc)
  712. {
  713. m_valid = FALSE;
  714. goto Cleanup;
  715. }
  716. m_schema = cnc->getProfileSchema(m_schemaName);
  717. if (m_schema)
  718. {
  719. m_schema->AddRef();
  720. }
  721. cnc->Release();
  722. if (!m_schema)
  723. {
  724. m_valid = FALSE;
  725. goto Cleanup;
  726. }
  727. cAtts = m_schema->Count();
  728. // Set up the arrays
  729. m_pos = new UINT[cAtts];
  730. m_bitPos = new UINT[cAtts];
  731. if (m_pos && m_bitPos &&
  732. SUCCEEDED(m_schema->parseProfile((LPSTR)raw, dwByteLen, m_pos, m_bitPos, &cAtts)))
  733. m_valid = TRUE;
  734. else
  735. m_valid = FALSE;
  736. Cleanup:
  737. if (m_valid == FALSE)
  738. {
  739. if(g_pAlert)
  740. g_pAlert->report(PassportAlertInterface::WARNING_TYPE, PM_INVALID_PROFILE,
  741. 0,NULL, dwByteLen, (LPVOID)raw);
  742. }
  743. }
  744. //===========================================================================
  745. //
  746. // get_updateString
  747. //
  748. STDMETHODIMP CProfile::get_updateString(BSTR *pVal)
  749. {
  750. if (!pVal)
  751. return E_INVALIDARG;
  752. *pVal = NULL;
  753. if (!m_valid) return S_OK;
  754. if (!m_schema)
  755. {
  756. AtlReportError(CLSID_Profile, PP_E_NOT_CONFIGUREDSTR,
  757. IID_IPassportProfile, PP_E_NOT_CONFIGURED);
  758. return PP_E_NOT_CONFIGURED;
  759. }
  760. if (!m_updates)
  761. return S_OK;
  762. int size = sizeof(u_long)*2, len;
  763. short i = 0;
  764. u_short Tmp;
  765. // Pack up each value, first find out how much space we need
  766. for (; i < m_schema->Count(); i++)
  767. {
  768. if (m_updates[i])
  769. {
  770. size += sizeof(u_short); // For the index
  771. CProfileSchema::AttrType t = m_schema->GetType(i);
  772. switch (t)
  773. {
  774. case CProfileSchema::tText:
  775. // How long is the string
  776. memcpy((PBYTE)&Tmp, m_updates[i], sizeof(Tmp));
  777. size += (sizeof(u_short) + ntohs(Tmp));
  778. break;
  779. case CProfileSchema::tChar:
  780. size += m_schema->GetByteSize(i);
  781. break;
  782. case CProfileSchema::tByte:
  783. size += 1;
  784. break;
  785. case CProfileSchema::tWord:
  786. size += sizeof(u_short);
  787. break;
  788. case CProfileSchema::tLong:
  789. case CProfileSchema::tDate:
  790. size += sizeof(u_long);
  791. break;
  792. // no default case needed, it never will be non-null
  793. }
  794. }
  795. }
  796. // Ok, now build it up...
  797. *pVal = ALLOC_BSTR_BYTE_LEN(NULL, size);
  798. if (NULL == *pVal)
  799. return E_OUTOFMEMORY;
  800. LPSTR raw = (LPSTR) *pVal;
  801. _bstr_t ml("memberIdLow"), mh("memberIdHigh");
  802. int iMl, iMh;
  803. iMl = m_schema->GetIndexByName(ml);
  804. iMh = m_schema->GetIndexByName(mh);
  805. if (iMl == -1 || iMh == -1)
  806. {
  807. AtlReportError(CLSID_Profile, PP_E_NO_SUCH_ATTRIBUTESTR,
  808. IID_IPassportProfile, PP_E_NO_SUCH_ATTRIBUTE);
  809. return PP_E_NO_SUCH_ATTRIBUTE;
  810. }
  811. if (m_schema->GetType(iMl) != CProfileSchema::tLong ||
  812. m_schema->GetType(iMh) != CProfileSchema::tLong)
  813. {
  814. AtlReportError(CLSID_Profile, PP_E_NSA_BADMID,
  815. IID_IPassportProfile, PP_E_NO_SUCH_ATTRIBUTE);
  816. return PP_E_NO_SUCH_ATTRIBUTE;
  817. }
  818. memcpy(raw, m_raw+m_pos[iMl], sizeof(int));
  819. memcpy(raw+sizeof(u_long), m_raw+m_pos[iMh], sizeof(int));
  820. size = 2*sizeof(u_long);
  821. for (i = 0; i < m_schema->Count(); i++)
  822. {
  823. if (m_updates[i])
  824. {
  825. Tmp = htons(i);
  826. memcpy(raw+size, (PBYTE)&Tmp, sizeof(Tmp));
  827. size+=sizeof(u_short);
  828. CProfileSchema::AttrType t = m_schema->GetType(i);
  829. switch (t)
  830. {
  831. case CProfileSchema::tText:
  832. // How long is the string
  833. memcpy((PBYTE)&Tmp, m_updates[i], sizeof(Tmp));
  834. len = ntohs(Tmp);
  835. memcpy(raw+size, (char*) m_updates[i], len+sizeof(u_short));
  836. size += len + sizeof(u_short);
  837. break;
  838. case CProfileSchema::tChar:
  839. memcpy(raw+size, (char*) m_updates[i], m_schema->GetByteSize(i));
  840. size += m_schema->GetByteSize(i);
  841. break;
  842. case CProfileSchema::tByte:
  843. *(raw+size) = *(BYTE*)m_updates[i];
  844. size += 1;
  845. break;
  846. case CProfileSchema::tWord:
  847. memcpy(raw+size, (char*) m_updates[i], sizeof(u_short));
  848. size += sizeof(u_short);
  849. break;
  850. case CProfileSchema::tLong:
  851. case CProfileSchema::tDate:
  852. memcpy(raw+size, (char*) m_updates[i], sizeof(u_long));
  853. size += sizeof(u_long);
  854. break;
  855. // no default case needed, it never will be non-null
  856. }
  857. }
  858. }
  859. GIVEAWAY_BSTR(*pVal);
  860. return S_OK;
  861. }
  862. //===========================================================================
  863. //
  864. // incrementVersion
  865. //
  866. HRESULT CProfile::incrementVersion()
  867. {
  868. int size = 0, len, i;
  869. LPSTR raw = (LPSTR)m_raw;
  870. u_short Tmp;
  871. u_long ulTmp;
  872. if (!m_valid) return S_OK;
  873. if (!m_schema)
  874. {
  875. AtlReportError(CLSID_Profile, PP_E_NOT_CONFIGUREDSTR,
  876. IID_IPassportProfile, PP_E_NOT_CONFIGURED);
  877. return PP_E_NOT_CONFIGURED;
  878. }
  879. m_versionAttributeIndex = m_schema->GetIndexByName(L"profileVersion");
  880. for(i = 0; i < m_versionAttributeIndex; i++)
  881. {
  882. CProfileSchema::AttrType t = m_schema->GetType(i);
  883. switch (t)
  884. {
  885. case CProfileSchema::tText:
  886. // How long is the string
  887. memcpy((PBYTE)&Tmp, m_raw+size, sizeof(Tmp));
  888. len = ntohs(Tmp);
  889. size += len + sizeof(u_short);
  890. break;
  891. case CProfileSchema::tChar:
  892. size += m_schema->GetByteSize(i);
  893. break;
  894. case CProfileSchema::tByte:
  895. size += 1;
  896. break;
  897. case CProfileSchema::tWord:
  898. size += sizeof(u_short);
  899. break;
  900. case CProfileSchema::tLong:
  901. case CProfileSchema::tDate:
  902. size += sizeof(u_long);
  903. break;
  904. // no default case needed, it never will be non-null
  905. }
  906. }
  907. memcpy((PBYTE)&ulTmp, m_raw+size, sizeof(ulTmp));
  908. ulTmp = htonl(ntohl(ulTmp) + 1);
  909. memcpy(raw+size, (PBYTE)&ulTmp, sizeof(ulTmp));
  910. return S_OK;
  911. }
  912. //===========================================================================
  913. //
  914. // get_IsSecure
  915. //
  916. HRESULT CProfile::get_IsSecure(VARIANT_BOOL *pbIsSecure)
  917. {
  918. HRESULT hr;
  919. if(pbIsSecure == NULL)
  920. {
  921. hr = E_POINTER;
  922. goto Cleanup;
  923. }
  924. *pbIsSecure = (m_secure ? VARIANT_TRUE : VARIANT_FALSE);
  925. hr = S_OK;
  926. Cleanup:
  927. return hr;
  928. }
  929. //===========================================================================
  930. //
  931. // IsSecure
  932. //
  933. BOOL CProfile::IsSecure()
  934. {
  935. return m_secure;
  936. }