// // ident.cpp - implementation of CIdentity class // #include "private.h" #include "multiusr.h" #include "multiui.h" #include "strconst.h" #include "resource.h" #include "mluisup.h" extern HINSTANCE g_hInst; BOOL g_fReleasedMutex = true; // // Constructor / destructor // CUserIdentityManager::CUserIdentityManager() { m_cRef = 1; m_fWndRegistered = FALSE; m_hwnd = NULL; m_pAdviseRegistry = NULL; InitializeCriticalSection(&m_rCritSect); DllAddRef(); } CUserIdentityManager::~CUserIdentityManager() { if (m_pAdviseRegistry) m_pAdviseRegistry->Release(); DeleteCriticalSection(&m_rCritSect); DllRelease(); } // // IUnknown members // STDMETHODIMP CUserIdentityManager::QueryInterface( REFIID riid, void **ppv) { if (NULL == ppv) { return E_INVALIDARG; } *ppv=NULL; // Validate requested interface if (IID_IUnknown == riid) { *ppv = (IUserIdentityManager *)this; } else if (IID_IUserIdentityManager == riid) { *ppv = (IUserIdentityManager *)this; } else if (IID_IConnectionPoint == riid) { *ppv = (IConnectionPoint *)this; } else if (IID_IPrivateIdentityManager == riid) { *ppv = (IPrivateIdentityManager *)this; } else if (IID_IPrivateIdentityManager2 == riid) { *ppv = (IPrivateIdentityManager2 *)this; } // Addref through the interface if (NULL != *ppv) { ((LPUNKNOWN)*ppv)->AddRef(); return S_OK; } return E_NOINTERFACE; } STDMETHODIMP_(ULONG) CUserIdentityManager::AddRef() { return ++m_cRef; } STDMETHODIMP_(ULONG) CUserIdentityManager::Release() { if (0L != --m_cRef) return m_cRef; delete this; return 0L; } STDMETHODIMP CUserIdentityManager::CreateIdentity(WCHAR *pszName, IUserIdentity **ppIdentity) { return CreateIdentity2(pszName, NULL, ppIdentity); } STDMETHODIMP CUserIdentityManager::CreateIdentity2(WCHAR *pszName, WCHAR *pszPassword, IUserIdentity **ppIdentity) { CUserIdentity *pIdentity; HRESULT hr; TCHAR szName[CCH_IDENTITY_NAME_MAX_LENGTH+1]; *ppIdentity = NULL; if (MU_IdentitiesDisabled()) return E_IDENTITIES_DISABLED; if (WideCharToMultiByte(CP_ACP, 0, pszName, -1, szName, CCH_IDENTITY_NAME_MAX_LENGTH, NULL, NULL) == 0) return GetLastError(); if (MU_UsernameExists(szName)) return E_IDENTITY_EXISTS; pIdentity = new CUserIdentity; Assert(pIdentity); if (!pIdentity) return E_OUTOFMEMORY; hr = pIdentity->SetName(pszName); if (SUCCEEDED(hr)) { if (pszPassword) { hr = pIdentity->SetPassword(pszPassword); } } if (SUCCEEDED(hr)) { *ppIdentity = pIdentity; } else { pIdentity->Release(); } PostMessage(HWND_BROADCAST, WM_IDENTITY_INFO_CHANGED, 0, IIC_IDENTITY_ADDED); return hr; } STDMETHODIMP CUserIdentityManager::ConfirmPassword(GUID *uidCookie, WCHAR *pszPassword) { TCHAR szPwd[CCH_USERPASSWORD_MAX_LENGTH+1]; HRESULT hr = E_FAIL; USERINFO userInfo; if (WideCharToMultiByte(CP_ACP, 0, pszPassword, -1, szPwd, CCH_USERPASSWORD_MAX_LENGTH, NULL, NULL) == 0) return E_FAIL; if (MU_GetUserInfo(uidCookie, &userInfo)) { if (userInfo.fPasswordValid) { if (!userInfo.fUsePassword) userInfo.szPassword[0] = 0; if (lstrcmp(szPwd, userInfo.szPassword) == 0) hr = S_OK; else hr = E_FAIL; } else { hr = E_FAIL; } } return hr; } STDMETHODIMP CUserIdentityManager::DestroyIdentity(GUID *uidCookie) { if (MU_IdentitiesDisabled()) return E_IDENTITIES_DISABLED; return MU_DeleteUser(uidCookie); } STDMETHODIMP CUserIdentityManager::EnumIdentities(IEnumUserIdentity **ppEnumIdentity) { CEnumUserIdentity *pEnumIdentity; *ppEnumIdentity = NULL; pEnumIdentity = new CEnumUserIdentity; if (!pEnumIdentity) return E_OUTOFMEMORY; *ppEnumIdentity = pEnumIdentity; return S_OK; } STDMETHODIMP CUserIdentityManager::SetDefaultIdentity(GUID *puidCookie) { if (MU_IdentitiesDisabled()) return E_IDENTITIES_DISABLED; return MU_MakeDefaultUser(puidCookie); } STDMETHODIMP CUserIdentityManager::GetDefaultIdentity(GUID *puidCookie) { if (MU_IdentitiesDisabled()) return E_IDENTITIES_DISABLED; return MU_GetDefaultUserID(puidCookie) ? S_OK : S_FALSE; } STDMETHODIMP CUserIdentityManager::ManageIdentities(HWND hwndParent, DWORD dwFlags) { TCHAR szUsername[CCH_USERNAME_MAX_LENGTH+1]; if (MU_IdentitiesDisabled()) return E_IDENTITIES_DISABLED; *szUsername = 0; MU_ManageUsers(hwndParent, szUsername, dwFlags); // if the user created a new user and said they want to switch to them now, // we should do so. if (*szUsername) { BOOL fGotUser; USERINFO rUser; GUID uidUserID; HRESULT hr; fGotUser = MU_GetUserInfo(NULL, &rUser); if (!fGotUser) { *rUser.szUsername = 0; ZeroMemory(&rUser.uidUserID, sizeof(GUID)); } MU_UsernameToUserId(szUsername, &uidUserID); if (FAILED(hr = _SwitchToUser(&rUser.uidUserID, &uidUserID))) { SetForegroundWindow(hwndParent); if (hr != E_USER_CANCELLED) MU_ShowErrorMessage(hwndParent, idsSwitchCancelled, idsSwitchCancelCaption); } } return S_OK; } STDMETHODIMP CUserIdentityManager::_PersistChangingIdentities() { HRESULT hr = E_FAIL; HKEY hKeyIdentities = NULL; if (ERROR_SUCCESS != RegOpenKey(HKEY_CURRENT_USER, c_szRegRoot, &hKeyIdentities)) { goto exit; } if (ERROR_SUCCESS != RegSetValueEx(hKeyIdentities, c_szOutgoingID, 0, REG_BINARY, (LPBYTE)&g_uidOldUserId, sizeof(GUID))) { goto exit; } if (ERROR_SUCCESS != RegSetValueEx(hKeyIdentities, c_szIncomingID, 0, REG_BINARY, (LPBYTE)&g_uidNewUserId, sizeof(GUID))) { goto exit; } if (ERROR_SUCCESS != RegSetValueEx(hKeyIdentities, c_szChanging, 0, REG_BINARY, (LPBYTE)&g_fNotifyComplete, sizeof(g_fNotifyComplete))) { goto exit; } hr = S_OK; exit: if (hKeyIdentities) { RegCloseKey(hKeyIdentities); } return hr; } STDMETHODIMP CUserIdentityManager::_LoadChangingIdentities() { HRESULT hr = E_FAIL; HKEY hKeyIdentities = NULL; DWORD dwType, dwSize; if (ERROR_SUCCESS != RegOpenKey(HKEY_CURRENT_USER, c_szRegRoot, &hKeyIdentities)) { goto exit; } dwType = REG_BINARY; dwSize = sizeof(GUID); if (ERROR_SUCCESS != RegQueryValueEx(hKeyIdentities, c_szOutgoingID, 0, &dwType, (LPBYTE)&g_uidOldUserId, &dwSize)) { goto exit; } dwSize = sizeof(GUID); if (ERROR_SUCCESS != RegQueryValueEx(hKeyIdentities, c_szIncomingID, 0, &dwType, (LPBYTE)&g_uidNewUserId, &dwSize)) { goto exit; } dwSize = sizeof(g_fNotifyComplete); if (ERROR_SUCCESS != RegQueryValueEx(hKeyIdentities, c_szChanging, 0, &dwType, (LPBYTE)&g_fNotifyComplete, &dwSize)) { goto exit; } hr = S_OK; exit: if (FAILED(hr)) { g_uidOldUserId = GUID_NULL; g_uidNewUserId = GUID_NULL; g_fNotifyComplete = TRUE; } if (hKeyIdentities) { RegCloseKey(hKeyIdentities); } return hr; } STDMETHODIMP CUserIdentityManager::ClearChangingIdentities() { HRESULT hr = E_FAIL; HKEY hKeyIdentities = NULL; if (ERROR_SUCCESS != RegOpenKey(HKEY_CURRENT_USER, c_szRegRoot, &hKeyIdentities)) { goto exit; } RegDeleteValue(hKeyIdentities, c_szChanging); RegDeleteValue(hKeyIdentities, c_szIncomingID); RegDeleteValue(hKeyIdentities, c_szOutgoingID); hr = S_OK; exit: if (hKeyIdentities) { RegCloseKey(hKeyIdentities); } return hr; } STDMETHODIMP CUserIdentityManager::Logon(HWND hwndParent, DWORD dwFlags, IUserIdentity **ppIdentity) { CUserIdentity *pIdentity; HRESULT hr = E_FAIL; USERINFO rUser; GUID uidUserID, uidNewUserID; BOOL fGotUser; TCHAR szOldUsername[CCH_USERNAME_MAX_LENGTH+1], szLogoffName[CCH_USERNAME_MAX_LENGTH+1]; TCHAR szRes[MAX_PATH]; // if identities are disabled, always return the default identity. // if they are forcing the UI, return an error, otherwise succeed and // send the message back that identities are disabled. if (MU_IdentitiesDisabled()) { if (!!(dwFlags & UIL_FORCE_UI)) return E_IDENTITIES_DISABLED; hr = GetIdentityByCookie((GUID *)&UID_GIBC_DEFAULT_USER, ppIdentity); return (SUCCEEDED(hr) ? S_IDENTITIES_DISABLED : hr); } if (!g_hMutex) return E_UNEXPECTED; _LoadChangingIdentities(); if (g_uidOldUserId != GUID_NULL || g_uidNewUserId != GUID_NULL) { // we are in the middle of a switch if (!g_fNotifyComplete) { // and we are not done checking to see if a switch is ok. if (!!(dwFlags & UIL_FORCE_UI)) //if its a force ui, then just fail. return E_IDENTITY_CHANGING; //otherwise, we need to do something here, but since they could be //calling Login from the notifier proc, this could create a deadlock, //but returning either the old or the new could be wrong. Return the //same error here unless we can come up with a better solution. return E_IDENTITY_CHANGING; } } DWORD dwWaitResult; dwWaitResult = WaitForSingleObject(g_hMutex, 5000); g_fReleasedMutex = false; if (dwWaitResult == WAIT_TIMEOUT) { char szMsg[255], szTitle[63]; // someone else seems to have a login dialog up. Notify the user // about this problem and bail. if (!!(dwFlags & UIL_FORCE_UI)) { MLLoadStringA(idsSwitchInProgressSwitch, szMsg, ARRAYSIZE(szMsg)); MLLoadStringA(idsSwitchIdentities, szTitle, ARRAYSIZE(szTitle)); } else { MLLoadStringA(idsSwitchInProgressLaunch, szMsg, ARRAYSIZE(szMsg)); MLLoadStringA(idsIdentityLogin, szTitle, ARRAYSIZE(szTitle)); } MessageBox(hwndParent, szMsg, szTitle, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL); return E_UNEXPECTED; } *ppIdentity = NULL; fGotUser = MU_GetUserInfo(NULL, &rUser); if (!fGotUser) { *rUser.szUsername = 0; ZeroMemory(&rUser.uidUserID, sizeof(GUID)); } lstrcpy(szOldUsername, rUser.szUsername); // if we don't have to do the UI and there is a current // user, then just return that identity if (!(dwFlags & UIL_FORCE_UI) && fGotUser) { pIdentity = new CUserIdentity; if (!pIdentity) hr = E_OUTOFMEMORY; if (pIdentity && SUCCEEDED(hr = pIdentity->InitFromUsername(rUser.szUsername))) *ppIdentity = pIdentity; } else { if (0 == *rUser.szUsername) { GUID uidStart; MU_GetLoginOption(&uidStart); if (GUID_NULL != uidStart) { MU_GetUserInfo(&uidStart, &rUser); rUser.uidUserID = GUID_NULL; } } if (MU_Login(hwndParent, dwFlags, rUser.szUsername)) { MLLoadStringA(idsLogoff, szLogoffName, sizeof(szLogoffName)); if (lstrcmp(szLogoffName, rUser.szUsername) == 0) { MLLoadStringA(idsConfirmLogoff, szRes, sizeof(szRes)); if (MessageBox(hwndParent, szRes, szLogoffName, MB_YESNO) == IDYES) { ReleaseMutex(g_hMutex); g_fReleasedMutex = true; Logoff(hwndParent); } } else { pIdentity = new CUserIdentity; if (pIdentity) { hr = pIdentity->InitFromUsername(rUser.szUsername); if (SUCCEEDED(hr)) { pIdentity->GetCookie(&uidNewUserID); hr = _SwitchToUser(&rUser.uidUserID, &uidNewUserID); *ppIdentity = pIdentity; } if (FAILED(hr)) { UINT iMsgId = idsSwitchCancelled; pIdentity->Release(); *ppIdentity = NULL; SetForegroundWindow(hwndParent); // could switch on some error codes to set iMsgId to // other error messages. For now, skip showing the // message if a user did the cancelling if (hr != E_USER_CANCELLED) MU_ShowErrorMessage(hwndParent, iMsgId, idsSwitchCancelCaption); } } } } else hr = E_USER_CANCELLED; } if (!g_fReleasedMutex) ReleaseMutex(g_hMutex); return hr; } STDMETHODIMP CUserIdentityManager::Logoff(HWND hwndParent) { GUID uidToID = GUID_NULL; HRESULT hr; USERINFO rUser; BOOL fGotUser; if (!g_hMutex) return E_UNEXPECTED; DWORD dwWaitResult; dwWaitResult = WaitForSingleObject(g_hMutex, INFINITE); if (dwWaitResult != WAIT_OBJECT_0) return E_UNEXPECTED; fGotUser = MU_GetUserInfo(NULL, &rUser); if (!fGotUser) rUser.uidUserID = GUID_NULL; // switch to the null user hr = _SwitchToUser(&rUser.uidUserID, &uidToID); if (FAILED(hr)) { UINT iMsgId = idsLogoutCancelled; SetForegroundWindow(hwndParent); // could switch on some error codes to set iMsgId to // other error messages. For now, skip showing the // message if a user did the cancelling if (hr != E_USER_CANCELLED) MU_ShowErrorMessage(hwndParent, iMsgId, idsSwitchCancelCaption); } ReleaseMutex(g_hMutex); return hr; } STDMETHODIMP CUserIdentityManager::_SwitchToUser(GUID *puidFromUser, GUID *puidToUser) { TCHAR szUsername[CCH_USERNAME_MAX_LENGTH+1] = ""; HRESULT hr; // switching to the same user is automatically OK. if (*puidFromUser == *puidToUser) return S_OK; // Set up the from and to users g_uidOldUserId = *puidFromUser; g_uidNewUserId = *puidToUser; g_fNotifyComplete = FALSE; _PersistChangingIdentities(); if (*puidToUser != GUID_NULL) MU_UserIdToUsername(puidToUser, szUsername, CCH_USERNAME_MAX_LENGTH); // Notify window's that a switch is coming if (SUCCEEDED(hr = _QueryProcessesCanSwitch())) { if (SUCCEEDED(hr = MU_SwitchToUser(szUsername))) { if (!g_fReleasedMutex) { g_fReleasedMutex = true; g_fNotifyComplete = true; ReleaseMutex(g_hMutex); } _NotifyIdentitiesSwitched(); } } g_fNotifyComplete = TRUE; // clear these back out again g_uidOldUserId = GUID_NULL; g_uidNewUserId = GUID_NULL; ClearChangingIdentities(); return hr; } STDMETHODIMP CUserIdentityManager::GetIdentityByCookie(GUID *uidCookie, IUserIdentity **ppIdentity) { CUserIdentity *pIdentity; HRESULT hr = E_IDENTITY_NOT_FOUND; GUID uidUserCookie = *uidCookie; *ppIdentity = NULL; if (MU_IdentitiesDisabled()) { // if disabled, they can only get the default identity. // if asking for the current, they will get the defalt. // if asking for default by the constant or the default's guid, then succeed. // otherwise return an error. if (!MU_GetDefaultUserID(&uidUserCookie)) return E_IDENTITY_NOT_FOUND; if (UID_GIBC_CURRENT_USER == uidUserCookie) uidUserCookie = UID_GIBC_DEFAULT_USER; if (!(uidUserCookie == uidUserCookie || UID_GIBC_DEFAULT_USER == uidUserCookie)) return E_IDENTITIES_DISABLED; } if (uidUserCookie == UID_GIBC_DEFAULT_USER) { if (!MU_GetDefaultUserID(&uidUserCookie)) return E_IDENTITY_NOT_FOUND; } else if (uidUserCookie == UID_GIBC_CURRENT_USER) { if (!MU_GetCurrentUserID(&uidUserCookie)) return E_NO_CURRENT_IDENTITY; } else if (uidUserCookie == UID_GIBC_OUTGOING_USER) { _LoadChangingIdentities(); if (g_uidOldUserId == GUID_NULL) return E_IDENTITY_NOT_FOUND; else uidUserCookie = g_uidOldUserId; } else if (uidUserCookie == UID_GIBC_INCOMING_USER) { _LoadChangingIdentities(); if (g_uidNewUserId == GUID_NULL) return E_IDENTITY_NOT_FOUND; else uidUserCookie = g_uidNewUserId; } pIdentity = new CUserIdentity; if (pIdentity) { hr = pIdentity->InitFromCookie(&uidUserCookie); if (SUCCEEDED(hr)) *ppIdentity = pIdentity; else { // Cleanup delete pIdentity; } } return hr; } STDMETHODIMP CUserIdentityManager::GetConnectionInterface(IID *pIID) { return E_NOTIMPL; } STDMETHODIMP CUserIdentityManager::GetConnectionPointContainer(IConnectionPointContainer **ppCPC) { *ppCPC = NULL; return E_NOTIMPL; } STDMETHODIMP CUserIdentityManager::Advise(IUnknown *pUnkSink, DWORD *pdwCookie) { HRESULT hr; EnterCriticalSection(&m_rCritSect); AddRef(); if (!m_pAdviseRegistry) m_pAdviseRegistry = new CNotifierList; Assert(m_pAdviseRegistry); if (m_pAdviseRegistry) { if (!m_fWndRegistered) _CreateWindowClass(); hr = m_pAdviseRegistry->Add(pUnkSink, pdwCookie); } else hr = E_OUTOFMEMORY; LeaveCriticalSection(&m_rCritSect); return hr; } STDMETHODIMP CUserIdentityManager::Unadvise(DWORD dwCookie) { HRESULT hr; EnterCriticalSection(&m_rCritSect); if (m_pAdviseRegistry) { hr = m_pAdviseRegistry->RemoveCookie(dwCookie); } else hr = E_FAIL; LeaveCriticalSection(&m_rCritSect); Release(); return hr; } STDMETHODIMP CUserIdentityManager::EnumConnections(IEnumConnections **ppEnum) { *ppEnum = NULL; return E_NOTIMPL; } STDMETHODIMP CUserIdentityManager::QuerySwitchIdentities() { HRESULT hr = S_OK; DWORD dwLength, dwIndex; if (!m_pAdviseRegistry) return S_OK; TraceCall("Identity - CUserIdentityManager::QuerySwitchIdentities"); dwLength = m_pAdviseRegistry->GetLength(); for (dwIndex = 0; dwIndex < dwLength; dwIndex++) { IUnknown *punk; IIdentityChangeNotify *pICNotify; if (SUCCEEDED(m_pAdviseRegistry->GetAtIndex(dwIndex, &punk)) && punk) { if (SUCCEEDED(punk->QueryInterface(IID_IIdentityChangeNotify, (void **)&pICNotify)) && pICNotify) { if (FAILED(hr = pICNotify->QuerySwitchIdentities())) { punk->Release(); pICNotify->Release(); goto exit; } pICNotify->Release(); } punk->Release(); } } exit: return hr; } STDMETHODIMP CUserIdentityManager::NotifySwitchIdentities() { HRESULT hr = S_OK; DWORD dwLength, dwIndex; if (!m_pAdviseRegistry) return S_OK; TraceCall("Identity - CUserIdentityManager::NotifySwitchIdentities"); dwLength = m_pAdviseRegistry->GetLength(); for (dwIndex = 0; dwIndex < dwLength; dwIndex++) { IUnknown *punk; IIdentityChangeNotify *pICNotify; if (SUCCEEDED(m_pAdviseRegistry->GetAtIndex(dwIndex, &punk)) && punk) { if (SUCCEEDED(punk->QueryInterface(IID_IIdentityChangeNotify, (void **)&pICNotify)) && pICNotify) { if (FAILED(hr = pICNotify->SwitchIdentities())) { punk->Release(); pICNotify->Release(); goto exit; } pICNotify->Release(); } punk->Release(); } } exit: return hr; } STDMETHODIMP CUserIdentityManager::_QueryProcessesCanSwitch() { HWND hWnd, hNextWnd = NULL; LRESULT lResult; HWND *prghwnd = NULL; DWORD chwnd = 0, cAllocHwnd = 0, dw; HRESULT hr; TraceCall("Identity - CUserIdentityManager::_QueryProcessesCanSwitch"); cAllocHwnd = 10; if (!MemAlloc((LPVOID*)(&prghwnd), cAllocHwnd * sizeof(HWND))) return E_OUTOFMEMORY; hWnd = GetTopWindow(NULL); while (hWnd) { hNextWnd = GetNextWindow(hWnd, GW_HWNDNEXT); if (!IsWindowVisible(hWnd)) { TCHAR szWndClassName[255]; GetClassName(hWnd, szWndClassName, sizeof(szWndClassName)); if (lstrcmp(szWndClassName, c_szNotifyWindowClass) == 0) { if (chwnd == cAllocHwnd) { cAllocHwnd += 10; if (!MemRealloc((LPVOID*)(&prghwnd), cAllocHwnd * sizeof(HWND))) { hr = E_OUTOFMEMORY; goto exit; } } prghwnd[chwnd++] = hWnd; } } hWnd = hNextWnd; } hr = S_OK; for (dw = 0; dw < chwnd; dw++) { if (IsWindow(prghwnd[dw])) { lResult = SendMessage(prghwnd[dw], WM_QUERY_IDENTITY_CHANGE, 0, 0); if (FAILED((HRESULT)lResult)) { hr = (HRESULT)lResult; goto exit; } } } exit: MemFree(prghwnd); prghwnd = NULL; return hr; } STDMETHODIMP CUserIdentityManager::_NotifyIdentitiesSwitched() { HWND hWnd, hNextWnd = NULL; LRESULT lResult; HWND *prghwnd = NULL; DWORD chwnd = 0, cAllocHwnd = 0, dw; TraceCall("Identity - CUserIdentityManager::_NotifyIdentitiesSwitched"); cAllocHwnd = 10; if (!MemAlloc((LPVOID*)(&prghwnd), cAllocHwnd * sizeof(HWND))) return E_OUTOFMEMORY; hWnd = GetTopWindow(NULL); while (hWnd) { hNextWnd = GetNextWindow(hWnd, GW_HWNDNEXT); if (!IsWindowVisible(hWnd)) { TCHAR szWndClassName[255]; GetClassName(hWnd, szWndClassName, sizeof(szWndClassName)); if (lstrcmp(szWndClassName, c_szNotifyWindowClass) == 0) { if (chwnd == cAllocHwnd) { cAllocHwnd += 10; if (!MemRealloc((LPVOID*)(&prghwnd), cAllocHwnd * sizeof(HWND))) goto exit; } prghwnd[chwnd++] = hWnd; } } hWnd = hNextWnd; } for (dw = 0; dw < chwnd; dw++) { DWORD_PTR dwResult; if (IsWindow(prghwnd[dw])) // lResult = PostMessage(prghwnd[dw], WM_IDENTITY_CHANGED, 0, 0); //Raid 48054 SendMessageTimeout(prghwnd[dw], WM_IDENTITY_CHANGED, 0, 0, SMTO_ABORTIFHUNG | SMTO_NORMAL, 1500, &dwResult); } exit: MemFree(prghwnd); prghwnd = NULL; return S_OK; } STDMETHODIMP CUserIdentityManager::_CreateWindowClass() { WNDCLASS wc; if (!m_fWndRegistered) /*set up window class and register it */ { wc.lpszClassName = c_szNotifyWindowClass; wc.hInstance = g_hInst; wc.lpfnWndProc = CUserIdentityManager::WndProc; wc.hCursor = NULL; wc.hIcon = NULL; wc.lpszMenuName = NULL; wc.hbrBackground = NULL; wc.style = CS_DBLCLKS; wc.cbClsExtra = 0; wc.cbWndExtra = 0; if (!RegisterClassA(&wc)) return E_FAIL; m_fWndRegistered = TRUE; } return S_OK; } LRESULT CALLBACK CUserIdentityManager::WndProc(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam) { CNotifierList *pList = NULL; HRESULT hr; if (messg == WM_QUERY_IDENTITY_CHANGE || messg == WM_IDENTITY_CHANGED || messg == WM_IDENTITY_INFO_CHANGED) { #if defined(DEBUG) DebugStrf("Identity - CUserIdentityManager::WndProc() called for notification.\r\n"); #endif pList = (CNotifierList *)GetWindowLongPtr(hWnd, GWLP_USERDATA); if (pList) { hr = pList->SendNotification(messg, (DWORD)lParam); return hr; } } else { switch(messg) { case WM_CREATE: LPCREATESTRUCT pcs; pcs = (LPCREATESTRUCT)lParam; SetWindowLongPtr(hWnd, GWLP_USERDATA, (LRESULT)pcs->lpCreateParams); return(DefWindowProc(hWnd, messg, wParam, lParam)); break; /* case WM_QUERY_IDENTITY_CHANGE: case WM_IDENTITY_CHANGED: case WM_IDENTITY_INFO_CHANGED: DebugStrf("Identity - CUserIdentityManager::WndProc() called for notification.\r\n"); pList = (CNotifierList *)GetWindowLongPtr(hWnd, GWLP_USERDATA); if (pList) { hr = pList->SendNotification(messg, (DWORD)lParam); return hr; } break; */ case WM_CLOSE: SetWindowLongPtr(hWnd, GWLP_USERDATA, 0); return(DefWindowProc(hWnd, messg, wParam, lParam)); break; default: return(DefWindowProc(hWnd, messg, wParam, lParam)); } } return 0; } //---------------------------------------------------------------------------- // Logon the specified user. // - Checks password //---------------------------------------------------------------------------- STDMETHODIMP CUserIdentityManager::LogonAs(WCHAR *pszName, WCHAR *pszPassword, IUserIdentity **ppIdentity) { CUserIdentity *pIdentity; HRESULT hr = E_FAIL; USERINFO rUser; GUID uidNewUserID; BOOL fGotUser; TCHAR szName[CCH_USERNAME_MAX_LENGTH+1]; if (WideCharToMultiByte(CP_ACP, 0, pszName, -1, szName, CCH_USERNAME_MAX_LENGTH, NULL, NULL) == 0) { return E_FAIL; } // if identities are disabled, always return the default identity. if (MU_IdentitiesDisabled()) { hr = GetIdentityByCookie((GUID *)&UID_GIBC_DEFAULT_USER, ppIdentity); return (SUCCEEDED(hr) ? S_IDENTITIES_DISABLED : hr); } if (!g_hMutex) return E_UNEXPECTED; if (g_uidOldUserId != GUID_NULL || g_uidOldUserId != GUID_NULL) { // we are in the middle of a switch if (!g_fNotifyComplete) { return E_IDENTITY_CHANGING; } } *ppIdentity = NULL; // // Grab info on the current user // fGotUser = MU_GetUserInfo(NULL, &rUser); if (!fGotUser) { *rUser.szUsername = 0; ZeroMemory(&rUser.uidUserID, sizeof(GUID)); } if (0 == *rUser.szUsername) { GUID uidStart; MU_GetLoginOption(&uidStart); if (GUID_NULL != uidStart) { MU_GetUserInfo(&uidStart, &rUser); rUser.uidUserID = GUID_NULL; } } pIdentity = new CUserIdentity; if (pIdentity) { hr = pIdentity->InitFromUsername(szName); if (SUCCEEDED(hr)) { pIdentity->GetCookie(&uidNewUserID); hr= ConfirmPassword(&uidNewUserID, pszPassword); if (SUCCEEDED(hr)) { hr = _SwitchToUser(&rUser.uidUserID, &uidNewUserID); if (SUCCEEDED(hr)) { *ppIdentity = pIdentity; } else { UINT iMsgId = idsSwitchCancelled; pIdentity->Release(); *ppIdentity = NULL; // could switch on some error codes to set iMsgId to // other error messages. For now, skip showing the // message if a user did the cancelling if (hr != E_USER_CANCELLED) MU_ShowErrorMessage(NULL, iMsgId, idsSwitchCancelCaption); } } // ConfirmPassword() } // InitFromUsername() } if (!g_fReleasedMutex) ReleaseMutex(g_hMutex); return hr; }