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.

3123 lines
77 KiB

  1. #include "pch.h"
  2. #include <SnapBase.h>
  3. #include "resource.h"
  4. #include "query.h"
  5. #include "attrres.h"
  6. #include "editui.h"
  7. #include "common.h"
  8. #include "attrqry.h"
  9. #include "editorui.h"
  10. ///////////////////////////////////////////////////////////////////////////////////////
  11. // CValueEditDialog
  12. BEGIN_MESSAGE_MAP(CValueEditDialog, CDialog)
  13. END_MESSAGE_MAP()
  14. HRESULT CValueEditDialog::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo)
  15. {
  16. HRESULT hr = S_OK;
  17. m_pOldADsValue = pAttributeEditorInfo->pADsValue;
  18. m_dwOldNumValues = pAttributeEditorInfo->dwNumValues;
  19. m_szClass = pAttributeEditorInfo->lpszClass;
  20. m_szAttribute = pAttributeEditorInfo->lpszAttribute;
  21. m_bMultivalued = pAttributeEditorInfo->bMultivalued;
  22. m_pfnBindingFunction = pAttributeEditorInfo->lpfnBind;
  23. m_lParam = pAttributeEditorInfo->lParam;
  24. return hr;
  25. }
  26. HRESULT CValueEditDialog::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues)
  27. {
  28. HRESULT hr = S_OK;
  29. if (ppADsValue == NULL ||
  30. pdwNumValues == NULL)
  31. {
  32. return E_OUTOFMEMORY;
  33. }
  34. *ppADsValue = NULL;
  35. *pdwNumValues = 0;
  36. return hr;
  37. }
  38. ///////////////////////////////////////////////////////////////////////////////////////
  39. // CSingleStringEditor
  40. CValueEditDialog* CreateSingleStringEditor(PCWSTR pszClass,
  41. PCWSTR pszAttribute,
  42. ADSTYPE adsType,
  43. BOOL bMultivalued)
  44. {
  45. return new CSingleStringEditor;
  46. }
  47. BEGIN_MESSAGE_MAP(CSingleStringEditor, CValueEditDialog)
  48. ON_BN_CLICKED(IDC_CLEAR_BUTTON, OnClear)
  49. END_MESSAGE_MAP()
  50. BOOL CSingleStringEditor::OnInitDialog()
  51. {
  52. //
  53. // Initialize the static control with the attribute name
  54. //
  55. SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute);
  56. //
  57. // Initialize the edit box with the value
  58. //
  59. if (m_szOldValue.IsEmpty())
  60. {
  61. CString szNotSet;
  62. VERIFY(szNotSet.LoadString(IDS_NOTSET));
  63. SetDlgItemText(IDC_VALUE_EDIT, szNotSet);
  64. }
  65. else
  66. {
  67. SetDlgItemText(IDC_VALUE_EDIT, m_szOldValue);
  68. }
  69. //
  70. // Select the text in the edit box
  71. //
  72. SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETSEL, 0, -1);
  73. return CDialog::OnInitDialog();
  74. }
  75. void CSingleStringEditor::OnOK()
  76. {
  77. GetDlgItemText(IDC_VALUE_EDIT, m_szNewValue);
  78. CDialog::OnOK();
  79. }
  80. HRESULT CSingleStringEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo)
  81. {
  82. HRESULT hr = S_OK;
  83. if (SUCCEEDED(CValueEditDialog::Initialize(pAttributeEditorInfo)))
  84. {
  85. if (pAttributeEditorInfo->dwNumValues > 0 &&
  86. pAttributeEditorInfo->pADsValue != NULL)
  87. {
  88. switch (pAttributeEditorInfo->pADsValue->dwType)
  89. {
  90. case ADSTYPE_CASE_IGNORE_STRING:
  91. m_szOldValue = pAttributeEditorInfo->pADsValue->CaseIgnoreString;
  92. break;
  93. case ADSTYPE_CASE_EXACT_STRING:
  94. m_szOldValue = pAttributeEditorInfo->pADsValue->CaseExactString;
  95. break;
  96. case ADSTYPE_PRINTABLE_STRING:
  97. m_szOldValue = pAttributeEditorInfo->pADsValue->PrintableString;
  98. break;
  99. case ADSTYPE_DN_STRING:
  100. m_szOldValue = pAttributeEditorInfo->pADsValue->DNString;
  101. break;
  102. default:
  103. ASSERT(FALSE);
  104. break;
  105. }
  106. }
  107. }
  108. return hr;
  109. }
  110. void CSingleStringEditor::OnClear()
  111. {
  112. //
  113. // Change the text in the edit box to "<not set>"
  114. //
  115. CString szNotSet;
  116. VERIFY(szNotSet.LoadString(IDS_NOTSET));
  117. SetDlgItemText(IDC_VALUE_EDIT, szNotSet);
  118. //
  119. // Change the focus to the edit box
  120. //
  121. GetDlgItem(IDC_VALUE_EDIT)->SetFocus();
  122. //
  123. // Select the text in the edit box
  124. //
  125. SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETSEL, 0, -1);
  126. }
  127. HRESULT CSingleStringEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues)
  128. {
  129. HRESULT hr = S_OK;
  130. if (ppADsValue == NULL ||
  131. pdwNumValues == NULL)
  132. {
  133. return E_OUTOFMEMORY;
  134. }
  135. CString szNotSet;
  136. VERIFY(szNotSet.LoadString(IDS_NOTSET));
  137. if (m_szNewValue == szNotSet)
  138. {
  139. *ppADsValue = NULL;
  140. *pdwNumValues = 0;
  141. }
  142. else
  143. {
  144. *ppADsValue = new ADSVALUE;
  145. if (*ppADsValue != NULL)
  146. {
  147. *pdwNumValues = 1;
  148. (*ppADsValue)->dwType = m_pOldADsValue->dwType;
  149. switch (m_pOldADsValue->dwType)
  150. {
  151. case ADSTYPE_CASE_IGNORE_STRING:
  152. (*ppADsValue)->CaseIgnoreString = new WCHAR[wcslen(m_szNewValue) + 1];
  153. if ((*ppADsValue)->CaseIgnoreString != NULL)
  154. {
  155. wcscpy((*ppADsValue)->CaseIgnoreString, m_szNewValue);
  156. }
  157. else
  158. {
  159. delete *ppADsValue;
  160. *ppADsValue = NULL;
  161. *pdwNumValues = 0;
  162. hr = E_OUTOFMEMORY;
  163. }
  164. break;
  165. case ADSTYPE_CASE_EXACT_STRING:
  166. (*ppADsValue)->CaseExactString = new WCHAR[wcslen(m_szNewValue) + 1];
  167. if ((*ppADsValue)->CaseExactString != NULL)
  168. {
  169. wcscpy((*ppADsValue)->CaseExactString, m_szNewValue);
  170. }
  171. else
  172. {
  173. delete *ppADsValue;
  174. *ppADsValue = NULL;
  175. *pdwNumValues = 0;
  176. hr = E_OUTOFMEMORY;
  177. }
  178. break;
  179. case ADSTYPE_PRINTABLE_STRING:
  180. (*ppADsValue)->PrintableString = new WCHAR[wcslen(m_szNewValue) + 1];
  181. if ((*ppADsValue)->PrintableString != NULL)
  182. {
  183. wcscpy((*ppADsValue)->PrintableString, m_szNewValue);
  184. }
  185. else
  186. {
  187. delete *ppADsValue;
  188. *ppADsValue = NULL;
  189. *pdwNumValues = 0;
  190. hr = E_OUTOFMEMORY;
  191. }
  192. break;
  193. case ADSTYPE_DN_STRING:
  194. (*ppADsValue)->DNString = new WCHAR[wcslen(m_szNewValue) + 1];
  195. if ((*ppADsValue)->DNString != NULL)
  196. {
  197. wcscpy((*ppADsValue)->DNString, m_szNewValue);
  198. }
  199. else
  200. {
  201. delete *ppADsValue;
  202. *ppADsValue = NULL;
  203. *pdwNumValues = 0;
  204. hr = E_OUTOFMEMORY;
  205. }
  206. break;
  207. default:
  208. ASSERT(FALSE);
  209. delete *ppADsValue;
  210. *ppADsValue = NULL;
  211. *pdwNumValues = 0;
  212. hr = E_FAIL;
  213. break;
  214. }
  215. }
  216. else
  217. {
  218. *pdwNumValues = 0;
  219. hr = E_OUTOFMEMORY;
  220. }
  221. }
  222. return hr;
  223. }
  224. ///////////////////////////////////////////////////////////////////////////////////////
  225. // CMultiStringEditor
  226. CValueEditDialog* CreateMultiStringEditor(PCWSTR pszClass,
  227. PCWSTR pszAttribute,
  228. ADSTYPE adsType,
  229. BOOL bMultivalued)
  230. {
  231. return new CMultiStringEditor;
  232. }
  233. BEGIN_MESSAGE_MAP(CMultiStringEditor, CValueEditDialog)
  234. ON_BN_CLICKED(IDC_ATTR_ADD_BUTTON, OnAddButton)
  235. ON_BN_CLICKED(IDC_ATTR_REMOVE_BUTTON, OnRemoveButton)
  236. ON_LBN_SELCHANGE(IDC_VALUE_LIST, OnListSelChange)
  237. ON_EN_CHANGE(IDC_VALUE_EDIT, OnEditChange)
  238. END_MESSAGE_MAP()
  239. BOOL CMultiStringEditor::OnInitDialog()
  240. {
  241. CDialog::OnInitDialog();
  242. //
  243. // Set the attribute name static
  244. //
  245. SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute);
  246. //
  247. // Fill the list box with the current values
  248. //
  249. POSITION pos = m_szOldValueList.GetHeadPosition();
  250. while (pos != NULL)
  251. {
  252. CString szValue = m_szOldValueList.GetNext(pos);
  253. if (!szValue.IsEmpty())
  254. {
  255. SendDlgItemMessage(IDC_VALUE_LIST, LB_ADDSTRING, 0, (LPARAM)(LPCWSTR)szValue);
  256. }
  257. }
  258. //
  259. // The remove button should be disabled until something is selected in the listbox
  260. //
  261. GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE);
  262. GetDlgItem(IDC_VALUE_EDIT)->SetFocus();
  263. ManageButtonStates();
  264. //
  265. // Update the width of the list box
  266. //
  267. UpdateListboxHorizontalExtent();
  268. //
  269. // NOTE: I have explicitly set the focus so return 0
  270. //
  271. return FALSE;
  272. }
  273. void CMultiStringEditor::OnOK()
  274. {
  275. //
  276. // Get the values out of the list box
  277. //
  278. m_szNewValueList.RemoveAll();
  279. CListBox* pListBox = reinterpret_cast<CListBox*>(GetDlgItem(IDC_VALUE_LIST));
  280. if (pListBox != NULL)
  281. {
  282. int iCount = pListBox->GetCount();
  283. for (int idx = 0; idx < iCount; idx++)
  284. {
  285. CString szNewValue;
  286. pListBox->GetText(idx, szNewValue);
  287. m_szNewValueList.AddTail(szNewValue);
  288. }
  289. }
  290. CDialog::OnOK();
  291. }
  292. void CMultiStringEditor::OnAddButton()
  293. {
  294. //
  295. // Add the value to the list box and clear the edit field
  296. //
  297. CString szNewValue;
  298. GetDlgItemText(IDC_VALUE_EDIT, szNewValue);
  299. if (!szNewValue.IsEmpty())
  300. {
  301. LRESULT lFind = SendDlgItemMessage(IDC_VALUE_LIST,
  302. LB_FINDSTRING,
  303. (WPARAM)-1,
  304. (LPARAM)(PCWSTR)szNewValue);
  305. if (lFind != LB_ERR)
  306. {
  307. //
  308. // Ask them if they really want to add the duplicate value
  309. //
  310. UINT nResult = ADSIEditMessageBox(IDS_ATTREDIT_DUPLICATE_VALUE, MB_YESNO);
  311. lFind = (nResult == IDYES) ? LB_ERR : 1;
  312. }
  313. if (lFind == LB_ERR)
  314. {
  315. SendDlgItemMessage(IDC_VALUE_LIST, LB_ADDSTRING, 0, (LPARAM)(LPCWSTR)szNewValue);
  316. }
  317. }
  318. SetDlgItemText(IDC_VALUE_EDIT, L"");
  319. ManageButtonStates();
  320. //
  321. // Update the width of the list box
  322. //
  323. UpdateListboxHorizontalExtent();
  324. }
  325. void CMultiStringEditor::OnRemoveButton()
  326. {
  327. CListBox* pListBox = reinterpret_cast<CListBox*>(GetDlgItem(IDC_VALUE_LIST));
  328. if (pListBox != NULL)
  329. {
  330. int iCurSel = pListBox->GetCurSel();
  331. if (iCurSel != LB_ERR)
  332. {
  333. //
  334. // Put the old value into the edit box
  335. //
  336. CString szOldValue;
  337. pListBox->GetText(iCurSel, szOldValue);
  338. SetDlgItemText(IDC_VALUE_EDIT, szOldValue);
  339. //
  340. // Delete the item from the list box
  341. //
  342. pListBox->DeleteString(iCurSel);
  343. }
  344. }
  345. //
  346. // Manage Button States
  347. //
  348. ManageButtonStates();
  349. //
  350. // Update the width of the list box
  351. //
  352. UpdateListboxHorizontalExtent();
  353. }
  354. void CMultiStringEditor::ManageButtonStates()
  355. {
  356. //
  357. // Change the default button to the Add button
  358. //
  359. CString szValue;
  360. GetDlgItemText(IDC_VALUE_EDIT, szValue);
  361. if (szValue.IsEmpty())
  362. {
  363. //
  364. // Set the default button to OK
  365. //
  366. SendMessage(DM_SETDEFID, (WPARAM)IDOK, 0);
  367. SendDlgItemMessage(IDC_ATTR_ADD_BUTTON,
  368. BM_SETSTYLE,
  369. BS_PUSHBUTTON,
  370. MAKELPARAM(TRUE, 0));
  371. SendDlgItemMessage(IDOK,
  372. BM_SETSTYLE,
  373. BS_DEFPUSHBUTTON,
  374. MAKELPARAM(TRUE, 0));
  375. }
  376. else
  377. {
  378. //
  379. // Set the default button to the Add button
  380. //
  381. SendMessage(DM_SETDEFID, (WPARAM)IDC_ATTR_ADD_BUTTON, 0);
  382. SendDlgItemMessage(IDOK,
  383. BM_SETSTYLE,
  384. BS_PUSHBUTTON,
  385. MAKELPARAM(TRUE, 0));
  386. SendDlgItemMessage(IDC_ATTR_ADD_BUTTON,
  387. BM_SETSTYLE,
  388. BS_DEFPUSHBUTTON,
  389. MAKELPARAM(TRUE, 0));
  390. }
  391. LRESULT lSelection = SendDlgItemMessage(IDC_VALUE_LIST, LB_GETCURSEL, 0, 0);
  392. if (lSelection != LB_ERR)
  393. {
  394. GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(TRUE);
  395. }
  396. else
  397. {
  398. GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE);
  399. }
  400. }
  401. void CMultiStringEditor::OnListSelChange()
  402. {
  403. ManageButtonStates();
  404. }
  405. void CMultiStringEditor::OnEditChange()
  406. {
  407. ManageButtonStates();
  408. }
  409. void CMultiStringEditor::UpdateListboxHorizontalExtent()
  410. {
  411. int nHorzExtent = 0;
  412. CListBox* pListBox = reinterpret_cast<CListBox*>(GetDlgItem(IDC_VALUE_LIST));
  413. if (pListBox != NULL)
  414. {
  415. CClientDC dc(pListBox);
  416. int nItems = pListBox->GetCount();
  417. for (int i=0; i < nItems; i++)
  418. {
  419. TEXTMETRIC tm;
  420. VERIFY(dc.GetTextMetrics(&tm));
  421. CString szBuffer;
  422. pListBox->GetText(i, szBuffer);
  423. CSize ext = dc.GetTextExtent(szBuffer,szBuffer.GetLength());
  424. nHorzExtent = max(ext.cx ,nHorzExtent);
  425. }
  426. pListBox->SetHorizontalExtent(nHorzExtent);
  427. }
  428. }
  429. HRESULT CMultiStringEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo)
  430. {
  431. HRESULT hr = S_OK;
  432. if (SUCCEEDED(CValueEditDialog::Initialize(pAttributeEditorInfo)))
  433. {
  434. if (pAttributeEditorInfo->dwNumValues > 0 &&
  435. pAttributeEditorInfo->pADsValue != NULL)
  436. {
  437. for (int idx = 0; idx < pAttributeEditorInfo->dwNumValues; idx++)
  438. {
  439. switch (pAttributeEditorInfo->pADsValue[idx].dwType)
  440. {
  441. case ADSTYPE_CASE_IGNORE_STRING:
  442. m_szOldValueList.AddTail(pAttributeEditorInfo->pADsValue[idx].CaseIgnoreString);
  443. break;
  444. case ADSTYPE_CASE_EXACT_STRING:
  445. m_szOldValueList.AddTail(pAttributeEditorInfo->pADsValue[idx].CaseExactString);
  446. break;
  447. case ADSTYPE_PRINTABLE_STRING:
  448. m_szOldValueList.AddTail(pAttributeEditorInfo->pADsValue[idx].PrintableString);
  449. break;
  450. case ADSTYPE_DN_STRING:
  451. m_szOldValueList.AddTail(pAttributeEditorInfo->pADsValue[idx].DNString);
  452. break;
  453. default:
  454. ASSERT(FALSE);
  455. break;
  456. }
  457. }
  458. }
  459. }
  460. return hr;
  461. }
  462. HRESULT CMultiStringEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues)
  463. {
  464. HRESULT hr = S_OK;
  465. if (ppADsValue == NULL ||
  466. pdwNumValues == NULL)
  467. {
  468. return E_OUTOFMEMORY;
  469. }
  470. int iCount = m_szNewValueList.GetCount();
  471. if (iCount == 0)
  472. {
  473. *ppADsValue = NULL;
  474. *pdwNumValues = 0;
  475. }
  476. else
  477. {
  478. *ppADsValue = new ADSVALUE[iCount];
  479. if (*ppADsValue != NULL)
  480. {
  481. *pdwNumValues = iCount;
  482. int idx = 0;
  483. POSITION pos = m_szNewValueList.GetHeadPosition();
  484. while (pos != NULL)
  485. {
  486. CString szNewValue = m_szNewValueList.GetNext(pos);
  487. (*ppADsValue)[idx].dwType = m_pOldADsValue->dwType;
  488. switch (m_pOldADsValue->dwType)
  489. {
  490. case ADSTYPE_CASE_IGNORE_STRING:
  491. (*ppADsValue)[idx].CaseIgnoreString = new WCHAR[wcslen(szNewValue) + 1];
  492. if ((*ppADsValue)[idx].CaseIgnoreString != NULL)
  493. {
  494. wcscpy((*ppADsValue)[idx].CaseIgnoreString, szNewValue);
  495. }
  496. else
  497. {
  498. delete[] *ppADsValue;
  499. *ppADsValue = NULL;
  500. *pdwNumValues = 0;
  501. hr = E_OUTOFMEMORY;
  502. }
  503. break;
  504. case ADSTYPE_CASE_EXACT_STRING:
  505. (*ppADsValue)[idx].CaseExactString = new WCHAR[wcslen(szNewValue) + 1];
  506. if ((*ppADsValue)[idx].CaseExactString != NULL)
  507. {
  508. wcscpy((*ppADsValue)[idx].CaseExactString, szNewValue);
  509. }
  510. else
  511. {
  512. delete[] *ppADsValue;
  513. *ppADsValue = NULL;
  514. *pdwNumValues = 0;
  515. hr = E_OUTOFMEMORY;
  516. }
  517. break;
  518. case ADSTYPE_PRINTABLE_STRING:
  519. (*ppADsValue)[idx].PrintableString = new WCHAR[wcslen(szNewValue) + 1];
  520. if ((*ppADsValue)[idx].PrintableString != NULL)
  521. {
  522. wcscpy((*ppADsValue)[idx].PrintableString, szNewValue);
  523. }
  524. else
  525. {
  526. delete[] *ppADsValue;
  527. *ppADsValue = NULL;
  528. *pdwNumValues = 0;
  529. hr = E_OUTOFMEMORY;
  530. }
  531. break;
  532. case ADSTYPE_DN_STRING:
  533. (*ppADsValue)[idx].DNString = new WCHAR[wcslen(szNewValue) + 1];
  534. if ((*ppADsValue)[idx].DNString != NULL)
  535. {
  536. wcscpy((*ppADsValue)[idx].DNString, szNewValue);
  537. }
  538. else
  539. {
  540. delete[] *ppADsValue;
  541. *ppADsValue = NULL;
  542. *pdwNumValues = 0;
  543. hr = E_OUTOFMEMORY;
  544. }
  545. break;
  546. default:
  547. ASSERT(FALSE);
  548. delete[] *ppADsValue;
  549. *ppADsValue = NULL;
  550. *pdwNumValues = 0;
  551. hr = E_FAIL;
  552. break;
  553. }
  554. idx++;
  555. }
  556. }
  557. else
  558. {
  559. *ppADsValue = NULL;
  560. *pdwNumValues = 0;
  561. hr = E_OUTOFMEMORY;
  562. }
  563. }
  564. return hr;
  565. }
  566. ///////////////////////////////////////////////////////////////////////////////////////
  567. // CSingleIntEditor
  568. CValueEditDialog* CreateSingleIntEditor(PCWSTR pszClass,
  569. PCWSTR pszAttribute,
  570. ADSTYPE adsType,
  571. BOOL bMultivalued)
  572. {
  573. return new CSingleIntEditor;
  574. }
  575. BEGIN_MESSAGE_MAP(CSingleIntEditor, CValueEditDialog)
  576. ON_BN_CLICKED(IDC_CLEAR_BUTTON, OnClear)
  577. END_MESSAGE_MAP()
  578. BOOL CSingleIntEditor::OnInitDialog()
  579. {
  580. //
  581. // Initialize the static control with the attribute name
  582. //
  583. SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute);
  584. //
  585. // Initialize the edit box with the value
  586. //
  587. if (!m_bValueSet)
  588. {
  589. CString szNotSet;
  590. VERIFY(szNotSet.LoadString(IDS_NOTSET));
  591. SetDlgItemText(IDC_VALUE_EDIT, szNotSet);
  592. }
  593. else
  594. {
  595. SetDlgItemInt(IDC_VALUE_EDIT, m_dwOldValue, FALSE);
  596. }
  597. //
  598. // Select the text in the edit box
  599. //
  600. SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETSEL, 0, -1);
  601. //
  602. // Disable IME support on the edit box
  603. //
  604. ImmAssociateContext(::GetDlgItem(GetSafeHwnd(), IDC_VALUE_EDIT), NULL);
  605. return CDialog::OnInitDialog();
  606. }
  607. void CSingleIntEditor::OnOK()
  608. {
  609. m_dwNewValue = GetDlgItemInt(IDC_VALUE_EDIT, &m_bValueSet, FALSE);
  610. CDialog::OnOK();
  611. }
  612. HRESULT CSingleIntEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo)
  613. {
  614. HRESULT hr = S_OK;
  615. if (SUCCEEDED(CValueEditDialog::Initialize(pAttributeEditorInfo)))
  616. {
  617. if (pAttributeEditorInfo->dwNumValues > 0 &&
  618. pAttributeEditorInfo->pADsValue != NULL)
  619. {
  620. switch (pAttributeEditorInfo->pADsValue->dwType)
  621. {
  622. case ADSTYPE_INTEGER:
  623. m_dwOldValue = pAttributeEditorInfo->pADsValue->Integer;
  624. m_bValueSet = TRUE;
  625. break;
  626. default:
  627. ASSERT(FALSE);
  628. break;
  629. }
  630. }
  631. }
  632. return hr;
  633. }
  634. void CSingleIntEditor::OnClear()
  635. {
  636. //
  637. // Change the text in the edit box to "<not set>"
  638. //
  639. CString szNotSet;
  640. VERIFY(szNotSet.LoadString(IDS_NOTSET));
  641. SetDlgItemText(IDC_VALUE_EDIT, szNotSet);
  642. //
  643. // Change the focus to the edit box
  644. //
  645. GetDlgItem(IDC_VALUE_EDIT)->SetFocus();
  646. //
  647. // Select the text in the edit box
  648. //
  649. SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETSEL, 0, -1);
  650. m_bValueSet = FALSE;
  651. }
  652. HRESULT CSingleIntEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues)
  653. {
  654. HRESULT hr = S_OK;
  655. if (ppADsValue == NULL ||
  656. pdwNumValues == NULL)
  657. {
  658. return E_OUTOFMEMORY;
  659. }
  660. CString szNotSet;
  661. VERIFY(szNotSet.LoadString(IDS_NOTSET));
  662. if (!m_bValueSet)
  663. {
  664. *ppADsValue = NULL;
  665. *pdwNumValues = 0;
  666. }
  667. else
  668. {
  669. *ppADsValue = new ADSVALUE;
  670. if (*ppADsValue != NULL)
  671. {
  672. *pdwNumValues = 1;
  673. (*ppADsValue)->dwType = m_pOldADsValue->dwType;
  674. switch (m_pOldADsValue->dwType)
  675. {
  676. case ADSTYPE_INTEGER:
  677. (*ppADsValue)->Integer = m_dwNewValue;
  678. break;
  679. default:
  680. ASSERT(FALSE);
  681. delete *ppADsValue;
  682. *ppADsValue = NULL;
  683. *pdwNumValues = 0;
  684. hr = E_FAIL;
  685. break;
  686. }
  687. }
  688. else
  689. {
  690. *pdwNumValues = 0;
  691. hr = E_OUTOFMEMORY;
  692. }
  693. }
  694. return hr;
  695. }
  696. ///////////////////////////////////////////////////////////////////////////////////////
  697. // CSingleLargeIntEditor
  698. CValueEditDialog* CreateSingleLargeIntEditor(PCWSTR pszClass,
  699. PCWSTR pszAttribute,
  700. ADSTYPE adsType,
  701. BOOL bMultivalued)
  702. {
  703. return new CSingleLargeIntEditor;
  704. }
  705. BEGIN_MESSAGE_MAP(CSingleLargeIntEditor, CValueEditDialog)
  706. ON_BN_CLICKED(IDC_CLEAR_BUTTON, OnClear)
  707. END_MESSAGE_MAP()
  708. BOOL CSingleLargeIntEditor::OnInitDialog()
  709. {
  710. //
  711. // Initialize the static control with the attribute name
  712. //
  713. SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute);
  714. //
  715. // Initialize the edit box with the value
  716. //
  717. if (!m_bValueSet)
  718. {
  719. CString szNotSet;
  720. VERIFY(szNotSet.LoadString(IDS_NOTSET));
  721. SetDlgItemText(IDC_VALUE_EDIT, szNotSet);
  722. }
  723. else
  724. {
  725. CString szOldValue;
  726. litow(m_liOldValue, szOldValue);
  727. SetDlgItemText(IDC_VALUE_EDIT, szOldValue);
  728. }
  729. //
  730. // Select the text in the edit box
  731. //
  732. SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETSEL, 0, -1);
  733. //
  734. // Disable IME support on the edit box
  735. //
  736. ImmAssociateContext(::GetDlgItem(GetSafeHwnd(), IDC_VALUE_EDIT), NULL);
  737. return CDialog::OnInitDialog();
  738. }
  739. void CSingleLargeIntEditor::OnOK()
  740. {
  741. CString szNotSet;
  742. VERIFY(szNotSet.LoadString(IDS_NOTSET));
  743. CString szNewValue;
  744. GetDlgItemText(IDC_VALUE_EDIT, szNewValue);
  745. if (szNewValue == szNotSet)
  746. {
  747. m_bValueSet = FALSE;
  748. }
  749. else
  750. {
  751. wtoli(szNewValue, m_liNewValue);
  752. m_bValueSet = TRUE;
  753. }
  754. CDialog::OnOK();
  755. }
  756. HRESULT CSingleLargeIntEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo)
  757. {
  758. HRESULT hr = S_OK;
  759. if (SUCCEEDED(CValueEditDialog::Initialize(pAttributeEditorInfo)))
  760. {
  761. if (pAttributeEditorInfo->dwNumValues > 0 &&
  762. pAttributeEditorInfo->pADsValue != NULL)
  763. {
  764. switch (pAttributeEditorInfo->pADsValue->dwType)
  765. {
  766. case ADSTYPE_LARGE_INTEGER:
  767. m_liOldValue = pAttributeEditorInfo->pADsValue->LargeInteger;
  768. m_bValueSet = TRUE;
  769. break;
  770. default:
  771. ASSERT(FALSE);
  772. break;
  773. }
  774. }
  775. else
  776. {
  777. m_bValueSet = FALSE;
  778. }
  779. }
  780. return hr;
  781. }
  782. void CSingleLargeIntEditor::OnClear()
  783. {
  784. //
  785. // Change the text in the edit box to "<not set>"
  786. //
  787. CString szNotSet;
  788. VERIFY(szNotSet.LoadString(IDS_NOTSET));
  789. SetDlgItemText(IDC_VALUE_EDIT, szNotSet);
  790. //
  791. // Change the focus to the edit box
  792. //
  793. GetDlgItem(IDC_VALUE_EDIT)->SetFocus();
  794. //
  795. // Select the text in the edit box
  796. //
  797. SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETSEL, 0, -1);
  798. m_bValueSet = FALSE;
  799. }
  800. HRESULT CSingleLargeIntEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues)
  801. {
  802. HRESULT hr = S_OK;
  803. if (ppADsValue == NULL ||
  804. pdwNumValues == NULL)
  805. {
  806. return E_OUTOFMEMORY;
  807. }
  808. if (!m_bValueSet)
  809. {
  810. *ppADsValue = NULL;
  811. *pdwNumValues = 0;
  812. }
  813. else
  814. {
  815. *ppADsValue = new ADSVALUE;
  816. if (*ppADsValue != NULL)
  817. {
  818. *pdwNumValues = 1;
  819. (*ppADsValue)->dwType = m_pOldADsValue->dwType;
  820. switch (m_pOldADsValue->dwType)
  821. {
  822. case ADSTYPE_LARGE_INTEGER:
  823. (*ppADsValue)->LargeInteger = m_liNewValue;
  824. break;
  825. default:
  826. ASSERT(FALSE);
  827. delete *ppADsValue;
  828. *ppADsValue = NULL;
  829. *pdwNumValues = 0;
  830. hr = E_FAIL;
  831. break;
  832. }
  833. }
  834. else
  835. {
  836. *pdwNumValues = 0;
  837. hr = E_OUTOFMEMORY;
  838. }
  839. }
  840. return hr;
  841. }
  842. ///////////////////////////////////////////////////////////////////////////////////////
  843. // CSingleBooleanEditor
  844. CValueEditDialog* CreateSingleBooleanEditor(PCWSTR pszClass,
  845. PCWSTR pszAttribute,
  846. ADSTYPE adsType,
  847. BOOL bMultivalued)
  848. {
  849. return new CSingleBooleanEditor;
  850. }
  851. BEGIN_MESSAGE_MAP(CSingleBooleanEditor, CValueEditDialog)
  852. END_MESSAGE_MAP()
  853. BOOL CSingleBooleanEditor::OnInitDialog()
  854. {
  855. //
  856. // Initialize the static control with the attribute name
  857. //
  858. SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute);
  859. //
  860. // Initialize the edit box with the value
  861. //
  862. if (!m_bValueSet)
  863. {
  864. SendDlgItemMessage(IDC_NOTSET_RADIO, BM_SETCHECK, BST_CHECKED, 0);
  865. }
  866. else
  867. {
  868. if (m_bOldValue)
  869. {
  870. SendDlgItemMessage(IDC_TRUE_RADIO, BM_SETCHECK, BST_CHECKED, 0);
  871. }
  872. else
  873. {
  874. SendDlgItemMessage(IDC_FALSE_RADIO, BM_SETCHECK, BST_CHECKED, 0);
  875. }
  876. }
  877. return CDialog::OnInitDialog();
  878. }
  879. void CSingleBooleanEditor::OnOK()
  880. {
  881. LRESULT lTrueCheck = SendDlgItemMessage(IDC_TRUE_RADIO, BM_GETCHECK, 0, 0);
  882. LRESULT lFalseCheck = SendDlgItemMessage(IDC_FALSE_RADIO, BM_GETCHECK, 0, 0);
  883. LRESULT lNotSetCheck = SendDlgItemMessage(IDC_NOTSET_RADIO, BM_GETCHECK, 0, 0);
  884. if (lTrueCheck == BST_CHECKED)
  885. {
  886. m_bNewValue = TRUE;
  887. m_bValueSet = TRUE;
  888. }
  889. if (lFalseCheck == BST_CHECKED)
  890. {
  891. m_bNewValue = FALSE;
  892. m_bValueSet = TRUE;
  893. }
  894. if (lNotSetCheck == BST_CHECKED)
  895. {
  896. m_bValueSet = FALSE;
  897. }
  898. CDialog::OnOK();
  899. }
  900. HRESULT CSingleBooleanEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo)
  901. {
  902. HRESULT hr = S_OK;
  903. if (SUCCEEDED(CValueEditDialog::Initialize(pAttributeEditorInfo)))
  904. {
  905. if (pAttributeEditorInfo->dwNumValues > 0 &&
  906. pAttributeEditorInfo->pADsValue != NULL)
  907. {
  908. switch (pAttributeEditorInfo->pADsValue->dwType)
  909. {
  910. case ADSTYPE_BOOLEAN:
  911. m_bOldValue = pAttributeEditorInfo->pADsValue->Boolean;
  912. m_bValueSet = TRUE;
  913. break;
  914. default:
  915. ASSERT(FALSE);
  916. break;
  917. }
  918. }
  919. else
  920. {
  921. m_bValueSet = FALSE;
  922. }
  923. }
  924. return hr;
  925. }
  926. HRESULT CSingleBooleanEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues)
  927. {
  928. HRESULT hr = S_OK;
  929. if (ppADsValue == NULL ||
  930. pdwNumValues == NULL)
  931. {
  932. return E_OUTOFMEMORY;
  933. }
  934. if (!m_bValueSet)
  935. {
  936. *ppADsValue = NULL;
  937. *pdwNumValues = 0;
  938. }
  939. else
  940. {
  941. *ppADsValue = new ADSVALUE;
  942. if (*ppADsValue != NULL)
  943. {
  944. *pdwNumValues = 1;
  945. (*ppADsValue)->dwType = m_pOldADsValue->dwType;
  946. switch (m_pOldADsValue->dwType)
  947. {
  948. case ADSTYPE_BOOLEAN:
  949. (*ppADsValue)->Boolean = m_bNewValue;
  950. break;
  951. default:
  952. ASSERT(FALSE);
  953. delete *ppADsValue;
  954. *ppADsValue = NULL;
  955. *pdwNumValues = 0;
  956. hr = E_FAIL;
  957. break;
  958. }
  959. }
  960. else
  961. {
  962. *pdwNumValues = 0;
  963. hr = E_OUTOFMEMORY;
  964. }
  965. }
  966. return hr;
  967. }
  968. ///////////////////////////////////////////////////////////////////////////////////////
  969. // CSingleBooleanEditor
  970. CValueEditDialog* CreateSingleTimeEditor(PCWSTR pszClass,
  971. PCWSTR pszAttribute,
  972. ADSTYPE adsType,
  973. BOOL bMultivalued)
  974. {
  975. return new CSingleTimeEditor;
  976. }
  977. BEGIN_MESSAGE_MAP(CSingleTimeEditor, CValueEditDialog)
  978. END_MESSAGE_MAP()
  979. BOOL CSingleTimeEditor::OnInitDialog()
  980. {
  981. //
  982. // Initialize the static control with the attribute name
  983. //
  984. SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute);
  985. if (m_bValueSet)
  986. {
  987. SendDlgItemMessage(IDC_DATE_PICKER, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&m_stOldValue);
  988. SendDlgItemMessage(IDC_TIME_PICKER, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&m_stOldValue);
  989. }
  990. else
  991. {
  992. SendDlgItemMessage(IDC_DATE_PICKER, DTM_SETSYSTEMTIME, GDT_NONE, (LPARAM)&m_stOldValue);
  993. SendDlgItemMessage(IDC_TIME_PICKER, DTM_SETSYSTEMTIME, GDT_NONE, (LPARAM)&m_stOldValue);
  994. }
  995. return CDialog::OnInitDialog();
  996. }
  997. void CSingleTimeEditor::OnOK()
  998. {
  999. SYSTEMTIME stDateResult = {0};
  1000. SYSTEMTIME stTimeResult = {0};
  1001. LRESULT lDateRes = SendDlgItemMessage(IDC_DATE_PICKER, DTM_GETSYSTEMTIME, 0, (LPARAM)&stDateResult);
  1002. LRESULT lTimeRes = SendDlgItemMessage(IDC_TIME_PICKER, DTM_SETSYSTEMTIME, 0, (LPARAM)&stTimeResult);
  1003. if (lDateRes == GDT_VALID &&
  1004. lTimeRes == GDT_VALID)
  1005. {
  1006. memcpy(&m_stNewValue, &stDateResult, sizeof(SYSTEMTIME));
  1007. m_stNewValue.wHour = stTimeResult.wHour;
  1008. m_stNewValue.wMinute = stTimeResult.wMinute;
  1009. m_stNewValue.wSecond = stTimeResult.wSecond;
  1010. m_stNewValue.wMilliseconds = stTimeResult.wMilliseconds;
  1011. }
  1012. CDialog::OnOK();
  1013. }
  1014. HRESULT CSingleTimeEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo)
  1015. {
  1016. HRESULT hr = S_OK;
  1017. if (SUCCEEDED(CValueEditDialog::Initialize(pAttributeEditorInfo)))
  1018. {
  1019. if (pAttributeEditorInfo->dwNumValues > 0 &&
  1020. pAttributeEditorInfo->pADsValue != NULL)
  1021. {
  1022. switch (pAttributeEditorInfo->pADsValue->dwType)
  1023. {
  1024. case ADSTYPE_UTC_TIME:
  1025. memcpy(&m_stOldValue, &(pAttributeEditorInfo->pADsValue->UTCTime), sizeof(SYSTEMTIME));
  1026. m_bValueSet = TRUE;
  1027. break;
  1028. default:
  1029. ASSERT(FALSE);
  1030. break;
  1031. }
  1032. }
  1033. else
  1034. {
  1035. m_bValueSet = FALSE;
  1036. }
  1037. }
  1038. return hr;
  1039. }
  1040. HRESULT CSingleTimeEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues)
  1041. {
  1042. HRESULT hr = S_OK;
  1043. if (ppADsValue == NULL ||
  1044. pdwNumValues == NULL)
  1045. {
  1046. return E_OUTOFMEMORY;
  1047. }
  1048. *ppADsValue = new ADSVALUE;
  1049. if (*ppADsValue != NULL)
  1050. {
  1051. *pdwNumValues = 1;
  1052. (*ppADsValue)->dwType = m_pOldADsValue->dwType;
  1053. switch (m_pOldADsValue->dwType)
  1054. {
  1055. case ADSTYPE_UTC_TIME:
  1056. memcpy(&((*ppADsValue)->UTCTime), &m_stNewValue, sizeof(SYSTEMTIME));
  1057. break;
  1058. default:
  1059. ASSERT(FALSE);
  1060. delete *ppADsValue;
  1061. *ppADsValue = NULL;
  1062. *pdwNumValues = 0;
  1063. hr = E_FAIL;
  1064. break;
  1065. }
  1066. }
  1067. else
  1068. {
  1069. *pdwNumValues = 0;
  1070. hr = E_OUTOFMEMORY;
  1071. }
  1072. return hr;
  1073. }
  1074. ///////////////////////////////////////////////////////////////////////////////////////
  1075. // COctetStringEditor
  1076. CValueEditDialog* CreateSingleOctetStringEditor(PCWSTR pszClass,
  1077. PCWSTR pszAttribute,
  1078. ADSTYPE adsType,
  1079. BOOL bMultivalued)
  1080. {
  1081. return new COctetStringEditor;
  1082. }
  1083. BEGIN_MESSAGE_MAP(COctetStringEditor, CValueEditDialog)
  1084. ON_EN_CHANGE(IDC_PROCESS_EDIT, OnProcessEdit)
  1085. ON_BN_CLICKED(IDC_ATTR_EDIT_BUTTON, OnEditButton)
  1086. ON_BN_CLICKED(IDC_CLEAR_BUTTON, OnClearButton)
  1087. END_MESSAGE_MAP()
  1088. BOOL COctetStringEditor::OnInitDialog()
  1089. {
  1090. //
  1091. // Initialize the static control with the attribute name
  1092. //
  1093. SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute);
  1094. DWORD dwDisplayFlags = BYTE_ARRAY_DISPLAY_HEX |
  1095. BYTE_ARRAY_DISPLAY_DEC |
  1096. BYTE_ARRAY_DISPLAY_OCT |
  1097. BYTE_ARRAY_DISPLAY_BIN;
  1098. VERIFY(m_display.Initialize(IDC_VALUE_EDIT,
  1099. IDC_VIEW_TYPE_COMBO,
  1100. dwDisplayFlags,
  1101. BYTE_ARRAY_DISPLAY_HEX, // default display
  1102. this,
  1103. 1024,
  1104. IDS_OCTET_DISPLAY_SIZE_EXCEEDED)); // Only show 1K of data in the edit box
  1105. m_display.SetData(m_pOldValue, m_dwOldLength);
  1106. return CDialog::OnInitDialog();
  1107. }
  1108. void COctetStringEditor::OnOK()
  1109. {
  1110. //
  1111. // Retrieve the new values from the control
  1112. //
  1113. if (m_pNewValue)
  1114. {
  1115. delete[] m_pNewValue;
  1116. m_pNewValue = 0;
  1117. m_dwNewLength = 0;
  1118. }
  1119. m_dwNewLength = m_display.GetData(&m_pNewValue);
  1120. CDialog::OnOK();
  1121. }
  1122. void COctetStringEditor::OnProcessEdit()
  1123. {
  1124. CString szProcess;
  1125. GetDlgItemText(IDC_PROCESS_EDIT, szProcess);
  1126. if (szProcess.IsEmpty())
  1127. {
  1128. GetDlgItem(IDC_ATTR_EDIT_BUTTON)->EnableWindow(FALSE);
  1129. //
  1130. // Set the default button to OK
  1131. //
  1132. SendMessage(DM_SETDEFID, (WPARAM)IDOK, 0);
  1133. SendDlgItemMessage(IDC_ATTR_EDIT_BUTTON,
  1134. BM_SETSTYLE,
  1135. BS_PUSHBUTTON,
  1136. MAKELPARAM(TRUE, 0));
  1137. SendDlgItemMessage(IDOK,
  1138. BM_SETSTYLE,
  1139. BS_DEFPUSHBUTTON,
  1140. MAKELPARAM(TRUE, 0));
  1141. }
  1142. else
  1143. {
  1144. GetDlgItem(IDC_ATTR_EDIT_BUTTON)->EnableWindow(TRUE);
  1145. //
  1146. // Set the default button to the Edit button
  1147. //
  1148. SendMessage(DM_SETDEFID, (WPARAM)IDC_ATTR_EDIT_BUTTON, 0);
  1149. SendDlgItemMessage(IDOK,
  1150. BM_SETSTYLE,
  1151. BS_PUSHBUTTON,
  1152. MAKELPARAM(TRUE, 0));
  1153. SendDlgItemMessage(IDC_ATTR_EDIT_BUTTON,
  1154. BM_SETSTYLE,
  1155. BS_DEFPUSHBUTTON,
  1156. MAKELPARAM(TRUE, 0));
  1157. }
  1158. }
  1159. void COctetStringEditor::OnEditButton()
  1160. {
  1161. CString szProcess;
  1162. GetDlgItemText(IDC_PROCESS_EDIT, szProcess);
  1163. //
  1164. // Create a temp file and write out the contents of the octet string
  1165. //
  1166. WCHAR szTempPath[MAX_PATH];
  1167. if (!::GetTempPath(MAX_PATH, szTempPath))
  1168. {
  1169. ADSIEditMessageBox(IDS_MSG_FAIL_CREATE_TEMPFILE, MB_OK);
  1170. return;
  1171. }
  1172. CString szDataPath;
  1173. if (!::GetTempFileName(szTempPath, _T("attredit"), 0x0, szDataPath.GetBuffer(MAX_PATH)))
  1174. {
  1175. ADSIEditMessageBox(IDS_MSG_FAIL_CREATE_TEMPFILE, MB_OK);
  1176. return;
  1177. }
  1178. szDataPath.ReleaseBuffer();
  1179. //
  1180. // Open the temp file so we can write out the data
  1181. //
  1182. CFile tempDataFile;
  1183. if (!tempDataFile.Open(szDataPath,
  1184. CFile::modeCreate | CFile::modeReadWrite |CFile::shareExclusive | CFile::typeBinary))
  1185. {
  1186. //
  1187. // Failed to open temp file, display error message
  1188. //
  1189. ADSIEditMessageBox(IDS_MSG_FAIL_CREATE_TEMPFILE, MB_OK);
  1190. return;
  1191. }
  1192. //
  1193. // Write the byte array to a temp file
  1194. //
  1195. BYTE* pData = 0;
  1196. DWORD dwDataLength = m_display.GetData(&pData);
  1197. if (dwDataLength != 0 && pData)
  1198. {
  1199. tempDataFile.Write(pData, dwDataLength);
  1200. }
  1201. tempDataFile.Close();
  1202. if (pData)
  1203. {
  1204. delete[] pData;
  1205. pData = 0;
  1206. }
  1207. dwDataLength = 0;
  1208. //
  1209. // Construct the command line from the executable and the temp file
  1210. //
  1211. CString szCommandLine = szProcess + L" " + szDataPath;
  1212. //
  1213. // Launch the process with the temp file as an argument
  1214. //
  1215. STARTUPINFO si;
  1216. PROCESS_INFORMATION pi;
  1217. ::ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
  1218. ::ZeroMemory(&si,sizeof(STARTUPINFO));
  1219. si.cb = sizeof (STARTUPINFO);
  1220. if(CreateProcess( NULL,
  1221. (LPWSTR)(LPCWSTR)szCommandLine,
  1222. NULL,
  1223. NULL,
  1224. FALSE,
  1225. 0,
  1226. NULL,
  1227. NULL,
  1228. &si,
  1229. &pi) )
  1230. {
  1231. // wait to finish the runing setup process
  1232. WaitForSingleObject(pi.hProcess,INFINITE);
  1233. // close process handle
  1234. if (pi.hProcess && pi.hProcess != INVALID_HANDLE_VALUE)
  1235. {
  1236. CloseHandle (pi.hProcess) ;
  1237. }
  1238. if (pi.hThread && pi.hThread != INVALID_HANDLE_VALUE)
  1239. {
  1240. CloseHandle (pi.hThread) ;
  1241. }
  1242. }
  1243. else
  1244. {
  1245. ADSIEditMessageBox(IDS_MSG_FAIL_LAUNCH_PROCESS, MB_OK);
  1246. return;
  1247. }
  1248. //
  1249. // Load the data from the saved temp file
  1250. //
  1251. if (!LoadFileAsByteArray(szDataPath, &pData, &dwDataLength))
  1252. {
  1253. ADSIEditMessageBox(IDS_MSG_FAIL_RETRIEVE_SAVED_DATA, MB_OK);
  1254. return;
  1255. }
  1256. //
  1257. // Delete temp file after picture is displayed
  1258. //
  1259. CFile::Remove(szDataPath);
  1260. //
  1261. // Update the UI with the new data
  1262. //
  1263. m_display.SetData(pData, dwDataLength);
  1264. }
  1265. void COctetStringEditor::OnClearButton()
  1266. {
  1267. m_display.ClearData();
  1268. }
  1269. HRESULT COctetStringEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo)
  1270. {
  1271. HRESULT hr = S_OK;
  1272. if (SUCCEEDED(CValueEditDialog::Initialize(pAttributeEditorInfo)))
  1273. {
  1274. if (pAttributeEditorInfo->dwNumValues > 0 &&
  1275. pAttributeEditorInfo->pADsValue)
  1276. {
  1277. switch (pAttributeEditorInfo->pADsValue->dwType)
  1278. {
  1279. case ADSTYPE_OCTET_STRING:
  1280. m_dwOldLength = pAttributeEditorInfo->pADsValue->OctetString.dwLength;
  1281. m_pOldValue = new BYTE[m_dwOldLength];
  1282. if (m_pOldValue)
  1283. {
  1284. memcpy(m_pOldValue, pAttributeEditorInfo->pADsValue->OctetString.lpValue, m_dwOldLength);
  1285. }
  1286. else
  1287. {
  1288. hr = E_OUTOFMEMORY;
  1289. }
  1290. m_bValueSet = TRUE;
  1291. break;
  1292. default:
  1293. ASSERT(FALSE);
  1294. break;
  1295. }
  1296. }
  1297. else
  1298. {
  1299. m_bValueSet = FALSE;
  1300. }
  1301. }
  1302. return hr;
  1303. }
  1304. HRESULT COctetStringEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues)
  1305. {
  1306. HRESULT hr = S_OK;
  1307. if (ppADsValue == NULL ||
  1308. pdwNumValues == NULL)
  1309. {
  1310. return E_OUTOFMEMORY;
  1311. }
  1312. if (m_dwNewLength > 0 && m_pNewValue)
  1313. {
  1314. *ppADsValue = new ADSVALUE;
  1315. if (*ppADsValue)
  1316. {
  1317. *pdwNumValues = 1;
  1318. (*ppADsValue)->dwType = m_pOldADsValue->dwType;
  1319. switch (m_pOldADsValue->dwType)
  1320. {
  1321. case ADSTYPE_OCTET_STRING:
  1322. (*ppADsValue)->OctetString.dwLength = m_dwNewLength;
  1323. (*ppADsValue)->OctetString.lpValue = new BYTE[m_dwNewLength];
  1324. if ((*ppADsValue)->OctetString.lpValue)
  1325. {
  1326. memcpy((*ppADsValue)->OctetString.lpValue, m_pNewValue, m_dwNewLength);
  1327. }
  1328. else
  1329. {
  1330. hr = E_OUTOFMEMORY;
  1331. }
  1332. break;
  1333. default:
  1334. ASSERT(FALSE);
  1335. delete *ppADsValue;
  1336. *ppADsValue = 0;
  1337. *pdwNumValues = 0;
  1338. hr = E_FAIL;
  1339. break;
  1340. }
  1341. }
  1342. else
  1343. {
  1344. *pdwNumValues = 0;
  1345. hr = E_OUTOFMEMORY;
  1346. }
  1347. }
  1348. else
  1349. {
  1350. *ppADsValue = 0;
  1351. *pdwNumValues = 0;
  1352. }
  1353. return hr;
  1354. }
  1355. CValueEditDialog* CreateMultiOctetStringEditor(PCWSTR pszClass,
  1356. PCWSTR pszAttribute,
  1357. ADSTYPE adsType,
  1358. BOOL bMultivalued)
  1359. {
  1360. return new CMultiOctetStringEditor;
  1361. }
  1362. BEGIN_MESSAGE_MAP(CMultiOctetStringEditor, CValueEditDialog)
  1363. ON_BN_CLICKED(IDC_ATTR_ADD_BUTTON, OnAddButton)
  1364. ON_BN_CLICKED(IDC_ATTR_REMOVE_BUTTON, OnRemoveButton)
  1365. ON_BN_CLICKED(IDC_EDIT_BUTTON, OnEditButton)
  1366. ON_LBN_SELCHANGE(IDC_VALUE_LIST, OnListSelChange)
  1367. END_MESSAGE_MAP()
  1368. BOOL CMultiOctetStringEditor::OnInitDialog()
  1369. {
  1370. CDialog::OnInitDialog();
  1371. //
  1372. // Set the attribute name static
  1373. //
  1374. SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute);
  1375. //
  1376. // Fill the list box with the current values
  1377. //
  1378. POSITION pos = m_OldValueList.GetHeadPosition();
  1379. while (pos)
  1380. {
  1381. PADSVALUE pADsValue = m_OldValueList.GetNext(pos);
  1382. if (pADsValue)
  1383. {
  1384. CString szValue;
  1385. GetStringFromADsValue(pADsValue, szValue, MAX_OCTET_STRING_VALUE_LENGTH);
  1386. LRESULT lIdx = SendDlgItemMessage(IDC_VALUE_LIST,
  1387. LB_ADDSTRING,
  1388. 0,
  1389. (LPARAM)(LPCWSTR)szValue);
  1390. if (lIdx != LB_ERR ||
  1391. lIdx != LB_ERRSPACE)
  1392. {
  1393. LRESULT lSetData = SendDlgItemMessage(IDC_VALUE_LIST,
  1394. LB_SETITEMDATA,
  1395. (WPARAM)lIdx,
  1396. (LPARAM)pADsValue);
  1397. if (lSetData == LB_ERR)
  1398. {
  1399. ASSERT(lSetData != LB_ERR);
  1400. continue;
  1401. }
  1402. }
  1403. }
  1404. }
  1405. //
  1406. // The remove button should be disabled until something is selected in the listbox
  1407. //
  1408. GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE);
  1409. SendDlgItemMessage(IDC_VALUE_LIST, LB_SETCURSEL, 0, 0);
  1410. ManageButtonStates();
  1411. //
  1412. // Update the width of the list box
  1413. //
  1414. UpdateListboxHorizontalExtent();
  1415. //
  1416. // NOTE: I have explicitly set the focus so return 0
  1417. //
  1418. return FALSE;
  1419. }
  1420. void CMultiOctetStringEditor::OnOK()
  1421. {
  1422. //
  1423. // Get the values out of the list box
  1424. //
  1425. m_NewValueList.RemoveAll();
  1426. CListBox* pListBox = reinterpret_cast<CListBox*>(GetDlgItem(IDC_VALUE_LIST));
  1427. if (pListBox != NULL)
  1428. {
  1429. int iCount = pListBox->GetCount();
  1430. for (int idx = 0; idx < iCount; idx++)
  1431. {
  1432. CString szNewValue;
  1433. LRESULT lData = SendDlgItemMessage(IDC_VALUE_LIST,
  1434. LB_GETITEMDATA,
  1435. (WPARAM)idx,
  1436. 0);
  1437. if (lData == LB_ERR)
  1438. {
  1439. ASSERT(lData != LB_ERR);
  1440. continue;
  1441. }
  1442. m_NewValueList.AddTail(reinterpret_cast<PADSVALUE>(lData));
  1443. }
  1444. }
  1445. CDialog::OnOK();
  1446. }
  1447. void CMultiOctetStringEditor::OnEditButton()
  1448. {
  1449. LRESULT lIdx = SendDlgItemMessage(IDC_VALUE_LIST, LB_GETCURSEL, 0, 0);
  1450. if (lIdx == LB_ERR)
  1451. {
  1452. ASSERT(lIdx != LB_ERR);
  1453. return;
  1454. }
  1455. LRESULT lData = SendDlgItemMessage(IDC_VALUE_LIST, LB_GETITEMDATA, (WPARAM)lIdx, 0);
  1456. if (lData == LB_ERR)
  1457. {
  1458. ASSERT(lIdx != LB_ERR);
  1459. return;
  1460. }
  1461. PADSVALUE pADsValue = reinterpret_cast<PADSVALUE>(lData);
  1462. if (!pADsValue)
  1463. {
  1464. ASSERT(pADsValue);
  1465. return;
  1466. }
  1467. DS_ATTRIBUTE_EDITORINFO attrEditInfo;
  1468. ::ZeroMemory(&attrEditInfo, sizeof(DS_ATTRIBUTE_EDITORINFO));
  1469. attrEditInfo.pADsValue = pADsValue;
  1470. attrEditInfo.dwNumValues = 1;
  1471. attrEditInfo.lpszClass = (PWSTR)(PCWSTR)m_szClass;
  1472. attrEditInfo.lpszAttribute = (PWSTR)(PCWSTR)m_szAttribute;
  1473. attrEditInfo.bMultivalued = FALSE;
  1474. attrEditInfo.lpfnBind = m_pfnBindingFunction;
  1475. attrEditInfo.lParam = m_lParam;
  1476. COctetStringEditor dlg;
  1477. HRESULT hr = dlg.Initialize(&attrEditInfo);
  1478. if (FAILED(hr))
  1479. {
  1480. ADSIEditErrorMessage(hr, IDS_FAILED_INITIALIZE_EDITOR, MB_OK | MB_ICONEXCLAMATION);
  1481. return;
  1482. }
  1483. if (dlg.DoModal() == IDOK)
  1484. {
  1485. PADSVALUE pNewADsValue = 0;
  1486. DWORD dwNumNewValues = 0;
  1487. hr = dlg.GetNewValue(&pNewADsValue, &dwNumNewValues);
  1488. if (FAILED(hr))
  1489. {
  1490. ADSIEditErrorMessage(hr, IDS_FAILED_GET_NEW_VALUE_EDITOR, MB_OK | MB_ICONEXCLAMATION);
  1491. return;
  1492. }
  1493. ASSERT(pNewADsValue);
  1494. ASSERT(dwNumNewValues == 1);
  1495. CString szNewValue;
  1496. GetStringFromADsValue(pNewADsValue, szNewValue, MAX_OCTET_STRING_VALUE_LENGTH);
  1497. ASSERT(!szNewValue.IsEmpty());
  1498. LRESULT lNewIdx = SendDlgItemMessage(IDC_VALUE_LIST,
  1499. LB_INSERTSTRING,
  1500. lIdx + 1,
  1501. (LPARAM)(PCWSTR)szNewValue);
  1502. if (lNewIdx != LB_ERR)
  1503. {
  1504. //
  1505. // Update the new item and delete the old
  1506. //
  1507. SendDlgItemMessage(IDC_VALUE_LIST, LB_SETITEMDATA, (WPARAM)lNewIdx, (LPARAM)pNewADsValue);
  1508. SendDlgItemMessage(IDC_VALUE_LIST, LB_DELETESTRING, (WPARAM)lIdx, 0);
  1509. }
  1510. else
  1511. {
  1512. //
  1513. // Since we had trouble adding the new item just update the old one. The string
  1514. // will be incorrect but the value will be fine.
  1515. //
  1516. SendDlgItemMessage(IDC_VALUE_LIST, LB_SETITEMDATA, (WPARAM)lIdx, (LPARAM)pNewADsValue);
  1517. }
  1518. }
  1519. }
  1520. void CMultiOctetStringEditor::OnRemoveButton()
  1521. {
  1522. CListBox* pListBox = reinterpret_cast<CListBox*>(GetDlgItem(IDC_VALUE_LIST));
  1523. if (pListBox != NULL)
  1524. {
  1525. int iCurSel = pListBox->GetCurSel();
  1526. if (iCurSel != LB_ERR)
  1527. {
  1528. //
  1529. // Delete the item from the list box
  1530. //
  1531. pListBox->DeleteString(iCurSel);
  1532. }
  1533. }
  1534. //
  1535. // Manage Button States
  1536. //
  1537. ManageButtonStates();
  1538. //
  1539. // Update the width of the list box
  1540. //
  1541. UpdateListboxHorizontalExtent();
  1542. }
  1543. void CMultiOctetStringEditor::OnAddButton()
  1544. {
  1545. DS_ATTRIBUTE_EDITORINFO attrEditInfo;
  1546. ZeroMemory(&attrEditInfo, sizeof(DS_ATTRIBUTE_EDITORINFO));
  1547. attrEditInfo.pADsValue = new ADSVALUE;
  1548. if (attrEditInfo.pADsValue)
  1549. {
  1550. ::ZeroMemory(attrEditInfo.pADsValue, sizeof(ADSVALUE));
  1551. }
  1552. attrEditInfo.pADsValue->dwType = ADSTYPE_OCTET_STRING;
  1553. attrEditInfo.dwNumValues = 0;
  1554. attrEditInfo.lpszClass = (PWSTR)(PCWSTR)m_szClass;
  1555. attrEditInfo.lpszAttribute = (PWSTR)(PCWSTR)m_szAttribute;
  1556. attrEditInfo.bMultivalued = FALSE;
  1557. attrEditInfo.lpfnBind = m_pfnBindingFunction;
  1558. attrEditInfo.lParam = m_lParam;
  1559. COctetStringEditor dlg;
  1560. HRESULT hr = dlg.Initialize(&attrEditInfo);
  1561. if (FAILED(hr))
  1562. {
  1563. ADSIEditErrorMessage(hr, IDS_FAILED_INITIALIZE_EDITOR, MB_OK | MB_ICONEXCLAMATION);
  1564. return;
  1565. }
  1566. if (dlg.DoModal() == IDOK)
  1567. {
  1568. PADSVALUE pNewADsValue = 0;
  1569. DWORD dwNumNewValues = 0;
  1570. hr = dlg.GetNewValue(&pNewADsValue, &dwNumNewValues);
  1571. if (FAILED(hr))
  1572. {
  1573. ADSIEditErrorMessage(hr, IDS_FAILED_GET_NEW_VALUE_EDITOR, MB_OK | MB_ICONEXCLAMATION);
  1574. return;
  1575. }
  1576. ASSERT(pNewADsValue);
  1577. ASSERT(dwNumNewValues == 1);
  1578. CString szNewValue;
  1579. GetStringFromADsValue(pNewADsValue,
  1580. szNewValue,
  1581. MAX_OCTET_STRING_VALUE_LENGTH);
  1582. if (!szNewValue.IsEmpty())
  1583. {
  1584. LRESULT lNewIdx = SendDlgItemMessage(IDC_VALUE_LIST,
  1585. LB_ADDSTRING,
  1586. 0,
  1587. (WPARAM)(PCWSTR)szNewValue);
  1588. if (lNewIdx != LB_ERR)
  1589. {
  1590. SendDlgItemMessage(IDC_VALUE_LIST, LB_SETITEMDATA, (WPARAM)lNewIdx, (LPARAM)pNewADsValue);
  1591. }
  1592. }
  1593. }
  1594. }
  1595. void CMultiOctetStringEditor::ManageButtonStates()
  1596. {
  1597. LRESULT lSelection = SendDlgItemMessage(IDC_VALUE_LIST, LB_GETCURSEL, 0, 0);
  1598. if (lSelection != LB_ERR)
  1599. {
  1600. GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(TRUE);
  1601. GetDlgItem(IDC_EDIT_BUTTON)->EnableWindow(TRUE);
  1602. }
  1603. else
  1604. {
  1605. GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE);
  1606. GetDlgItem(IDC_EDIT_BUTTON)->EnableWindow(FALSE);
  1607. }
  1608. }
  1609. void CMultiOctetStringEditor::OnListSelChange()
  1610. {
  1611. ManageButtonStates();
  1612. }
  1613. void CMultiOctetStringEditor::UpdateListboxHorizontalExtent()
  1614. {
  1615. //
  1616. // Note if the size passed to SetHorizontalExtent is less than the width of the control
  1617. // then the scroll bar will be removed
  1618. //
  1619. int nHorzExtent = 0;
  1620. CListBox* pListBox = reinterpret_cast<CListBox*>(GetDlgItem(IDC_VALUE_LIST));
  1621. if (pListBox != NULL)
  1622. {
  1623. CClientDC dc(pListBox);
  1624. int nItems = pListBox->GetCount();
  1625. for (int i=0; i < nItems; i++)
  1626. {
  1627. TEXTMETRIC tm;
  1628. VERIFY(dc.GetTextMetrics(&tm));
  1629. CString szBuffer;
  1630. pListBox->GetText(i, szBuffer);
  1631. CSize ext = dc.GetTextExtent(szBuffer,szBuffer.GetLength());
  1632. nHorzExtent = max(ext.cx ,nHorzExtent);
  1633. }
  1634. pListBox->SetHorizontalExtent(nHorzExtent);
  1635. }
  1636. }
  1637. HRESULT CMultiOctetStringEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo)
  1638. {
  1639. HRESULT hr = S_OK;
  1640. if (SUCCEEDED(CValueEditDialog::Initialize(pAttributeEditorInfo)))
  1641. {
  1642. if (pAttributeEditorInfo->dwNumValues > 0 &&
  1643. pAttributeEditorInfo->pADsValue != NULL)
  1644. {
  1645. for (int idx = 0; idx < pAttributeEditorInfo->dwNumValues; idx++)
  1646. {
  1647. switch (pAttributeEditorInfo->pADsValue[idx].dwType)
  1648. {
  1649. case ADSTYPE_OCTET_STRING:
  1650. m_OldValueList.AddTail(&(pAttributeEditorInfo->pADsValue[idx]));
  1651. break;
  1652. default:
  1653. ASSERT(FALSE);
  1654. break;
  1655. }
  1656. }
  1657. }
  1658. }
  1659. return hr;
  1660. }
  1661. HRESULT CMultiOctetStringEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues)
  1662. {
  1663. HRESULT hr = S_OK;
  1664. if (!ppADsValue ||
  1665. !pdwNumValues)
  1666. {
  1667. return E_OUTOFMEMORY;
  1668. }
  1669. int iCount = m_NewValueList.GetCount();
  1670. if (iCount == 0)
  1671. {
  1672. *ppADsValue = 0;
  1673. *pdwNumValues = 0;
  1674. }
  1675. else
  1676. {
  1677. *ppADsValue = new ADSVALUE[iCount];
  1678. if (*ppADsValue)
  1679. {
  1680. *pdwNumValues = iCount;
  1681. int idx = 0;
  1682. POSITION pos = m_NewValueList.GetHeadPosition();
  1683. while (pos)
  1684. {
  1685. PADSVALUE pADsValue = m_NewValueList.GetNext(pos);
  1686. (*ppADsValue)[idx].dwType = m_pOldADsValue->dwType;
  1687. switch (m_pOldADsValue->dwType)
  1688. {
  1689. case ADSTYPE_OCTET_STRING:
  1690. (*ppADsValue)[idx].OctetString.dwLength = pADsValue->OctetString.dwLength;
  1691. (*ppADsValue)[idx].OctetString.lpValue = new BYTE[pADsValue->OctetString.dwLength];
  1692. if ((*ppADsValue)[idx].OctetString.lpValue)
  1693. {
  1694. memcpy((*ppADsValue)[idx].OctetString.lpValue,
  1695. pADsValue->OctetString.lpValue,
  1696. pADsValue->OctetString.dwLength);
  1697. }
  1698. else
  1699. {
  1700. for (int i = 0; i < idx; i++)
  1701. {
  1702. if ((*ppADsValue)[i].OctetString.lpValue)
  1703. {
  1704. delete[] (*ppADsValue)[i].OctetString.lpValue;
  1705. (*ppADsValue)[i].OctetString.lpValue = 0;
  1706. }
  1707. }
  1708. delete[] *ppADsValue;
  1709. *ppADsValue = 0;
  1710. *pdwNumValues = 0;
  1711. hr = E_OUTOFMEMORY;
  1712. }
  1713. break;
  1714. default:
  1715. ASSERT(FALSE);
  1716. for (int i = 0; i < idx; i++)
  1717. {
  1718. if ((*ppADsValue)[i].OctetString.lpValue)
  1719. {
  1720. delete[] (*ppADsValue)[i].OctetString.lpValue;
  1721. (*ppADsValue)[i].OctetString.lpValue = 0;
  1722. }
  1723. }
  1724. delete[] *ppADsValue;
  1725. *ppADsValue = 0;
  1726. *pdwNumValues = 0;
  1727. hr = E_FAIL;
  1728. break;
  1729. }
  1730. if (FAILED(hr))
  1731. {
  1732. return hr;
  1733. }
  1734. idx++;
  1735. }
  1736. }
  1737. else
  1738. {
  1739. *ppADsValue = NULL;
  1740. *pdwNumValues = 0;
  1741. hr = E_OUTOFMEMORY;
  1742. }
  1743. }
  1744. return hr;
  1745. }
  1746. ///////////////////////////////////////////////////////////////////////////////////////
  1747. // CAttributeEditorPropertyPage
  1748. BEGIN_MESSAGE_MAP(CAttributeEditorPropertyPage, CPropertyPage)
  1749. ON_BN_CLICKED(IDC_MANDATORY_CHECK, OnMandatoryCheck)
  1750. ON_BN_CLICKED(IDC_OPTIONAL_CHECK, OnOptionalCheck)
  1751. ON_BN_CLICKED(IDC_SET_CHECK, OnValueSetCheck)
  1752. ON_BN_CLICKED(IDC_ATTR_EDIT_BUTTON,OnEditAttribute)
  1753. ON_NOTIFY(LVN_ITEMACTIVATE, IDC_ATTRIBUTE_LIST, OnNotifyEditAttribute)
  1754. ON_NOTIFY(LVN_ITEMCHANGED, IDC_ATTRIBUTE_LIST, OnListItemChanged)
  1755. ON_NOTIFY(LVN_COLUMNCLICK, IDC_ATTRIBUTE_LIST, OnSortList)
  1756. END_MESSAGE_MAP()
  1757. CAttributeEditorPropertyPage::CAttributeEditorPropertyPage(IADs* pIADs,
  1758. IADsClass* pIADsClass,
  1759. LPDS_ATTREDITOR_BINDINGINFO pBindingInfo,
  1760. CADSIEditPropertyPageHolder* pHolder)
  1761. : CPropertyPage(IDD_ATTRIBUTE_EDITOR_DIALOG)
  1762. {
  1763. m_spIADs = pIADs;
  1764. m_spIADsClass = pIADsClass;
  1765. m_bMandatory = TRUE;
  1766. m_bOptional = TRUE;
  1767. m_bSet = FALSE;
  1768. m_nSortColumn = 0;
  1769. ASSERT(pBindingInfo != NULL);
  1770. ASSERT(pBindingInfo->dwSize == sizeof(DS_ATTREDITOR_BINDINGINFO));
  1771. ASSERT(pBindingInfo->lpfnBind != NULL);
  1772. ASSERT(pBindingInfo->lpszProviderServer != NULL);
  1773. m_szPrefix = pBindingInfo->lpszProviderServer;
  1774. m_pfnBind = pBindingInfo->lpfnBind;
  1775. m_BindLPARAM = pBindingInfo->lParam;
  1776. m_dwBindFlags = pBindingInfo->dwFlags;
  1777. m_pHolder = pHolder;
  1778. ASSERT(m_pHolder);
  1779. }
  1780. CAttributeEditorPropertyPage::~CAttributeEditorPropertyPage()
  1781. {
  1782. }
  1783. BOOL CAttributeEditorPropertyPage::OnInitDialog()
  1784. {
  1785. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1786. CWaitCursor cursor;
  1787. // Set the hwnd in the property page holder so that we can
  1788. // be activated when necessary
  1789. m_pHolder->SetSheetWindow(GetParent()->GetSafeHwnd());
  1790. ((CButton*)GetDlgItem(IDC_MANDATORY_CHECK))->SetCheck(TRUE);
  1791. ((CButton*)GetDlgItem(IDC_OPTIONAL_CHECK))->SetCheck(TRUE);
  1792. ((CButton*)GetDlgItem(IDC_SET_CHECK))->SetCheck(FALSE);
  1793. GetDlgItem(IDC_ATTR_EDIT_BUTTON)->EnableWindow(FALSE);
  1794. HRESULT hr = GetSchemaNamingContext();
  1795. ShowListCtrl();
  1796. hr = RetrieveAttributes();
  1797. if (FAILED(hr))
  1798. {
  1799. TRACE(_T("OnInitDialog() : error returned from RetrieveAttributes() = 0x%x\n"), hr);
  1800. }
  1801. CComBSTR bstr;
  1802. hr = m_spIADs->get_Class(&bstr);
  1803. if (FAILED(hr))
  1804. {
  1805. TRACE(_T("OnInitDialog() : error returned from m_pIADs->get_Class() = 0x%x\n"), hr);
  1806. }
  1807. else
  1808. {
  1809. m_szClass = bstr;
  1810. }
  1811. FillListControl();
  1812. return FALSE;
  1813. }
  1814. HRESULT CAttributeEditorPropertyPage::GetSchemaNamingContext()
  1815. {
  1816. HRESULT hr = S_OK;
  1817. CComPtr<IADs> spIADs;
  1818. CString m_szPath = m_szPrefix + _T("RootDSE");
  1819. hr = m_pfnBind(m_szPath,
  1820. ADS_SECURE_AUTHENTICATION,
  1821. IID_IADs,
  1822. (PVOID*)&spIADs,
  1823. m_BindLPARAM);
  1824. if (SUCCEEDED(hr))
  1825. {
  1826. CComVariant var;
  1827. hr = spIADs->Get(L"schemaNamingContext", &var);
  1828. if (SUCCEEDED(hr))
  1829. {
  1830. m_szSchemaNamingContext = var.bstrVal;
  1831. }
  1832. }
  1833. m_szSchemaNamingContext = m_szPrefix + m_szSchemaNamingContext;
  1834. return hr;
  1835. }
  1836. BOOL CAttributeEditorPropertyPage::OnApply()
  1837. {
  1838. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1839. if (m_AttrList.HasDirty())
  1840. {
  1841. CComPtr<IDirectoryObject> spDirObject;
  1842. // bind to object with authentication
  1843. //
  1844. HRESULT hr = S_OK;
  1845. hr = m_spIADs->QueryInterface(IID_IDirectoryObject, (PVOID*) &spDirObject);
  1846. if (FAILED(hr))
  1847. {
  1848. AfxMessageBox(L"Failed to QI the IDirectoryObject from the IADs.");
  1849. return FALSE;
  1850. }
  1851. // Change or add values to ADSI cache that have changed
  1852. //
  1853. hr = CADSIAttribute::SetValuesInDS(&m_AttrList, spDirObject);
  1854. if (FAILED(hr))
  1855. {
  1856. ADSIEditErrorMessage(hr);
  1857. //
  1858. // Instead of removing all the attributes we need to query for the ones that failed
  1859. // or something to that effect.
  1860. //
  1861. // m_AttrList.RemoveAllAttr();
  1862. return FALSE;
  1863. }
  1864. }
  1865. return TRUE;
  1866. }
  1867. void CAttributeEditorPropertyPage::OnMandatoryCheck()
  1868. {
  1869. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1870. TRACE(_T("OnMandatoryCheck()\n"));
  1871. m_bMandatory = ((CButton*)GetDlgItem(IDC_MANDATORY_CHECK))->GetCheck();
  1872. FillListControl();
  1873. }
  1874. void CAttributeEditorPropertyPage::OnOptionalCheck()
  1875. {
  1876. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1877. TRACE(_T("OnOptionalCheck()\n"));
  1878. m_bOptional = ((CButton*)GetDlgItem(IDC_OPTIONAL_CHECK))->GetCheck();
  1879. FillListControl();
  1880. }
  1881. void CAttributeEditorPropertyPage::OnValueSetCheck()
  1882. {
  1883. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1884. TRACE(_T("OnValueSetCheck()\n"));
  1885. m_bSet = ((CButton*)GetDlgItem(IDC_SET_CHECK))->GetCheck();
  1886. FillListControl();
  1887. }
  1888. //
  1889. // Callback function used by CListCtrl::SortItems the items by the column that was clicked
  1890. //
  1891. static int CALLBACK CompareAttrColumns(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  1892. {
  1893. CAttributeEditorPropertyPage* pProppage = reinterpret_cast<CAttributeEditorPropertyPage*>(lParamSort);
  1894. if (!pProppage)
  1895. {
  1896. ASSERT(pProppage);
  1897. return 0;
  1898. }
  1899. UINT nColumn = pProppage->GetSortColumn();
  1900. CListCtrl* pListCtrl = (CListCtrl*)pProppage->GetDlgItem(IDC_ATTRIBUTE_LIST);
  1901. if (!pListCtrl)
  1902. {
  1903. ASSERT(pListCtrl);
  1904. return 0;
  1905. }
  1906. //
  1907. // Since lParam1 and lParam2 are pointers to the data we have to search for each item
  1908. // in the list and remember their index
  1909. //
  1910. int iItem1 = -1;
  1911. int iItem2 = -1;
  1912. LVFINDINFO findInfo;
  1913. ZeroMemory(&findInfo, sizeof(LVFINDINFO));
  1914. findInfo.flags = LVFI_PARAM;
  1915. findInfo.lParam = lParam1;
  1916. iItem1 = pListCtrl->FindItem(&findInfo);
  1917. findInfo.lParam = lParam2;
  1918. iItem2 = pListCtrl->FindItem(&findInfo);
  1919. //
  1920. // Put any items with values above those that don't have values
  1921. //
  1922. int iRetVal = 0;
  1923. if (iItem1 != -1 &&
  1924. iItem2 == -1)
  1925. {
  1926. iRetVal = -1;
  1927. }
  1928. else if (iItem1 == -1 &&
  1929. iItem2 != -1)
  1930. {
  1931. iRetVal = 1;
  1932. }
  1933. else if (iItem1 == -1 &&
  1934. iItem2 == -1)
  1935. {
  1936. iRetVal = 0;
  1937. }
  1938. else
  1939. {
  1940. CString szItem1 = pListCtrl->GetItemText(iItem1, nColumn);
  1941. CString szItem2 = pListCtrl->GetItemText(iItem2, nColumn);
  1942. //
  1943. // Have to put this in so that empty strings end up at the bottom
  1944. //
  1945. if (szItem1.IsEmpty() && !szItem2.IsEmpty())
  1946. {
  1947. iRetVal = 1;
  1948. }
  1949. else if (!szItem1.IsEmpty() && szItem2.IsEmpty())
  1950. {
  1951. iRetVal = -1;
  1952. }
  1953. else
  1954. {
  1955. iRetVal = _wcsicmp(szItem1, szItem2);
  1956. }
  1957. }
  1958. return iRetVal;
  1959. }
  1960. void CAttributeEditorPropertyPage::OnSortList(NMHDR* pNotifyStruct, LRESULT* result)
  1961. {
  1962. if (!result ||
  1963. !pNotifyStruct)
  1964. {
  1965. return;
  1966. }
  1967. *result = 0;
  1968. //
  1969. // Get the list view notify struct
  1970. //
  1971. LPNMLISTVIEW pnmv = (LPNMLISTVIEW)pNotifyStruct;
  1972. if (!pnmv)
  1973. {
  1974. return;
  1975. }
  1976. //
  1977. // Right now I only have 3 columns
  1978. //
  1979. if (pnmv->iSubItem < 0 ||
  1980. pnmv->iSubItem >= 3)
  1981. {
  1982. return;
  1983. }
  1984. //
  1985. // Store the sort column
  1986. //
  1987. m_nSortColumn = pnmv->iSubItem;
  1988. CListCtrl* pAttrListCtrl = (CListCtrl*)GetDlgItem(IDC_ATTRIBUTE_LIST);
  1989. ASSERT(pAttrListCtrl);
  1990. pAttrListCtrl->SortItems(CompareAttrColumns, reinterpret_cast<LPARAM>(this));
  1991. }
  1992. void CAttributeEditorPropertyPage::OnListItemChanged(NMHDR* /*pNotifyStruct*/, LRESULT* result)
  1993. {
  1994. if (!result)
  1995. {
  1996. return;
  1997. }
  1998. *result = 0;
  1999. SetEditButton();
  2000. }
  2001. void CAttributeEditorPropertyPage::SetEditButton()
  2002. {
  2003. //
  2004. // Enable the edit button if something is selected in the ListCtrl
  2005. //
  2006. BOOL bEnableEdit = FALSE;
  2007. if (!(m_dwBindFlags & DSATTR_EDITOR_ROOTDSE))
  2008. {
  2009. CListCtrl* pAttrListCtrl = (CListCtrl*)GetDlgItem(IDC_ATTRIBUTE_LIST);
  2010. ASSERT(pAttrListCtrl != NULL);
  2011. int nSelectedItem = pAttrListCtrl->GetNextItem(-1, LVIS_SELECTED);
  2012. if (nSelectedItem != -1)
  2013. {
  2014. bEnableEdit = TRUE;
  2015. }
  2016. }
  2017. GetDlgItem(IDC_ATTR_EDIT_BUTTON)->EnableWindow(bEnableEdit);
  2018. }
  2019. void CAttributeEditorPropertyPage::OnNotifyEditAttribute(NMHDR* pNotifyStruct, LRESULT* result)
  2020. {
  2021. if (result == NULL ||
  2022. pNotifyStruct == NULL)
  2023. {
  2024. return;
  2025. }
  2026. //
  2027. // Don't allow editing on the RootDSE
  2028. //
  2029. if (m_dwBindFlags & DSATTR_EDITOR_ROOTDSE)
  2030. {
  2031. *result = 0;
  2032. return;
  2033. }
  2034. LPNMITEMACTIVATE pnmia = (LPNMITEMACTIVATE)pNotifyStruct;
  2035. ASSERT(pnmia != NULL);
  2036. if (pnmia != NULL)
  2037. {
  2038. int iSelectedItem = pnmia->iItem;
  2039. if (iSelectedItem != -1)
  2040. {
  2041. CADSIAttribute* pSelectedAttr = GetAttributeFromList(iSelectedItem);
  2042. if (pSelectedAttr != NULL)
  2043. {
  2044. EditAttribute(pSelectedAttr);
  2045. }
  2046. else
  2047. {
  2048. //
  2049. // REVIEW_JEFFJON : display an appropriate error message
  2050. //
  2051. }
  2052. }
  2053. }
  2054. *result = 0;
  2055. }
  2056. void CAttributeEditorPropertyPage::OnEditAttribute()
  2057. {
  2058. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2059. TRACE(_T("OnEditAttribute()\n"));
  2060. CListCtrl* pAttrListCtrl = (CListCtrl*)GetDlgItem(IDC_ATTRIBUTE_LIST);
  2061. ASSERT(pAttrListCtrl != NULL);
  2062. int nSelectedItem = pAttrListCtrl->GetNextItem(-1, LVIS_SELECTED);
  2063. if (nSelectedItem == -1)
  2064. {
  2065. return;
  2066. }
  2067. CADSIAttribute* pSelectedAttr = GetAttributeFromList(nSelectedItem);
  2068. ASSERT(pSelectedAttr != NULL);
  2069. EditAttribute(pSelectedAttr);
  2070. }
  2071. void CAttributeEditorPropertyPage::EditAttribute(CADSIAttribute* pSelectedAttr)
  2072. {
  2073. HRESULT hr = S_OK;
  2074. //
  2075. // Retrieve all necessary info for initializing the appropriate editor
  2076. //
  2077. LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo = NULL;
  2078. BOOL bOwnValueMemory = FALSE;
  2079. GetAttributeInfo(pSelectedAttr, &pAttributeEditorInfo, &bOwnValueMemory);
  2080. if (pAttributeEditorInfo == NULL)
  2081. {
  2082. ADSIEditMessageBox(IDS_NO_ATTRIBUTE_INFO, MB_OK);
  2083. return;
  2084. }
  2085. //
  2086. // Obtain the editor from the attribute and syntax map
  2087. //
  2088. CValueEditDialog* pEditorDialog = RetrieveEditor(pAttributeEditorInfo);
  2089. if (pEditorDialog)
  2090. {
  2091. hr = pEditorDialog->Initialize(pAttributeEditorInfo);
  2092. if (SUCCEEDED(hr))
  2093. {
  2094. if (pEditorDialog->DoModal() == IDOK)
  2095. {
  2096. PADSVALUE pNewValue = 0;
  2097. DWORD dwNumValues = 0;
  2098. hr = pEditorDialog->GetNewValue(&pNewValue, &dwNumValues);
  2099. if (SUCCEEDED(hr))
  2100. {
  2101. //
  2102. // Do what ever needs done with the new value
  2103. //
  2104. hr = pSelectedAttr->SetValues(pNewValue, dwNumValues);
  2105. //
  2106. // REVIEW_JEFFJON : what should be done here if that failed?
  2107. //
  2108. pSelectedAttr->SetDirty(TRUE);
  2109. CListCtrl* pAttrListCtrl = (CListCtrl*)GetDlgItem(IDC_ATTRIBUTE_LIST);
  2110. ASSERT(pAttrListCtrl != NULL);
  2111. int nSelectedItem = pAttrListCtrl->GetNextItem(-1, LVIS_SELECTED);
  2112. if (nSelectedItem != -1)
  2113. {
  2114. if (dwNumValues > 0)
  2115. {
  2116. //
  2117. // Get the new values (limit each individual value to MAX_OCTET_STRING_VALUE_LENGTH characters)
  2118. //
  2119. CStringList szValuesList;
  2120. pSelectedAttr->GetValues(szValuesList, MAX_OCTET_STRING_VALUE_LENGTH);
  2121. CString szCombinedString;
  2122. POSITION pos = szValuesList.GetHeadPosition();
  2123. while (pos != NULL)
  2124. {
  2125. CString szTemp = szValuesList.GetNext(pos);
  2126. szCombinedString += szTemp;
  2127. if (pos != NULL)
  2128. {
  2129. szCombinedString += L";";
  2130. }
  2131. }
  2132. VERIFY(-1 != pAttrListCtrl->SetItemText(nSelectedItem, 2, szCombinedString));
  2133. }
  2134. else
  2135. {
  2136. CString szNotSet;
  2137. VERIFY(szNotSet.LoadString(IDS_ATTR_NOTSET));
  2138. VERIFY(-1 != pAttrListCtrl->SetItemText(nSelectedItem, 2, szNotSet));
  2139. }
  2140. }
  2141. SetModified();
  2142. }
  2143. else
  2144. {
  2145. //
  2146. // REVIEW_JEFFJON : handle the GetNewValue() failure
  2147. //
  2148. ASSERT(FALSE);
  2149. ADSIEditErrorMessage(hr);
  2150. }
  2151. }
  2152. }
  2153. else
  2154. {
  2155. //
  2156. // REVIEW_JEFFJON : Handle the error Initialize
  2157. //
  2158. ASSERT(FALSE);
  2159. ADSIEditErrorMessage(hr);
  2160. }
  2161. if (pEditorDialog)
  2162. {
  2163. delete pEditorDialog;
  2164. pEditorDialog = 0;
  2165. }
  2166. }
  2167. else
  2168. {
  2169. //
  2170. // Unable to retrieve an appropriate editor for this attribute
  2171. //
  2172. ADSIEditMessageBox(IDS_NO_EDITOR, MB_OK);
  2173. }
  2174. if (pAttributeEditorInfo)
  2175. {
  2176. if (pAttributeEditorInfo->lpszAttribute)
  2177. {
  2178. delete[] pAttributeEditorInfo->lpszAttribute;
  2179. }
  2180. if (pAttributeEditorInfo->lpszClass)
  2181. {
  2182. delete[] pAttributeEditorInfo->lpszClass;
  2183. }
  2184. if (pAttributeEditorInfo->pADsValue && bOwnValueMemory)
  2185. {
  2186. delete pAttributeEditorInfo->pADsValue;
  2187. pAttributeEditorInfo->pADsValue = 0;
  2188. }
  2189. delete pAttributeEditorInfo;
  2190. pAttributeEditorInfo = 0;
  2191. }
  2192. }
  2193. CADSIAttribute* CAttributeEditorPropertyPage::GetAttributeFromList(int iSelectedItem)
  2194. {
  2195. if (iSelectedItem == -1)
  2196. {
  2197. return NULL;
  2198. }
  2199. CListCtrl* pAttrListCtrl = (CListCtrl*)GetDlgItem(IDC_ATTRIBUTE_LIST);
  2200. ASSERT(pAttrListCtrl != NULL);
  2201. return (CADSIAttribute*)pAttrListCtrl->GetItemData(iSelectedItem);
  2202. }
  2203. void CAttributeEditorPropertyPage::GetAttributeInfo(CADSIAttribute* pAttr,
  2204. LPDS_ATTRIBUTE_EDITORINFO* ppAttributeEditorInfo,
  2205. BOOL* pbOwnValueMemory)
  2206. {
  2207. //
  2208. // Get the attribute to be edited
  2209. //
  2210. CString szAttribute = _T("");
  2211. pAttr->GetProperty(szAttribute);
  2212. //
  2213. // Get the type and whether it is multi-valued or not by the syntax
  2214. // of the attribute
  2215. //
  2216. CString szSyntax;
  2217. BOOL bMultiValued = FALSE;
  2218. ADSTYPE adsType = RetrieveADsTypeFromSyntax(szAttribute, &bMultiValued, szSyntax);
  2219. *pbOwnValueMemory = FALSE;
  2220. DWORD dwNumValues = 0;
  2221. PADSVALUE pADsValue = pAttr->GetADsValues();
  2222. if (!pADsValue)
  2223. {
  2224. //
  2225. // Value for attribute was not set so we have to
  2226. // create an empty ADSVALUE to pass the type
  2227. //
  2228. pADsValue = new ADSVALUE;
  2229. ASSERT(pADsValue != NULL);
  2230. pADsValue->dwType = adsType;
  2231. dwNumValues = 0;
  2232. *pbOwnValueMemory = TRUE;
  2233. }
  2234. else
  2235. {
  2236. //
  2237. // Get the number of values in the attribute
  2238. //
  2239. dwNumValues = pAttr->GetNumValues();
  2240. }
  2241. //
  2242. // Figure out how much space we need
  2243. //
  2244. DWORD dwStructSize = sizeof(DS_ATTRIBUTE_EDITORINFO);
  2245. DWORD dwClassSize = m_szClass.GetLength() + 1;
  2246. DWORD dwAttrSize = szAttribute.GetLength() + 1;
  2247. try
  2248. {
  2249. *ppAttributeEditorInfo = new DS_ATTRIBUTE_EDITORINFO;
  2250. ASSERT(*ppAttributeEditorInfo != NULL);
  2251. if (*ppAttributeEditorInfo != NULL)
  2252. {
  2253. (*ppAttributeEditorInfo)->lpszClass = new WCHAR[dwClassSize];
  2254. if (m_szClass != _T(""))
  2255. {
  2256. wcscpy((*ppAttributeEditorInfo)->lpszClass, m_szClass);
  2257. }
  2258. (*ppAttributeEditorInfo)->lpszAttribute = new WCHAR[dwAttrSize];
  2259. if (szAttribute != _T(""))
  2260. {
  2261. wcscpy((*ppAttributeEditorInfo)->lpszAttribute, szAttribute);
  2262. }
  2263. (*ppAttributeEditorInfo)->adsType = adsType;
  2264. (*ppAttributeEditorInfo)->bMultivalued = bMultiValued;
  2265. (*ppAttributeEditorInfo)->dwNumValues = dwNumValues;
  2266. (*ppAttributeEditorInfo)->pADsValue = pADsValue;
  2267. (*ppAttributeEditorInfo)->dwSize = sizeof(DS_ATTRIBUTE_EDITORINFO);
  2268. }
  2269. else
  2270. {
  2271. delete pADsValue;
  2272. pADsValue = 0;
  2273. }
  2274. }
  2275. catch (...)
  2276. {
  2277. if (pADsValue)
  2278. {
  2279. delete pADsValue;
  2280. pADsValue = 0;
  2281. }
  2282. }
  2283. }
  2284. void CAttributeEditorPropertyPage::ShowListCtrl()
  2285. {
  2286. CListCtrl* pAttrListCtrl = (CListCtrl*)GetDlgItem(IDC_ATTRIBUTE_LIST);
  2287. ASSERT(pAttrListCtrl != NULL);
  2288. // Set full row select
  2289. ListView_SetExtendedListViewStyle(
  2290. pAttrListCtrl->GetSafeHwnd(),
  2291. LVS_EX_FULLROWSELECT);
  2292. //
  2293. // Insert the Attribute column
  2294. //
  2295. CString szAttribute;
  2296. VERIFY(szAttribute.LoadString(IDS_ATTR_COL_ATTRIBUTE));
  2297. int iRet = pAttrListCtrl->InsertColumn(0, szAttribute, LVCFMT_LEFT, 120);
  2298. if (iRet == -1)
  2299. {
  2300. TRACE(_T("Failed to insert the \"Attribute\" column.\n"));
  2301. }
  2302. //
  2303. // Insert the Syntax column
  2304. // This column will be hidden by default
  2305. //
  2306. CString szSyntax;
  2307. VERIFY(szSyntax.LoadString(IDS_ATTR_COL_SYNTAX));
  2308. iRet = pAttrListCtrl->InsertColumn(1, szSyntax, LVCFMT_LEFT, 90);
  2309. if (iRet == -1)
  2310. {
  2311. TRACE(_T("Failed to insert the \"Syntax\" column.\n"));
  2312. }
  2313. //
  2314. // Insert the Value column
  2315. //
  2316. CString szValue;
  2317. VERIFY(szValue.LoadString(IDS_ATTR_COL_VALUE));
  2318. iRet = pAttrListCtrl->InsertColumn(2, szValue, LVCFMT_LEFT, 400);
  2319. if (iRet == -1)
  2320. {
  2321. TRACE(_T("Failed to insert the \"Value\" column.\n"));
  2322. }
  2323. }
  2324. void CAttributeEditorPropertyPage::FillListControl()
  2325. {
  2326. TRACE(_T("FillListControl()\n"));
  2327. CListCtrl* pAttrListCtrl = (CListCtrl*)GetDlgItem(IDC_ATTRIBUTE_LIST);
  2328. ASSERT(pAttrListCtrl != NULL);
  2329. CString szNotSet;
  2330. VERIFY(szNotSet.LoadString(IDS_ATTR_NOTSET));
  2331. //
  2332. // Clear the list control
  2333. //
  2334. pAttrListCtrl->DeleteAllItems();
  2335. //
  2336. // Add the attributes and their values into the list control
  2337. //
  2338. UINT nState = 0;
  2339. int nIndex = 0;
  2340. POSITION pos = m_AttrList.GetHeadPosition();
  2341. while (pos != NULL)
  2342. {
  2343. CADSIAttribute* pAttr = m_AttrList.GetNext(pos);
  2344. ASSERT(pAttr != NULL);
  2345. CString szProperty;
  2346. pAttr->GetProperty(szProperty);
  2347. //
  2348. // Don't add the nTSecurityDescriptor, we use the ACL UI instead
  2349. //
  2350. if (szProperty.CompareNoCase(L"nTSecurityDescriptor") == 0)
  2351. {
  2352. continue;
  2353. }
  2354. if (m_dwBindFlags & DSATTR_EDITOR_ROOTDSE)
  2355. {
  2356. int iNewIndex = pAttrListCtrl->InsertItem(LVIF_TEXT | LVIF_PARAM, nIndex,
  2357. szProperty, nState, 0, 0, (LPARAM)pAttr);
  2358. if (iNewIndex != -1)
  2359. {
  2360. CString szValue;
  2361. szValue = m_RootDSEValueList.GetAt(m_RootDSEValueList.FindIndex(nIndex));
  2362. if (!szValue.IsEmpty())
  2363. {
  2364. VERIFY(-1 != pAttrListCtrl->SetItemText(iNewIndex, 2, szValue));
  2365. }
  2366. else
  2367. {
  2368. VERIFY(-1 != pAttrListCtrl->SetItemText(iNewIndex, 2, szNotSet));
  2369. }
  2370. }
  2371. nIndex++;
  2372. }
  2373. else // not RootDSE
  2374. {
  2375. if ((m_bMandatory && pAttr->IsMandatory()) || (m_bOptional && !pAttr->IsMandatory()))
  2376. {
  2377. if (!m_bSet || (m_bSet && pAttr->IsValueSet()))
  2378. {
  2379. int iNewIndex = pAttrListCtrl->InsertItem(LVIF_TEXT | LVIF_PARAM, nIndex,
  2380. szProperty, nState, 0, 0, (LPARAM)pAttr);
  2381. if (iNewIndex != -1)
  2382. {
  2383. // Insert the syntax
  2384. VERIFY(-1 != pAttrListCtrl->SetItemText(iNewIndex, 1, pAttr->GetSyntax()));
  2385. // Insert the value
  2386. if (pAttr->IsValueSet())
  2387. {
  2388. //
  2389. // Retrieve the values
  2390. //
  2391. CStringList szValuesList;
  2392. pAttr->GetValues(szValuesList);
  2393. CString szCombinedString;
  2394. POSITION posList = szValuesList.GetHeadPosition();
  2395. while (posList)
  2396. {
  2397. CString szTemp = szValuesList.GetNext(posList);
  2398. szCombinedString += szTemp;
  2399. if (posList)
  2400. {
  2401. szCombinedString += L";";
  2402. }
  2403. }
  2404. VERIFY(-1 != pAttrListCtrl->SetItemText(iNewIndex, 2, szCombinedString));
  2405. }
  2406. else
  2407. {
  2408. VERIFY(-1 != pAttrListCtrl->SetItemText(iNewIndex, 2, szNotSet));
  2409. }
  2410. }
  2411. nIndex++;
  2412. }
  2413. }
  2414. }
  2415. }
  2416. TRACE(_T("Added %u properties\n"), nIndex);
  2417. //
  2418. // Select the first attribute in the list
  2419. //
  2420. pAttrListCtrl->SetItemState(0, 1, LVIS_SELECTED);
  2421. SetEditButton();
  2422. }
  2423. HRESULT CAttributeEditorPropertyPage::RetrieveAttributes()
  2424. {
  2425. TRACE(_T("RetrieveAttributes()\n"));
  2426. HRESULT hr = S_OK;
  2427. CWaitCursor cursor;
  2428. if (m_dwBindFlags & DSATTR_EDITOR_ROOTDSE)
  2429. {
  2430. CStringList sMandList;
  2431. m_spIADs->GetInfo();
  2432. CComPtr<IADsPropertyList> spPropList;
  2433. hr = m_spIADs->QueryInterface(IID_IADsPropertyList, (PVOID*)&spPropList);
  2434. if (SUCCEEDED(hr))
  2435. {
  2436. LONG lCount = 0;
  2437. hr = spPropList->get_PropertyCount(&lCount);
  2438. if (SUCCEEDED(hr) && lCount > 0)
  2439. {
  2440. CComVariant var;
  2441. while (hr == S_OK)
  2442. {
  2443. hr = spPropList->Next(&var);
  2444. if (hr == S_OK)
  2445. {
  2446. ASSERT(var.vt == VT_DISPATCH);
  2447. CComPtr<IADsPropertyEntry> spEntry;
  2448. hr = V_DISPATCH(&var)->QueryInterface(IID_IADsPropertyEntry,
  2449. (PVOID*)&spEntry);
  2450. if (SUCCEEDED(hr))
  2451. {
  2452. CComBSTR bstrName;
  2453. hr = spEntry->get_Name(&bstrName);
  2454. if (SUCCEEDED(hr))
  2455. {
  2456. sMandList.AddTail(bstrName);
  2457. }
  2458. }
  2459. }
  2460. }
  2461. }
  2462. }
  2463. hr = CreateAttributeList(sMandList, TRUE);
  2464. }
  2465. else
  2466. {
  2467. //
  2468. // Retrieve mandatory properties
  2469. //
  2470. CStringList sMandList;
  2471. VARIANT varMand;
  2472. VariantInit(&varMand);
  2473. hr = m_spIADsClass->get_MandatoryProperties(&varMand);
  2474. if (SUCCEEDED(hr))
  2475. {
  2476. VariantToStringList( varMand, sMandList );
  2477. }
  2478. VariantClear(&varMand);
  2479. //
  2480. // Retrieve optional properties
  2481. //
  2482. CStringList sOptionalList;
  2483. VARIANT varOpt;
  2484. VariantInit(&varOpt);
  2485. hr = m_spIADsClass->get_OptionalProperties(&varOpt);
  2486. if (SUCCEEDED(hr))
  2487. {
  2488. VariantToStringList( varOpt, sOptionalList );
  2489. }
  2490. VariantClear(&varOpt);
  2491. hr = CreateAttributeList(sMandList, TRUE);
  2492. if (FAILED(hr))
  2493. {
  2494. return hr;
  2495. }
  2496. hr = CreateAttributeList(sOptionalList, FALSE);
  2497. if (FAILED(hr))
  2498. {
  2499. return hr;
  2500. }
  2501. }
  2502. return hr;
  2503. }
  2504. HRESULT CAttributeEditorPropertyPage::CreateAttributeList(CStringList& sAttrList, BOOL bMandatory)
  2505. {
  2506. HRESULT hr = S_OK;
  2507. LPWSTR* lpszAttrArray;
  2508. UINT nCount = 0;
  2509. GetStringArrayFromStringList(sAttrList, &lpszAttrArray, &nCount);
  2510. TRACE(_T("There are %u properties to add\n"), nCount);
  2511. for (UINT idx = 0; idx < nCount; idx++)
  2512. {
  2513. CADSIAttribute* pNewAttr = new CADSIAttribute(lpszAttrArray[idx]);
  2514. ASSERT(pNewAttr != NULL);
  2515. pNewAttr->SetMandatory(bMandatory);
  2516. // Get the syntax
  2517. BOOL bMultivalued = FALSE;
  2518. CString szSyntax;
  2519. ADSTYPE adstype = RetrieveADsTypeFromSyntax(lpszAttrArray[idx], &bMultivalued, szSyntax);
  2520. pNewAttr->SetADsType(adstype);
  2521. pNewAttr->SetMultivalued(bMultivalued);
  2522. pNewAttr->SetSyntax(szSyntax);
  2523. m_AttrList.AddTail(pNewAttr);
  2524. }
  2525. //
  2526. // Retrieve the values that are set
  2527. //
  2528. #define RETRIEVESET
  2529. #ifdef RETRIEVESET
  2530. if (m_dwBindFlags & DSATTR_EDITOR_ROOTDSE)
  2531. {
  2532. //
  2533. // Special case RootDSE because it does not support IDirectoryObject
  2534. //
  2535. hr = m_spIADs->GetInfo();
  2536. for (UINT idx = 0; idx < nCount; idx++)
  2537. {
  2538. VARIANT var;
  2539. hr = m_spIADs->GetEx( lpszAttrArray[idx] , &var );
  2540. if ( FAILED(hr) )
  2541. {
  2542. m_RootDSEValueList.AddTail(L" ");
  2543. continue;
  2544. }
  2545. /////////////////////////////////////////
  2546. // Convert and populate
  2547. ///////////////////////////////////////////
  2548. CStringList sList;
  2549. hr = VariantToStringList( var, sList );
  2550. if (SUCCEEDED(hr))
  2551. {
  2552. CString szTempValue;
  2553. POSITION pos = sList.GetHeadPosition();
  2554. while (pos != NULL)
  2555. {
  2556. CString szValue = sList.GetNext(pos);
  2557. if (szTempValue.IsEmpty())
  2558. {
  2559. szTempValue += szValue;
  2560. }
  2561. else
  2562. {
  2563. szTempValue += L";" + szValue;
  2564. }
  2565. }
  2566. m_RootDSEValueList.AddTail(szTempValue);
  2567. }
  2568. }
  2569. }
  2570. else
  2571. {
  2572. CComPtr<IDirectoryObject> spDirObject;
  2573. hr = m_spIADs->QueryInterface(IID_IDirectoryObject, (PVOID*)&spDirObject);
  2574. if (FAILED(hr))
  2575. {
  2576. return hr;
  2577. }
  2578. PADS_ATTR_INFO pAttrInfo = NULL;
  2579. DWORD dwReturned = 0;
  2580. hr = spDirObject->GetObjectAttributes(lpszAttrArray, nCount, &pAttrInfo, &dwReturned);
  2581. if (SUCCEEDED(hr))
  2582. {
  2583. //
  2584. // Save the attribute info pointer for later deletion
  2585. //
  2586. if (bMandatory)
  2587. {
  2588. m_AttrList.SaveMandatoryValuesPointer(pAttrInfo);
  2589. }
  2590. else
  2591. {
  2592. m_AttrList.SaveOptionalValuesPointer(pAttrInfo);
  2593. }
  2594. for (DWORD idx = 0; idx < dwReturned; idx++)
  2595. {
  2596. POSITION pos = m_AttrList.FindProperty(pAttrInfo[idx].pszAttrName);
  2597. CADSIAttribute* pNewAttr = m_AttrList.GetAt(pos);
  2598. ASSERT(pNewAttr != NULL);
  2599. pNewAttr->SetValueSet(TRUE);
  2600. pNewAttr->SetAttrInfo(&(pAttrInfo[idx]));
  2601. }
  2602. TRACE(_T("Added %u properties to the list\nThe list has %u total properties\n"), dwReturned, m_AttrList.GetCount());
  2603. }
  2604. else
  2605. {
  2606. ADSIEditErrorMessage(hr, IDS_MSG_FAIL_LOAD_VALUES, MB_OK);
  2607. }
  2608. for (UINT nIndex = 0; nIndex < nCount; nIndex++)
  2609. {
  2610. delete lpszAttrArray[nIndex];
  2611. lpszAttrArray[nIndex] = NULL;
  2612. }
  2613. delete[] lpszAttrArray;
  2614. lpszAttrArray = NULL;
  2615. }
  2616. #endif //RETRIEVESET
  2617. return hr;
  2618. }
  2619. ATTR_EDITOR_MAP g_attrEditorMap[] = {
  2620. // Class, Attribute, ADSTYPE, Multivalued, Creation function
  2621. { NULL, NULL, ADSTYPE_DN_STRING, FALSE, CreateSingleStringEditor },
  2622. { NULL, NULL, ADSTYPE_DN_STRING, TRUE, CreateMultiStringEditor },
  2623. { NULL, NULL, ADSTYPE_CASE_IGNORE_STRING, FALSE, CreateSingleStringEditor },
  2624. { NULL, NULL, ADSTYPE_CASE_IGNORE_STRING, TRUE, CreateMultiStringEditor },
  2625. { NULL, NULL, ADSTYPE_CASE_EXACT_STRING, FALSE, CreateSingleStringEditor },
  2626. { NULL, NULL, ADSTYPE_CASE_EXACT_STRING, TRUE, CreateMultiStringEditor },
  2627. { NULL, NULL, ADSTYPE_PRINTABLE_STRING, FALSE, CreateSingleStringEditor },
  2628. { NULL, NULL, ADSTYPE_PRINTABLE_STRING, TRUE, CreateMultiStringEditor },
  2629. { NULL, NULL, ADSTYPE_NUMERIC_STRING, FALSE, CreateSingleStringEditor },
  2630. { NULL, NULL, ADSTYPE_NUMERIC_STRING, TRUE, CreateMultiStringEditor },
  2631. { NULL, NULL, ADSTYPE_OBJECT_CLASS, FALSE, CreateSingleStringEditor },
  2632. { NULL, NULL, ADSTYPE_OBJECT_CLASS, TRUE, CreateMultiStringEditor },
  2633. { NULL, NULL, ADSTYPE_INTEGER, FALSE, CreateSingleIntEditor },
  2634. { NULL, NULL, ADSTYPE_LARGE_INTEGER, FALSE, CreateSingleLargeIntEditor },
  2635. { NULL, NULL, ADSTYPE_BOOLEAN, FALSE, CreateSingleBooleanEditor },
  2636. { NULL, NULL, ADSTYPE_UTC_TIME, FALSE, CreateSingleTimeEditor },
  2637. { NULL, NULL, ADSTYPE_TIMESTAMP, FALSE, CreateSingleTimeEditor },
  2638. { NULL, NULL, ADSTYPE_OCTET_STRING, FALSE, CreateSingleOctetStringEditor },
  2639. { NULL, NULL, ADSTYPE_OCTET_STRING, TRUE, CreateMultiOctetStringEditor },
  2640. };
  2641. size_t g_attrEditMapCount = sizeof(g_attrEditorMap)/sizeof(ATTR_EDITOR_MAP);
  2642. CValueEditDialog* CAttributeEditorPropertyPage::RetrieveEditor(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo)
  2643. {
  2644. CValueEditDialog* pNewDialog = NULL;
  2645. if (pAttributeEditorInfo != NULL)
  2646. {
  2647. int iMultivalued = 0;
  2648. CString szSyntax;
  2649. ADSTYPE adsType = RetrieveADsTypeFromSyntax(pAttributeEditorInfo->lpszAttribute, &iMultivalued, szSyntax);
  2650. for (size_t idx = 0; idx < g_attrEditMapCount; idx++)
  2651. {
  2652. //
  2653. // REVIEW_JEFFJON : for now I am just looking at ADSTYPE and single/multivalued
  2654. //
  2655. if (g_attrEditorMap[idx].adsType == adsType &&
  2656. g_attrEditorMap[idx].bMultivalued == pAttributeEditorInfo->bMultivalued)
  2657. {
  2658. pNewDialog = g_attrEditorMap[idx].pfnCreateFunc(pAttributeEditorInfo->lpszClass,
  2659. pAttributeEditorInfo->lpszAttribute,
  2660. adsType,
  2661. pAttributeEditorInfo->bMultivalued);
  2662. break;
  2663. }
  2664. }
  2665. }
  2666. return pNewDialog;
  2667. }
  2668. ADSTYPE CAttributeEditorPropertyPage::RetrieveADsTypeFromSyntax(LPCWSTR lpszAttribute, BOOL* pbMulti, CString& szSyntax)
  2669. {
  2670. ADSTYPE adsType = ADSTYPE_INVALID;
  2671. CADSIQueryObject schemaSearch;
  2672. HRESULT hr = S_OK;
  2673. CComPtr<IDirectorySearch> spDirSearch;
  2674. // REVIEW_JEFFJON : this needs to be replaced with proper binding calls
  2675. // REVIEW_JEFFJON : maybe this interface pointer should be retained for future use
  2676. hr = m_pfnBind(m_szSchemaNamingContext,
  2677. ADS_SECURE_AUTHENTICATION,
  2678. IID_IDirectorySearch,
  2679. (PVOID*)&spDirSearch,
  2680. m_BindLPARAM);
  2681. if (FAILED(hr))
  2682. {
  2683. return ADSTYPE_INVALID;
  2684. }
  2685. //
  2686. // Initialize search object with IDirectorySearch
  2687. //
  2688. hr = schemaSearch.Init(spDirSearch);
  2689. if (FAILED(hr))
  2690. {
  2691. return ADSTYPE_INVALID;
  2692. }
  2693. int cCols = 2;
  2694. LPWSTR pszAttributes[] = {L"isSingleValued", L"attributeSyntax"};
  2695. ADS_SEARCH_COLUMN ColumnData;
  2696. hr = schemaSearch.SetSearchPrefs(ADS_SCOPE_ONELEVEL);
  2697. if (FAILED(hr))
  2698. {
  2699. return ADSTYPE_INVALID;
  2700. }
  2701. CString csFilter;
  2702. csFilter.Format(L"(&(objectClass=attributeSchema)(lDAPDisplayName=%s))", lpszAttribute);
  2703. schemaSearch.SetFilterString((LPWSTR)(LPCWSTR)csFilter);
  2704. schemaSearch.SetAttributeList (pszAttributes, cCols);
  2705. hr = schemaSearch.DoQuery ();
  2706. if (SUCCEEDED(hr))
  2707. {
  2708. hr = schemaSearch.GetNextRow();
  2709. if (SUCCEEDED(hr))
  2710. {
  2711. hr = schemaSearch.GetColumn(pszAttributes[0], &ColumnData);
  2712. if (SUCCEEDED(hr))
  2713. {
  2714. TRACE(_T("\t\tisSingleValued: %d\n"),
  2715. ColumnData.pADsValues->Boolean);
  2716. *pbMulti = !ColumnData.pADsValues->Boolean;
  2717. schemaSearch.FreeColumn(&ColumnData);
  2718. }
  2719. hr = schemaSearch.GetColumn(pszAttributes[1], &ColumnData);
  2720. if (SUCCEEDED(hr))
  2721. {
  2722. TRACE(_T("\t\tattributeSyntax: %s\n"),
  2723. ColumnData.pADsValues->CaseIgnoreString);
  2724. adsType = GetADsTypeFromString(ColumnData.pADsValues->CaseIgnoreString, szSyntax);
  2725. schemaSearch.FreeColumn(&ColumnData);
  2726. }
  2727. }
  2728. }
  2729. return adsType;
  2730. }