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

842 lines
25 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Windows NT Directory Service Property Pages
  4. //
  5. // Microsoft Windows
  6. // Copyright (C) Microsoft Corporation, 1992 - 2001
  7. //
  8. // File: user.cxx
  9. //
  10. // Contents: AD user shell property pages
  11. //
  12. // History: 05-May-97 EricB created
  13. //
  14. //-----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #include "proppage.h"
  17. #include "objlist.h"
  18. #include "user.h"
  19. //#include "group.h"
  20. #ifndef UNICODE
  21. # include <stdio.h>
  22. #endif
  23. //+----------------------------------------------------------------------------
  24. //
  25. // Function: CountryCode
  26. //
  27. // Synopsis: Handles the Country combo box to get/set the Country-Code
  28. // (LDAP display name: countryCode) numeric ISO-3166 code.
  29. //
  30. // Notes: This attr function MUST be called after CountryName. It
  31. // relies on CountryName populating the combobox and setting its
  32. // item data values.
  33. //
  34. //-----------------------------------------------------------------------------
  35. HRESULT
  36. CountryCode(CDsPropPageBase * pPage, PATTR_MAP pAttrMap,
  37. PADS_ATTR_INFO pAttrInfo, LPARAM lParam, PATTR_DATA pAttrData,
  38. DLG_OP DlgOp)
  39. {
  40. switch(DlgOp)
  41. {
  42. case fOnCommand:
  43. if (CBN_SELCHANGE == lParam)
  44. {
  45. pPage->SetDirty();
  46. PATTR_DATA_SET_DIRTY(pAttrData);
  47. }
  48. break;
  49. case fApply:
  50. DBG_OUT("CountryCode: fApply");
  51. if (!PATTR_DATA_IS_WRITABLE(pAttrData) || !PATTR_DATA_IS_DIRTY(pAttrData))
  52. {
  53. return ADM_S_SKIP;
  54. }
  55. int iSel = (int)SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
  56. CB_GETCURSEL, 0, 0);
  57. if (iSel < 0)
  58. {
  59. pAttrInfo->dwControlCode = ADS_ATTR_CLEAR;
  60. }
  61. else
  62. {
  63. INT_PTR pCur = SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
  64. CB_GETITEMDATA, iSel, 0);
  65. if (pCur == LB_ERR)
  66. {
  67. DWORD dwErr = GetLastError();
  68. CHECK_WIN32_REPORT(dwErr, pPage->GetHWnd(), return HRESULT_FROM_WIN32(dwErr););
  69. }
  70. PDsCountryCode pCountryCode = (PDsCountryCode)pCur;
  71. PADSVALUE pADsValue;
  72. pADsValue = new ADSVALUE;
  73. CHECK_NULL_REPORT(pADsValue, pPage->GetHWnd(), return E_OUTOFMEMORY);
  74. pAttrInfo->pADsValues = pADsValue;
  75. pAttrInfo->dwNumValues = 1;
  76. pAttrInfo->dwControlCode = ADS_ATTR_UPDATE;
  77. pADsValue->dwType = pAttrInfo->dwADsType;
  78. pADsValue->Integer = pCountryCode->wCode;
  79. }
  80. break;
  81. }
  82. return S_OK;
  83. }
  84. //+----------------------------------------------------------------------------
  85. //
  86. // Function: CountryName
  87. //
  88. // Synopsis: Handles the Country combo box/static control to get/set the
  89. // Country-Name (LDAP display name: c) 2 character ISO-3166 code.
  90. //
  91. // Notes: If the control is read-only, then assume it is a static text
  92. // control (or a read-only edit control) rather than a combobox.
  93. // Also, if read-only, then only the fInit should be called.
  94. //
  95. //-----------------------------------------------------------------------------
  96. HRESULT
  97. CountryName(CDsPropPageBase * pPage, PATTR_MAP pAttrMap,
  98. PADS_ATTR_INFO pAttrInfo, LPARAM lParam, PATTR_DATA pAttrData,
  99. DLG_OP DlgOp)
  100. {
  101. PWSTR pwsz = NULL;
  102. DWORD dwErr = 0;
  103. INT_PTR pCur = NULL;
  104. PDsCountryCode pCountryCode = NULL;
  105. int iSel = 0, iCur = -1, cxExtent = 0;
  106. #ifdef UNICODE
  107. CStrW strFirstCode, strLastCode, strCodeLine, strCurName;
  108. #else
  109. CStr strFirstCode, strLastCode, strCodeLine, strCurName;
  110. #endif
  111. CStrW str2CharAbrev;
  112. switch (DlgOp)
  113. {
  114. case fInit:
  115. dspAssert(pAttrData);
  116. if (!pAttrMap->fIsReadOnly && !PATTR_DATA_IS_WRITABLE(pAttrData))
  117. {
  118. EnableWindow(GetDlgItem(pPage->GetHWnd(), pAttrMap->nCtrlID),
  119. FALSE);
  120. //
  121. // Remove the accelerator from the label since a disabled control
  122. // is not reachable.
  123. //
  124. CStr strLabel;
  125. strLabel.LoadString(g_hInstance, IDS_COUNTRY_LABEL_NO_ACCEL);
  126. SetDlgItemText(pPage->GetHWnd(), IDC_COUNTRY_LABEL, strLabel.GetBuffer(0));
  127. }
  128. // fall through...
  129. case fObjChanged:
  130. {
  131. DBG_OUT("CountryName: fInit");
  132. PTSTR ptzFullName = NULL;
  133. WORD wCode = 0;
  134. HDC hDC = NULL;
  135. unsigned long ulFirstCode, ulLastCode, i;
  136. strFirstCode.LoadString(g_hInstance, IDS_FIRST_COUNTRY_CODE);
  137. strLastCode.LoadString(g_hInstance, IDS_LAST_COUNTRY_CODE);
  138. if (strFirstCode.IsEmpty() || strLastCode.IsEmpty())
  139. {
  140. ERR_MSG(IDS_ERR_COUNTRY_DATA_BAD, pPage->GetHWnd());
  141. return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  142. }
  143. ulFirstCode = _tcstoul(strFirstCode, NULL, 10);
  144. ulLastCode = _tcstoul(strLastCode, NULL, 10);
  145. if (!pAttrMap->fIsReadOnly)
  146. {
  147. hDC = GetDC(GetDlgItem(pPage->GetHWnd(), pAttrMap->nCtrlID));
  148. }
  149. PWSTR pwzCurCode;
  150. if (pAttrInfo && pAttrInfo->dwNumValues)
  151. {
  152. pwzCurCode = pAttrInfo->pADsValues->CaseIgnoreString;
  153. }
  154. else
  155. {
  156. pwzCurCode = NULL;
  157. }
  158. for (i = ulFirstCode; i <= ulLastCode; i++)
  159. {
  160. strCodeLine.LoadString(g_hInstance, i);
  161. if (strCodeLine.IsEmpty())
  162. {
  163. ERR_MSG(IDS_ERR_COUNTRY_DATA_BAD, pPage->GetHWnd());
  164. return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  165. }
  166. if (!GetALineOfCodes(strCodeLine.GetBuffer(1), &ptzFullName, str2CharAbrev, &wCode))
  167. {
  168. ERR_MSG(IDS_ERR_COUNTRY_DATA_BAD, pPage->GetHWnd());
  169. return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  170. }
  171. if (!pAttrMap->fIsReadOnly)
  172. {
  173. // If not in read-only mode, then we use a combobox from which
  174. // the user selects the country.
  175. // Insert the full name into the combobox list.
  176. //
  177. SIZE s;
  178. if (hDC != NULL)
  179. {
  180. GetTextExtentPoint32(hDC, ptzFullName, static_cast<int>(_tcslen(ptzFullName)), &s);
  181. if (s.cx > cxExtent)
  182. {
  183. cxExtent = s.cx;
  184. }
  185. iSel = (int)SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
  186. CB_ADDSTRING, 0, (LPARAM)ptzFullName);
  187. if (iSel < 0)
  188. {
  189. CHECK_HRESULT_REPORT(E_OUTOFMEMORY, pPage->GetHWnd(), return E_OUTOFMEMORY);
  190. }
  191. //
  192. // Add the name codes as item data.
  193. //
  194. pCountryCode = new DsCountryCode;
  195. CHECK_NULL_REPORT(pCountryCode, pPage->GetHWnd(), return E_OUTOFMEMORY);
  196. wcscpy(pCountryCode->pwz2CharAbrev, str2CharAbrev);
  197. pCountryCode->wCode = wCode;
  198. if (SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
  199. CB_SETITEMDATA, iSel,
  200. (LPARAM)pCountryCode) == CB_ERR)
  201. {
  202. CHECK_HRESULT_REPORT(E_OUTOFMEMORY, pPage->GetHWnd(), return E_OUTOFMEMORY);
  203. }
  204. }
  205. }
  206. //
  207. // See if the current country matches that saved on the DS object
  208. // (if one has been saved).
  209. //
  210. if (pwzCurCode)
  211. {
  212. if (_wcsicmp(pwzCurCode, str2CharAbrev) == 0)
  213. {
  214. iCur = iSel;
  215. strCurName = ptzFullName;
  216. }
  217. }
  218. if ((iCur == iSel) && pAttrMap->fIsReadOnly)
  219. {
  220. // Read-only mode means that we are using a static text
  221. // control. Insert the full name into the control.
  222. //
  223. SetDlgItemText(pPage->GetHWnd(), pAttrMap->nCtrlID, ptzFullName);
  224. break;
  225. }
  226. if (pAttrMap->fIsReadOnly)
  227. {
  228. iSel++;
  229. }
  230. }
  231. if (!pAttrMap->fIsReadOnly)
  232. {
  233. if (hDC != NULL)
  234. {
  235. ReleaseDC(GetDlgItem(pPage->GetHWnd(), pAttrMap->nCtrlID), hDC);
  236. }
  237. SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
  238. CB_SETHORIZONTALEXTENT, (WPARAM)cxExtent, 0);
  239. if (iCur >= 0)
  240. {
  241. iCur = (int) SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
  242. CB_FINDSTRINGEXACT, 0,
  243. (WPARAM)(LPCTSTR)strCurName);
  244. dspAssert(iCur != CB_ERR);
  245. SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
  246. CB_SETCURSEL, iCur, 0);
  247. }
  248. }
  249. else
  250. {
  251. if (iCur < 0)
  252. {
  253. // If iCur is still -1, then country code hasn't been set.
  254. //
  255. SetDlgItemText(pPage->GetHWnd(), pAttrMap->nCtrlID, TEXT(""));
  256. }
  257. }
  258. break;
  259. }
  260. case fApply:
  261. DBG_OUT("CountryName: fApply");
  262. if (!PATTR_DATA_IS_WRITABLE(pAttrData) || !PATTR_DATA_IS_DIRTY(pAttrData))
  263. {
  264. return ADM_S_SKIP;
  265. }
  266. iSel = (int)SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
  267. CB_GETCURSEL, 0, 0);
  268. if (iSel < 0)
  269. {
  270. pAttrInfo->dwControlCode = ADS_ATTR_CLEAR;
  271. }
  272. else
  273. {
  274. pCur = SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
  275. CB_GETITEMDATA, iSel, 0);
  276. if (pCur == LB_ERR)
  277. {
  278. dwErr = GetLastError();
  279. CHECK_WIN32_REPORT(dwErr, pPage->GetHWnd(), return HRESULT_FROM_WIN32(dwErr););
  280. }
  281. pCountryCode = (PDsCountryCode)pCur;
  282. if (!AllocWStr(pCountryCode->pwz2CharAbrev, &pwsz))
  283. {
  284. CHECK_HRESULT_REPORT(E_OUTOFMEMORY, pPage->GetHWnd(), return E_OUTOFMEMORY);
  285. }
  286. PADSVALUE pADsValue;
  287. pADsValue = new ADSVALUE;
  288. CHECK_NULL_REPORT(pADsValue, pPage->GetHWnd(), return E_OUTOFMEMORY);
  289. pAttrInfo->pADsValues = pADsValue;
  290. pAttrInfo->dwNumValues = 1;
  291. pAttrInfo->dwControlCode = ADS_ATTR_UPDATE;
  292. pADsValue->dwType = pAttrInfo->dwADsType;
  293. pADsValue->CaseIgnoreString = pwsz;
  294. }
  295. break;
  296. case fOnCommand:
  297. if (CBN_SELCHANGE == lParam)
  298. {
  299. pPage->SetDirty();
  300. PATTR_DATA_SET_DIRTY(pAttrData);
  301. }
  302. break;
  303. case fOnDestroy:
  304. DBG_OUT("CountryName: fOnDestroy");
  305. iSel = 0;
  306. do
  307. {
  308. pCur = SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
  309. CB_GETITEMDATA, iSel, 0);
  310. if (pCur != CB_ERR)
  311. {
  312. // Delete the itemdata string.
  313. //
  314. delete (PDsCountryCode)pCur;
  315. iSel++;
  316. }
  317. } while (pCur != CB_ERR);
  318. break;
  319. }
  320. return S_OK;
  321. }
  322. //+----------------------------------------------------------------------------
  323. //
  324. // Function: TextCountry
  325. //
  326. // Synopsis: Handles the Country combo box to get/set the Text-Country
  327. // (LDAP display name: co)
  328. //
  329. // Notes: This attr function MUST be called after CountryName. It
  330. // relies on CountryName populating the combobox
  331. //
  332. //-----------------------------------------------------------------------------
  333. HRESULT
  334. TextCountry(CDsPropPageBase * pPage, PATTR_MAP pAttrMap,
  335. PADS_ATTR_INFO pAttrInfo, LPARAM lParam, PATTR_DATA pAttrData,
  336. DLG_OP DlgOp)
  337. {
  338. switch(DlgOp)
  339. {
  340. case fOnCommand:
  341. if (CBN_SELCHANGE == lParam)
  342. {
  343. pPage->SetDirty();
  344. PATTR_DATA_SET_DIRTY(pAttrData);
  345. }
  346. break;
  347. case fApply:
  348. DBG_OUT("TextCountry: fApply");
  349. if (!PATTR_DATA_IS_WRITABLE(pAttrData) || !PATTR_DATA_IS_DIRTY(pAttrData))
  350. {
  351. return ADM_S_SKIP;
  352. }
  353. int iSel = (int)SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
  354. CB_GETCURSEL, 0, 0);
  355. if (iSel < 0)
  356. {
  357. pAttrInfo->dwControlCode = ADS_ATTR_CLEAR;
  358. }
  359. else
  360. {
  361. LPTSTR ptz = new TCHAR[pAttrMap->nSizeLimit + 1];
  362. CHECK_NULL_REPORT(ptz, pPage->GetHWnd(), return E_OUTOFMEMORY);
  363. INT_PTR pCur = SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
  364. CB_GETLBTEXT, iSel, (LPARAM) (LPCSTR) ptz );
  365. if (pCur == LB_ERR)
  366. {
  367. delete [] ptz;
  368. DWORD dwErr = GetLastError();
  369. CHECK_WIN32_REPORT(dwErr, pPage->GetHWnd(), return HRESULT_FROM_WIN32(dwErr););
  370. }
  371. PADSVALUE pADsValue;
  372. pADsValue = new ADSVALUE;
  373. if( pADsValue == NULL )
  374. {
  375. ReportError(E_OUTOFMEMORY,0, pPage->GetHWnd());
  376. delete [] ptz;
  377. return E_OUTOFMEMORY;
  378. }
  379. if (!TcharToUnicode(ptz, &pADsValue->CaseIgnoreString))
  380. {
  381. delete [] ptz;
  382. delete pADsValue;
  383. REPORT_ERROR(E_OUTOFMEMORY, pPage->GetHWnd());
  384. return E_OUTOFMEMORY;
  385. }
  386. delete [] ptz;
  387. pAttrInfo->pADsValues = pADsValue;
  388. pAttrInfo->dwNumValues = 1;
  389. pAttrInfo->dwControlCode = ADS_ATTR_UPDATE;
  390. pADsValue->dwType = pAttrInfo->dwADsType;
  391. }
  392. break;
  393. }
  394. return S_OK;
  395. }
  396. // CountryName helpers:
  397. //+----------------------------------------------------------------------------
  398. //
  399. // Function: GetALineOfCodes
  400. //
  401. // Synopsis: Parse a line of country codes.
  402. //
  403. //-----------------------------------------------------------------------------
  404. BOOL GetALineOfCodes(PTSTR ptzLine, PTSTR * pptzFullName,
  405. CStrW & str2CharAbrev, LPWORD pwCode)
  406. {
  407. //
  408. // The line is parsed from end to beginning. That way we don't need to
  409. // dependend on the column widths being fixed.
  410. //
  411. // The last token is the numeric code. Read it.
  412. //
  413. RemoveTrailingWhitespace(ptzLine);
  414. PTSTR ptzCode = _tcsrchr(ptzLine, TEXT(' '));
  415. if (!ptzCode)
  416. {
  417. // try tab char.
  418. //
  419. ptzCode = _tcsrchr(ptzLine, TEXT('\t'));
  420. }
  421. if (!ptzCode || (ptzCode <= ptzLine) || (_tcslen(ptzCode) < 2))
  422. {
  423. return FALSE;
  424. }
  425. *ptzCode = TEXT('\0');
  426. ptzCode++;
  427. int iScanned = _stscanf(ptzCode, TEXT("%u"), pwCode);
  428. dspAssert(iScanned == 1);
  429. //
  430. // The next to last token is the 3 character code. Skip it.
  431. //
  432. RemoveTrailingWhitespace(ptzLine);
  433. size_t nLen = _tcslen(ptzLine);
  434. if (3 >= nLen)
  435. {
  436. return FALSE;
  437. }
  438. ptzLine[nLen - 3] = TEXT('\0');
  439. //
  440. // The next token (moving toward the front) is the 2 character code.
  441. //
  442. RemoveTrailingWhitespace(ptzLine);
  443. PTSTR ptz2CharAbrev = _tcsrchr(ptzLine, TEXT(' '));
  444. if (!ptz2CharAbrev)
  445. {
  446. // try tab char.
  447. //
  448. ptz2CharAbrev = _tcsrchr(ptzLine, TEXT('\t'));
  449. }
  450. if (!ptz2CharAbrev || (ptz2CharAbrev <= ptzLine))
  451. {
  452. return FALSE;
  453. }
  454. *ptz2CharAbrev = TEXT('\0');
  455. ptz2CharAbrev++;
  456. if (_tcslen(ptz2CharAbrev) != 2)
  457. {
  458. return FALSE;
  459. }
  460. str2CharAbrev = ptz2CharAbrev;
  461. //
  462. // The first token is the full country name.
  463. //
  464. RemoveTrailingWhitespace(ptzLine);
  465. if (!_tcslen(ptzLine))
  466. {
  467. return FALSE;
  468. }
  469. *pptzFullName = ptzLine;
  470. return TRUE;
  471. }
  472. //+----------------------------------------------------------------------------
  473. //
  474. // Function: RemoveTrailingWhitespace
  475. //
  476. // Synopsis: Trailing white space is replaced by NULLs.
  477. //
  478. //-----------------------------------------------------------------------------
  479. void RemoveTrailingWhitespace(PTSTR ptz)
  480. {
  481. size_t nLen = _tcslen(ptz);
  482. while (nLen)
  483. {
  484. if (!iswspace(ptz[nLen - 1]))
  485. {
  486. return;
  487. }
  488. ptz[nLen - 1] = L'\0';
  489. nLen--;
  490. }
  491. }
  492. //+----------------------------------------------------------------------------
  493. //
  494. // Function: ManagerEdit
  495. //
  496. // Synopsis: Handles the manager edit control.
  497. //
  498. // Notes: The page member m_pData stores the pAttrData value whose pVoid
  499. // element is set to the DN of the manager. The other manager
  500. // attr functions can then access the manager value and can also
  501. // read the fWritable element.
  502. //
  503. //-----------------------------------------------------------------------------
  504. HRESULT
  505. ManagerEdit(CDsPropPageBase * pPage, PATTR_MAP pAttrMap,
  506. PADS_ATTR_INFO pAttrInfo, LPARAM lParam, PATTR_DATA pAttrData,
  507. DLG_OP DlgOp)
  508. {
  509. PWSTR pwz = NULL;
  510. PWSTR canonical = NULL;
  511. HRESULT hr = S_OK;
  512. switch (DlgOp)
  513. {
  514. case fInit:
  515. dspAssert(pAttrData);
  516. if (pAttrInfo && pAttrInfo->dwNumValues > 0)
  517. {
  518. if (!AllocWStr(pAttrInfo->pADsValues[0].DNString, &pwz))
  519. {
  520. REPORT_ERROR(E_OUTOFMEMORY, pPage->GetHWnd());
  521. return E_OUTOFMEMORY;
  522. }
  523. hr = CrackName (pwz, &canonical, GET_OBJ_CAN_NAME_EX, pPage->GetHWnd());
  524. if (FAILED(hr))
  525. {
  526. delete [] pwz;
  527. return S_FALSE;
  528. }
  529. PTSTR ptz, ptzName;
  530. if (!UnicodeToTchar(canonical, &ptz))
  531. {
  532. REPORT_ERROR(E_OUTOFMEMORY, pPage->GetHWnd());
  533. delete [] pwz;
  534. return E_OUTOFMEMORY;
  535. }
  536. LocalFreeStringW(&canonical);
  537. ptzName = _tcschr(ptz, TEXT('\n'));
  538. dspAssert(ptzName);
  539. ptzName++;
  540. SetDlgItemText(pPage->GetHWnd(), pAttrMap->nCtrlID, ptzName);
  541. delete [] ptz;
  542. }
  543. pAttrData->pVoid = reinterpret_cast<LPARAM>(pwz);
  544. ((CDsTableDrivenPage *)pPage)->m_pData = reinterpret_cast<LPARAM>(pAttrData);
  545. break;
  546. case fOnCommand:
  547. if (EN_CHANGE == lParam)
  548. {
  549. pPage->SetDirty();
  550. PATTR_DATA_SET_DIRTY(pAttrData);
  551. }
  552. break;
  553. case fApply:
  554. if (!PATTR_DATA_IS_WRITABLE(pAttrData) || !PATTR_DATA_IS_DIRTY(pAttrData))
  555. {
  556. return ADM_S_SKIP;
  557. }
  558. pwz = (PWSTR)reinterpret_cast<PATTR_DATA>(((CDsTableDrivenPage *)pPage)->m_pData)->pVoid;
  559. if (pwz)
  560. {
  561. // make a copy cause CDsTableDrivenPage::OnApply deletes it.
  562. PWSTR pwzTmp;
  563. if (!AllocWStr(pwz, &pwzTmp))
  564. {
  565. REPORT_ERROR(E_OUTOFMEMORY, pPage->GetHWnd());
  566. return E_OUTOFMEMORY;
  567. }
  568. PADSVALUE pADsValue;
  569. pADsValue = new ADSVALUE;
  570. CHECK_NULL(pADsValue, return E_OUTOFMEMORY);
  571. pAttrInfo->pADsValues = pADsValue;
  572. pAttrInfo->dwNumValues = 1;
  573. pAttrInfo->dwControlCode = ADS_ATTR_UPDATE;
  574. pADsValue->dwType = pAttrInfo->dwADsType;
  575. pADsValue->CaseIgnoreString = pwzTmp;
  576. }
  577. else
  578. {
  579. pAttrInfo->pADsValues = NULL;
  580. pAttrInfo->dwNumValues = 0;
  581. pAttrInfo->dwControlCode = ADS_ATTR_CLEAR;
  582. }
  583. break;
  584. case fOnDestroy:
  585. if (reinterpret_cast<CDsTableDrivenPage *>(pPage)->m_pData)
  586. {
  587. PATTR_DATA pData = reinterpret_cast<PATTR_DATA>(((CDsTableDrivenPage *)pPage)->m_pData);
  588. PVOID pVoid = reinterpret_cast<PVOID>(pData->pVoid);
  589. DO_DEL(pVoid);
  590. }
  591. break;
  592. }
  593. return S_OK;
  594. }
  595. //+----------------------------------------------------------------------------
  596. //
  597. // Function: DirectReportsList
  598. //
  599. // Synopsis: Handles the User Organisation Direct Reports list.
  600. //
  601. //-----------------------------------------------------------------------------
  602. HRESULT
  603. DirectReportsList(CDsPropPageBase * pPage, PATTR_MAP pAttrMap,
  604. PADS_ATTR_INFO pAttrInfo, LPARAM lParam, PATTR_DATA,
  605. DLG_OP DlgOp)
  606. {
  607. //
  608. // Multi-select will result in a return at this point
  609. //
  610. if (pPage->GetObjPathName() == NULL)
  611. {
  612. return S_OK;
  613. }
  614. switch (DlgOp)
  615. {
  616. case fInit:
  617. {
  618. HRESULT hr;
  619. Smart_PADS_ATTR_INFO spAttrs;
  620. DWORD cAttrs = 0;
  621. PWSTR rgpwzAttrNames[] = {pAttrMap->AttrInfo.pszAttrName};
  622. CComPtr <IDirectoryObject> spGcObj;
  623. hr = BindToGCcopyOfObj(pPage, pPage->GetObjPathName(), &spGcObj);
  624. if (SUCCEEDED(hr))
  625. {
  626. hr = spGcObj->GetObjectAttributes(rgpwzAttrNames, 1, &spAttrs, &cAttrs);
  627. if (SUCCEEDED(hr))
  628. {
  629. //
  630. // If the bind to the GC was successful, use those results.
  631. // Otherwise, use the results of the local object read.
  632. //
  633. if (!cAttrs)
  634. {
  635. return S_OK;
  636. }
  637. pAttrInfo = spAttrs;
  638. }
  639. }
  640. if (!pAttrInfo)
  641. {
  642. return S_OK;
  643. }
  644. for (DWORD i = 0; i < pAttrInfo->dwNumValues; i++)
  645. {
  646. PWSTR pwzDns;
  647. hr = CrackName(pAttrInfo->pADsValues[i].DNString, &pwzDns,
  648. GET_OBJ_CAN_NAME_EX, pPage->GetHWnd());
  649. CHECK_HRESULT(hr, return hr);
  650. PTSTR ptz, ptzName;
  651. if (!UnicodeToTchar(pwzDns, &ptz))
  652. {
  653. LocalFreeStringW(&pwzDns);
  654. REPORT_ERROR(E_OUTOFMEMORY, pPage->GetHWnd());
  655. return E_OUTOFMEMORY;
  656. }
  657. LocalFreeStringW(&pwzDns);
  658. ptzName = _tcschr(ptz, TEXT('\n'));
  659. dspAssert(ptzName);
  660. ptzName++;
  661. LRESULT lresult = SendDlgItemMessage(pPage->GetHWnd(), IDC_REPORTS_LIST, LB_ADDSTRING,
  662. 0, (LPARAM)ptzName);
  663. if (lresult != LB_ERR)
  664. {
  665. PWSTR pwzDN = new WCHAR[wcslen(pAttrInfo->pADsValues[i].DNString) + 1];
  666. if (pwzDN != NULL)
  667. {
  668. wcscpy(pwzDN, pAttrInfo->pADsValues[i].DNString);
  669. SendDlgItemMessage(pPage->GetHWnd(), IDC_REPORTS_LIST,
  670. LB_SETITEMDATA, lresult, (LPARAM)pwzDN);
  671. }
  672. }
  673. delete [] ptz;
  674. }
  675. }
  676. break;
  677. case fOnCommand:
  678. {
  679. if (lParam == LBN_DBLCLK)
  680. {
  681. //
  682. // Retrieve the current selection
  683. //
  684. PWSTR pwzDN = NULL;
  685. LRESULT lresult = SendDlgItemMessage(pPage->GetHWnd(), IDC_REPORTS_LIST,
  686. LB_GETCURSEL, 0, 0);
  687. if (lresult != LB_ERR)
  688. {
  689. //
  690. // Get the DN associated with the item
  691. //
  692. lresult = SendDlgItemMessage(pPage->GetHWnd(), IDC_REPORTS_LIST,
  693. LB_GETITEMDATA, lresult, 0);
  694. if (lresult != LB_ERR)
  695. {
  696. pwzDN = (PWSTR)lresult;
  697. if (pwzDN != NULL)
  698. {
  699. //
  700. // Launch the secondary proppages
  701. //
  702. PostPropSheet(pwzDN, pPage);
  703. }
  704. }
  705. }
  706. }
  707. }
  708. break;
  709. case fOnDestroy:
  710. {
  711. //
  712. // Must free the memory associated with the list box
  713. //
  714. LRESULT lresult = SendDlgItemMessage(pPage->GetHWnd(), IDC_REPORTS_LIST,
  715. LB_GETCOUNT, 0, 0);
  716. if (lresult != LB_ERR)
  717. {
  718. for (LRESULT idx = lresult - 1 ; idx >= 0; idx--)
  719. {
  720. lresult = SendDlgItemMessage(pPage->GetHWnd(), IDC_REPORTS_LIST,
  721. LB_GETITEMDATA, idx, 0);
  722. if (lresult != LB_ERR)
  723. {
  724. PWSTR pwzDN = (PWSTR)lresult;
  725. if (pwzDN != NULL)
  726. {
  727. delete [] pwzDN;
  728. }
  729. }
  730. }
  731. }
  732. }
  733. break;
  734. default:
  735. break;
  736. }
  737. return S_OK;
  738. }