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.

2189 lines
54 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: libmain.cxx
  7. //
  8. // Contents: LibMain for nds.dll
  9. //
  10. // Functions: LibMain, DllGetClassObject
  11. //
  12. // History: 25-Oct-94 KrishnaG Created.
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "oleds.hxx"
  16. #pragma hdrstop
  17. CRITICAL_SECTION g_StringsCriticalSection;
  18. WCHAR g_szBuiltin[100];
  19. WCHAR g_szNT_Authority[100];
  20. WCHAR g_szAccountOperators[100];
  21. WCHAR g_szPrintOperators[100];
  22. WCHAR g_szBackupOperators[100];
  23. WCHAR g_szServerOperators[100];
  24. WCHAR g_szPreWindows2000[100];
  25. BOOL g_fStringsLoaded = FALSE;
  26. //
  27. // Global variables for dynamically loaded fn's.
  28. //
  29. HANDLE g_hDllAdvapi32 = NULL;
  30. BOOL g_fDllsLoaded = FALSE;
  31. extern "C" {
  32. HRESULT
  33. ConvertSidToString(
  34. PSID pSid,
  35. LPWSTR String
  36. );
  37. }
  38. DWORD
  39. GetDomainDNSNameForDomain(
  40. LPWSTR pszDomainFlatName,
  41. BOOL fVerify,
  42. BOOL fWriteable,
  43. LPWSTR pszServerName,
  44. LPWSTR pszDomainDNSName
  45. );
  46. #define GetAce ADSIGetAce
  47. #define AddAce ADSIAddAce
  48. #define DeleteAce ADSIDeleteAce
  49. #define GetAclInformation ADSIGetAclInformation
  50. #define SetAclInformation ADSISetAclInformation
  51. #define IsValidAcl ADSIIsValidAcl
  52. #define InitializeAcl ADSIInitializeAcl
  53. #define SetSecurityDescriptorControl ADSISetControlSecurityDescriptor
  54. #define SE_VALID_CONTROL_BITS ( SE_DACL_UNTRUSTED | \
  55. SE_SERVER_SECURITY | \
  56. SE_DACL_AUTO_INHERIT_REQ | \
  57. SE_SACL_AUTO_INHERIT_REQ | \
  58. SE_DACL_AUTO_INHERITED | \
  59. SE_SACL_AUTO_INHERITED | \
  60. SE_DACL_PROTECTED | \
  61. SE_SACL_PROTECTED )
  62. BOOL
  63. EquivalentServers(
  64. LPWSTR pszTargetServer,
  65. LPWSTR pszSourceServer
  66. );
  67. HRESULT
  68. SecCreateSidFromArray (
  69. OUT PSID *PPSid,
  70. IN PSID_IDENTIFIER_AUTHORITY PSidAuthority,
  71. IN UCHAR SubAuthorityCount,
  72. IN ULONG SubAuthorities[],
  73. OUT PDWORD pdwSidSize
  74. );
  75. HRESULT
  76. ConvertStringToSid(
  77. IN PWSTR string,
  78. OUT PSID *sid,
  79. OUT PDWORD pdwSidSize,
  80. OUT PWSTR *end
  81. );
  82. HRESULT
  83. AddFilteredACEs(
  84. PACL pAcl,
  85. DWORD dwAclRevision,
  86. PACE_HEADER *ppAceHdr,
  87. DWORD dwCountACEs,
  88. DWORD *pdwAclPosition,
  89. BOOL fInheritedACEs,
  90. BOOL fDenyACEs,
  91. BOOL fDenyObjectACEs,
  92. BOOL fGrantACEs,
  93. BOOL fGrantObjectACEs,
  94. BOOL fAuditACEs
  95. );
  96. //
  97. // These wrapper functions are needed as some fn's need to
  98. // be loaded dynamically as they are not available on NT4
  99. //
  100. #define SET_SD_CONTROL_API "SetSecurityDescriptorControl"
  101. //
  102. // Helper that loads functions in advapi32.
  103. //
  104. PVOID LoadAdvapi32Function(CHAR *function)
  105. {
  106. //
  107. // Since the strings critical section is only used in this file,
  108. // be fine just re-using it here.
  109. //
  110. if (!g_fDllsLoaded) {
  111. EnterCriticalSection(&g_StringsCriticalSection);
  112. if (!g_fDllsLoaded) {
  113. g_hDllAdvapi32 = LoadLibrary(L"ADVAPI32.DLL");
  114. //
  115. // Even if this fails, there is nothing we can do.
  116. //
  117. g_fDllsLoaded = TRUE;
  118. }
  119. LeaveCriticalSection(&g_StringsCriticalSection);
  120. }
  121. if (g_hDllAdvapi32) {
  122. return((PVOID*) GetProcAddress((HMODULE) g_hDllAdvapi32, function));
  123. }
  124. return NULL;
  125. }
  126. typedef DWORD (*PF_SetSecurityDescriptorControl) (
  127. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  128. IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
  129. IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet
  130. );
  131. //
  132. // Wrapper function for the same.
  133. //
  134. DWORD SetSecurityDescriptorControlWrapper(
  135. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  136. IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
  137. IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet
  138. )
  139. {
  140. static PF_SetSecurityDescriptorControl pfSetSecDescControl = NULL;
  141. static BOOL f_LoadAttempted = FALSE;
  142. //
  143. // Load the fn and set the variables accordingly.
  144. //
  145. if (!f_LoadAttempted && pfSetSecDescControl == NULL) {
  146. pfSetSecDescControl = (PF_SetSecurityDescriptorControl)
  147. LoadAdvapi32Function(SET_SD_CONTROL_API);
  148. f_LoadAttempted = TRUE;
  149. }
  150. if (pfSetSecDescControl != NULL) {
  151. return ((*pfSetSecDescControl)(
  152. pSecurityDescriptor,
  153. ControlBitsOfInterest,
  154. ControlBitsToSet
  155. )
  156. );
  157. }
  158. else {
  159. //
  160. // This will call the routine in acledit.cxx.
  161. // We should be in this codepath only in pre win2k
  162. // machines.
  163. //
  164. return SetSecurityDescriptorControl(
  165. pSecurityDescriptor,
  166. ControlBitsOfInterest,
  167. ControlBitsToSet
  168. );
  169. }
  170. }
  171. HRESULT
  172. ConvertSecurityDescriptorToSecDes(
  173. LPWSTR pszServerName,
  174. CCredentials& Credentials,
  175. IADsSecurityDescriptor FAR * pSecDes,
  176. PSECURITY_DESCRIPTOR * ppSecurityDescriptor,
  177. PDWORD pdwSDLength,
  178. BOOL fNTDSType
  179. )
  180. {
  181. HRESULT hr = S_OK;
  182. SECURITY_DESCRIPTOR AbsoluteSD;
  183. PSECURITY_DESCRIPTOR pRelative = NULL;
  184. BOOL Defaulted = FALSE;
  185. BOOL DaclPresent = FALSE;
  186. BOOL SaclPresent = FALSE;
  187. BOOL fDaclDefaulted = FALSE;
  188. BOOL fSaclDefaulted = FALSE;
  189. BOOL fOwnerDefaulted = FALSE;
  190. BOOL fGroupDefaulted = FALSE;
  191. PSID pOwnerSid = NULL;
  192. PSID pGroupSid = NULL;
  193. PACL pDacl = NULL;
  194. PACL pSacl = NULL;
  195. DWORD dwSDLength = 0;
  196. BOOL dwStatus = 0;
  197. DWORD dwControl = 0;
  198. DWORD dwRevision = 0;
  199. hr = pSecDes->get_Revision((long *)&dwRevision);
  200. BAIL_ON_FAILURE(hr);
  201. dwStatus = InitializeSecurityDescriptor (
  202. &AbsoluteSD,
  203. dwRevision
  204. );
  205. if (!dwStatus) {
  206. hr = HRESULT_FROM_WIN32(GetLastError());
  207. BAIL_ON_FAILURE(hr);
  208. }
  209. hr = pSecDes->get_Control((long *)&dwControl);
  210. BAIL_ON_FAILURE(hr);
  211. dwStatus = SetSecurityDescriptorControlWrapper(
  212. &AbsoluteSD,
  213. SE_VALID_CONTROL_BITS,
  214. (SECURITY_DESCRIPTOR_CONTROL) (dwControl & SE_VALID_CONTROL_BITS)
  215. );
  216. if (!dwStatus) {
  217. hr = HRESULT_FROM_WIN32(GetLastError());
  218. BAIL_ON_FAILURE(hr);
  219. }
  220. hr = GetOwnerSecurityIdentifier(
  221. pszServerName,
  222. Credentials,
  223. pSecDes,
  224. &pOwnerSid,
  225. &fOwnerDefaulted,
  226. fNTDSType
  227. );
  228. BAIL_ON_FAILURE(hr);
  229. dwStatus = SetSecurityDescriptorOwner(
  230. &AbsoluteSD,
  231. pOwnerSid,
  232. fOwnerDefaulted
  233. );
  234. if (!dwStatus) {
  235. hr = HRESULT_FROM_WIN32(GetLastError());
  236. BAIL_ON_FAILURE(hr);
  237. }
  238. hr = GetGroupSecurityIdentifier(
  239. pszServerName,
  240. Credentials,
  241. pSecDes,
  242. &pGroupSid,
  243. &fGroupDefaulted,
  244. fNTDSType
  245. );
  246. BAIL_ON_FAILURE(hr);
  247. dwStatus = SetSecurityDescriptorGroup(
  248. &AbsoluteSD,
  249. pGroupSid,
  250. fGroupDefaulted
  251. );
  252. if (!dwStatus) {
  253. hr = HRESULT_FROM_WIN32(GetLastError());
  254. BAIL_ON_FAILURE(hr);
  255. }
  256. hr = GetDacl(
  257. pszServerName,
  258. Credentials,
  259. pSecDes,
  260. &pDacl,
  261. &fDaclDefaulted,
  262. fNTDSType
  263. );
  264. BAIL_ON_FAILURE(hr);
  265. if (pDacl || fDaclDefaulted) {
  266. DaclPresent = TRUE;
  267. }
  268. //
  269. // This is a special case, basically the DACL is defaulted
  270. // and pDacl is NULL. In order for this to work correctly,
  271. // pDacl should be an empty ACL not null.
  272. //
  273. if (DaclPresent && !pDacl) {
  274. pDacl = (PACL) AllocADsMem(sizeof(ACL));
  275. if (!pDacl) {
  276. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  277. }
  278. dwStatus = InitializeAcl(
  279. pDacl,
  280. sizeof(ACL),
  281. ACL_REVISION // this revision will work for NT4 and Win2k
  282. );
  283. if (!dwStatus) {
  284. hr = HRESULT_FROM_WIN32(GetLastError());
  285. BAIL_ON_FAILURE(hr);
  286. }
  287. }
  288. dwStatus = SetSecurityDescriptorDacl(
  289. &AbsoluteSD,
  290. DaclPresent,
  291. pDacl,
  292. fDaclDefaulted
  293. );
  294. if (!dwStatus) {
  295. hr = HRESULT_FROM_WIN32(GetLastError());
  296. BAIL_ON_FAILURE(hr);
  297. }
  298. hr = GetSacl(
  299. pszServerName,
  300. Credentials,
  301. pSecDes,
  302. &pSacl,
  303. &fSaclDefaulted,
  304. fNTDSType
  305. );
  306. BAIL_ON_FAILURE(hr);
  307. if (pSacl || fSaclDefaulted) {
  308. SaclPresent = TRUE;
  309. }
  310. dwStatus = SetSecurityDescriptorSacl(
  311. &AbsoluteSD,
  312. SaclPresent,
  313. pSacl,
  314. fSaclDefaulted
  315. );
  316. if (!dwStatus) {
  317. hr = HRESULT_FROM_WIN32(GetLastError());
  318. BAIL_ON_FAILURE(hr);
  319. }
  320. dwSDLength = GetSecurityDescriptorLength(
  321. &AbsoluteSD
  322. );
  323. pRelative = AllocADsMem(dwSDLength);
  324. if (!pRelative) {
  325. hr = E_OUTOFMEMORY;
  326. BAIL_ON_FAILURE(hr);
  327. }
  328. if (!MakeSelfRelativeSD (&AbsoluteSD, pRelative, &dwSDLength)) {
  329. FreeADsMem(pRelative);
  330. hr = HRESULT_FROM_WIN32(GetLastError());
  331. BAIL_ON_FAILURE(hr);
  332. }
  333. *ppSecurityDescriptor = pRelative;
  334. *pdwSDLength = dwSDLength;
  335. cleanup:
  336. if (pDacl) {
  337. FreeADsMem(pDacl);
  338. }
  339. if (pSacl) {
  340. FreeADsMem(pSacl);
  341. }
  342. if (pOwnerSid) {
  343. FreeADsMem(pOwnerSid);
  344. }
  345. if (pGroupSid) {
  346. FreeADsMem(pGroupSid);
  347. }
  348. RRETURN(hr);
  349. error:
  350. if (pRelative) {
  351. FreeADsMem(pRelative);
  352. }
  353. *ppSecurityDescriptor = NULL;
  354. *pdwSDLength = 0;
  355. goto cleanup;
  356. }
  357. HRESULT
  358. GetOwnerSecurityIdentifier(
  359. LPWSTR pszServerName,
  360. CCredentials& Credentials,
  361. IADsSecurityDescriptor FAR * pSecDes,
  362. PSID * ppSid,
  363. PBOOL pfOwnerDefaulted,
  364. BOOL fNTDSType
  365. )
  366. {
  367. BSTR bstrOwner = NULL;
  368. DWORD dwSidSize = 0;
  369. HRESULT hr = S_OK;
  370. VARIANT_BOOL varBool = VARIANT_FALSE;
  371. hr = pSecDes->get_Owner(
  372. &bstrOwner
  373. );
  374. BAIL_ON_FAILURE(hr);
  375. hr = pSecDes->get_OwnerDefaulted(
  376. &varBool
  377. );
  378. BAIL_ON_FAILURE(hr);
  379. if (varBool == VARIANT_FALSE) {
  380. if (bstrOwner && *bstrOwner) {
  381. hr = ConvertTrusteeToSid(
  382. pszServerName,
  383. Credentials,
  384. bstrOwner,
  385. ppSid,
  386. &dwSidSize,
  387. fNTDSType
  388. );
  389. BAIL_ON_FAILURE(hr);
  390. *pfOwnerDefaulted = FALSE;
  391. }else {
  392. *ppSid = NULL;
  393. *pfOwnerDefaulted = FALSE;
  394. }
  395. }else {
  396. *ppSid = NULL;
  397. dwSidSize = 0;
  398. *pfOwnerDefaulted = TRUE;
  399. }
  400. error:
  401. if (bstrOwner) {
  402. ADsFreeString(bstrOwner);
  403. }
  404. RRETURN(hr);
  405. }
  406. HRESULT
  407. GetGroupSecurityIdentifier(
  408. LPWSTR pszServerName,
  409. CCredentials& Credentials,
  410. IADsSecurityDescriptor FAR * pSecDes,
  411. PSID * ppSid,
  412. PBOOL pfGroupDefaulted,
  413. BOOL fNTDSType
  414. )
  415. {
  416. BSTR bstrGroup = NULL;
  417. DWORD dwSidSize = 0;
  418. HRESULT hr = S_OK;
  419. VARIANT_BOOL varBool = VARIANT_FALSE;
  420. hr = pSecDes->get_Group(
  421. &bstrGroup
  422. );
  423. BAIL_ON_FAILURE(hr);
  424. hr = pSecDes->get_GroupDefaulted(
  425. &varBool
  426. );
  427. BAIL_ON_FAILURE(hr);
  428. if (varBool == VARIANT_FALSE) {
  429. if (bstrGroup && *bstrGroup) {
  430. hr = ConvertTrusteeToSid(
  431. pszServerName,
  432. Credentials,
  433. bstrGroup,
  434. ppSid,
  435. &dwSidSize,
  436. fNTDSType
  437. );
  438. BAIL_ON_FAILURE(hr);
  439. *pfGroupDefaulted = FALSE;
  440. }else {
  441. *ppSid = NULL;
  442. *pfGroupDefaulted = FALSE;
  443. }
  444. }else {
  445. *ppSid = NULL;
  446. dwSidSize = 0;
  447. *pfGroupDefaulted = TRUE;
  448. }
  449. error:
  450. if (bstrGroup) {
  451. ADsFreeString(bstrGroup);
  452. }
  453. RRETURN(hr);
  454. }
  455. HRESULT
  456. GetDacl(
  457. LPWSTR pszServerName,
  458. CCredentials& Credentials,
  459. IADsSecurityDescriptor FAR * pSecDes,
  460. PACL * ppDacl,
  461. PBOOL pfDaclDefaulted,
  462. BOOL fNTDSType
  463. )
  464. {
  465. IADsAccessControlList FAR * pDiscAcl = NULL;
  466. IDispatch FAR * pDispatch = NULL;
  467. HRESULT hr = S_OK;
  468. VARIANT_BOOL varBool = VARIANT_FALSE;
  469. hr = pSecDes->get_DaclDefaulted(
  470. &varBool
  471. );
  472. BAIL_ON_FAILURE(hr);
  473. if (varBool == VARIANT_FALSE) {
  474. *pfDaclDefaulted = FALSE;
  475. }else {
  476. *pfDaclDefaulted = TRUE;
  477. }
  478. hr = pSecDes->get_DiscretionaryAcl(
  479. &pDispatch
  480. );
  481. BAIL_ON_FAILURE(hr);
  482. if (!pDispatch) {
  483. *ppDacl = NULL;
  484. goto error;
  485. }
  486. hr = pDispatch->QueryInterface(
  487. IID_IADsAccessControlList,
  488. (void **)&pDiscAcl
  489. );
  490. BAIL_ON_FAILURE(hr);
  491. hr = ConvertAccessControlListToAcl(
  492. pszServerName,
  493. Credentials,
  494. pDiscAcl,
  495. ppDacl,
  496. fNTDSType
  497. );
  498. BAIL_ON_FAILURE(hr);
  499. error:
  500. if (pDispatch) {
  501. pDispatch->Release();
  502. }
  503. if (pDiscAcl) {
  504. pDiscAcl->Release();
  505. }
  506. RRETURN(hr);
  507. }
  508. HRESULT
  509. GetSacl(
  510. LPWSTR pszServerName,
  511. CCredentials& Credentials,
  512. IADsSecurityDescriptor FAR * pSecDes,
  513. PACL * ppSacl,
  514. PBOOL pfSaclDefaulted,
  515. BOOL fNTDSType
  516. )
  517. {
  518. IADsAccessControlList FAR * pSystemAcl = NULL;
  519. IDispatch FAR * pDispatch = NULL;
  520. HRESULT hr = S_OK;
  521. VARIANT_BOOL varBool = VARIANT_FALSE;
  522. hr = pSecDes->get_SaclDefaulted(
  523. &varBool
  524. );
  525. BAIL_ON_FAILURE(hr);
  526. if (varBool == VARIANT_FALSE) {
  527. *pfSaclDefaulted = FALSE;
  528. }else {
  529. *pfSaclDefaulted = TRUE;
  530. }
  531. hr = pSecDes->get_SystemAcl(
  532. &pDispatch
  533. );
  534. BAIL_ON_FAILURE(hr);
  535. if (!pDispatch) {
  536. *ppSacl = NULL;
  537. goto error;
  538. }
  539. hr = pDispatch->QueryInterface(
  540. IID_IADsAccessControlList,
  541. (void **)&pSystemAcl
  542. );
  543. BAIL_ON_FAILURE(hr);
  544. hr = ConvertAccessControlListToAcl(
  545. pszServerName,
  546. Credentials,
  547. pSystemAcl,
  548. ppSacl,
  549. fNTDSType
  550. );
  551. BAIL_ON_FAILURE(hr);
  552. error:
  553. if (pDispatch) {
  554. pDispatch->Release();
  555. }
  556. if (pSystemAcl) {
  557. pSystemAcl->Release();
  558. }
  559. RRETURN(hr);
  560. }
  561. HRESULT
  562. ConvertAccessControlListToAcl(
  563. LPWSTR pszServerName,
  564. CCredentials& Credentials,
  565. IADsAccessControlList FAR * pAccessList,
  566. PACL * ppAcl,
  567. BOOL fNTDSType
  568. )
  569. {
  570. IUnknown * pUnknown = NULL;
  571. IEnumVARIANT * pEnumerator = NULL;
  572. HRESULT hr = S_OK;
  573. DWORD i = 0;
  574. DWORD iAclPosition = 0;
  575. DWORD cReturned = 0;
  576. VARIANT varAce;
  577. DWORD dwAceCount = 0;
  578. IADsAccessControlEntry FAR * pAccessControlEntry = NULL;
  579. LPBYTE pTempAce = NULL;
  580. DWORD dwCount = 0;
  581. PACL pAcl = NULL;
  582. DWORD dwAclSize = 0;
  583. PACE_HEADER * ppAceHdr = NULL;
  584. DWORD dwRet = 0;
  585. DWORD dwAclRevision = 0;
  586. DWORD dwError = 0;
  587. //
  588. // Defines the canonical ordering of the ACEs.
  589. //
  590. struct AceOrderElement
  591. {
  592. BOOL fInheritedACEs;
  593. BOOL fDenyACEs;
  594. BOOL fDenyObjectACEs;
  595. BOOL fGrantACEs;
  596. BOOL fGrantObjectACEs;
  597. BOOL fAuditACEs;
  598. } AceOrderSequence [] =
  599. {
  600. {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE},
  601. {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE},
  602. {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE},
  603. {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE},
  604. {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE},
  605. {TRUE, FALSE, FALSE, FALSE, FALSE, TRUE},
  606. {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE},
  607. {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE},
  608. {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE},
  609. {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE}
  610. };
  611. DWORD dwAceOrderSequenceLen = sizeof(AceOrderSequence) / sizeof (AceOrderElement);
  612. hr = pAccessList->get_AceCount((long *)&dwAceCount);
  613. BAIL_ON_FAILURE(hr);
  614. hr = pAccessList->get__NewEnum(
  615. &pUnknown
  616. );
  617. BAIL_ON_FAILURE(hr);
  618. hr = pUnknown->QueryInterface(
  619. IID_IEnumVARIANT,
  620. (void FAR * FAR *)&pEnumerator
  621. );
  622. BAIL_ON_FAILURE(hr);
  623. ppAceHdr = (PACE_HEADER *)AllocADsMem(sizeof(PACE_HEADER)*dwAceCount);
  624. if (!ppAceHdr) {
  625. hr = E_OUTOFMEMORY;
  626. BAIL_ON_FAILURE(hr);
  627. }
  628. for (i = 0; i < dwAceCount; i++) {
  629. VariantInit(&varAce);
  630. hr = pEnumerator->Next(
  631. 1,
  632. &varAce,
  633. &cReturned
  634. );
  635. //
  636. // Need to BAIL here as we could not convert an ACL.
  637. //
  638. BAIL_ON_FAILURE(hr);
  639. hr = (V_DISPATCH(&varAce))->QueryInterface(
  640. IID_IADsAccessControlEntry,
  641. (void **)&pAccessControlEntry
  642. );
  643. BAIL_ON_FAILURE(hr);
  644. hr = ConvertAccessControlEntryToAce(
  645. pszServerName,
  646. Credentials,
  647. pAccessControlEntry,
  648. &(pTempAce),
  649. fNTDSType
  650. );
  651. BAIL_ON_FAILURE(hr);
  652. *(ppAceHdr + dwCount) = (PACE_HEADER)pTempAce;
  653. VariantClear(&varAce);
  654. if (pAccessControlEntry) {
  655. pAccessControlEntry->Release();
  656. pAccessControlEntry = NULL;
  657. }
  658. dwCount++;
  659. }
  660. hr = ComputeTotalAclSize(ppAceHdr, dwCount, &dwAclSize);
  661. BAIL_ON_FAILURE(hr);
  662. pAcl = (PACL)AllocADsMem(dwAclSize);
  663. if (!pAcl) {
  664. hr = E_OUTOFMEMORY;
  665. BAIL_ON_FAILURE(hr);
  666. }
  667. hr = pAccessList->get_AclRevision((long *)&dwAclRevision);
  668. BAIL_ON_FAILURE(hr);
  669. dwRet = InitializeAcl(
  670. pAcl,
  671. dwAclSize,
  672. dwAclRevision
  673. );
  674. if (!dwRet) {
  675. hr = HRESULT_FROM_WIN32(GetLastError());
  676. BAIL_ON_FAILURE(hr);
  677. }
  678. //
  679. // Add the ACEs in canonical ordering:
  680. // All Explitic Audit
  681. // All Explicit Deny
  682. // All Explicit Object Deny
  683. // All Explicit Allow
  684. // All Explicit Object Allow
  685. //
  686. // All Inherited Audit
  687. // All Inherited Deny
  688. // All Inherited Object Deny
  689. // All Inherited Allow
  690. // All Inherited Object Allow
  691. //
  692. for (i=0; i < dwAceOrderSequenceLen; i++) {
  693. hr = AddFilteredACEs(
  694. pAcl,
  695. dwAclRevision,
  696. ppAceHdr,
  697. dwCount,
  698. &iAclPosition,
  699. AceOrderSequence[i].fInheritedACEs,
  700. AceOrderSequence[i].fDenyACEs,
  701. AceOrderSequence[i].fDenyObjectACEs,
  702. AceOrderSequence[i].fGrantACEs,
  703. AceOrderSequence[i].fGrantObjectACEs,
  704. AceOrderSequence[i].fAuditACEs
  705. );
  706. BAIL_ON_FAILURE(hr);
  707. }
  708. *ppAcl = pAcl;
  709. error:
  710. if (ppAceHdr) {
  711. for (i = 0; i < dwCount; i++) {
  712. if (*(ppAceHdr + i)) {
  713. FreeADsMem(*(ppAceHdr + i));
  714. }
  715. }
  716. FreeADsMem(ppAceHdr);
  717. }
  718. if (pUnknown) {
  719. pUnknown->Release();
  720. }
  721. if (pEnumerator) {
  722. pEnumerator->Release();
  723. }
  724. RRETURN(hr);
  725. }
  726. /*
  727. * AddFilteredACEs
  728. *
  729. * Adds ACEs from ppAceHdr (of size dwCountACEs) to the ACL pAcl
  730. * (of revision dwAclRevision), starting at position *pdwAclPosition in
  731. * the ACL, based on the filter settings fInheritedACEs, fDenyACEs,
  732. * fGrantACEs, fDenyObjectACEs, fGrantObjectACEs, and fAuditACEs.
  733. *
  734. * On return, *pdwAclPosition is the position to continue adding
  735. * ACEs at.
  736. *
  737. */
  738. HRESULT
  739. AddFilteredACEs(
  740. PACL pAcl, // the ACL to add the ACEs to
  741. DWORD dwAclRevision, // the revision of the ACL
  742. PACE_HEADER *ppAceHdr, // the ACEs to add
  743. DWORD dwCountACEs, // number of ACEs in ppAceHdr
  744. DWORD *pdwAclPosition, // starting(in)/ending(out) position
  745. BOOL fInheritedACEs, // include explicit or inherited ACEs?
  746. BOOL fDenyACEs, // include access-deny ACEs?
  747. BOOL fDenyObjectACEs, // include access-deny-object ACEs?
  748. BOOL fGrantACEs, // include access-grant ACEs?
  749. BOOL fGrantObjectACEs, // include access-grant-object ACEs?
  750. BOOL fAuditACEs // include audit ACEs?
  751. )
  752. {
  753. HRESULT hr = S_OK;
  754. DWORD dwStatus;
  755. DWORD i;
  756. DWORD iAclPosition = *pdwAclPosition;
  757. BOOL fAddIt;
  758. BOOL fIsAceInherited;
  759. for (i = 0; i < dwCountACEs; i++) {
  760. //
  761. // Filter based on whether we're adding explicit or inherited ACEs
  762. //
  763. fIsAceInherited = (((*(ppAceHdr + i))->AceFlags) & INHERITED_ACE) ? TRUE : FALSE;
  764. if ( fIsAceInherited == fInheritedACEs) {
  765. fAddIt = FALSE;
  766. //
  767. // Filter based on ACE type
  768. //
  769. switch ((*(ppAceHdr + i))->AceType) {
  770. case ACCESS_ALLOWED_ACE_TYPE:
  771. if (fGrantACEs) {
  772. fAddIt = TRUE;
  773. }
  774. break;
  775. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  776. if (fGrantObjectACEs) {
  777. fAddIt = TRUE;
  778. }
  779. break;
  780. case ACCESS_DENIED_ACE_TYPE:
  781. if (fDenyACEs) {
  782. fAddIt = TRUE;
  783. }
  784. break;
  785. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  786. if (fDenyObjectACEs) {
  787. fAddIt = TRUE;
  788. }
  789. break;
  790. case SYSTEM_AUDIT_ACE_TYPE:
  791. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  792. if (fAuditACEs) {
  793. fAddIt = TRUE;
  794. }
  795. break;
  796. default:
  797. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  798. break;
  799. }
  800. //
  801. // If the ACE met the criteria, add it to the ACL
  802. //
  803. if (fAddIt) {
  804. dwStatus = AddAce(
  805. pAcl,
  806. dwAclRevision,
  807. iAclPosition++,
  808. (LPBYTE)*(ppAceHdr + i),
  809. (*(ppAceHdr + i))->AceSize
  810. );
  811. if (!dwStatus) {
  812. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
  813. }
  814. }
  815. }
  816. }
  817. error:
  818. *pdwAclPosition = iAclPosition;
  819. RRETURN(hr);
  820. }
  821. HRESULT
  822. ConvertAccessControlEntryToAce(
  823. LPWSTR pszServerName,
  824. CCredentials& Credentials,
  825. IADsAccessControlEntry * pAccessControlEntry,
  826. LPBYTE * ppAce,
  827. BOOL fNTDSType
  828. )
  829. {
  830. DWORD dwAceType = 0;
  831. HRESULT hr = S_OK;
  832. BSTR bstrTrustee = NULL;
  833. PSID pSid = NULL;
  834. DWORD dwSidSize = 0;
  835. DWORD dwAceFlags = 0;
  836. DWORD dwAccessMask = 0;
  837. DWORD dwAceSize = 0;
  838. LPBYTE pAce = NULL;
  839. PACCESS_MASK pAccessMask = NULL;
  840. PSID pSidAddress = NULL;
  841. PUSHORT pCompoundAceType = NULL;
  842. DWORD dwCompoundAceType = 0;
  843. PACE_HEADER pAceHeader = NULL;
  844. LPBYTE pOffset = NULL;
  845. BSTR bstrObjectTypeClsid = NULL;
  846. BSTR bstrInheritedObjectTypeClsid = NULL;
  847. GUID ObjectTypeGUID;
  848. GUID InheritedObjectTypeGUID;
  849. PULONG pFlags;
  850. DWORD dwFlags = 0;
  851. BOOL fLookupTrustee = TRUE;
  852. BOOL fSidValid = FALSE;
  853. IADsAcePrivate *pPrivAce = NULL;
  854. hr = pAccessControlEntry->get_AceType((LONG *)&dwAceType);
  855. BAIL_ON_FAILURE(hr);
  856. hr = pAccessControlEntry->get_Trustee(&bstrTrustee);
  857. BAIL_ON_FAILURE(hr);
  858. //
  859. // We need to see if we can use a cached SID here.
  860. //
  861. hr = pAccessControlEntry->QueryInterface(
  862. IID_IADsAcePrivate,
  863. (void **)&pPrivAce
  864. );
  865. if (SUCCEEDED(hr)) {
  866. //
  867. // See if the SID is valid and if so try and retrieve it.
  868. //
  869. hr = pPrivAce->isSidValid(&fSidValid);
  870. if (SUCCEEDED(hr) && fSidValid) {
  871. hr = pPrivAce->getSid(
  872. &pSid,
  873. &dwSidSize
  874. );
  875. if (SUCCEEDED(hr)) {
  876. fLookupTrustee = FALSE;
  877. }
  878. }
  879. }
  880. if (fLookupTrustee) {
  881. hr = ConvertTrusteeToSid(
  882. pszServerName,
  883. Credentials,
  884. bstrTrustee,
  885. &pSid,
  886. &dwSidSize,
  887. fNTDSType
  888. );
  889. }
  890. BAIL_ON_FAILURE(hr);
  891. hr = pAccessControlEntry->get_AceFlags((long *)&dwAceFlags);
  892. BAIL_ON_FAILURE(hr);
  893. hr = pAccessControlEntry->get_AccessMask((long *)&dwAccessMask);
  894. BAIL_ON_FAILURE(hr);
  895. //
  896. // we will compensateby adding the entire ACE size
  897. //
  898. dwAceSize = dwSidSize - sizeof(ULONG);
  899. switch (dwAceType) {
  900. case ACCESS_ALLOWED_ACE_TYPE:
  901. dwAceSize += sizeof(ACCESS_ALLOWED_ACE);
  902. pAce = (LPBYTE)AllocADsMem(dwAceSize);
  903. if (!pAce) {
  904. hr = E_OUTOFMEMORY;
  905. BAIL_ON_FAILURE(hr);
  906. }
  907. pAceHeader = (PACE_HEADER)pAce;
  908. pAceHeader->AceType = (UCHAR)dwAceType;
  909. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  910. pAceHeader->AceSize = (USHORT)dwAceSize;
  911. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  912. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  913. pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK));
  914. memcpy(pSidAddress, pSid, dwSidSize);
  915. break;
  916. case ACCESS_DENIED_ACE_TYPE:
  917. dwAceSize += sizeof(ACCESS_ALLOWED_ACE);
  918. pAce = (LPBYTE)AllocADsMem(dwAceSize);
  919. if (!pAce) {
  920. hr = E_OUTOFMEMORY;
  921. BAIL_ON_FAILURE(hr);
  922. }
  923. pAceHeader = (PACE_HEADER)pAce;
  924. pAceHeader->AceType = (UCHAR)dwAceType;
  925. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  926. pAceHeader->AceSize = (USHORT)dwAceSize;
  927. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  928. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  929. pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK));
  930. memcpy(pSidAddress, pSid, dwSidSize);
  931. break;
  932. case SYSTEM_AUDIT_ACE_TYPE:
  933. dwAceSize += sizeof(ACCESS_ALLOWED_ACE);
  934. pAce = (LPBYTE)AllocADsMem(dwAceSize);
  935. if (!pAce) {
  936. hr = E_OUTOFMEMORY;
  937. BAIL_ON_FAILURE(hr);
  938. }
  939. pAceHeader = (PACE_HEADER)pAce;
  940. pAceHeader->AceType = (UCHAR)dwAceType;
  941. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  942. pAceHeader->AceSize = (USHORT)dwAceSize;
  943. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  944. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  945. pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK));
  946. memcpy(pSidAddress, pSid, dwSidSize);
  947. break;
  948. case SYSTEM_ALARM_ACE_TYPE:
  949. dwAceSize += sizeof(ACCESS_ALLOWED_ACE);
  950. pAce = (LPBYTE)AllocADsMem(dwAceSize);
  951. if (!pAce) {
  952. hr = E_OUTOFMEMORY;
  953. BAIL_ON_FAILURE(hr);
  954. }
  955. pAceHeader = (PACE_HEADER)pAce;
  956. pAceHeader->AceType = (UCHAR)dwAceType;
  957. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  958. pAceHeader->AceSize = (USHORT)dwAceSize;
  959. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  960. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  961. pSidAddress = (PSID)((LPBYTE)pAccessMask + sizeof(ACCESS_MASK));
  962. memcpy(pSidAddress, pSid, dwSidSize);
  963. break;
  964. case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
  965. dwAceSize += sizeof(COMPOUND_ACCESS_ALLOWED_ACE);
  966. pAce = (LPBYTE)AllocADsMem(dwAceSize);
  967. if (!pAce) {
  968. hr = E_OUTOFMEMORY;
  969. BAIL_ON_FAILURE(hr);
  970. }
  971. pAceHeader = (PACE_HEADER)pAce;
  972. pAceHeader->AceType = (UCHAR)dwAceType;
  973. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  974. pAceHeader->AceSize = (USHORT)dwAceSize;
  975. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  976. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  977. pCompoundAceType = (PUSHORT)(pAccessMask + sizeof(ACCESS_MASK));
  978. *pCompoundAceType = (USHORT)dwCompoundAceType;
  979. //
  980. // Fill in the reserved field here.
  981. //
  982. pSidAddress = (PSID)((LPBYTE)pCompoundAceType + sizeof(DWORD));
  983. memcpy(pSidAddress, pSid, dwSidSize);
  984. break;
  985. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  986. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  987. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  988. case SYSTEM_ALARM_OBJECT_ACE_TYPE:
  989. hr = pAccessControlEntry->get_AceFlags((LONG *)&dwAceFlags);
  990. BAIL_ON_FAILURE(hr);
  991. hr = pAccessControlEntry->get_Flags((LONG *)&dwFlags);
  992. BAIL_ON_FAILURE(hr);
  993. if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
  994. dwAceSize += sizeof(GUID);
  995. }
  996. if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
  997. dwAceSize += sizeof(GUID);
  998. }
  999. hr = pAccessControlEntry->get_ObjectType(&bstrObjectTypeClsid);
  1000. BAIL_ON_FAILURE(hr);
  1001. hr = CLSIDFromString(bstrObjectTypeClsid, &ObjectTypeGUID);
  1002. BAIL_ON_FAILURE(hr);
  1003. hr = pAccessControlEntry->get_InheritedObjectType(&bstrInheritedObjectTypeClsid);
  1004. BAIL_ON_FAILURE(hr);
  1005. hr = CLSIDFromString(bstrInheritedObjectTypeClsid, &InheritedObjectTypeGUID);
  1006. BAIL_ON_FAILURE(hr);
  1007. dwAceSize += sizeof(ACCESS_ALLOWED_OBJECT_ACE);
  1008. pAce = (LPBYTE)AllocADsMem(dwAceSize);
  1009. if (!pAce) {
  1010. hr = E_OUTOFMEMORY;
  1011. BAIL_ON_FAILURE(hr);
  1012. }
  1013. pAceHeader = (PACE_HEADER)pAce;
  1014. pAceHeader->AceType = (UCHAR)dwAceType;
  1015. pAceHeader->AceFlags = (UCHAR)dwAceFlags;
  1016. pAceHeader->AceSize = (USHORT)dwAceSize;
  1017. pAccessMask = (PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  1018. *pAccessMask = (ACCESS_MASK)dwAccessMask;
  1019. //
  1020. // Fill in Flags
  1021. //
  1022. pOffset = (LPBYTE)((LPBYTE)pAceHeader + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK));
  1023. pFlags = (PULONG)(pOffset);
  1024. *pFlags = dwFlags;
  1025. pOffset += sizeof(ULONG);
  1026. if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
  1027. memcpy(pOffset, &ObjectTypeGUID, sizeof(GUID));
  1028. pOffset += sizeof(GUID);
  1029. }
  1030. if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
  1031. memcpy(pOffset, &InheritedObjectTypeGUID, sizeof(GUID));
  1032. pOffset += sizeof(GUID);
  1033. }
  1034. pSidAddress = (PSID)((LPBYTE)pOffset);
  1035. memcpy(pSidAddress, pSid, dwSidSize);
  1036. break;
  1037. default:
  1038. hr = HRESULT_FROM_WIN32(ERROR_INVALID_ACL);
  1039. BAIL_ON_FAILURE(hr);
  1040. break;
  1041. }
  1042. *ppAce = pAce;
  1043. error:
  1044. if (bstrTrustee) {
  1045. ADsFreeString(bstrTrustee);
  1046. }
  1047. if (pSid) {
  1048. FreeADsMem(pSid);
  1049. }
  1050. if (bstrObjectTypeClsid) {
  1051. SysFreeString(bstrObjectTypeClsid);
  1052. }
  1053. if (bstrInheritedObjectTypeClsid) {
  1054. SysFreeString(bstrInheritedObjectTypeClsid);
  1055. }
  1056. if (pPrivAce) {
  1057. pPrivAce->Release();
  1058. }
  1059. RRETURN(hr);
  1060. }
  1061. HRESULT
  1062. ComputeTotalAclSize(
  1063. PACE_HEADER * ppAceHdr,
  1064. DWORD dwAceCount,
  1065. PDWORD pdwAclSize
  1066. )
  1067. {
  1068. DWORD i = 0;
  1069. PACE_HEADER pAceHdr = NULL;
  1070. DWORD dwAceSize = 0;
  1071. DWORD dwAclSize = 0;
  1072. for (i = 0; i < dwAceCount; i++) {
  1073. pAceHdr = *(ppAceHdr + i);
  1074. dwAceSize = pAceHdr->AceSize;
  1075. dwAclSize += dwAceSize;
  1076. }
  1077. dwAclSize += sizeof(ACL);
  1078. *pdwAclSize = dwAclSize;
  1079. RRETURN(S_OK);
  1080. }
  1081. HRESULT
  1082. ParseAccountName(LPWSTR szFullAccountName,
  1083. LPWSTR *pszUserDomainName,
  1084. LPWSTR *pszUserAccountName)
  1085. {
  1086. HRESULT hr = S_OK;
  1087. DWORD dwDomain = 0;
  1088. BOOLEAN bFound = FALSE;
  1089. LPWSTR szUserDomainName = NULL;
  1090. LPWSTR szUserAccountName = NULL;
  1091. LPWSTR szCount = szFullAccountName;
  1092. if (!szFullAccountName) {
  1093. hr = E_FAIL;
  1094. BAIL_ON_FAILURE(hr);
  1095. }
  1096. while (*szCount) {
  1097. if (*szCount == '\\') {
  1098. bFound = TRUE;
  1099. break;
  1100. }
  1101. dwDomain++;
  1102. szCount++;
  1103. }
  1104. if (bFound) {
  1105. DWORD dwRest = 0;
  1106. szUserDomainName = (LPWSTR)AllocADsMem(sizeof(WCHAR) * (dwDomain+1));
  1107. if (!szUserDomainName) {
  1108. hr = E_OUTOFMEMORY;
  1109. BAIL_ON_FAILURE(hr);
  1110. }
  1111. wcsncpy(szUserDomainName,
  1112. szFullAccountName,
  1113. dwDomain);
  1114. wcscat(szUserDomainName, L"\0");
  1115. szUserAccountName = AllocADsStr(szCount+1);
  1116. if (!szUserAccountName) {
  1117. hr = E_OUTOFMEMORY;
  1118. BAIL_ON_FAILURE(hr);
  1119. }
  1120. }
  1121. else {
  1122. szUserAccountName = AllocADsStr(szFullAccountName);
  1123. if (!szUserAccountName) {
  1124. hr = E_OUTOFMEMORY;
  1125. BAIL_ON_FAILURE(hr);
  1126. }
  1127. szUserDomainName = NULL;
  1128. }
  1129. *pszUserAccountName = szUserAccountName;
  1130. *pszUserDomainName = szUserDomainName;
  1131. return hr;
  1132. error:
  1133. if (szUserAccountName) {
  1134. FreeADsMem(szUserAccountName);
  1135. }
  1136. if (szUserDomainName) {
  1137. FreeADsMem(szUserDomainName);
  1138. }
  1139. return hr;
  1140. }
  1141. HRESULT
  1142. ConvertTrusteeToSid(
  1143. LPWSTR pszServerName,
  1144. CCredentials& Credentials,
  1145. BSTR bstrTrustee,
  1146. PSID * ppSid,
  1147. PDWORD pdwSidSize,
  1148. BOOL fNTDSType
  1149. )
  1150. {
  1151. HRESULT hr = S_OK;
  1152. BYTE Sid[MAX_PATH];
  1153. DWORD dwSidSize = sizeof(Sid);
  1154. DWORD dwRet = 0;
  1155. DWORD dwErr = 0;
  1156. WCHAR szDomainName[MAX_PATH];
  1157. DWORD dwDomainSize = sizeof(szDomainName)/sizeof(WCHAR);
  1158. SID_NAME_USE eUse;
  1159. PSID pSid = NULL;
  1160. LPWSTR pszEnd = NULL;
  1161. LPWSTR szUserDomainName = NULL;
  1162. LPWSTR szUserAccountName = NULL;
  1163. LPWSTR szAccountName = NULL;
  1164. BOOL fForceVerify = FALSE;
  1165. //
  1166. // Load the strings into table if necessary
  1167. //
  1168. if (!g_fStringsLoaded) {
  1169. EnterCriticalSection(&g_StringsCriticalSection);
  1170. //
  1171. // Verify flag again.
  1172. //
  1173. if (!g_fStringsLoaded) {
  1174. dwRet = LoadStringW(
  1175. g_hInst,
  1176. ADS_BUILTIN,
  1177. g_szBuiltin,
  1178. sizeof( g_szBuiltin ) / sizeof( WCHAR )
  1179. );
  1180. if (!dwRet) {
  1181. //
  1182. // Default to English values.
  1183. //
  1184. wcscpy(g_szBuiltin, L"BUILTIN");
  1185. }
  1186. dwRet = LoadStringW(
  1187. g_hInst,
  1188. ADS_NT_AUTHORITY,
  1189. g_szNT_Authority,
  1190. sizeof( g_szNT_Authority ) / sizeof( WCHAR )
  1191. );
  1192. if (!dwRet) {
  1193. //
  1194. // Default to English values.
  1195. //
  1196. wcscpy(g_szNT_Authority, L"NT AUTHORITY");
  1197. }
  1198. dwRet = LoadStringW(
  1199. g_hInst,
  1200. ADS_ACCOUNT_OPERATORS,
  1201. g_szAccountOperators,
  1202. sizeof( g_szAccountOperators ) / sizeof( WCHAR )
  1203. );
  1204. if (!dwRet) {
  1205. //
  1206. // Default to English values.
  1207. //
  1208. wcscpy(g_szAccountOperators, L"Account Operators");
  1209. }
  1210. dwRet = LoadStringW(
  1211. g_hInst,
  1212. ADS_PRINT_OPERATORS,
  1213. g_szPrintOperators,
  1214. sizeof( g_szPrintOperators ) / sizeof( WCHAR )
  1215. );
  1216. if (!dwRet) {
  1217. //
  1218. // Default to English values.
  1219. //
  1220. wcscpy(g_szPrintOperators, L"Print Operators");
  1221. }
  1222. dwRet = LoadStringW(
  1223. g_hInst,
  1224. ADS_BACKUP_OPERATORS,
  1225. g_szBackupOperators,
  1226. sizeof( g_szBackupOperators ) / sizeof( WCHAR )
  1227. );
  1228. if (!dwRet) {
  1229. //
  1230. // Default to English values.
  1231. //
  1232. wcscpy(g_szBackupOperators, L"Backup Operators");
  1233. }
  1234. dwRet = LoadStringW(
  1235. g_hInst,
  1236. ADS_SERVER_OPERATORS,
  1237. g_szServerOperators,
  1238. sizeof( g_szServerOperators ) / sizeof( WCHAR )
  1239. );
  1240. if (!dwRet) {
  1241. //
  1242. // Default to English values.
  1243. //
  1244. wcscpy(g_szServerOperators, L"Server Operators");
  1245. }
  1246. dwRet = LoadStringW(
  1247. g_hInst,
  1248. ADS_PRE_WIN2000,
  1249. g_szPreWindows2000,
  1250. sizeof( g_szPreWindows2000 ) / sizeof( WCHAR )
  1251. );
  1252. if (!dwRet) {
  1253. //
  1254. // Default to English values.
  1255. //
  1256. wcscpy(
  1257. g_szPreWindows2000,
  1258. L"Pre-Windows 2000 Compatible Access"
  1259. );
  1260. }
  1261. }
  1262. g_fStringsLoaded = TRUE;
  1263. LeaveCriticalSection(&g_StringsCriticalSection);
  1264. }
  1265. //
  1266. //
  1267. // parse Trustee and determine whether its NTDS or U2
  1268. //
  1269. if (fNTDSType) {
  1270. WCHAR szDomainName[MAX_PATH];
  1271. WCHAR szServerName[MAX_PATH];
  1272. LPWSTR szLookupServer = NULL;
  1273. BOOL fSpecialLookup = FALSE;
  1274. BOOL fLookupOnServer = FALSE;
  1275. DWORD dwTmpSidLen = 0;
  1276. dwSidSize = sizeof(Sid);
  1277. szAccountName = bstrTrustee;
  1278. hr = ParseAccountName(bstrTrustee,
  1279. &szUserDomainName,
  1280. &szUserAccountName);
  1281. BAIL_ON_FAILURE(hr);
  1282. //
  1283. // Need to look these up on the server only.
  1284. //
  1285. if (szUserAccountName
  1286. && ((_wcsicmp(szUserAccountName, g_szAccountOperators) == 0)
  1287. || (_wcsicmp(szUserAccountName, g_szPrintOperators) == 0)
  1288. || (_wcsicmp(szUserAccountName, g_szBackupOperators) == 0)
  1289. || (_wcsicmp(szUserAccountName, g_szServerOperators) == 0)
  1290. || (_wcsicmp(szUserAccountName, g_szPreWindows2000) == 0)
  1291. )
  1292. ) {
  1293. if (szUserDomainName
  1294. && (_wcsicmp(szUserDomainName, g_szBuiltin)) == 0) {
  1295. fSpecialLookup = TRUE;
  1296. } else {
  1297. fSpecialLookup = FALSE;
  1298. }
  1299. } // special users
  1300. if (fSpecialLookup ||
  1301. (szUserDomainName &&
  1302. (_wcsicmp(szUserDomainName, g_szBuiltin) != 0) &&
  1303. (_wcsicmp(szUserDomainName, g_szNT_Authority) != 0))
  1304. ) {
  1305. //
  1306. // We will come back here and do a force retry
  1307. // if the server is down.
  1308. //
  1309. retryForce:
  1310. //
  1311. // Force hr to S_OK. This will be needed especially
  1312. // when we jump to the retryForce label.
  1313. //
  1314. hr = S_OK;
  1315. //
  1316. // Set Lookup on server to true so that later
  1317. // on we do not do the lookup on the server again.
  1318. // In some cases just like we fall back to local machine,
  1319. // we need to look at the server if the local machine fails.
  1320. // this will be the case for mixed locale domains.
  1321. //
  1322. DWORD dwStatus = GetDomainDNSNameForDomain(
  1323. fSpecialLookup ?
  1324. NULL :
  1325. szUserDomainName,
  1326. fForceVerify, // forceVerify
  1327. FALSE,
  1328. szServerName,
  1329. szDomainName
  1330. );
  1331. fLookupOnServer = TRUE;
  1332. if (dwStatus) {
  1333. szLookupServer = NULL;
  1334. }
  1335. else {
  1336. szLookupServer = szServerName;
  1337. }
  1338. szAccountName = szUserAccountName;
  1339. }
  1340. dwRet = LookupAccountName(
  1341. szLookupServer,
  1342. bstrTrustee,
  1343. Sid,
  1344. &dwSidSize,
  1345. szDomainName,
  1346. &dwDomainSize,
  1347. (PSID_NAME_USE)&eUse
  1348. );
  1349. if (!dwRet) {
  1350. hr = HRESULT_FROM_WIN32(GetLastError());
  1351. }
  1352. else {
  1353. //
  1354. // Update the length of the SID.
  1355. //
  1356. //
  1357. // Call needed on NT4 where GetLenghtSid does not
  1358. // reset the error correctly leading to false errors.
  1359. //
  1360. SetLastError(NO_ERROR);
  1361. dwTmpSidLen = GetLengthSid(Sid);
  1362. if ((dwRet = GetLastError()) == NO_ERROR) {
  1363. //
  1364. // Got the correct length so update dwSidSize
  1365. //
  1366. dwSidSize = dwTmpSidLen;
  1367. }
  1368. }
  1369. if (FAILED(hr)
  1370. && hr != HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)) {
  1371. //
  1372. // This code path should not be hit often but it can
  1373. // happen on multi locale domains. The server when might
  1374. // have returned say Builtin instead of german for the same.
  1375. // If the client is german we will be looking for germanbuiltin
  1376. // and that wont work. The lookup will fail locally but
  1377. // will succeed on the server. This is especially true for
  1378. // Builtin\Print Operators as that can only be resolved on the DC.
  1379. //
  1380. if (pszServerName) {
  1381. //
  1382. // Before we do a dsgetdc, we should try with
  1383. // the serverName passed in.
  1384. //
  1385. hr = S_OK;
  1386. dwRet = LookupAccountName(
  1387. pszServerName,
  1388. bstrTrustee,
  1389. Sid,
  1390. &dwSidSize,
  1391. szDomainName,
  1392. &dwDomainSize,
  1393. (PSID_NAME_USE)&eUse
  1394. );
  1395. if (!dwRet) {
  1396. hr = HRESULT_FROM_WIN32(GetLastError());
  1397. //
  1398. // force server name to NULL so we wont
  1399. // try this again.
  1400. //
  1401. pszServerName = NULL;
  1402. }
  1403. else {
  1404. //
  1405. // Update the length of the SID.
  1406. //
  1407. //
  1408. // Call needed on NT4 where GetLenghtSid does not
  1409. // reset the error correctly leading to false errors.
  1410. //
  1411. SetLastError(NO_ERROR);
  1412. dwTmpSidLen = GetLengthSid(Sid);
  1413. if ((dwRet = GetLastError()) == NO_ERROR) {
  1414. //
  1415. // Got the correct length so update dwSidSize
  1416. //
  1417. dwSidSize = dwTmpSidLen;
  1418. }
  1419. }
  1420. }
  1421. if (FAILED(hr)) {
  1422. //
  1423. // We could be here if either pszServerName was always
  1424. // NULL or if the call to the server failed.
  1425. // The only thing we can do is to retry if we know
  1426. // that the szLookupServer was NULL (that is local machine)
  1427. // or if szLookupServer was something other than the default
  1428. // server for the machine (that is we called DsGetDC with
  1429. // the name of a domain rather than NULL).
  1430. // In all other cases we should not retry and just return
  1431. // the error.
  1432. //
  1433. if (fSpecialLookup) {
  1434. //
  1435. // We should not retry in this case as we will not
  1436. // get anything useful. Setting fLookupOnServer
  1437. // to true will force this (if you look above this
  1438. // is not really needed but it helps clear things)
  1439. //
  1440. fLookupOnServer = TRUE;
  1441. }
  1442. else {
  1443. //
  1444. // This was not a special lookup, so we
  1445. // need to retry irrespective of what
  1446. // szLookupServer was.
  1447. //
  1448. fLookupOnServer = FALSE;
  1449. szLookupServer = NULL;
  1450. }
  1451. }
  1452. //
  1453. // This will do the correct thing even if the above
  1454. // LookUpCall failed. If not we should go down this
  1455. // as we can get stuck in an infinite loop.
  1456. //
  1457. if (FAILED(hr)
  1458. && !pszServerName
  1459. && !szLookupServer
  1460. && !fLookupOnServer
  1461. ) {
  1462. //
  1463. // In this case we want to try and call
  1464. // DsGetDCName and hopefully we will get the right
  1465. // DC. fSpecialLookup will be true so that we go to
  1466. // the default DC for the machine/user.
  1467. //
  1468. fSpecialLookup = TRUE;
  1469. goto retryForce;
  1470. }
  1471. }
  1472. //
  1473. // If failure was due to an expected error then retry
  1474. //
  1475. if (FAILED(hr)
  1476. && hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)
  1477. ) {
  1478. if (!fForceVerify) {
  1479. fForceVerify = TRUE;
  1480. goto retryForce;
  1481. }
  1482. }
  1483. }else {
  1484. //
  1485. // We know that LookupAccountName failed,
  1486. // so now try the U2 DS
  1487. //
  1488. dwSidSize = 0;
  1489. hr = ConvertU2TrusteeToSid(
  1490. pszServerName,
  1491. Credentials,
  1492. bstrTrustee,
  1493. Sid,
  1494. &dwSidSize
  1495. );
  1496. }
  1497. //
  1498. // If neither the NTDS nor the U2 conversion
  1499. // worked, then try a textual translation
  1500. //
  1501. if (FAILED(hr)) {
  1502. hr = ConvertStringToSid(
  1503. bstrTrustee,
  1504. &pSid,
  1505. &dwSidSize,
  1506. &pszEnd
  1507. );
  1508. BAIL_ON_FAILURE(hr);
  1509. memcpy(Sid,pSid, dwSidSize);
  1510. if (pSid) {
  1511. FreeADsMem(pSid);
  1512. }
  1513. }
  1514. //
  1515. // On NT4 for some reason GetLengthSID does not set lasterror to 0
  1516. //
  1517. SetLastError(NO_ERROR);
  1518. dwSidSize = GetLengthSid((PSID) Sid);
  1519. dwErr = GetLastError();
  1520. //
  1521. // This is an extra check to make sure that we have the
  1522. // correct length.
  1523. //
  1524. if (dwErr != NO_ERROR) {
  1525. hr = HRESULT_FROM_WIN32(dwErr);
  1526. }
  1527. BAIL_ON_FAILURE(hr); ;
  1528. pSid = AllocADsMem(dwSidSize);
  1529. if (!pSid) {
  1530. hr = E_OUTOFMEMORY;
  1531. BAIL_ON_FAILURE(hr);
  1532. }
  1533. memcpy(pSid, Sid, dwSidSize);
  1534. *pdwSidSize = dwSidSize;
  1535. *ppSid = pSid;
  1536. error:
  1537. if (szUserDomainName) {
  1538. FreeADsStr(szUserDomainName);
  1539. };
  1540. if (szUserAccountName) {
  1541. FreeADsStr(szUserAccountName);
  1542. }
  1543. RRETURN(hr);
  1544. }
  1545. /*
  1546. +--------------------------------------------------------------------------------+
  1547. NAME: get_sid_out_of_string
  1548. FUNCTION: Convert a string representation of a SID back into
  1549. a sid. The expected format of the string is:
  1550. L"S-1-5-32-549"
  1551. If a string in a different format or an incorrect or
  1552. incomplete string is given, the operation is failed.
  1553. The returned sid must be free via a call to SEC_FREE.
  1554. Arguments:
  1555. string - The wide string to be converted
  1556. sid - Where the created SID is to be returned
  1557. end - Where in the string we stopped processing
  1558. RETURN:
  1559. NTSTATUS error codes or success.
  1560. +--------------------------------------------------------------------------------+
  1561. */
  1562. HRESULT
  1563. ConvertStringToSid(
  1564. IN PWSTR string,
  1565. OUT PSID *sid,
  1566. OUT PDWORD pdwSidSize,
  1567. OUT PWSTR *end
  1568. )
  1569. {
  1570. HRESULT hr = S_OK;
  1571. UCHAR revision;
  1572. UCHAR sub_authority_count;
  1573. SID_IDENTIFIER_AUTHORITY authority;
  1574. ULONG sub_authority[SID_MAX_SUB_AUTHORITIES];
  1575. PWSTR end_list;
  1576. PWSTR current;
  1577. PWSTR next;
  1578. ULONG x;
  1579. *sid = NULL;
  1580. if (((*string != L'S') && (*string != L's')) || (*(string + 1) != L'-'))
  1581. {
  1582. hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID);
  1583. BAIL_ON_FAILURE(hr);
  1584. }
  1585. current = string + 2;
  1586. revision = (UCHAR)wcstol(current, &end_list, 10);
  1587. current = end_list + 1;
  1588. //
  1589. // Count the number of characters in the indentifer authority...
  1590. //
  1591. next = wcschr(current, L'-');
  1592. if (!next) {
  1593. hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID);
  1594. BAIL_ON_FAILURE(hr);
  1595. }
  1596. if(next - current == 6)
  1597. {
  1598. for(x = 0; x < 6; x++)
  1599. {
  1600. authority.Value[x] = (UCHAR)next[x];
  1601. }
  1602. current +=6;
  1603. }
  1604. else
  1605. {
  1606. ULONG Auto = wcstoul(current, &end_list, 10);
  1607. authority.Value[0] = authority.Value[1] = 0;
  1608. authority.Value[5] = (UCHAR)Auto & 0xF;
  1609. authority.Value[4] = (UCHAR)((Auto >> 8) & 0xFF);
  1610. authority.Value[3] = (UCHAR)((Auto >> 16) & 0xFF);
  1611. authority.Value[2] = (UCHAR)((Auto >> 24) & 0xFF);
  1612. current = end_list;
  1613. }
  1614. //
  1615. // Now, count the number of sub auths
  1616. //
  1617. sub_authority_count = 0;
  1618. next = current;
  1619. //
  1620. // We'll have to count our sub authoritys one character at a time,
  1621. // since there are several deliminators that we can have...
  1622. //
  1623. while(next)
  1624. {
  1625. next++;
  1626. if(*next == L'-')
  1627. {
  1628. //
  1629. // We've found one!
  1630. //
  1631. sub_authority_count++;
  1632. }
  1633. else if(*next == L';' || *next == L'\0')
  1634. {
  1635. *end = next;
  1636. sub_authority_count++;
  1637. break;
  1638. }
  1639. }
  1640. if(sub_authority_count != 0)
  1641. {
  1642. current++;
  1643. for(x = 0; x < sub_authority_count; x++)
  1644. {
  1645. sub_authority[x] = wcstoul(current, &end_list, 10);
  1646. current = end_list + 1;
  1647. }
  1648. }
  1649. //
  1650. // Now, create the SID
  1651. //
  1652. hr = SecCreateSidFromArray(
  1653. sid,
  1654. &authority,
  1655. sub_authority_count,
  1656. sub_authority,
  1657. pdwSidSize
  1658. );
  1659. if (SUCCEEDED(hr))
  1660. {
  1661. /* Set the revision to what was specified in the string, in case, our
  1662. system creates one with newer revision */
  1663. ((SID *)(*sid))->Revision = revision;
  1664. }
  1665. error:
  1666. RRETURN(hr);
  1667. }
  1668. HRESULT
  1669. SecCreateSidFromArray (
  1670. OUT PSID *PPSid,
  1671. IN PSID_IDENTIFIER_AUTHORITY PSidAuthority,
  1672. IN UCHAR SubAuthorityCount,
  1673. IN ULONG SubAuthorities[],
  1674. OUT PDWORD pdwSidSize
  1675. )
  1676. /*++
  1677. Routine Description:
  1678. Creates a SID with desired authority and sub authorities.
  1679. NOTE: This routine allocates memory for the SID. When finished
  1680. the caller should free memory using SEC_FREE (PSid).
  1681. Arguments:
  1682. PPSid -- addr of ptr to SID to be created
  1683. Note: if SID creation fails ptr set to NULL
  1684. PSidAuthority -- desired value for SID authority
  1685. SubAuthorityCount -- number of sub authorities desired
  1686. SubAuthorities -- sub-authority values, MUST SPECIFY contain
  1687. at least SubAuthorityCount number of values
  1688. Return Value:
  1689. STATUS_SUCCESS if SID created.
  1690. STATUS_UNSUCCESSFUL otherwise.
  1691. --*/
  1692. {
  1693. USHORT iSub; /* sub-authority index */
  1694. DWORD dwSidSize = 0;
  1695. HRESULT hr = S_OK;
  1696. /* allocate memory for SID */
  1697. dwSidSize = RtlLengthRequiredSid(SubAuthorityCount);
  1698. *PPSid = (PSID) AllocADsMem( dwSidSize );
  1699. if (! *PPSid){
  1700. hr = E_OUTOFMEMORY;
  1701. BAIL_ON_FAILURE(hr);
  1702. }
  1703. *pdwSidSize = dwSidSize;
  1704. /* initialize SID with top level SID identifier authority */
  1705. RtlInitializeSid( *PPSid, PSidAuthority, SubAuthorityCount);
  1706. /* fill in sub authorities */
  1707. for (iSub=0; iSub < SubAuthorityCount; iSub++)
  1708. * RtlSubAuthoritySid( *PPSid, iSub) = SubAuthorities[iSub];
  1709. /* sanity check */
  1710. if ( ! RtlValidSid( *PPSid) ) {
  1711. FreeADsMem( *PPSid);
  1712. *PPSid = NULL;
  1713. hr = HRESULT_FROM_WIN32(ERROR_INVALID_SID);
  1714. BAIL_ON_FAILURE(hr);
  1715. }
  1716. error:
  1717. RRETURN(hr);
  1718. }
  1719. BOOL
  1720. EquivalentServers(
  1721. LPWSTR pszTargetServer,
  1722. LPWSTR pszSourceServer
  1723. )
  1724. {
  1725. if (!pszTargetServer && !pszSourceServer) {
  1726. return(TRUE);
  1727. }
  1728. if (pszTargetServer && pszSourceServer) {
  1729. #ifdef WIN95
  1730. if (!_wcsicmp(pszTargetServer, pszSourceServer)) {
  1731. #else
  1732. if (CompareStringW(
  1733. LOCALE_SYSTEM_DEFAULT,
  1734. NORM_IGNORECASE,
  1735. pszTargetServer,
  1736. -1,
  1737. pszSourceServer,
  1738. -1
  1739. ) == CSTR_EQUAL ) {
  1740. #endif
  1741. return(TRUE);
  1742. }
  1743. }
  1744. return(FALSE);
  1745. }