// // ident.cpp - implementation of CIdentity class // #include "private.h" #include "strconst.h" #include "multiusr.h" // // Constructor / destructor // CEnumUserIdentity::CEnumUserIdentity() { m_cRef = 1; m_dwCurrentUser = 0; m_cCountUsers = 0; m_rguidUsers = NULL; m_fInited = FALSE; DllAddRef(); } CEnumUserIdentity::~CEnumUserIdentity() { _Cleanup(); DllRelease(); } // // IUnknown members // STDMETHODIMP CEnumUserIdentity::QueryInterface( REFIID riid, void **ppv) { if (NULL == ppv) { return E_INVALIDARG; } *ppv=NULL; // Validate requested interface if(IID_IUnknown == riid) { *ppv = (IUnknown *)this; } else if(IID_IEnumUserIdentity == riid) { *ppv = (IEnumUserIdentity *)this; } // Addref through the interface if( NULL != *ppv ) { ((LPUNKNOWN)*ppv)->AddRef(); return S_OK; } return E_NOINTERFACE; } STDMETHODIMP_(ULONG) CEnumUserIdentity::AddRef() { return ++m_cRef; } STDMETHODIMP_(ULONG) CEnumUserIdentity::Release() { if( 0L != --m_cRef ) return m_cRef; delete this; return 0L; } // // IEnumUserIdentity members // STDMETHODIMP CEnumUserIdentity::Next(ULONG celt, IUnknown **rgelt, ULONG *pceltFetched) { ULONG celtFetched = 0; HRESULT hr = ResultFromScode(S_OK); CUserIdentity *pIdentity; if (!m_fInited) hr = _Init(); if (FAILED(hr)) return hr; while (celt) { if (m_dwCurrentUser == m_cCountUsers) { hr = ResultFromScode(S_FALSE); break; } pIdentity = new CUserIdentity; if (pIdentity) { if (SUCCEEDED(pIdentity->InitFromCookie(&m_rguidUsers[m_dwCurrentUser]))) { rgelt[celtFetched++] = pIdentity; m_dwCurrentUser++; } else { pIdentity->Release(); hr = ResultFromScode(E_OUTOFMEMORY); break; } } else { hr = ResultFromScode(E_OUTOFMEMORY); break; } celt--; } if (FAILED(hr)) { for (ULONG i = 0; i < celtFetched; i++) rgelt[i]->Release(); celtFetched = 0; } if (pceltFetched != NULL) *pceltFetched = celtFetched; return hr; } STDMETHODIMP CEnumUserIdentity::Skip(ULONG celt) { SCODE sc; HRESULT hr = S_OK; if (!m_fInited) hr = _Init(); if (FAILED(hr)) return hr; if (m_dwCurrentUser + celt > m_cCountUsers) { m_dwCurrentUser = m_cCountUsers; sc = S_FALSE; } else { m_dwCurrentUser += celt; sc = S_OK; } return ResultFromScode(sc); } STDMETHODIMP CEnumUserIdentity::Reset(void) { m_dwCurrentUser = 0; _Cleanup(); return S_OK; } STDMETHODIMP CEnumUserIdentity::Clone(IEnumUserIdentity **ppenum) { CEnumUserIdentity *pEnum; HRESULT hr = S_OK; if (!m_fInited) hr = _Init(); if (FAILED(hr)) return hr; pEnum = new CEnumUserIdentity; if (pEnum) { hr = pEnum->_Init(m_dwCurrentUser, m_cCountUsers, m_rguidUsers); if (SUCCEEDED(hr)) *ppenum = pEnum; } return hr; } STDMETHODIMP CEnumUserIdentity::GetCount(ULONG *pnCount) { HRESULT hr = S_OK; if (!m_fInited) hr = _Init(); if (FAILED(hr)) return hr; *pnCount = m_cCountUsers; return S_OK; } STDMETHODIMP CEnumUserIdentity::_Cleanup() { MemFree(m_rguidUsers); m_rguidUsers = NULL; m_cCountUsers = 0; m_fInited = FALSE; return S_OK; } STDMETHODIMP CEnumUserIdentity::_Init() { HRESULT hr=S_OK; HKEY hReg = NULL; DWORD cUsers = 0; DWORD cbMaxSubKeyLen; DWORD cb; DWORD dwEnumIndex = 0; BOOL fDisabled = MU_IdentitiesDisabled(); m_cCountUsers = 0; // Open or Create root server key if (RegCreateKeyEx(HKEY_CURRENT_USER, c_szRegRoot, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hReg, NULL) != ERROR_SUCCESS) { hr = E_FAIL; goto exit; } // Enumerate keys if (RegQueryInfoKey(hReg, NULL, NULL, 0, &cUsers, &cbMaxSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) { hr = E_FAIL; goto exit; } // No users ? if (cUsers == 0) goto done; if (fDisabled) cUsers = 1; // Allocate the users array MemAlloc((LPVOID *)&m_rguidUsers, sizeof(GUID) * cUsers); if (!m_rguidUsers) { cUsers = 0; goto done; } // Zero init ZeroMemory(m_rguidUsers, sizeof(GUID) * cUsers); if (fDisabled) { MU_GetDefaultUserID(&m_rguidUsers[0]); goto done; } while (TRUE) { HKEY hkUserKey; DWORD dwStatus, dwSize, dwType; TCHAR szKeyNameBuffer[MAX_PATH]; TCHAR szUid[255]; if (RegEnumKey(hReg, dwEnumIndex++, szKeyNameBuffer,MAX_PATH) != ERROR_SUCCESS) break; if (RegOpenKey(hReg, szKeyNameBuffer, &hkUserKey) == ERROR_SUCCESS) { dwSize = sizeof(szUid); dwStatus = RegQueryValueEx(hkUserKey, c_szUserID, NULL, &dwType, (LPBYTE)szUid, &dwSize); Assert(ERROR_SUCCESS == dwStatus); if (ERROR_SUCCESS == dwStatus) GUIDFromAString(szUid, &m_rguidUsers[dwEnumIndex - 1]); RegCloseKey(hkUserKey); } else AssertSz(FALSE, "Couldn't open user's key"); } done: m_cCountUsers = cUsers; m_fInited = TRUE; exit: if (hReg) RegCloseKey(hReg); return hr; } STDMETHODIMP CEnumUserIdentity::_Init(DWORD dwCurrentUser, DWORD dwCountUsers, GUID *prgUserCookies) { m_dwCurrentUser = dwCurrentUser; m_cCountUsers = dwCountUsers; // Allocate the users array MemAlloc((LPVOID *)&m_rguidUsers, sizeof(GUID) * dwCountUsers); if (!m_rguidUsers) return E_OUTOFMEMORY; CopyMemory(m_rguidUsers, prgUserCookies, sizeof(GUID) * dwCountUsers); m_fInited = TRUE; return S_OK; }