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.

441 lines
11 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. LPSERVER_INFO_101 lpServerInfo =NULL;
  78. NET_API_STATUS nasStatus;
  79. WCHAR szServer[MAX_PATH];
  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. MakeUncName(ServerName, szServer);
  110. nasStatus = NetServerGetInfo(
  111. szServer,
  112. 101,
  113. (LPBYTE *)&lpServerInfo
  114. );
  115. hr = HRESULT_FROM_WIN32(nasStatus);
  116. BAIL_ON_FAILURE(hr);
  117. if( (lpServerInfo->sv101_type & SV_TYPE_DOMAIN_CTRL) ||
  118. (lpServerInfo->sv101_type & SV_TYPE_DOMAIN_BAKCTRL) ) {
  119. penumvariant->_fIsDomainController = TRUE;
  120. }
  121. else
  122. penumvariant->_fIsDomainController = FALSE;
  123. hr = penumvariant->DoEnumeration();
  124. BAIL_ON_FAILURE(hr);
  125. penumvariant->_Credentials = Credentials;
  126. hr = penumvariant->_Credentials.Ref(ServerName, DomainName, ParentType);
  127. BAIL_ON_FAILURE(hr);
  128. *ppenumvariant = penumvariant;
  129. RRETURN(hr);
  130. error:
  131. delete penumvariant;
  132. if(lpServerInfo)
  133. NetApiBufferFree(lpServerInfo);
  134. RRETURN_EXP_IF_ERR(hr);
  135. }
  136. HRESULT
  137. CWinNTUserGroupsCollectionEnum::DoEnumeration()
  138. {
  139. HRESULT hr;
  140. if (_ParentType == WINNT_DOMAIN_ID) {
  141. hr = DoGlobalEnumeration();
  142. BAIL_ON_FAILURE(hr);
  143. hr = DoLocalEnumeration();
  144. } else if (_ParentType == WINNT_COMPUTER_ID) {
  145. // We also want to try and get the global groups,
  146. // as this will be empty if the user does not belong to
  147. // any global groups.
  148. // We need to be careful on where we fail as we should
  149. // continue enumerating local groups for lots of cases.
  150. hr = DoGlobalEnumeration();
  151. if ((hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED))
  152. || (hr == HRESULT_FROM_WIN32(NERR_InvalidComputer))
  153. || (hr == HRESULT_FROM_WIN32(NERR_UserNotFound))
  154. || (hr == E_FAIL)) {
  155. hr = S_OK;
  156. _dwGlobalTotal = 0;
  157. }
  158. BAIL_ON_FAILURE(hr);
  159. hr = DoLocalEnumeration();
  160. } else {
  161. hr = E_FAIL;
  162. }
  163. error:
  164. _dwTotal = _dwGlobalTotal + _dwLocalTotal;
  165. RRETURN(hr);
  166. }
  167. HRESULT
  168. CWinNTUserGroupsCollectionEnum::DoGlobalEnumeration()
  169. {
  170. HRESULT hr;
  171. DWORD dwStatus;
  172. DWORD dwRead = 0;
  173. WCHAR szServer[MAX_PATH];
  174. LPGROUP_USERS_INFO_0 pGroupUserInfo = NULL;
  175. GROUP_INFO_2 *pGroupInfo2 = NULL;
  176. NET_API_STATUS nasStatus;
  177. MakeUncName(_ServerName, szServer);
  178. dwStatus = NetUserGetGroups(szServer,
  179. _UserName,
  180. 0,
  181. (LPBYTE*)&_pGlobalBuffer,
  182. MAX_PREFERRED_LENGTH,
  183. &dwRead,
  184. &_dwGlobalTotal);
  185. hr = HRESULT_FROM_WIN32(dwStatus);
  186. BAIL_ON_FAILURE(hr);
  187. if (dwRead != _dwGlobalTotal)
  188. hr = E_FAIL;
  189. if (dwRead == 1) {
  190. //
  191. // Check if it is the none group - dont want that
  192. //
  193. pGroupUserInfo = (LPGROUP_USERS_INFO_0)_pGlobalBuffer;
  194. if ( pGroupUserInfo->grui0_name && (FALSE == _fIsDomainController) &&
  195. (1 == _dwGlobalTotal) ) {
  196. // check if this the none group. Only non-DCs will return this group.
  197. nasStatus = NetGroupGetInfo(
  198. szServer,
  199. pGroupUserInfo->grui0_name,
  200. 2,
  201. (LPBYTE *) &pGroupInfo2
  202. );
  203. hr = HRESULT_FROM_WIN32(nasStatus);
  204. BAIL_ON_FAILURE(hr);
  205. if (pGroupInfo2->grpi2_group_id == DOMAIN_GROUP_RID_USERS) {
  206. //
  207. // Set the global total to zero - destructor will dealloc.
  208. //
  209. _dwGlobalTotal = 0;
  210. }
  211. }
  212. }
  213. error:
  214. if(pGroupInfo2)
  215. NetApiBufferFree(pGroupInfo2);
  216. RRETURN(hr);
  217. }
  218. HRESULT
  219. CWinNTUserGroupsCollectionEnum::DoLocalEnumeration()
  220. {
  221. HRESULT hr;
  222. DWORD dwStatus;
  223. DWORD dwRead = 0;
  224. WCHAR szServer[MAX_PATH];
  225. MakeUncName(_ServerName, szServer);
  226. dwStatus = NetUserGetLocalGroups(szServer,
  227. _UserName,
  228. 0,
  229. 0,
  230. (LPBYTE*)&_pLocalBuffer,
  231. MAX_PREFERRED_LENGTH,
  232. &dwRead,
  233. &_dwLocalTotal);
  234. hr = HRESULT_FROM_WIN32(dwStatus);
  235. BAIL_ON_FAILURE(hr);
  236. if (dwRead != _dwLocalTotal)
  237. hr = E_FAIL;
  238. error:
  239. RRETURN(hr);
  240. }
  241. //+---------------------------------------------------------------------------
  242. //
  243. // Function: CWinNTUserGroupsCollectionEnum::Next
  244. //
  245. // Synopsis: Returns cElements number of requested NetOle objects in the
  246. // array supplied in pvar.
  247. //
  248. // Arguments: [cElements] -- The number of elements requested by client
  249. // [pvar] -- ptr to array of VARIANTs to for return objects
  250. // [pcElementFetched] -- if non-NULL, then number of elements
  251. // -- actually returned is placed here
  252. //
  253. // Returns: HRESULT -- S_OK if number of elements requested are returned
  254. // -- S_FALSE if number of elements is < requested
  255. //
  256. // Modifies:
  257. //
  258. // History: 11-3-95 krishnag Created.
  259. //
  260. //----------------------------------------------------------------------------
  261. STDMETHODIMP
  262. CWinNTUserGroupsCollectionEnum::Next(
  263. ULONG cElements,
  264. VARIANT FAR* pvar,
  265. ULONG FAR* pcElementFetched
  266. )
  267. {
  268. ULONG cElementFetched = 0;
  269. HRESULT hr = S_OK;
  270. hr = EnumUserGroups(
  271. cElements,
  272. pvar,
  273. &cElementFetched
  274. );
  275. if (pcElementFetched) {
  276. *pcElementFetched = cElementFetched;
  277. }
  278. RRETURN_EXP_IF_ERR(hr);
  279. }
  280. STDMETHODIMP
  281. CWinNTUserGroupsCollectionEnum::Skip(ULONG cElements)
  282. {
  283. //
  284. // Note: we better not wrap around when we add!
  285. //
  286. _dwCurrent += cElements;
  287. _dwCurrent = min(_dwTotal, _dwCurrent);
  288. if (_dwCurrent < _dwTotal)
  289. return S_OK;
  290. return S_FALSE;
  291. }
  292. STDMETHODIMP
  293. CWinNTUserGroupsCollectionEnum::Reset()
  294. {
  295. _dwCurrent = 0;
  296. return S_OK;
  297. }
  298. HRESULT
  299. CWinNTUserGroupsCollectionEnum::EnumUserGroups(
  300. ULONG cElements,
  301. VARIANT FAR* pvar,
  302. ULONG FAR* pcElementFetched
  303. )
  304. {
  305. HRESULT hr = S_FALSE;
  306. IDispatch *pDispatch = NULL;
  307. DWORD i = 0;
  308. while (i < cElements) {
  309. hr = GetNextUserGroup(&pDispatch);
  310. if (hr == S_FALSE) {
  311. break;
  312. }
  313. VariantInit(&pvar[i]);
  314. pvar[i].vt = VT_DISPATCH;
  315. pvar[i].pdispVal = pDispatch;
  316. (*pcElementFetched)++;
  317. i++;
  318. }
  319. RRETURN(hr);
  320. }
  321. HRESULT
  322. CWinNTUserGroupsCollectionEnum::GetNextUserGroup(
  323. IDispatch ** ppDispatch
  324. )
  325. {
  326. HRESULT hr;
  327. LPGROUP_USERS_INFO_0 lpInfo;
  328. LPWSTR GroupName;
  329. ULONG GroupType;
  330. if (_dwCurrent >= _dwTotal)
  331. return S_FALSE;
  332. if (_dwCurrent < _dwGlobalTotal) {
  333. lpInfo = (LPGROUP_USERS_INFO_0)_pGlobalBuffer + _dwCurrent;
  334. GroupType = WINNT_GROUP_GLOBAL;
  335. } else {
  336. lpInfo = (LPGROUP_USERS_INFO_0)_pLocalBuffer + _dwCurrent -
  337. _dwGlobalTotal;
  338. GroupType = WINNT_GROUP_LOCAL;
  339. }
  340. _dwCurrent++;
  341. GroupName = lpInfo->grui0_name;
  342. //
  343. // On an error, should we try to keep going?
  344. //
  345. if (GroupType == WINNT_GROUP_GLOBAL) {
  346. hr = CWinNTGroup::CreateGroup(_ParentADsPath,
  347. _ParentType,
  348. _DomainName,
  349. _ServerName,
  350. GroupName,
  351. GroupType,
  352. ADS_OBJECT_BOUND,
  353. IID_IDispatch,
  354. _Credentials,
  355. (void **)ppDispatch
  356. );
  357. }
  358. else {
  359. hr = CWinNTGroup::CreateGroup(_ParentADsPath,
  360. _ParentType,
  361. _DomainName,
  362. _ServerName,
  363. GroupName,
  364. GroupType,
  365. ADS_OBJECT_BOUND,
  366. IID_IDispatch,
  367. _Credentials,
  368. (void **)ppDispatch
  369. );
  370. }
  371. if (FAILED(hr))
  372. return S_FALSE;
  373. return S_OK;
  374. }