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.

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