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.

460 lines
11 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. penumvariant->_Credentials = Credentials;
  55. *ppenumvariant = penumvariant;
  56. RRETURN(hr);
  57. error:
  58. if (penumvariant) {
  59. delete penumvariant;
  60. }
  61. RRETURN(hr);
  62. }
  63. //+---------------------------------------------------------------------------
  64. //
  65. // Function: CNDSNamespaceEnum::CNDSNamespaceEnum
  66. //
  67. // Synopsis:
  68. //
  69. //
  70. // Arguments:
  71. //
  72. //
  73. // Returns:
  74. //
  75. // Modifies:
  76. //
  77. // History: 01-30-95 krishnag Created.
  78. //
  79. //----------------------------------------------------------------------------
  80. CNDSNamespaceEnum::CNDSNamespaceEnum()
  81. {
  82. _dwEntriesRead = 0;
  83. _dwCurrentEntry = 0;
  84. _pBuffer = NULL;
  85. }
  86. //+---------------------------------------------------------------------------
  87. //
  88. // Function: CNDSNamespaceEnum::~CNDSNamespaceEnum
  89. //
  90. // Synopsis:
  91. //
  92. //
  93. // Arguments:
  94. //
  95. // Returns:
  96. //
  97. // Modifies:
  98. //
  99. // History: 01-30-95 krishnag Created.
  100. //
  101. //----------------------------------------------------------------------------
  102. CNDSNamespaceEnum::~CNDSNamespaceEnum()
  103. {
  104. if (_pBuffer)
  105. FreeADsMem(_pBuffer);
  106. }
  107. //+---------------------------------------------------------------------------
  108. //
  109. // Function: CNDSNamespaceEnum::Next
  110. //
  111. // Synopsis: Returns cElements number of requested ADs objects in the
  112. // array supplied in pvar.
  113. //
  114. // Arguments: [cElements] -- The number of elements requested by client
  115. // [pvar] -- ptr to array of VARIANTs to for return objects
  116. // [pcElementFetched] -- if non-NULL, then number of elements
  117. // -- actually returned is placed here
  118. //
  119. // Returns: HRESULT -- S_OK if number of elements requested are returned
  120. // -- S_FALSE if number of elements is < requested
  121. //
  122. // Modifies:
  123. //
  124. // History:
  125. //
  126. //----------------------------------------------------------------------------
  127. STDMETHODIMP
  128. CNDSNamespaceEnum::Next(
  129. ULONG cElements,
  130. VARIANT FAR* pvar,
  131. ULONG FAR* pcElementFetched
  132. )
  133. {
  134. ULONG cElementFetched = 0;
  135. HRESULT hr = S_OK;
  136. hr = FetchObjects(
  137. cElements,
  138. pvar,
  139. &cElementFetched
  140. );
  141. if (pcElementFetched) {
  142. *pcElementFetched = cElementFetched;
  143. }
  144. RRETURN(hr);
  145. }
  146. HRESULT
  147. CNDSNamespaceEnum::FetchObjects(
  148. ULONG cElements,
  149. VARIANT FAR* pvar,
  150. ULONG FAR* pcElementFetched
  151. )
  152. {
  153. HRESULT hr = S_OK;
  154. IDispatch *pDispatch = NULL;
  155. DWORD i = 0;
  156. while (i < cElements) {
  157. hr = FetchNextObject(&pDispatch);
  158. if (hr == S_FALSE) {
  159. break;
  160. }
  161. VariantInit(&pvar[i]);
  162. pvar[i].vt = VT_DISPATCH;
  163. pvar[i].pdispVal = pDispatch;
  164. (*pcElementFetched)++;
  165. i++;
  166. }
  167. return(hr);
  168. }
  169. //+---------------------------------------------------------------------------
  170. //
  171. // Function: CNDSNamespaceEnum::FetchNextObject
  172. //
  173. // Synopsis: Gets IDispatch pointer of next object in namespace.
  174. //
  175. // Arguments: [ppDispatch] -- Pointer to where to return IDispatch pointer.
  176. //
  177. // Returns: HRESULT -- S_OK if got the next object
  178. // -- S_FALSE if not
  179. //
  180. // Modifies: [*ppDispatch]
  181. //
  182. // History: 31-Jul-96 t-danal Use Multiple Network Provider for enum
  183. //
  184. //----------------------------------------------------------------------------
  185. HRESULT
  186. CNDSNamespaceEnum::FetchNextObject(
  187. IDispatch ** ppDispatch
  188. )
  189. {
  190. HRESULT hr;
  191. DWORD dwStatus;
  192. LPTSTR lpTreeName ;
  193. *ppDispatch = NULL;
  194. //
  195. // Ensure that the buffer is valid
  196. //
  197. hr = PrepBuffer();
  198. BAIL_ON_FAILURE(hr);
  199. //
  200. // Grab next (tree) name out of the buffer
  201. //
  202. lpTreeName = (LPWSTR)_pBuffer + (_dwCurrentEntry++ * OBJ_NAME_SIZE) ;
  203. //
  204. // Now create and send back the current object
  205. //
  206. hr = CNDSTree::CreateTreeObject(
  207. L"NDS:",
  208. lpTreeName,
  209. L"Top",
  210. _Credentials,
  211. ADS_OBJECT_BOUND,
  212. IID_IDispatch,
  213. (void **)ppDispatch
  214. );
  215. BAIL_ON_FAILURE(hr);
  216. error:
  217. RRETURN_ENUM_STATUS(hr);
  218. }
  219. //+---------------------------------------------------------------------------
  220. //
  221. // Function: CNDSNamespaceEnum::PrepBuffer
  222. //
  223. // Synopsis: Ensures that the enumeration buffer has something
  224. //
  225. // Arguments: none
  226. //
  227. // Returns: HRESULT -- S_OK if the buffer is ready to be used
  228. // -- an error if not
  229. //
  230. // Modifies: _pBuffer, _dwCurrentEntry, _dwEntriesRead
  231. //
  232. // History: 31-Jul-96 t-danal Created
  233. //
  234. //----------------------------------------------------------------------------
  235. HRESULT
  236. CNDSNamespaceEnum::PrepBuffer()
  237. {
  238. HRESULT hr = S_OK;
  239. DWORD cb = ENUM_BUFFER_SIZE;
  240. DWORD dwIter = 0, i;
  241. BOOL fFound ;
  242. LPWSTR lpString = NULL;
  243. WCHAR pszObjectName[OBJ_NAME_SIZE];
  244. NWDSCCODE ccode;
  245. nuint32 connRef = 0;
  246. nstr8 aObjectName[OBJ_NAME_SIZE];
  247. nuint32 objectID = 0xFFFFFFFF; /* -1 */
  248. nuint16 objectType;
  249. nuint8 objectHasProperties;
  250. nuint8 objectFlag;
  251. nuint8 objectSecurity;
  252. NWCCConnInfo connInfo;
  253. NWCONN_HANDLE connHandle;
  254. nstr8 searchObjectName[48] = "*";
  255. nuint16 searchObjectType = OT_TREE_NAME;
  256. //
  257. // Fill buffer as need. In theory we can get called to refill.
  258. // But since we need get everything to remove dups in
  259. // th case of TREEs, we dont allow this case. Ie. we get all
  260. // and there should be no more. So if _dwCurrentEntry is not
  261. // 0 and we need read more - then its time to bail.
  262. //
  263. if ( (_dwCurrentEntry < _dwEntriesRead) ) {
  264. //
  265. // Buffer still good
  266. //
  267. ADsAssert(_pBuffer) ;
  268. return(S_OK) ;
  269. }
  270. if (_dwCurrentEntry != 0) {
  271. return (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS));
  272. }
  273. //
  274. // Allocate buffer, if needed
  275. //
  276. if (!_pBuffer) {
  277. _pBuffer = AllocADsMem(cb);
  278. if (!_pBuffer) {
  279. hr = E_OUTOFMEMORY;
  280. RRETURN(hr);
  281. }
  282. lpString = (LPWSTR) _pBuffer ;
  283. _pBufferEnd = (LPBYTE)_pBuffer + cb ;
  284. }
  285. //
  286. // Get handle
  287. //
  288. ccode = NWCCGetPrimConnRef(
  289. &connRef
  290. );
  291. ccode = NWCCOpenConnByRef(
  292. connRef,
  293. NWCC_OPEN_UNLICENSED,
  294. NWCC_RESERVED,
  295. &connHandle
  296. );
  297. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  298. ccode = NWCCGetAllConnInfo(
  299. connHandle,
  300. NWCC_INFO_VERSION_1,
  301. &connInfo
  302. );
  303. CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
  304. _dwEntriesRead = 0 ;
  305. do {
  306. //
  307. // Scan bindery for NDS tree objects
  308. //
  309. ccode = NWScanObject(connHandle,
  310. searchObjectName,
  311. searchObjectType,
  312. &objectID,
  313. aObjectName,
  314. &objectType,
  315. &objectHasProperties,
  316. &objectFlag,
  317. &objectSecurity);
  318. if ( ccode ) {
  319. if (_dwEntriesRead > 0)
  320. hr = S_OK ;
  321. break ;
  322. }
  323. AnsiToUnicodeString(
  324. aObjectName,
  325. pszObjectName,
  326. NULL_TERMINATED
  327. );
  328. //
  329. // Remove any trailing '_' upto 32 chars. This is standard NDS tree
  330. // naming stuff.
  331. //
  332. dwIter = 31;
  333. while (pszObjectName[dwIter] == L'_' && dwIter > 0 ) {
  334. dwIter--;
  335. }
  336. pszObjectName[dwIter + 1] = L'\0';
  337. //
  338. // Scan for duplicates. We are doing linear everytime, but then again,
  339. // there shouldnt be many trees.
  340. //
  341. fFound = FALSE ;
  342. for (i = 0; i < _dwEntriesRead; i++) {
  343. if (_wcsicmp(
  344. pszObjectName,
  345. (LPWSTR)_pBuffer + (i * OBJ_NAME_SIZE)) == 0) {
  346. fFound = TRUE ;
  347. break ;
  348. }
  349. }
  350. //
  351. // Copy this unique tree name into the buffer
  352. //
  353. if (!fFound) {
  354. //
  355. // Check that we have enough space.
  356. //
  357. if ((lpString + OBJ_NAME_SIZE) >= _pBufferEnd) {
  358. cb = (LPBYTE)_pBufferEnd - (LPBYTE)_pBuffer ;
  359. _pBuffer = ReallocADsMem(
  360. _pBuffer,
  361. cb,
  362. 2 * cb
  363. );
  364. if (!_pBuffer) {
  365. hr = E_OUTOFMEMORY;
  366. BAIL_ON_FAILURE(hr);
  367. }
  368. lpString = (LPWSTR)_pBuffer + (_dwEntriesRead * OBJ_NAME_SIZE) ;
  369. _pBufferEnd = (LPBYTE) _pBuffer + (2 * cb) ;
  370. }
  371. //
  372. // Assume fixed size (max NW name). Yes, its more than
  373. // we really need but keeps things simpler.
  374. //
  375. wcscpy(lpString, pszObjectName);
  376. lpString += OBJ_NAME_SIZE ;
  377. _dwEntriesRead++ ;
  378. }
  379. } while (TRUE) ;
  380. error:
  381. if (connHandle) {
  382. NWCCCloseConn(
  383. connHandle
  384. );
  385. }
  386. RRETURN(hr);
  387. }