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.

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