980 lines
27 KiB
C++
980 lines
27 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1993 - 1999.
|
|
//
|
|
// File: CLocalMachine.cpp
|
|
//
|
|
// Contents: implementation of CLocalMachine
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "priv.h"
|
|
|
|
#include "UserOM.h"
|
|
#include "LogonIPC.h"
|
|
#include "CInteractiveLogon.h"
|
|
#include "WinUser.h"
|
|
#include "trayp.h" // for TM_REFRESH
|
|
#include <lmaccess.h> // for NetUserModalsGet
|
|
#include <lmapibuf.h> // for NetApiBufferFree
|
|
#include <lmerr.h> // for NERR_Success
|
|
#include <ntlsa.h>
|
|
#include <cfgmgr32.h>
|
|
//
|
|
// IUnknown Interface
|
|
//
|
|
|
|
ULONG CLocalMachine::AddRef()
|
|
{
|
|
_cRef++;
|
|
return _cRef;
|
|
}
|
|
|
|
|
|
ULONG CLocalMachine::Release()
|
|
{
|
|
ASSERT(_cRef > 0);
|
|
_cRef--;
|
|
|
|
if (_cRef > 0)
|
|
{
|
|
return _cRef;
|
|
}
|
|
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
|
|
HRESULT CLocalMachine::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
static const QITAB qit[] =
|
|
{
|
|
QITABENT(CLocalMachine, IDispatch),
|
|
QITABENT(CLocalMachine, ILocalMachine),
|
|
{0},
|
|
};
|
|
|
|
return QISearch(this, qit, riid, ppvObj);
|
|
}
|
|
|
|
|
|
//
|
|
// IDispatch Interface
|
|
//
|
|
|
|
STDMETHODIMP CLocalMachine::GetTypeInfoCount(UINT* pctinfo)
|
|
{
|
|
return CIDispatchHelper::GetTypeInfoCount(pctinfo);
|
|
}
|
|
|
|
|
|
STDMETHODIMP CLocalMachine::GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
|
|
{
|
|
return CIDispatchHelper::GetTypeInfo(itinfo, lcid, pptinfo);
|
|
}
|
|
|
|
|
|
STDMETHODIMP CLocalMachine::GetIDsOfNames(REFIID riid, OLECHAR** rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid)
|
|
{
|
|
return CIDispatchHelper::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
|
|
}
|
|
|
|
|
|
STDMETHODIMP CLocalMachine::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr)
|
|
{
|
|
return CIDispatchHelper::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
|
|
}
|
|
|
|
|
|
//
|
|
// ILocalMachine Interface
|
|
//
|
|
|
|
|
|
|
|
STDMETHODIMP CLocalMachine::get_MachineName(VARIANT* pvar)
|
|
{
|
|
HRESULT hr;
|
|
DWORD cch;
|
|
WCHAR szMachineName[MAX_COMPUTERNAME_LENGTH+1];
|
|
|
|
if (pvar)
|
|
{
|
|
pvar->vt = VT_BSTR;
|
|
cch = MAX_COMPUTERNAME_LENGTH+1;
|
|
if (GetComputerNameW(szMachineName, &cch))
|
|
{
|
|
pvar->bstrVal = SysAllocString(szMachineName);
|
|
}
|
|
else
|
|
{
|
|
pvar->bstrVal = SysAllocString(TEXT(""));
|
|
}
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
DWORD BuildAccountSidFromRid(LPCWSTR pszServer, DWORD dwRid, PSID* ppSid)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
PUSER_MODALS_INFO_2 umi2;
|
|
NET_API_STATUS nasRet;
|
|
|
|
// Get the account domain Sid on the target machine
|
|
nasRet = NetUserModalsGet(pszServer, 2, (LPBYTE*)&umi2);
|
|
|
|
if ( nasRet == NERR_Success )
|
|
{
|
|
UCHAR cSubAuthorities;
|
|
PSID pSid;
|
|
|
|
cSubAuthorities = *GetSidSubAuthorityCount(umi2->usrmod2_domain_id);
|
|
|
|
// Allocate storage for new the Sid (domain Sid + account Rid)
|
|
pSid = (PSID)LocalAlloc(LPTR, GetSidLengthRequired((UCHAR)(cSubAuthorities+1)));
|
|
|
|
if ( pSid != NULL )
|
|
{
|
|
if ( InitializeSid(pSid,
|
|
GetSidIdentifierAuthority(umi2->usrmod2_domain_id),
|
|
(BYTE)(cSubAuthorities+1)) )
|
|
{
|
|
// Copy existing subauthorities from domain Sid to new Sid
|
|
for (UINT i = 0; i < cSubAuthorities; i++)
|
|
{
|
|
*GetSidSubAuthority(pSid, i) = *GetSidSubAuthority(umi2->usrmod2_domain_id, i);
|
|
}
|
|
|
|
// Append Rid to new Sid
|
|
*GetSidSubAuthority(pSid, cSubAuthorities) = dwRid;
|
|
|
|
*ppSid = pSid;
|
|
}
|
|
else
|
|
{
|
|
dwErr = GetLastError();
|
|
LocalFree(pSid);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwErr = GetLastError();
|
|
}
|
|
|
|
NetApiBufferFree(umi2);
|
|
}
|
|
else
|
|
{
|
|
dwErr = nasRet;
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
BYTE s_rgbGuestSid[sizeof(SID) + (SID_MAX_SUB_AUTHORITIES-1)*sizeof(ULONG)] = {0};
|
|
|
|
DWORD GetGuestSid(PSID* ppSid)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
if (0 == *GetSidSubAuthorityCount((PSID)s_rgbGuestSid))
|
|
{
|
|
PSID pSid = NULL;
|
|
dwErr = BuildAccountSidFromRid(NULL, DOMAIN_USER_RID_GUEST, &pSid);
|
|
|
|
if (ERROR_SUCCESS == dwErr)
|
|
{
|
|
CopySid(sizeof(s_rgbGuestSid), (PSID)s_rgbGuestSid, pSid);
|
|
LocalFree(pSid);
|
|
}
|
|
}
|
|
|
|
// There is no need to free the returned PSID (static buffer)
|
|
*ppSid = (PSID)s_rgbGuestSid;
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
WCHAR s_szGuest[UNLEN + sizeof('\0')] = L"";
|
|
|
|
LPCWSTR GetGuestAccountName(void)
|
|
{
|
|
if (s_szGuest[0] == L'\0')
|
|
{
|
|
DWORD dwGuestSize, dwDomainSize;
|
|
WCHAR szDomain[DNLEN + sizeof('\0')];
|
|
PSID pSID;
|
|
SID_NAME_USE eUse;
|
|
|
|
dwGuestSize = ARRAYSIZE(s_szGuest);
|
|
dwDomainSize = ARRAYSIZE(szDomain);
|
|
if ((ERROR_SUCCESS != GetGuestSid(&pSID)) ||
|
|
!LookupAccountSidW(NULL,
|
|
pSID,
|
|
s_szGuest,
|
|
&dwGuestSize,
|
|
szDomain,
|
|
&dwDomainSize,
|
|
&eUse))
|
|
{
|
|
// Huh? No Guest account on this machine. Try English.
|
|
lstrcpyW(s_szGuest, L"Guest");
|
|
|
|
// Try to go the other way and lookup the SID.
|
|
// If this fails, we're SOL.
|
|
*GetSidSubAuthorityCount((PSID)s_rgbGuestSid) = 0;
|
|
dwGuestSize = sizeof(s_rgbGuestSid);
|
|
dwDomainSize = ARRAYSIZE(szDomain);
|
|
LookupAccountNameW(NULL,
|
|
s_szGuest,
|
|
(PSID)s_rgbGuestSid,
|
|
&dwGuestSize,
|
|
szDomain,
|
|
&dwDomainSize,
|
|
&eUse);
|
|
}
|
|
}
|
|
return(s_szGuest);
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::get_isGuestEnabled(ILM_GUEST_FLAGS flags, VARIANT_BOOL* pbEnabled)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwErr;
|
|
BOOL bEnabled = FALSE;
|
|
USER_INFO_1 *pusri1 = NULL;
|
|
DWORD dwFlags = (DWORD)(flags & (ILM_GUEST_INTERACTIVE_LOGON | ILM_GUEST_NETWORK_LOGON));
|
|
|
|
if (NULL == pbEnabled)
|
|
return E_POINTER;
|
|
|
|
// First check to see if the guest account is truly enabled
|
|
|
|
dwErr = NetUserGetInfo(NULL, GetGuestAccountName(), 1, (LPBYTE*)&pusri1);
|
|
if ((ERROR_SUCCESS == dwErr) && ((pusri1->usri1_flags & UF_ACCOUNTDISABLE) == 0))
|
|
{
|
|
// Guest is enabled
|
|
bEnabled = TRUE;
|
|
|
|
// Do they want to check the LSA logon rights?
|
|
if (0 != dwFlags)
|
|
{
|
|
BOOL bDenyInteractiveLogon = FALSE;
|
|
BOOL bDenyNetworkLogon = FALSE;
|
|
LSA_HANDLE hLsa;
|
|
LSA_OBJECT_ATTRIBUTES oa = {0};
|
|
|
|
oa.Length = sizeof(oa);
|
|
dwErr = LsaNtStatusToWinError(LsaOpenPolicy(NULL, &oa, POLICY_LOOKUP_NAMES, &hLsa));
|
|
|
|
if (ERROR_SUCCESS == dwErr)
|
|
{
|
|
PSID pSid;
|
|
|
|
dwErr = GetGuestSid(&pSid);
|
|
if (ERROR_SUCCESS == dwErr)
|
|
{
|
|
PLSA_UNICODE_STRING pAccountRights;
|
|
ULONG cRights;
|
|
|
|
// Get the list of LSA rights assigned to the Guest account
|
|
//
|
|
// Note that SE_INTERACTIVE_LOGON_NAME is often inherited via
|
|
// group membership, so its absence doesn't mean much. We could
|
|
// bend over backwards and check group membership and such, but
|
|
// Guest normally gets SE_INTERACTIVE_LOGON_NAME one way or
|
|
// another, so we only check for SE_DENY_INTERACTIVE_LOGON_NAME
|
|
// here.
|
|
|
|
dwErr = LsaNtStatusToWinError(LsaEnumerateAccountRights(hLsa, pSid, &pAccountRights, &cRights));
|
|
if (ERROR_SUCCESS == dwErr)
|
|
{
|
|
PLSA_UNICODE_STRING pRight;
|
|
for (pRight = pAccountRights; cRights > 0 && 0 != dwFlags; pRight++, cRights--)
|
|
{
|
|
if (0 != (dwFlags & ILM_GUEST_INTERACTIVE_LOGON) &&
|
|
CSTR_EQUAL == CompareStringW(LOCALE_SYSTEM_DEFAULT,
|
|
NORM_IGNORECASE,
|
|
SE_DENY_INTERACTIVE_LOGON_NAME,
|
|
-1,
|
|
pRight->Buffer,
|
|
pRight->Length/2))
|
|
{
|
|
bDenyInteractiveLogon = TRUE;
|
|
dwFlags &= ~ILM_GUEST_INTERACTIVE_LOGON;
|
|
}
|
|
else if (0 != (dwFlags & ILM_GUEST_NETWORK_LOGON) &&
|
|
CSTR_EQUAL == CompareStringW(LOCALE_SYSTEM_DEFAULT,
|
|
NORM_IGNORECASE,
|
|
SE_DENY_NETWORK_LOGON_NAME,
|
|
-1,
|
|
pRight->Buffer,
|
|
pRight->Length/2))
|
|
{
|
|
bDenyNetworkLogon = TRUE;
|
|
dwFlags &= ~ILM_GUEST_NETWORK_LOGON;
|
|
}
|
|
}
|
|
LsaFreeMemory(pAccountRights);
|
|
}
|
|
else if (ERROR_FILE_NOT_FOUND == dwErr)
|
|
{
|
|
// Guest isn't in LSA's database, so we know it can't
|
|
// have either of the deny logon rights.
|
|
dwErr = ERROR_SUCCESS;
|
|
}
|
|
}
|
|
LsaClose(hLsa);
|
|
}
|
|
|
|
if (bDenyInteractiveLogon || bDenyNetworkLogon)
|
|
bEnabled = FALSE;
|
|
}
|
|
}
|
|
|
|
if (NULL != pusri1)
|
|
{
|
|
(NET_API_STATUS)NetApiBufferFree(pusri1);
|
|
}
|
|
|
|
hr = HRESULT_FROM_WIN32(dwErr);
|
|
|
|
*pbEnabled = bEnabled ? VARIANT_TRUE : VARIANT_FALSE;
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::EnableGuest(ILM_GUEST_FLAGS flags)
|
|
{
|
|
DWORD dwErr;
|
|
USER_INFO_1 *pusri1;
|
|
DWORD dwFlags = (DWORD)(flags & (ILM_GUEST_INTERACTIVE_LOGON | ILM_GUEST_NETWORK_LOGON));
|
|
|
|
// First truly enable the guest account. Do this ALL the time.
|
|
|
|
dwErr = NetUserGetInfo(NULL, GetGuestAccountName(), 1, (LPBYTE*)&pusri1);
|
|
if (ERROR_SUCCESS == dwErr)
|
|
{
|
|
pusri1->usri1_flags &= ~UF_ACCOUNTDISABLE;
|
|
dwErr = NetUserSetInfo(NULL, GetGuestAccountName(), 1, (LPBYTE)pusri1, NULL);
|
|
if (ERROR_SUCCESS == dwErr && 0 != dwFlags)
|
|
{
|
|
LSA_HANDLE hLsa;
|
|
LSA_OBJECT_ATTRIBUTES oa = {0};
|
|
|
|
oa.Length = sizeof(oa);
|
|
dwErr = LsaNtStatusToWinError(LsaOpenPolicy(NULL, &oa, POLICY_LOOKUP_NAMES, &hLsa));
|
|
|
|
if (ERROR_SUCCESS == dwErr)
|
|
{
|
|
PSID pSid;
|
|
|
|
dwErr = GetGuestSid(&pSid);
|
|
if (ERROR_SUCCESS == dwErr)
|
|
{
|
|
if (0 != (dwFlags & ILM_GUEST_INTERACTIVE_LOGON))
|
|
{
|
|
DECLARE_CONST_UNICODE_STRING(usDenyLogon, SE_DENY_INTERACTIVE_LOGON_NAME);
|
|
NTSTATUS status = LsaRemoveAccountRights(hLsa, pSid, FALSE, (PLSA_UNICODE_STRING)&usDenyLogon, 1);
|
|
dwErr = LsaNtStatusToWinError(status);
|
|
}
|
|
if (0 != (dwFlags & ILM_GUEST_NETWORK_LOGON))
|
|
{
|
|
DECLARE_CONST_UNICODE_STRING(usDenyLogon, SE_DENY_NETWORK_LOGON_NAME);
|
|
NTSTATUS status = LsaRemoveAccountRights(hLsa, pSid, FALSE, (PLSA_UNICODE_STRING)&usDenyLogon, 1);
|
|
if (ERROR_SUCCESS == dwErr)
|
|
dwErr = LsaNtStatusToWinError(status);
|
|
}
|
|
|
|
if (ERROR_FILE_NOT_FOUND == dwErr)
|
|
{
|
|
//
|
|
// NTRAID#NTBUG9-396428-2001/05/16-jeffreys
|
|
//
|
|
// This means Guest isn't in LSA's database, so we know
|
|
// it can't have either of the deny logon rights. Since
|
|
// we were trying to remove one or both rights, count
|
|
// this as success.
|
|
//
|
|
dwErr = ERROR_SUCCESS;
|
|
}
|
|
}
|
|
LsaClose(hLsa);
|
|
}
|
|
}
|
|
(NET_API_STATUS)NetApiBufferFree(pusri1);
|
|
}
|
|
|
|
return HRESULT_FROM_WIN32(dwErr);
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::DisableGuest(ILM_GUEST_FLAGS flags)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
DWORD dwFlags = (DWORD)(flags & (ILM_GUEST_INTERACTIVE_LOGON | ILM_GUEST_NETWORK_LOGON));
|
|
|
|
if (0 != dwFlags)
|
|
{
|
|
LSA_HANDLE hLsa;
|
|
LSA_OBJECT_ATTRIBUTES oa = {0};
|
|
|
|
// Turn on DenyInteractiveLogon and/or DenyNetworkLogon, but don't
|
|
// necessarily change the enabled state of the guest account.
|
|
|
|
oa.Length = sizeof(oa);
|
|
dwErr = LsaNtStatusToWinError(LsaOpenPolicy(NULL, &oa, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES, &hLsa));
|
|
|
|
if (ERROR_SUCCESS == dwErr)
|
|
{
|
|
PSID pSid;
|
|
|
|
dwErr = GetGuestSid(&pSid);
|
|
if (ERROR_SUCCESS == dwErr)
|
|
{
|
|
if (0 != (dwFlags & ILM_GUEST_INTERACTIVE_LOGON))
|
|
{
|
|
DECLARE_CONST_UNICODE_STRING(usDenyLogon, SE_DENY_INTERACTIVE_LOGON_NAME);
|
|
NTSTATUS status = LsaAddAccountRights(hLsa, pSid, (PLSA_UNICODE_STRING)&usDenyLogon, 1);
|
|
dwErr = LsaNtStatusToWinError(status);
|
|
}
|
|
if (0 != (dwFlags & ILM_GUEST_NETWORK_LOGON))
|
|
{
|
|
DECLARE_CONST_UNICODE_STRING(usDenyLogon, SE_DENY_NETWORK_LOGON_NAME);
|
|
NTSTATUS status = LsaAddAccountRights(hLsa, pSid, (PLSA_UNICODE_STRING)&usDenyLogon, 1);
|
|
if (ERROR_SUCCESS == dwErr)
|
|
dwErr = LsaNtStatusToWinError(status);
|
|
}
|
|
}
|
|
LsaClose(hLsa);
|
|
}
|
|
|
|
if (ERROR_SUCCESS == dwErr)
|
|
{
|
|
// If both SE_DENY_INTERACTIVE_LOGON_NAME and SE_DENY_NETWORK_LOGON_NAME
|
|
// are turned on, then we might as well disable the account altogether.
|
|
if ((ILM_GUEST_INTERACTIVE_LOGON | ILM_GUEST_NETWORK_LOGON) == dwFlags)
|
|
{
|
|
// We just turned both on, so disable guest below
|
|
dwFlags = 0;
|
|
}
|
|
else
|
|
{
|
|
VARIANT_BOOL bEnabled;
|
|
|
|
if (ILM_GUEST_INTERACTIVE_LOGON == dwFlags)
|
|
{
|
|
// We just turned on SE_DENY_INTERACTIVE_LOGON_NAME, check
|
|
// for SE_DENY_NETWORK_LOGON_NAME.
|
|
flags = ILM_GUEST_NETWORK_LOGON;
|
|
}
|
|
else if (ILM_GUEST_NETWORK_LOGON == dwFlags)
|
|
{
|
|
// We just turned on SE_DENY_NETWORK_LOGON_NAME, check
|
|
// for SE_DENY_INTERACTIVE_LOGON_NAME.
|
|
flags = ILM_GUEST_INTERACTIVE_LOGON;
|
|
}
|
|
else
|
|
{
|
|
// Getting here implies that someone defined a new flag.
|
|
// Setting flags to ILM_GUEST_ACCOUNT causes a benign
|
|
// result in all cases (we only disable guest if guest
|
|
// is already disabled).
|
|
flags = ILM_GUEST_ACCOUNT;
|
|
}
|
|
|
|
if (SUCCEEDED(get_isGuestEnabled(flags, &bEnabled)) && (VARIANT_FALSE == bEnabled))
|
|
{
|
|
// Both are on, so disable guest below
|
|
dwFlags = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (0 == dwFlags)
|
|
{
|
|
USER_INFO_1 *pusri1;
|
|
|
|
// Truly disable the guest account.
|
|
|
|
dwErr = NetUserGetInfo(NULL, GetGuestAccountName(), 1, (LPBYTE*)&pusri1);
|
|
if (ERROR_SUCCESS == dwErr)
|
|
{
|
|
pusri1->usri1_flags |= UF_ACCOUNTDISABLE;
|
|
dwErr = NetUserSetInfo(NULL, GetGuestAccountName(), 1, (LPBYTE)pusri1, NULL);
|
|
(NET_API_STATUS)NetApiBufferFree(pusri1);
|
|
}
|
|
}
|
|
|
|
return HRESULT_FROM_WIN32(dwErr);
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::get_isFriendlyUIEnabled(VARIANT_BOOL* pbEnabled)
|
|
|
|
{
|
|
*pbEnabled = ShellIsFriendlyUIActive() ? VARIANT_TRUE : VARIANT_FALSE;
|
|
return(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::put_isFriendlyUIEnabled(VARIANT_BOOL bEnabled)
|
|
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (ShellEnableFriendlyUI(bEnabled != VARIANT_FALSE ? TRUE : FALSE) != FALSE)
|
|
{
|
|
RefreshStartMenu();
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::get_isMultipleUsersEnabled(VARIANT_BOOL* pbEnabled)
|
|
|
|
{
|
|
*pbEnabled = ShellIsMultipleUsersEnabled() ? VARIANT_TRUE : VARIANT_FALSE;
|
|
return(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::put_isMultipleUsersEnabled(VARIANT_BOOL bEnabled)
|
|
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (ShellEnableMultipleUsers(bEnabled != VARIANT_FALSE ? TRUE : FALSE) != FALSE)
|
|
{
|
|
RefreshStartMenu();
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::get_isRemoteConnectionsEnabled(VARIANT_BOOL* pbEnabled)
|
|
|
|
{
|
|
*pbEnabled = ShellIsRemoteConnectionsEnabled() ? VARIANT_TRUE : VARIANT_FALSE;
|
|
return(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::put_isRemoteConnectionsEnabled(VARIANT_BOOL bEnabled)
|
|
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (ShellEnableRemoteConnections(bEnabled != VARIANT_FALSE ? TRUE : FALSE) != FALSE)
|
|
{
|
|
RefreshStartMenu();
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
BOOL _CanEject()
|
|
{
|
|
BOOL fEjectAllowed = FALSE;
|
|
|
|
if(SHRestricted(REST_NOSMEJECTPC)) //Is there a policy restriction?
|
|
return FALSE;
|
|
|
|
CM_Is_Dock_Station_Present(&fEjectAllowed);
|
|
|
|
return SHTestTokenPrivilege(NULL, SE_UNDOCK_NAME) &&
|
|
fEjectAllowed &&
|
|
!GetSystemMetrics(SM_REMOTESESSION);
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::get_isUndockEnabled(VARIANT_BOOL* pbEnabled)
|
|
|
|
{
|
|
CLogonIPC objLogon;
|
|
|
|
if (objLogon.IsLogonServiceAvailable())
|
|
{
|
|
*pbEnabled = objLogon.TestEjectAllowed() ? VARIANT_TRUE : VARIANT_FALSE;
|
|
}
|
|
else
|
|
{
|
|
*pbEnabled = _CanEject() ? VARIANT_TRUE : VARIANT_FALSE;
|
|
}
|
|
return(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::get_isShutdownAllowed(VARIANT_BOOL* pbShutdownAllowed)
|
|
|
|
{
|
|
CLogonIPC objLogon;
|
|
|
|
if (objLogon.IsLogonServiceAvailable())
|
|
{
|
|
*pbShutdownAllowed = objLogon.TestShutdownAllowed() ? VARIANT_TRUE : VARIANT_FALSE;
|
|
}
|
|
else
|
|
{
|
|
*pbShutdownAllowed = VARIANT_FALSE;
|
|
}
|
|
return(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::get_isGuestAccessMode(VARIANT_BOOL* pbForceGuest)
|
|
{
|
|
*pbForceGuest = SUCCEEDED(_IsGuestAccessMode()) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CLocalMachine::get_isOfflineFilesEnabled(VARIANT_BOOL *pbEnabled)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
*pbEnabled = VARIANT_FALSE;
|
|
|
|
HINSTANCE hInstCscdll = LoadLibrary(TEXT("cscdll.dll"));
|
|
if (NULL != hInstCscdll)
|
|
{
|
|
typedef BOOL (WINAPI *LPCSCENABLED)(void);
|
|
LPCSCENABLED pfnCscEnabled = (LPCSCENABLED)GetProcAddress(hInstCscdll, "CSCIsCSCEnabled");
|
|
if (NULL != pfnCscEnabled)
|
|
{
|
|
if ((*pfnCscEnabled)())
|
|
{
|
|
*pbEnabled = VARIANT_TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = ResultFromLastError();
|
|
}
|
|
FreeLibrary(hInstCscdll);
|
|
}
|
|
else
|
|
{
|
|
hr = ResultFromLastError();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
WCHAR s_szAdmin[UNLEN + sizeof('\0')] = L"";
|
|
|
|
LPCWSTR GetAdminAccountName(void)
|
|
{
|
|
if (s_szAdmin[0] == L'\0')
|
|
{
|
|
BOOL bSuccess = FALSE;
|
|
PSID pSid;
|
|
|
|
if (ERROR_SUCCESS == BuildAccountSidFromRid(NULL,
|
|
DOMAIN_USER_RID_ADMIN,
|
|
&pSid))
|
|
{
|
|
DWORD dwAdminSize, dwDomainSize;
|
|
WCHAR szDomain[DNLEN + sizeof('\0')];
|
|
SID_NAME_USE eUse;
|
|
|
|
dwAdminSize = ARRAYSIZE(s_szAdmin);
|
|
dwDomainSize = ARRAYSIZE(szDomain);
|
|
|
|
bSuccess = LookupAccountSidW(NULL,
|
|
pSid,
|
|
s_szAdmin,
|
|
&dwAdminSize,
|
|
szDomain,
|
|
&dwDomainSize,
|
|
&eUse);
|
|
LocalFree(pSid);
|
|
}
|
|
if (!bSuccess)
|
|
{
|
|
lstrcpyW(s_szAdmin, L"Administrator");
|
|
}
|
|
}
|
|
return(s_szAdmin);
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP CLocalMachine::get_AccountName(VARIANT varAccount, VARIANT* pvar)
|
|
{
|
|
DWORD dwRID = 0;
|
|
LPCWSTR pszName = NULL;
|
|
|
|
if (NULL == pvar)
|
|
return E_POINTER;
|
|
|
|
switch (varAccount.vt)
|
|
{
|
|
case VT_I4:
|
|
case VT_UI4:
|
|
dwRID = varAccount.ulVal;
|
|
break;
|
|
|
|
case VT_BSTR:
|
|
if (0 == StrCmpIW(varAccount.bstrVal, L"Guest"))
|
|
dwRID = DOMAIN_USER_RID_GUEST;
|
|
else if (0 == StrCmpIW(varAccount.bstrVal, L"Administrator"))
|
|
dwRID = DOMAIN_USER_RID_ADMIN;
|
|
else
|
|
return E_INVALIDARG;
|
|
break;
|
|
|
|
default:
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
switch (dwRID)
|
|
{
|
|
case DOMAIN_USER_RID_GUEST:
|
|
pszName = GetGuestAccountName();
|
|
break;
|
|
|
|
case DOMAIN_USER_RID_ADMIN:
|
|
pszName = GetAdminAccountName();
|
|
break;
|
|
|
|
default:
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
pvar->vt = VT_BSTR;
|
|
pvar->bstrVal = SysAllocString(pszName);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::TurnOffComputer()
|
|
{
|
|
HRESULT hr;
|
|
CLogonIPC objLogon;
|
|
|
|
if (!objLogon.IsLogonServiceAvailable())
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (objLogon.TurnOffComputer ())
|
|
hr = S_OK;
|
|
else
|
|
hr = E_FAIL;
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::UndockComputer()
|
|
{
|
|
HRESULT hr;
|
|
CLogonIPC objLogon;
|
|
|
|
if (!objLogon.IsLogonServiceAvailable())
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (objLogon.EjectComputer())
|
|
hr = S_OK;
|
|
else
|
|
hr = E_FAIL;
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::SignalUIHostFailure()
|
|
{
|
|
CLogonIPC objLogon;
|
|
|
|
if (!objLogon.IsLogonServiceAvailable())
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
objLogon.SignalUIHostFailure ();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::AllowExternalCredentials()
|
|
|
|
{
|
|
CLogonIPC objLogon;
|
|
|
|
if (!objLogon.IsLogonServiceAvailable())
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (!objLogon.AllowExternalCredentials ())
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
else
|
|
{
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::RequestExternalCredentials()
|
|
{
|
|
CLogonIPC objLogon;
|
|
|
|
if (!objLogon.IsLogonServiceAvailable())
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
objLogon.RequestExternalCredentials ();
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CLocalMachine::LogonWithExternalCredentials(BSTR pstrUsername, BSTR pstrDomain, BSTR pstrPassword, VARIANT_BOOL* pbRet)
|
|
{
|
|
HRESULT hr;
|
|
CLogonIPC objLogon;
|
|
TCHAR szUsername[UNLEN + sizeof('\0')],
|
|
szDomain[DNLEN + sizeof('\0')],
|
|
szPassword[PWLEN + sizeof('\0')];
|
|
|
|
if (pstrUsername)
|
|
{
|
|
lstrcpyn(szUsername, pstrUsername, ARRAYSIZE(szUsername));
|
|
}
|
|
else
|
|
{
|
|
szUsername[0] = TEXT('\0');
|
|
}
|
|
if (pstrDomain)
|
|
{
|
|
lstrcpyn(szDomain, pstrDomain, ARRAYSIZE(szDomain));
|
|
}
|
|
else
|
|
{
|
|
szDomain[0] = TEXT('\0');
|
|
}
|
|
if (pstrPassword)
|
|
{
|
|
lstrcpyn(szPassword, pstrPassword, ARRAYSIZE(szPassword));
|
|
}
|
|
else
|
|
{
|
|
szPassword[0] = TEXT('\0');
|
|
}
|
|
|
|
if (!objLogon.IsLogonServiceAvailable())
|
|
{
|
|
*pbRet = VARIANT_FALSE;
|
|
return S_OK;
|
|
}
|
|
|
|
if (objLogon.LogUserOn (szUsername, szDomain, szPassword))
|
|
*pbRet = VARIANT_TRUE;
|
|
else
|
|
*pbRet = VARIANT_FALSE;
|
|
|
|
|
|
if (*pbRet)
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CLocalMachine::InitiateInteractiveLogon
|
|
//
|
|
// Arguments: pstrUsername = User name.
|
|
// pstrDomain = Domain.
|
|
// pstrPassword = Password (in clear text).
|
|
// pbRet = Result (returned).
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// Purpose: Send a request for interactive logon using CInteractiveLogon.
|
|
// It's magic. I don't care how it works.
|
|
//
|
|
// History: 2000-12-06 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CLocalMachine::InitiateInteractiveLogon(BSTR pstrUsername, BSTR pstrDomain, BSTR pstrPassword, DWORD dwTimeout, VARIANT_BOOL* pbRet)
|
|
|
|
{
|
|
DWORD dwErrorCode;
|
|
|
|
dwErrorCode = CInteractiveLogon::Initiate(pstrUsername, pstrDomain, pstrPassword, dwTimeout);
|
|
*pbRet = (ERROR_SUCCESS == dwErrorCode) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
return(HRESULT_FROM_WIN32(dwErrorCode));
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CLocalMachine::RefreshStartMenu
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Finds the shell tray window and sends it a message to refresh
|
|
// its contents.
|
|
//
|
|
// History: 2000-08-01 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
void CLocalMachine::RefreshStartMenu (void)
|
|
|
|
{
|
|
HWND hwndTray;
|
|
|
|
hwndTray = FindWindow(TEXT("Shell_TrayWnd"), NULL);
|
|
if (hwndTray != NULL)
|
|
{
|
|
TBOOL(PostMessage(hwndTray, TM_REFRESH, 0, 0));
|
|
}
|
|
}
|
|
|
|
CLocalMachine::CLocalMachine() : _cRef(1), CIDispatchHelper(&IID_ILocalMachine, &LIBID_SHGINALib)
|
|
{
|
|
DllAddRef();
|
|
}
|
|
|
|
|
|
CLocalMachine::~CLocalMachine()
|
|
{
|
|
ASSERT(_cRef == 0);
|
|
DllRelease();
|
|
}
|
|
|
|
|
|
STDAPI CLocalMachine_Create(REFIID riid, LPVOID* ppv)
|
|
{
|
|
HRESULT hr = E_OUTOFMEMORY;
|
|
CLocalMachine* pLocalMachine = new CLocalMachine();
|
|
|
|
if (pLocalMachine)
|
|
{
|
|
hr = pLocalMachine->QueryInterface(riid, ppv);
|
|
pLocalMachine->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|