#include "mslocusr.h" #include "msluglob.h" #include CLUEnum::CLUEnum(CLUDatabase *pDB) : m_cRef(1), m_hkeyDB(NULL), m_papszNames(NULL), m_cNames(0), m_cAlloc(0), m_iCurrent(0), m_pDB(pDB) { m_pDB->AddRef(); RefThisDLL(TRUE); } CLUEnum::~CLUEnum(void) { Cleanup(); if (m_pDB != NULL) m_pDB->Release(); RefThisDLL(FALSE); } #define cpPerAlloc 16 /* allocate 16 pointers at a go */ HRESULT CLUEnum::Init(void) { UINT err = (UINT)RegOpenKey(HKEY_LOCAL_MACHINE, ::szProfileList, &m_hkeyDB); if (err != ERROR_SUCCESS) return HRESULT_FROM_WIN32(err); m_papszNames = (LPSTR *)::MemAlloc(cpPerAlloc * sizeof(LPCSTR)); /* not "new", so we can realloc */ if (m_papszNames == NULL) return ResultFromScode(E_OUTOFMEMORY); m_cAlloc = cpPerAlloc; NLS_STR nlsTempName(cchMaxUsername+1); err = nlsTempName.QueryError(); if (err) return HRESULT_FROM_WIN32(err); for (DWORD iSubkey=0; err == ERROR_SUCCESS; iSubkey++) { DWORD cbBuffer = nlsTempName.QueryAllocSize(); err = (UINT)RegEnumKey(m_hkeyDB, iSubkey, nlsTempName.Party(), cbBuffer); nlsTempName.DonePartying(); if (err == ERROR_SUCCESS) { if (m_cNames == m_cAlloc) { LPSTR *pNew = (LPSTR *)::MemReAlloc(m_papszNames, (m_cAlloc + cpPerAlloc) * sizeof(LPCSTR)); if (pNew == NULL) { err = ERROR_NOT_ENOUGH_MEMORY; break; } m_cAlloc += cpPerAlloc; m_papszNames = pNew; } LPSTR pszNewName = new char[nlsTempName.strlen()+1]; if (pszNewName == NULL) { err = ERROR_NOT_ENOUGH_MEMORY; break; } ::strcpyf(pszNewName, nlsTempName.QueryPch()); m_papszNames[m_cNames++] = pszNewName; } } return NOERROR; } void CLUEnum::Cleanup(void) { if (m_hkeyDB != NULL) { RegCloseKey(m_hkeyDB); m_hkeyDB = NULL; } if (m_papszNames != NULL) { for (UINT i=0; iInit(m_papszNames[m_iCurrent]); } if (FAILED(hres)) { for (ULONG i=0; iRelease(); } celtFetched = 0; if (pUser != NULL) pUser->Release(); break; } m_iCurrent++; /* If this is a name without a real profile attached, don't return * it, just go on to the next one. Advancing m_iCurrent (the index * into the name array) above ensures that we won't infinite-loop. */ if (!pUser->Exists()) { pUser->Release(); continue; } rgelt[celtFetched++] = pUser; celt--; } if (pceltFetched != NULL) *pceltFetched = celtFetched; return hres; } STDMETHODIMP CLUEnum::Skip(ULONG celt) { SCODE sc; if (m_iCurrent + celt > m_cNames) { m_iCurrent = m_cNames; sc = S_FALSE; } else { m_iCurrent += celt; sc = S_OK; } return ResultFromScode(sc); } STDMETHODIMP CLUEnum::Reset(void) { Cleanup(); m_iCurrent = 0; return Init(); } STDMETHODIMP CLUEnum::Clone(IEnumUnknown __RPC_FAR *__RPC_FAR *ppenum) { CLUEnum *pNewEnum = new CLUEnum(m_pDB); if (pNewEnum == NULL) return ResultFromScode(E_OUTOFMEMORY); HRESULT hres = pNewEnum->Init(); if (FAILED(hres)) { pNewEnum->Release(); return hres; } if (m_iCurrent == m_cNames) { /* if at end, new one is at end */ pNewEnum->m_iCurrent = pNewEnum->m_cNames; } else { LPCSTR pszCurrentName = m_papszNames[m_iCurrent]; for (UINT i=0; im_cNames; i++) { if (!::strcmpf(pszCurrentName, pNewEnum->m_papszNames[i])) { pNewEnum->m_iCurrent = i; /* names match, start here */ break; } } if (i == pNewEnum->m_cNames) pNewEnum->m_iCurrent = 0; /* current name not found, start at beginning */ } return NOERROR; }