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.

735 lines
20 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation 1996-2001.
  5. //
  6. // File: addgrp.cpp
  7. //
  8. // Contents: implementation of CSCEAddGroup
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. #include "wsecmgr.h"
  13. #include "AddGrp.h"
  14. #include "snapmgr.h"
  15. #include "GetUser.h"
  16. #include "resource.h"
  17. #include "util.h"
  18. #ifdef _DEBUG
  19. #define new DEBUG_NEW
  20. #undef THIS_FILE
  21. static char THIS_FILE[] = __FILE__;
  22. #endif
  23. /////////////////////////////////////////////////////////////////////////////
  24. // CSCEAddGroup dialog
  25. CSCEAddGroup::CSCEAddGroup(CWnd* pParent /*=NULL*/)
  26. : CHelpDialog(a212HelpIDs, IDD, pParent)
  27. {
  28. m_dwFlags = SCE_SHOW_GROUPS | SCE_SHOW_ALIASES | SCE_SHOW_SINGLESEL;
  29. m_pnlGroup = NULL;
  30. m_pKnownNames = NULL;
  31. m_fCheckName = TRUE;
  32. //{{AFX_DATA_INIT(CSCEAddGroup)
  33. // NOTE: the ClassWizard will add member initialization here
  34. //}}AFX_DATA_INIT
  35. }
  36. CSCEAddGroup::~CSCEAddGroup()
  37. {
  38. SceFreeMemory( m_pnlGroup, SCE_STRUCT_NAME_LIST );
  39. m_pnlGroup = NULL;
  40. SceFreeMemory( m_pKnownNames, SCE_STRUCT_NAME_LIST );
  41. m_pKnownNames = NULL;
  42. }
  43. void CSCEAddGroup::DoDataExchange(CDataExchange* pDX)
  44. {
  45. CDialog::DoDataExchange(pDX);
  46. //{{AFX_DATA_MAP(CSCEAddGroup)
  47. // NOTE: the ClassWizard will add DDX and DDV calls here
  48. //}}AFX_DATA_MAP
  49. }
  50. DWORD CSCEAddGroup::GetModeFlags() {
  51. if (m_dwModeBits & MB_GROUP_POLICY) {
  52. return (SCE_SHOW_SCOPE_DOMAIN | SCE_SHOW_SCOPE_DIRECTORY);
  53. }
  54. if (m_dwModeBits & MB_LOCAL_POLICY) {
  55. return (SCE_SHOW_SCOPE_ALL | SCE_SHOW_DIFF_MODE_OFF_DC);
  56. }
  57. if (m_dwModeBits & MB_ANALYSIS_VIEWER) {
  58. return (SCE_SHOW_SCOPE_ALL | SCE_SHOW_DIFF_MODE_OFF_DC);
  59. }
  60. if (m_dwModeBits & MB_TEMPLATE_EDITOR) {
  61. return (SCE_SHOW_SCOPE_ALL);
  62. }
  63. return 0;
  64. }
  65. BEGIN_MESSAGE_MAP(CSCEAddGroup, CHelpDialog)
  66. //{{AFX_MSG_MAP(CSCEAddGroup)
  67. ON_BN_CLICKED(IDC_BROWSE, OnBrowse)
  68. ON_EN_CHANGE(IDC_LOG_FILE, OnChangeLogFile)
  69. ON_NOTIFY( EN_MSGFILTER, IDC_LOG_FILE, OnEditMsgFilter )
  70. //}}AFX_MSG_MAP
  71. END_MESSAGE_MAP()
  72. /////////////////////////////////////////////////////////////////////////////
  73. // CSCEAddGroup message handlers
  74. /*-------------------------------------------------------------------------------------
  75. CSCEAddGroup::IsKnownAccount
  76. Synopsis: This functions searches throught m_pKnownNames and does a case
  77. insensitive match on [pszAccount]. If [pszAccount] exists in the
  78. array then this function returns TRUE.
  79. Arguments: [pszAccount] - The account to look for.
  80. Returns: TRUE if [pszAccount] is in the list false otherwise
  81. -------------------------------------------------------------------------------------*/
  82. BOOL CSCEAddGroup::IsKnownAccount( LPCTSTR pszAccount )
  83. {
  84. if ( pszAccount == NULL ) return FALSE;
  85. PSCE_NAME_LIST pNew = m_pKnownNames;
  86. while(pNew){
  87. if( !lstrcmpi( pszAccount, pNew->Name ) ){
  88. return TRUE;
  89. }
  90. pNew = pNew->Next;
  91. }
  92. return FALSE;
  93. }
  94. /*------------------------------------------------------------------------------------
  95. CSCEAddGroup::CleanName
  96. Synopsis: Removes leading and trailing spaces from the string. This function
  97. places the string into the same buffer as is passed in.
  98. Arguments: [pszAccount] - The buffer to clean.
  99. ------------------------------------------------------------------------------------*/
  100. void CSCEAddGroup::CleanName( LPTSTR pszAccount )
  101. {
  102. if ( pszAccount == NULL ) return;
  103. int i = 0;
  104. while( IsSpace( pszAccount[i] ) ){
  105. i++;
  106. }
  107. int iLen = lstrlen(pszAccount) - 1;
  108. while(iLen > i && IsSpace( pszAccount[iLen] ) ){
  109. iLen--;
  110. }
  111. iLen -= i;
  112. while(iLen >= 0){
  113. *pszAccount = *(pszAccount + i);
  114. pszAccount++;
  115. iLen--;
  116. }
  117. *pszAccount = 0;
  118. }
  119. /*------------------------------------------------------------------------------------
  120. CSCEAddGroup::AddKnownAccount
  121. Synopsis: Adds a string to the Known accounts link list. This list is later
  122. used to underline strings that are contained in this list
  123. Arguments: [pszAccount] - The account to remeber.
  124. ------------------------------------------------------------------------------------*/
  125. BOOL CSCEAddGroup::AddKnownAccount( LPCTSTR pszAccount )
  126. {
  127. PSCE_NAME_LIST pNew = NULL;
  128. if ( pszAccount == NULL ) return FALSE;
  129. if(IsKnownAccount( pszAccount ) ){
  130. return TRUE;
  131. }
  132. pNew = (PSCE_NAME_LIST)LocalAlloc(0, sizeof(SCE_NAME_LIST));
  133. if(!pNew){
  134. return FALSE;
  135. }
  136. pNew->Name = (LPTSTR)LocalAlloc( 0, sizeof(TCHAR) * (1 + lstrlen(pszAccount)) );
  137. if(!pNew->Name){
  138. LocalFree(pNew);
  139. return FALSE;
  140. }
  141. lstrcpy(pNew->Name, pszAccount);
  142. pNew->Next = m_pKnownNames;
  143. m_pKnownNames = pNew;
  144. return TRUE;
  145. }
  146. /*------------------------------------------------------------------------------------
  147. CSCEAddGroup::OnBrowse
  148. Synopsis: Calls the CGetUser dialog box to create the object picker and display
  149. real choices. Since we wan't to underline all names returned by
  150. object picker, this function also places all names returned by
  151. CGetUser into the known accounts array.
  152. ------------------------------------------------------------------------------------*/
  153. void CSCEAddGroup::OnBrowse()
  154. {
  155. CGetUser gu;
  156. BOOL bFailed = TRUE;
  157. //
  158. // Get the rich edit control.
  159. //
  160. CRichEditCtrl *ed = (CRichEditCtrl *)GetDlgItem(IDC_LOG_FILE);
  161. if ( ed ) {
  162. //
  163. // Always multi select mode.
  164. //
  165. m_dwFlags &= ~SCE_SHOW_SINGLESEL;
  166. if (gu.Create( GetSafeHwnd(), m_dwFlags | GetModeFlags()) ) {
  167. //
  168. // Set the dialog text.
  169. // pAccount is a pointer to a member in getuser.cpp which will be freed there
  170. //
  171. PSCE_NAME_LIST pAccount = gu.GetUsers();
  172. //
  173. // Set the charformat, because we need to set it not to underline
  174. // things that we will paste into the edit control.
  175. //
  176. CHARFORMAT cf;
  177. ZeroMemory(&cf, sizeof( CHARFORMAT ));
  178. cf.cbSize = sizeof(CHARFORMAT);
  179. cf.dwMask = CFM_UNDERLINE;
  180. //
  181. // Enumerate through the account list and past them into the edit control.
  182. //
  183. int iLen;
  184. bFailed = FALSE;
  185. while (pAccount) {
  186. if(pAccount->Name){
  187. iLen = ed->GetTextLength();
  188. ed->SetSel( iLen, iLen);
  189. if(iLen){
  190. ed->SetSelectionCharFormat( cf );
  191. ed->ReplaceSel( L";" );
  192. iLen ++;
  193. }
  194. if ( AddKnownAccount( pAccount->Name ) ) {
  195. ed->ReplaceSel( pAccount->Name );
  196. } else {
  197. bFailed = TRUE;
  198. }
  199. }
  200. pAccount = pAccount->Next;
  201. }
  202. //
  203. // Everything we pasted will be underlined.
  204. //
  205. UnderlineNames();
  206. }
  207. }
  208. if ( bFailed ) {
  209. //
  210. // something is wrong creating the object picker or pasting the account into the control
  211. // popup a message
  212. //
  213. CString strErr;
  214. strErr.LoadString( IDS_ERR_INVALIDACCOUNT );
  215. AfxMessageBox( strErr );
  216. }
  217. }
  218. /*-------------------------------------------------------------------------------------
  219. CSCEAddGroup::OnInitDialog()
  220. Synopsis: Change the text for title and group static box. To "Add Group" and
  221. "Group"
  222. -------------------------------------------------------------------------------------*/
  223. BOOL CSCEAddGroup::OnInitDialog()
  224. {
  225. CDialog::OnInitDialog();
  226. CString str;
  227. //
  228. // Set the window title. If the caller has already set the title then
  229. // we don't need to load the resource.
  230. //
  231. if(m_sTitle.IsEmpty()){
  232. // Set window text of dialog.
  233. m_sTitle.LoadString(IDS_ADDGROUP_TITLE);
  234. }
  235. if(m_sDescription.IsEmpty()){
  236. m_sDescription.LoadString(IDS_ADDGROUP_GROUP);
  237. }
  238. SetWindowText( m_sTitle );
  239. // Set group static text.
  240. CWnd *pWnd = GetDlgItem(IDC_STATIC_FILENAME);
  241. if (pWnd) {
  242. pWnd->SetWindowText(m_sDescription);
  243. }
  244. pWnd = GetDlgItem(IDC_LOG_FILE);
  245. if ( pWnd )
  246. {
  247. pWnd->SendMessage(EM_SETEVENTMASK, 0, ENM_CHANGE | ENM_KEYEVENTS);
  248. pWnd->SendMessage(EM_LIMITTEXT, 4096, 0); //Raid #271219
  249. }
  250. // disable OK button.
  251. pWnd = GetDlgItem(IDOK);
  252. if ( pWnd )
  253. pWnd->EnableWindow( FALSE );
  254. return TRUE; // return TRUE unless you set the focus to a control
  255. // EXCEPTION: OCX Property Pages should return FALSE
  256. }
  257. /*-------------------------------------------------------------------------------------
  258. CSCEAddGroup::OnChangeLogFile()
  259. Synopsis: Check to see if any text is available in edit control, and disable the
  260. OK button if no text is available.
  261. -------------------------------------------------------------------------------------*/
  262. void CSCEAddGroup::OnChangeLogFile()
  263. {
  264. // Enable disable edit OK button depending on edit control content.
  265. CRichEditCtrl *pWnd = reinterpret_cast<CRichEditCtrl *>(GetDlgItem(IDC_LOG_FILE));
  266. CString str;
  267. str.Empty();
  268. if (pWnd) {
  269. pWnd->GetWindowText(str);
  270. }
  271. CWnd *pControl = GetDlgItem(IDOK);
  272. if ( pControl )
  273. pControl->EnableWindow( !str.IsEmpty() );
  274. }
  275. /*-------------------------------------------------------------------------------------
  276. CSCEAddGroup::UnderlineNames
  277. Synopsis: Underlines all names that are in the KnownAccounts list.
  278. -------------------------------------------------------------------------------------*/
  279. void CSCEAddGroup::UnderlineNames()
  280. {
  281. LONG nStart, nEnd;
  282. //
  283. // Get the edit control.
  284. //
  285. CRichEditCtrl *pWnd = reinterpret_cast<CRichEditCtrl *>(GetDlgItem(IDC_LOG_FILE));
  286. if(!pWnd){
  287. return;
  288. }
  289. LPTSTR pszText = NULL;
  290. int iPos, iLen, i;
  291. //
  292. // Retrieve the edit control text.
  293. //
  294. iLen = pWnd->GetWindowTextLength();
  295. pszText = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR) * (2 + iLen) );
  296. if(!pszText){
  297. return;
  298. }
  299. pWnd->GetWindowText(pszText, iLen+1);
  300. iPos = 0;
  301. //
  302. // Get the current selection (the position of the caret)
  303. //
  304. pWnd->GetSel(nStart, nEnd );
  305. //
  306. // Hide the window so it doesn't flicker.
  307. //
  308. pWnd->SetWindowPos( NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSENDCHANGING);
  309. for(i = 0; i < iLen + 1; i++){
  310. //
  311. // Simi colon deliminated list.
  312. //
  313. if( pszText[i] == L';' ){
  314. pszText[i] = 0;
  315. }
  316. if(!pszText[i]){
  317. //
  318. // Format known names with underline.
  319. //
  320. CHARFORMAT cf;
  321. cf.cbSize = sizeof( CHARFORMAT );
  322. cf.dwMask = CFM_UNDERLINE;
  323. int isUn, ieUn;
  324. isUn = iPos;
  325. while( IsSpace(pszText[isUn]) ){
  326. isUn++;
  327. }
  328. ieUn = lstrlen( &(pszText[isUn]) ) - 1 + isUn;
  329. while( ieUn > 0 && IsSpace( pszText[ieUn] ) ){
  330. ieUn--;
  331. }
  332. //
  333. // See if we need to underline the name or not.
  334. //
  335. CleanName( &(pszText[isUn]) );
  336. if( IsKnownAccount( &(pszText[isUn]) ) ){
  337. cf.dwEffects = CFE_UNDERLINE;
  338. } else {
  339. cf.dwEffects &= ~CFE_UNDERLINE;
  340. }
  341. //
  342. // Make sure leading space characters aren't underlined.
  343. //
  344. if(isUn != iPos && cf.dwEffects & CFE_UNDERLINE){
  345. pWnd->SetSel( iPos, isUn);
  346. cf.dwEffects = 0;
  347. pWnd->SetSelectionCharFormat( cf );
  348. cf.dwEffects = CFE_UNDERLINE;
  349. } else {
  350. isUn = iPos;
  351. }
  352. //
  353. // trailing space characters are also not underlined.
  354. //
  355. if(cf.dwEffects & CFE_UNDERLINE){
  356. pWnd->SetSel(ieUn, i + 1);
  357. cf.dwEffects = 0;
  358. pWnd->SetSelectionCharFormat( cf );
  359. cf.dwEffects = CFE_UNDERLINE;
  360. } else {
  361. ieUn = i;
  362. }
  363. pWnd->SetSel( isUn, ieUn + 1);
  364. pWnd->SetSelectionCharFormat( cf );
  365. iPos = i + 1;
  366. }
  367. }
  368. //
  369. // Show the window without redrawing. We will call RedrawWindow to redraw.
  370. //
  371. pWnd->SetWindowPos( NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOREDRAW);
  372. pWnd->RedrawWindow(NULL, NULL, RDW_INVALIDATE);
  373. //
  374. // Reset selection.
  375. //
  376. pWnd->SetSel(nStart, nEnd);
  377. }
  378. /*------------------------------------------------------------------------------------
  379. CSCEAddGroup::OnEditMsgFilter
  380. Synopsis: Captures input message events from the RichEdit control. We want,
  381. to underline things as the user types them.
  382. Arguments: [pNM] - [in] Pointer to a MSGFILTER structure.
  383. [pResult]- [out] Pointer to a LRESULT type. Always set to 0
  384. ------------------------------------------------------------------------------------*/
  385. void CSCEAddGroup::OnEditMsgFilter( NMHDR *pNM, LRESULT *pResult)
  386. {
  387. *pResult = 0;
  388. #define pmf ((MSGFILTER *)pNM)
  389. switch( pmf->msg ){
  390. case WM_LBUTTONUP:
  391. case WM_KEYUP:
  392. //
  393. // If the caret is being moved around in the window then we don't want
  394. // to proccess the string since it isn't being changed.
  395. //
  396. if( pmf->msg == WM_KEYUP && pmf->wParam == VK_RIGHT ||
  397. pmf->wParam == VK_LEFT || pmf->wParam == VK_UP || pmf->wParam == VK_DOWN){
  398. break;
  399. }
  400. UnderlineNames();
  401. break;
  402. }
  403. #undef pmf
  404. }
  405. /*-------------------------------------------------------------------------------------
  406. CSCEAddGroup::CSCEAddGroup::OnOK()
  407. Synopsis: Copy the text the user input into the SCE_NAME_LIST structure.
  408. -------------------------------------------------------------------------------------*/
  409. void CSCEAddGroup::OnOK()
  410. {
  411. if( !CheckNames() ){
  412. return;
  413. }
  414. CreateNameList( &m_pnlGroup );
  415. CDialog::OnOK();
  416. }
  417. /*------------------------------------------------------------------------------------
  418. CSCEAddGroup::CreateNameList
  419. Synopsis: Creates the name list from the edit window. The function will ensure
  420. that each name is only in the list once.
  421. Arguments: [pNameList] -[out] Pointer a PSCE_NAME_LIST;
  422. Returns: The number of items added.
  423. ------------------------------------------------------------------------------------*/
  424. int CSCEAddGroup::CreateNameList( PSCE_NAME_LIST *pNameList )
  425. {
  426. if(!pNameList){
  427. return 0;
  428. }
  429. CWnd *pWnd = GetDlgItem(IDC_LOG_FILE);
  430. LPTSTR pszAccounts = NULL;
  431. //
  432. // Retrieve the window text.
  433. //
  434. int iLen = 0;
  435. if (pWnd) {
  436. iLen = pWnd->GetWindowTextLength();
  437. if(iLen){
  438. pszAccounts = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR) * (iLen + 2));
  439. if(pszAccounts){
  440. pWnd->GetWindowText( pszAccounts, iLen+1);
  441. }
  442. }
  443. }
  444. //
  445. // Create an account name for each string daliminated by a semi colon.
  446. //
  447. int iCount = 0;
  448. if (pszAccounts) {
  449. LPTSTR pszCur = pszAccounts;
  450. int Len=0;
  451. for(int i = 0; i < iLen + 1; i++){
  452. if( pszAccounts[i] == L';' ){
  453. pszAccounts[i] = 0;
  454. }
  455. if( !pszAccounts[i] ){
  456. CleanName(pszCur);
  457. if((Len = lstrlen(pszCur))){
  458. //
  459. // Ensure that we don't already have this string in our link list.
  460. //
  461. PSCE_NAME_LIST pNew = NULL;
  462. pNew = *pNameList;
  463. while(pNew){
  464. if(!lstrcmpi( pNew->Name, pszCur ) ){
  465. pszCur[0] = 0;
  466. break;
  467. }
  468. pNew = pNew->Next;
  469. }
  470. if(pszCur[0]){
  471. //
  472. // Create a new link.
  473. //
  474. SceAddToNameList( pNameList, pszCur, Len);
  475. }
  476. }
  477. //
  478. // Next string to check.
  479. //
  480. pszCur = pszAccounts + i + 1;
  481. }
  482. }
  483. }
  484. return TRUE;
  485. }
  486. /*------------------------------------------------------------------------------------
  487. CSCEAddGroup::CheckNames
  488. Synopsis: Verifies the account the user has added. This function will display an
  489. error message box if any accounts are found to be in err. .
  490. Returns: TRUE if all names are valid, FALSE otherwise.
  491. ------------------------------------------------------------------------------------*/
  492. BOOL CSCEAddGroup::CheckNames()
  493. {
  494. PSCE_NAME_LIST pNameList = NULL;
  495. PSCE_NAME_LIST pErrList = NULL;
  496. if( !m_fCheckName ) //Raid #404989
  497. {
  498. return TRUE;
  499. }
  500. BOOL bErr = TRUE;
  501. if( !CreateNameList( &pNameList ) ){
  502. return TRUE;
  503. }
  504. CString tempstr; //raid #387570, #387739
  505. int iFind = -1;
  506. PSCE_NAME_LIST pNext = pNameList;
  507. while(pNext)
  508. {
  509. tempstr = pNext->Name;
  510. iFind = tempstr.FindOneOf(IDS_INVALID_USERNAME_CHARS);
  511. if( iFind == 0 )
  512. {
  513. CString text;
  514. CString charsWithSpaces;
  515. PCWSTR szInvalidCharSet = IDS_INVALID_USERNAME_CHARS;
  516. UINT nIndex = 0;
  517. while (szInvalidCharSet[nIndex])
  518. {
  519. charsWithSpaces += szInvalidCharSet[nIndex];
  520. charsWithSpaces += L" ";
  521. nIndex++;
  522. }
  523. text.FormatMessage (IDS_INVALID_STRING, charsWithSpaces);
  524. AfxMessageBox(text);
  525. GetDlgItem(IDC_LOG_FILE)->SetFocus();
  526. return FALSE;
  527. }
  528. pNext = pNext->Next;
  529. }
  530. pNext = pNameList;
  531. while(pNext){
  532. LPTSTR pszStr = pNext->Name;
  533. if(!IsKnownAccount(pNext->Name)){
  534. BOOL fname = FALSE;
  535. while( pszStr && *pszStr ){
  536. if( *pszStr == L'\\' ){
  537. fname = TRUE;
  538. SID_NAME_USE su = CGetUser::GetAccountType( pNext->Name );
  539. if( su == SidTypeInvalid || su == SidTypeUnknown ||
  540. !AddKnownAccount(pNext->Name) ){
  541. PSCE_NAME_LIST pNew = (PSCE_NAME_LIST)LocalAlloc( 0, sizeof(SCE_NAME_LIST));
  542. if(pNew){
  543. pNew->Name = pNext->Name;
  544. pNew->Next = pErrList;
  545. pErrList = pNew;
  546. }
  547. } else {
  548. UnderlineNames();
  549. }
  550. break;
  551. }
  552. pszStr++;
  553. }
  554. if( !fname ) //Raid #404989
  555. {
  556. SID_NAME_USE su = CGetUser::GetAccountType( pNext->Name );
  557. if( su == SidTypeInvalid || su == SidTypeUnknown ||
  558. !AddKnownAccount(pNext->Name) ){
  559. PSCE_NAME_LIST pNew = (PSCE_NAME_LIST)LocalAlloc( 0, sizeof(SCE_NAME_LIST));
  560. if(pNew){
  561. pNew->Name = pNext->Name;
  562. pNew->Next = pErrList;
  563. pErrList = pNew;
  564. }
  565. } else {
  566. UnderlineNames();
  567. }
  568. }
  569. }
  570. pNext = pNext->Next;
  571. }
  572. if( pErrList ){
  573. CString strErr;
  574. strErr.LoadString( IDS_ERR_INVALIDACCOUNT );
  575. pNext = pErrList;
  576. while(pNext){
  577. pErrList = pNext->Next;
  578. strErr += pNext->Name;
  579. if(pErrList){
  580. strErr += L',';
  581. }
  582. LocalFree(pNext);
  583. pNext = pErrList;
  584. }
  585. AfxMessageBox( strErr );
  586. bErr = FALSE;
  587. }
  588. SceFreeMemory( pNameList, SCE_STRUCT_NAME_LIST );
  589. return bErr;
  590. }
  591. void CSCEAddGroup::OnChecknames()
  592. {
  593. PSCE_NAME_LIST pNameList = NULL;
  594. if( CreateNameList( &pNameList ) ){
  595. PSCE_NAME_LIST pNext = pNameList;
  596. while(pNext){
  597. SID_NAME_USE su = CGetUser::GetAccountType( pNext->Name );
  598. if( su != SidTypeInvalid && su != SidTypeUnknown ){
  599. //
  600. // Add the name.
  601. //
  602. AddKnownAccount( pNext->Name );
  603. }
  604. pNext = pNext->Next;
  605. }
  606. SceFreeMemory( pNameList, SCE_STRUCT_NAME_LIST );
  607. UnderlineNames();
  608. }
  609. }