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

//+---------------------------------------------------------------------------
//
// 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>
#include <cscapi.h> // for CSCIsCSCEnabled
//
// 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;
*ppSid = NULL;
// 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;
}
PSID g_pGuestSid = NULL;
DWORD GetGuestSid(PSID* ppSid)
{
DWORD dwErr = ERROR_SUCCESS;
if (g_pGuestSid == NULL)
{
PSID pSid;
dwErr = BuildAccountSidFromRid(NULL, DOMAIN_USER_RID_GUEST, &pSid);
if (dwErr == ERROR_SUCCESS)
{
if (InterlockedCompareExchangePointer(&g_pGuestSid, pSid, NULL))
{
// someone else beat us to initing g_pGuestSid, free ours
LocalFree(pSid);
pSid = NULL;
}
}
}
// There is no need to free the returned PSID
*ppSid = g_pGuestSid;
if (*ppSid == NULL)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
}
return dwErr;
}
BOOL FreeGuestSid()
{
BOOL bRet = FALSE;
PSID pSid = (PSID)InterlockedExchangePointer(&g_pGuestSid, NULL);
if (pSid)
{
LocalFree(pSid);
bRet = TRUE;
}
return bRet;
}
LPCWSTR g_pszGuestAccountName = NULL;
LPCWSTR GetGuestAccountName()
{
if (g_pszGuestAccountName == NULL)
{
PSID pSidGuest;
WCHAR szGuestAccountName[UNLEN + 1];
WCHAR szDomain[DNLEN + 1];
DWORD cchGuestAccountName;
DWORD cchDomain;
SID_NAME_USE eUse;
szGuestAccountName[0] = L'\0';
if (GetGuestSid(&pSidGuest) == ERROR_SUCCESS)
{
cchGuestAccountName = ARRAYSIZE(szGuestAccountName);
cchDomain = ARRAYSIZE(szDomain);
if (LookupAccountSidW(NULL,
pSidGuest,
szGuestAccountName,
&cchGuestAccountName,
szDomain,
&cchDomain,
&eUse))
{
ASSERT(szGuestAccountName[0] != L'\0');
}
else
{
// If LookupAccountSid failed, assume english "Guest" and see if the reverse-lookup matches
// the pSidGuest
BYTE rgByte[sizeof(SID) + ((SID_MAX_SUB_AUTHORITIES - 1) * sizeof(ULONG))] = {0};
PSID pSid;
DWORD cbSid;
pSid = (PSID)&rgByte;
cbSid = sizeof(rgByte);
cchDomain = ARRAYSIZE(szDomain);
if (LookupAccountNameW(NULL,
L"Guest",
pSid,
&cbSid,
szDomain,
&cchDomain,
&eUse))
{
if (!EqualSid(pSidGuest, pSid))
{
// guest sid dosen't match the sid for "Guest" account
szGuestAccountName[0] = L'\0';
}
}
}
}
if (szGuestAccountName[0] != L'\0')
{
LPWSTR pwsz;
size_t cch;
cch = lstrlenW(szGuestAccountName) + 1;
pwsz = (LPWSTR)LocalAlloc(LPTR, cch * sizeof(WCHAR));
if (pwsz)
{
if (FAILED(StringCchCopy(pwsz, cch, szGuestAccountName)) ||
InterlockedCompareExchangePointer((void**)&g_pszGuestAccountName, pwsz, NULL))
{
// someone else beat us to initializing g_pszGuestAccountName, free ours
LocalFree(pwsz);
pwsz = NULL;
}
}
}
}
return g_pszGuestAccountName;
}
BOOL FreeGuestAccountName()
{
BOOL bRet = FALSE;
LPWSTR psz = (LPWSTR)InterlockedExchangePointer((void **)&g_pszGuestAccountName, NULL);
if (psz)
{
LocalFree(psz);
bRet = TRUE;
}
return bRet;
}
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));
LPCTSTR pszGuest;
if (NULL == pbEnabled)
{
return E_POINTER;
}
pszGuest = GetGuestAccountName();
if (pszGuest)
{
// First check to see if the guest account is truly enabled
dwErr = NetUserGetInfo(NULL, pszGuest, 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;
}
}
}
else
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
}
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));
LPCTSTR pszGuest;
pszGuest = GetGuestAccountName();
if (pszGuest)
{
// First truly enable the guest account. Do this ALL the time.
dwErr = NetUserGetInfo(NULL, pszGuest, 1, (LPBYTE*)&pusri1);
if (ERROR_SUCCESS == dwErr)
{
pusri1->usri1_flags &= ~UF_ACCOUNTDISABLE;
dwErr = NetUserSetInfo(NULL, pszGuest, 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);
}
}
else
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
}
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;
LPCTSTR pszGuest = GetGuestAccountName();
if (pszGuest)
{
// Truly disable the guest account.
dwErr = NetUserGetInfo(NULL, pszGuest, 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);
}
}
else
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
}
}
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)
{
if (CSCIsCSCEnabled())
{
*pbEnabled = VARIANT_TRUE;
}
else
{
*pbEnabled = VARIANT_FALSE;
}
return S_OK;
}
LPCWSTR g_pszAdminAccountName = NULL;
LPCWSTR GetAdminAccountName(void)
{
if (g_pszAdminAccountName == NULL)
{
PSID pSidAdmin;
if (BuildAccountSidFromRid(NULL,
DOMAIN_USER_RID_ADMIN,
&pSidAdmin) == ERROR_SUCCESS)
{
WCHAR szAdminAccountName[UNLEN + 1];
WCHAR szDomain[DNLEN + 1];
DWORD cchAdminAccountName;
DWORD cchDomain;
SID_NAME_USE eUse;
cchAdminAccountName = ARRAYSIZE(szAdminAccountName);
cchDomain = ARRAYSIZE(szDomain);
if (LookupAccountSidW(NULL,
pSidAdmin,
szAdminAccountName,
&cchAdminAccountName,
szDomain,
&cchDomain,
&eUse))
{
LPWSTR psz;
DWORD cch;
ASSERT(szAdminAccountName[0] != L'\0');
cch = lstrlenW(szAdminAccountName) + 1;
psz = (LPWSTR)LocalAlloc(LPTR, cch * sizeof(WCHAR));
if (psz)
{
if (InterlockedCompareExchangePointer((void**)&g_pszAdminAccountName, psz, NULL))
{
// someone else beat us to initing g_pszAdminAccountName, free ours
LocalFree(psz);
psz = NULL;
}
}
}
LocalFree(pSidAdmin);
}
}
return g_pszAdminAccountName;
}
BOOL FreeAdminAccountName()
{
BOOL bRet = FALSE;
LPWSTR psz = (LPWSTR)InterlockedExchangePointer((void **)&g_pszAdminAccountName, NULL);
if (psz)
{
LocalFree(psz);
bRet = TRUE;
}
return bRet;
}
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 + 1];
TCHAR szDomain[DNLEN + 1];
TCHAR szPassword[PWLEN + 1];
if (pstrUsername)
{
StringCchCopy(szUsername, ARRAYSIZE(szUsername), pstrUsername);
}
else
{
szUsername[0] = TEXT('\0');
}
if (pstrDomain)
{
StringCchCopy(szDomain, ARRAYSIZE(szDomain), pstrDomain);
}
else
{
szDomain[0] = TEXT('\0');
}
if (pstrPassword)
{
StringCchCopy(szPassword, ARRAYSIZE(szPassword), pstrPassword);
}
else
{
szPassword[0] = TEXT('\0');
}
if (!objLogon.IsLogonServiceAvailable())
{
*pbRet = VARIANT_FALSE;
hr = S_OK;
}
else
{
if (objLogon.LogUserOn(szUsername, szDomain, szPassword))
{
*pbRet = VARIANT_TRUE;
hr = S_OK;
}
else
{
*pbRet = VARIANT_FALSE;
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;
}