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.

664 lines
20 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation 1996-2001.
  5. //
  6. // File: getuser.cpp
  7. //
  8. // Contents: implementation of CGetUser
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. #include "wsecmgr.h"
  13. #include "GetUser.h"
  14. #include "util.h"
  15. #include "wrapper.h"
  16. #ifdef _DEBUG
  17. #undef THIS_FILE
  18. static char THIS_FILE[]=__FILE__;
  19. #define new DEBUG_NEW
  20. #endif
  21. const TCHAR c_szSep[] = TEXT("\\");
  22. //////////////////////////////////////////////////////////////////////
  23. // CGetUser Class
  24. //////////////////////////////////////////////////////////////////////
  25. //////////////////////////////////////////////////////////////////////
  26. // Construction/Destruction
  27. //////////////////////////////////////////////////////////////////////
  28. CTypedPtrArray<CPtrArray, PWSCE_ACCOUNTINFO> CGetUser::m_aKnownAccounts;
  29. BOOL IsDomainAccountSid( PSID pSid )
  30. {
  31. if ( pSid == NULL ) {
  32. return(FALSE);
  33. }
  34. if ( !IsValidSid(pSid) ) {
  35. return(FALSE);
  36. }
  37. PISID ISid = (PISID)pSid;
  38. if ( ISid->IdentifierAuthority.Value[5] != 5 ||
  39. ISid->IdentifierAuthority.Value[0] != 0 ||
  40. ISid->IdentifierAuthority.Value[1] != 0 ||
  41. ISid->IdentifierAuthority.Value[2] != 0 ||
  42. ISid->IdentifierAuthority.Value[3] != 0 ||
  43. ISid->IdentifierAuthority.Value[4] != 0 ) {
  44. //
  45. // this is not a account from account domain
  46. //
  47. return(FALSE);
  48. }
  49. if ( ISid->SubAuthorityCount == 0 ||
  50. ISid->SubAuthority[0] != SECURITY_NT_NON_UNIQUE ) {
  51. return(FALSE);
  52. }
  53. return(TRUE);
  54. }
  55. /*------------------------------------------------------------------------------------------------------------
  56. CGetUser::GetAccountType
  57. Synopsis: Returns the type of the user account. Call this function with a NULL to remove saved
  58. account name information.
  59. Arguments: [pszName] - The account name old NT4 format
  60. Returns: One of the enumerated Sid types.
  61. ------------------------------------------------------------------------------------------------------------*/
  62. SID_NAME_USE
  63. CGetUser::GetAccountType(LPCTSTR pszName)
  64. {
  65. if(!pszName){
  66. // Delete the whole list.
  67. for(int i = 0; i < m_aKnownAccounts.GetSize(); i++){
  68. PWSCE_ACCOUNTINFO pAccount = m_aKnownAccounts[i];
  69. if(pAccount){
  70. if(pAccount->pszName){
  71. LocalFree(pAccount->pszName);
  72. }
  73. LocalFree(pAccount);
  74. }
  75. }
  76. m_aKnownAccounts.RemoveAll();
  77. return SidTypeUnknown;
  78. }
  79. // Check to see if we've already got the account.
  80. for(int i = 0; i < m_aKnownAccounts.GetSize(); i++){
  81. if( !lstrcmpi( m_aKnownAccounts[i]->pszName, pszName) ){
  82. return m_aKnownAccounts[i]->sidType;
  83. }
  84. }
  85. PSID sid = NULL;
  86. LPTSTR pszDomain = NULL;
  87. DWORD cbSid = 0,
  88. cbRefDomain = 0;
  89. SID_NAME_USE type = SidTypeUnknown;
  90. LookupAccountName(
  91. NULL,
  92. pszName,
  93. sid,
  94. &cbSid,
  95. NULL,
  96. &cbRefDomain,
  97. &type
  98. );
  99. if(cbSid){
  100. sid = (PSID)LocalAlloc(0, cbSid);
  101. if(!sid){
  102. return SidTypeUnknown;
  103. }
  104. pszDomain = (LPTSTR)LocalAlloc(0, (cbRefDomain + 1) * sizeof(TCHAR));
  105. if(!pszDomain){
  106. cbRefDomain = 0;
  107. }
  108. type = SidTypeUser;
  109. if( LookupAccountName(
  110. NULL,
  111. pszName,
  112. sid,
  113. &cbSid,
  114. pszDomain,
  115. &cbRefDomain,
  116. &type
  117. ) ){
  118. //
  119. // Add the account name to the list.
  120. //
  121. PWSCE_ACCOUNTINFO pNew = (PWSCE_ACCOUNTINFO)LocalAlloc(0, sizeof(WSCE_ACCOUNTINFO));
  122. if(pNew){
  123. pNew->pszName = (LPTSTR)LocalAlloc(0, (lstrlen( pszName ) + 1) * sizeof(TCHAR));
  124. if(!pNew->pszName){
  125. LocalFree(pNew);
  126. LocalFree(sid);
  127. if ( pszDomain ) {
  128. LocalFree(pszDomain);
  129. }
  130. return SidTypeUnknown;
  131. }
  132. lstrcpy(pNew->pszName, pszName);
  133. pNew->sidType = type;
  134. m_aKnownAccounts.Add(pNew);
  135. }
  136. }
  137. LocalFree(sid);
  138. if(pszDomain){
  139. LocalFree(pszDomain);
  140. }
  141. }
  142. return type;
  143. }
  144. CGetUser::CGetUser()
  145. {
  146. m_pszServerName = NULL;
  147. m_pNameList = NULL;
  148. }
  149. CGetUser::~CGetUser()
  150. {
  151. PSCE_NAME_LIST p;
  152. while(m_pNameList) {
  153. p=m_pNameList;
  154. m_pNameList = m_pNameList->Next;
  155. LocalFree(p->Name);
  156. LocalFree(p);
  157. }
  158. }
  159. BOOL CGetUser::Create(HWND hwnd, DWORD nShowFlag)
  160. {
  161. if( m_pNameList ) {
  162. return FALSE;
  163. }
  164. HRESULT hr;
  165. IDsObjectPicker *pDsObjectPicker;
  166. BOOL bRet = TRUE;
  167. PSCE_NAME_LIST pName;
  168. BOOL bDC = IsDomainController( m_pszServerName );
  169. BOOL bHasADsPath;
  170. //
  171. // Initialize and get the Object picker interface.
  172. //
  173. hr = CoInitialize(NULL);
  174. if (!SUCCEEDED(hr)) {
  175. return FALSE;
  176. }
  177. hr = CoCreateInstance(
  178. CLSID_DsObjectPicker,
  179. NULL,
  180. CLSCTX_INPROC_SERVER,
  181. IID_IDsObjectPicker,
  182. (void **) &pDsObjectPicker
  183. );
  184. if(!SUCCEEDED(hr)){
  185. CoUninitialize();
  186. return FALSE;
  187. }
  188. #define SCE_SCOPE_INDEX_DOMAIN 0
  189. #define SCE_SCOPE_INDEX_DIRECTORY 1
  190. #define SCE_SCOPE_INDEX_LOCAL 2
  191. #define SCE_NUM_SCOPE_INDICES 3
  192. DSOP_SCOPE_INIT_INFO aScopes[SCE_NUM_SCOPE_INDICES];
  193. DSOP_SCOPE_INIT_INFO aScopesUsed[SCE_NUM_SCOPE_INDICES];
  194. ZeroMemory(aScopes, sizeof(aScopes));
  195. ZeroMemory(aScopesUsed, sizeof(aScopesUsed));
  196. DWORD dwDownLevel = 0, dwUpLevel = 0;
  197. //
  198. // Users
  199. //
  200. if (nShowFlag & SCE_SHOW_USERS ) {
  201. dwDownLevel |= DSOP_DOWNLEVEL_FILTER_USERS;
  202. dwUpLevel |= DSOP_FILTER_USERS ;
  203. }
  204. if( nShowFlag & SCE_SHOW_LOCALGROUPS ){
  205. dwUpLevel |= DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE;
  206. dwDownLevel |= DSOP_DOWNLEVEL_FILTER_LOCAL_GROUPS | DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS;
  207. }
  208. if( nShowFlag & SCE_SHOW_BUILTIN ){
  209. dwUpLevel |= DSOP_FILTER_BUILTIN_GROUPS;
  210. dwDownLevel |= DSOP_DOWNLEVEL_FILTER_LOCAL_GROUPS | DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS;
  211. } else {
  212. dwDownLevel |= DSOP_DOWNLEVEL_FILTER_EXCLUDE_BUILTIN_GROUPS;
  213. }
  214. //
  215. // Built in groups.
  216. //
  217. if (nShowFlag & SCE_SHOW_GROUPS ) {
  218. dwDownLevel |= DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS | DSOP_DOWNLEVEL_FILTER_LOCAL_GROUPS;
  219. dwUpLevel |= DSOP_FILTER_BUILTIN_GROUPS;
  220. }
  221. //
  222. // Domain groups.
  223. //
  224. if( nShowFlag & (SCE_SHOW_GROUPS | SCE_SHOW_DOMAINGROUPS | SCE_SHOW_ALIASES | SCE_SHOW_GLOBAL) ){
  225. if( !(nShowFlag & SCE_SHOW_LOCALONLY)){
  226. dwUpLevel |= DSOP_FILTER_UNIVERSAL_GROUPS_SE
  227. | DSOP_FILTER_UNIVERSAL_GROUPS_SE
  228. | DSOP_FILTER_GLOBAL_GROUPS_SE
  229. | DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE;
  230. } else if(bDC){
  231. dwDownLevel |= DSOP_DOWNLEVEL_FILTER_AUTHENTICATED_USER;
  232. dwUpLevel |= DSOP_FILTER_GLOBAL_GROUPS_SE
  233. | DSOP_FILTER_UNIVERSAL_GROUPS_SE
  234. | DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE;
  235. }
  236. }
  237. //
  238. //
  239. // principal well known sids.
  240. //
  241. if( (!(nShowFlag & SCE_SHOW_LOCALONLY) &&
  242. nShowFlag & SCE_SHOW_GROUPS &&
  243. nShowFlag & SCE_SHOW_USERS) ||
  244. nShowFlag & SCE_SHOW_WELLKNOWN ){
  245. /*
  246. dwDownLevel |= DSOP_DOWNLEVEL_FILTER_CREATOR_OWNER
  247. | DSOP_DOWNLEVEL_FILTER_CREATOR_GROUP
  248. | DSOP_DOWNLEVEL_FILTER_INTERACTIVE
  249. | DSOP_DOWNLEVEL_FILTER_SYSTEM
  250. | DSOP_DOWNLEVEL_FILTER_AUTHENTICATED_USER
  251. | DSOP_DOWNLEVEL_FILTER_WORLD
  252. | DSOP_DOWNLEVEL_FILTER_ANONYMOUS
  253. | DSOP_DOWNLEVEL_FILTER_BATCH
  254. | DSOP_DOWNLEVEL_FILTER_DIALUP
  255. | DSOP_DOWNLEVEL_FILTER_NETWORK
  256. | DSOP_DOWNLEVEL_FILTER_SERVICE
  257. | DSOP_DOWNLEVEL_FILTER_TERMINAL_SERVER
  258. | DSOP_DOWNLEVEL_FILTER_LOCAL_SERVICE
  259. | DSOP_DOWNLEVEL_FILTER_NETWORK_SERVICE
  260. | DSOP_DOWNLEVEL_FILTER_REMOTE_LOGON;
  261. */
  262. dwDownLevel |= DSOP_DOWNLEVEL_FILTER_ALL_WELLKNOWN_SIDS;
  263. dwUpLevel |= DSOP_FILTER_WELL_KNOWN_PRINCIPALS;
  264. }
  265. DSOP_INIT_INFO InitInfo;
  266. ZeroMemory(&InitInfo, sizeof(InitInfo));
  267. //
  268. // Other attributes that we need object picker to return to use.
  269. //
  270. PCWSTR aAttributes[] = { L"groupType",
  271. L"objectSid" };
  272. InitInfo.cAttributesToFetch = 2;
  273. InitInfo.apwzAttributeNames = aAttributes;
  274. //
  275. // First Item we want to view is the local computer.
  276. //
  277. aScopes[SCE_SCOPE_INDEX_LOCAL].cbSize = sizeof(DSOP_SCOPE_INIT_INFO);
  278. aScopes[SCE_SCOPE_INDEX_LOCAL].flType = DSOP_SCOPE_TYPE_TARGET_COMPUTER;
  279. aScopes[SCE_SCOPE_INDEX_LOCAL].flScope = DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT;
  280. aScopes[SCE_SCOPE_INDEX_LOCAL].FilterFlags.Uplevel.flBothModes = dwUpLevel;
  281. aScopes[SCE_SCOPE_INDEX_LOCAL].FilterFlags.flDownlevel = dwDownLevel;
  282. //
  283. // Flags for the domain we're joined to.
  284. //
  285. aScopes[SCE_SCOPE_INDEX_DOMAIN].cbSize = sizeof(DSOP_SCOPE_INIT_INFO);
  286. aScopes[SCE_SCOPE_INDEX_DOMAIN].flType = DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN;
  287. aScopes[SCE_SCOPE_INDEX_DOMAIN].flScope = DSOP_SCOPE_FLAG_STARTING_SCOPE | DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT;
  288. //
  289. // May need to differentiate native & mixed modes on non-DCs.
  290. //
  291. if (nShowFlag & SCE_SHOW_DIFF_MODE_OFF_DC && !bDC) {
  292. aScopes[SCE_SCOPE_INDEX_DOMAIN].FilterFlags.Uplevel.flNativeModeOnly = dwUpLevel;
  293. aScopes[SCE_SCOPE_INDEX_DOMAIN].FilterFlags.Uplevel.flMixedModeOnly =
  294. ( dwUpLevel & (~( DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE )) );
  295. } else {
  296. aScopes[SCE_SCOPE_INDEX_DOMAIN].FilterFlags.Uplevel.flBothModes = dwUpLevel;
  297. }
  298. aScopes[SCE_SCOPE_INDEX_DOMAIN].FilterFlags.flDownlevel = dwDownLevel;
  299. //
  300. // Next set flags for other scope items. Everything same, only not show builtin and local groups
  301. //
  302. aScopes[SCE_SCOPE_INDEX_DIRECTORY].cbSize = sizeof(DSOP_SCOPE_INIT_INFO);
  303. aScopes[SCE_SCOPE_INDEX_DIRECTORY].flScope = DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT;
  304. aScopes[SCE_SCOPE_INDEX_DIRECTORY].FilterFlags.Uplevel.flBothModes = ( dwUpLevel &
  305. (~( DSOP_FILTER_BUILTIN_GROUPS |DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE )) );
  306. aScopes[SCE_SCOPE_INDEX_DIRECTORY].FilterFlags.flDownlevel = dwDownLevel & (~ DSOP_DOWNLEVEL_FILTER_LOCAL_GROUPS );
  307. aScopes[SCE_SCOPE_INDEX_DIRECTORY].FilterFlags.flDownlevel |= DSOP_DOWNLEVEL_FILTER_EXCLUDE_BUILTIN_GROUPS |
  308. DSOP_DOWNLEVEL_FILTER_COMPUTERS;
  309. aScopes[SCE_SCOPE_INDEX_DIRECTORY].flType = DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN
  310. | DSOP_SCOPE_TYPE_GLOBAL_CATALOG
  311. | DSOP_SCOPE_TYPE_WORKGROUP
  312. | DSOP_SCOPE_TYPE_USER_ENTERED_UPLEVEL_SCOPE
  313. | DSOP_SCOPE_TYPE_USER_ENTERED_DOWNLEVEL_SCOPE
  314. | DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN
  315. | DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN;
  316. //
  317. // Show each scope's information or not.
  318. //
  319. InitInfo.cDsScopeInfos = 0;
  320. if (nShowFlag & SCE_SHOW_SCOPE_LOCAL) {
  321. memcpy(&aScopesUsed[InitInfo.cDsScopeInfos],&aScopes[SCE_SCOPE_INDEX_LOCAL],sizeof(DSOP_SCOPE_INIT_INFO));
  322. InitInfo.cDsScopeInfos++;
  323. }
  324. if (nShowFlag & SCE_SHOW_SCOPE_DOMAIN) {
  325. memcpy(&aScopesUsed[InitInfo.cDsScopeInfos],&aScopes[SCE_SCOPE_INDEX_DOMAIN],sizeof(DSOP_SCOPE_INIT_INFO));
  326. InitInfo.cDsScopeInfos++;
  327. }
  328. if (nShowFlag & SCE_SHOW_SCOPE_DIRECTORY) {
  329. memcpy(&aScopesUsed[InitInfo.cDsScopeInfos],&aScopes[SCE_SCOPE_INDEX_DIRECTORY],sizeof(DSOP_SCOPE_INIT_INFO));
  330. InitInfo.cDsScopeInfos++;
  331. }
  332. ASSERT(InitInfo.cDsScopeInfos > 0);
  333. //
  334. // If workgroup is supplied then we must filter computers.
  335. //
  336. int i;
  337. for (i=0;i<sizeof(aScopes)/sizeof(aScopes[0]);i++) {
  338. if( aScopes[i].flType & DSOP_SCOPE_TYPE_WORKGROUP ){
  339. aScopes[i].FilterFlags.flDownlevel |= DSOP_DOWNLEVEL_FILTER_COMPUTERS;
  340. }
  341. }
  342. //
  343. // Initialize and display the object picker.
  344. //
  345. InitInfo.cbSize = sizeof(InitInfo);
  346. InitInfo.aDsScopeInfos = aScopesUsed;
  347. InitInfo.flOptions = ((nShowFlag & SCE_SHOW_SINGLESEL) ? 0:DSOP_FLAG_MULTISELECT);
  348. InitInfo.pwzTargetComputer = m_pszServerName;
  349. hr = pDsObjectPicker->Initialize(&InitInfo);
  350. if( FAILED(hr) ){
  351. CoUninitialize();
  352. return FALSE;
  353. }
  354. IDataObject *pdo = NULL;
  355. hr = pDsObjectPicker->InvokeDialog(hwnd, &pdo);
  356. while (SUCCEEDED(hr) && pdo) { // FALSE LOOP
  357. //
  358. // The user pressed OK. Prepare clipboard dataformat from the object picker.
  359. //
  360. STGMEDIUM stgmedium =
  361. {
  362. TYMED_HGLOBAL,
  363. NULL
  364. };
  365. CLIPFORMAT cf = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
  366. FORMATETC formatetc =
  367. {
  368. cf,
  369. NULL,
  370. DVASPECT_CONTENT,
  371. -1,
  372. TYMED_HGLOBAL
  373. };
  374. hr = pdo->GetData(&formatetc, &stgmedium);
  375. if ( FAILED(hr) ) {
  376. bRet = FALSE;
  377. pdo->Release();
  378. pdo = NULL;
  379. break;
  380. }
  381. //
  382. // Lock the selection list.
  383. //
  384. PDS_SELECTION_LIST pDsSelList =
  385. (PDS_SELECTION_LIST) GlobalLock(stgmedium.hGlobal);
  386. ULONG i;
  387. ULONG iLen = 0;
  388. //
  389. // Enumerate through all selections.
  390. //
  391. for (i = 0; i < pDsSelList->cItems && bRet; i++) {
  392. LPTSTR pszCur = pDsSelList->aDsSelection[i].pwzADsPath;
  393. bHasADsPath = TRUE;
  394. int iPath = 0;
  395. //
  396. // Se if this is a valid string. If the string isn't empty or NULL then use it
  397. // with the full path, we will figure out later wiether we need to strip the prefix.
  398. //
  399. if (pszCur && *pszCur
  400. ){
  401. //
  402. // Create name with one path.
  403. //
  404. iLen = lstrlen(pszCur);
  405. while (iLen) {
  406. if ( pszCur[iLen] == L'/' ) {
  407. if (iPath) {
  408. iLen++;
  409. iPath -= iLen;
  410. break;
  411. }
  412. iPath = iLen;
  413. }
  414. iLen--;
  415. }
  416. pszCur += iLen;
  417. } else {
  418. //
  419. // Use just the name then.
  420. //
  421. bHasADsPath = FALSE;
  422. pszCur = pDsSelList->aDsSelection[i].pwzName;
  423. if (!pszCur || !(*pszCur)) {
  424. continue;
  425. }
  426. }
  427. iLen = lstrlen(pszCur);
  428. if (iLen) {
  429. //
  430. // Allocate and copy the user name.
  431. //
  432. LPTSTR pszNew = (LPTSTR)LocalAlloc( LMEM_FIXED, (iLen + 1) * sizeof(TCHAR));
  433. if (!pszNew) {
  434. bRet = FALSE;
  435. break;
  436. }
  437. lstrcpy(pszNew, pszCur);
  438. if (bHasADsPath)
  439. {
  440. if (iPath) {
  441. //
  442. // Set forward slash to back slash.
  443. //
  444. pszNew[iPath] = L'\\';
  445. }
  446. ULONG uAttributes;
  447. //
  448. // Bug 395424:
  449. //
  450. // Obsel passes attributes in VT_I4 on DCs and in VT_UI4 on other systems
  451. // Need to check both to properly detect built-ins, etc.
  452. //
  453. if (V_VT(pDsSelList->aDsSelection[i].pvarFetchedAttributes) == VT_UI4) {
  454. uAttributes = V_UI4(pDsSelList->aDsSelection[i].pvarFetchedAttributes);
  455. } else if (V_VT(pDsSelList->aDsSelection[i].pvarFetchedAttributes) == VT_I4) {
  456. uAttributes = static_cast<ULONG>(V_I4(pDsSelList->aDsSelection[i].pvarFetchedAttributes));
  457. }
  458. //
  459. // Determine if the name we recieved is group.
  460. // The type and value of pDsSelList->aDsSelection[i].pvarFetchedAttributes
  461. // may change in the future release by Object Picker. Therefore,
  462. // the following code should change accordingly.
  463. //
  464. if ( (V_VT(pDsSelList->aDsSelection[i].pvarFetchedAttributes) == VT_UI4) ||
  465. (V_VT(pDsSelList->aDsSelection[i].pvarFetchedAttributes) == VT_I4 ))
  466. {
  467. //
  468. // Determine if it is a built-in group. We don't want
  469. // built-in groups to have a prefix.
  470. //
  471. if ( uAttributes & 0x1 &&
  472. V_ISARRAY(pDsSelList->aDsSelection[i].pvarFetchedAttributes + 1) )
  473. {
  474. lstrcpy( pszNew, &(pszCur[iPath + 1]) );
  475. }
  476. else if ( uAttributes & 0x4 &&
  477. V_ISARRAY(pDsSelList->aDsSelection[i].pvarFetchedAttributes + 1) )
  478. {
  479. //
  480. // It's a group, but we have to check the sids account type. If it's
  481. // not in the domain accounts authority then we can assume it's a built-in sid
  482. //
  483. PVOID pvData = NULL;
  484. HRESULT hr = SafeArrayAccessData( V_ARRAY(pDsSelList->aDsSelection[i].pvarFetchedAttributes + 1), &pvData);
  485. if (SUCCEEDED(hr) ) {
  486. if ( IsValidSid( (PSID)pvData ) && !IsDomainAccountSid( (PSID)pvData ) )
  487. {
  488. lstrcpy(pszNew, &(pszCur[iPath + 1]) );
  489. }
  490. hr = SafeArrayUnaccessData( V_ARRAY(pDsSelList->aDsSelection[i].pvarFetchedAttributes + 1) );
  491. }
  492. }
  493. }
  494. else if(V_VT(pDsSelList->aDsSelection[i].pvarFetchedAttributes) == VT_EMPTY)
  495. {
  496. LPTSTR pszTemp = pDsSelList->aDsSelection[i].pwzClass;
  497. //
  498. // Determine if it is a well-known account. We don't want
  499. // well-known account to have a prefix.
  500. //
  501. if (lstrcmpi(pszTemp, _T("user")))
  502. {
  503. lstrcpy( pszNew, &(pszCur[iPath + 1]) );
  504. }
  505. }
  506. }
  507. //
  508. // Make sure we don't already have this name in the list.
  509. //
  510. pName = m_pNameList;
  511. while (pName) {
  512. if (!lstrcmpi(pName->Name, pszNew)) {
  513. LocalFree(pszNew);
  514. pszNew = NULL;
  515. break;
  516. }
  517. pName = pName->Next;
  518. }
  519. if ( !pszNew ) {
  520. //
  521. // Don;t do anything because this name already exists.
  522. //
  523. continue;
  524. }
  525. //
  526. // New entry in list.
  527. //
  528. pName = (PSCE_NAME_LIST) LocalAlloc(LPTR,sizeof(SCE_NAME_LIST));
  529. if ( !pName ) {
  530. LocalFree(pszNew);
  531. bRet = FALSE;
  532. break;
  533. }
  534. ZeroMemory(pName, sizeof(SCE_NAME_LIST));
  535. //GetAccountType(pszNew);
  536. pName->Name = pszNew;
  537. pName->Next = m_pNameList;
  538. m_pNameList = pName;
  539. }
  540. }
  541. GlobalUnlock(stgmedium.hGlobal);
  542. ReleaseStgMedium(&stgmedium);
  543. pdo->Release();
  544. break;
  545. }
  546. pDsObjectPicker->Release();
  547. CoUninitialize();
  548. if (!bRet) {
  549. //
  550. // If we had an error somewhere clean up.
  551. //
  552. pName = m_pNameList;
  553. while (pName) {
  554. if (pName->Name) {
  555. LocalFree(pName->Name);
  556. }
  557. m_pNameList = pName->Next;
  558. LocalFree(pName);
  559. pName = m_pNameList;
  560. }
  561. m_pNameList = NULL;
  562. }
  563. return bRet;
  564. }
  565. PSCE_NAME_LIST CGetUser::GetUsers()
  566. {
  567. return m_pNameList;
  568. }