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.

465 lines
12 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995
  5. //
  6. // File: cenumGroupCollection.cxx
  7. //
  8. // Contents: Windows NT 3.5 GroupCollection Enumeration Code
  9. //
  10. // History:
  11. //----------------------------------------------------------------------------
  12. #include "winnt.hxx"
  13. #pragma hdrstop
  14. #define BASE_BUFFER_SIZE (4096 * sizeof(WCHAR))
  15. CWinNTUserGroupsCollectionEnum::CWinNTUserGroupsCollectionEnum():
  16. _ParentType(0),
  17. _ParentADsPath(NULL),
  18. _DomainName(NULL),
  19. _ServerName(NULL),
  20. _UserName(NULL),
  21. _pGlobalBuffer(NULL),
  22. _pLocalBuffer(NULL),
  23. _dwCurrent(0),
  24. _dwTotal(0),
  25. _dwGlobalTotal(0),
  26. _dwLocalTotal(0),
  27. _fIsDomainController(FALSE)
  28. {
  29. VariantInit(&_vFilter);
  30. }
  31. CWinNTUserGroupsCollectionEnum::~CWinNTUserGroupsCollectionEnum()
  32. {
  33. if (_ParentADsPath)
  34. ADsFreeString(_ParentADsPath);
  35. if (_DomainName)
  36. ADsFreeString(_DomainName);
  37. if (_ServerName)
  38. ADsFreeString(_ServerName);
  39. if (_UserName)
  40. ADsFreeString(_UserName);
  41. if (_pGlobalBuffer)
  42. NetApiBufferFree(_pGlobalBuffer);
  43. if (_pLocalBuffer)
  44. NetApiBufferFree(_pLocalBuffer);
  45. VariantClear(&_vFilter);
  46. }
  47. //+---------------------------------------------------------------------------
  48. //
  49. // Function: CWinNTEnumVariant::Create
  50. //
  51. // Synopsis:
  52. //
  53. // Arguments: [pCollection]
  54. // [ppEnumVariant]
  55. //
  56. // Returns: HRESULT
  57. //
  58. // Modifies:
  59. //
  60. // History: 01-30-95 krishnag Created.
  61. //
  62. //----------------------------------------------------------------------------
  63. HRESULT
  64. CWinNTUserGroupsCollectionEnum::Create(
  65. CWinNTUserGroupsCollectionEnum FAR* FAR* ppenumvariant,
  66. ULONG ParentType,
  67. BSTR ParentADsPath,
  68. BSTR DomainName,
  69. BSTR ServerName,
  70. BSTR UserName,
  71. VARIANT vFilter,
  72. CWinNTCredentials& Credentials
  73. )
  74. {
  75. HRESULT hr = NOERROR;
  76. CWinNTUserGroupsCollectionEnum FAR* penumvariant = NULL;
  77. WCHAR szServer[MAX_PATH];
  78. DSROLE_PRIMARY_DOMAIN_INFO_BASIC* pdomainInfo = NULL;
  79. DWORD dwResult = ERROR_SUCCESS;
  80. //
  81. // Should the checks below be assertions?
  82. //
  83. if (!ppenumvariant)
  84. return E_FAIL;
  85. if (ParentType != WINNT_DOMAIN_ID &&
  86. ParentType != WINNT_COMPUTER_ID)
  87. return E_FAIL;
  88. *ppenumvariant = NULL;
  89. penumvariant = new CWinNTUserGroupsCollectionEnum();
  90. if (!penumvariant) {
  91. hr = E_OUTOFMEMORY;
  92. BAIL_ON_FAILURE(hr);
  93. }
  94. penumvariant->_ParentType = ParentType;
  95. hr = ADsAllocString(ParentADsPath , &penumvariant->_ParentADsPath);
  96. BAIL_ON_FAILURE(hr);
  97. hr = ADsAllocString(DomainName, &penumvariant->_DomainName);
  98. BAIL_ON_FAILURE(hr);
  99. hr = ADsAllocString(ServerName, &penumvariant->_ServerName);
  100. BAIL_ON_FAILURE(hr);
  101. hr = ADsAllocString(UserName, &penumvariant->_UserName);
  102. BAIL_ON_FAILURE(hr);
  103. //
  104. // We currently copy the filter but do nothing with it!!!
  105. //
  106. hr = VariantCopy(&penumvariant->_vFilter, &vFilter);
  107. BAIL_ON_FAILURE(hr);
  108. // check if the server is a DC
  109. hr = MakeUncName(ServerName, szServer);
  110. BAIL_ON_FAILURE(hr);
  111. dwResult = DsRoleGetPrimaryDomainInformation(
  112. szServer,
  113. DsRolePrimaryDomainInfoBasic, // InfoLevel
  114. (PBYTE*)&pdomainInfo // pBuffer
  115. );
  116. hr = HRESULT_FROM_WIN32(dwResult);
  117. BAIL_ON_FAILURE(hr);
  118. if( (pdomainInfo->MachineRole == DsRole_RoleBackupDomainController) ||
  119. (pdomainInfo->MachineRole == DsRole_RolePrimaryDomainController) ) {
  120. penumvariant->_fIsDomainController = TRUE;
  121. }
  122. else
  123. penumvariant->_fIsDomainController = FALSE;
  124. hr = penumvariant->DoEnumeration();
  125. BAIL_ON_FAILURE(hr);
  126. penumvariant->_Credentials = Credentials;
  127. hr = penumvariant->_Credentials.Ref(ServerName, DomainName, ParentType);
  128. BAIL_ON_FAILURE(hr);
  129. if ( pdomainInfo )
  130. {
  131. DsRoleFreeMemory(pdomainInfo);
  132. }
  133. *ppenumvariant = penumvariant;
  134. RRETURN(hr);
  135. error:
  136. delete penumvariant;
  137. if ( pdomainInfo )
  138. {
  139. DsRoleFreeMemory(pdomainInfo);
  140. }
  141. RRETURN_EXP_IF_ERR(hr);
  142. }
  143. HRESULT
  144. CWinNTUserGroupsCollectionEnum::DoEnumeration()
  145. {
  146. HRESULT hr;
  147. if (_ParentType == WINNT_DOMAIN_ID) {
  148. hr = DoGlobalEnumeration();
  149. BAIL_ON_FAILURE(hr);
  150. hr = DoLocalEnumeration();
  151. } else if (_ParentType == WINNT_COMPUTER_ID) {
  152. // We also want to try and get the global groups,
  153. // as this will be empty if the user does not belong to
  154. // any global groups.
  155. // We need to be careful on where we fail as we should
  156. // continue enumerating local groups for lots of cases.
  157. hr = DoGlobalEnumeration();
  158. if ((hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED))
  159. || (hr == HRESULT_FROM_WIN32(NERR_InvalidComputer))
  160. || (hr == HRESULT_FROM_WIN32(NERR_UserNotFound))
  161. || (hr == E_FAIL)) {
  162. hr = S_OK;
  163. _dwGlobalTotal = 0;
  164. }
  165. BAIL_ON_FAILURE(hr);
  166. hr = DoLocalEnumeration();
  167. } else {
  168. hr = E_FAIL;
  169. }
  170. error:
  171. _dwTotal = _dwGlobalTotal + _dwLocalTotal;
  172. RRETURN(hr);
  173. }
  174. HRESULT
  175. CWinNTUserGroupsCollectionEnum::DoGlobalEnumeration()
  176. {
  177. HRESULT hr;
  178. DWORD dwStatus;
  179. DWORD dwRead = 0;
  180. WCHAR szServer[MAX_PATH];
  181. LPGROUP_USERS_INFO_0 pGroupUserInfo = NULL;
  182. GROUP_INFO_2 *pGroupInfo2 = NULL;
  183. NET_API_STATUS nasStatus;
  184. hr = MakeUncName(_ServerName, szServer);
  185. BAIL_ON_FAILURE(hr);
  186. dwStatus = NetUserGetGroups(szServer,
  187. _UserName,
  188. 0,
  189. (LPBYTE*)&_pGlobalBuffer,
  190. MAX_PREFERRED_LENGTH,
  191. &dwRead,
  192. &_dwGlobalTotal);
  193. hr = HRESULT_FROM_WIN32(dwStatus);
  194. BAIL_ON_FAILURE(hr);
  195. if (dwRead != _dwGlobalTotal)
  196. hr = E_FAIL;
  197. if (dwRead == 1) {
  198. //
  199. // Check if it is the none group - dont want that
  200. //
  201. pGroupUserInfo = (LPGROUP_USERS_INFO_0)_pGlobalBuffer;
  202. if ( pGroupUserInfo->grui0_name && (FALSE == _fIsDomainController) &&
  203. (1 == _dwGlobalTotal) ) {
  204. // check if this the none group. Only non-DCs will return this group.
  205. nasStatus = NetGroupGetInfo(
  206. szServer,
  207. pGroupUserInfo->grui0_name,
  208. 2,
  209. (LPBYTE *) &pGroupInfo2
  210. );
  211. hr = HRESULT_FROM_WIN32(nasStatus);
  212. BAIL_ON_FAILURE(hr);
  213. if (pGroupInfo2->grpi2_group_id == DOMAIN_GROUP_RID_USERS) {
  214. //
  215. // Set the global total to zero - destructor will dealloc.
  216. //
  217. _dwGlobalTotal = 0;
  218. }
  219. }
  220. }
  221. error:
  222. if(pGroupInfo2)
  223. NetApiBufferFree(pGroupInfo2);
  224. RRETURN(hr);
  225. }
  226. HRESULT
  227. CWinNTUserGroupsCollectionEnum::DoLocalEnumeration()
  228. {
  229. HRESULT hr;
  230. DWORD dwStatus;
  231. DWORD dwRead = 0;
  232. WCHAR szServer[MAX_PATH];
  233. hr = MakeUncName(_ServerName, szServer);
  234. BAIL_ON_FAILURE(hr);
  235. dwStatus = NetUserGetLocalGroups(szServer,
  236. _UserName,
  237. 0,
  238. 0,
  239. (LPBYTE*)&_pLocalBuffer,
  240. MAX_PREFERRED_LENGTH,
  241. &dwRead,
  242. &_dwLocalTotal);
  243. hr = HRESULT_FROM_WIN32(dwStatus);
  244. BAIL_ON_FAILURE(hr);
  245. if (dwRead != _dwLocalTotal)
  246. hr = E_FAIL;
  247. error:
  248. RRETURN(hr);
  249. }
  250. //+---------------------------------------------------------------------------
  251. //
  252. // Function: CWinNTUserGroupsCollectionEnum::Next
  253. //
  254. // Synopsis: Returns cElements number of requested NetOle objects in the
  255. // array supplied in pvar.
  256. //
  257. // Arguments: [cElements] -- The number of elements requested by client
  258. // [pvar] -- ptr to array of VARIANTs to for return objects
  259. // [pcElementFetched] -- if non-NULL, then number of elements
  260. // -- actually returned is placed here
  261. //
  262. // Returns: HRESULT -- S_OK if number of elements requested are returned
  263. // -- S_FALSE if number of elements is < requested
  264. //
  265. // Modifies:
  266. //
  267. // History: 11-3-95 krishnag Created.
  268. //
  269. //----------------------------------------------------------------------------
  270. STDMETHODIMP
  271. CWinNTUserGroupsCollectionEnum::Next(
  272. ULONG cElements,
  273. VARIANT FAR* pvar,
  274. ULONG FAR* pcElementFetched
  275. )
  276. {
  277. ULONG cElementFetched = 0;
  278. HRESULT hr = S_OK;
  279. if (NULL == pvar)
  280. {
  281. //
  282. // Returning S_FALSE to indicate that we aren't returning
  283. // as many elements as requested.
  284. //
  285. hr = S_FALSE;
  286. }
  287. else
  288. {
  289. hr = EnumUserGroups(
  290. cElements,
  291. pvar,
  292. &cElementFetched
  293. );
  294. }
  295. if (pcElementFetched) {
  296. *pcElementFetched = cElementFetched;
  297. }
  298. RRETURN_EXP_IF_ERR(hr);
  299. }
  300. STDMETHODIMP
  301. CWinNTUserGroupsCollectionEnum::Skip(ULONG cElements)
  302. {
  303. //
  304. // Note: we better not wrap around when we add!
  305. //
  306. _dwCurrent += cElements;
  307. _dwCurrent = min(_dwTotal, _dwCurrent);
  308. if (_dwCurrent < _dwTotal)
  309. return S_OK;
  310. return S_FALSE;
  311. }
  312. STDMETHODIMP
  313. CWinNTUserGroupsCollectionEnum::Reset()
  314. {
  315. _dwCurrent = 0;
  316. return S_OK;
  317. }
  318. HRESULT
  319. CWinNTUserGroupsCollectionEnum::EnumUserGroups(
  320. ULONG cElements,
  321. VARIANT FAR* pvar,
  322. ULONG FAR* pcElementFetched
  323. )
  324. {
  325. HRESULT hr = S_FALSE;
  326. IDispatch *pDispatch = NULL;
  327. DWORD i = 0;
  328. while (i < cElements) {
  329. hr = GetNextUserGroup(&pDispatch);
  330. if (hr == S_FALSE) {
  331. break;
  332. }
  333. VariantInit(&pvar[i]);
  334. pvar[i].vt = VT_DISPATCH;
  335. pvar[i].pdispVal = pDispatch;
  336. (*pcElementFetched)++;
  337. i++;
  338. }
  339. RRETURN(hr);
  340. }
  341. HRESULT
  342. CWinNTUserGroupsCollectionEnum::GetNextUserGroup(
  343. IDispatch ** ppDispatch
  344. )
  345. {
  346. HRESULT hr;
  347. LPGROUP_USERS_INFO_0 lpInfo;
  348. LPWSTR GroupName;
  349. ULONG GroupType;
  350. if (_dwCurrent >= _dwTotal)
  351. return S_FALSE;
  352. if (_dwCurrent < _dwGlobalTotal) {
  353. lpInfo = (LPGROUP_USERS_INFO_0)_pGlobalBuffer + _dwCurrent;
  354. GroupType = WINNT_GROUP_GLOBAL;
  355. } else {
  356. lpInfo = (LPGROUP_USERS_INFO_0)_pLocalBuffer + _dwCurrent -
  357. _dwGlobalTotal;
  358. GroupType = WINNT_GROUP_LOCAL;
  359. }
  360. _dwCurrent++;
  361. GroupName = lpInfo->grui0_name;
  362. //
  363. // On an error, should we try to keep going?
  364. //
  365. if (GroupType == WINNT_GROUP_GLOBAL) {
  366. hr = CWinNTGroup::CreateGroup(_ParentADsPath,
  367. _ParentType,
  368. _DomainName,
  369. _ServerName,
  370. GroupName,
  371. GroupType,
  372. ADS_OBJECT_BOUND,
  373. IID_IDispatch,
  374. _Credentials,
  375. (void **)ppDispatch
  376. );
  377. }
  378. else {
  379. hr = CWinNTGroup::CreateGroup(_ParentADsPath,
  380. _ParentType,
  381. _DomainName,
  382. _ServerName,
  383. GroupName,
  384. GroupType,
  385. ADS_OBJECT_BOUND,
  386. IID_IDispatch,
  387. _Credentials,
  388. (void **)ppDispatch
  389. );
  390. }
  391. if (FAILED(hr))
  392. return S_FALSE;
  393. return S_OK;
  394. }