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.

1154 lines
25 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995
  5. //
  6. // File: cgroup.cxx
  7. //
  8. // Contents: Group object
  9. //
  10. // History: 11-1-95 krishnag Created.
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "winnt.hxx"
  14. #pragma hdrstop
  15. // Class CWinNTGroup -> GlobalGroup DS class
  16. DEFINE_IDispatch_ExtMgr_Implementation(CWinNTGroup)
  17. DEFINE_IADsExtension_ExtMgr_Implementation(CWinNTGroup)
  18. DEFINE_IADs_TempImplementation(CWinNTGroup)
  19. DEFINE_IADs_PutGetImplementation(CWinNTGroup,GroupClass,gdwGroupTableSize)
  20. DEFINE_IADsPropertyList_Implementation(CWinNTGroup, GroupClass,gdwGroupTableSize)
  21. CWinNTGroup::CWinNTGroup():
  22. _pDispMgr(NULL),
  23. _pExtMgr(NULL),
  24. _pPropertyCache(NULL),
  25. _ParentType(0),
  26. _DomainName(NULL),
  27. _ServerName(NULL)
  28. {
  29. ENLIST_TRACKING(CWinNTGroup);
  30. }
  31. HRESULT
  32. CWinNTGroup::CreateGroup(
  33. BSTR Parent,
  34. ULONG ParentType,
  35. BSTR DomainName,
  36. BSTR ServerName,
  37. BSTR GroupName,
  38. ULONG GroupType,
  39. DWORD dwObjectState,
  40. PSID pSid, // OPTIONAL
  41. REFIID riid,
  42. CWinNTCredentials& Credentials,
  43. void **ppvObj
  44. )
  45. {
  46. CWinNTGroup FAR * pGroup = NULL;
  47. HRESULT hr = S_OK;
  48. BOOL fAccountSid = TRUE;
  49. hr = AllocateGroupObject(&pGroup);
  50. BAIL_ON_FAILURE(hr);
  51. ADsAssert(pGroup->_pDispMgr);
  52. hr = pGroup->InitializeCoreObject(
  53. Parent,
  54. GroupName,
  55. GROUP_CLASS_NAME,
  56. GROUP_SCHEMA_NAME,
  57. CLSID_WinNTGroup,
  58. dwObjectState
  59. );
  60. BAIL_ON_FAILURE(hr);
  61. hr = ADsAllocString(DomainName, &pGroup->_DomainName);
  62. BAIL_ON_FAILURE(hr);
  63. hr = ADsAllocString(ServerName, &pGroup->_ServerName);
  64. BAIL_ON_FAILURE(hr);
  65. pGroup->_ParentType = ParentType;
  66. pGroup->_GroupType = GroupType;
  67. hr = SetDWORDPropertyInCache(
  68. pGroup->_pPropertyCache,
  69. TEXT("groupType"),
  70. GroupType,
  71. TRUE // fExplicit
  72. );
  73. BAIL_ON_FAILURE(hr);
  74. //
  75. // Try to determine if object corresponds to a account
  76. // domain
  77. //
  78. if (pSid) {
  79. //
  80. // A domain account sid has:
  81. // (1) a identifier authority of SECURITY_NT_AUTHORITY
  82. // (2) at least one subauth identifier
  83. // (3) the first subauth identifier is SECURITY_NT_NON_UNIQUE
  84. //
  85. PSID_IDENTIFIER_AUTHORITY pSidIdentAuth = NULL;
  86. SID_IDENTIFIER_AUTHORITY NtAuthIdentAuth = SECURITY_NT_AUTHORITY;
  87. PDWORD pdwSidSubAuth = NULL;
  88. fAccountSid = FALSE;
  89. pSidIdentAuth = GetSidIdentifierAuthority(pSid);
  90. ADsAssert(pSidIdentAuth);
  91. if (memcmp(pSidIdentAuth, &NtAuthIdentAuth, sizeof(SID_IDENTIFIER_AUTHORITY)) == 0) {
  92. if (GetSidSubAuthorityCount(pSid) > 0) {
  93. pdwSidSubAuth = GetSidSubAuthority(pSid, 0);
  94. ADsAssert(pdwSidSubAuth);
  95. if (*pdwSidSubAuth == SECURITY_NT_NON_UNIQUE) {
  96. fAccountSid = TRUE;
  97. }
  98. }
  99. }
  100. }
  101. pGroup->_Credentials = Credentials;
  102. hr = pGroup->_Credentials.Ref(ServerName, DomainName, ParentType);
  103. if (fAccountSid) {
  104. //
  105. // We permit this to fail if we can determine it is not a account
  106. // sid, since we won't be able to ref credentials on a non-existent
  107. // pseudo-domain like NT AUTHORITY (e.g., the well-known sids)
  108. //
  109. BAIL_ON_FAILURE(hr);
  110. }
  111. //
  112. // Load ext mgr and extensions
  113. //
  114. hr = ADSILoadExtensionManager(
  115. GROUP_CLASS_NAME,
  116. (IADsGroup *) pGroup,
  117. pGroup->_pDispMgr,
  118. Credentials,
  119. &pGroup->_pExtMgr
  120. );
  121. BAIL_ON_FAILURE(hr);
  122. ADsAssert(pGroup->_pExtMgr);
  123. //
  124. // Prepopulate the object
  125. //
  126. hr = pGroup->Prepopulate(TRUE,
  127. pSid);
  128. BAIL_ON_FAILURE(hr);
  129. // check if the call is from UMI
  130. if(Credentials.GetFlags() & ADS_AUTH_RESERVED) {
  131. //
  132. // we do not pass riid to InitUmiObject below. This is because UMI object
  133. // does not support IDispatch. There are several places in ADSI code where
  134. // riid passed into this function is defaulted to IID_IDispatch -
  135. // IADsContainer::Create for example. To handle these cases, we always
  136. // request IID_IUnknown from the UMI object. Subsequent code within UMI
  137. // will QI for the appropriate interface.
  138. //
  139. if(3 == pGroup->_dwNumComponents) {
  140. pGroup->_CompClasses[0] = L"Domain";
  141. pGroup->_CompClasses[1] = L"Computer";
  142. pGroup->_CompClasses[2] = L"Group";
  143. }
  144. else if(2 == pGroup->_dwNumComponents) {
  145. if(NULL == DomainName) {
  146. // workstation services not started. See getobj.cxx.
  147. pGroup->_CompClasses[0] = L"Computer";
  148. pGroup->_CompClasses[1] = L"Group";
  149. }
  150. else if(NULL == ServerName) {
  151. pGroup->_CompClasses[0] = L"Domain";
  152. pGroup->_CompClasses[1] = L"Group";
  153. }
  154. else
  155. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  156. }
  157. else
  158. BAIL_ON_FAILURE(hr = UMI_E_FAIL);
  159. hr = pGroup->InitUmiObject(
  160. pGroup->_Credentials,
  161. GroupClass,
  162. gdwGroupTableSize,
  163. pGroup->_pPropertyCache,
  164. (IUnknown *) (INonDelegatingUnknown *) pGroup,
  165. pGroup->_pExtMgr,
  166. IID_IUnknown,
  167. ppvObj
  168. );
  169. BAIL_ON_FAILURE(hr);
  170. //
  171. // UMI object was created and the interface was obtained successfully.
  172. // UMI object now has a reference to the inner unknown of IADs, since
  173. // the call to Release() below is not going to be made in this case.
  174. //
  175. RRETURN(hr);
  176. }
  177. hr = pGroup->QueryInterface(riid, ppvObj);
  178. BAIL_ON_FAILURE(hr);
  179. pGroup->Release();
  180. RRETURN(hr);
  181. error:
  182. delete pGroup;
  183. RRETURN_EXP_IF_ERR(hr);
  184. }
  185. HRESULT
  186. CWinNTGroup::CreateGroup(
  187. BSTR Parent,
  188. ULONG ParentType,
  189. BSTR DomainName,
  190. BSTR ServerName,
  191. BSTR GroupName,
  192. ULONG GroupType,
  193. DWORD dwObjectState,
  194. REFIID riid,
  195. CWinNTCredentials& Credentials,
  196. void **ppvObj
  197. )
  198. {
  199. HRESULT hr = S_OK;
  200. hr = CWinNTGroup::CreateGroup(
  201. Parent,
  202. ParentType,
  203. DomainName,
  204. ServerName,
  205. GroupName,
  206. GroupType,
  207. dwObjectState,
  208. NULL,
  209. riid,
  210. Credentials,
  211. ppvObj
  212. );
  213. RRETURN_EXP_IF_ERR(hr);
  214. }
  215. CWinNTGroup::~CWinNTGroup( )
  216. {
  217. ADsFreeString(_DomainName);
  218. ADsFreeString(_ServerName);
  219. delete _pExtMgr; // created last, destroyed first
  220. delete _pDispMgr;
  221. delete _pPropertyCache;
  222. }
  223. //----------------------------------------------------------------------------
  224. // Function: QueryInterface
  225. //
  226. // Synopsis: If this object is aggregated within another object, then
  227. // all calls will delegate to the outer object. Otherwise, the
  228. // non-delegating QI is called
  229. //
  230. // Arguments:
  231. //
  232. // iid interface requested
  233. // ppInterface Returns pointer to interface requested. NULL if interface
  234. // is not supported.
  235. //
  236. // Returns: S_OK on success. Error code otherwise.
  237. //
  238. // Modifies: *ppInterface to return interface pointer
  239. //
  240. //----------------------------------------------------------------------------
  241. STDMETHODIMP CWinNTGroup::QueryInterface(
  242. REFIID iid,
  243. LPVOID *ppInterface
  244. )
  245. {
  246. if(_pUnkOuter != NULL)
  247. RRETURN(_pUnkOuter->QueryInterface(
  248. iid,
  249. ppInterface
  250. ));
  251. RRETURN(NonDelegatingQueryInterface(
  252. iid,
  253. ppInterface
  254. ));
  255. }
  256. //----------------------------------------------------------------------------
  257. // Function: AddRef
  258. //
  259. // Synopsis: IUnknown::AddRef. If this object is aggregated within
  260. // another, all calls will delegate to the outer object.
  261. // Otherwise, the non-delegating AddRef is called
  262. //
  263. // Arguments:
  264. //
  265. // None
  266. //
  267. // Returns: New reference count
  268. //
  269. // Modifies: Nothing
  270. //
  271. //----------------------------------------------------------------------------
  272. STDMETHODIMP_(ULONG) CWinNTGroup::AddRef(void)
  273. {
  274. if(_pUnkOuter != NULL)
  275. RRETURN(_pUnkOuter->AddRef());
  276. RRETURN(NonDelegatingAddRef());
  277. }
  278. //----------------------------------------------------------------------------
  279. // Function: Release
  280. //
  281. // Synopsis: IUnknown::Release. If this object is aggregated within
  282. // another, all calls will delegate to the outer object.
  283. // Otherwise, the non-delegating Release is called
  284. //
  285. // Arguments:
  286. //
  287. // None
  288. //
  289. // Returns: New reference count
  290. //
  291. // Modifies: Nothing
  292. //
  293. //----------------------------------------------------------------------------
  294. STDMETHODIMP_(ULONG) CWinNTGroup::Release(void)
  295. {
  296. if(_pUnkOuter != NULL)
  297. RRETURN(_pUnkOuter->Release());
  298. RRETURN(NonDelegatingRelease());
  299. }
  300. //----------------------------------------------------------------------------
  301. STDMETHODIMP
  302. CWinNTGroup::NonDelegatingQueryInterface(
  303. REFIID iid,
  304. LPVOID FAR* ppv
  305. )
  306. {
  307. HRESULT hr = S_OK;
  308. if (ppv == NULL) {
  309. RRETURN(E_POINTER);
  310. }
  311. if (IsEqualIID(iid, IID_IUnknown))
  312. {
  313. *ppv = (IADsGroup FAR *) this;
  314. }
  315. else if (IsEqualIID(iid, IID_IADsGroup))
  316. {
  317. *ppv = (IADsGroup FAR *) this;
  318. }
  319. else if (IsEqualIID(iid, IID_IADs))
  320. {
  321. *ppv = (IADsGroup FAR *) this;
  322. }
  323. else if (IsEqualIID(iid, IID_IADsPropertyList))
  324. {
  325. *ppv = (IADsPropertyList FAR *) this;
  326. }
  327. else if (IsEqualIID(iid, IID_IDispatch))
  328. {
  329. *ppv = (IADsGroup FAR *) this;
  330. }
  331. else if (IsEqualIID(iid, IID_ISupportErrorInfo))
  332. {
  333. *ppv = (ISupportErrorInfo FAR *) this;
  334. }
  335. else if( (_pDispatch != NULL) &&
  336. IsEqualIID(iid, IID_IADsExtension) )
  337. {
  338. *ppv = (IADsExtension *) this;
  339. }
  340. else if (_pExtMgr)
  341. {
  342. RRETURN( _pExtMgr->QueryInterface(iid, ppv));
  343. }
  344. else
  345. {
  346. *ppv = NULL;
  347. return E_NOINTERFACE;
  348. }
  349. AddRef();
  350. return NOERROR;
  351. }
  352. /* ISupportErrorInfo method */
  353. STDMETHODIMP
  354. CWinNTGroup::InterfaceSupportsErrorInfo(
  355. THIS_ REFIID riid
  356. )
  357. {
  358. if (IsEqualIID(riid, IID_IADs) ||
  359. IsEqualIID(riid, IID_IADsGroup) ||
  360. IsEqualIID(riid, IID_IADsPropertyList)) {
  361. RRETURN(S_OK);
  362. } else {
  363. RRETURN(S_FALSE);
  364. }
  365. }
  366. /* IADs methods */
  367. STDMETHODIMP
  368. CWinNTGroup::SetInfo(THIS)
  369. {
  370. HRESULT hr;
  371. NET_API_STATUS nasStatus;
  372. WCHAR szHostServerName[MAX_PATH];
  373. LPBYTE lpBuffer = NULL;
  374. DWORD dwGroupType = _GroupType;
  375. //
  376. // We need to see if the cache has changed a value for
  377. // groupType and use that info down the line.
  378. //
  379. hr = GetDWORDPropertyFromCache(
  380. _pPropertyCache,
  381. TEXT("groupType"),
  382. &dwGroupType
  383. );
  384. if (SUCCEEDED(hr)) {
  385. //
  386. // Verify the value
  387. //
  388. if ((dwGroupType != WINNT_GROUP_LOCAL)
  389. && (dwGroupType != WINNT_GROUP_GLOBAL)) {
  390. //
  391. // This is bad value so we need to BAIL
  392. //
  393. hr = E_ADS_BAD_PARAMETER;
  394. }
  395. else {
  396. if (GetObjectState() == ADS_OBJECT_UNBOUND)
  397. _GroupType = dwGroupType;
  398. else
  399. if (_GroupType != dwGroupType) {
  400. hr = E_ADS_BAD_PARAMETER;
  401. }
  402. }
  403. } else {
  404. dwGroupType = _GroupType;
  405. hr = S_OK;
  406. }
  407. BAIL_ON_FAILURE(hr);
  408. if (_ParentType == WINNT_DOMAIN_ID) {
  409. hr = WinNTGetCachedDCName(
  410. _DomainName,
  411. szHostServerName,
  412. _Credentials.GetFlags()
  413. );
  414. } else {
  415. hr = MakeUncName(
  416. _ServerName,
  417. szHostServerName
  418. );
  419. }
  420. BAIL_ON_FAILURE(hr);
  421. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  422. if (dwGroupType == WINNT_GROUP_GLOBAL) {
  423. if (_ParentType == WINNT_DOMAIN_ID) {
  424. hr = WinNTCreateGlobalGroup(
  425. szHostServerName + 2,
  426. _Name
  427. );
  428. BAIL_ON_FAILURE(hr);
  429. }else {
  430. hr = WinNTCreateGlobalGroup(
  431. _ServerName,
  432. _Name
  433. );
  434. BAIL_ON_FAILURE(hr);
  435. }
  436. }
  437. else {
  438. //
  439. // Group type has to be local
  440. //
  441. hr = WinNTCreateLocalGroup(
  442. szHostServerName + 2,
  443. _Name
  444. );
  445. BAIL_ON_FAILURE(hr);
  446. }
  447. SetObjectState(ADS_OBJECT_BOUND);
  448. } // if Object not bound
  449. if (dwGroupType == WINNT_GROUP_GLOBAL) {
  450. nasStatus = NetGroupGetInfo(
  451. szHostServerName,
  452. _Name,
  453. 1,
  454. &lpBuffer
  455. );
  456. } else {
  457. nasStatus = NetLocalGroupGetInfo(
  458. szHostServerName,
  459. _Name,
  460. 1,
  461. &lpBuffer
  462. );
  463. }
  464. hr = HRESULT_FROM_WIN32(nasStatus);
  465. BAIL_ON_FAILURE(hr);
  466. hr = Marshall_Set_Level1(
  467. szHostServerName,
  468. TRUE,
  469. lpBuffer
  470. );
  471. BAIL_ON_FAILURE(hr);
  472. if(SUCCEEDED(hr))
  473. _pPropertyCache->ClearModifiedFlags();
  474. //
  475. // objectSid not writable
  476. //
  477. error:
  478. if (lpBuffer) {
  479. NetApiBufferFree(lpBuffer);
  480. }
  481. RRETURN_EXP_IF_ERR(hr);
  482. }
  483. STDMETHODIMP
  484. CWinNTGroup::GetInfo(THIS)
  485. {
  486. HRESULT hr;
  487. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  488. RRETURN_EXP_IF_ERR(E_ADS_OBJECT_UNBOUND);
  489. }
  490. _pPropertyCache->flushpropcache();
  491. //
  492. // Need to add the group type attribute here.
  493. //
  494. hr = SetDWORDPropertyInCache(
  495. _pPropertyCache,
  496. TEXT("groupType"),
  497. _GroupType,
  498. TRUE // fExplicit
  499. );
  500. //
  501. // GROUP_INFO
  502. //
  503. hr = GetInfo(1, TRUE);
  504. BAIL_ON_FAILURE(hr);
  505. //
  506. // objectSid
  507. //
  508. hr = GetInfo(20, TRUE);
  509. error :
  510. RRETURN(hr);
  511. }
  512. STDMETHODIMP
  513. CWinNTGroup::ImplicitGetInfo(THIS)
  514. {
  515. HRESULT hr;
  516. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  517. RRETURN_EXP_IF_ERR(E_ADS_OBJECT_UNBOUND);
  518. }
  519. //
  520. // Need to add the group type attribute here.
  521. //
  522. hr = SetDWORDPropertyInCache(
  523. _pPropertyCache,
  524. TEXT("groupType"),
  525. _GroupType,
  526. FALSE // fExplicit
  527. );
  528. //
  529. // GROUP_INFO
  530. //
  531. hr = GetInfo(1, FALSE);
  532. BAIL_ON_FAILURE(hr);
  533. //
  534. // objectSid
  535. //
  536. hr = GetInfo(20, FALSE);
  537. error :
  538. RRETURN(hr);
  539. }
  540. HRESULT
  541. CWinNTGroup::AllocateGroupObject(
  542. CWinNTGroup ** ppGroup
  543. )
  544. {
  545. CWinNTGroup FAR * pGroup = NULL;
  546. CAggregatorDispMgr FAR * pDispMgr = NULL;
  547. CPropertyCache FAR * pPropertyCache = NULL;
  548. HRESULT hr = S_OK;
  549. pGroup = new CWinNTGroup();
  550. if (pGroup == NULL) {
  551. hr = E_OUTOFMEMORY;
  552. }
  553. BAIL_ON_FAILURE(hr);
  554. pDispMgr = new CAggregatorDispMgr;
  555. if (pDispMgr == NULL) {
  556. hr = E_OUTOFMEMORY;
  557. }
  558. BAIL_ON_FAILURE(hr);
  559. hr = LoadTypeInfoEntry(
  560. pDispMgr,
  561. LIBID_ADs,
  562. IID_IADsGroup,
  563. (IADsGroup *)pGroup,
  564. DISPID_REGULAR
  565. );
  566. BAIL_ON_FAILURE(hr);
  567. hr = LoadTypeInfoEntry(
  568. pDispMgr,
  569. LIBID_ADs,
  570. IID_IADsPropertyList,
  571. (IADsPropertyList *)pGroup,
  572. DISPID_VALUE
  573. );
  574. BAIL_ON_FAILURE(hr);
  575. hr = CPropertyCache::createpropertycache(
  576. GroupClass,
  577. gdwGroupTableSize,
  578. (CCoreADsObject *)pGroup,
  579. &pPropertyCache
  580. );
  581. BAIL_ON_FAILURE(hr);
  582. pDispMgr->RegisterPropertyCache(
  583. pPropertyCache
  584. );
  585. pGroup->_pPropertyCache = pPropertyCache;
  586. pGroup->_pDispMgr = pDispMgr;
  587. *ppGroup = pGroup;
  588. RRETURN(hr);
  589. error:
  590. delete pPropertyCache;
  591. delete pDispMgr;
  592. delete pGroup;
  593. RRETURN(hr);
  594. }
  595. //
  596. // For current implementation in clocgroup:
  597. // If this function is called as a public function (ie. by another
  598. // modual/class), fExplicit must be FALSE since the cache is NOT
  599. // flushed in this function.
  600. //
  601. // External functions should ONLY call GetInfo(no param) for explicit
  602. // GetInfo. This will flush the cache properly.
  603. //
  604. STDMETHODIMP
  605. CWinNTGroup::GetInfo(
  606. THIS_ DWORD dwApiLevel,
  607. BOOL fExplicit
  608. )
  609. {
  610. HRESULT hr=E_FAIL;
  611. switch (dwApiLevel) {
  612. case 1:
  613. hr = GetStandardInfo(
  614. dwApiLevel,
  615. fExplicit
  616. );
  617. RRETURN_EXP_IF_ERR(hr);
  618. case 20:
  619. hr = GetSidInfo(
  620. fExplicit
  621. );
  622. RRETURN_EXP_IF_ERR(hr);
  623. default:
  624. RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
  625. }
  626. }
  627. HRESULT
  628. CWinNTGroup::GetStandardInfo(
  629. DWORD dwApiLevel,
  630. BOOL fExplicit
  631. )
  632. {
  633. NET_API_STATUS nasStatus;
  634. LPBYTE lpBuffer = NULL;
  635. HRESULT hr;
  636. WCHAR szHostServerName[MAX_PATH];
  637. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  638. RRETURN_EXP_IF_ERR(E_ADS_OBJECT_UNBOUND);
  639. }
  640. if (_ParentType == WINNT_DOMAIN_ID) {
  641. hr = WinNTGetCachedDCName(
  642. _DomainName,
  643. szHostServerName,
  644. _Credentials.GetFlags()
  645. );
  646. BAIL_ON_FAILURE(hr);
  647. }else {
  648. hr = MakeUncName(
  649. _ServerName,
  650. szHostServerName
  651. );
  652. BAIL_ON_FAILURE(hr);
  653. }
  654. //
  655. // Since the object is bound, the groupType has to be
  656. // _GroupType and cannot change.
  657. //
  658. if (_GroupType == WINNT_GROUP_GLOBAL) {
  659. nasStatus = NetGroupGetInfo(
  660. szHostServerName,
  661. _Name,
  662. dwApiLevel,
  663. &lpBuffer
  664. );
  665. } else {
  666. nasStatus = NetLocalGroupGetInfo(
  667. szHostServerName,
  668. _Name,
  669. dwApiLevel,
  670. &lpBuffer
  671. );
  672. }
  673. hr = HRESULT_FROM_WIN32(nasStatus);
  674. BAIL_ON_FAILURE(hr);
  675. hr = UnMarshall(
  676. lpBuffer,
  677. dwApiLevel,
  678. fExplicit
  679. );
  680. BAIL_ON_FAILURE(hr);
  681. error:
  682. if (lpBuffer) {
  683. NetApiBufferFree(lpBuffer);
  684. }
  685. RRETURN_EXP_IF_ERR(hr);
  686. }
  687. HRESULT
  688. CWinNTGroup::UnMarshall(
  689. LPBYTE lpBuffer,
  690. DWORD dwApiLevel,
  691. BOOL fExplicit
  692. )
  693. {
  694. HRESULT hr;
  695. ADsAssert(lpBuffer);
  696. switch (dwApiLevel) {
  697. case 1:
  698. hr = UnMarshall_Level1(fExplicit, lpBuffer);
  699. break;
  700. default:
  701. hr = E_FAIL;
  702. }
  703. RRETURN_EXP_IF_ERR(hr);
  704. }
  705. HRESULT
  706. CWinNTGroup::UnMarshall_Level1(BOOL fExplicit, LPBYTE pBuffer)
  707. {
  708. BSTR bstrData = NULL;
  709. LPGROUP_INFO_1 pGroupInfo1 = NULL;
  710. LPLOCALGROUP_INFO_1 pLocalGroupInfo1 = NULL;
  711. HRESULT hr = S_OK;
  712. hr = SetLPTSTRPropertyInCache(
  713. _pPropertyCache,
  714. TEXT("Name"),
  715. _Name,
  716. fExplicit
  717. );
  718. if (_GroupType == WINNT_GROUP_GLOBAL) {
  719. pGroupInfo1 = (LPGROUP_INFO_1)pBuffer;
  720. hr = SetLPTSTRPropertyInCache(
  721. _pPropertyCache,
  722. TEXT("Description"),
  723. pGroupInfo1->grpi1_comment,
  724. fExplicit
  725. );
  726. }
  727. else {
  728. pLocalGroupInfo1 = (LPLOCALGROUP_INFO_1) pBuffer;
  729. hr = SetLPTSTRPropertyInCache(
  730. _pPropertyCache,
  731. TEXT("Description"),
  732. pLocalGroupInfo1->lgrpi1_comment,
  733. fExplicit
  734. );
  735. }
  736. RRETURN(hr);
  737. }
  738. HRESULT
  739. CWinNTGroup::Prepopulate(
  740. BOOL fExplicit,
  741. PSID pSid // OPTIONAL
  742. )
  743. {
  744. HRESULT hr = S_OK;
  745. DWORD dwErr = 0;
  746. DWORD dwSidLength = 0;
  747. if (pSid) {
  748. //
  749. // On NT4 for some reason GetLengthSID does not set lasterror to 0
  750. //
  751. SetLastError(NO_ERROR);
  752. dwSidLength = GetLengthSid((PSID) pSid);
  753. //
  754. // This is an extra check to make sure that we have the
  755. // correct length.
  756. //
  757. dwErr = GetLastError();
  758. if (dwErr != NO_ERROR) {
  759. hr = HRESULT_FROM_WIN32(dwErr);
  760. BAIL_ON_FAILURE(hr);
  761. }
  762. hr = SetOctetPropertyInCache(
  763. _pPropertyCache,
  764. TEXT("objectSid"),
  765. (PBYTE) pSid,
  766. dwSidLength,
  767. TRUE
  768. );
  769. BAIL_ON_FAILURE(hr);
  770. }
  771. error:
  772. RRETURN(hr);
  773. }
  774. HRESULT
  775. CWinNTGroup::Marshall_Set_Level1(
  776. LPWSTR szHostServerName,
  777. BOOL fExplicit,
  778. LPBYTE pBuffer
  779. )
  780. {
  781. LPGROUP_INFO_1 pGroupInfo1 = NULL;
  782. LPLOCALGROUP_INFO_1 pLocalGroupInfo1 = NULL;
  783. HRESULT hr = S_OK;
  784. NET_API_STATUS nasStatus;
  785. DWORD dwParmErr;
  786. LPWSTR pszDescription = NULL;
  787. hr = GetLPTSTRPropertyFromCache(
  788. _pPropertyCache,
  789. TEXT("Description"),
  790. &pszDescription
  791. );
  792. if(SUCCEEDED(hr)) {
  793. if (_GroupType == WINNT_GROUP_GLOBAL) {
  794. // hr = UM_GET_BSTR_PROPERTY(_pGenInfo,Description, bstrData);
  795. //
  796. // This should in reality call a virtual function of a derived
  797. // class, beta fix!
  798. //
  799. pGroupInfo1 = (LPGROUP_INFO_1)pBuffer;
  800. pGroupInfo1->grpi1_comment = pszDescription;
  801. //
  802. // Now perform the Set call.
  803. //
  804. nasStatus = NetGroupSetInfo(
  805. szHostServerName,
  806. _Name,
  807. 1,
  808. (LPBYTE)pGroupInfo1,
  809. &dwParmErr
  810. );
  811. }
  812. else {
  813. pLocalGroupInfo1 = (LPLOCALGROUP_INFO_1)pBuffer;
  814. pLocalGroupInfo1->lgrpi1_comment = pszDescription;
  815. nasStatus = NetLocalGroupSetInfo(
  816. szHostServerName,
  817. _Name,
  818. 1,
  819. (LPBYTE)pLocalGroupInfo1,
  820. &dwParmErr
  821. );
  822. }
  823. hr = HRESULT_FROM_WIN32(nasStatus);
  824. BAIL_ON_FAILURE(hr);
  825. }else {
  826. //
  827. // This is because there is no data to marshall
  828. //
  829. hr = S_OK;
  830. }
  831. error:
  832. if (pszDescription) {
  833. FreeADsStr(pszDescription);
  834. }
  835. RRETURN(hr);
  836. }
  837. HRESULT
  838. CWinNTGroup::Marshall_Create_Level1(
  839. LPWSTR szHostServerName,
  840. LPGROUP_INFO_1 pGroupInfo1
  841. )
  842. {
  843. //
  844. // This routine is not called from anywhere ???
  845. //
  846. HRESULT hr = S_OK;
  847. NET_API_STATUS nasStatus = ERROR_INVALID_DATA;
  848. DWORD dwParmErr;
  849. if (_GroupType == WINNT_GROUP_GLOBAL) {
  850. pGroupInfo1->grpi1_name = _Name;
  851. pGroupInfo1->grpi1_comment = NULL;
  852. nasStatus = NetGroupAdd(
  853. szHostServerName,
  854. 1,
  855. (LPBYTE)pGroupInfo1,
  856. &dwParmErr
  857. );
  858. }
  859. else {
  860. ADsAssert(!"Group type is bad internally!");
  861. /*
  862. pLocalGroupInfo1->lgrp1_name = _Name;
  863. pLocalGroupInfo1->grp1_comment = NULL;
  864. nasStatus = NetLocalGroupAdd(
  865. szHostServerName,
  866. 1,
  867. (LPBYTE)pLocalGroupInfo1,
  868. &dwParmErr
  869. );
  870. */
  871. }
  872. hr = HRESULT_FROM_WIN32(nasStatus);
  873. BAIL_ON_FAILURE(hr);
  874. error:
  875. RRETURN(hr);
  876. }
  877. HRESULT
  878. CWinNTGroup::GetSidInfo(
  879. IN BOOL fExplicit
  880. )
  881. {
  882. HRESULT hr = E_FAIL;
  883. WCHAR szHostServerName[MAX_PATH];
  884. //
  885. // Get Server Name
  886. //
  887. if (_ParentType == WINNT_DOMAIN_ID) {
  888. hr = WinNTGetCachedDCName(
  889. _DomainName,
  890. szHostServerName,
  891. _Credentials.GetFlags()
  892. );
  893. BAIL_ON_FAILURE(hr);
  894. }else {
  895. hr = MakeUncName(
  896. _ServerName,
  897. szHostServerName
  898. );
  899. }
  900. //
  901. // Get Sid of this group and store in cache if fExplicit.
  902. //
  903. hr = GetSidIntoCache(
  904. szHostServerName,
  905. _Name,
  906. _pPropertyCache,
  907. fExplicit
  908. );
  909. BAIL_ON_FAILURE(hr);
  910. error:
  911. RRETURN(hr);
  912. }