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.

464 lines
10 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996
  5. //
  6. // File: cenumns.cxx
  7. //
  8. // Contents: LDAP Enumerator Code
  9. //
  10. // History:
  11. //----------------------------------------------------------------------------
  12. #include "ldap.hxx"
  13. #pragma hdrstop
  14. DWORD
  15. GetDefaultServer(
  16. DWORD dwPort,
  17. BOOL fVerify,
  18. LPWSTR szDomainDnsName,
  19. LPWSTR szServerName,
  20. BOOL fWriteable
  21. );
  22. DWORD
  23. GetDefaultLdapServer(
  24. LPWSTR Addresses[],
  25. LPDWORD Count,
  26. BOOL Verify,
  27. DWORD dwPort
  28. ) ;
  29. //+---------------------------------------------------------------------------
  30. //
  31. // Function: CLDAPNamespaceEnum::Create
  32. //
  33. // Synopsis:
  34. //
  35. // Arguments: [pCollection]
  36. // [ppEnumVariant]
  37. //
  38. // Returns: HRESULT
  39. //
  40. // Modifies:
  41. //
  42. // History: 01-30-95 krishnag Created.
  43. //
  44. //----------------------------------------------------------------------------
  45. HRESULT
  46. CLDAPNamespaceEnum::Create(
  47. CLDAPNamespaceEnum FAR* FAR* ppenumvariant,
  48. VARIANT var,
  49. CCredentials& Credentials,
  50. LPTSTR pszNamespace
  51. )
  52. {
  53. HRESULT hr = S_OK;
  54. CLDAPNamespaceEnum FAR* penumvariant = NULL;
  55. penumvariant = new CLDAPNamespaceEnum();
  56. if (penumvariant == NULL){
  57. hr = E_OUTOFMEMORY;
  58. BAIL_ON_FAILURE(hr);
  59. }
  60. hr = ObjectTypeList::CreateObjectTypeList(
  61. var,
  62. &penumvariant->_pObjList
  63. );
  64. BAIL_ON_FAILURE(hr);
  65. penumvariant->_Credentials = Credentials;
  66. penumvariant->_pszNamespace = AllocADsStr(pszNamespace);
  67. if (!(penumvariant->_pszNamespace)) {
  68. hr = E_OUTOFMEMORY;
  69. BAIL_ON_FAILURE(hr);
  70. }
  71. if( IsGCNamespace(pszNamespace) )
  72. penumvariant->_dwPort = (DWORD) USE_DEFAULT_GC_PORT;
  73. else
  74. penumvariant->_dwPort = (DWORD) USE_DEFAULT_LDAP_PORT;
  75. *ppenumvariant = penumvariant;
  76. RRETURN(hr);
  77. error:
  78. if (penumvariant) {
  79. delete penumvariant;
  80. }
  81. RRETURN_EXP_IF_ERR(hr);
  82. }
  83. //+---------------------------------------------------------------------------
  84. //
  85. // Function: CLDAPNamespaceEnum::CLDAPNamespaceEnum
  86. //
  87. // Synopsis:
  88. //
  89. //
  90. // Arguments:
  91. //
  92. //
  93. // Returns:
  94. //
  95. // Modifies:
  96. //
  97. // History: 01-30-95 krishnag Created.
  98. //
  99. //----------------------------------------------------------------------------
  100. CLDAPNamespaceEnum::CLDAPNamespaceEnum()
  101. {
  102. _dwIndex = 0;
  103. _pObjList = NULL;
  104. }
  105. //+---------------------------------------------------------------------------
  106. //
  107. // Function: CLDAPNamespaceEnum::~CLDAPNamespaceEnum
  108. //
  109. // Synopsis:
  110. //
  111. //
  112. // Arguments:
  113. //
  114. // Returns:
  115. //
  116. // Modifies:
  117. //
  118. // History: 01-30-95 krishnag Created.
  119. //
  120. //----------------------------------------------------------------------------
  121. CLDAPNamespaceEnum::~CLDAPNamespaceEnum()
  122. {
  123. if (_pszNamespace)
  124. FreeADsMem(_pszNamespace);
  125. if ( _pObjList )
  126. delete _pObjList;
  127. }
  128. //+---------------------------------------------------------------------------
  129. //
  130. // Function: CLDAPNamespaceEnum::Next
  131. //
  132. // Synopsis: Returns cElements number of requested ADs objects in the
  133. // array supplied in pvar.
  134. //
  135. // Arguments: [cElements] -- The number of elements requested by client
  136. // [pvar] -- ptr to array of VARIANTs to for return objects
  137. // [pcElementFetched] -- if non-NULL, then number of elements
  138. // -- actually returned is placed here
  139. //
  140. // Returns: HRESULT -- S_OK if number of elements requested are returned
  141. // -- S_FALSE if number of elements is < requested
  142. //
  143. // Modifies:
  144. //
  145. // History:
  146. //
  147. //----------------------------------------------------------------------------
  148. STDMETHODIMP
  149. CLDAPNamespaceEnum::Next(
  150. ULONG cElements,
  151. VARIANT FAR* pvar,
  152. ULONG FAR* pcElementFetched
  153. )
  154. {
  155. ULONG cElementFetched = 0;
  156. HRESULT hr = S_OK;
  157. if ( _dwIndex > 0 ) // only your default ds will be returned, one element
  158. {
  159. if (pcElementFetched)
  160. *pcElementFetched = 0;
  161. RRETURN(S_FALSE);
  162. }
  163. hr = EnumObjects(
  164. cElements,
  165. pvar,
  166. &cElementFetched
  167. );
  168. if (pcElementFetched) {
  169. *pcElementFetched = cElementFetched;
  170. }
  171. RRETURN_EXP_IF_ERR(hr);
  172. }
  173. HRESULT
  174. CLDAPNamespaceEnum::EnumObjects(
  175. ULONG cElements,
  176. VARIANT FAR* pvar,
  177. ULONG FAR* pcElementFetched
  178. )
  179. {
  180. HRESULT hr = S_FALSE;
  181. IDispatch *pDispatch = NULL;
  182. DWORD i = 0;
  183. while (i < cElements) {
  184. if ( _dwIndex > 0 ) // only your default ds will be returned,
  185. // i.e. one element only
  186. {
  187. hr = S_FALSE;
  188. break;
  189. }
  190. _dwIndex++;
  191. hr = GetTreeObject(&pDispatch);
  192. if (hr == S_FALSE) {
  193. break;
  194. }
  195. VariantInit(&pvar[i]);
  196. pvar[i].vt = VT_DISPATCH;
  197. pvar[i].pdispVal = pDispatch;
  198. (*pcElementFetched)++;
  199. i++;
  200. }
  201. RRETURN_EXP_IF_ERR(hr);
  202. }
  203. HRESULT
  204. CLDAPNamespaceEnum::GetTreeObject(
  205. IDispatch ** ppDispatch
  206. )
  207. {
  208. DWORD err = NO_ERROR;
  209. HRESULT hr = S_OK;
  210. LPTSTR *aValuesNamingContext = NULL;
  211. LPTSTR *aValuesObjectClass = NULL;
  212. int nCountValues = 0;
  213. TCHAR *pszLDAPPathName = NULL;
  214. TCHAR szADsClassName[64];
  215. WCHAR szDomainName[MAX_PATH];
  216. WCHAR szServerName[MAX_PATH];
  217. TCHAR *pszNewADsPath = NULL;
  218. TCHAR *pszLast = NULL;
  219. LPWSTR pszNamingContext = NULL;
  220. LPWSTR pszNewADsParent = NULL;
  221. LPWSTR pszNewADsCommonName = NULL;
  222. DWORD fVerify = FALSE;
  223. *ppDispatch = NULL;
  224. ADS_LDP *ld = NULL;
  225. BOOL fGCDefaulted = FALSE;
  226. //
  227. // Now send back the current object
  228. //
  229. RetryGetDefaultServer:
  230. if ( err = GetDefaultServer(
  231. _dwPort,
  232. fVerify,
  233. szDomainName,
  234. szServerName,
  235. TRUE) ){
  236. hr = HRESULT_FROM_WIN32(err);
  237. BAIL_ON_FAILURE(hr);
  238. }
  239. //
  240. // Read the naming contexts
  241. //
  242. if (_dwPort == USE_DEFAULT_GC_PORT) {
  243. fGCDefaulted = TRUE;
  244. pszNamingContext = NULL;
  245. } else {
  246. pszNamingContext = TEXT(LDAP_OPATT_DEFAULT_NAMING_CONTEXT);
  247. }
  248. hr = LdapOpenObject2(
  249. szDomainName,
  250. szServerName,
  251. NULL,
  252. &ld,
  253. _Credentials,
  254. _dwPort
  255. );
  256. if (((hr == HRESULT_FROM_WIN32(ERROR_BAD_NETPATH)) ||
  257. (hr == HRESULT_FROM_WIN32(ERROR_DS_SERVER_DOWN)))
  258. && !fVerify) {
  259. fVerify = TRUE;
  260. goto RetryGetDefaultServer ;
  261. }
  262. BAIL_ON_FAILURE(hr);
  263. if (!fGCDefaulted) {
  264. hr = LdapReadAttributeFast(
  265. ld,
  266. NULL,
  267. pszNamingContext,
  268. &aValuesNamingContext,
  269. &nCountValues
  270. );
  271. BAIL_ON_FAILURE(hr);
  272. if ( nCountValues == 0 ) {
  273. //
  274. // The hr will be modified at the end of the function to S_FALSE
  275. // in case of error
  276. BAIL_ON_FAILURE(hr = E_FAIL);
  277. }
  278. hr = BuildADsPathFromLDAPPath2(
  279. FALSE, //Server is present till DSSnapin Works
  280. _pszNamespace,
  281. szDomainName,
  282. _dwPort,
  283. fGCDefaulted ?
  284. TEXT("") :
  285. aValuesNamingContext[0],
  286. &pszNewADsPath
  287. );
  288. } else {
  289. //
  290. // In this case we want to force it to be GC://yourDomain
  291. // so that all searches will be truly global
  292. //
  293. hr = BuildADsPathFromLDAPPath2(
  294. TRUE, // server is present
  295. _pszNamespace,
  296. szDomainName,
  297. _dwPort,
  298. TEXT(""),
  299. &pszNewADsPath
  300. );
  301. }
  302. BAIL_ON_FAILURE(hr);
  303. // this part is common to both code paths
  304. hr = BuildADsParentPath(
  305. pszNewADsPath,
  306. &pszNewADsParent,
  307. &pszNewADsCommonName
  308. );
  309. BAIL_ON_FAILURE(hr);
  310. nCountValues = 0;
  311. //
  312. // Read the object class of the path if necessary
  313. //
  314. if (!fGCDefaulted) {
  315. hr = LdapReadAttributeFast(
  316. ld,
  317. aValuesNamingContext[0],
  318. L"objectClass",
  319. &aValuesObjectClass,
  320. &nCountValues
  321. );
  322. BAIL_ON_FAILURE(hr);
  323. }
  324. if ( nCountValues == 0 && !fGCDefaulted)
  325. {
  326. // This object exists but does not contain objectClass attribute
  327. // which is required for all DS objects. Hence, ignore the object
  328. // and return error.
  329. hr = E_ADS_BAD_PATHNAME;
  330. BAIL_ON_FAILURE(hr);
  331. }
  332. //
  333. // Create the object
  334. //
  335. if (fGCDefaulted) {
  336. hr = CLDAPGenObject::CreateGenericObject(
  337. pszNewADsParent,
  338. pszNewADsCommonName,
  339. L"top",
  340. _Credentials,
  341. ADS_OBJECT_BOUND,
  342. IID_IUnknown,
  343. (void **) ppDispatch
  344. );
  345. } else {
  346. //
  347. // Send all the classes so we can load all extensions
  348. //
  349. hr = CLDAPGenObject::CreateGenericObject(
  350. pszNewADsParent,
  351. pszNewADsCommonName,
  352. aValuesObjectClass,
  353. nCountValues,
  354. _Credentials,
  355. ADS_OBJECT_BOUND,
  356. IID_IDispatch,
  357. (void **) ppDispatch
  358. );
  359. }
  360. BAIL_ON_FAILURE(hr);
  361. error:
  362. if ( aValuesNamingContext )
  363. LdapValueFree( aValuesNamingContext );
  364. if ( aValuesObjectClass )
  365. LdapValueFree( aValuesObjectClass );
  366. if ( pszNewADsPath )
  367. FreeADsStr( pszNewADsPath );
  368. if ( pszNewADsParent) {
  369. FreeADsStr(pszNewADsParent);
  370. }
  371. if (pszNewADsCommonName) {
  372. FreeADsStr(pszNewADsCommonName);
  373. }
  374. if ( ld ){
  375. LdapCloseObject( ld );
  376. }
  377. RRETURN_ENUM_STATUS(hr);
  378. }