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

1098 lines
31 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1993 - 1999.
  5. //
  6. // File: CLocalMachine.cpp
  7. //
  8. // Contents: implementation of CLocalMachine
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "priv.h"
  12. #include "UserOM.h"
  13. #include "LogonIPC.h"
  14. #include "CInteractiveLogon.h"
  15. #include "WinUser.h"
  16. #include "trayp.h" // for TM_REFRESH
  17. #include <lmaccess.h> // for NetUserModalsGet
  18. #include <lmapibuf.h> // for NetApiBufferFree
  19. #include <lmerr.h> // for NERR_Success
  20. #include <ntlsa.h>
  21. #include <cfgmgr32.h>
  22. #include <cscapi.h> // for CSCIsCSCEnabled
  23. //
  24. // IUnknown Interface
  25. //
  26. ULONG CLocalMachine::AddRef()
  27. {
  28. _cRef++;
  29. return _cRef;
  30. }
  31. ULONG CLocalMachine::Release()
  32. {
  33. ASSERT(_cRef > 0);
  34. _cRef--;
  35. if (_cRef > 0)
  36. {
  37. return _cRef;
  38. }
  39. delete this;
  40. return 0;
  41. }
  42. HRESULT CLocalMachine::QueryInterface(REFIID riid, void **ppvObj)
  43. {
  44. static const QITAB qit[] =
  45. {
  46. QITABENT(CLocalMachine, IDispatch),
  47. QITABENT(CLocalMachine, ILocalMachine),
  48. {0},
  49. };
  50. return QISearch(this, qit, riid, ppvObj);
  51. }
  52. //
  53. // IDispatch Interface
  54. //
  55. STDMETHODIMP CLocalMachine::GetTypeInfoCount(UINT* pctinfo)
  56. {
  57. return CIDispatchHelper::GetTypeInfoCount(pctinfo);
  58. }
  59. STDMETHODIMP CLocalMachine::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
  60. {
  61. return CIDispatchHelper::GetTypeInfo(itinfo, lcid, pptinfo);
  62. }
  63. STDMETHODIMP CLocalMachine::GetIDsOfNames(REFIID riid, OLECHAR** rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid)
  64. {
  65. return CIDispatchHelper::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
  66. }
  67. STDMETHODIMP CLocalMachine::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr)
  68. {
  69. return CIDispatchHelper::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
  70. }
  71. //
  72. // ILocalMachine Interface
  73. //
  74. STDMETHODIMP CLocalMachine::get_MachineName(VARIANT* pvar)
  75. {
  76. HRESULT hr;
  77. DWORD cch;
  78. WCHAR szMachineName[MAX_COMPUTERNAME_LENGTH+1];
  79. if (pvar)
  80. {
  81. pvar->vt = VT_BSTR;
  82. cch = MAX_COMPUTERNAME_LENGTH+1;
  83. if (GetComputerNameW(szMachineName, &cch))
  84. {
  85. pvar->bstrVal = SysAllocString(szMachineName);
  86. }
  87. else
  88. {
  89. pvar->bstrVal = SysAllocString(TEXT(""));
  90. }
  91. hr = S_OK;
  92. }
  93. else
  94. {
  95. hr = E_INVALIDARG;
  96. }
  97. return hr;
  98. }
  99. DWORD BuildAccountSidFromRid(LPCWSTR pszServer, DWORD dwRid, PSID* ppSid)
  100. {
  101. DWORD dwErr = ERROR_SUCCESS;
  102. PUSER_MODALS_INFO_2 umi2;
  103. NET_API_STATUS nasRet;
  104. *ppSid = NULL;
  105. // Get the account domain Sid on the target machine
  106. nasRet = NetUserModalsGet(pszServer, 2, (LPBYTE*)&umi2);
  107. if ( nasRet == NERR_Success )
  108. {
  109. UCHAR cSubAuthorities;
  110. PSID pSid;
  111. cSubAuthorities = *GetSidSubAuthorityCount(umi2->usrmod2_domain_id);
  112. // Allocate storage for new the Sid (domain Sid + account Rid)
  113. pSid = (PSID)LocalAlloc(LPTR, GetSidLengthRequired((UCHAR)(cSubAuthorities+1)));
  114. if (pSid != NULL)
  115. {
  116. if (InitializeSid(pSid,
  117. GetSidIdentifierAuthority(umi2->usrmod2_domain_id),
  118. (BYTE)(cSubAuthorities+1)))
  119. {
  120. // Copy existing subauthorities from domain Sid to new Sid
  121. for (UINT i = 0; i < cSubAuthorities; i++)
  122. {
  123. *GetSidSubAuthority(pSid, i) = *GetSidSubAuthority(umi2->usrmod2_domain_id, i);
  124. }
  125. // Append Rid to new Sid
  126. *GetSidSubAuthority(pSid, cSubAuthorities) = dwRid;
  127. *ppSid = pSid;
  128. }
  129. else
  130. {
  131. dwErr = GetLastError();
  132. LocalFree(pSid);
  133. }
  134. }
  135. else
  136. {
  137. dwErr = GetLastError();
  138. }
  139. NetApiBufferFree(umi2);
  140. }
  141. else
  142. {
  143. dwErr = nasRet;
  144. }
  145. return dwErr;
  146. }
  147. PSID g_pGuestSid = NULL;
  148. DWORD GetGuestSid(PSID* ppSid)
  149. {
  150. DWORD dwErr = ERROR_SUCCESS;
  151. if (g_pGuestSid == NULL)
  152. {
  153. PSID pSid;
  154. dwErr = BuildAccountSidFromRid(NULL, DOMAIN_USER_RID_GUEST, &pSid);
  155. if (dwErr == ERROR_SUCCESS)
  156. {
  157. if (InterlockedCompareExchangePointer(&g_pGuestSid, pSid, NULL))
  158. {
  159. // someone else beat us to initing g_pGuestSid, free ours
  160. LocalFree(pSid);
  161. pSid = NULL;
  162. }
  163. }
  164. }
  165. // There is no need to free the returned PSID
  166. *ppSid = g_pGuestSid;
  167. if (*ppSid == NULL)
  168. {
  169. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  170. }
  171. return dwErr;
  172. }
  173. BOOL FreeGuestSid()
  174. {
  175. BOOL bRet = FALSE;
  176. PSID pSid = (PSID)InterlockedExchangePointer(&g_pGuestSid, NULL);
  177. if (pSid)
  178. {
  179. LocalFree(pSid);
  180. bRet = TRUE;
  181. }
  182. return bRet;
  183. }
  184. LPCWSTR g_pszGuestAccountName = NULL;
  185. LPCWSTR GetGuestAccountName()
  186. {
  187. if (g_pszGuestAccountName == NULL)
  188. {
  189. PSID pSidGuest;
  190. WCHAR szGuestAccountName[UNLEN + 1];
  191. WCHAR szDomain[DNLEN + 1];
  192. DWORD cchGuestAccountName;
  193. DWORD cchDomain;
  194. SID_NAME_USE eUse;
  195. szGuestAccountName[0] = L'\0';
  196. if (GetGuestSid(&pSidGuest) == ERROR_SUCCESS)
  197. {
  198. cchGuestAccountName = ARRAYSIZE(szGuestAccountName);
  199. cchDomain = ARRAYSIZE(szDomain);
  200. if (LookupAccountSidW(NULL,
  201. pSidGuest,
  202. szGuestAccountName,
  203. &cchGuestAccountName,
  204. szDomain,
  205. &cchDomain,
  206. &eUse))
  207. {
  208. ASSERT(szGuestAccountName[0] != L'\0');
  209. }
  210. else
  211. {
  212. // If LookupAccountSid failed, assume english "Guest" and see if the reverse-lookup matches
  213. // the pSidGuest
  214. BYTE rgByte[sizeof(SID) + ((SID_MAX_SUB_AUTHORITIES - 1) * sizeof(ULONG))] = {0};
  215. PSID pSid;
  216. DWORD cbSid;
  217. pSid = (PSID)&rgByte;
  218. cbSid = sizeof(rgByte);
  219. cchDomain = ARRAYSIZE(szDomain);
  220. if (LookupAccountNameW(NULL,
  221. L"Guest",
  222. pSid,
  223. &cbSid,
  224. szDomain,
  225. &cchDomain,
  226. &eUse))
  227. {
  228. if (!EqualSid(pSidGuest, pSid))
  229. {
  230. // guest sid dosen't match the sid for "Guest" account
  231. szGuestAccountName[0] = L'\0';
  232. }
  233. }
  234. }
  235. }
  236. if (szGuestAccountName[0] != L'\0')
  237. {
  238. LPWSTR pwsz;
  239. size_t cch;
  240. cch = lstrlenW(szGuestAccountName) + 1;
  241. pwsz = (LPWSTR)LocalAlloc(LPTR, cch * sizeof(WCHAR));
  242. if (pwsz)
  243. {
  244. if (FAILED(StringCchCopy(pwsz, cch, szGuestAccountName)) ||
  245. InterlockedCompareExchangePointer((void**)&g_pszGuestAccountName, pwsz, NULL))
  246. {
  247. // someone else beat us to initializing g_pszGuestAccountName, free ours
  248. LocalFree(pwsz);
  249. pwsz = NULL;
  250. }
  251. }
  252. }
  253. }
  254. return g_pszGuestAccountName;
  255. }
  256. BOOL FreeGuestAccountName()
  257. {
  258. BOOL bRet = FALSE;
  259. LPWSTR psz = (LPWSTR)InterlockedExchangePointer((void **)&g_pszGuestAccountName, NULL);
  260. if (psz)
  261. {
  262. LocalFree(psz);
  263. bRet = TRUE;
  264. }
  265. return bRet;
  266. }
  267. STDMETHODIMP CLocalMachine::get_isGuestEnabled(ILM_GUEST_FLAGS flags, VARIANT_BOOL* pbEnabled)
  268. {
  269. HRESULT hr = S_OK;
  270. DWORD dwErr;
  271. BOOL bEnabled = FALSE;
  272. USER_INFO_1 *pusri1 = NULL;
  273. DWORD dwFlags = (DWORD)(flags & (ILM_GUEST_INTERACTIVE_LOGON | ILM_GUEST_NETWORK_LOGON));
  274. LPCTSTR pszGuest;
  275. if (NULL == pbEnabled)
  276. {
  277. return E_POINTER;
  278. }
  279. pszGuest = GetGuestAccountName();
  280. if (pszGuest)
  281. {
  282. // First check to see if the guest account is truly enabled
  283. dwErr = NetUserGetInfo(NULL, pszGuest, 1, (LPBYTE*)&pusri1);
  284. if ((ERROR_SUCCESS == dwErr) && ((pusri1->usri1_flags & UF_ACCOUNTDISABLE) == 0))
  285. {
  286. // Guest is enabled
  287. bEnabled = TRUE;
  288. // Do they want to check the LSA logon rights?
  289. if (0 != dwFlags)
  290. {
  291. BOOL bDenyInteractiveLogon = FALSE;
  292. BOOL bDenyNetworkLogon = FALSE;
  293. LSA_HANDLE hLsa;
  294. LSA_OBJECT_ATTRIBUTES oa = {0};
  295. oa.Length = sizeof(oa);
  296. dwErr = LsaNtStatusToWinError(LsaOpenPolicy(NULL, &oa, POLICY_LOOKUP_NAMES, &hLsa));
  297. if (ERROR_SUCCESS == dwErr)
  298. {
  299. PSID pSid;
  300. dwErr = GetGuestSid(&pSid);
  301. if (ERROR_SUCCESS == dwErr)
  302. {
  303. PLSA_UNICODE_STRING pAccountRights;
  304. ULONG cRights;
  305. // Get the list of LSA rights assigned to the Guest account
  306. //
  307. // Note that SE_INTERACTIVE_LOGON_NAME is often inherited via
  308. // group membership, so its absence doesn't mean much. We could
  309. // bend over backwards and check group membership and such, but
  310. // Guest normally gets SE_INTERACTIVE_LOGON_NAME one way or
  311. // another, so we only check for SE_DENY_INTERACTIVE_LOGON_NAME
  312. // here.
  313. dwErr = LsaNtStatusToWinError(LsaEnumerateAccountRights(hLsa, pSid, &pAccountRights, &cRights));
  314. if (ERROR_SUCCESS == dwErr)
  315. {
  316. PLSA_UNICODE_STRING pRight;
  317. for (pRight = pAccountRights; cRights > 0 && 0 != dwFlags; pRight++, cRights--)
  318. {
  319. if (0 != (dwFlags & ILM_GUEST_INTERACTIVE_LOGON) &&
  320. CSTR_EQUAL == CompareStringW(LOCALE_SYSTEM_DEFAULT,
  321. NORM_IGNORECASE,
  322. SE_DENY_INTERACTIVE_LOGON_NAME,
  323. -1,
  324. pRight->Buffer,
  325. pRight->Length/2))
  326. {
  327. bDenyInteractiveLogon = TRUE;
  328. dwFlags &= ~ILM_GUEST_INTERACTIVE_LOGON;
  329. }
  330. else if (0 != (dwFlags & ILM_GUEST_NETWORK_LOGON) &&
  331. CSTR_EQUAL == CompareStringW(LOCALE_SYSTEM_DEFAULT,
  332. NORM_IGNORECASE,
  333. SE_DENY_NETWORK_LOGON_NAME,
  334. -1,
  335. pRight->Buffer,
  336. pRight->Length/2))
  337. {
  338. bDenyNetworkLogon = TRUE;
  339. dwFlags &= ~ILM_GUEST_NETWORK_LOGON;
  340. }
  341. }
  342. LsaFreeMemory(pAccountRights);
  343. }
  344. else if (ERROR_FILE_NOT_FOUND == dwErr)
  345. {
  346. // Guest isn't in LSA's database, so we know it can't
  347. // have either of the deny logon rights.
  348. dwErr = ERROR_SUCCESS;
  349. }
  350. }
  351. LsaClose(hLsa);
  352. }
  353. if (bDenyInteractiveLogon || bDenyNetworkLogon)
  354. bEnabled = FALSE;
  355. }
  356. }
  357. }
  358. else
  359. {
  360. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  361. }
  362. if (NULL != pusri1)
  363. {
  364. (NET_API_STATUS)NetApiBufferFree(pusri1);
  365. }
  366. hr = HRESULT_FROM_WIN32(dwErr);
  367. *pbEnabled = bEnabled ? VARIANT_TRUE : VARIANT_FALSE;
  368. return hr;
  369. }
  370. STDMETHODIMP CLocalMachine::EnableGuest(ILM_GUEST_FLAGS flags)
  371. {
  372. DWORD dwErr;
  373. USER_INFO_1 *pusri1;
  374. DWORD dwFlags = (DWORD)(flags & (ILM_GUEST_INTERACTIVE_LOGON | ILM_GUEST_NETWORK_LOGON));
  375. LPCTSTR pszGuest;
  376. pszGuest = GetGuestAccountName();
  377. if (pszGuest)
  378. {
  379. // First truly enable the guest account. Do this ALL the time.
  380. dwErr = NetUserGetInfo(NULL, pszGuest, 1, (LPBYTE*)&pusri1);
  381. if (ERROR_SUCCESS == dwErr)
  382. {
  383. pusri1->usri1_flags &= ~UF_ACCOUNTDISABLE;
  384. dwErr = NetUserSetInfo(NULL, pszGuest, 1, (LPBYTE)pusri1, NULL);
  385. if (ERROR_SUCCESS == dwErr && 0 != dwFlags)
  386. {
  387. LSA_HANDLE hLsa;
  388. LSA_OBJECT_ATTRIBUTES oa = {0};
  389. oa.Length = sizeof(oa);
  390. dwErr = LsaNtStatusToWinError(LsaOpenPolicy(NULL, &oa, POLICY_LOOKUP_NAMES, &hLsa));
  391. if (ERROR_SUCCESS == dwErr)
  392. {
  393. PSID pSid;
  394. dwErr = GetGuestSid(&pSid);
  395. if (ERROR_SUCCESS == dwErr)
  396. {
  397. if (0 != (dwFlags & ILM_GUEST_INTERACTIVE_LOGON))
  398. {
  399. DECLARE_CONST_UNICODE_STRING(usDenyLogon, SE_DENY_INTERACTIVE_LOGON_NAME);
  400. NTSTATUS status = LsaRemoveAccountRights(hLsa, pSid, FALSE, (PLSA_UNICODE_STRING)&usDenyLogon, 1);
  401. dwErr = LsaNtStatusToWinError(status);
  402. }
  403. if (0 != (dwFlags & ILM_GUEST_NETWORK_LOGON))
  404. {
  405. DECLARE_CONST_UNICODE_STRING(usDenyLogon, SE_DENY_NETWORK_LOGON_NAME);
  406. NTSTATUS status = LsaRemoveAccountRights(hLsa, pSid, FALSE, (PLSA_UNICODE_STRING)&usDenyLogon, 1);
  407. if (ERROR_SUCCESS == dwErr)
  408. dwErr = LsaNtStatusToWinError(status);
  409. }
  410. if (ERROR_FILE_NOT_FOUND == dwErr)
  411. {
  412. //
  413. // NTRAID#NTBUG9-396428-2001/05/16-jeffreys
  414. //
  415. // This means Guest isn't in LSA's database, so we know
  416. // it can't have either of the deny logon rights. Since
  417. // we were trying to remove one or both rights, count
  418. // this as success.
  419. //
  420. dwErr = ERROR_SUCCESS;
  421. }
  422. }
  423. LsaClose(hLsa);
  424. }
  425. }
  426. (NET_API_STATUS)NetApiBufferFree(pusri1);
  427. }
  428. }
  429. else
  430. {
  431. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  432. }
  433. return HRESULT_FROM_WIN32(dwErr);
  434. }
  435. STDMETHODIMP CLocalMachine::DisableGuest(ILM_GUEST_FLAGS flags)
  436. {
  437. DWORD dwErr = ERROR_SUCCESS;
  438. DWORD dwFlags = (DWORD)(flags & (ILM_GUEST_INTERACTIVE_LOGON | ILM_GUEST_NETWORK_LOGON));
  439. if (0 != dwFlags)
  440. {
  441. LSA_HANDLE hLsa;
  442. LSA_OBJECT_ATTRIBUTES oa = {0};
  443. // Turn on DenyInteractiveLogon and/or DenyNetworkLogon, but don't
  444. // necessarily change the enabled state of the guest account.
  445. oa.Length = sizeof(oa);
  446. dwErr = LsaNtStatusToWinError(LsaOpenPolicy(NULL, &oa, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &hLsa));
  447. if (ERROR_SUCCESS == dwErr)
  448. {
  449. PSID pSid;
  450. dwErr = GetGuestSid(&pSid);
  451. if (ERROR_SUCCESS == dwErr)
  452. {
  453. if (0 != (dwFlags & ILM_GUEST_INTERACTIVE_LOGON))
  454. {
  455. DECLARE_CONST_UNICODE_STRING(usDenyLogon, SE_DENY_INTERACTIVE_LOGON_NAME);
  456. NTSTATUS status = LsaAddAccountRights(hLsa, pSid, (PLSA_UNICODE_STRING)&usDenyLogon, 1);
  457. dwErr = LsaNtStatusToWinError(status);
  458. }
  459. if (0 != (dwFlags & ILM_GUEST_NETWORK_LOGON))
  460. {
  461. DECLARE_CONST_UNICODE_STRING(usDenyLogon, SE_DENY_NETWORK_LOGON_NAME);
  462. NTSTATUS status = LsaAddAccountRights(hLsa, pSid, (PLSA_UNICODE_STRING)&usDenyLogon, 1);
  463. if (ERROR_SUCCESS == dwErr)
  464. dwErr = LsaNtStatusToWinError(status);
  465. }
  466. }
  467. LsaClose(hLsa);
  468. }
  469. if (ERROR_SUCCESS == dwErr)
  470. {
  471. // If both SE_DENY_INTERACTIVE_LOGON_NAME and SE_DENY_NETWORK_LOGON_NAME
  472. // are turned on, then we might as well disable the account altogether.
  473. if ((ILM_GUEST_INTERACTIVE_LOGON | ILM_GUEST_NETWORK_LOGON) == dwFlags)
  474. {
  475. // We just turned both on, so disable guest below
  476. dwFlags = 0;
  477. }
  478. else
  479. {
  480. VARIANT_BOOL bEnabled;
  481. if (ILM_GUEST_INTERACTIVE_LOGON == dwFlags)
  482. {
  483. // We just turned on SE_DENY_INTERACTIVE_LOGON_NAME, check
  484. // for SE_DENY_NETWORK_LOGON_NAME.
  485. flags = ILM_GUEST_NETWORK_LOGON;
  486. }
  487. else if (ILM_GUEST_NETWORK_LOGON == dwFlags)
  488. {
  489. // We just turned on SE_DENY_NETWORK_LOGON_NAME, check
  490. // for SE_DENY_INTERACTIVE_LOGON_NAME.
  491. flags = ILM_GUEST_INTERACTIVE_LOGON;
  492. }
  493. else
  494. {
  495. // Getting here implies that someone defined a new flag.
  496. // Setting flags to ILM_GUEST_ACCOUNT causes a benign
  497. // result in all cases (we only disable guest if guest
  498. // is already disabled).
  499. flags = ILM_GUEST_ACCOUNT;
  500. }
  501. if (SUCCEEDED(get_isGuestEnabled(flags, &bEnabled)) && (VARIANT_FALSE == bEnabled))
  502. {
  503. // Both are on, so disable guest below
  504. dwFlags = 0;
  505. }
  506. }
  507. }
  508. }
  509. if (0 == dwFlags)
  510. {
  511. USER_INFO_1 *pusri1;
  512. LPCTSTR pszGuest = GetGuestAccountName();
  513. if (pszGuest)
  514. {
  515. // Truly disable the guest account.
  516. dwErr = NetUserGetInfo(NULL, pszGuest, 1, (LPBYTE*)&pusri1);
  517. if (ERROR_SUCCESS == dwErr)
  518. {
  519. pusri1->usri1_flags |= UF_ACCOUNTDISABLE;
  520. dwErr = NetUserSetInfo(NULL, GetGuestAccountName(), 1, (LPBYTE)pusri1, NULL);
  521. (NET_API_STATUS)NetApiBufferFree(pusri1);
  522. }
  523. }
  524. else
  525. {
  526. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  527. }
  528. }
  529. return HRESULT_FROM_WIN32(dwErr);
  530. }
  531. STDMETHODIMP CLocalMachine::get_isFriendlyUIEnabled(VARIANT_BOOL* pbEnabled)
  532. {
  533. *pbEnabled = ShellIsFriendlyUIActive() ? VARIANT_TRUE : VARIANT_FALSE;
  534. return(S_OK);
  535. }
  536. STDMETHODIMP CLocalMachine::put_isFriendlyUIEnabled(VARIANT_BOOL bEnabled)
  537. {
  538. HRESULT hr;
  539. if (ShellEnableFriendlyUI(bEnabled != VARIANT_FALSE ? TRUE : FALSE) != FALSE)
  540. {
  541. RefreshStartMenu();
  542. hr = S_OK;
  543. }
  544. else
  545. {
  546. hr = HRESULT_FROM_WIN32(GetLastError());
  547. }
  548. return(hr);
  549. }
  550. STDMETHODIMP CLocalMachine::get_isMultipleUsersEnabled(VARIANT_BOOL* pbEnabled)
  551. {
  552. *pbEnabled = ShellIsMultipleUsersEnabled() ? VARIANT_TRUE : VARIANT_FALSE;
  553. return(S_OK);
  554. }
  555. STDMETHODIMP CLocalMachine::put_isMultipleUsersEnabled(VARIANT_BOOL bEnabled)
  556. {
  557. HRESULT hr;
  558. if (ShellEnableMultipleUsers(bEnabled != VARIANT_FALSE ? TRUE : FALSE) != FALSE)
  559. {
  560. RefreshStartMenu();
  561. hr = S_OK;
  562. }
  563. else
  564. {
  565. hr = HRESULT_FROM_WIN32(GetLastError());
  566. }
  567. return(hr);
  568. }
  569. STDMETHODIMP CLocalMachine::get_isRemoteConnectionsEnabled(VARIANT_BOOL* pbEnabled)
  570. {
  571. *pbEnabled = ShellIsRemoteConnectionsEnabled() ? VARIANT_TRUE : VARIANT_FALSE;
  572. return(S_OK);
  573. }
  574. STDMETHODIMP CLocalMachine::put_isRemoteConnectionsEnabled(VARIANT_BOOL bEnabled)
  575. {
  576. HRESULT hr;
  577. if (ShellEnableRemoteConnections(bEnabled != VARIANT_FALSE ? TRUE : FALSE) != FALSE)
  578. {
  579. RefreshStartMenu();
  580. hr = S_OK;
  581. }
  582. else
  583. {
  584. hr = HRESULT_FROM_WIN32(GetLastError());
  585. }
  586. return(hr);
  587. }
  588. BOOL _CanEject()
  589. {
  590. BOOL fEjectAllowed = FALSE;
  591. if(SHRestricted(REST_NOSMEJECTPC)) //Is there a policy restriction?
  592. return FALSE;
  593. CM_Is_Dock_Station_Present(&fEjectAllowed);
  594. return SHTestTokenPrivilege(NULL, SE_UNDOCK_NAME) &&
  595. fEjectAllowed &&
  596. !GetSystemMetrics(SM_REMOTESESSION);
  597. }
  598. STDMETHODIMP CLocalMachine::get_isUndockEnabled(VARIANT_BOOL* pbEnabled)
  599. {
  600. CLogonIPC objLogon;
  601. if (objLogon.IsLogonServiceAvailable())
  602. {
  603. *pbEnabled = objLogon.TestEjectAllowed() ? VARIANT_TRUE : VARIANT_FALSE;
  604. }
  605. else
  606. {
  607. *pbEnabled = _CanEject() ? VARIANT_TRUE : VARIANT_FALSE;
  608. }
  609. return(S_OK);
  610. }
  611. STDMETHODIMP CLocalMachine::get_isShutdownAllowed(VARIANT_BOOL* pbShutdownAllowed)
  612. {
  613. CLogonIPC objLogon;
  614. if (objLogon.IsLogonServiceAvailable())
  615. {
  616. *pbShutdownAllowed = objLogon.TestShutdownAllowed() ? VARIANT_TRUE : VARIANT_FALSE;
  617. }
  618. else
  619. {
  620. *pbShutdownAllowed = VARIANT_FALSE;
  621. }
  622. return(S_OK);
  623. }
  624. STDMETHODIMP CLocalMachine::get_isGuestAccessMode(VARIANT_BOOL* pbForceGuest)
  625. {
  626. *pbForceGuest = SUCCEEDED(_IsGuestAccessMode()) ? VARIANT_TRUE : VARIANT_FALSE;
  627. return S_OK;
  628. }
  629. STDMETHODIMP CLocalMachine::get_isOfflineFilesEnabled(VARIANT_BOOL *pbEnabled)
  630. {
  631. if (CSCIsCSCEnabled())
  632. {
  633. *pbEnabled = VARIANT_TRUE;
  634. }
  635. else
  636. {
  637. *pbEnabled = VARIANT_FALSE;
  638. }
  639. return S_OK;
  640. }
  641. LPCWSTR g_pszAdminAccountName = NULL;
  642. LPCWSTR GetAdminAccountName(void)
  643. {
  644. if (g_pszAdminAccountName == NULL)
  645. {
  646. PSID pSidAdmin;
  647. if (BuildAccountSidFromRid(NULL,
  648. DOMAIN_USER_RID_ADMIN,
  649. &pSidAdmin) == ERROR_SUCCESS)
  650. {
  651. WCHAR szAdminAccountName[UNLEN + 1];
  652. WCHAR szDomain[DNLEN + 1];
  653. DWORD cchAdminAccountName;
  654. DWORD cchDomain;
  655. SID_NAME_USE eUse;
  656. cchAdminAccountName = ARRAYSIZE(szAdminAccountName);
  657. cchDomain = ARRAYSIZE(szDomain);
  658. if (LookupAccountSidW(NULL,
  659. pSidAdmin,
  660. szAdminAccountName,
  661. &cchAdminAccountName,
  662. szDomain,
  663. &cchDomain,
  664. &eUse))
  665. {
  666. LPWSTR psz;
  667. DWORD cch;
  668. ASSERT(szAdminAccountName[0] != L'\0');
  669. cch = lstrlenW(szAdminAccountName) + 1;
  670. psz = (LPWSTR)LocalAlloc(LPTR, cch * sizeof(WCHAR));
  671. if (psz)
  672. {
  673. if (InterlockedCompareExchangePointer((void**)&g_pszAdminAccountName, psz, NULL))
  674. {
  675. // someone else beat us to initing g_pszAdminAccountName, free ours
  676. LocalFree(psz);
  677. psz = NULL;
  678. }
  679. }
  680. }
  681. LocalFree(pSidAdmin);
  682. }
  683. }
  684. return g_pszAdminAccountName;
  685. }
  686. BOOL FreeAdminAccountName()
  687. {
  688. BOOL bRet = FALSE;
  689. LPWSTR psz = (LPWSTR)InterlockedExchangePointer((void **)&g_pszAdminAccountName, NULL);
  690. if (psz)
  691. {
  692. LocalFree(psz);
  693. bRet = TRUE;
  694. }
  695. return bRet;
  696. }
  697. STDMETHODIMP CLocalMachine::get_AccountName(VARIANT varAccount, VARIANT* pvar)
  698. {
  699. DWORD dwRID = 0;
  700. LPCWSTR pszName = NULL;
  701. if (NULL == pvar)
  702. return E_POINTER;
  703. switch (varAccount.vt)
  704. {
  705. case VT_I4:
  706. case VT_UI4:
  707. dwRID = varAccount.ulVal;
  708. break;
  709. case VT_BSTR:
  710. if (0 == StrCmpIW(varAccount.bstrVal, L"Guest"))
  711. dwRID = DOMAIN_USER_RID_GUEST;
  712. else if (0 == StrCmpIW(varAccount.bstrVal, L"Administrator"))
  713. dwRID = DOMAIN_USER_RID_ADMIN;
  714. else
  715. return E_INVALIDARG;
  716. break;
  717. default:
  718. return E_INVALIDARG;
  719. }
  720. switch (dwRID)
  721. {
  722. case DOMAIN_USER_RID_GUEST:
  723. pszName = GetGuestAccountName();
  724. break;
  725. case DOMAIN_USER_RID_ADMIN:
  726. pszName = GetAdminAccountName();
  727. break;
  728. default:
  729. return E_INVALIDARG;
  730. }
  731. pvar->vt = VT_BSTR;
  732. pvar->bstrVal = SysAllocString(pszName);
  733. return(S_OK);
  734. }
  735. STDMETHODIMP CLocalMachine::TurnOffComputer()
  736. {
  737. HRESULT hr;
  738. CLogonIPC objLogon;
  739. if (!objLogon.IsLogonServiceAvailable())
  740. {
  741. return E_FAIL;
  742. }
  743. if (objLogon.TurnOffComputer ())
  744. hr = S_OK;
  745. else
  746. hr = E_FAIL;
  747. return hr;
  748. }
  749. STDMETHODIMP CLocalMachine::UndockComputer()
  750. {
  751. HRESULT hr;
  752. CLogonIPC objLogon;
  753. if (!objLogon.IsLogonServiceAvailable())
  754. {
  755. return E_FAIL;
  756. }
  757. if (objLogon.EjectComputer())
  758. hr = S_OK;
  759. else
  760. hr = E_FAIL;
  761. return hr;
  762. }
  763. STDMETHODIMP CLocalMachine::SignalUIHostFailure()
  764. {
  765. CLogonIPC objLogon;
  766. if (!objLogon.IsLogonServiceAvailable())
  767. {
  768. return E_FAIL;
  769. }
  770. objLogon.SignalUIHostFailure ();
  771. return S_OK;
  772. }
  773. STDMETHODIMP CLocalMachine::AllowExternalCredentials()
  774. {
  775. CLogonIPC objLogon;
  776. if (!objLogon.IsLogonServiceAvailable())
  777. {
  778. return E_FAIL;
  779. }
  780. if (!objLogon.AllowExternalCredentials ())
  781. {
  782. return E_NOTIMPL;
  783. }
  784. else
  785. {
  786. return S_OK;
  787. }
  788. }
  789. STDMETHODIMP CLocalMachine::RequestExternalCredentials()
  790. {
  791. CLogonIPC objLogon;
  792. if (!objLogon.IsLogonServiceAvailable())
  793. {
  794. return E_FAIL;
  795. }
  796. objLogon.RequestExternalCredentials ();
  797. return S_OK;
  798. }
  799. STDMETHODIMP CLocalMachine::LogonWithExternalCredentials(BSTR pstrUsername, BSTR pstrDomain, BSTR pstrPassword, VARIANT_BOOL* pbRet)
  800. {
  801. HRESULT hr;
  802. CLogonIPC objLogon;
  803. TCHAR szUsername[UNLEN + 1];
  804. TCHAR szDomain[DNLEN + 1];
  805. TCHAR szPassword[PWLEN + 1];
  806. if (pstrUsername)
  807. {
  808. StringCchCopy(szUsername, ARRAYSIZE(szUsername), pstrUsername);
  809. }
  810. else
  811. {
  812. szUsername[0] = TEXT('\0');
  813. }
  814. if (pstrDomain)
  815. {
  816. StringCchCopy(szDomain, ARRAYSIZE(szDomain), pstrDomain);
  817. }
  818. else
  819. {
  820. szDomain[0] = TEXT('\0');
  821. }
  822. if (pstrPassword)
  823. {
  824. StringCchCopy(szPassword, ARRAYSIZE(szPassword), pstrPassword);
  825. }
  826. else
  827. {
  828. szPassword[0] = TEXT('\0');
  829. }
  830. if (!objLogon.IsLogonServiceAvailable())
  831. {
  832. *pbRet = VARIANT_FALSE;
  833. hr = S_OK;
  834. }
  835. else
  836. {
  837. if (objLogon.LogUserOn(szUsername, szDomain, szPassword))
  838. {
  839. *pbRet = VARIANT_TRUE;
  840. hr = S_OK;
  841. }
  842. else
  843. {
  844. *pbRet = VARIANT_FALSE;
  845. hr = HRESULT_FROM_WIN32(GetLastError());
  846. }
  847. }
  848. return hr;
  849. }
  850. // --------------------------------------------------------------------------
  851. // CLocalMachine::InitiateInteractiveLogon
  852. //
  853. // Arguments: pstrUsername = User name.
  854. // pstrDomain = Domain.
  855. // pstrPassword = Password (in clear text).
  856. // pbRet = Result (returned).
  857. //
  858. // Returns: HRESULT
  859. //
  860. // Purpose: Send a request for interactive logon using CInteractiveLogon.
  861. // It's magic. I don't care how it works.
  862. //
  863. // History: 2000-12-06 vtan created
  864. // --------------------------------------------------------------------------
  865. STDMETHODIMP CLocalMachine::InitiateInteractiveLogon(BSTR pstrUsername, BSTR pstrDomain, BSTR pstrPassword, DWORD dwTimeout, VARIANT_BOOL* pbRet)
  866. {
  867. DWORD dwErrorCode;
  868. dwErrorCode = CInteractiveLogon::Initiate(pstrUsername, pstrDomain, pstrPassword, dwTimeout);
  869. *pbRet = (ERROR_SUCCESS == dwErrorCode) ? VARIANT_TRUE : VARIANT_FALSE;
  870. return(HRESULT_FROM_WIN32(dwErrorCode));
  871. }
  872. // --------------------------------------------------------------------------
  873. // CLocalMachine::RefreshStartMenu
  874. //
  875. // Arguments: <none>
  876. //
  877. // Returns: <none>
  878. //
  879. // Purpose: Finds the shell tray window and sends it a message to refresh
  880. // its contents.
  881. //
  882. // History: 2000-08-01 vtan created
  883. // --------------------------------------------------------------------------
  884. void CLocalMachine::RefreshStartMenu (void)
  885. {
  886. HWND hwndTray;
  887. hwndTray = FindWindow(TEXT("Shell_TrayWnd"), NULL);
  888. if (hwndTray != NULL)
  889. {
  890. TBOOL(PostMessage(hwndTray, TM_REFRESH, 0, 0));
  891. }
  892. }
  893. CLocalMachine::CLocalMachine() : _cRef(1), CIDispatchHelper(&IID_ILocalMachine, &LIBID_SHGINALib)
  894. {
  895. DllAddRef();
  896. }
  897. CLocalMachine::~CLocalMachine()
  898. {
  899. ASSERT(_cRef == 0);
  900. DllRelease();
  901. }
  902. STDAPI CLocalMachine_Create(REFIID riid, LPVOID* ppv)
  903. {
  904. HRESULT hr = E_OUTOFMEMORY;
  905. CLocalMachine* pLocalMachine = new CLocalMachine();
  906. if (pLocalMachine)
  907. {
  908. hr = pLocalMachine->QueryInterface(riid, ppv);
  909. pLocalMachine->Release();
  910. }
  911. return hr;
  912. }