Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

233 lines
4.7 KiB

  1. #include "mslocusr.h"
  2. #include "msluglob.h"
  3. #include <ole2.h>
  4. CLUEnum::CLUEnum(CLUDatabase *pDB)
  5. : m_cRef(1),
  6. m_hkeyDB(NULL),
  7. m_papszNames(NULL),
  8. m_cNames(0),
  9. m_cAlloc(0),
  10. m_iCurrent(0),
  11. m_pDB(pDB)
  12. {
  13. m_pDB->AddRef();
  14. RefThisDLL(TRUE);
  15. }
  16. CLUEnum::~CLUEnum(void)
  17. {
  18. Cleanup();
  19. if (m_pDB != NULL)
  20. m_pDB->Release();
  21. RefThisDLL(FALSE);
  22. }
  23. #define cpPerAlloc 16 /* allocate 16 pointers at a go */
  24. HRESULT CLUEnum::Init(void)
  25. {
  26. UINT err = (UINT)RegOpenKey(HKEY_LOCAL_MACHINE, ::szProfileList, &m_hkeyDB);
  27. if (err != ERROR_SUCCESS)
  28. return HRESULT_FROM_WIN32(err);
  29. m_papszNames = (LPSTR *)::MemAlloc(cpPerAlloc * sizeof(LPCSTR)); /* not "new", so we can realloc */
  30. if (m_papszNames == NULL)
  31. return ResultFromScode(E_OUTOFMEMORY);
  32. m_cAlloc = cpPerAlloc;
  33. NLS_STR nlsTempName(cchMaxUsername+1);
  34. err = nlsTempName.QueryError();
  35. if (err)
  36. return HRESULT_FROM_WIN32(err);
  37. for (DWORD iSubkey=0; err == ERROR_SUCCESS; iSubkey++) {
  38. DWORD cbBuffer = nlsTempName.QueryAllocSize();
  39. err = (UINT)RegEnumKey(m_hkeyDB, iSubkey, nlsTempName.Party(), cbBuffer);
  40. nlsTempName.DonePartying();
  41. if (err == ERROR_SUCCESS) {
  42. if (m_cNames == m_cAlloc) {
  43. LPSTR *pNew = (LPSTR *)::MemReAlloc(m_papszNames, (m_cAlloc + cpPerAlloc) * sizeof(LPCSTR));
  44. if (pNew == NULL) {
  45. err = ERROR_NOT_ENOUGH_MEMORY;
  46. break;
  47. }
  48. m_cAlloc += cpPerAlloc;
  49. m_papszNames = pNew;
  50. }
  51. LPSTR pszNewName = new char[nlsTempName.strlen()+1];
  52. if (pszNewName == NULL) {
  53. err = ERROR_NOT_ENOUGH_MEMORY;
  54. break;
  55. }
  56. ::strcpyf(pszNewName, nlsTempName.QueryPch());
  57. m_papszNames[m_cNames++] = pszNewName;
  58. }
  59. }
  60. return NOERROR;
  61. }
  62. void CLUEnum::Cleanup(void)
  63. {
  64. if (m_hkeyDB != NULL) {
  65. RegCloseKey(m_hkeyDB);
  66. m_hkeyDB = NULL;
  67. }
  68. if (m_papszNames != NULL) {
  69. for (UINT i=0; i<m_cNames; i++) {
  70. delete m_papszNames[i];
  71. }
  72. ::MemFree(m_papszNames);
  73. m_papszNames = NULL;
  74. m_cNames = 0;
  75. }
  76. }
  77. STDMETHODIMP CLUEnum::QueryInterface(REFIID riid, LPVOID * ppvObj)
  78. {
  79. if (!IsEqualIID(riid, IID_IUnknown) &&
  80. !IsEqualIID(riid, IID_IEnumUnknown)) {
  81. *ppvObj = NULL;
  82. return ResultFromScode(E_NOINTERFACE);
  83. }
  84. *ppvObj = this;
  85. AddRef();
  86. return NOERROR;
  87. }
  88. STDMETHODIMP_(ULONG) CLUEnum::AddRef(void)
  89. {
  90. return ++m_cRef;
  91. }
  92. STDMETHODIMP_(ULONG) CLUEnum::Release(void)
  93. {
  94. ULONG cRef;
  95. cRef = --m_cRef;
  96. if (0L == m_cRef) {
  97. delete this;
  98. }
  99. return cRef;
  100. }
  101. STDMETHODIMP CLUEnum::Next(ULONG celt, IUnknown __RPC_FAR *__RPC_FAR *rgelt,
  102. ULONG __RPC_FAR *pceltFetched)
  103. {
  104. ULONG celtFetched = 0;
  105. HRESULT hres = ResultFromScode(S_OK);
  106. while (celt) {
  107. if (m_iCurrent == m_cNames) {
  108. hres = ResultFromScode(S_FALSE);
  109. break;
  110. }
  111. CLUUser *pUser = new CLUUser(m_pDB);
  112. if (pUser == NULL) {
  113. hres = ResultFromScode(E_OUTOFMEMORY);
  114. }
  115. else {
  116. hres = pUser->Init(m_papszNames[m_iCurrent]);
  117. }
  118. if (FAILED(hres)) {
  119. for (ULONG i=0; i<celtFetched; i++) {
  120. rgelt[i]->Release();
  121. }
  122. celtFetched = 0;
  123. if (pUser != NULL)
  124. pUser->Release();
  125. break;
  126. }
  127. m_iCurrent++;
  128. /* If this is a name without a real profile attached, don't return
  129. * it, just go on to the next one. Advancing m_iCurrent (the index
  130. * into the name array) above ensures that we won't infinite-loop.
  131. */
  132. if (!pUser->Exists()) {
  133. pUser->Release();
  134. continue;
  135. }
  136. rgelt[celtFetched++] = pUser;
  137. celt--;
  138. }
  139. if (pceltFetched != NULL)
  140. *pceltFetched = celtFetched;
  141. return hres;
  142. }
  143. STDMETHODIMP CLUEnum::Skip(ULONG celt)
  144. {
  145. SCODE sc;
  146. if (m_iCurrent + celt > m_cNames) {
  147. m_iCurrent = m_cNames;
  148. sc = S_FALSE;
  149. }
  150. else {
  151. m_iCurrent += celt;
  152. sc = S_OK;
  153. }
  154. return ResultFromScode(sc);
  155. }
  156. STDMETHODIMP CLUEnum::Reset(void)
  157. {
  158. Cleanup();
  159. m_iCurrent = 0;
  160. return Init();
  161. }
  162. STDMETHODIMP CLUEnum::Clone(IEnumUnknown __RPC_FAR *__RPC_FAR *ppenum)
  163. {
  164. CLUEnum *pNewEnum = new CLUEnum(m_pDB);
  165. if (pNewEnum == NULL)
  166. return ResultFromScode(E_OUTOFMEMORY);
  167. HRESULT hres = pNewEnum->Init();
  168. if (FAILED(hres)) {
  169. pNewEnum->Release();
  170. return hres;
  171. }
  172. if (m_iCurrent == m_cNames) { /* if at end, new one is at end */
  173. pNewEnum->m_iCurrent = pNewEnum->m_cNames;
  174. }
  175. else {
  176. LPCSTR pszCurrentName = m_papszNames[m_iCurrent];
  177. for (UINT i=0; i<pNewEnum->m_cNames; i++) {
  178. if (!::strcmpf(pszCurrentName, pNewEnum->m_papszNames[i])) {
  179. pNewEnum->m_iCurrent = i; /* names match, start here */
  180. break;
  181. }
  182. }
  183. if (i == pNewEnum->m_cNames)
  184. pNewEnum->m_iCurrent = 0; /* current name not found, start at beginning */
  185. }
  186. return NOERROR;
  187. }