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.

1448 lines
40 KiB

  1. //*************************************************************
  2. //
  3. // Microsoft Confidential. Copyright (c) Microsoft Corporation 1999. All rights reserved
  4. //
  5. // File: diagprov.cpp
  6. //
  7. // Description: Rsop diagnostic mode provider
  8. //
  9. // History: 8-20-99 leonardm Created
  10. //
  11. //*************************************************************
  12. #include "uenv.h"
  13. #include "diagprov.h"
  14. #include "rsopinc.h"
  15. #include "Indicate.h"
  16. #include "rsopdbg.h"
  17. #include "rsopsec.h"
  18. HRESULT EnumerateUserNameSpace( IWbemLocator *pWbemLocator, HANDLE hToken, SAFEARRAY **psaUserSids );
  19. HRESULT UpdateGPCoreStatus(IWbemLocator *pWbemLocator,
  20. LPWSTR szSid, LPWSTR szNameSpace);
  21. //*************************************************************
  22. //
  23. // GetMachAccountName()
  24. //
  25. // Purpose: Gets Machine account name
  26. //
  27. // Return: Machine Account
  28. //
  29. // Note: Need to call it w/o impersonation
  30. //*************************************************************
  31. LPTSTR GetMachAccountName()
  32. {
  33. return MyGetUserName(NameSamCompatible);
  34. }
  35. //*************************************************************
  36. //
  37. // GetUserAccountName()
  38. //
  39. // Purpose: Gets the user account given the Sid
  40. //
  41. // Parameters: lpSidString - Sid in string format that we are interested in
  42. //
  43. // Return: Account Name
  44. //
  45. //*************************************************************
  46. LPTSTR GetUserAccountName(LPTSTR lpSidString)
  47. {
  48. SID_NAME_USE peUse;
  49. DWORD dwNameSize = 0;
  50. PSID pSid = NULL;
  51. DWORD dwDomainSize = 0;
  52. LPTSTR szRetAccount = NULL;
  53. if (AllocateAndInitSidFromString(lpSidString, &pSid) != STATUS_SUCCESS ) {
  54. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("GetUserAccountName::AllocateAndInitSidFromString failed."));
  55. goto Exit;
  56. }
  57. LookupAccountSid(NULL, pSid, NULL, &dwNameSize, NULL, &dwDomainSize, &peUse);
  58. if (dwNameSize && dwDomainSize) {
  59. XPtrLF<TCHAR> xszAccount =
  60. LocalAlloc(LPTR, sizeof(TCHAR)*(dwNameSize+dwDomainSize+4));
  61. XPtrLF<TCHAR> xszDomainName =
  62. LocalAlloc(LPTR, sizeof(TCHAR)*(dwDomainSize+1));
  63. XPtrLF<TCHAR> xszName =
  64. LocalAlloc(LPTR, sizeof(TCHAR)*(dwNameSize+1));
  65. if (!xszAccount || !xszDomainName || !xszName ) {
  66. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("GetUserAccountName::AllocMem failed with 0x%x."), GetLastError());
  67. goto Exit;
  68. }
  69. if (!LookupAccountSid(NULL, pSid, xszName, &dwNameSize, xszDomainName, &dwDomainSize, &peUse)) {
  70. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("GetUserAccountName::LookupaccountSid failed with 0x%x."), GetLastError());
  71. goto Exit;
  72. }
  73. lstrcpy(xszAccount, xszDomainName);
  74. lstrcat(xszAccount, TEXT("\\"));
  75. lstrcat(xszAccount, xszName);
  76. dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("GetUserAccountName::User account is %s."), xszAccount);
  77. szRetAccount = xszAccount.Acquire();
  78. }
  79. Exit:
  80. if (pSid)
  81. FreeSid(pSid);
  82. return szRetAccount;
  83. }
  84. //*************************************************************
  85. //
  86. // CheckRsopDiagPolicyInteractive()
  87. //
  88. // Purpose: Can this user get the rsop data even if the user is logged
  89. // on interactively
  90. //
  91. // Parameters:
  92. //
  93. // Return: CheckRsopDiagPolicyInteractive
  94. //
  95. //*************************************************************
  96. BOOL CheckRsopDiagPolicyInteractive()
  97. {
  98. HKEY hKeyUser = NULL;
  99. HKEY hKey;
  100. DWORD dwSize = 0, dwType = 0;
  101. BOOL bDeny = FALSE;
  102. CoImpersonateClient();
  103. if (!RegOpenCurrentUser(KEY_READ, &hKeyUser) == ERROR_SUCCESS) {
  104. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CheckRsopDiagPolicyInteractive:: couldn't access registry of interactive user."));
  105. hKeyUser = NULL;
  106. }
  107. CoRevertToSelf();
  108. //
  109. // First, check for a user preference
  110. //
  111. if (hKeyUser) {
  112. if (RegOpenKeyEx (hKeyUser, WINLOGON_KEY, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
  113. dwSize = sizeof(bDeny);
  114. RegQueryValueEx (hKey, DENY_RSOP_FROM_INTERACTIVE_USER, NULL, &dwType,
  115. (LPBYTE) &bDeny, &dwSize);
  116. RegCloseKey (hKey);
  117. }
  118. }
  119. //
  120. // Check for a machine preference
  121. //
  122. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, WINLOGON_KEY, 0,
  123. KEY_READ, &hKey) == ERROR_SUCCESS) {
  124. dwSize = sizeof(bDeny);
  125. RegQueryValueEx (hKey, DENY_RSOP_FROM_INTERACTIVE_USER, NULL, &dwType,
  126. (LPBYTE) &bDeny, &dwSize);
  127. RegCloseKey (hKey);
  128. }
  129. //
  130. // Check for a user policy
  131. //
  132. if (hKeyUser) {
  133. if (RegOpenKeyEx (hKeyUser, SYSTEM_POLICIES_KEY, 0,
  134. KEY_READ, &hKey) == ERROR_SUCCESS) {
  135. dwSize = sizeof(bDeny);
  136. RegQueryValueEx (hKey, DENY_RSOP_FROM_INTERACTIVE_USER, NULL, &dwType,
  137. (LPBYTE) &bDeny, &dwSize);
  138. RegCloseKey (hKey);
  139. }
  140. }
  141. //
  142. // Check for a machine policy
  143. //
  144. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, SYSTEM_POLICIES_KEY, 0,
  145. KEY_READ, &hKey) == ERROR_SUCCESS) {
  146. dwSize = sizeof(bDeny);
  147. RegQueryValueEx (hKey, DENY_RSOP_FROM_INTERACTIVE_USER, NULL, &dwType,
  148. (LPBYTE) &bDeny, &dwSize);
  149. RegCloseKey (hKey);
  150. }
  151. if (hKeyUser) {
  152. RegCloseKey(hKeyUser);
  153. }
  154. return (!bDeny);
  155. }
  156. //*************************************************************
  157. //
  158. // Functions: Constructor, Destructor, QueryInterface, AddRef, Release
  159. //
  160. //*************************************************************
  161. CSnapProv::CSnapProv()
  162. : m_cRef(1),
  163. m_bInitialized(false),
  164. m_pNamespace(NULL)
  165. {
  166. InterlockedIncrement(&g_cObj);
  167. m_xbstrUserSid = L"userSid";
  168. if ( !m_xbstrUserSid )
  169. return;
  170. m_xbstrUserSids = L"userSids";
  171. if ( !m_xbstrUserSids )
  172. return;
  173. m_xbstrNameSpace = L"nameSpace";
  174. if ( !m_xbstrNameSpace )
  175. return;
  176. m_xbstrResult = L"hResult";
  177. if ( !m_xbstrResult )
  178. return;
  179. m_xbstrFlags = L"flags";
  180. if ( !m_xbstrFlags )
  181. return;
  182. m_xbstrExtendedInfo = L"ExtendedInfo";
  183. if ( !m_xbstrExtendedInfo )
  184. return;
  185. m_xbstrClass = L"RsopLoggingModeProvider";
  186. if ( !m_xbstrClass )
  187. return;
  188. m_bInitialized = TRUE;
  189. }
  190. CSnapProv::~CSnapProv()
  191. {
  192. if(m_pNamespace != NULL)
  193. {
  194. m_pNamespace->Release();
  195. }
  196. InterlockedDecrement(&g_cObj);
  197. }
  198. STDMETHODIMP CSnapProv::QueryInterface (REFIID riid, LPVOID* ppv)
  199. {
  200. if(riid == IID_IUnknown || riid == IID_IWbemServices)
  201. {
  202. *ppv = static_cast<IWbemServices*>(this);
  203. }
  204. else if(riid == IID_IWbemProviderInit)
  205. {
  206. *ppv = static_cast<IWbemProviderInit*>(this);
  207. }
  208. else
  209. {
  210. *ppv=NULL;
  211. return E_NOINTERFACE;
  212. }
  213. AddRef();
  214. return S_OK;
  215. }
  216. STDMETHODIMP_(ULONG) CSnapProv::AddRef()
  217. {
  218. return InterlockedIncrement( &m_cRef );
  219. }
  220. STDMETHODIMP_(ULONG) CSnapProv::Release()
  221. {
  222. if (!InterlockedDecrement(&m_cRef))
  223. {
  224. delete this;
  225. return 0;
  226. }
  227. return m_cRef;
  228. }
  229. //*************************************************************
  230. //
  231. // Initialize()
  232. //
  233. // Purpose: WbemProvider's initialize method
  234. //
  235. // Parameters: See IWbemProivderInit::Initialize
  236. //
  237. // Return: hresult
  238. //
  239. //*************************************************************
  240. STDMETHODIMP CSnapProv::Initialize( LPWSTR pszUser,
  241. LONG lFlags,
  242. LPWSTR pszNamespace,
  243. LPWSTR pszLocale,
  244. IWbemServices __RPC_FAR *pNamespace,
  245. IWbemContext __RPC_FAR *pCtx,
  246. IWbemProviderInitSink __RPC_FAR *pInitSink)
  247. {
  248. HRESULT hr;
  249. if ( !m_bInitialized ) {
  250. hr = pInitSink->SetStatus(E_FAIL, 0);
  251. return hr;
  252. }
  253. //
  254. // No need to authenticate user. The ACLs on Rsop namespace will
  255. // deny access to users that cannot snapshot diagnostic mode data.
  256. //
  257. m_pNamespace = pNamespace;
  258. m_pNamespace->AddRef();
  259. hr = pInitSink->SetStatus(WBEM_S_INITIALIZED, 0);
  260. return hr;
  261. }
  262. #if _MSC_FULL_VER <= 13008827 && defined(_M_IX86)
  263. #pragma optimize("", off)
  264. #endif
  265. //*************************************************************
  266. //
  267. // ExecMethodAsync()
  268. //
  269. // Purpose: Execute method
  270. //
  271. // Parameters: See IWbemServices::ExecMethodAsync
  272. //
  273. // Return: hresult
  274. //
  275. //*************************************************************
  276. STDMETHODIMP CSnapProv::ExecMethodAsync( const BSTR bstrObject,
  277. const BSTR bstrMethod,
  278. long lFlags,
  279. IWbemContext __RPC_FAR *pCtx,
  280. IWbemClassObject __RPC_FAR *pInParams,
  281. IWbemObjectSink __RPC_FAR *pResponseHandler)
  282. {
  283. HRESULT hr;
  284. CFailRetStatus retStatus( pResponseHandler );
  285. IUnknown *pOldSecContext;
  286. //
  287. // Make sure the provider is properly initialized
  288. //
  289. //
  290. // Allow for debugging level to be dynamically changed during queries
  291. //
  292. dbgRsop.Initialize( L"Software\\Microsoft\\Windows NT\\CurrentVersion\\winlogon",
  293. L"RsopDebugLevel",
  294. L"userenv.log",
  295. L"userenv.bak",
  296. FALSE );
  297. InitDebugSupport(0);
  298. if ( !m_bInitialized )
  299. {
  300. hr = E_OUTOFMEMORY;
  301. retStatus.SetError( hr );
  302. return hr;
  303. }
  304. //
  305. // Initialize the return status object to fail status
  306. //
  307. IWbemLocator *pWbemLocator = NULL;
  308. hr = CoCreateInstance( CLSID_WbemAuthenticatedLocator,
  309. NULL,
  310. CLSCTX_INPROC_SERVER,
  311. IID_IWbemLocator,
  312. (LPVOID *) &pWbemLocator );
  313. if ( FAILED(hr) )
  314. {
  315. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecMethodAsync: CoCreateInstance returned 0x%x"), hr );
  316. retStatus.SetError( hr );
  317. return hr;
  318. }
  319. XInterface<IWbemLocator> xLocator( pWbemLocator );
  320. IWbemClassObject* pProvClass = NULL;
  321. IWbemClassObject* pOutClass = NULL;
  322. IWbemClassObject* pOutParams = NULL;
  323. hr = m_pNamespace->GetObject( m_xbstrClass, 0, pCtx, &pProvClass, NULL);
  324. if ( FAILED(hr) )
  325. {
  326. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::GetObject failed with 0x%x."), hr );
  327. retStatus.SetError( hr );
  328. return hr;
  329. }
  330. XInterface<IWbemClassObject> xProvClass( pProvClass );
  331. hr = pProvClass->GetMethod( bstrMethod, 0, NULL, &pOutClass);
  332. if ( FAILED(hr) )
  333. {
  334. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::GetMethod failed with 0x%x."), hr );
  335. retStatus.SetError( hr );
  336. return hr;
  337. }
  338. XInterface<IWbemClassObject> xOutClass( pOutClass );
  339. hr = pOutClass->SpawnInstance(0, &pOutParams);
  340. if ( FAILED(hr) )
  341. {
  342. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::SpawnInstance failed with 0x%x."), hr );
  343. retStatus.SetError( hr );
  344. return hr;
  345. }
  346. //
  347. // Get the tokens and Sids upfront
  348. //
  349. XPtrLF <WCHAR> xszSidString;
  350. XPtrLF <SID> xSid;
  351. XHandle xUserToken;
  352. hr = CoImpersonateClient();
  353. if ( FAILED(hr) )
  354. {
  355. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoImpersonateClient failed with 0x%x"), hr );
  356. retStatus.SetError( hr );
  357. return hr;
  358. }
  359. if (OpenThreadToken (GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &xUserToken)) {
  360. LPWSTR szSid = GetSidString(xUserToken);
  361. if (!szSid) {
  362. hr = HRESULT_FROM_WIN32(GetLastError());
  363. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::GetSidString failed with %d"), GetLastError() );
  364. CoRevertToSelf();
  365. retStatus.SetError( hr );
  366. return hr;
  367. }
  368. else {
  369. xszSidString = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*(lstrlen(szSid)+1));
  370. if (!xszSidString) {
  371. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::LocalAlloc failed with %d"), GetLastError() );
  372. hr = HRESULT_FROM_WIN32(GetLastError());
  373. DeleteSidString(szSid);
  374. CoRevertToSelf();
  375. retStatus.SetError( hr );
  376. return hr;
  377. }
  378. lstrcpy(xszSidString, szSid);
  379. DeleteSidString(szSid);
  380. }
  381. xSid = (SID *)GetUserSid(xUserToken);
  382. if (!xSid) {
  383. hr = HRESULT_FROM_WIN32(GetLastError());
  384. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::GetUserSid failed with %d"), GetLastError() );
  385. CoRevertToSelf();
  386. retStatus.SetError( hr );
  387. return hr;
  388. }
  389. } else {
  390. hr = HRESULT_FROM_WIN32(GetLastError());
  391. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Openthreadtoken failed with 0x%x"), hr );
  392. CoRevertToSelf();
  393. retStatus.SetError( hr );
  394. return hr;
  395. }
  396. CoRevertToSelf();
  397. XInterface<IWbemClassObject> xOutParams( pOutParams );
  398. if ( _wcsicmp( (WCHAR *) bstrMethod, L"RsopDeleteSession" ) == 0 ) {
  399. //
  400. // rsopdeletesession
  401. //
  402. VARIANT vNameSpace;
  403. hr = pInParams->Get( m_xbstrNameSpace, 0, &vNameSpace, NULL, NULL);
  404. if ( FAILED(hr) )
  405. {
  406. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Get machine name failed with 0x%x."), hr );
  407. retStatus.SetError( hr );
  408. return hr;
  409. }
  410. XVariant xvNameSpace( &vNameSpace );
  411. if (vNameSpace.vt != VT_NULL ) {
  412. //
  413. // We want to run as LS
  414. //
  415. hr = CoSwitchCallContext(NULL, &pOldSecContext);
  416. if (FAILED(hr)) {
  417. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr );
  418. retStatus.SetError( hr );
  419. return hr;
  420. }
  421. hr = ProviderDeleteRsopNameSpace( pWbemLocator,
  422. vNameSpace.bstrVal,
  423. xUserToken,
  424. xszSidString,
  425. SETUP_NS_SM);
  426. IUnknown *pNewObject;
  427. HRESULT hr2 = CoSwitchCallContext(pOldSecContext, &pNewObject);
  428. if (FAILED(hr2)) {
  429. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr2 );
  430. }
  431. }
  432. else {
  433. hr = E_INVALIDARG;
  434. }
  435. VARIANT var;
  436. var.vt = VT_I4;
  437. var.lVal = hr;
  438. hr = pOutParams->Put( m_xbstrResult, 0, &var, 0);
  439. if ( FAILED(hr) )
  440. {
  441. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Put result failed with 0x%x"), hr );
  442. retStatus.SetError( hr );
  443. return hr;
  444. }
  445. hr = pResponseHandler->Indicate(1, &pOutParams);
  446. if ( FAILED(hr) )
  447. {
  448. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod:: Indicate failed with 0x%x"), hr );
  449. retStatus.SetError( hr );
  450. return hr;
  451. }
  452. return hr;
  453. }
  454. else if ( _wcsicmp( (WCHAR *) bstrMethod, L"RsopEnumerateUsers" ) == 0 )
  455. {
  456. //
  457. // RsopenumerateUsers
  458. //
  459. SAFEARRAY *pArray;
  460. hr = EnumerateUserNameSpace( pWbemLocator, xUserToken, &pArray );
  461. XSafeArray xsaUserSids(pArray);
  462. if ( FAILED(hr) )
  463. {
  464. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::EnumerateUserNameSpace failed") );
  465. }
  466. VARIANT var;
  467. var.vt = VT_I4;
  468. var.lVal = hr;
  469. hr = pOutParams->Put( m_xbstrResult, 0, &var, 0);
  470. if ( FAILED(hr) )
  471. {
  472. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Put result failed with 0x%x"), hr );
  473. retStatus.SetError( hr );
  474. return hr;
  475. }
  476. var.vt = VT_ARRAY | VT_BSTR;
  477. var.parray = xsaUserSids;
  478. hr = pOutParams->Put( m_xbstrUserSids, 0, &var, 0 );
  479. if ( FAILED(hr) )
  480. {
  481. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Put sids failed with 0x%x"), hr );
  482. retStatus.SetError( hr );
  483. return hr;
  484. }
  485. hr = pResponseHandler->Indicate(1, &pOutParams);
  486. if ( FAILED(hr) )
  487. {
  488. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod:: Indicate failed with 0x%x"), hr );
  489. retStatus.SetError( hr );
  490. return hr;
  491. }
  492. return hr;
  493. }
  494. //
  495. // progress indicator.
  496. // 25% done when we enter the first critical section.
  497. // 50% done when we enter the second critical section.
  498. // 100% complete when we copy the namespace.
  499. //
  500. CProgressIndicator Indicator( pResponseHandler,
  501. (lFlags & WBEM_FLAG_SEND_STATUS) != 0 );
  502. //
  503. // 5% done. Hack for UI.
  504. //
  505. hr = Indicator.IncrementBy( 5 );
  506. VARIANT vUserSid;
  507. hr = pInParams->Get( m_xbstrUserSid, 0, &vUserSid, NULL, NULL);
  508. if ( FAILED(hr) )
  509. {
  510. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Get RemoteComputer failed with 0x%x."), hr );
  511. retStatus.SetError( hr );
  512. return hr;
  513. }
  514. XVariant xvUserSid ( &vUserSid );
  515. VARIANT vFlags;
  516. VariantInit( &vFlags );
  517. hr = pInParams->Get( m_xbstrFlags, 0, &vFlags, NULL, NULL);
  518. if ( FAILED(hr) )
  519. {
  520. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Get dwFlags failed with 0x%x."), hr );
  521. retStatus.SetError( hr );
  522. return hr;
  523. }
  524. DWORD dwFlags = vFlags.vt == VT_EMPTY || vFlags.vt == VT_NULL ? 0 : vFlags.ulVal;
  525. //
  526. // Flags specific to Diagnostic mode provider
  527. //
  528. if ((dwFlags & FLAG_NO_USER) && (dwFlags & FLAG_NO_COMPUTER)) {
  529. hr = WBEM_E_INVALID_PARAMETER;
  530. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod:: Both user and computer are null."));
  531. retStatus.SetError( hr );
  532. return hr;
  533. }
  534. //
  535. // We can dump out all the input parameters here later on.
  536. //
  537. dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::---------------RsopCreateSession::Input Parameters--------------------"));
  538. dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::UserSid = <%s>"), vUserSid.vt == VT_NULL ? L"NULL" : vUserSid.bstrVal);
  539. dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::flags = <%d>"), dwFlags);
  540. dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::---------------RsopCreateSession::Input Parameters--------------------"));
  541. //
  542. // Code for RsopCreateSession method
  543. //
  544. XPtrLF<TCHAR> xszMachSOM;
  545. XPtrLF<TCHAR> xszUserSOM;
  546. BOOL bDelegated = FALSE;
  547. BOOL bCheckAccess = FALSE;
  548. DWORD dwExtendedInfo = 0;
  549. XPtrLF<TCHAR> xszUserAccount;
  550. XPtrLF<TCHAR> xszMachAccount;
  551. //
  552. // Get the machine SOM
  553. //
  554. if ( !(dwFlags & FLAG_NO_COMPUTER) ) {
  555. xszMachAccount = GetMachAccountName();
  556. dwExtendedInfo |= RSOP_COMPUTER_ACCESS_DENIED;
  557. if (!xszMachAccount) {
  558. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::No machine account. error %d"), GetLastError() );
  559. }
  560. else {
  561. xszMachSOM = GetSOM(xszMachAccount);
  562. if (xszMachSOM) {
  563. bCheckAccess = TRUE;
  564. dwExtendedInfo &= ~RSOP_COMPUTER_ACCESS_DENIED;
  565. }
  566. else {
  567. dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::No machine SOM. error %d"), GetLastError() );
  568. }
  569. }
  570. }
  571. else {
  572. bCheckAccess = TRUE;
  573. }
  574. //
  575. // Get the User SOM
  576. //
  577. if ((bCheckAccess) && ( !(dwFlags & FLAG_NO_USER) ) ) {
  578. bCheckAccess = FALSE;
  579. dwExtendedInfo |= RSOP_USER_ACCESS_DENIED;
  580. xszUserAccount = GetUserAccountName(vUserSid.vt == VT_NULL ? xszSidString : vUserSid.bstrVal);
  581. if (!xszUserAccount) {
  582. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::No User account. error %d"), GetLastError() );
  583. }
  584. else {
  585. xszUserSOM = GetSOM(xszUserAccount);
  586. if (xszUserSOM) {
  587. bCheckAccess = TRUE;
  588. dwExtendedInfo &= ~RSOP_USER_ACCESS_DENIED;
  589. }
  590. else {
  591. dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::No User SOM. error %d"), GetLastError() );
  592. }
  593. }
  594. }
  595. //
  596. // Check access now
  597. //
  598. if (bCheckAccess) {
  599. hr = AuthenticateUser(xUserToken, xszMachSOM, xszUserSOM, TRUE, &dwExtendedInfo);
  600. if (FAILED(hr)) {
  601. dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::User is not a delegated admin. Error 0x%x"), hr );
  602. hr = S_OK;
  603. }
  604. else {
  605. dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::User is a delegated admin. Error 0x%x"), hr );
  606. bDelegated = TRUE;
  607. }
  608. }
  609. dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecMethodAsync::Getting policy critical sections"));
  610. XCriticalPolicySection criticalPolicySectionMACHINE( EnterCriticalPolicySectionEx(TRUE, 40000, ECP_FAIL_ON_WAIT_TIMEOUT) );
  611. if ( !criticalPolicySectionMACHINE )
  612. {
  613. hr = HRESULT_FROM_WIN32( GetLastError() );
  614. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecMethodAsync::EnterCriticalPolicySection failed with 0x%x"), hr );
  615. retStatus.SetError( hr );
  616. return hr;
  617. }
  618. //
  619. // 25% done when we enter the first critical section.
  620. //
  621. hr = Indicator.IncrementBy( 20 );
  622. if ( FAILED( hr ) )
  623. {
  624. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecMethodAsync::IncrementBy() failed with 0x%x"), hr );
  625. }
  626. XCriticalPolicySection criticalPolicySectionUSER( EnterCriticalPolicySectionEx(FALSE, 40000, ECP_FAIL_ON_WAIT_TIMEOUT) );
  627. if ( !criticalPolicySectionUSER )
  628. {
  629. hr = HRESULT_FROM_WIN32( GetLastError() );
  630. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecMethodAsync::EnterCriticalPolicySection failed with 0x%x"), hr );
  631. retStatus.SetError( hr );
  632. return hr;
  633. }
  634. //
  635. // 50% done when we enter the second critical section.
  636. //
  637. hr = Indicator.IncrementBy( 25 );
  638. if ( FAILED( hr ) )
  639. {
  640. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecMethodAsync::IncrementBy() failed with 0x%x"), hr );
  641. }
  642. LPWSTR wszNameSpace = 0;
  643. //
  644. // Impersonate if not delegated
  645. //
  646. if (!bDelegated) {
  647. hr = CoImpersonateClient();
  648. if ( FAILED(hr) )
  649. {
  650. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoImpersonateClient failed with 0x%x"), hr );
  651. retStatus.SetError( hr );
  652. return hr;
  653. }
  654. }
  655. else {
  656. //
  657. // We want to run as LS
  658. //
  659. hr = CoSwitchCallContext(NULL, &pOldSecContext);
  660. if (FAILED(hr)) {
  661. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr );
  662. retStatus.SetError( hr );
  663. return hr;
  664. }
  665. }
  666. XPtrLF<WCHAR> xwszNameSpace;
  667. DWORD dwNewNameSpaceFlags = SETUP_NS_SM;
  668. dwNewNameSpaceFlags |= (dwFlags & FLAG_NO_USER) ? SETUP_NS_SM_NO_USER : 0;
  669. dwNewNameSpaceFlags |= (dwFlags & FLAG_NO_COMPUTER) ? SETUP_NS_SM_NO_COMPUTER : 0;
  670. dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::UserSid = <%s>"), vUserSid.vt == VT_NULL ? L"NULL" : vUserSid.bstrVal);
  671. dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::User who is running the tool = <%s>"), (LPWSTR)xszSidString);
  672. hr = SetupNewNameSpace( &xwszNameSpace,
  673. 0, // namespace on this machine
  674. (vUserSid.vt == VT_NULL) ? ((LPWSTR)xszSidString) : vUserSid.bstrVal,
  675. xSid,
  676. pWbemLocator,
  677. dwNewNameSpaceFlags,
  678. &dwExtendedInfo);
  679. if (!bDelegated) {
  680. CoRevertToSelf();
  681. }
  682. else {
  683. //
  684. // restore call context
  685. //
  686. IUnknown *pNewObject;
  687. HRESULT hr2 = CoSwitchCallContext(pOldSecContext, &pNewObject);
  688. if (FAILED(hr2)) {
  689. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr2 );
  690. }
  691. }
  692. if ( FAILED(hr) && !bDelegated)
  693. {
  694. dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::SetupNewNameSpace failed with 0x%x"), hr );
  695. if (IsUserAnInteractiveUser(xUserToken) && CheckRsopDiagPolicyInteractive()) {
  696. if ( (vUserSid.vt == VT_NULL) || (_wcsicmp(vUserSid.bstrVal, xszSidString) == 0 )) {
  697. dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::SetupNewNameSpace failed. retrying in interactive mode"), hr );
  698. //
  699. // We want to run as LS
  700. //
  701. hr = CoSwitchCallContext(NULL, &pOldSecContext);
  702. if (FAILED(hr)) {
  703. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr );
  704. retStatus.SetError( hr );
  705. return hr;
  706. }
  707. //
  708. // if the namespace is null, get the name of the interactive namespace
  709. //
  710. XPtrLF<WCHAR> xszInteractiveNS;
  711. hr = GetInteractiveNameSpace(xszSidString, &xszInteractiveNS);
  712. if (FAILED(hr)) {
  713. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr );
  714. retStatus.SetError( hr );
  715. return hr;
  716. }
  717. BOOL bContinue=TRUE;
  718. if (dwFlags & FLAG_FORCE_CREATENAMESPACE) {
  719. hr = DeleteRsopNameSpace( xszInteractiveNS, pWbemLocator );
  720. // ignore error
  721. }
  722. else {
  723. XInterface<IWbemServices> xWbemServices;
  724. hr = pWbemLocator->ConnectServer( xszInteractiveNS,
  725. NULL,
  726. NULL,
  727. 0L,
  728. 0L,
  729. NULL,
  730. NULL,
  731. &xWbemServices );
  732. if (SUCCEEDED(hr)) {
  733. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod:: Namespace already exists. Failing call"));
  734. hr = WBEM_E_ALREADY_EXISTS;
  735. dwExtendedInfo = RSOP_TEMPNAMESPACE_EXISTS;
  736. bContinue = FALSE;
  737. }
  738. }
  739. if (bContinue) {
  740. dwNewNameSpaceFlags |= SETUP_NS_SM_INTERACTIVE;
  741. hr = SetupNewNameSpace( &xwszNameSpace,
  742. 0, // namespace on this machine
  743. xszSidString,
  744. xSid,
  745. pWbemLocator,
  746. dwNewNameSpaceFlags,
  747. &dwExtendedInfo);
  748. }
  749. //
  750. // restore call context
  751. //
  752. IUnknown *pNewObject;
  753. HRESULT hr2 = CoSwitchCallContext(pOldSecContext, &pNewObject);
  754. if (FAILED(hr2)) {
  755. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr2 );
  756. }
  757. }
  758. }
  759. }
  760. if (FAILED(hr)) {
  761. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::SetupNewNameSpace failed with 0x%x"), hr );
  762. }
  763. else
  764. {
  765. HRESULT hr2;
  766. VARIANT var;
  767. //
  768. // if we managed to get a snapshot, then ignore the extended access denied info
  769. //
  770. dwExtendedInfo = 0;
  771. //
  772. // We want to run as LS
  773. //
  774. hr = CoSwitchCallContext(NULL, &pOldSecContext);
  775. if (FAILED(hr)) {
  776. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr );
  777. retStatus.SetError( hr );
  778. return hr;
  779. }
  780. if ( !(dwFlags & FLAG_NO_COMPUTER) ) {
  781. hr = UpdateGPCoreStatus(pWbemLocator, NULL, xwszNameSpace);
  782. }
  783. if ( (SUCCEEDED(hr)) && (!(dwFlags & FLAG_NO_USER)) ) {
  784. hr = UpdateGPCoreStatus(pWbemLocator,
  785. vUserSid.vt == VT_NULL ? xszSidString : vUserSid.bstrVal,
  786. xwszNameSpace);
  787. }
  788. //
  789. // restore call context
  790. //
  791. IUnknown *pNewObject;
  792. hr2 = CoSwitchCallContext(pOldSecContext, &pNewObject);
  793. if (FAILED(hr2)) {
  794. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr2 );
  795. }
  796. //
  797. // Return the error code if the status cannot be updated..
  798. //
  799. if (FAILED(hr)) {
  800. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::UpdateGPCoreStatus failed with 0x%x"), hr );
  801. retStatus.SetError( hr );
  802. return hr;
  803. }
  804. XBStr xbstrNS( xwszNameSpace );
  805. if ( !xbstrNS )
  806. {
  807. hr2 = HRESULT_FROM_WIN32( E_OUTOFMEMORY );
  808. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Memory allocate failed") );
  809. retStatus.SetError( hr2 );
  810. return hr2;
  811. }
  812. var.vt = VT_BSTR;
  813. var.bstrVal = xbstrNS;
  814. hr2 = pOutParams->Put( m_xbstrNameSpace, 0, &var, 0);
  815. if ( FAILED(hr2) )
  816. {
  817. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Put namespace failed with 0x%x"), hr );
  818. retStatus.SetError( hr2 );
  819. return hr2;
  820. }
  821. }
  822. VARIANT var;
  823. var.vt = VT_I4;
  824. var.lVal = hr;
  825. hr = pOutParams->Put( m_xbstrResult, 0, &var, 0);
  826. if ( FAILED(hr) )
  827. {
  828. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Put result failed with 0x%x"), hr );
  829. retStatus.SetError( hr );
  830. return hr;
  831. }
  832. var.lVal = dwExtendedInfo;
  833. hr = pOutParams->Put( m_xbstrExtendedInfo, 0, &var, 0);
  834. if ( FAILED(hr) )
  835. {
  836. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Put result failed with 0x%x"), hr );
  837. retStatus.SetError( hr );
  838. return hr;
  839. }
  840. //
  841. // 100% complete when we copy the namespace.
  842. //
  843. hr = Indicator.SetComplete();
  844. if ( FAILED( hr ) )
  845. {
  846. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecMethodAsync::IncrementBy() failed with 0x%x"), hr );
  847. }
  848. hr = pResponseHandler->Indicate(1, &pOutParams);
  849. if ( FAILED(hr) )
  850. {
  851. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod:: Indicate failed with 0x%x"), hr );
  852. retStatus.SetError( hr );
  853. return hr;
  854. }
  855. return hr;
  856. }
  857. #if _MSC_FULL_VER <= 13008827 && defined(_M_IX86)
  858. #pragma optimize("", on)
  859. #endif
  860. //*************************************************************
  861. //
  862. // EnumerateUserNameSpace()
  863. //
  864. // Purpose: EnumerateUserNameSpace
  865. //
  866. // Parameters:
  867. // pWbemLocator - Pointer to a locator
  868. // [out] psaUserSids - Pointer to User Sids
  869. //
  870. // Return: hresult
  871. //
  872. //*************************************************************
  873. typedef struct _UserSidList {
  874. LPWSTR szUserSid;
  875. struct _UserSidList *pNext;
  876. } USERSIDLIST, *PUSERSIDLIST;
  877. HRESULT EnumerateUserNameSpace( IWbemLocator *pWbemLocator, HANDLE hToken, SAFEARRAY **psaUserSids )
  878. {
  879. USERSIDLIST SidList = {0,0};
  880. DWORD dwNum = 0;
  881. PUSERSIDLIST pElem = NULL;
  882. HRESULT hr = S_OK;
  883. DWORD dwExtendedInfo;
  884. IUnknown *pOldSecContext;
  885. //
  886. // Connect to namespace ROOT\RSOP\User
  887. //
  888. *psaUserSids = NULL;
  889. XInterface<IWbemServices>xpWbemServices = NULL;
  890. XBStr xbstrNamespace = RSOP_NS_DIAG_USERROOT;
  891. if(!xbstrNamespace)
  892. {
  893. DebugMsg((DM_WARNING, TEXT("EnumerateUserNameSpace: Failed to allocate memory.")));
  894. return E_OUTOFMEMORY;
  895. }
  896. hr = pWbemLocator->ConnectServer(xbstrNamespace,
  897. NULL,
  898. NULL,
  899. 0L,
  900. 0L,
  901. NULL,
  902. NULL,
  903. &xpWbemServices);
  904. if(FAILED(hr))
  905. {
  906. DebugMsg((DM_WARNING, TEXT("EnumerateUserNameSpace: ConnectServer failed. hr=0x%x" ), hr ));
  907. return hr;
  908. }
  909. //
  910. // Enumerate all instances of __namespace at the root\rsop\user level.
  911. //
  912. XInterface<IEnumWbemClassObject> xpEnum;
  913. XBStr xbstrClass = L"__namespace";
  914. if(!xbstrClass)
  915. {
  916. DebugMsg((DM_WARNING, TEXT("EnumerateUserNameSpace: Failed to allocate memory.")));
  917. return E_OUTOFMEMORY;
  918. }
  919. hr = xpWbemServices->CreateInstanceEnum( xbstrClass,
  920. WBEM_FLAG_SHALLOW | WBEM_FLAG_FORWARD_ONLY,
  921. NULL,
  922. &xpEnum);
  923. if(FAILED(hr))
  924. {
  925. DebugMsg((DM_WARNING, TEXT("EnumerateUserNameSpace: CreateInstanceEnum failed. hr=0x%x" ), hr ));
  926. return hr;
  927. }
  928. XBStr xbstrProperty = L"Name";
  929. if(!xbstrProperty)
  930. {
  931. DebugMsg((DM_WARNING, TEXT("EnumerateUserNameSpace: Failed to allocate memory")));
  932. return E_FAIL;
  933. }
  934. XInterface<IWbemClassObject>xpInstance = NULL;
  935. ULONG ulReturned = 1;
  936. while(1)
  937. {
  938. hr = xpEnum->Next( WBEM_NO_WAIT, 1, &xpInstance, &ulReturned);
  939. if (hr != WBEM_S_NO_ERROR || !ulReturned)
  940. {
  941. break;
  942. }
  943. VARIANT var;
  944. VariantInit(&var);
  945. hr = xpInstance->Get(xbstrProperty, 0L, &var, NULL, NULL);
  946. xpInstance = NULL;
  947. if(FAILED(hr))
  948. {
  949. DebugMsg((DM_VERBOSE, TEXT("EnumerateUserNameSpace: Get failed. hr=0x%x" ), hr ));
  950. goto Exit; // continue
  951. }
  952. //
  953. // Check to see whether user is delegated admin for the user account
  954. //
  955. XPtrLF<WCHAR> xszUserSid = (LPWSTR)LocalAlloc(LPTR, (1+lstrlen(var.bstrVal))*sizeof(WCHAR));
  956. if (!xszUserSid) {
  957. hr = HRESULT_FROM_WIN32(GetLastError());
  958. DebugMsg((DM_VERBOSE, TEXT("EnumerateUserNameSpace: AllocMem failed. hr=0x%x" ), hr ));
  959. goto Exit;
  960. }
  961. ConvertWMINameToSid(var.bstrVal, xszUserSid);
  962. //
  963. // See whether it is a valid Sid
  964. //
  965. PSID pSid = NULL;
  966. if (AllocateAndInitSidFromString(xszUserSid, &pSid) != STATUS_SUCCESS ) {
  967. DebugMsg((DM_VERBOSE, TEXT("EnumerateUserNameSpace: AllocateAndInitSidFromString - %s is not a valid Sid" ), xszUserSid));
  968. continue;
  969. }
  970. if (!IsValidSid(pSid)) {
  971. DebugMsg((DM_VERBOSE, TEXT("EnumerateUserNameSpace: %s is not a valid Sid" ), xszUserSid));
  972. FreeSid(pSid);
  973. continue;
  974. }
  975. FreeSid(pSid);
  976. //
  977. // First try to connect to the NameSpace
  978. //
  979. hr = CoImpersonateClient();
  980. if ( FAILED(hr) )
  981. {
  982. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoImpersonateClient failed with 0x%x"), hr );
  983. goto Exit;
  984. }
  985. XInterface<IWbemServices> xpChildNamespace = NULL;
  986. hr = xpWbemServices->OpenNamespace( var.bstrVal,
  987. 0,
  988. NULL,
  989. &xpChildNamespace,
  990. NULL);
  991. CoRevertToSelf();
  992. if(FAILED(hr))
  993. {
  994. IUnknown *pNewObject;
  995. HRESULT hr2=S_OK;
  996. BOOL bDelegated = TRUE;
  997. DebugMsg((DM_VERBOSE, TEXT("EnumerateUserNameSpace: OpenNamespace returned 0x%x"), hr));
  998. //
  999. // Check whether user has access as LS
  1000. //
  1001. //
  1002. // We want to run as LS
  1003. //
  1004. hr = CoSwitchCallContext(NULL, &pOldSecContext);
  1005. if (FAILED(hr)) {
  1006. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr );
  1007. goto Exit;
  1008. }
  1009. XPtrLF<TCHAR> xszAccount = GetUserAccountName(xszUserSid);
  1010. if (!xszAccount) {
  1011. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::No User account. error %d"), GetLastError() );
  1012. bDelegated = FALSE;
  1013. }
  1014. XPtrLF<TCHAR> xszUserSOM;
  1015. if (bDelegated) {
  1016. xszUserSOM = GetSOM(xszAccount);
  1017. if (!xszUserSOM) {
  1018. dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::No User SOM. Probably local account. error %d"), GetLastError() );
  1019. bDelegated = FALSE;
  1020. }
  1021. }
  1022. //
  1023. // Check access now
  1024. //
  1025. if (bDelegated) {
  1026. hr = AuthenticateUser(hToken, NULL, xszUserSOM, TRUE, &dwExtendedInfo);
  1027. if (FAILED(hr)) {
  1028. dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::User is not a delegated admin. Error 0x%x"), hr );
  1029. bDelegated = FALSE;
  1030. }
  1031. }
  1032. //
  1033. // restore call context
  1034. //
  1035. hr2 = CoSwitchCallContext(pOldSecContext, &pNewObject);
  1036. if (FAILED(hr2)) {
  1037. dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr2 );
  1038. }
  1039. if (!bDelegated) {
  1040. continue;
  1041. }
  1042. }
  1043. //
  1044. // For every instance of __namespace under ROOT\RSOP\user
  1045. // convert it to Sid and return
  1046. //
  1047. pElem = (PUSERSIDLIST)LocalAlloc(LPTR, sizeof(USERSIDLIST));
  1048. if (!pElem) {
  1049. DebugMsg((DM_WARNING, TEXT("EnumerateUserNameSpace: Couldn't allocate memory Error = GetLastError()" ), GetLastError()));
  1050. goto Exit;
  1051. }
  1052. pElem->szUserSid = xszUserSid.Acquire();
  1053. //
  1054. // Attach to the beginning of the list
  1055. //
  1056. pElem->pNext = SidList.pNext;
  1057. SidList.pNext = pElem;
  1058. dwNum++;
  1059. VariantClear( &var );
  1060. }
  1061. if(hr != WBEM_S_FALSE || ulReturned)
  1062. {
  1063. DebugMsg((DM_WARNING, TEXT("EnumerateUserNameSpace: Get failed. hr=0x%x" ), hr ));
  1064. hr = E_FAIL;
  1065. goto Exit;
  1066. }
  1067. //
  1068. // Now make the safe array from the list that we got
  1069. //
  1070. SAFEARRAYBOUND arrayBound[1];
  1071. arrayBound[0].lLbound = 0;
  1072. arrayBound[0].cElements = dwNum;
  1073. *psaUserSids = SafeArrayCreate( VT_BSTR, 1, arrayBound );
  1074. if ( *psaUserSids == NULL ) {
  1075. DebugMsg((DM_WARNING, TEXT("EnumerateUserNameSpace: Failed to allocate memory. Error = %d" ), GetLastError() ));
  1076. hr = E_FAIL;
  1077. goto Exit;
  1078. }
  1079. //
  1080. // traverse the list
  1081. //
  1082. DWORD i;
  1083. for (i=0, pElem = SidList.pNext; (i < dwNum); i++, pElem = pElem->pNext) {
  1084. XBStr xbstrUserSid(pElem->szUserSid);
  1085. SafeArrayPutElement( *psaUserSids, (LONG *)&i, xbstrUserSid);
  1086. }
  1087. hr = S_OK;
  1088. Exit:
  1089. // free
  1090. for (i=0, pElem = SidList.pNext; (i < dwNum); i++ ) {
  1091. if (pElem->szUserSid)
  1092. LocalFree(pElem->szUserSid);
  1093. PUSERSIDLIST pTemp = pElem;
  1094. pElem = pElem->pNext;
  1095. LocalFree(pTemp);
  1096. }
  1097. return hr;
  1098. }