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.

739 lines
17 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995
  5. //
  6. // File: cggi.cxx
  7. //
  8. // Contents: This file contains the Group Object's
  9. // IADsGroup and IADsGroupOperation methods
  10. //
  11. // History: 11-1-95 krishnag Created.
  12. //
  13. //----------------------------------------------------------------------------
  14. #include "winnt.hxx"
  15. #pragma hdrstop
  16. BOOL
  17. VerifyIfMember(
  18. BSTR bstrMember,
  19. VARIANT * VariantArray,
  20. ULONG cElementFetched
  21. );
  22. BOOL
  23. IsStringSID(LPWSTR pszStringSID);
  24. // Class CWinNTGroup
  25. STDMETHODIMP CWinNTGroup::get_Description(THIS_ BSTR FAR* retval)
  26. {
  27. GET_PROPERTY_BSTR((IADsGroup *)this,Description);
  28. }
  29. STDMETHODIMP CWinNTGroup::put_Description(THIS_ BSTR bstrDescription)
  30. {
  31. PUT_PROPERTY_BSTR((IADsGroup *)this,Description);
  32. }
  33. STDMETHODIMP
  34. CWinNTGroup::Members(
  35. THIS_ IADsMembers FAR* FAR* ppMembers
  36. )
  37. {
  38. HRESULT hr;
  39. WCHAR szHostServerName[MAX_PATH];
  40. NET_API_STATUS nasStatus = 0;
  41. if (_ParentType == WINNT_DOMAIN_ID) {
  42. hr = WinNTGetCachedDCName(
  43. _DomainName,
  44. szHostServerName,
  45. _Credentials.GetFlags()
  46. );
  47. BAIL_ON_FAILURE(hr);
  48. }
  49. if (_GroupType == WINNT_GROUP_GLOBAL) {
  50. hr = CWinNTGroupCollection::CreateGroupCollection(
  51. _Parent,
  52. _ParentType,
  53. _DomainName,
  54. _ParentType == WINNT_DOMAIN_ID ?
  55. (szHostServerName + 2) :
  56. _ServerName,
  57. _Name,
  58. _GroupType,
  59. IID_IADsMembers,
  60. _Credentials,
  61. (void **)ppMembers
  62. );
  63. } else {
  64. hr = CWinNTLocalGroupCollection::CreateGroupCollection(
  65. _Parent,
  66. _ParentType,
  67. _DomainName,
  68. _ParentType == WINNT_DOMAIN_ID ?
  69. (szHostServerName + 2) :
  70. _ServerName,
  71. _Name,
  72. _GroupType,
  73. IID_IADsMembers,
  74. _Credentials,
  75. (void **)ppMembers
  76. );
  77. }
  78. error:
  79. RRETURN_EXP_IF_ERR(hr);
  80. }
  81. STDMETHODIMP
  82. CWinNTGroup::IsMember(
  83. THIS_ BSTR bstrMember,
  84. VARIANT_BOOL FAR* bMember
  85. )
  86. {
  87. IADsMembers FAR * pMembers = NULL;
  88. IUnknown FAR * pUnknown = NULL;
  89. IEnumVARIANT FAR * pEnumVar = NULL;
  90. DWORD i = 0;
  91. HRESULT hr = S_OK;
  92. VARIANT_BOOL fMember = FALSE;
  93. VARIANT VariantArray[10];
  94. BOOL fContinue = TRUE;
  95. ULONG cElementFetched = 0;
  96. const DWORD dwMaxFailures = 1000;
  97. DWORD dwFailureCount = 0;
  98. hr = Members(
  99. &pMembers
  100. );
  101. BAIL_ON_FAILURE(hr);
  102. hr = pMembers->get__NewEnum(
  103. &pUnknown
  104. );
  105. BAIL_ON_FAILURE(hr);
  106. hr = pUnknown->QueryInterface(
  107. IID_IEnumVARIANT,
  108. (void **)&pEnumVar
  109. );
  110. BAIL_ON_FAILURE(hr);
  111. while (fContinue) {
  112. IADs *pObject ;
  113. //
  114. // Reset the fetched count in case the function fails.
  115. //
  116. cElementFetched = 0;
  117. hr = pEnumVar->Next(
  118. 10,
  119. VariantArray,
  120. &cElementFetched
  121. );
  122. if (FAILED(hr))
  123. {
  124. //
  125. // An error occurred, if we have exceeded our maximum number
  126. // of failures, give up and return. Otherwise just ignore
  127. // the error and try again.
  128. //
  129. if (dwMaxFailures < ++dwFailureCount)
  130. {
  131. //
  132. // The rest of the processing in the loop can be done because
  133. // it doesn't do any harm and will clean up any allocated objects.
  134. //
  135. fContinue = FALSE;
  136. hr = S_FALSE;
  137. }
  138. else
  139. {
  140. //
  141. // Reset hr to S_OK because we may have been returned valid data,
  142. // we don't really care about the error and we don't want to return
  143. // an error code if the data that we were returned is a match.
  144. // Just in case we were returned valid data, continue with the
  145. // rest of the processing.
  146. //
  147. hr = S_OK;
  148. }
  149. }
  150. else if (hr == S_FALSE) {
  151. fContinue = FALSE;
  152. //
  153. // Reset hr to S_OK, we want to return success
  154. //
  155. hr = S_OK;
  156. }
  157. fMember = (VARIANT_BOOL)VerifyIfMember(
  158. bstrMember,
  159. VariantArray,
  160. cElementFetched
  161. );
  162. if (fMember) {
  163. fContinue = FALSE;
  164. }
  165. for (i = 0; i < cElementFetched; i++ ) {
  166. IDispatch *pDispatch = NULL;
  167. pDispatch = VariantArray[i].pdispVal;
  168. pDispatch->Release();
  169. }
  170. memset(VariantArray, 0, sizeof(VARIANT)*10);
  171. }
  172. error:
  173. *bMember = fMember? VARIANT_TRUE : VARIANT_FALSE;
  174. if (pEnumVar) {
  175. pEnumVar->Release();
  176. }
  177. if (pUnknown) {
  178. pUnknown->Release();
  179. }
  180. if (pMembers) {
  181. pMembers->Release();
  182. }
  183. RRETURN_EXP_IF_ERR(hr);
  184. }
  185. STDMETHODIMP
  186. CWinNTGroup::Add(THIS_ BSTR bstrNewItem)
  187. {
  188. HRESULT hr;
  189. NET_API_STATUS nasStatus;
  190. LOCALGROUP_MEMBERS_INFO_3 Member;
  191. LPLOCALGROUP_MEMBERS_INFO_3 pMember = &Member;
  192. POBJECTINFO pObjectInfo = NULL;
  193. WCHAR szDomName[MAX_PATH];
  194. WCHAR szHostServerName[MAX_PATH];
  195. int iLastIndx = 0;
  196. BOOL fStringSID = FALSE;
  197. hr = BuildObjectInfo(
  198. bstrNewItem,
  199. &pObjectInfo
  200. );
  201. BAIL_ON_FAILURE(hr);
  202. iLastIndx = pObjectInfo->NumComponents - 1;
  203. //
  204. // If there is only one component, it has to be in the SID form
  205. // or it has to be a Special SID like everyone.
  206. //
  207. if (pObjectInfo->NumComponents == 1) {
  208. //
  209. // Check to see if this is S-12-11
  210. //
  211. fStringSID = IsStringSID(pObjectInfo->ComponentArray[0]);
  212. }
  213. memset(pMember, 0, sizeof(LOCALGROUP_MEMBERS_INFO_3));
  214. if (_ParentType == WINNT_COMPUTER_ID) {
  215. hr = MakeUncName(
  216. _ServerName,
  217. szHostServerName
  218. );
  219. BAIL_ON_FAILURE(hr);
  220. }else if (_ParentType == WINNT_DOMAIN_ID){
  221. hr = WinNTGetCachedDCName(
  222. _DomainName,
  223. szHostServerName,
  224. _Credentials.GetFlags()
  225. );
  226. BAIL_ON_FAILURE(hr);
  227. }
  228. if (_GroupType == WINNT_GROUP_GLOBAL) {
  229. #ifdef WIN95
  230. if (_wcsicmp(pObjectInfo->ComponentArray[0], _DomainName)) {
  231. #else
  232. if (CompareStringW(
  233. LOCALE_SYSTEM_DEFAULT,
  234. NORM_IGNORECASE,
  235. pObjectInfo->ComponentArray[0],
  236. -1,
  237. _DomainName,
  238. -1
  239. ) != CSTR_EQUAL ) {
  240. #endif
  241. hr = E_ADS_INVALID_USER_OBJECT;
  242. BAIL_ON_FAILURE(hr);
  243. }
  244. nasStatus = NetGroupAddUser(
  245. szHostServerName,
  246. _Name,
  247. pObjectInfo->ComponentArray[(
  248. pObjectInfo->NumComponents - 1)]
  249. );
  250. hr = HRESULT_FROM_WIN32(nasStatus);
  251. BAIL_ON_FAILURE(hr);
  252. }else if (_GroupType == WINNT_GROUP_LOCAL){
  253. if (fStringSID) {
  254. hr = AddBySID(
  255. pObjectInfo->ComponentArray[0],
  256. szHostServerName
  257. );
  258. goto error;
  259. }
  260. //
  261. // 0 implies special sid name.
  262. //
  263. if (iLastIndx != 0) {
  264. hr = MakeWinNTAccountName(pObjectInfo, szDomName, FALSE);
  265. BAIL_ON_FAILURE(hr);
  266. pMember->lgrmi3_domainandname = szDomName;
  267. }
  268. else {
  269. pMember->lgrmi3_domainandname =
  270. pObjectInfo->ComponentArray[iLastIndx];
  271. }
  272. //
  273. // For performance reasos we will first assume that the
  274. // use has domain name
  275. //
  276. nasStatus = NetLocalGroupAddMembers(
  277. szHostServerName,
  278. _Name,
  279. 3,
  280. (LPBYTE)pMember,
  281. 1
  282. );
  283. if (nasStatus == ERROR_NO_SUCH_MEMBER) {
  284. //
  285. // Try with true to see if that makes a difference
  286. //
  287. hr = MakeWinNTAccountName(pObjectInfo, szDomName, TRUE);
  288. if (SUCCEEDED(hr)) {
  289. //
  290. // Try again with this value
  291. //
  292. pMember->lgrmi3_domainandname = szDomName;
  293. nasStatus = NetLocalGroupAddMembers(
  294. szHostServerName,
  295. _Name,
  296. 3,
  297. (LPBYTE)pMember,
  298. 1
  299. );
  300. }
  301. }
  302. //
  303. // Either way nasStatus will have the correct value
  304. //
  305. hr = HRESULT_FROM_WIN32(nasStatus);
  306. BAIL_ON_FAILURE(hr);
  307. }
  308. error:
  309. if (pObjectInfo) {
  310. FreeObjectInfo(pObjectInfo);
  311. }
  312. RRETURN_EXP_IF_ERR(hr);
  313. }
  314. STDMETHODIMP
  315. CWinNTGroup::Remove(THIS_ BSTR bstrItemToBeRemoved)
  316. {
  317. HRESULT hr;
  318. NET_API_STATUS nasStatus;
  319. LOCALGROUP_MEMBERS_INFO_3 Member;
  320. LPLOCALGROUP_MEMBERS_INFO_3 pMember = &Member;
  321. POBJECTINFO pObjectInfo = NULL;
  322. WCHAR szDomName[MAX_PATH];
  323. WCHAR szHostServerName[MAX_PATH];
  324. BOOL fSpecialName = FALSE;
  325. BOOL fStringSID = FALSE;
  326. hr = BuildObjectInfo(
  327. bstrItemToBeRemoved,
  328. &pObjectInfo
  329. );
  330. BAIL_ON_FAILURE(hr);
  331. //
  332. // If there is only one component, it has to be in the SID form
  333. // or it has to be a Special SID like everyone.
  334. //
  335. if (pObjectInfo->NumComponents == 1) {
  336. //
  337. // Check to see if this is S-12-11
  338. //
  339. fStringSID = IsStringSID(pObjectInfo->ComponentArray[0]);
  340. if (!fStringSID) {
  341. fSpecialName = TRUE;
  342. }
  343. }
  344. memset(pMember, 0, sizeof(LOCALGROUP_MEMBERS_INFO_3));
  345. if (_ParentType == WINNT_COMPUTER_ID) {
  346. hr = MakeUncName(
  347. _ServerName,
  348. szHostServerName
  349. );
  350. BAIL_ON_FAILURE(hr);
  351. }else if (_ParentType == WINNT_DOMAIN_ID){
  352. hr = WinNTGetCachedDCName(
  353. _DomainName,
  354. szHostServerName,
  355. _Credentials.GetFlags()
  356. );
  357. BAIL_ON_FAILURE(hr);
  358. }
  359. if (fStringSID) {
  360. hr = DeleteBySID(
  361. pObjectInfo->ComponentArray[0],
  362. szHostServerName
  363. );
  364. goto error;
  365. }
  366. if (_GroupType == WINNT_GROUP_GLOBAL) {
  367. #ifdef WIN95
  368. if (_wcsicmp(pObjectInfo->ComponentArray[0], _DomainName)) {
  369. #else
  370. if (CompareStringW(
  371. LOCALE_SYSTEM_DEFAULT,
  372. NORM_IGNORECASE,
  373. pObjectInfo->ComponentArray[0],
  374. -1,
  375. _DomainName,
  376. -1
  377. ) != CSTR_EQUAL ) {
  378. #endif
  379. hr = E_ADS_INVALID_USER_OBJECT;
  380. BAIL_ON_FAILURE(hr);
  381. }
  382. nasStatus = NetGroupDelUser(
  383. szHostServerName,
  384. _Name,
  385. pObjectInfo->ComponentArray[(
  386. pObjectInfo->NumComponents) - 1]
  387. );
  388. hr = HRESULT_FROM_WIN32(nasStatus);
  389. BAIL_ON_FAILURE(hr);
  390. }else {
  391. if (!fSpecialName) {
  392. hr = MakeWinNTAccountName(pObjectInfo, szDomName, FALSE);
  393. BAIL_ON_FAILURE(hr);
  394. pMember->lgrmi3_domainandname = szDomName;
  395. }
  396. else {
  397. pMember->lgrmi3_domainandname =
  398. pObjectInfo->ComponentArray[0];
  399. }
  400. nasStatus = NetLocalGroupDelMembers(
  401. szHostServerName,
  402. _Name,
  403. 3,
  404. (LPBYTE)pMember,
  405. 1
  406. );
  407. if (nasStatus == ERROR_NO_SUCH_MEMBER) {
  408. hr = MakeWinNTAccountName(pObjectInfo, szDomName, TRUE);
  409. if (SUCCEEDED(hr)) {
  410. pMember->lgrmi3_domainandname = szDomName;
  411. nasStatus = NetLocalGroupDelMembers(
  412. szHostServerName,
  413. _Name,
  414. 3,
  415. (LPBYTE)pMember,
  416. 1
  417. );
  418. }
  419. }
  420. hr = HRESULT_FROM_WIN32(nasStatus);
  421. BAIL_ON_FAILURE(hr);
  422. }
  423. error:
  424. if (pObjectInfo) {
  425. FreeObjectInfo(pObjectInfo);
  426. }
  427. RRETURN_EXP_IF_ERR(hr);
  428. }
  429. BOOL
  430. VerifyIfMember(
  431. BSTR bstrMember,
  432. VARIANT * VariantArray,
  433. ULONG cElementFetched
  434. )
  435. {
  436. DWORD i = 0;
  437. HRESULT hr = S_OK;
  438. IADs FAR * pObject = NULL;
  439. IDispatch FAR * pDispatch = NULL;
  440. for (i = 0; i < cElementFetched; i++ ) {
  441. IDispatch *pDispatch = NULL;
  442. BSTR bstrName = NULL;
  443. pDispatch = VariantArray[i].pdispVal;
  444. hr = pDispatch->QueryInterface(
  445. IID_IADs,
  446. (VOID **) &pObject
  447. );
  448. BAIL_ON_FAILURE(hr);
  449. hr = pObject->get_ADsPath(&bstrName);
  450. BAIL_ON_FAILURE(hr);
  451. #ifdef WIN95
  452. if (!_wcsicmp(bstrName, bstrMember)) {
  453. #else
  454. if (CompareStringW(
  455. LOCALE_SYSTEM_DEFAULT,
  456. NORM_IGNORECASE,
  457. bstrName,
  458. -1,
  459. bstrMember,
  460. -1
  461. ) == CSTR_EQUAL ) {
  462. #endif
  463. SysFreeString(bstrName);
  464. bstrName = NULL;
  465. pObject->Release();
  466. return(TRUE);
  467. }
  468. SysFreeString(bstrName);
  469. bstrName = NULL;
  470. pObject->Release();
  471. }
  472. error:
  473. return(FALSE);
  474. }
  475. HRESULT
  476. CWinNTGroup::DeleteBySID(
  477. LPWSTR pszStringSID,
  478. LPWSTR pszServerName
  479. )
  480. {
  481. HRESULT hr = S_OK;
  482. BOOL fRet = FALSE;
  483. PSID pSid = NULL;
  484. NET_API_STATUS nasStatus;
  485. LOCALGROUP_MEMBERS_INFO_0 member;
  486. //
  487. // SDDL.H is currently available only for Win2k
  488. //
  489. #if !defined(WIN95)
  490. if (!pszStringSID) {
  491. BAIL_ON_FAILURE(hr = E_FAIL);
  492. }
  493. fRet = ConvertStringSidToSidWrapper(
  494. pszStringSID,
  495. &pSid
  496. );
  497. if (!pSid) {
  498. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
  499. }
  500. member.lgrmi0_sid = pSid;
  501. nasStatus = NetLocalGroupDelMembers(
  502. pszServerName,
  503. _Name,
  504. 0,
  505. (LPBYTE) &member,
  506. 1
  507. );
  508. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus));
  509. #else
  510. BAIL_ON_FAILURE(hr = E_FAIL);
  511. #endif
  512. error:
  513. if (pSid) {
  514. LocalFree(pSid);
  515. }
  516. RRETURN(hr);
  517. }
  518. //
  519. // Same as delete only this time to add by SID.
  520. //
  521. HRESULT
  522. CWinNTGroup::AddBySID(
  523. LPWSTR pszStringSID,
  524. LPWSTR pszServerName
  525. )
  526. {
  527. HRESULT hr = S_OK;
  528. BOOL fRet = FALSE;
  529. PSID pSid = NULL;
  530. NET_API_STATUS nasStatus;
  531. LOCALGROUP_MEMBERS_INFO_0 member;
  532. //
  533. // SDDL.H is currently available only for Win2k
  534. //
  535. #if !defined(WIN95)
  536. if (!pszStringSID) {
  537. BAIL_ON_FAILURE(hr = E_FAIL);
  538. }
  539. fRet = ConvertStringSidToSidWrapper(
  540. pszStringSID,
  541. &pSid
  542. );
  543. if (!pSid) {
  544. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
  545. }
  546. member.lgrmi0_sid = pSid;
  547. nasStatus = NetLocalGroupAddMembers(
  548. pszServerName,
  549. _Name,
  550. 0,
  551. (LPBYTE) &member,
  552. 1
  553. );
  554. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus));
  555. #else
  556. BAIL_ON_FAILURE(hr = E_FAIL);
  557. #endif
  558. error:
  559. if (pSid) {
  560. LocalFree(pSid);
  561. }
  562. RRETURN(hr);
  563. }
  564. //
  565. // Helper routine that checks if a string is a sid or not.
  566. //
  567. BOOL
  568. IsStringSID(LPWSTR pszStringSID)
  569. {
  570. BOOL fRet = FALSE;
  571. if (!pszStringSID || (wcslen(pszStringSID) < 4)) {
  572. return FALSE;
  573. }
  574. if (((*pszStringSID != L'S') && (*pszStringSID != L's'))
  575. || (*(pszStringSID + 1) != L'-')
  576. ) {
  577. return FALSE;
  578. }
  579. return TRUE;
  580. }