windows-nt/Source/XPSP1/NT/shell/ext/msident/idenum.cpp
2020-09-26 16:20:57 +08:00

324 lines
6.1 KiB
C++

//
// 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;
}