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.

642 lines
16 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows NT **/
  3. /** Copyright(c) Microsoft Corp., 1991-1996 **/
  4. /**********************************************************************/
  5. /*
  6. LUsers.cpp : implementation file
  7. CPropertyPage support for Group management wizard
  8. FILE HISTORY:
  9. Jony Apr-1996 created
  10. */
  11. #include "stdafx.h"
  12. #include "Romaine.h"
  13. #include "userlist.h"
  14. #include "LUsers.h"
  15. #include "trstlist.h"
  16. #include <winreg.h>
  17. #include <lmcons.h>
  18. #include <lmaccess.h>
  19. #include <lmerr.h>
  20. #include <lmapibuf.h>
  21. #include <winnetwk.h>
  22. #ifdef _DEBUG
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. // some global objects used in the EnumUsers and EnumGroups threads
  28. CStringList csaNames;
  29. CStringList csaLNames;
  30. CStringList csaGroups;
  31. void EnumGroups(DWORD pDCName);
  32. void EnumLocalGroups(DWORD pDCName);
  33. void EnumUsers(DWORD pDCName);
  34. /////////////////////////////////////////////////////////////////////////////
  35. // CLUsers property page
  36. IMPLEMENT_DYNCREATE(CLUsers, CPropertyPage)
  37. CLUsers::CLUsers() : CPropertyPage(CLUsers::IDD)
  38. {
  39. //{{AFX_DATA_INIT(CLUsers)
  40. m_csDomainName = _T("");
  41. m_csAvailableUserList = _T("");
  42. //}}AFX_DATA_INIT
  43. }
  44. CLUsers::~CLUsers()
  45. {
  46. }
  47. void CLUsers::DoDataExchange(CDataExchange* pDX)
  48. {
  49. CPropertyPage::DoDataExchange(pDX);
  50. //{{AFX_DATA_MAP(CLUsers)
  51. DDX_Control(pDX, IDC_ADDED_LOCAL_USERS, m_lbAddedUserList);
  52. DDX_Control(pDX, IDC_AVAILABLE_LOCAL_USERS, m_lbAvailableUserList);
  53. DDX_Control(pDX, IDC_DOMAIN_COMBO, m_csDomainList);
  54. DDX_CBString(pDX, IDC_DOMAIN_COMBO, m_csDomainName);
  55. DDX_LBString(pDX, IDC_AVAILABLE_LOCAL_USERS, m_csAvailableUserList);
  56. //}}AFX_DATA_MAP
  57. }
  58. BEGIN_MESSAGE_MAP(CLUsers, CPropertyPage)
  59. //{{AFX_MSG_MAP(CLUsers)
  60. ON_BN_CLICKED(IDC_ADD_BUTTON, OnAddButton)
  61. ON_CBN_SELCHANGE(IDC_DOMAIN_COMBO, OnSelchangeDomainCombo)
  62. ON_WM_SHOWWINDOW()
  63. ON_LBN_DBLCLK(IDC_ADDED_LOCAL_USERS, OnDblclkAddedLocalUsers)
  64. ON_LBN_DBLCLK(IDC_AVAILABLE_LOCAL_USERS, OnDblclkAvailableLocalUsers)
  65. ON_LBN_SETFOCUS(IDC_AVAILABLE_LOCAL_USERS, OnSetfocusAvailableLocalUsers)
  66. ON_LBN_SETFOCUS(IDC_ADDED_LOCAL_USERS, OnSetfocusAddedLocalUsers)
  67. ON_BN_CLICKED(IDC_REMOVE_BUTTON, OnRemoveButton)
  68. //}}AFX_MSG_MAP
  69. END_MESSAGE_MAP()
  70. /////////////////////////////////////////////////////////////////////////////
  71. // CLUsers message handlers
  72. BOOL CLUsers::OnInitDialog()
  73. {
  74. CPropertyPage::OnInitDialog();
  75. return FALSE; // return TRUE unless you set the focus to a control
  76. // EXCEPTION: OCX Property Pages should return FALSE
  77. }
  78. // launch two threads to enumerate the global groups and user accounts in the selected domain
  79. void CLUsers::CatalogAccounts(const TCHAR* lpDomain, CUserList& pListBox, BOOL bLocal /* = FALSE*/)
  80. {
  81. CWaitCursor wait;
  82. wchar_t lpwDomain[255];
  83. _tcscpy(lpwDomain, lpDomain);
  84. wchar_t* lpszPrimaryDC = NULL;
  85. NET_API_STATUS err = 0;
  86. // first get the name of the PDC machine
  87. if (bLocal)
  88. {
  89. lpszPrimaryDC = (TCHAR*)malloc((_tcslen(lpDomain) + 1)* sizeof(TCHAR));
  90. _tcscpy(lpszPrimaryDC, lpDomain);
  91. }
  92. else
  93. err = NetGetDCName( NULL, // Local Machine
  94. lpwDomain, // Domain Name
  95. (LPBYTE *)&lpszPrimaryDC ); // returned PDC *
  96. // empty the listbox
  97. pListBox.ResetContent();
  98. if (err != 0)
  99. {
  100. AfxMessageBox(IDS_GENERIC_NO_PDC, MB_ICONEXCLAMATION);
  101. return;
  102. }
  103. csaNames.RemoveAll();
  104. csaLNames.RemoveAll();
  105. csaGroups.RemoveAll();
  106. // create a thread each for names and groups. Run them simultaneously to save some time.
  107. HANDLE hThreads[2];
  108. USHORT usObjCount = 2;
  109. DWORD dwThreadID;
  110. hThreads[0] = ::CreateThread(NULL, 100,
  111. (LPTHREAD_START_ROUTINE)EnumUsers,
  112. lpszPrimaryDC,
  113. 0,
  114. &dwThreadID);
  115. if (!bLocal)
  116. {
  117. hThreads[1] = ::CreateThread(NULL, 100,
  118. (LPTHREAD_START_ROUTINE)EnumGroups,
  119. lpszPrimaryDC,
  120. 0,
  121. &dwThreadID);
  122. }
  123. else usObjCount = 1;
  124. // when both threads return, add all the names to the listbox.
  125. DWORD dwWait = WaitForMultipleObjects(usObjCount,
  126. hThreads,
  127. TRUE,
  128. INFINITE);
  129. POSITION pos;
  130. CRomaineApp* pApp = (CRomaineApp*)AfxGetApp();
  131. for (pos = csaNames.GetHeadPosition(); pos != NULL;)
  132. pListBox.AddString(0, csaNames.GetNext(pos));
  133. if (!bLocal)
  134. {
  135. for (pos = csaGroups.GetHeadPosition(); pos != NULL;)
  136. pListBox.AddString(1, csaGroups.GetNext(pos));
  137. }
  138. if (!bLocal) NetApiBufferFree( lpszPrimaryDC );
  139. else free(lpszPrimaryDC);
  140. }
  141. // enum users thread
  142. void EnumUsers(DWORD pDCName)
  143. {
  144. wchar_t* lpszPrimaryDC = NULL;
  145. lpszPrimaryDC = (TCHAR*)pDCName;
  146. CString csTemp;
  147. // now enumerate the users on that machine
  148. void* netUserBuffer;
  149. DWORD dwReturnedEntries;
  150. DWORD err = NetQueryDisplayInformation(lpszPrimaryDC, 1,
  151. 0, 100, 100 * sizeof(NET_DISPLAY_USER),
  152. &dwReturnedEntries, &netUserBuffer);
  153. // check return for error
  154. if (err != NERR_Success && err != ERROR_MORE_DATA) return;
  155. // add these users to the dialog
  156. DWORD dwCurrent;
  157. NET_DISPLAY_USER* netUser;
  158. netUser = (NET_DISPLAY_USER*)netUserBuffer;
  159. for (dwCurrent = 0; dwCurrent < dwReturnedEntries; dwCurrent++)
  160. {
  161. csTemp = netUser->usri1_name;
  162. csTemp += ";";
  163. csTemp += netUser->usri1_comment;
  164. if (netUser->usri1_flags & UF_NORMAL_ACCOUNT) csaNames.AddHead(csTemp);
  165. else csaLNames.AddHead(csTemp);
  166. netUser++;
  167. }
  168. // add more users?
  169. DWORD dwNext;
  170. while (err == ERROR_MORE_DATA)
  171. {
  172. netUser--;
  173. NetGetDisplayInformationIndex(lpszPrimaryDC, 1, netUser->usri1_name, &dwNext);
  174. NetApiBufferFree(netUserBuffer);
  175. err = NetQueryDisplayInformation(lpszPrimaryDC, 1,
  176. dwNext, 100, 32767,
  177. &dwReturnedEntries, &netUserBuffer);
  178. // check return for error
  179. if (err != NERR_Success && err != ERROR_MORE_DATA) return;
  180. netUser = (NET_DISPLAY_USER*)netUserBuffer;
  181. for (dwCurrent = 0; dwCurrent < dwReturnedEntries; dwCurrent++)
  182. {
  183. csTemp = netUser->usri1_name;
  184. csTemp += ";";
  185. csTemp += netUser->usri1_comment;
  186. if (netUser->usri1_flags & UF_NORMAL_ACCOUNT) csaNames.AddHead(csTemp);
  187. else csaLNames.AddHead(csTemp);
  188. netUser++;
  189. }
  190. }
  191. NetApiBufferFree(netUserBuffer);
  192. }
  193. void EnumGroups(DWORD pDCName)
  194. {
  195. wchar_t* lpszPrimaryDC = NULL;
  196. lpszPrimaryDC = (TCHAR*)pDCName;
  197. CString csTemp;
  198. void* netGroupBuffer;
  199. DWORD dwReturnedEntries;
  200. DWORD dwCurrent;
  201. DWORD dwNext;
  202. // now enumerate the groups on that machine
  203. DWORD err = NetQueryDisplayInformation(lpszPrimaryDC, 3,
  204. 0, 100, 100 * sizeof(NET_DISPLAY_GROUP),
  205. &dwReturnedEntries, &netGroupBuffer);
  206. // check return for error
  207. if (err != NERR_Success && err != ERROR_MORE_DATA) return;
  208. NET_DISPLAY_GROUP* netGroup;
  209. netGroup = (NET_DISPLAY_GROUP*)netGroupBuffer;
  210. // add these names to the dialog
  211. netGroup = (NET_DISPLAY_GROUP*)netGroupBuffer;
  212. for (dwCurrent = 0; dwCurrent < dwReturnedEntries; dwCurrent++)
  213. {
  214. csTemp = netGroup->grpi3_name;
  215. csTemp += ";";
  216. csTemp += netGroup->grpi3_comment;
  217. csaGroups.AddHead(csTemp);
  218. netGroup++;
  219. }
  220. // add more names?
  221. while (err == ERROR_MORE_DATA)
  222. {
  223. netGroup--;
  224. NetGetDisplayInformationIndex(lpszPrimaryDC, 3, netGroup->grpi3_name, &dwNext);
  225. NetApiBufferFree(netGroupBuffer);
  226. err = NetQueryDisplayInformation(lpszPrimaryDC, 3,
  227. dwNext, 100, 32767,
  228. &dwReturnedEntries, &netGroupBuffer);
  229. // check return for error
  230. if (err != NERR_Success && err != ERROR_MORE_DATA) return;
  231. netGroup = (NET_DISPLAY_GROUP*)netGroupBuffer;
  232. for (dwCurrent = 0; dwCurrent < dwReturnedEntries; dwCurrent++)
  233. {
  234. csTemp = netGroup->grpi3_name;
  235. csTemp += ";";
  236. csTemp += netGroup->grpi3_comment;
  237. csaGroups.AddHead(csTemp);
  238. netGroup++;
  239. }
  240. }
  241. NetApiBufferFree(netGroupBuffer);
  242. }
  243. void CLUsers::OnAddButton()
  244. {
  245. UpdateData(TRUE);
  246. // start with the domain or machine name to create the account information
  247. CString csValue = m_csDomainName;
  248. if (csValue.Left(2) == _T("\\\\"))
  249. csValue = csValue.Right(csValue.GetLength() - 2);
  250. csValue += "\\";
  251. csValue += m_csAvailableUserList.Left(m_csAvailableUserList.Find(_T(";")));;
  252. if (m_lbAddedUserList.FindString(-1, csValue) == LB_ERR)
  253. m_lbAddedUserList.AddString(csValue, m_lbAvailableUserList.GetItemData(m_lbAvailableUserList.GetCurSel()));
  254. /*
  255. // start with the domain or machine name to create the account information
  256. CString csValue = m_csDomainName;
  257. if (csValue.Left(2) == _T("\\\\"))
  258. csValue = csValue.Right(csValue.GetLength() - 2);
  259. csValue += "\\";
  260. INT* pnItems;
  261. m_lbAvailableUserList.GetSelItems(1024, pnItems);
  262. USHORT sCount = 0;
  263. while (sCount < m_lbAvailableUserList.GetSelCount())
  264. {
  265. CString csUserName = csValue;
  266. CString csSelItem;
  267. m_lbAvailableUserList.GetText(*pnItems, csSelItem);
  268. csUserName += csSelItem.Left(csSelItem.Find(_T(";")));
  269. if (m_lbAddedUserList.FindString(-1, csUserName) == LB_ERR)
  270. m_lbAddedUserList.AddString(csUserName,
  271. m_lbAvailableUserList.GetItemData(*pnItems));
  272. pnItems++;
  273. sCount++;
  274. }
  275. */
  276. }
  277. LRESULT CLUsers::OnWizardBack()
  278. {
  279. CRomaineApp* pApp = (CRomaineApp*)AfxGetApp();
  280. if (pApp->m_bServer) return IDD_GROUP_TYPE_DLG;
  281. else if (pApp->m_csCmdLine != L"") return IDD_GROUP_LIST_DIALOG;
  282. else if (pApp->m_sMode == 1) return IDD_GROUP_LIST_DIALOG;
  283. else return IDD_LR_DIALOG;
  284. }
  285. LRESULT CLUsers::OnWizardNext()
  286. {
  287. CRomaineApp* pApp = (CRomaineApp*)AfxGetApp();
  288. pApp->m_cps1.SetWizardButtons(PSWIZB_FINISH | PSWIZB_BACK);
  289. // empty the list
  290. pApp->m_csaNames.RemoveAll();
  291. // fill with new names.
  292. USHORT us;
  293. CString csTemp;
  294. for (us = 0; us < m_lbAddedUserList.GetCount(); us++)
  295. {
  296. m_lbAddedUserList.GetText(us, csTemp);
  297. pApp->m_csaNames.AddHead(csTemp);
  298. }
  299. return IDD_FINISH_DLG;
  300. }
  301. void CLUsers::OnSelchangeDomainCombo()
  302. {
  303. UpdateData(TRUE);
  304. m_lbAvailableUserList.ResetContent();
  305. if (m_csDomainName.Left(2) == "\\\\")
  306. CatalogAccounts((const TCHAR*)m_csDomainName, m_lbAvailableUserList, TRUE);
  307. else
  308. CatalogAccounts((const TCHAR*)m_csDomainName, m_lbAvailableUserList);
  309. //#ifdef KKBUGFIX
  310. m_lbAvailableUserList.SetCurSel(0);
  311. //#endif
  312. }
  313. void CLUsers::OnShowWindow(BOOL bShow, UINT nStatus)
  314. {
  315. CPropertyPage::OnShowWindow(bShow, nStatus);
  316. CRomaineApp* pApp = (CRomaineApp*)AfxGetApp();
  317. CWaitCursor wait;
  318. if (bShow)
  319. {
  320. if (m_csServer != pApp->m_csServer)
  321. {
  322. m_csServer = pApp->m_csServer;
  323. m_lbAddedUserList.ResetContent();
  324. }
  325. // on a rerun clean out the members from the last group
  326. else if (pApp->bRestart2)
  327. {
  328. m_lbAddedUserList.ResetContent();
  329. pApp->bRestart2 = FALSE;
  330. }
  331. else return;
  332. m_csDomainList.ResetContent();
  333. // get domain list
  334. CWaitCursor wait;
  335. CTrustList pList;
  336. if (!pList.BuildTrustList((LPTSTR)pApp->m_csServer.GetBuffer(pApp->m_csServer.GetLength())))
  337. {
  338. AfxMessageBox(IDS_NO_WKSALLOWED);
  339. pApp->m_cps1.SetActivePage(1);
  340. return;
  341. }
  342. UINT i;
  343. for(i = 0 ; i < pList.m_dwTrustCount ; i++)
  344. m_csDomainList.AddString(pList.m_ppszTrustList[i]);
  345. // remove the current machine from the list
  346. if ((i = m_csDomainList.FindStringExact(-1, pApp->m_csServer.Right(pApp->m_csServer.GetLength() - 2))) != LB_ERR)
  347. m_csDomainList.DeleteString(i);
  348. // put machine name into list (assuming we are adding to a machine and not a domain)
  349. if (!pApp->m_bDomain) m_csDomainList.AddString(pApp->m_csServer);
  350. // get primary domain
  351. DWORD dwRet;
  352. HKEY hKey;
  353. DWORD cbProv = 0;
  354. TCHAR* lpProv = NULL;
  355. CRomaineApp* pApp = (CRomaineApp*)AfxGetApp();
  356. long lRet = RegConnectRegistry(
  357. (LPTSTR)pApp->m_csServer.GetBuffer(pApp->m_csServer.GetLength()),
  358. HKEY_LOCAL_MACHINE,
  359. &hKey);
  360. dwRet = RegOpenKey(hKey,
  361. TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), &hKey );
  362. TCHAR* lpPrimaryDomain = NULL;
  363. if ((dwRet = RegQueryValueEx( hKey, TEXT("CachePrimaryDomain"), NULL, NULL, NULL, &cbProv )) == ERROR_SUCCESS)
  364. {
  365. lpPrimaryDomain = (TCHAR*)malloc(cbProv);
  366. if (lpPrimaryDomain == NULL)
  367. {
  368. AfxMessageBox(IDS_GENERIC_NO_HEAP, MB_ICONEXCLAMATION);
  369. exit(1);
  370. }
  371. dwRet = RegQueryValueEx( hKey, TEXT("CachePrimaryDomain"), NULL, NULL, (LPBYTE) lpPrimaryDomain, &cbProv );
  372. }
  373. m_csPrimaryDomain = lpPrimaryDomain;
  374. free(lpPrimaryDomain);
  375. RegCloseKey(hKey);
  376. CatalogAccounts((const TCHAR*)m_csPrimaryDomain, m_lbAvailableUserList);
  377. //#ifdef KKBUGFIX
  378. if (m_csDomainList.SelectString(-1, (const TCHAR*)m_csPrimaryDomain ) == CB_ERR)
  379. {
  380. CatalogAccounts((const TCHAR*)m_csServer, m_lbAvailableUserList,TRUE);
  381. m_csDomainList.SelectString(-1, (const TCHAR*)m_csServer);
  382. }
  383. //#else
  384. else m_csDomainList.SelectString(-1, (const TCHAR*)m_csPrimaryDomain);
  385. //#endif
  386. GetDlgItem(IDC_AVAILABLE_LOCAL_USERS)->SetFocus();
  387. m_lbAvailableUserList.SetCurSel(0);
  388. // editing a group? add the current members
  389. if (pApp->m_sMode == 1)
  390. {
  391. DWORD dwEntriesRead;
  392. DWORD dwTotalEntries;
  393. DWORD dwResumeHandle = 0;
  394. // m_lbAddedUserList.ResetContent();
  395. TCHAR* pServer = pApp->m_csServer.GetBuffer(pApp->m_csServer.GetLength());
  396. pApp->m_csServer.ReleaseBuffer();
  397. TCHAR* pGroup = pApp->m_csGroupName.GetBuffer(pApp->m_csGroupName.GetLength());
  398. pApp->m_csGroupName.ReleaseBuffer();
  399. PLOCALGROUP_MEMBERS_INFO_1 pMembers;
  400. NET_API_STATUS nApi = NetLocalGroupGetMembers(pServer,
  401. pGroup,
  402. 1,
  403. (LPBYTE*)&pMembers,
  404. 5000,
  405. &dwEntriesRead,
  406. &dwTotalEntries,
  407. &dwResumeHandle);
  408. if (nApi != ERROR_SUCCESS) return;
  409. USHORT sIndex;
  410. for (sIndex = 0; sIndex < dwEntriesRead; sIndex++)
  411. {
  412. TCHAR pName[50];
  413. DWORD dwNameSize = 50;
  414. TCHAR pDomain[50];
  415. DWORD dwDomainNameSize = 50;
  416. SID_NAME_USE pUse;
  417. LookupAccountSid(pServer, pMembers[sIndex].lgrmi1_sid,
  418. pName, &dwNameSize,
  419. pDomain, &dwDomainNameSize,
  420. &pUse);
  421. wchar_t sTemp[150];
  422. swprintf(sTemp, TEXT("%s\\%s"), pDomain, pName);
  423. if (pUse == 1) m_lbAddedUserList.AddString(0, sTemp);
  424. else m_lbAddedUserList.AddString(1, sTemp);
  425. }
  426. NetApiBufferFree(pMembers);
  427. while (dwResumeHandle != 0)
  428. {
  429. nApi = NetLocalGroupGetMembers(pServer,
  430. pGroup,
  431. 1,
  432. (LPBYTE*)&pMembers,
  433. 5000,
  434. &dwEntriesRead,
  435. &dwTotalEntries,
  436. &dwResumeHandle);
  437. if (nApi != ERROR_SUCCESS) return;
  438. USHORT sIndex;
  439. for (sIndex = 0; sIndex < dwEntriesRead; sIndex++)
  440. {
  441. TCHAR pName[50];
  442. DWORD dwNameSize = 50;
  443. TCHAR pDomain[50];
  444. DWORD dwDomainNameSize = 50;
  445. SID_NAME_USE pUse;
  446. LookupAccountSid(pServer, pMembers[sIndex].lgrmi1_sid,
  447. pName, &dwNameSize,
  448. pDomain, &dwDomainNameSize,
  449. &pUse);
  450. wchar_t sTemp[150];
  451. swprintf(sTemp, TEXT("%s\\%s"), pDomain, pName);
  452. if (pUse == 1) m_lbAddedUserList.AddString(0, sTemp);
  453. else m_lbAddedUserList.AddString(1, sTemp);
  454. }
  455. NetApiBufferFree(pMembers);
  456. }
  457. }
  458. }
  459. }
  460. void CLUsers::OnDblclkAddedLocalUsers()
  461. {
  462. // CString csSelItem;
  463. // int nSel = m_lbAddedUserList.GetCaretIndex();
  464. // m_lbAddedUserList.DeleteString(nSel);
  465. m_lbAddedUserList.DeleteString(m_lbAddedUserList.GetCurSel());
  466. }
  467. void CLUsers::OnDblclkAvailableLocalUsers()
  468. {
  469. UpdateData(TRUE);
  470. // start with the domain or machine name to create the account information
  471. CString csValue = m_csDomainName;
  472. if (csValue.Left(2) == _T("\\\\"))
  473. csValue = csValue.Right(csValue.GetLength() - 2);
  474. csValue += "\\";
  475. csValue += m_csAvailableUserList.Left(m_csAvailableUserList.Find(_T(";")));;
  476. if (m_lbAddedUserList.FindString(-1, csValue) == LB_ERR)
  477. m_lbAddedUserList.AddString(csValue, m_lbAvailableUserList.GetItemData(m_lbAvailableUserList.GetCurSel()));
  478. // start with the domain or machine name to create the account information
  479. /* CString csValue = m_csDomainName;
  480. if (csValue.Left(2) == _T("\\\\"))
  481. csValue = csValue.Right(csValue.GetLength() - 2);
  482. csValue += "\\";
  483. CString csSelItem;
  484. int nSel = m_lbAvailableUserList.GetCaretIndex();
  485. m_lbAvailableUserList.GetText(nSel, csSelItem);
  486. csValue += csSelItem.Left(csSelItem.Find(_T(";")));
  487. if (m_lbAddedUserList.FindString(-1, csValue) == LB_ERR)
  488. m_lbAddedUserList.AddString(csValue, m_lbAvailableUserList.GetItemData(nSel));
  489. */
  490. }
  491. void CLUsers::OnSetfocusAvailableLocalUsers()
  492. {
  493. GetDlgItem(IDC_ADD_BUTTON)->EnableWindow(TRUE);
  494. GetDlgItem(IDC_REMOVE_BUTTON)->EnableWindow(FALSE);
  495. m_lbAddedUserList.SetCurSel(-1);
  496. }
  497. void CLUsers::OnSetfocusAddedLocalUsers()
  498. {
  499. GetDlgItem(IDC_ADD_BUTTON)->EnableWindow(FALSE);
  500. GetDlgItem(IDC_REMOVE_BUTTON)->EnableWindow(TRUE);
  501. m_lbAvailableUserList.SetCurSel(-1);
  502. }
  503. void CLUsers::OnRemoveButton()
  504. {
  505. /* INT* pnItems;
  506. m_lbAddedUserList.GetSelItems(1024, pnItems);
  507. USHORT sCount = 0;
  508. while (sCount < m_lbAddedUserList.GetSelCount())
  509. {
  510. // m_lbAddedUserList.DeleteString(*pnItems);
  511. TRACE(L"Item = %d\n\r", *pnItems);
  512. pnItems++;
  513. sCount++;
  514. }
  515. */
  516. m_lbAddedUserList.DeleteString(m_lbAddedUserList.GetCurSel());
  517. m_lbAddedUserList.SetCurSel(0);
  518. }