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.

705 lines
15 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. hr = Members(
  97. &pMembers
  98. );
  99. BAIL_ON_FAILURE(hr);
  100. hr = pMembers->get__NewEnum(
  101. &pUnknown
  102. );
  103. BAIL_ON_FAILURE(hr);
  104. hr = pUnknown->QueryInterface(
  105. IID_IEnumVARIANT,
  106. (void **)&pEnumVar
  107. );
  108. BAIL_ON_FAILURE(hr);
  109. while (fContinue) {
  110. IADs *pObject ;
  111. hr = pEnumVar->Next(
  112. 10,
  113. VariantArray,
  114. &cElementFetched
  115. );
  116. if (hr == S_FALSE) {
  117. fContinue = FALSE;
  118. //
  119. // Reset hr to S_OK, we want to return success
  120. //
  121. hr = S_OK;
  122. }
  123. fMember = (VARIANT_BOOL)VerifyIfMember(
  124. bstrMember,
  125. VariantArray,
  126. cElementFetched
  127. );
  128. if (fMember) {
  129. fContinue = FALSE;
  130. }
  131. for (i = 0; i < cElementFetched; i++ ) {
  132. IDispatch *pDispatch = NULL;
  133. pDispatch = VariantArray[i].pdispVal;
  134. pDispatch->Release();
  135. }
  136. memset(VariantArray, 0, sizeof(VARIANT)*10);
  137. }
  138. error:
  139. *bMember = fMember? VARIANT_TRUE : VARIANT_FALSE;
  140. if (pEnumVar) {
  141. pEnumVar->Release();
  142. }
  143. if (pUnknown) {
  144. pUnknown->Release();
  145. }
  146. if (pMembers) {
  147. pMembers->Release();
  148. }
  149. RRETURN_EXP_IF_ERR(hr);
  150. }
  151. STDMETHODIMP
  152. CWinNTGroup::Add(THIS_ BSTR bstrNewItem)
  153. {
  154. HRESULT hr;
  155. NET_API_STATUS nasStatus;
  156. LOCALGROUP_MEMBERS_INFO_3 Member;
  157. LPLOCALGROUP_MEMBERS_INFO_3 pMember = &Member;
  158. POBJECTINFO pObjectInfo = NULL;
  159. WCHAR szDomName[MAX_PATH];
  160. WCHAR szHostServerName[MAX_PATH];
  161. int iLastIndx = 0;
  162. BOOL fStringSID = FALSE;
  163. hr = BuildObjectInfo(
  164. bstrNewItem,
  165. &pObjectInfo
  166. );
  167. BAIL_ON_FAILURE(hr);
  168. iLastIndx = pObjectInfo->NumComponents - 1;
  169. //
  170. // If there is only one component, it has to be in the SID form
  171. // or it has to be a Special SID like everyone.
  172. //
  173. if (pObjectInfo->NumComponents == 1) {
  174. //
  175. // Check to see if this is S-12-11
  176. //
  177. fStringSID = IsStringSID(pObjectInfo->ComponentArray[0]);
  178. }
  179. memset(pMember, 0, sizeof(LOCALGROUP_MEMBERS_INFO_3));
  180. if (_ParentType == WINNT_COMPUTER_ID) {
  181. hr = MakeUncName(
  182. _ServerName,
  183. szHostServerName
  184. );
  185. BAIL_ON_FAILURE(hr);
  186. }else if (_ParentType == WINNT_DOMAIN_ID){
  187. hr = WinNTGetCachedDCName(
  188. _DomainName,
  189. szHostServerName,
  190. _Credentials.GetFlags()
  191. );
  192. BAIL_ON_FAILURE(hr);
  193. }
  194. if (_GroupType == WINNT_GROUP_GLOBAL) {
  195. #ifdef WIN95
  196. if (_wcsicmp(pObjectInfo->ComponentArray[0], _DomainName)) {
  197. #else
  198. if (CompareStringW(
  199. LOCALE_SYSTEM_DEFAULT,
  200. NORM_IGNORECASE,
  201. pObjectInfo->ComponentArray[0],
  202. -1,
  203. _DomainName,
  204. -1
  205. ) != CSTR_EQUAL ) {
  206. #endif
  207. hr = E_ADS_INVALID_USER_OBJECT;
  208. BAIL_ON_FAILURE(hr);
  209. }
  210. nasStatus = NetGroupAddUser(
  211. szHostServerName,
  212. _Name,
  213. pObjectInfo->ComponentArray[(
  214. pObjectInfo->NumComponents - 1)]
  215. );
  216. hr = HRESULT_FROM_WIN32(nasStatus);
  217. BAIL_ON_FAILURE(hr);
  218. }else if (_GroupType == WINNT_GROUP_LOCAL){
  219. if (fStringSID) {
  220. hr = AddBySID(
  221. pObjectInfo->ComponentArray[0],
  222. szHostServerName
  223. );
  224. goto error;
  225. }
  226. //
  227. // 0 implies special sid name.
  228. //
  229. if (iLastIndx != 0) {
  230. hr = MakeWinNTAccountName(pObjectInfo, szDomName, FALSE);
  231. BAIL_ON_FAILURE(hr);
  232. pMember->lgrmi3_domainandname = szDomName;
  233. }
  234. else {
  235. pMember->lgrmi3_domainandname =
  236. pObjectInfo->ComponentArray[iLastIndx];
  237. }
  238. //
  239. // For performance reasos we will first assume that the
  240. // use has domain name
  241. //
  242. nasStatus = NetLocalGroupAddMembers(
  243. szHostServerName,
  244. _Name,
  245. 3,
  246. (LPBYTE)pMember,
  247. 1
  248. );
  249. if (nasStatus == ERROR_NO_SUCH_MEMBER) {
  250. //
  251. // Try with true to see if that makes a difference
  252. //
  253. hr = MakeWinNTAccountName(pObjectInfo, szDomName, TRUE);
  254. if (SUCCEEDED(hr)) {
  255. //
  256. // Try again with this value
  257. //
  258. pMember->lgrmi3_domainandname = szDomName;
  259. nasStatus = NetLocalGroupAddMembers(
  260. szHostServerName,
  261. _Name,
  262. 3,
  263. (LPBYTE)pMember,
  264. 1
  265. );
  266. }
  267. }
  268. //
  269. // Either way nasStatus will have the correct value
  270. //
  271. hr = HRESULT_FROM_WIN32(nasStatus);
  272. BAIL_ON_FAILURE(hr);
  273. }
  274. error:
  275. if (pObjectInfo) {
  276. FreeObjectInfo(pObjectInfo);
  277. }
  278. RRETURN_EXP_IF_ERR(hr);
  279. }
  280. STDMETHODIMP
  281. CWinNTGroup::Remove(THIS_ BSTR bstrItemToBeRemoved)
  282. {
  283. HRESULT hr;
  284. NET_API_STATUS nasStatus;
  285. LOCALGROUP_MEMBERS_INFO_3 Member;
  286. LPLOCALGROUP_MEMBERS_INFO_3 pMember = &Member;
  287. POBJECTINFO pObjectInfo = NULL;
  288. WCHAR szDomName[MAX_PATH];
  289. WCHAR szHostServerName[MAX_PATH];
  290. BOOL fSpecialName = FALSE;
  291. BOOL fStringSID = FALSE;
  292. hr = BuildObjectInfo(
  293. bstrItemToBeRemoved,
  294. &pObjectInfo
  295. );
  296. BAIL_ON_FAILURE(hr);
  297. //
  298. // If there is only one component, it has to be in the SID form
  299. // or it has to be a Special SID like everyone.
  300. //
  301. if (pObjectInfo->NumComponents == 1) {
  302. //
  303. // Check to see if this is S-12-11
  304. //
  305. fStringSID = IsStringSID(pObjectInfo->ComponentArray[0]);
  306. if (!fStringSID) {
  307. fSpecialName = TRUE;
  308. }
  309. }
  310. memset(pMember, 0, sizeof(LOCALGROUP_MEMBERS_INFO_3));
  311. if (_ParentType == WINNT_COMPUTER_ID) {
  312. hr = MakeUncName(
  313. _ServerName,
  314. szHostServerName
  315. );
  316. BAIL_ON_FAILURE(hr);
  317. }else if (_ParentType == WINNT_DOMAIN_ID){
  318. hr = WinNTGetCachedDCName(
  319. _DomainName,
  320. szHostServerName,
  321. _Credentials.GetFlags()
  322. );
  323. BAIL_ON_FAILURE(hr);
  324. }
  325. if (fStringSID) {
  326. hr = DeleteBySID(
  327. pObjectInfo->ComponentArray[0],
  328. szHostServerName
  329. );
  330. goto error;
  331. }
  332. if (_GroupType == WINNT_GROUP_GLOBAL) {
  333. #ifdef WIN95
  334. if (_wcsicmp(pObjectInfo->ComponentArray[0], _DomainName)) {
  335. #else
  336. if (CompareStringW(
  337. LOCALE_SYSTEM_DEFAULT,
  338. NORM_IGNORECASE,
  339. pObjectInfo->ComponentArray[0],
  340. -1,
  341. _DomainName,
  342. -1
  343. ) != CSTR_EQUAL ) {
  344. #endif
  345. hr = E_ADS_INVALID_USER_OBJECT;
  346. BAIL_ON_FAILURE(hr);
  347. }
  348. nasStatus = NetGroupDelUser(
  349. szHostServerName,
  350. _Name,
  351. pObjectInfo->ComponentArray[(
  352. pObjectInfo->NumComponents) - 1]
  353. );
  354. hr = HRESULT_FROM_WIN32(nasStatus);
  355. BAIL_ON_FAILURE(hr);
  356. }else {
  357. if (!fSpecialName) {
  358. hr = MakeWinNTAccountName(pObjectInfo, szDomName, FALSE);
  359. BAIL_ON_FAILURE(hr);
  360. pMember->lgrmi3_domainandname = szDomName;
  361. }
  362. else {
  363. pMember->lgrmi3_domainandname =
  364. pObjectInfo->ComponentArray[0];
  365. }
  366. nasStatus = NetLocalGroupDelMembers(
  367. szHostServerName,
  368. _Name,
  369. 3,
  370. (LPBYTE)pMember,
  371. 1
  372. );
  373. if (nasStatus == ERROR_NO_SUCH_MEMBER) {
  374. hr = MakeWinNTAccountName(pObjectInfo, szDomName, TRUE);
  375. if (SUCCEEDED(hr)) {
  376. pMember->lgrmi3_domainandname = szDomName;
  377. nasStatus = NetLocalGroupDelMembers(
  378. szHostServerName,
  379. _Name,
  380. 3,
  381. (LPBYTE)pMember,
  382. 1
  383. );
  384. }
  385. }
  386. hr = HRESULT_FROM_WIN32(nasStatus);
  387. BAIL_ON_FAILURE(hr);
  388. }
  389. error:
  390. if (pObjectInfo) {
  391. FreeObjectInfo(pObjectInfo);
  392. }
  393. RRETURN_EXP_IF_ERR(hr);
  394. }
  395. BOOL
  396. VerifyIfMember(
  397. BSTR bstrMember,
  398. VARIANT * VariantArray,
  399. ULONG cElementFetched
  400. )
  401. {
  402. DWORD i = 0;
  403. HRESULT hr = S_OK;
  404. IADs FAR * pObject = NULL;
  405. IDispatch FAR * pDispatch = NULL;
  406. for (i = 0; i < cElementFetched; i++ ) {
  407. IDispatch *pDispatch = NULL;
  408. BSTR bstrName = NULL;
  409. pDispatch = VariantArray[i].pdispVal;
  410. hr = pDispatch->QueryInterface(
  411. IID_IADs,
  412. (VOID **) &pObject
  413. );
  414. BAIL_ON_FAILURE(hr);
  415. hr = pObject->get_ADsPath(&bstrName);
  416. BAIL_ON_FAILURE(hr);
  417. #ifdef WIN95
  418. if (!_wcsicmp(bstrName, bstrMember)) {
  419. #else
  420. if (CompareStringW(
  421. LOCALE_SYSTEM_DEFAULT,
  422. NORM_IGNORECASE,
  423. bstrName,
  424. -1,
  425. bstrMember,
  426. -1
  427. ) == CSTR_EQUAL ) {
  428. #endif
  429. SysFreeString(bstrName);
  430. bstrName = NULL;
  431. pObject->Release();
  432. return(TRUE);
  433. }
  434. SysFreeString(bstrName);
  435. bstrName = NULL;
  436. pObject->Release();
  437. }
  438. error:
  439. return(FALSE);
  440. }
  441. HRESULT
  442. CWinNTGroup::DeleteBySID(
  443. LPWSTR pszStringSID,
  444. LPWSTR pszServerName
  445. )
  446. {
  447. HRESULT hr = S_OK;
  448. BOOL fRet = FALSE;
  449. PSID pSid = NULL;
  450. NET_API_STATUS nasStatus;
  451. LOCALGROUP_MEMBERS_INFO_0 member;
  452. //
  453. // SDDL.H is currently available only for Win2k
  454. //
  455. #if !defined(WIN95)
  456. if (!pszStringSID) {
  457. BAIL_ON_FAILURE(hr = E_FAIL);
  458. }
  459. fRet = ConvertStringSidToSidWrapper(
  460. pszStringSID,
  461. &pSid
  462. );
  463. if (!pSid) {
  464. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
  465. }
  466. member.lgrmi0_sid = pSid;
  467. nasStatus = NetLocalGroupDelMembers(
  468. pszServerName,
  469. _Name,
  470. 0,
  471. (LPBYTE) &member,
  472. 1
  473. );
  474. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus));
  475. #else
  476. BAIL_ON_FAILURE(hr = E_FAIL);
  477. #endif
  478. error:
  479. if (pSid) {
  480. LocalFree(pSid);
  481. }
  482. RRETURN(hr);
  483. }
  484. //
  485. // Same as delete only this time to add by SID.
  486. //
  487. HRESULT
  488. CWinNTGroup::AddBySID(
  489. LPWSTR pszStringSID,
  490. LPWSTR pszServerName
  491. )
  492. {
  493. HRESULT hr = S_OK;
  494. BOOL fRet = FALSE;
  495. PSID pSid = NULL;
  496. NET_API_STATUS nasStatus;
  497. LOCALGROUP_MEMBERS_INFO_0 member;
  498. //
  499. // SDDL.H is currently available only for Win2k
  500. //
  501. #if !defined(WIN95)
  502. if (!pszStringSID) {
  503. BAIL_ON_FAILURE(hr = E_FAIL);
  504. }
  505. fRet = ConvertStringSidToSidWrapper(
  506. pszStringSID,
  507. &pSid
  508. );
  509. if (!pSid) {
  510. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
  511. }
  512. member.lgrmi0_sid = pSid;
  513. nasStatus = NetLocalGroupAddMembers(
  514. pszServerName,
  515. _Name,
  516. 0,
  517. (LPBYTE) &member,
  518. 1
  519. );
  520. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(nasStatus));
  521. #else
  522. BAIL_ON_FAILURE(hr = E_FAIL);
  523. #endif
  524. error:
  525. if (pSid) {
  526. LocalFree(pSid);
  527. }
  528. RRETURN(hr);
  529. }
  530. //
  531. // Helper routine that checks if a string is a sid or not.
  532. //
  533. BOOL
  534. IsStringSID(LPWSTR pszStringSID)
  535. {
  536. BOOL fRet = FALSE;
  537. if (!pszStringSID || (wcslen(pszStringSID) < 4)) {
  538. return FALSE;
  539. }
  540. if (((*pszStringSID != L'S') && (*pszStringSID != L's'))
  541. || (*(pszStringSID + 1) != L'-')
  542. ) {
  543. return FALSE;
  544. }
  545. return TRUE;
  546. }