Source code of Windows XP (NT5)
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.

395 lines
9.4 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995
  5. //
  6. // File: cenumvar.cxx
  7. //
  8. // Contents: Windows NT 3.5 Enumerator Code
  9. //
  10. // CWinNTNamespaceEnum::Create
  11. // CWinNTNamespaceEnum::CWinNTNamespaceEnum
  12. // CWinNTNamespaceEnum::~CWinNTNamespaceEnum
  13. // CWinNTNamespaceEnum::QueryInterface
  14. // CWinNTNamespaceEnum::AddRef
  15. // CWinNTNamespaceEnum::Release
  16. // CWinNTNamespaceEnum::Next
  17. // CWinNTNamespaceEnum::Skip
  18. // CWinNTNamespaceEnum::Clone
  19. //
  20. // History:
  21. //----------------------------------------------------------------------------
  22. #include "winnt.hxx"
  23. #pragma hdrstop
  24. //+---------------------------------------------------------------------------
  25. //
  26. // Function: CWinNTNamespaceEnum::Create
  27. //
  28. // Synopsis:
  29. //
  30. // Arguments: [pCollection]
  31. // [ppEnumVariant]
  32. //
  33. // Returns: HRESULT
  34. //
  35. // Modifies:
  36. //
  37. // History: 01-30-95 krishnag Created.
  38. //
  39. //----------------------------------------------------------------------------
  40. HRESULT
  41. CWinNTNamespaceEnum::Create(
  42. CWinNTNamespaceEnum FAR* FAR* ppenumvariant,
  43. VARIANT var,
  44. CWinNTCredentials& Credentials
  45. )
  46. {
  47. HRESULT hr = S_OK;
  48. CWinNTNamespaceEnum FAR* penumvariant = NULL;
  49. penumvariant = new CWinNTNamespaceEnum();
  50. if (penumvariant == NULL){
  51. hr = E_OUTOFMEMORY;
  52. BAIL_ON_FAILURE(hr);
  53. }
  54. hr = ObjectTypeList::CreateObjectTypeList(
  55. var,
  56. &penumvariant->_pObjList
  57. );
  58. BAIL_ON_FAILURE(hr);
  59. penumvariant->_Credentials = Credentials;
  60. *ppenumvariant = penumvariant;
  61. RRETURN(hr);
  62. error:
  63. if (penumvariant) {
  64. delete penumvariant;
  65. }
  66. RRETURN_EXP_IF_ERR(hr);
  67. }
  68. //+---------------------------------------------------------------------------
  69. //
  70. // Function: CWinNTNamespaceEnum::CWinNTNamespaceEnum
  71. //
  72. // Synopsis:
  73. //
  74. //
  75. // Arguments:
  76. //
  77. //
  78. // Returns:
  79. //
  80. // Modifies:
  81. //
  82. // History: 01-30-95 krishnag Created.
  83. //
  84. //----------------------------------------------------------------------------
  85. CWinNTNamespaceEnum::CWinNTNamespaceEnum()
  86. {
  87. _pObjList = NULL;
  88. _pBuffer = 0;
  89. _dwObjectReturned = 0;
  90. _dwObjectCurrentEntry = 0;
  91. _dwObjectTotal = 0;
  92. _dwResumeHandle = 0;
  93. _bNoMore = FALSE;
  94. }
  95. //+---------------------------------------------------------------------------
  96. //
  97. // Function: CWinNTNamespaceEnum::~CWinNTNamespaceEnum
  98. //
  99. // Synopsis:
  100. //
  101. //
  102. // Arguments:
  103. //
  104. // Returns:
  105. //
  106. // Modifies:
  107. //
  108. // History: 01-30-95 krishnag Created.
  109. //
  110. //----------------------------------------------------------------------------
  111. CWinNTNamespaceEnum::~CWinNTNamespaceEnum()
  112. {
  113. if (_pBuffer) {
  114. NetApiBufferFree(_pBuffer);
  115. }
  116. if ( _pObjList )
  117. delete _pObjList;
  118. }
  119. HRESULT
  120. CWinNTNamespaceEnum::EnumObjects(
  121. DWORD ObjectType,
  122. ULONG cElements,
  123. VARIANT FAR * pvar,
  124. ULONG FAR * pcElementFetched
  125. )
  126. {
  127. HRESULT hr = S_OK;
  128. switch (ObjectType) {
  129. case WINNT_DOMAIN_ID:
  130. hr = EnumDomains(cElements, pvar, pcElementFetched);
  131. RRETURN(hr);
  132. default:
  133. RRETURN(S_FALSE);
  134. }
  135. }
  136. HRESULT
  137. CWinNTNamespaceEnum::EnumObjects(
  138. ULONG cElements,
  139. VARIANT FAR* pvar,
  140. ULONG FAR* pcElementFetched
  141. )
  142. {
  143. DWORD i;
  144. ULONG cRequested = 0;
  145. ULONG cFetchedByPath = 0;
  146. ULONG cTotalFetched = 0;
  147. VARIANT FAR* pPathvar = pvar;
  148. HRESULT hr = S_FALSE;
  149. DWORD ObjectType;
  150. for (i = 0; i < cElements; i++) {
  151. VariantInit(&pvar[i]);
  152. }
  153. cRequested = cElements;
  154. while (SUCCEEDED(_pObjList->GetCurrentObject(&ObjectType)) &&
  155. ((hr = EnumObjects(ObjectType,
  156. cRequested,
  157. pPathvar,
  158. &cFetchedByPath)) == S_FALSE )) {
  159. pPathvar += cFetchedByPath;
  160. cRequested -= cFetchedByPath;
  161. cTotalFetched += cFetchedByPath;
  162. cFetchedByPath = 0;
  163. if (FAILED(_pObjList->Next())){
  164. if (pcElementFetched)
  165. *pcElementFetched = cTotalFetched;
  166. RRETURN(S_FALSE);
  167. }
  168. }
  169. if (pcElementFetched) {
  170. *pcElementFetched = cTotalFetched + cFetchedByPath;
  171. }
  172. RRETURN_EXP_IF_ERR(hr);
  173. }
  174. //+---------------------------------------------------------------------------
  175. //
  176. // Function: CWinNTNamespaceEnum::Next
  177. //
  178. // Synopsis: Returns cElements number of requested NetOle objects in the
  179. // array supplied in pvar.
  180. //
  181. // Arguments: [cElements] -- The number of elements requested by client
  182. // [pvar] -- ptr to array of VARIANTs to for return objects
  183. // [pcElementFetched] -- if non-NULL, then number of elements
  184. // -- actually returned is placed here
  185. //
  186. // Returns: HRESULT -- S_OK if number of elements requested are returned
  187. // -- S_FALSE if number of elements is < requested
  188. //
  189. // Modifies:
  190. //
  191. // History: 11-3-95 krishnag Created.
  192. //
  193. //----------------------------------------------------------------------------
  194. STDMETHODIMP
  195. CWinNTNamespaceEnum::Next(
  196. ULONG cElements,
  197. VARIANT FAR* pvar,
  198. ULONG FAR* pcElementFetched
  199. )
  200. {
  201. ULONG cElementFetched = 0;
  202. HRESULT hr = S_OK;
  203. hr = EnumObjects(
  204. cElements,
  205. pvar,
  206. &cElementFetched
  207. );
  208. if (pcElementFetched) {
  209. *pcElementFetched = cElementFetched;
  210. }
  211. RRETURN_EXP_IF_ERR(hr);
  212. }
  213. HRESULT
  214. CWinNTNamespaceEnum::EnumDomains(
  215. ULONG cElements,
  216. VARIANT FAR* pvar,
  217. ULONG FAR* pcElementFetched
  218. )
  219. {
  220. HRESULT hr = S_FALSE;
  221. IDispatch *pDispatch = NULL;
  222. DWORD i = 0;
  223. BOOL fRepeat = FALSE;
  224. DWORD dwFailureCount = 0;
  225. DWORD dwPermitFailure = 1000;
  226. while (i < cElements) {
  227. hr = GetDomainObject(&pDispatch);
  228. if (hr == S_FALSE) {
  229. break;
  230. }
  231. else if (FAILED(hr)) {
  232. //
  233. // Got an error while retrieving the object, ignore the
  234. // error and continue with the next object.
  235. // If continuously getting error more than dwPermitFailure,
  236. // make the return value S_FALSE, leave the loop.
  237. //
  238. if (fRepeat) {
  239. dwFailureCount++;
  240. if(dwFailureCount > dwPermitFailure) {
  241. hr = S_FALSE;
  242. break;
  243. }
  244. }
  245. else {
  246. fRepeat = TRUE;
  247. dwFailureCount = 1;
  248. }
  249. // we need to move the _dwObjectCurrentEntry
  250. _dwObjectCurrentEntry++;
  251. hr = S_OK;
  252. continue;
  253. }
  254. if (fRepeat) {
  255. fRepeat = FALSE;
  256. }
  257. VariantInit(&pvar[i]);
  258. pvar[i].vt = VT_DISPATCH;
  259. pvar[i].pdispVal = pDispatch;
  260. (*pcElementFetched)++;
  261. i++;
  262. }
  263. RRETURN_EXP_IF_ERR(hr);
  264. }
  265. HRESULT
  266. CWinNTNamespaceEnum::GetDomainObject(
  267. IDispatch ** ppDispatch
  268. )
  269. {
  270. HRESULT hr = S_OK;
  271. PSERVER_INFO_100 pServerInfo100 = NULL;
  272. NET_API_STATUS nasStatus = 0;
  273. if (!_pBuffer || (_dwObjectCurrentEntry == _dwObjectReturned)) {
  274. if (_pBuffer) {
  275. NetApiBufferFree(_pBuffer);
  276. _pBuffer = NULL;
  277. }
  278. _dwObjectCurrentEntry = 0;
  279. _dwObjectReturned = 0;
  280. if (_bNoMore) {
  281. RRETURN(S_FALSE);
  282. }
  283. nasStatus = NetServerEnum(
  284. NULL,
  285. 100,
  286. (LPBYTE *)&_pBuffer,
  287. MAX_PREFERRED_LENGTH,
  288. &_dwObjectReturned,
  289. &_dwObjectTotal,
  290. SV_TYPE_DOMAIN_ENUM,
  291. NULL,
  292. &_dwResumeHandle
  293. );
  294. //
  295. // The following if clause is to handle real errors; anything
  296. // other than ERROR_SUCCESS and ERROR_MORE_DATA
  297. //
  298. if ((nasStatus != ERROR_SUCCESS) && (nasStatus != ERROR_MORE_DATA)) {
  299. hr =S_FALSE;
  300. goto cleanup;
  301. }
  302. if (nasStatus == ERROR_SUCCESS) {
  303. _bNoMore = TRUE;
  304. }
  305. }
  306. //
  307. // Now send back the current object
  308. //
  309. //
  310. // There is a scenario where NetServerEnum returns ERROR_SUCCESS
  311. // when there is no data to send back. However the field
  312. // _dwObjectsReturned will also be 0. We need to check that and
  313. // bail out if necessary
  314. //
  315. if ((nasStatus == ERROR_SUCCESS) && _dwObjectReturned == 0){
  316. RRETURN(S_FALSE);
  317. }
  318. pServerInfo100 = (LPSERVER_INFO_100)_pBuffer;
  319. pServerInfo100 += _dwObjectCurrentEntry;
  320. //
  321. // We couldn't have any credentials coming in from a Namespace
  322. // enumeration, since you can't have credentials coming in from
  323. // a Namespace. So we use null credentials.
  324. //
  325. hr = CWinNTDomain::CreateDomain(
  326. L"WinNT:",
  327. pServerInfo100->sv100_name,
  328. ADS_OBJECT_BOUND,
  329. IID_IDispatch,
  330. _Credentials,
  331. (void **) ppDispatch
  332. );
  333. BAIL_IF_ERROR(hr);
  334. _dwObjectCurrentEntry++;
  335. RRETURN(S_OK);
  336. cleanup:
  337. *ppDispatch = NULL;
  338. return hr;
  339. }