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.

1034 lines
23 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. }
  165. HRESULT
  166. CWinNTDomainEnum::EnumObjects(
  167. DWORD ObjectType,
  168. ULONG cElements,
  169. VARIANT FAR * pvar,
  170. ULONG FAR * pcElementFetched
  171. )
  172. {
  173. HRESULT hr = S_OK;
  174. ULONG cElementGlobal = 0;
  175. ULONG cElementLocal = 0;
  176. switch (ObjectType) {
  177. case WINNT_COMPUTER_ID:
  178. hr = EnumComputers(cElements, pvar, pcElementFetched);
  179. break;
  180. case WINNT_USER_ID:
  181. hr = EnumUsers(cElements, pvar, pcElementFetched);
  182. break;
  183. case WINNT_GROUP_ID:
  184. //
  185. // for backward compatabillity, "group" includes "local group" and
  186. // "global group" during enumeration
  187. //
  188. //
  189. // enum all the global groups first
  190. //
  191. hr = EnumGlobalGroups(
  192. cElements,
  193. pvar,
  194. &cElementGlobal
  195. );
  196. //
  197. // enum local groups when there is no more global
  198. //
  199. if (hr == S_FALSE) {
  200. hr = EnumLocalGroups(
  201. cElements-cElementGlobal, // we have reduced buffer size!
  202. pvar+cElementGlobal,
  203. &cElementLocal
  204. );
  205. }
  206. //
  207. // increment instead of just assingment: for consistency with
  208. // other switch cases
  209. //
  210. (*pcElementFetched) += (cElementGlobal+cElementLocal);
  211. break;
  212. case WINNT_LOCALGROUP_ID:
  213. hr = EnumLocalGroups(cElements, pvar, pcElementFetched);
  214. break;
  215. case WINNT_GLOBALGROUP_ID:
  216. hr = EnumGlobalGroups(cElements, pvar, pcElementFetched);
  217. break;
  218. case WINNT_SCHEMA_ID:
  219. hr = EnumSchema(cElements, pvar, pcElementFetched);
  220. break;
  221. default:
  222. RRETURN(S_FALSE);
  223. }
  224. RRETURN_EXP_IF_ERR(hr);
  225. }
  226. HRESULT
  227. CWinNTDomainEnum::EnumObjects(
  228. ULONG cElements,
  229. VARIANT FAR* pvar,
  230. ULONG FAR* pcElementFetched
  231. )
  232. {
  233. DWORD i;
  234. ULONG cRequested = 0;
  235. ULONG cFetchedByPath = 0;
  236. ULONG cTotalFetched = 0;
  237. VARIANT FAR* pPathvar = pvar;
  238. HRESULT hr = S_OK;
  239. DWORD ObjectType;
  240. for (i = 0; i < cElements; i++) {
  241. VariantInit(&pvar[i]);
  242. }
  243. cRequested = cElements;
  244. while (SUCCEEDED(_pObjList->GetCurrentObject(&ObjectType)) &&
  245. ((hr = EnumObjects(ObjectType,
  246. cRequested,
  247. pPathvar,
  248. &cFetchedByPath)) == S_FALSE )) {
  249. pPathvar += cFetchedByPath;
  250. cRequested -= cFetchedByPath;
  251. cTotalFetched += cFetchedByPath;
  252. cFetchedByPath = 0;
  253. if (FAILED(_pObjList->Next())){
  254. if (pcElementFetched)
  255. *pcElementFetched = cTotalFetched;
  256. RRETURN(S_FALSE);
  257. }
  258. }
  259. if (pcElementFetched) {
  260. *pcElementFetched = cTotalFetched + cFetchedByPath;
  261. }
  262. RRETURN_EXP_IF_ERR(hr);
  263. }
  264. HRESULT
  265. CWinNTDomainEnum::EnumSchema(
  266. ULONG cElements,
  267. VARIANT FAR* pvar,
  268. ULONG FAR* pcElementFetched
  269. )
  270. {
  271. HRESULT hr = S_OK;
  272. IDispatch *pDispatch = NULL;
  273. if ( _fSchemaReturned )
  274. RRETURN(S_FALSE);
  275. if ( cElements > 0 )
  276. {
  277. hr = CWinNTSchema::CreateSchema(
  278. _ADsPath,
  279. TEXT("Schema"),
  280. ADS_OBJECT_BOUND,
  281. IID_IDispatch,
  282. _Credentials,
  283. (void **)&pDispatch
  284. );
  285. if ( hr == S_OK )
  286. {
  287. VariantInit(&pvar[0]);
  288. pvar[0].vt = VT_DISPATCH;
  289. pvar[0].pdispVal = pDispatch;
  290. (*pcElementFetched)++;
  291. _fSchemaReturned = TRUE;
  292. }
  293. }
  294. RRETURN(hr);
  295. }
  296. HRESULT
  297. CWinNTDomainEnum::EnumUsers(
  298. ULONG cElements,
  299. VARIANT FAR* pvar,
  300. ULONG FAR* pcElementFetched
  301. )
  302. {
  303. HRESULT hr = S_OK;
  304. IDispatch *pDispatch = NULL;
  305. DWORD i = 0;
  306. if(!_fIsDomain){
  307. RRETURN(S_FALSE);
  308. }
  309. while (i < cElements) {
  310. hr = GetUserObject(&pDispatch);
  311. if (hr == S_FALSE) {
  312. break;
  313. }
  314. VariantInit(&pvar[i]);
  315. pvar[i].vt = VT_DISPATCH;
  316. pvar[i].pdispVal = pDispatch;
  317. (*pcElementFetched)++;
  318. i++;
  319. }
  320. return(hr);
  321. }
  322. HRESULT
  323. CWinNTDomainEnum::GetUserObject(
  324. IDispatch ** ppDispatch
  325. )
  326. {
  327. HRESULT hr = S_OK;
  328. NTSTATUS Status;
  329. PNET_DISPLAY_USER pUserInfo1 = NULL;
  330. NET_API_STATUS nasStatus = 0;
  331. DWORD dwResumeHandle = 0;
  332. if (!_pBuffer || (_dwObjectCurrentEntry == _dwObjectReturned)) {
  333. if (_pBuffer) {
  334. NetApiBufferFree(_pBuffer);
  335. _pBuffer = NULL;
  336. }
  337. _dwObjectCurrentEntry = 0;
  338. _dwObjectReturned = 0;
  339. nasStatus = NetQueryDisplayInformation(
  340. _szDomainPDCName,
  341. 1,
  342. _dwIndex,
  343. 1024,
  344. MAX_PREFERRED_LENGTH,
  345. &_dwObjectReturned,
  346. (PVOID *)&_pBuffer
  347. );
  348. _dwNetCount++;
  349. //
  350. // The following if clause is to handle real errors; anything
  351. // other than ERROR_SUCCESS and ERROR_MORE_DATA
  352. //
  353. if ((nasStatus != ERROR_SUCCESS) && (nasStatus != ERROR_MORE_DATA)) {
  354. RRETURN(S_FALSE);
  355. }
  356. //
  357. // This one is to handle the termination case - Call completed
  358. // successfully but there is no data to retrieve _pBuffer = NULL
  359. //
  360. if (!_pBuffer) {
  361. RRETURN(S_FALSE);
  362. }
  363. _dwIndex = (_pBuffer + _dwObjectReturned -1)->usri1_next_index;
  364. }
  365. //
  366. // Now send back the current ovbject
  367. //
  368. pUserInfo1 = (PNET_DISPLAY_USER)_pBuffer;
  369. pUserInfo1 += _dwObjectCurrentEntry;
  370. hr = CWinNTUser::CreateUser(
  371. _ADsPath,
  372. WINNT_DOMAIN_ID,
  373. _DomainName,
  374. NULL,
  375. pUserInfo1->usri1_name,
  376. ADS_OBJECT_BOUND,
  377. &(pUserInfo1->usri1_flags),
  378. pUserInfo1->usri1_full_name,
  379. pUserInfo1->usri1_comment,
  380. NULL,
  381. IID_IDispatch,
  382. _Credentials,
  383. (void **)ppDispatch
  384. );
  385. BAIL_IF_ERROR(hr);
  386. _dwObjectCurrentEntry++;
  387. RRETURN(S_OK);
  388. cleanup:
  389. *ppDispatch = NULL;
  390. RRETURN(S_FALSE);
  391. }
  392. HRESULT
  393. CWinNTDomainEnum::EnumComputers(
  394. ULONG cElements,
  395. VARIANT FAR* pvar,
  396. ULONG FAR* pcElementFetched
  397. )
  398. {
  399. HRESULT hr = S_OK;
  400. IDispatch *pDispatch = NULL;
  401. DWORD i = 0;
  402. while (i < cElements) {
  403. if(_fIsDomain == TRUE){
  404. hr = GetComputerObject(&pDispatch);
  405. }
  406. else {
  407. hr = GetComputerObjectInWorkGroup(&pDispatch);
  408. }
  409. if (hr == S_FALSE) {
  410. break;
  411. }
  412. VariantInit(&pvar[i]);
  413. pvar[i].vt = VT_DISPATCH;
  414. pvar[i].pdispVal = pDispatch;
  415. (*pcElementFetched)++;
  416. i++;
  417. }
  418. return(hr);
  419. }
  420. HRESULT
  421. CWinNTDomainEnum::GetComputerObject(
  422. IDispatch ** ppDispatch
  423. )
  424. {
  425. HRESULT hr = S_OK;
  426. NTSTATUS Status;
  427. PNET_DISPLAY_MACHINE pDisplayComp = NULL;
  428. NET_API_STATUS nasStatus = 0;
  429. DWORD dwResumeHandle = 0;
  430. DWORD clen = 0;
  431. if (!_pCompBuffer || (_dwCompObjectCurrentEntry == _dwCompObjectReturned)) {
  432. if (_pCompBuffer) {
  433. NetApiBufferFree(_pCompBuffer);
  434. _pCompBuffer = NULL;
  435. }
  436. _dwCompObjectCurrentEntry = 0;
  437. _dwCompObjectReturned = 0;
  438. nasStatus = NetQueryDisplayInformation(
  439. _szDomainPDCName,
  440. 2,
  441. _dwCompIndex,
  442. 100,
  443. MAX_PREFERRED_LENGTH,
  444. &_dwCompObjectReturned,
  445. (PVOID *)&_pCompBuffer
  446. );
  447. // The following if clause is to handle real errors; anything
  448. // other than ERROR_SUCCESS and ERROR_MORE_DATA
  449. //
  450. if ((nasStatus != ERROR_SUCCESS) && (nasStatus != ERROR_MORE_DATA)) {
  451. RRETURN(S_FALSE);
  452. }
  453. //
  454. // This one is to handle the termination case - Call completed
  455. // successfully but there is no data to retrieve _pBuffer = NULL
  456. //
  457. if (!_pCompBuffer) {
  458. RRETURN(S_FALSE);
  459. }
  460. _dwCompIndex = (_pCompBuffer + _dwCompObjectReturned -1)->usri2_next_index;
  461. }
  462. //
  463. // Now send back the current object
  464. //
  465. pDisplayComp = (PNET_DISPLAY_MACHINE)_pCompBuffer;
  466. pDisplayComp += _dwCompObjectCurrentEntry;
  467. //
  468. // The usri2_name is going to be returned back with a
  469. // $ character appended. Null set the $ character.
  470. //
  471. clen = wcslen(pDisplayComp->usri2_name);
  472. *(pDisplayComp->usri2_name + clen -1) = L'\0';
  473. hr = CWinNTComputer::CreateComputer(
  474. _ADsPath,
  475. _DomainName,
  476. pDisplayComp->usri2_name,
  477. ADS_OBJECT_BOUND,
  478. IID_IDispatch,
  479. _Credentials,
  480. (void **)ppDispatch
  481. );
  482. BAIL_IF_ERROR(hr);
  483. _dwCompObjectCurrentEntry++;
  484. RRETURN(S_OK);
  485. cleanup:
  486. *ppDispatch = NULL;
  487. RRETURN(S_FALSE);
  488. }
  489. //+---------------------------------------------------------------------------
  490. //
  491. // Function: CWinNTDomainEnum::Next
  492. //
  493. // Synopsis: Returns cElements number of requested NetOle objects in the
  494. // array supplied in pvar.
  495. //
  496. // Arguments: [cElements] -- The number of elements requested by client
  497. // [pvar] -- ptr to array of VARIANTs to for return objects
  498. // [pcElementFetched] -- if non-NULL, then number of elements
  499. // -- actually returned is placed here
  500. //
  501. // Returns: HRESULT -- S_OK if number of elements requested are returned
  502. // -- S_FALSE if number of elements is < requested
  503. //
  504. // Modifies:
  505. //
  506. // History: 11-3-95 krishnag Created.
  507. //
  508. //----------------------------------------------------------------------------
  509. STDMETHODIMP
  510. CWinNTDomainEnum::Next(
  511. ULONG cElements,
  512. VARIANT FAR* pvar,
  513. ULONG FAR* pcElementFetched
  514. )
  515. {
  516. ULONG cElementFetched = 0;
  517. HRESULT hr = S_OK;
  518. hr = EnumObjects(
  519. cElements,
  520. pvar,
  521. &cElementFetched
  522. );
  523. if (pcElementFetched) {
  524. *pcElementFetched = cElementFetched;
  525. }
  526. RRETURN(hr);
  527. }
  528. HRESULT
  529. CWinNTDomainEnum::GetComputerObjectInWorkGroup(
  530. IDispatch ** ppDispatch
  531. )
  532. {
  533. HRESULT hr = S_OK;
  534. NTSTATUS Status;
  535. PSERVER_INFO_100 pServerInfo = NULL;
  536. NET_API_STATUS nasStatus = 0;
  537. DWORD clen = 0;
  538. if (!_pServerInfo || (_dwCompObjectCurrentEntry == _dwCompObjectReturned))
  539. {
  540. if (_pServerInfo) {
  541. NetApiBufferFree(_pServerInfo);
  542. _pServerInfo = NULL;
  543. }
  544. if(_dwCompObjectTotal == _dwCompObjectReturned
  545. && (_dwCompObjectTotal !=0)){
  546. //
  547. // we got all elements already, no need to do another call
  548. //
  549. RRETURN(S_FALSE);
  550. }
  551. nasStatus = NetServerEnum(
  552. NULL,
  553. 100,
  554. (LPBYTE *)&_pServerInfo,
  555. MAX_PREFERRED_LENGTH,
  556. &_dwCompObjectReturned,
  557. &_dwCompObjectTotal,
  558. SV_TYPE_NT,
  559. _DomainName,
  560. &_dwCompResumeHandle
  561. );
  562. /*
  563. nasStatus = NetQueryDisplayInformation(
  564. _szDomainPDCName,
  565. 2,
  566. _dwCompIndex,
  567. 100,
  568. MAX_PREFERRED_LENGTH,
  569. &_dwCompObjectReturned,
  570. (PVOID *)&_pServerInfo
  571. );
  572. */
  573. //
  574. // The following if clause is to handle real errors; anything
  575. // other than ERROR_SUCCESS and ERROR_MORE_DATA
  576. //
  577. if ((nasStatus != ERROR_SUCCESS) && (nasStatus != ERROR_MORE_DATA)) {
  578. RRETURN(S_FALSE);
  579. }
  580. _dwCompObjectCurrentEntry = 0;
  581. //
  582. // This one is to handle the termination case - Call completed
  583. // successfully but there is no data to retrieve _pServerInfo = NULL
  584. //
  585. if (!_dwCompObjectReturned) {
  586. _pServerInfo = NULL;
  587. RRETURN(S_FALSE);
  588. }
  589. }
  590. //
  591. // Now send back the current object
  592. //
  593. pServerInfo = (PSERVER_INFO_100)_pServerInfo;
  594. pServerInfo += _dwCompObjectCurrentEntry;
  595. hr = CWinNTComputer::CreateComputer(
  596. _ADsPath,
  597. _DomainName,
  598. pServerInfo->sv100_name,
  599. ADS_OBJECT_BOUND,
  600. IID_IDispatch,
  601. _Credentials,
  602. (void **)ppDispatch
  603. );
  604. BAIL_IF_ERROR(hr);
  605. _dwCompObjectCurrentEntry++;
  606. RRETURN(S_OK);
  607. cleanup:
  608. *ppDispatch = NULL;
  609. RRETURN(S_FALSE);
  610. }
  611. HRESULT
  612. CWinNTDomainEnum::GetGlobalGroupObject(
  613. IDispatch ** ppDispatch
  614. )
  615. {
  616. HRESULT hr = S_OK;
  617. LPWINNT_GROUP pWinNTGrp = NULL;
  618. LPBYTE pBuffer = NULL;
  619. DWORD dwReturned = 0;
  620. BOOL dwRet = 0;
  621. if (!_hGGroupComputer) {
  622. dwRet = WinNTComputerOpen(
  623. _DomainName,
  624. (_szDomainPDCName + 2),
  625. WINNT_DOMAIN_ID,
  626. &_hGGroupComputer
  627. );
  628. if (!dwRet) {
  629. goto error;
  630. }
  631. }
  632. dwRet = WinNTEnumGlobalGroups(
  633. _hGGroupComputer,
  634. 1,
  635. &pBuffer,
  636. &dwReturned
  637. );
  638. if (!dwRet) {
  639. goto error;
  640. }
  641. pWinNTGrp = (LPWINNT_GROUP)pBuffer;
  642. hr = CWinNTGroup::CreateGroup(
  643. pWinNTGrp->Parent,
  644. WINNT_DOMAIN_ID,
  645. pWinNTGrp->Domain,
  646. pWinNTGrp->Computer,
  647. pWinNTGrp->Name,
  648. WINNT_GROUP_GLOBAL,
  649. ADS_OBJECT_BOUND,
  650. IID_IDispatch,
  651. _Credentials,
  652. (void **)ppDispatch
  653. );
  654. BAIL_ON_FAILURE(hr);
  655. hr = S_OK;
  656. cleanup:
  657. if (pBuffer) {
  658. FreeADsMem(pBuffer);
  659. }
  660. RRETURN(hr);
  661. error:
  662. *ppDispatch = NULL;
  663. hr = S_FALSE;
  664. goto cleanup;
  665. }
  666. HRESULT
  667. CWinNTDomainEnum::GetLocalGroupObject(
  668. IDispatch ** ppDispatch
  669. )
  670. {
  671. HRESULT hr = S_OK;
  672. LPWINNT_GROUP pWinNTGrp = NULL;
  673. LPBYTE pBuffer = NULL;
  674. DWORD dwReturned = 0;
  675. BOOL dwRet = 0;
  676. if (!_hLGroupComputer) {
  677. dwRet = WinNTComputerOpen(
  678. _DomainName,
  679. (_szDomainPDCName + 2),
  680. WINNT_DOMAIN_ID,
  681. &_hLGroupComputer
  682. );
  683. if (!dwRet) {
  684. goto error;
  685. }
  686. }
  687. dwRet = WinNTEnumLocalGroups(
  688. _hLGroupComputer,
  689. 1,
  690. &pBuffer,
  691. &dwReturned
  692. );
  693. if (!dwRet) {
  694. goto error;
  695. }
  696. pWinNTGrp = (LPWINNT_GROUP)pBuffer;
  697. hr = CWinNTGroup::CreateGroup(
  698. pWinNTGrp->Parent,
  699. WINNT_DOMAIN_ID,
  700. pWinNTGrp->Domain,
  701. pWinNTGrp->Computer,
  702. pWinNTGrp->Name,
  703. WINNT_GROUP_LOCAL,
  704. ADS_OBJECT_BOUND,
  705. IID_IDispatch,
  706. _Credentials,
  707. (void **)ppDispatch
  708. );
  709. BAIL_ON_FAILURE(hr);
  710. hr = S_OK;
  711. cleanup:
  712. if (pBuffer) {
  713. FreeADsMem(pBuffer);
  714. }
  715. RRETURN(hr);
  716. error:
  717. *ppDispatch = NULL;
  718. hr = S_FALSE;
  719. goto cleanup;
  720. }
  721. HRESULT
  722. CWinNTDomainEnum::EnumGroupObjects(
  723. DWORD ObjectType,
  724. ULONG cElements,
  725. VARIANT FAR * pvar,
  726. ULONG FAR * pcElementFetched
  727. )
  728. {
  729. HRESULT hr;
  730. switch (ObjectType) {
  731. case WINNT_GROUP_GLOBAL:
  732. hr = EnumGlobalGroups(cElements, pvar, pcElementFetched);
  733. break;
  734. case WINNT_GROUP_LOCAL:
  735. hr = EnumLocalGroups(cElements, pvar, pcElementFetched);
  736. break;
  737. default:
  738. hr = S_FALSE;
  739. break;
  740. }
  741. RRETURN(hr);
  742. }
  743. ULONG GroupTypeArray[] = {WINNT_GROUP_GLOBAL, WINNT_GROUP_LOCAL, 0xFFFFFFFF};
  744. HRESULT
  745. CWinNTDomainEnum::EnumGroups(
  746. ULONG cElements,
  747. VARIANT FAR* pvar,
  748. ULONG FAR* pcElementFetched
  749. )
  750. {
  751. DWORD i;
  752. ULONG cRequested = 0;
  753. ULONG cFetchedByPath = 0;
  754. ULONG cTotalFetched = 0;
  755. VARIANT FAR* pPathvar = pvar;
  756. HRESULT hr = S_OK;
  757. DWORD ObjectType;
  758. if(!_fIsDomain){
  759. RRETURN(S_FALSE);
  760. }
  761. for (i = 0; i < cElements; i++) {
  762. VariantInit(&pvar[i]);
  763. }
  764. cRequested = cElements;
  765. while ((GroupTypeArray[_dwGroupArrayIndex] != (ULONG)-1) &&
  766. ((hr = EnumGroupObjects(
  767. GroupTypeArray[_dwGroupArrayIndex],
  768. cRequested,
  769. pPathvar,
  770. &cFetchedByPath)) == S_FALSE )) {
  771. pPathvar += cFetchedByPath;
  772. cRequested -= cFetchedByPath;
  773. cTotalFetched += cFetchedByPath;
  774. cFetchedByPath = 0;
  775. if (GroupTypeArray[_dwGroupArrayIndex++] == (ULONG)-1){
  776. if (pcElementFetched)
  777. *pcElementFetched = cTotalFetched;
  778. RRETURN(S_FALSE);
  779. }
  780. }
  781. if (pcElementFetched) {
  782. *pcElementFetched = cTotalFetched + cFetchedByPath;
  783. }
  784. RRETURN(hr);
  785. }
  786. HRESULT
  787. CWinNTDomainEnum::EnumGlobalGroups(
  788. ULONG cElements,
  789. VARIANT FAR* pvar,
  790. ULONG FAR* pcElementFetched
  791. )
  792. {
  793. HRESULT hr = S_OK;
  794. IDispatch *pDispatch = NULL;
  795. DWORD i = 0;
  796. while (i < cElements) {
  797. hr = GetGlobalGroupObject(&pDispatch);
  798. if (hr == S_FALSE) {
  799. break;
  800. }
  801. VariantInit(&pvar[i]);
  802. pvar[i].vt = VT_DISPATCH;
  803. pvar[i].pdispVal = pDispatch;
  804. (*pcElementFetched)++;
  805. i++;
  806. }
  807. return(hr);
  808. }
  809. HRESULT
  810. CWinNTDomainEnum::EnumLocalGroups(
  811. ULONG cElements,
  812. VARIANT FAR* pvar,
  813. ULONG FAR* pcElementFetched
  814. )
  815. {
  816. HRESULT hr = S_OK;
  817. IDispatch *pDispatch = NULL;
  818. DWORD i = 0;
  819. while (i < cElements) {
  820. hr = GetLocalGroupObject(&pDispatch);
  821. if (hr == S_FALSE) {
  822. break;
  823. }
  824. VariantInit(&pvar[i]);
  825. pvar[i].vt = VT_DISPATCH;
  826. pvar[i].pdispVal = pDispatch;
  827. (*pcElementFetched)++;
  828. i++;
  829. }
  830. return(hr);
  831. }