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.

1049 lines
25 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995
  5. //
  6. // File: cenumdom.cxx
  7. //
  8. // Contents: Windows NT 3.5 Domain Enumeration Code
  9. //
  10. // CWinNTDomainEnum::CWinNTDomainEnum()
  11. // CWinNTDomainEnum::CWinNTDomainEnum
  12. // CWinNTDomainEnum::EnumObjects
  13. // CWinNTDomainEnum::EnumObjects
  14. //
  15. // History:
  16. //----------------------------------------------------------------------------
  17. #include "winnt.hxx"
  18. #pragma hdrstop
  19. //+---------------------------------------------------------------------------
  20. //
  21. // Function: CWinNTEnumVariant::Create
  22. //
  23. // Synopsis:
  24. //
  25. // Arguments: [pCollection]
  26. // [ppEnumVariant]
  27. //
  28. // Returns: HRESULT
  29. //
  30. // Modifies:
  31. //
  32. // History: 01-30-95 krishnag Created.
  33. //
  34. //----------------------------------------------------------------------------
  35. HRESULT
  36. CWinNTDomainEnum::Create(
  37. CWinNTDomainEnum FAR* FAR* ppenumvariant,
  38. LPWSTR ADsPath,
  39. LPWSTR DomainName,
  40. VARIANT var,
  41. CWinNTCredentials& Credentials
  42. )
  43. {
  44. HRESULT hr = NOERROR;
  45. CWinNTDomainEnum FAR* penumvariant = NULL;
  46. NET_API_STATUS nasStatus = 0;
  47. *ppenumvariant = NULL;
  48. penumvariant = new CWinNTDomainEnum();
  49. if (!penumvariant) {
  50. hr = E_OUTOFMEMORY;
  51. BAIL_ON_FAILURE(hr);
  52. }
  53. penumvariant->_ADsPath = AllocADsStr( ADsPath);
  54. if (!penumvariant->_ADsPath) {
  55. hr = E_OUTOFMEMORY;
  56. }
  57. BAIL_ON_FAILURE(hr);
  58. penumvariant->_DomainName = AllocADsStr( DomainName);
  59. if (!penumvariant->_DomainName) {
  60. hr = E_OUTOFMEMORY;
  61. }
  62. BAIL_ON_FAILURE(hr);
  63. hr = ObjectTypeList::CreateObjectTypeList(
  64. var,
  65. &penumvariant->_pObjList
  66. );
  67. BAIL_ON_FAILURE(hr);
  68. //
  69. // ramv's change. You don't need to do a WinNTGetCachedDCName
  70. // to validate a domain here. You might be dealing with a
  71. // workgroup. If this call succeeds then we keep a BOOL variable
  72. // which tells us next time when it is necessary whether it is a
  73. // domain or workgroup
  74. //
  75. hr = WinNTGetCachedDCName(
  76. penumvariant->_DomainName,
  77. penumvariant->_szDomainPDCName,
  78. Credentials.GetFlags()
  79. );
  80. if(SUCCEEDED(hr)){
  81. penumvariant->_fIsDomain = TRUE;
  82. } else {
  83. penumvariant->_fIsDomain = FALSE;
  84. }
  85. penumvariant->_Credentials = Credentials;
  86. hr = penumvariant->_Credentials.RefDomain(DomainName);
  87. BAIL_ON_FAILURE(hr);
  88. *ppenumvariant = penumvariant;
  89. RRETURN(S_OK);
  90. error:
  91. delete penumvariant;
  92. RRETURN_EXP_IF_ERR(hr);
  93. }
  94. CWinNTDomainEnum::CWinNTDomainEnum():
  95. _ADsPath(NULL),
  96. _DomainName(NULL)
  97. {
  98. _pObjList = NULL;
  99. _pBuffer = NULL;
  100. _dwObjectReturned = 0;
  101. _dwIndex = 0;
  102. _dwObjectCurrentEntry = 0;
  103. _dwObjectTotal = 0;
  104. _dwNetCount = 0;
  105. _hLGroupComputer = NULL;
  106. _hGGroupComputer = NULL;
  107. _dwGroupArrayIndex = 0;
  108. _dwCompObjectReturned = 0;
  109. _dwCompObjectCurrentEntry = 0;
  110. _dwCompObjectTotal = 0;
  111. _pCompBuffer = 0;
  112. _dwCompIndex = 0;
  113. _pServerInfo = NULL;
  114. _fSchemaReturned = FALSE;
  115. memset(_szDomainPDCName, 0, sizeof(WCHAR)*MAX_PATH);
  116. }
  117. CWinNTDomainEnum::CWinNTDomainEnum(ObjectTypeList ObjList):
  118. _ADsPath(NULL),
  119. _DomainName(NULL)
  120. {
  121. _pObjList = NULL;
  122. _pBuffer = NULL;
  123. _dwObjectReturned = 0;
  124. _dwObjectCurrentEntry = 0;
  125. _dwIndex = 0;
  126. _dwNetCount = 0;
  127. _hLGroupComputer = NULL;
  128. _hGGroupComputer = NULL;
  129. _dwGroupArrayIndex = 0;
  130. _dwCompObjectReturned = NULL;
  131. _dwCompObjectCurrentEntry = NULL;
  132. _dwCompObjectTotal = NULL;
  133. _dwCompResumeHandle = 0;
  134. _pCompBuffer = NULL;
  135. _fIsDomain = FALSE;
  136. _pServerInfo = NULL;
  137. _fSchemaReturned = FALSE;
  138. memset(_szDomainPDCName, 0, sizeof(WCHAR)*MAX_PATH);
  139. }
  140. CWinNTDomainEnum::~CWinNTDomainEnum()
  141. {
  142. if (_hLGroupComputer) {
  143. WinNTCloseComputer(
  144. _hLGroupComputer
  145. );
  146. }
  147. if (_hGGroupComputer) {
  148. WinNTCloseComputer(
  149. _hGGroupComputer
  150. );
  151. }
  152. if (_pCompBuffer) {
  153. NetApiBufferFree(_pCompBuffer);
  154. }
  155. if (_DomainName) {
  156. FreeADsStr(_DomainName);
  157. }
  158. if (_ADsPath) {
  159. FreeADsStr(_ADsPath);
  160. }
  161. if (_pObjList) {
  162. delete _pObjList;
  163. }
  164. if (_pBuffer)
  165. {
  166. NetApiBufferFree(_pBuffer);
  167. }
  168. if (_pServerInfo)
  169. {
  170. NetApiBufferFree(_pServerInfo);
  171. }
  172. }
  173. HRESULT
  174. CWinNTDomainEnum::EnumObjects(
  175. DWORD ObjectType,
  176. ULONG cElements,
  177. VARIANT FAR * pvar,
  178. ULONG FAR * pcElementFetched
  179. )
  180. {
  181. HRESULT hr = S_OK;
  182. ULONG cElementGlobal = 0;
  183. ULONG cElementLocal = 0;
  184. switch (ObjectType) {
  185. case WINNT_COMPUTER_ID:
  186. hr = EnumComputers(cElements, pvar, pcElementFetched);
  187. break;
  188. case WINNT_USER_ID:
  189. hr = EnumUsers(cElements, pvar, pcElementFetched);
  190. break;
  191. case WINNT_GROUP_ID:
  192. //
  193. // for backward compatabillity, "group" includes "local group" and
  194. // "global group" during enumeration
  195. //
  196. //
  197. // enum all the global groups first
  198. //
  199. hr = EnumGlobalGroups(
  200. cElements,
  201. pvar,
  202. &cElementGlobal
  203. );
  204. //
  205. // enum local groups when there is no more global
  206. //
  207. if (hr == S_FALSE) {
  208. hr = EnumLocalGroups(
  209. cElements-cElementGlobal, // we have reduced buffer size!
  210. pvar+cElementGlobal,
  211. &cElementLocal
  212. );
  213. }
  214. //
  215. // increment instead of just assingment: for consistency with
  216. // other switch cases
  217. //
  218. (*pcElementFetched) += (cElementGlobal+cElementLocal);
  219. break;
  220. case WINNT_LOCALGROUP_ID:
  221. hr = EnumLocalGroups(cElements, pvar, pcElementFetched);
  222. break;
  223. case WINNT_GLOBALGROUP_ID:
  224. hr = EnumGlobalGroups(cElements, pvar, pcElementFetched);
  225. break;
  226. case WINNT_SCHEMA_ID:
  227. hr = EnumSchema(cElements, pvar, pcElementFetched);
  228. break;
  229. default:
  230. RRETURN(S_FALSE);
  231. }
  232. RRETURN_EXP_IF_ERR(hr);
  233. }
  234. HRESULT
  235. CWinNTDomainEnum::EnumObjects(
  236. ULONG cElements,
  237. VARIANT FAR* pvar,
  238. ULONG FAR* pcElementFetched
  239. )
  240. {
  241. DWORD i;
  242. ULONG cRequested = 0;
  243. ULONG cFetchedByPath = 0;
  244. ULONG cTotalFetched = 0;
  245. VARIANT FAR* pPathvar = pvar;
  246. HRESULT hr = S_OK;
  247. DWORD ObjectType;
  248. for (i = 0; i < cElements; i++) {
  249. VariantInit(&pvar[i]);
  250. }
  251. cRequested = cElements;
  252. while (SUCCEEDED(_pObjList->GetCurrentObject(&ObjectType)) &&
  253. ((hr = EnumObjects(ObjectType,
  254. cRequested,
  255. pPathvar,
  256. &cFetchedByPath)) == S_FALSE )) {
  257. pPathvar += cFetchedByPath;
  258. cRequested -= cFetchedByPath;
  259. cTotalFetched += cFetchedByPath;
  260. cFetchedByPath = 0;
  261. if (FAILED(_pObjList->Next())){
  262. if (pcElementFetched)
  263. *pcElementFetched = cTotalFetched;
  264. RRETURN(S_FALSE);
  265. }
  266. }
  267. if (pcElementFetched) {
  268. *pcElementFetched = cTotalFetched + cFetchedByPath;
  269. }
  270. RRETURN_EXP_IF_ERR(hr);
  271. }
  272. HRESULT
  273. CWinNTDomainEnum::EnumSchema(
  274. ULONG cElements,
  275. VARIANT FAR* pvar,
  276. ULONG FAR* pcElementFetched
  277. )
  278. {
  279. HRESULT hr = S_OK;
  280. IDispatch *pDispatch = NULL;
  281. if ( _fSchemaReturned )
  282. RRETURN(S_FALSE);
  283. if ( cElements > 0 )
  284. {
  285. hr = CWinNTSchema::CreateSchema(
  286. _ADsPath,
  287. TEXT("Schema"),
  288. ADS_OBJECT_BOUND,
  289. IID_IDispatch,
  290. _Credentials,
  291. (void **)&pDispatch
  292. );
  293. if ( hr == S_OK )
  294. {
  295. VariantInit(&pvar[0]);
  296. pvar[0].vt = VT_DISPATCH;
  297. pvar[0].pdispVal = pDispatch;
  298. (*pcElementFetched)++;
  299. _fSchemaReturned = TRUE;
  300. }
  301. }
  302. RRETURN(hr);
  303. }
  304. HRESULT
  305. CWinNTDomainEnum::EnumUsers(
  306. ULONG cElements,
  307. VARIANT FAR* pvar,
  308. ULONG FAR* pcElementFetched
  309. )
  310. {
  311. HRESULT hr = S_OK;
  312. IDispatch *pDispatch = NULL;
  313. DWORD i = 0;
  314. if(!_fIsDomain){
  315. RRETURN(S_FALSE);
  316. }
  317. while (i < cElements) {
  318. hr = GetUserObject(&pDispatch);
  319. if (hr == S_FALSE) {
  320. break;
  321. }
  322. VariantInit(&pvar[i]);
  323. pvar[i].vt = VT_DISPATCH;
  324. pvar[i].pdispVal = pDispatch;
  325. (*pcElementFetched)++;
  326. i++;
  327. }
  328. return(hr);
  329. }
  330. HRESULT
  331. CWinNTDomainEnum::GetUserObject(
  332. IDispatch ** ppDispatch
  333. )
  334. {
  335. HRESULT hr = S_OK;
  336. NTSTATUS Status;
  337. PNET_DISPLAY_USER pUserInfo1 = NULL;
  338. NET_API_STATUS nasStatus = 0;
  339. DWORD dwResumeHandle = 0;
  340. if (!_pBuffer || (_dwObjectCurrentEntry == _dwObjectReturned)) {
  341. if (_pBuffer) {
  342. NetApiBufferFree(_pBuffer);
  343. _pBuffer = NULL;
  344. }
  345. _dwObjectCurrentEntry = 0;
  346. _dwObjectReturned = 0;
  347. nasStatus = NetQueryDisplayInformation(
  348. _szDomainPDCName,
  349. 1,
  350. _dwIndex,
  351. 1024,
  352. MAX_PREFERRED_LENGTH,
  353. &_dwObjectReturned,
  354. (PVOID *)&_pBuffer
  355. );
  356. _dwNetCount++;
  357. //
  358. // The following if clause is to handle real errors; anything
  359. // other than ERROR_SUCCESS and ERROR_MORE_DATA
  360. //
  361. if ((nasStatus != ERROR_SUCCESS) && (nasStatus != ERROR_MORE_DATA)) {
  362. RRETURN(S_FALSE);
  363. }
  364. //
  365. // This one is to handle the termination case - Call completed
  366. // successfully but there is no data to retrieve _pBuffer = NULL
  367. //
  368. if (!_pBuffer) {
  369. RRETURN(S_FALSE);
  370. }
  371. _dwIndex = (_pBuffer + _dwObjectReturned -1)->usri1_next_index;
  372. }
  373. //
  374. // Now send back the current ovbject
  375. //
  376. pUserInfo1 = (PNET_DISPLAY_USER)_pBuffer;
  377. pUserInfo1 += _dwObjectCurrentEntry;
  378. hr = CWinNTUser::CreateUser(
  379. _ADsPath,
  380. WINNT_DOMAIN_ID,
  381. _DomainName,
  382. NULL,
  383. pUserInfo1->usri1_name,
  384. ADS_OBJECT_BOUND,
  385. &(pUserInfo1->usri1_flags),
  386. pUserInfo1->usri1_full_name,
  387. pUserInfo1->usri1_comment,
  388. NULL,
  389. IID_IDispatch,
  390. _Credentials,
  391. (void **)ppDispatch
  392. );
  393. BAIL_IF_ERROR(hr);
  394. _dwObjectCurrentEntry++;
  395. RRETURN(S_OK);
  396. cleanup:
  397. *ppDispatch = NULL;
  398. RRETURN(S_FALSE);
  399. }
  400. HRESULT
  401. CWinNTDomainEnum::EnumComputers(
  402. ULONG cElements,
  403. VARIANT FAR* pvar,
  404. ULONG FAR* pcElementFetched
  405. )
  406. {
  407. HRESULT hr = S_OK;
  408. IDispatch *pDispatch = NULL;
  409. DWORD i = 0;
  410. while (i < cElements) {
  411. if(_fIsDomain == TRUE){
  412. hr = GetComputerObject(&pDispatch);
  413. }
  414. else {
  415. hr = GetComputerObjectInWorkGroup(&pDispatch);
  416. }
  417. if (hr == S_FALSE) {
  418. break;
  419. }
  420. VariantInit(&pvar[i]);
  421. pvar[i].vt = VT_DISPATCH;
  422. pvar[i].pdispVal = pDispatch;
  423. (*pcElementFetched)++;
  424. i++;
  425. }
  426. return(hr);
  427. }
  428. HRESULT
  429. CWinNTDomainEnum::GetComputerObject(
  430. IDispatch ** ppDispatch
  431. )
  432. {
  433. HRESULT hr = S_OK;
  434. NTSTATUS Status;
  435. PNET_DISPLAY_MACHINE pDisplayComp = NULL;
  436. NET_API_STATUS nasStatus = 0;
  437. DWORD dwResumeHandle = 0;
  438. DWORD clen = 0;
  439. if (!_pCompBuffer || (_dwCompObjectCurrentEntry == _dwCompObjectReturned)) {
  440. if (_pCompBuffer) {
  441. NetApiBufferFree(_pCompBuffer);
  442. _pCompBuffer = NULL;
  443. }
  444. _dwCompObjectCurrentEntry = 0;
  445. _dwCompObjectReturned = 0;
  446. nasStatus = NetQueryDisplayInformation(
  447. _szDomainPDCName,
  448. 2,
  449. _dwCompIndex,
  450. 100,
  451. MAX_PREFERRED_LENGTH,
  452. &_dwCompObjectReturned,
  453. (PVOID *)&_pCompBuffer
  454. );
  455. // The following if clause is to handle real errors; anything
  456. // other than ERROR_SUCCESS and ERROR_MORE_DATA
  457. //
  458. if ((nasStatus != ERROR_SUCCESS) && (nasStatus != ERROR_MORE_DATA)) {
  459. RRETURN(S_FALSE);
  460. }
  461. //
  462. // This one is to handle the termination case - Call completed
  463. // successfully but there is no data to retrieve _pBuffer = NULL
  464. //
  465. if (!_pCompBuffer) {
  466. RRETURN(S_FALSE);
  467. }
  468. _dwCompIndex = (_pCompBuffer + _dwCompObjectReturned -1)->usri2_next_index;
  469. }
  470. //
  471. // Now send back the current object
  472. //
  473. pDisplayComp = (PNET_DISPLAY_MACHINE)_pCompBuffer;
  474. pDisplayComp += _dwCompObjectCurrentEntry;
  475. //
  476. // The usri2_name is going to be returned back with a
  477. // $ character appended. Null set the $ character.
  478. //
  479. clen = wcslen(pDisplayComp->usri2_name);
  480. *(pDisplayComp->usri2_name + clen -1) = L'\0';
  481. hr = CWinNTComputer::CreateComputer(
  482. _ADsPath,
  483. _DomainName,
  484. pDisplayComp->usri2_name,
  485. ADS_OBJECT_BOUND,
  486. IID_IDispatch,
  487. _Credentials,
  488. (void **)ppDispatch
  489. );
  490. BAIL_IF_ERROR(hr);
  491. _dwCompObjectCurrentEntry++;
  492. RRETURN(S_OK);
  493. cleanup:
  494. *ppDispatch = NULL;
  495. RRETURN(S_FALSE);
  496. }
  497. //+---------------------------------------------------------------------------
  498. //
  499. // Function: CWinNTDomainEnum::Next
  500. //
  501. // Synopsis: Returns cElements number of requested NetOle objects in the
  502. // array supplied in pvar.
  503. //
  504. // Arguments: [cElements] -- The number of elements requested by client
  505. // [pvar] -- ptr to array of VARIANTs to for return objects
  506. // [pcElementFetched] -- if non-NULL, then number of elements
  507. // -- actually returned is placed here
  508. //
  509. // Returns: HRESULT -- S_OK if number of elements requested are returned
  510. // -- S_FALSE if number of elements is < requested
  511. //
  512. // Modifies:
  513. //
  514. // History: 11-3-95 krishnag Created.
  515. //
  516. //----------------------------------------------------------------------------
  517. STDMETHODIMP
  518. CWinNTDomainEnum::Next(
  519. ULONG cElements,
  520. VARIANT FAR* pvar,
  521. ULONG FAR* pcElementFetched
  522. )
  523. {
  524. ULONG cElementFetched = 0;
  525. HRESULT hr = S_OK;
  526. if (NULL == pvar)
  527. {
  528. hr = S_FALSE;
  529. }
  530. else
  531. {
  532. hr = EnumObjects(
  533. cElements,
  534. pvar,
  535. &cElementFetched
  536. );
  537. }
  538. if (pcElementFetched) {
  539. *pcElementFetched = cElementFetched;
  540. }
  541. RRETURN(hr);
  542. }
  543. HRESULT
  544. CWinNTDomainEnum::GetComputerObjectInWorkGroup(
  545. IDispatch ** ppDispatch
  546. )
  547. {
  548. HRESULT hr = S_OK;
  549. NTSTATUS Status;
  550. PSERVER_INFO_100 pServerInfo = NULL;
  551. NET_API_STATUS nasStatus = 0;
  552. DWORD clen = 0;
  553. if (!_pServerInfo || (_dwCompObjectCurrentEntry == _dwCompObjectReturned))
  554. {
  555. if (_pServerInfo) {
  556. NetApiBufferFree(_pServerInfo);
  557. _pServerInfo = NULL;
  558. }
  559. if(_dwCompObjectTotal == _dwCompObjectReturned
  560. && (_dwCompObjectTotal !=0)){
  561. //
  562. // we got all elements already, no need to do another call
  563. //
  564. RRETURN(S_FALSE);
  565. }
  566. nasStatus = NetServerEnum(
  567. NULL,
  568. 100,
  569. (LPBYTE *)&_pServerInfo,
  570. MAX_PREFERRED_LENGTH,
  571. &_dwCompObjectReturned,
  572. &_dwCompObjectTotal,
  573. SV_TYPE_NT,
  574. _DomainName,
  575. &_dwCompResumeHandle
  576. );
  577. /*
  578. nasStatus = NetQueryDisplayInformation(
  579. _szDomainPDCName,
  580. 2,
  581. _dwCompIndex,
  582. 100,
  583. MAX_PREFERRED_LENGTH,
  584. &_dwCompObjectReturned,
  585. (PVOID *)&_pServerInfo
  586. );
  587. */
  588. //
  589. // The following if clause is to handle real errors; anything
  590. // other than ERROR_SUCCESS and ERROR_MORE_DATA
  591. //
  592. if ((nasStatus != ERROR_SUCCESS) && (nasStatus != ERROR_MORE_DATA)) {
  593. RRETURN(S_FALSE);
  594. }
  595. _dwCompObjectCurrentEntry = 0;
  596. //
  597. // This one is to handle the termination case - Call completed
  598. // successfully but there is no data to retrieve _pServerInfo = NULL
  599. //
  600. if (!_dwCompObjectReturned) {
  601. _pServerInfo = NULL;
  602. RRETURN(S_FALSE);
  603. }
  604. }
  605. //
  606. // Now send back the current object
  607. //
  608. pServerInfo = (PSERVER_INFO_100)_pServerInfo;
  609. pServerInfo += _dwCompObjectCurrentEntry;
  610. hr = CWinNTComputer::CreateComputer(
  611. _ADsPath,
  612. _DomainName,
  613. pServerInfo->sv100_name,
  614. ADS_OBJECT_BOUND,
  615. IID_IDispatch,
  616. _Credentials,
  617. (void **)ppDispatch
  618. );
  619. BAIL_IF_ERROR(hr);
  620. _dwCompObjectCurrentEntry++;
  621. RRETURN(S_OK);
  622. cleanup:
  623. *ppDispatch = NULL;
  624. RRETURN(S_FALSE);
  625. }
  626. HRESULT
  627. CWinNTDomainEnum::GetGlobalGroupObject(
  628. IDispatch ** ppDispatch
  629. )
  630. {
  631. HRESULT hr = S_OK;
  632. LPWINNT_GROUP pWinNTGrp = NULL;
  633. LPBYTE pBuffer = NULL;
  634. DWORD dwReturned = 0;
  635. BOOL dwRet = 0;
  636. if (!_hGGroupComputer) {
  637. dwRet = WinNTComputerOpen(
  638. _DomainName,
  639. (_szDomainPDCName + 2),
  640. WINNT_DOMAIN_ID,
  641. &_hGGroupComputer
  642. );
  643. if (!dwRet) {
  644. goto error;
  645. }
  646. }
  647. dwRet = WinNTEnumGlobalGroups(
  648. _hGGroupComputer,
  649. 1,
  650. &pBuffer,
  651. &dwReturned
  652. );
  653. if (!dwRet) {
  654. goto error;
  655. }
  656. pWinNTGrp = (LPWINNT_GROUP)pBuffer;
  657. hr = CWinNTGroup::CreateGroup(
  658. pWinNTGrp->Parent,
  659. WINNT_DOMAIN_ID,
  660. pWinNTGrp->Domain,
  661. pWinNTGrp->Computer,
  662. pWinNTGrp->Name,
  663. WINNT_GROUP_GLOBAL,
  664. ADS_OBJECT_BOUND,
  665. IID_IDispatch,
  666. _Credentials,
  667. (void **)ppDispatch
  668. );
  669. BAIL_ON_FAILURE(hr);
  670. hr = S_OK;
  671. cleanup:
  672. if (pBuffer) {
  673. FreeADsMem(pBuffer);
  674. }
  675. RRETURN(hr);
  676. error:
  677. *ppDispatch = NULL;
  678. hr = S_FALSE;
  679. goto cleanup;
  680. }
  681. HRESULT
  682. CWinNTDomainEnum::GetLocalGroupObject(
  683. IDispatch ** ppDispatch
  684. )
  685. {
  686. HRESULT hr = S_OK;
  687. LPWINNT_GROUP pWinNTGrp = NULL;
  688. LPBYTE pBuffer = NULL;
  689. DWORD dwReturned = 0;
  690. BOOL dwRet = 0;
  691. if (!_hLGroupComputer) {
  692. dwRet = WinNTComputerOpen(
  693. _DomainName,
  694. (_szDomainPDCName + 2),
  695. WINNT_DOMAIN_ID,
  696. &_hLGroupComputer
  697. );
  698. if (!dwRet) {
  699. goto error;
  700. }
  701. }
  702. dwRet = WinNTEnumLocalGroups(
  703. _hLGroupComputer,
  704. 1,
  705. &pBuffer,
  706. &dwReturned
  707. );
  708. if (!dwRet) {
  709. goto error;
  710. }
  711. pWinNTGrp = (LPWINNT_GROUP)pBuffer;
  712. hr = CWinNTGroup::CreateGroup(
  713. pWinNTGrp->Parent,
  714. WINNT_DOMAIN_ID,
  715. pWinNTGrp->Domain,
  716. pWinNTGrp->Computer,
  717. pWinNTGrp->Name,
  718. WINNT_GROUP_LOCAL,
  719. ADS_OBJECT_BOUND,
  720. IID_IDispatch,
  721. _Credentials,
  722. (void **)ppDispatch
  723. );
  724. BAIL_ON_FAILURE(hr);
  725. hr = S_OK;
  726. cleanup:
  727. if (pBuffer) {
  728. FreeADsMem(pBuffer);
  729. }
  730. RRETURN(hr);
  731. error:
  732. *ppDispatch = NULL;
  733. hr = S_FALSE;
  734. goto cleanup;
  735. }
  736. HRESULT
  737. CWinNTDomainEnum::EnumGroupObjects(
  738. DWORD ObjectType,
  739. ULONG cElements,
  740. VARIANT FAR * pvar,
  741. ULONG FAR * pcElementFetched
  742. )
  743. {
  744. HRESULT hr;
  745. switch (ObjectType) {
  746. case WINNT_GROUP_GLOBAL:
  747. hr = EnumGlobalGroups(cElements, pvar, pcElementFetched);
  748. break;
  749. case WINNT_GROUP_LOCAL:
  750. hr = EnumLocalGroups(cElements, pvar, pcElementFetched);
  751. break;
  752. default:
  753. hr = S_FALSE;
  754. break;
  755. }
  756. RRETURN(hr);
  757. }
  758. ULONG GroupTypeArray[] = {WINNT_GROUP_GLOBAL, WINNT_GROUP_LOCAL, 0xFFFFFFFF};
  759. HRESULT
  760. CWinNTDomainEnum::EnumGroups(
  761. ULONG cElements,
  762. VARIANT FAR* pvar,
  763. ULONG FAR* pcElementFetched
  764. )
  765. {
  766. DWORD i;
  767. ULONG cRequested = 0;
  768. ULONG cFetchedByPath = 0;
  769. ULONG cTotalFetched = 0;
  770. VARIANT FAR* pPathvar = pvar;
  771. HRESULT hr = S_OK;
  772. DWORD ObjectType;
  773. if(!_fIsDomain){
  774. RRETURN(S_FALSE);
  775. }
  776. for (i = 0; i < cElements; i++) {
  777. VariantInit(&pvar[i]);
  778. }
  779. cRequested = cElements;
  780. while ((GroupTypeArray[_dwGroupArrayIndex] != (ULONG)-1) &&
  781. ((hr = EnumGroupObjects(
  782. GroupTypeArray[_dwGroupArrayIndex],
  783. cRequested,
  784. pPathvar,
  785. &cFetchedByPath)) == S_FALSE )) {
  786. pPathvar += cFetchedByPath;
  787. cRequested -= cFetchedByPath;
  788. cTotalFetched += cFetchedByPath;
  789. cFetchedByPath = 0;
  790. if (GroupTypeArray[_dwGroupArrayIndex++] == (ULONG)-1){
  791. if (pcElementFetched)
  792. *pcElementFetched = cTotalFetched;
  793. RRETURN(S_FALSE);
  794. }
  795. }
  796. if (pcElementFetched) {
  797. *pcElementFetched = cTotalFetched + cFetchedByPath;
  798. }
  799. RRETURN(hr);
  800. }
  801. HRESULT
  802. CWinNTDomainEnum::EnumGlobalGroups(
  803. ULONG cElements,
  804. VARIANT FAR* pvar,
  805. ULONG FAR* pcElementFetched
  806. )
  807. {
  808. HRESULT hr = S_OK;
  809. IDispatch *pDispatch = NULL;
  810. DWORD i = 0;
  811. while (i < cElements) {
  812. hr = GetGlobalGroupObject(&pDispatch);
  813. if (hr == S_FALSE) {
  814. break;
  815. }
  816. VariantInit(&pvar[i]);
  817. pvar[i].vt = VT_DISPATCH;
  818. pvar[i].pdispVal = pDispatch;
  819. (*pcElementFetched)++;
  820. i++;
  821. }
  822. return(hr);
  823. }
  824. HRESULT
  825. CWinNTDomainEnum::EnumLocalGroups(
  826. ULONG cElements,
  827. VARIANT FAR* pvar,
  828. ULONG FAR* pcElementFetched
  829. )
  830. {
  831. HRESULT hr = S_OK;
  832. IDispatch *pDispatch = NULL;
  833. DWORD i = 0;
  834. while (i < cElements) {
  835. hr = GetLocalGroupObject(&pDispatch);
  836. if (hr == S_FALSE) {
  837. break;
  838. }
  839. VariantInit(&pvar[i]);
  840. pvar[i].vt = VT_DISPATCH;
  841. pvar[i].pdispVal = pDispatch;
  842. (*pcElementFetched)++;
  843. i++;
  844. }
  845. return(hr);
  846. }