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.

683 lines
15 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: attribute.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "pch.h"
  11. #include <SnapBase.h>
  12. #include "common.h"
  13. #include "attredit.h"
  14. #include "attribute.h"
  15. #ifdef DEBUG_ALLOCATOR
  16. #ifdef _DEBUG
  17. #define new DEBUG_NEW
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. #endif
  22. ///////////////////////////////////////////////////////////////////////////
  23. // CADSIAttr
  24. CADSIAttr::CADSIAttr(ADS_ATTR_INFO* pInfo, BOOL bMulti, PCWSTR pszSyntax, BOOL bReadOnly)
  25. {
  26. m_pAttrInfo = pInfo;
  27. m_bDirty = FALSE;
  28. m_bMulti = bMulti;
  29. m_bReadOnly = bReadOnly;
  30. m_szSyntax = pszSyntax;
  31. PWSTR pwz = wcsrchr(pInfo->pszAttrName, L';');
  32. if (pwz)
  33. {
  34. pwz; // move past the hyphen to the range end value.
  35. ASSERT(*pwz);
  36. *pwz=L'\0';
  37. }
  38. }
  39. CADSIAttr::CADSIAttr(LPCWSTR lpszAttr)
  40. {
  41. m_pAttrInfo = new ADS_ATTR_INFO;
  42. memset(m_pAttrInfo, 0, sizeof(ADS_ATTR_INFO));
  43. PWSTR pwz = wcsrchr(lpszAttr, L';');
  44. if (pwz)
  45. {
  46. pwz; // move past the hyphen to the range end value.
  47. ASSERT(*pwz);
  48. *pwz=L'\0';
  49. }
  50. _AllocString(lpszAttr, &(m_pAttrInfo->pszAttrName));
  51. m_bMulti = FALSE;
  52. m_bDirty = FALSE;
  53. m_bReadOnly = FALSE;
  54. }
  55. CADSIAttr::CADSIAttr(CADSIAttr* pOldAttr)
  56. {
  57. m_pAttrInfo = NULL;
  58. ADS_ATTR_INFO* pAttrInfo = pOldAttr->GetAttrInfo();
  59. // These copies are done separately because there are places
  60. // that I need to copy only the ADsAttrInfo and not the values
  61. //
  62. _CopyADsAttrInfo(pAttrInfo, &m_pAttrInfo);
  63. _CopyADsValues(pAttrInfo, m_pAttrInfo );
  64. m_bReadOnly = FALSE;
  65. m_bMulti = pOldAttr->m_bMulti;
  66. m_bDirty = pOldAttr->m_bDirty;
  67. }
  68. CADSIAttr::~CADSIAttr()
  69. {
  70. _FreeADsAttrInfo(&m_pAttrInfo, m_bReadOnly);
  71. }
  72. ADSVALUE* CADSIAttr::GetADSVALUE(int idx)
  73. {
  74. return &(m_pAttrInfo->pADsValues[idx]);
  75. }
  76. HRESULT CADSIAttr::SetValues(const CStringList& sValues)
  77. {
  78. HRESULT hr;
  79. ADS_ATTR_INFO* pNewAttrInfo = NULL;
  80. if (!_CopyADsAttrInfo(m_pAttrInfo, &pNewAttrInfo))
  81. {
  82. return E_FAIL;
  83. }
  84. int iCount = sValues.GetCount();
  85. pNewAttrInfo->dwNumValues = iCount;
  86. if (!_AllocValues(&pNewAttrInfo->pADsValues, iCount))
  87. {
  88. return E_FAIL;
  89. }
  90. int idx = 0;
  91. POSITION pos = sValues.GetHeadPosition();
  92. while (pos != NULL)
  93. {
  94. CString s = sValues.GetNext(pos);
  95. ADSVALUE* pADsValue = &(pNewAttrInfo->pADsValues[idx]);
  96. ASSERT(pADsValue != NULL);
  97. hr = _SetADsFromString(
  98. s,
  99. pNewAttrInfo->dwADsType,
  100. pADsValue
  101. );
  102. if (FAILED(hr))
  103. {
  104. _FreeADsAttrInfo(&pNewAttrInfo, FALSE);
  105. return hr;
  106. }
  107. idx++;
  108. }
  109. // Free the old one and swap in the new one
  110. //
  111. _FreeADsAttrInfo(&m_pAttrInfo, m_bReadOnly);
  112. m_pAttrInfo = pNewAttrInfo;
  113. m_bReadOnly = FALSE;
  114. return hr;
  115. }
  116. void CADSIAttr::GetValues(CStringList& sValues, DWORD dwMaxCharCount)
  117. {
  118. GetStringFromADs(m_pAttrInfo, sValues, dwMaxCharCount);
  119. }
  120. ADS_ATTR_INFO* CADSIAttr::GetAttrInfo()
  121. {
  122. return m_pAttrInfo;
  123. }
  124. ////////////////////////////////////////////////////////////////////////
  125. // Public Helper Functions
  126. ///////////////////////////////////////////////////////////////////////
  127. HRESULT CADSIAttr::SetValuesInDS(CAttrList* ptouchedAttr, IDirectoryObject* pDirObject)
  128. {
  129. DWORD dwReturn;
  130. DWORD dwAttrCount = 0;
  131. ADS_ATTR_INFO* pAttrInfo;
  132. pAttrInfo = new ADS_ATTR_INFO[ptouchedAttr->GetCount()];
  133. CADSIAttr* pCurrentAttr;
  134. POSITION pos = ptouchedAttr->GetHeadPosition();
  135. while(pos != NULL)
  136. {
  137. ptouchedAttr->GetNextDirty(pos, &pCurrentAttr);
  138. if (pCurrentAttr != NULL)
  139. {
  140. ADS_ATTR_INFO* pCurrentAttrInfo = pCurrentAttr->GetAttrInfo();
  141. ADS_ATTR_INFO* pNewAttrInfo = &pAttrInfo[dwAttrCount];
  142. if (!_CopyADsAttrInfo(pCurrentAttrInfo, pNewAttrInfo))
  143. {
  144. for (int itr = 0; itr < dwAttrCount; itr++)
  145. {
  146. _FreeADsAttrInfo(&pAttrInfo[itr]);
  147. }
  148. delete[] pAttrInfo;
  149. return E_FAIL;
  150. }
  151. if (!_CopyADsValues(pCurrentAttrInfo, pNewAttrInfo))
  152. {
  153. delete[] pAttrInfo;
  154. return E_FAIL;
  155. }
  156. if (pAttrInfo[dwAttrCount].dwNumValues == 0)
  157. {
  158. pAttrInfo[dwAttrCount].dwControlCode = ADS_ATTR_CLEAR;
  159. }
  160. else
  161. {
  162. pAttrInfo[dwAttrCount].dwControlCode = ADS_ATTR_UPDATE;
  163. }
  164. dwAttrCount++;
  165. }
  166. }
  167. // Commit the changes that have been made to the ADSI cache
  168. //
  169. HRESULT hr = pDirObject->SetObjectAttributes(pAttrInfo, dwAttrCount, &dwReturn);
  170. for (int itr = 0; itr < dwAttrCount; itr++)
  171. {
  172. _FreeADsAttrInfo(&pAttrInfo[itr]);
  173. }
  174. delete[] pAttrInfo;
  175. return hr;
  176. }
  177. /////////////////////////////////////////////////////////////////////////
  178. // Private Helper Functions
  179. ////////////////////////////////////////////////////////////////////////
  180. HRESULT CADSIAttr::_SetADsFromString(LPCWSTR lpszValue, ADSTYPE adsType, ADSVALUE* pADsValue)
  181. {
  182. HRESULT hr = E_FAIL;
  183. if ( adsType == ADSTYPE_INVALID )
  184. {
  185. return hr;
  186. }
  187. pADsValue->dwType = adsType;
  188. switch( adsType )
  189. {
  190. case ADSTYPE_DN_STRING :
  191. if (!_AllocString(lpszValue, &pADsValue->DNString))
  192. {
  193. return E_FAIL;
  194. }
  195. hr = S_OK;
  196. break;
  197. case ADSTYPE_CASE_EXACT_STRING :
  198. if (!_AllocString(lpszValue, &pADsValue->CaseExactString))
  199. {
  200. return E_FAIL;
  201. }
  202. hr = S_OK;
  203. break;
  204. case ADSTYPE_CASE_IGNORE_STRING :
  205. if (!_AllocString(lpszValue, &pADsValue->CaseIgnoreString))
  206. {
  207. return E_FAIL;
  208. }
  209. hr = S_OK;
  210. break;
  211. case ADSTYPE_PRINTABLE_STRING :
  212. if (!_AllocString(lpszValue, &pADsValue->PrintableString))
  213. {
  214. return E_FAIL;
  215. }
  216. hr = S_OK;
  217. break;
  218. case ADSTYPE_NUMERIC_STRING :
  219. if (!_AllocString(lpszValue, &pADsValue->NumericString))
  220. {
  221. return E_FAIL;
  222. }
  223. hr = S_OK;
  224. break;
  225. case ADSTYPE_OBJECT_CLASS :
  226. if (!_AllocString(lpszValue, &pADsValue->ClassName))
  227. {
  228. return E_FAIL;
  229. }
  230. hr = S_OK;
  231. break;
  232. case ADSTYPE_BOOLEAN :
  233. if (_wcsnicmp(lpszValue, L"TRUE", 4) == 0)
  234. {
  235. (DWORD)pADsValue->Boolean = TRUE;
  236. }
  237. else if (_wcsnicmp(lpszValue, L"FALSE", 5) == 0)
  238. {
  239. (DWORD)pADsValue->Boolean = FALSE;
  240. }
  241. else
  242. {
  243. return E_FAIL;
  244. }
  245. hr = S_OK;
  246. break;
  247. case ADSTYPE_INTEGER :
  248. int value;
  249. value = swscanf(lpszValue, L"%ld", &pADsValue->Integer);
  250. if (value > 0)
  251. {
  252. hr = S_OK;
  253. }
  254. else
  255. {
  256. hr = E_FAIL;
  257. }
  258. break;
  259. case ADSTYPE_OCTET_STRING :
  260. {
  261. pADsValue->OctetString.lpValue = new BYTE[256];
  262. int iCount = 0, index = 0, iResult = 0;
  263. do
  264. {
  265. while (lpszValue[index] == ' ' || lpszValue[index] == '/t')
  266. {
  267. index++;
  268. }
  269. iResult = swscanf(&lpszValue[index], L"0x%2x", &pADsValue->OctetString.lpValue[iCount++]);
  270. if (iResult == 0 && lpszValue[index] == '\0')
  271. {
  272. hr = S_OK;
  273. break;
  274. }
  275. index += 4; // NOTE : OctetStrings must be in the form 0x00, ie 4 characters
  276. } while (iResult != 0);
  277. iCount--; // the last one had to fail
  278. pADsValue->OctetString.dwLength = iCount;
  279. }
  280. break;
  281. case ADSTYPE_LARGE_INTEGER :
  282. wtoli(lpszValue, pADsValue->LargeInteger);
  283. hr = S_OK;
  284. break;
  285. case ADSTYPE_UTC_TIME :
  286. int iNum;
  287. WORD n;
  288. iNum = swscanf(lpszValue, L"%02d/%02d/%04d %02d:%02d:%02d",
  289. &n,
  290. &pADsValue->UTCTime.wDay,
  291. &pADsValue->UTCTime.wYear,
  292. &pADsValue->UTCTime.wHour,
  293. &pADsValue->UTCTime.wMinute,
  294. &pADsValue->UTCTime.wSecond
  295. );
  296. pADsValue->UTCTime.wMonth = n;
  297. // This strange conversion is done so that the DayOfWeek will be set in
  298. // the UTCTime. By converting it to a filetime it ignores the dayofweek but
  299. // converting back fills it in.
  300. //
  301. FILETIME ft;
  302. SystemTimeToFileTime(&pADsValue->UTCTime, &ft);
  303. FileTimeToSystemTime(&ft, &pADsValue->UTCTime);
  304. if (iNum == 6)
  305. {
  306. hr = S_OK;
  307. }
  308. else
  309. {
  310. hr = E_FAIL;
  311. }
  312. break;
  313. default :
  314. break;
  315. }
  316. return hr;
  317. }
  318. BOOL CADSIAttr::_AllocOctetString(ADS_OCTET_STRING& rOldOctetString,
  319. ADS_OCTET_STRING& rNew)
  320. {
  321. _FreeOctetString(rNew.lpValue);
  322. int iLength = rOldOctetString.dwLength;
  323. rNew.dwLength = iLength;
  324. rNew.lpValue = new BYTE[iLength];
  325. if (rNew.lpValue == NULL)
  326. {
  327. _FreeOctetString(rNew.lpValue);
  328. return FALSE;
  329. }
  330. memcpy(rNew.lpValue, rOldOctetString.lpValue, iLength);
  331. return TRUE;
  332. }
  333. void CADSIAttr::_FreeOctetString(BYTE* lpValue)
  334. {
  335. if (lpValue != NULL)
  336. {
  337. delete lpValue;
  338. lpValue = NULL;
  339. }
  340. }
  341. BOOL CADSIAttr::_AllocString(LPCWSTR lpsz, LPWSTR* lppszNew)
  342. {
  343. _FreeString(lppszNew);
  344. int iLength = wcslen(lpsz);
  345. *lppszNew = new WCHAR[iLength + 1]; // an extra for the NULL
  346. if (*lppszNew == NULL)
  347. {
  348. _FreeString(lppszNew);
  349. return FALSE;
  350. }
  351. wcscpy(*lppszNew, lpsz);
  352. return TRUE;
  353. }
  354. void CADSIAttr::_FreeString(LPWSTR* lppsz)
  355. {
  356. if (*lppsz != NULL)
  357. {
  358. delete *lppsz;
  359. }
  360. *lppsz = NULL;
  361. }
  362. BOOL CADSIAttr::_AllocValues(ADSVALUE** ppValues, DWORD dwLength)
  363. {
  364. _FreeADsValues(ppValues, dwLength);
  365. *ppValues = new ADSVALUE[dwLength];
  366. if (*ppValues == NULL)
  367. {
  368. _FreeADsValues(ppValues, dwLength);
  369. return FALSE;
  370. }
  371. memset(*ppValues, 0, sizeof(ADSVALUE) * dwLength);
  372. return TRUE;
  373. }
  374. BOOL CADSIAttr::_CopyADsValues(ADS_ATTR_INFO* pOldAttrInfo, ADS_ATTR_INFO* pNewAttrInfo)
  375. {
  376. _FreeADsValues(&pNewAttrInfo->pADsValues, pNewAttrInfo->dwNumValues);
  377. pNewAttrInfo->dwNumValues = pOldAttrInfo->dwNumValues;
  378. if (!_AllocValues(&pNewAttrInfo->pADsValues, pOldAttrInfo->dwNumValues))
  379. {
  380. _FreeADsValues(&pNewAttrInfo->pADsValues, pNewAttrInfo->dwNumValues);
  381. return FALSE;
  382. }
  383. for (int itr = 0; itr < pOldAttrInfo->dwNumValues; itr++)
  384. {
  385. pNewAttrInfo->pADsValues[itr].dwType = pOldAttrInfo->pADsValues[itr].dwType;
  386. switch( pNewAttrInfo->pADsValues[itr].dwType )
  387. {
  388. case ADSTYPE_DN_STRING :
  389. if (!_AllocString(pOldAttrInfo->pADsValues[itr].DNString,
  390. &pNewAttrInfo->pADsValues[itr].DNString))
  391. {
  392. _FreeADsValues(&pNewAttrInfo->pADsValues, pNewAttrInfo->dwNumValues);
  393. return FALSE;
  394. }
  395. break;
  396. case ADSTYPE_CASE_EXACT_STRING :
  397. if (!_AllocString(pOldAttrInfo->pADsValues[itr].CaseExactString,
  398. &pNewAttrInfo->pADsValues[itr].CaseExactString))
  399. {
  400. _FreeADsValues(&pNewAttrInfo->pADsValues, pNewAttrInfo->dwNumValues);
  401. return FALSE;
  402. }
  403. break;
  404. case ADSTYPE_CASE_IGNORE_STRING :
  405. if (!_AllocString(pOldAttrInfo->pADsValues[itr].CaseIgnoreString,
  406. &pNewAttrInfo->pADsValues[itr].CaseIgnoreString))
  407. {
  408. _FreeADsValues(&pNewAttrInfo->pADsValues, pNewAttrInfo->dwNumValues);
  409. return FALSE;
  410. }
  411. break;
  412. case ADSTYPE_PRINTABLE_STRING :
  413. if (!_AllocString(pOldAttrInfo->pADsValues[itr].PrintableString,
  414. &pNewAttrInfo->pADsValues[itr].PrintableString))
  415. {
  416. _FreeADsValues(&pNewAttrInfo->pADsValues, pNewAttrInfo->dwNumValues);
  417. return FALSE;
  418. }
  419. break;
  420. case ADSTYPE_NUMERIC_STRING :
  421. if (!_AllocString(pOldAttrInfo->pADsValues[itr].NumericString,
  422. &pNewAttrInfo->pADsValues[itr].NumericString))
  423. {
  424. _FreeADsValues(&pNewAttrInfo->pADsValues, pNewAttrInfo->dwNumValues);
  425. return FALSE;
  426. }
  427. break;
  428. case ADSTYPE_OBJECT_CLASS :
  429. if (!_AllocString(pOldAttrInfo->pADsValues[itr].ClassName,
  430. &pNewAttrInfo->pADsValues[itr].ClassName))
  431. {
  432. _FreeADsValues(&pNewAttrInfo->pADsValues, pNewAttrInfo->dwNumValues);
  433. return FALSE;
  434. }
  435. break;
  436. case ADSTYPE_BOOLEAN :
  437. pNewAttrInfo->pADsValues[itr].Boolean = pOldAttrInfo->pADsValues[itr].Boolean;
  438. break;
  439. case ADSTYPE_INTEGER :
  440. pNewAttrInfo->pADsValues[itr].Integer = pOldAttrInfo->pADsValues[itr].Integer;
  441. break;
  442. case ADSTYPE_OCTET_STRING :
  443. if (!_AllocOctetString(pOldAttrInfo->pADsValues[itr].OctetString,
  444. pNewAttrInfo->pADsValues[itr].OctetString))
  445. {
  446. _FreeADsValues(&pNewAttrInfo->pADsValues, pNewAttrInfo->dwNumValues);
  447. return FALSE;
  448. }
  449. break;
  450. case ADSTYPE_LARGE_INTEGER :
  451. pNewAttrInfo->pADsValues[itr].LargeInteger = pOldAttrInfo->pADsValues[itr].LargeInteger;
  452. break;
  453. case ADSTYPE_UTC_TIME :
  454. pNewAttrInfo->pADsValues[itr].UTCTime = pOldAttrInfo->pADsValues[itr].UTCTime;
  455. break;
  456. default :
  457. break;
  458. }
  459. }
  460. return TRUE;
  461. }
  462. void CADSIAttr::_FreeADsValues(ADSVALUE** ppADsValues, DWORD dwLength)
  463. {
  464. ADSVALUE* pADsValue = *ppADsValues;
  465. for (int idx = 0; idx < dwLength; idx++)
  466. {
  467. if (pADsValue != NULL)
  468. {
  469. switch( pADsValue->dwType )
  470. {
  471. case ADSTYPE_DN_STRING :
  472. _FreeString(&pADsValue->DNString);
  473. break;
  474. case ADSTYPE_CASE_EXACT_STRING :
  475. _FreeString(&pADsValue->CaseExactString);
  476. break;
  477. case ADSTYPE_CASE_IGNORE_STRING :
  478. _FreeString(&pADsValue->CaseIgnoreString);
  479. break;
  480. case ADSTYPE_PRINTABLE_STRING :
  481. _FreeString(&pADsValue->PrintableString);
  482. break;
  483. case ADSTYPE_NUMERIC_STRING :
  484. _FreeString(&pADsValue->NumericString);
  485. break;
  486. case ADSTYPE_OBJECT_CLASS :
  487. _FreeString(&pADsValue->ClassName);
  488. break;
  489. case ADSTYPE_OCTET_STRING :
  490. _FreeOctetString(pADsValue->OctetString.lpValue);
  491. break;
  492. default :
  493. break;
  494. }
  495. pADsValue++;
  496. }
  497. }
  498. // May be NULL if there are no values set
  499. // WARNING! : make sure that you memset the memory after
  500. // creating an ADS_ATTR_INFO so that it will be NULL if there
  501. // are no values
  502. //
  503. if (*ppADsValues != NULL)
  504. {
  505. delete *ppADsValues;
  506. *ppADsValues = NULL;
  507. }
  508. }
  509. // The values are not copied here. They must be copied after the ADS_ATTR_INFO
  510. // is copied by using _CopyADsValues()
  511. //
  512. BOOL CADSIAttr::_CopyADsAttrInfo(ADS_ATTR_INFO* pAttrInfo, ADS_ATTR_INFO** ppNewAttrInfo)
  513. {
  514. _FreeADsAttrInfo(ppNewAttrInfo, FALSE);
  515. *ppNewAttrInfo = new ADS_ATTR_INFO;
  516. if (*ppNewAttrInfo == NULL)
  517. {
  518. return FALSE;
  519. }
  520. memset(*ppNewAttrInfo, 0, sizeof(ADS_ATTR_INFO));
  521. BOOL bReturn = _AllocString(pAttrInfo->pszAttrName, &((*ppNewAttrInfo)->pszAttrName));
  522. if (!bReturn)
  523. {
  524. _FreeADsAttrInfo(ppNewAttrInfo, FALSE);
  525. return FALSE;
  526. }
  527. (*ppNewAttrInfo)->dwADsType = pAttrInfo->dwADsType;
  528. (*ppNewAttrInfo)->dwControlCode = pAttrInfo->dwControlCode;
  529. (*ppNewAttrInfo)->dwNumValues = pAttrInfo->dwNumValues;
  530. return TRUE;
  531. }
  532. BOOL CADSIAttr::_CopyADsAttrInfo(ADS_ATTR_INFO* pAttrInfo, ADS_ATTR_INFO* pNewAttrInfo)
  533. {
  534. memset(pNewAttrInfo, 0, sizeof(ADS_ATTR_INFO));
  535. BOOL bReturn = _AllocString(pAttrInfo->pszAttrName, &pNewAttrInfo->pszAttrName);
  536. if (!bReturn)
  537. {
  538. return FALSE;
  539. }
  540. pNewAttrInfo->dwADsType = pAttrInfo->dwADsType;
  541. pNewAttrInfo->dwControlCode = pAttrInfo->dwControlCode;
  542. pNewAttrInfo->dwNumValues = pAttrInfo->dwNumValues;
  543. return TRUE;
  544. }
  545. void CADSIAttr::_FreeADsAttrInfo(ADS_ATTR_INFO** ppAttrInfo, BOOL bReadOnly)
  546. {
  547. if (*ppAttrInfo == NULL)
  548. {
  549. return;
  550. }
  551. if (!bReadOnly)
  552. {
  553. _FreeString(&(*ppAttrInfo)->pszAttrName);
  554. _FreeADsValues(&(*ppAttrInfo)->pADsValues, (*ppAttrInfo)->dwNumValues);
  555. delete *ppAttrInfo;
  556. }
  557. else
  558. {
  559. FreeADsMem(*ppAttrInfo);
  560. }
  561. *ppAttrInfo = NULL;
  562. }
  563. void CADSIAttr::_FreeADsAttrInfo(ADS_ATTR_INFO* pAttrInfo)
  564. {
  565. if (pAttrInfo == NULL)
  566. {
  567. return;
  568. }
  569. _FreeString(&pAttrInfo->pszAttrName);
  570. _FreeADsValues(&pAttrInfo->pADsValues, pAttrInfo->dwNumValues);
  571. }