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.

511 lines
12 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. // CNDSNamespaceEnum::Create
  11. // CNDSNamespaceEnum::CNDSNamespaceEnum
  12. // CNDSNamespaceEnum::~CNDSNamespaceEnum
  13. // CNDSNamespaceEnum::Next
  14. // CNDSNamespaceEnum::FetchObjects
  15. // CNDSNamespaceEnum::FetchNextObject
  16. // CNDSNamespaceEnum::PrepBuffer
  17. //
  18. // History:
  19. //----------------------------------------------------------------------------
  20. #include "NDS.hxx"
  21. #pragma hdrstop
  22. #define ENUM_BUFFER_SIZE (1024 * 16)
  23. //+---------------------------------------------------------------------------
  24. //
  25. // Function: CNDSNamespaceEnum::Create
  26. //
  27. // Synopsis:
  28. //
  29. // Arguments: [pCollection]
  30. // [ppEnumVariant]
  31. //
  32. // Returns: HRESULT
  33. //
  34. // Modifies:
  35. //
  36. // History: 01-30-95 krishnag Created.
  37. //
  38. //----------------------------------------------------------------------------
  39. HRESULT
  40. CNDSNamespaceEnum::Create(
  41. CNDSNamespaceEnum FAR* FAR* ppenumvariant,
  42. VARIANT var,
  43. CCredentials& Credentials
  44. )
  45. {
  46. HRESULT hr = S_OK;
  47. CNDSNamespaceEnum FAR* penumvariant = NULL;
  48. DWORD dwStatus;
  49. penumvariant = new CNDSNamespaceEnum();
  50. if (penumvariant == NULL){
  51. hr = E_OUTOFMEMORY;
  52. BAIL_ON_FAILURE(hr);
  53. }
  54. #ifndef WIN95
  55. dwStatus = NPOpenEnum(RESOURCE_GLOBALNET,
  56. RESOURCETYPE_ANY,
  57. 0,
  58. NULL,
  59. &penumvariant->_hEnum);
  60. #else
  61. dwStatus = WNetOpenEnumA(RESOURCE_GLOBALNET,
  62. RESOURCETYPE_ANY,
  63. 0,
  64. NULL,
  65. &penumvariant->_hEnum);
  66. #endif
  67. if (dwStatus != NO_ERROR) {
  68. hr = HRESULT_FROM_WIN32(dwStatus);
  69. BAIL_ON_FAILURE(hr);
  70. }
  71. hr = ObjectTypeList::CreateObjectTypeList(
  72. var,
  73. &penumvariant->_pObjList
  74. );
  75. BAIL_ON_FAILURE(hr);
  76. penumvariant->_Credentials = Credentials;
  77. *ppenumvariant = penumvariant;
  78. RRETURN(hr);
  79. error:
  80. if (penumvariant) {
  81. delete penumvariant;
  82. }
  83. RRETURN_EXP_IF_ERR(hr);
  84. }
  85. //+---------------------------------------------------------------------------
  86. //
  87. // Function: CNDSNamespaceEnum::CNDSNamespaceEnum
  88. //
  89. // Synopsis:
  90. //
  91. //
  92. // Arguments:
  93. //
  94. //
  95. // Returns:
  96. //
  97. // Modifies:
  98. //
  99. // History: 01-30-95 krishnag Created.
  100. //
  101. //----------------------------------------------------------------------------
  102. CNDSNamespaceEnum::CNDSNamespaceEnum()
  103. {
  104. _pObjList = NULL;
  105. _dwEntriesRead = 0;
  106. _dwCurrentEntry = 0;
  107. _hEnum = NULL;
  108. _pBuffer = NULL;
  109. }
  110. //+---------------------------------------------------------------------------
  111. //
  112. // Function: CNDSNamespaceEnum::~CNDSNamespaceEnum
  113. //
  114. // Synopsis:
  115. //
  116. //
  117. // Arguments:
  118. //
  119. // Returns:
  120. //
  121. // Modifies:
  122. //
  123. // History: 01-30-95 krishnag Created.
  124. //
  125. //----------------------------------------------------------------------------
  126. CNDSNamespaceEnum::~CNDSNamespaceEnum()
  127. {
  128. if (_pBuffer)
  129. FreeADsMem(_pBuffer);
  130. if ( _pObjList )
  131. delete _pObjList;
  132. }
  133. //+---------------------------------------------------------------------------
  134. //
  135. // Function: CNDSNamespaceEnum::Next
  136. //
  137. // Synopsis: Returns cElements number of requested ADs objects in the
  138. // array supplied in pvar.
  139. //
  140. // Arguments: [cElements] -- The number of elements requested by client
  141. // [pvar] -- ptr to array of VARIANTs to for return objects
  142. // [pcElementFetched] -- if non-NULL, then number of elements
  143. // -- actually returned is placed here
  144. //
  145. // Returns: HRESULT -- S_OK if number of elements requested are returned
  146. // -- S_FALSE if number of elements is < requested
  147. //
  148. // Modifies:
  149. //
  150. // History:
  151. //
  152. //----------------------------------------------------------------------------
  153. STDMETHODIMP
  154. CNDSNamespaceEnum::Next(
  155. ULONG cElements,
  156. VARIANT FAR* pvar,
  157. ULONG FAR* pcElementFetched
  158. )
  159. {
  160. ULONG cElementFetched = 0;
  161. HRESULT hr = S_OK;
  162. hr = EnumObjects(
  163. cElements,
  164. pvar,
  165. &cElementFetched
  166. );
  167. if (pcElementFetched) {
  168. *pcElementFetched = cElementFetched;
  169. }
  170. RRETURN_EXP_IF_ERR(hr);
  171. }
  172. HRESULT
  173. CNDSNamespaceEnum::FetchObjects(
  174. ULONG cElements,
  175. VARIANT FAR* pvar,
  176. ULONG FAR* pcElementFetched
  177. )
  178. {
  179. HRESULT hr = S_OK;
  180. IDispatch *pDispatch = NULL;
  181. DWORD i = 0;
  182. while (i < cElements) {
  183. hr = FetchNextObject(&pDispatch);
  184. if (hr == S_FALSE) {
  185. break;
  186. }
  187. VariantInit(&pvar[i]);
  188. pvar[i].vt = VT_DISPATCH;
  189. pvar[i].pdispVal = pDispatch;
  190. (*pcElementFetched)++;
  191. i++;
  192. }
  193. return(hr);
  194. }
  195. //+---------------------------------------------------------------------------
  196. //
  197. // Function: CNDSNamespaceEnum::FetchNextObject
  198. //
  199. // Synopsis: Gets IDispatch pointer of next object in namespace.
  200. //
  201. // Arguments: [ppDispatch] -- Pointer to where to return IDispatch pointer.
  202. //
  203. // Returns: HRESULT -- S_OK if got the next object
  204. // -- S_FALSE if not
  205. //
  206. // Modifies: [*ppDispatch]
  207. //
  208. // History: 31-Jul-96 t-danal Use Multiple Network Provider for enum
  209. //
  210. //----------------------------------------------------------------------------
  211. HRESULT
  212. CNDSNamespaceEnum::FetchNextObject(
  213. IDispatch ** ppDispatch
  214. )
  215. {
  216. HRESULT hr;
  217. DWORD dwStatus;
  218. LPTSTR lpTreeName ;
  219. *ppDispatch = NULL;
  220. //
  221. // Ensure that the buffer is valid
  222. //
  223. hr = PrepBuffer();
  224. BAIL_ON_FAILURE(hr);
  225. //
  226. // Grab next (tree) name out of the buffer
  227. //
  228. lpTreeName = (LPWSTR)_pBuffer + (_dwCurrentEntry++ * OBJ_NAME_SIZE) ;
  229. //
  230. // Now create and send back the current object
  231. //
  232. hr = CNDSTree::CreateTreeObject(
  233. L"NDS:",
  234. lpTreeName,
  235. L"Top",
  236. _Credentials,
  237. ADS_OBJECT_BOUND,
  238. IID_IDispatch,
  239. (void **)ppDispatch
  240. );
  241. BAIL_ON_FAILURE(hr);
  242. error:
  243. RRETURN_ENUM_STATUS(hr);
  244. }
  245. //+---------------------------------------------------------------------------
  246. //
  247. // Function: CNDSNamespaceEnum::PrepBuffer
  248. //
  249. // Synopsis: Ensures that the enumeration buffer has something
  250. //
  251. // Arguments: none
  252. //
  253. // Returns: HRESULT -- S_OK if the buffer is ready to be used
  254. // -- an error if not
  255. //
  256. // Modifies: _pBuffer, _dwCurrentEntry, _dwEntriesRead
  257. //
  258. // History: 31-Jul-96 t-danal Created
  259. //
  260. //----------------------------------------------------------------------------
  261. HRESULT
  262. CNDSNamespaceEnum::PrepBuffer()
  263. {
  264. NWCONN_HANDLE hConn;
  265. NWOBJ_ID dwResumeObjectID = 0xFFFFFFFF;
  266. HRESULT hr = S_OK;
  267. DWORD cb = ENUM_BUFFER_SIZE;
  268. LPWSTR lpString = NULL, pszObjectName = NULL;
  269. DWORD dwIter = 0, i;
  270. BOOL fFound ;
  271. //
  272. // Fill buffer as need. In theory we can get called to refill.
  273. // But since we need get everything to remove dups in
  274. // th case of TREEs, we dont allow this case. Ie. we get all
  275. // and there should be no more. So if _dwCurrentEntry is not
  276. // 0 and we need read more - then its time to bail.
  277. //
  278. if ( (_dwCurrentEntry < _dwEntriesRead) ) {
  279. //
  280. // Buffer still good
  281. //
  282. ADsAssert(_pBuffer) ;
  283. return(S_OK) ;
  284. }
  285. if (_dwCurrentEntry != 0) {
  286. return (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS));
  287. }
  288. //
  289. // Allocate buffer, if needed
  290. //
  291. if (!_pBuffer) {
  292. _pBuffer = AllocADsMem(cb);
  293. if (!_pBuffer) {
  294. hr = E_OUTOFMEMORY;
  295. RRETURN(hr);
  296. }
  297. lpString = (LPWSTR) _pBuffer ;
  298. _pBufferEnd = (LPBYTE)_pBuffer + cb ;
  299. }
  300. //
  301. // Get handle
  302. //
  303. hr = NWApiGetAnyBinderyHandle(
  304. &hConn
  305. );
  306. if FAILED(hr) {
  307. return(hr) ;
  308. }
  309. _dwEntriesRead = 0 ;
  310. do {
  311. hr = NWApiObjectEnum(
  312. hConn,
  313. OT_DIRSERVER,
  314. &pszObjectName,
  315. &dwResumeObjectID
  316. );
  317. if (FAILED(hr)) {
  318. if (_dwEntriesRead > 0)
  319. hr = S_OK ;
  320. break ;
  321. }
  322. //
  323. // Remove any trailing '_' upto 32 chars. This is standard NDS tree
  324. // naming stuff.
  325. //
  326. dwIter = 31;
  327. while (pszObjectName[dwIter] == L'_' && dwIter > 0 ) {
  328. dwIter--;
  329. }
  330. pszObjectName[dwIter + 1] =L'\0';
  331. //
  332. // Scan for duplicates. We are doing linear everytime, but then again,
  333. // there shouldnt be many trees.
  334. //
  335. fFound = FALSE ;
  336. for (i = 0; i < _dwEntriesRead; i++) {
  337. if (_wcsicmp(
  338. pszObjectName,
  339. (LPWSTR)_pBuffer + (i * OBJ_NAME_SIZE)) == 0) {
  340. fFound = TRUE ;
  341. break ;
  342. }
  343. }
  344. //
  345. // Copy this unique tree name into the buffer
  346. //
  347. if (!fFound) {
  348. //
  349. // Check that we have enough space.
  350. //
  351. if ((lpString + OBJ_NAME_SIZE) >= _pBufferEnd) {
  352. cb = (DWORD) ((LPBYTE)_pBufferEnd - (LPBYTE)_pBuffer) ;
  353. _pBuffer = ReallocADsMem(
  354. _pBuffer,
  355. cb,
  356. 2 * cb
  357. );
  358. if (!_pBuffer) {
  359. hr = E_OUTOFMEMORY;
  360. BAIL_ON_FAILURE(hr);
  361. }
  362. lpString = (LPWSTR)_pBuffer + (_dwEntriesRead * OBJ_NAME_SIZE) ;
  363. _pBufferEnd = (LPBYTE) _pBuffer + (2 * cb) ;
  364. }
  365. //
  366. // Assume fixed size (max NW name). Yes, its more than
  367. // we really need but keeps things simpler.
  368. //
  369. wcscpy(lpString, pszObjectName);
  370. lpString += OBJ_NAME_SIZE ;
  371. _dwEntriesRead++ ;
  372. }
  373. FreeADsStr(pszObjectName) ;
  374. pszObjectName = NULL;
  375. } while (TRUE) ;
  376. error:
  377. if (pszObjectName) {
  378. FreeADsStr(pszObjectName);
  379. }
  380. (void) NWApiReleaseBinderyHandle(hConn);
  381. RRETURN(hr);
  382. }
  383. HRESULT
  384. CNDSNamespaceEnum::EnumObjects(
  385. DWORD ObjectType,
  386. ULONG cElements,
  387. VARIANT FAR * pvar,
  388. ULONG FAR * pcElementFetched
  389. )
  390. {
  391. switch (ObjectType) {
  392. case NDS_TREE_ID:
  393. RRETURN (FetchObjects(cElements, pvar, pcElementFetched));
  394. default:
  395. RRETURN(S_FALSE);
  396. }
  397. }
  398. HRESULT
  399. CNDSNamespaceEnum::EnumObjects(
  400. ULONG cElements,
  401. VARIANT FAR* pvar,
  402. ULONG FAR* pcElementFetched
  403. )
  404. {
  405. DWORD i;
  406. ULONG cRequested = 0;
  407. ULONG cFetchedByPath = 0;
  408. ULONG cTotalFetched = 0;
  409. VARIANT FAR* pPathvar = pvar;
  410. HRESULT hr = E_FAIL;
  411. DWORD ObjectType;
  412. for (i = 0; i < cElements; i++) {
  413. VariantInit(&pvar[i]);
  414. }
  415. cRequested = cElements;
  416. while (SUCCEEDED(_pObjList->GetCurrentObject(&ObjectType)) &&
  417. ((hr = EnumObjects(ObjectType,
  418. cRequested,
  419. pPathvar,
  420. &cFetchedByPath)) == S_FALSE )) {
  421. pPathvar += cFetchedByPath;
  422. cRequested -= cFetchedByPath;
  423. cTotalFetched += cFetchedByPath;
  424. cFetchedByPath = 0;
  425. if (FAILED(_pObjList->Next())){
  426. if (pcElementFetched)
  427. *pcElementFetched = cTotalFetched;
  428. RRETURN(S_FALSE);
  429. }
  430. }
  431. if (pcElementFetched) {
  432. *pcElementFetched = cTotalFetched + cFetchedByPath;
  433. }
  434. RRETURN(hr);
  435. }