//+--------------------------------------------------------------------------- // // 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 // for NetUserModalsGet #include // for NetApiBufferFree #include // for NERR_Success #include #include #include // 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: // // Returns: // // 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; }