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.

1007 lines
22 KiB

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