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.

1558 lines
40 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. #define GetAce ADSIGetAce
  18. #define DeleteAce ADSIDeleteAce
  19. #define GetAclInformation ADSIGetAclInformation
  20. #define SetAclInformation ADSISetAclInformation
  21. #define IsValidAcl ADSIIsValidAcl
  22. #define InitializeAcl ADSIInitializeAcl
  23. extern HRESULT
  24. ConvertSidToString(
  25. PSID pSid,
  26. LPWSTR String
  27. );
  28. DWORD
  29. GetDomainDNSNameForDomain(
  30. LPWSTR pszDomainFlatName,
  31. BOOL fVerify,
  32. BOOL fWriteable,
  33. LPWSTR pszServerName,
  34. LPWSTR pszDomainDNSName
  35. );
  36. //
  37. // Helper routine.
  38. //
  39. PSID
  40. ComputeSidFromAceAddress(
  41. LPBYTE pAce
  42. );
  43. //+---------------------------------------------------------------------------
  44. // Function: GetLsaPolicyHandle - helper routine.
  45. //
  46. // Synopsis: Returns the lsa policy handle to the server in question.
  47. // If a serverName is present we will first try that. If no servername
  48. // is present we will try and connect up to the default server for the
  49. // currently logged on user. If everything else fails, we will
  50. // connnect to the local machine (NULL server).
  51. //
  52. // Arguments: pszServerName - Name of targtet server/domain or NULL.
  53. // Credentials - Credentials to use for the connection.
  54. // Currently this is not used.
  55. // phLsaPolicy - Return ptr for lsa policy handle.
  56. //
  57. // Returns: S_OK or any valid error code.
  58. //
  59. // Modifies: phLsaPolicy.
  60. //
  61. //----------------------------------------------------------------------------
  62. HRESULT
  63. GetLsaPolicyHandle(
  64. LPWSTR pszServerName,
  65. CCredentials &Credentials,
  66. PLSA_HANDLE phLsaPolicy
  67. )
  68. {
  69. HRESULT hr = S_OK;
  70. DWORD dwStatus = NO_ERROR;
  71. NTSTATUS ntStatus = STATUS_SUCCESS;
  72. DWORD dwErr;
  73. DWORD dwLen = 0;
  74. LPWSTR pszServer = NULL;
  75. BOOL fNullServer = FALSE;
  76. LSA_OBJECT_ATTRIBUTES lsaObjectAttributes;
  77. LSA_UNICODE_STRING lsaSystemName;
  78. WCHAR szDomainName[MAX_PATH];
  79. WCHAR szServerName[MAX_PATH];
  80. memset(&lsaObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES));
  81. //
  82. // First most common case of serverless paths.
  83. //
  84. if (!pszServerName) {
  85. dwStatus = GetDomainDNSNameForDomain(
  86. NULL,
  87. FALSE, // do not force verify
  88. FALSE, // does not need to be writable
  89. szServerName,
  90. szDomainName
  91. );
  92. //
  93. // If we succeeded we will use the name returned,
  94. // otherwise we will go with NULL.
  95. //
  96. if (dwStatus == NO_ERROR) {
  97. pszServer = szServerName;
  98. }
  99. else {
  100. fNullServer = TRUE;
  101. }
  102. }
  103. else {
  104. pszServer = pszServerName;
  105. }
  106. if (pszServer) {
  107. dwLen = wcslen(pszServer);
  108. }
  109. lsaSystemName.Buffer = pszServer;
  110. lsaSystemName.Length = dwLen * sizeof(WCHAR);
  111. lsaSystemName.MaximumLength = lsaSystemName.Length;
  112. //
  113. // First attempt at opening policy handle.
  114. //
  115. ntStatus = LsaOpenPolicy(
  116. &lsaSystemName,
  117. &lsaObjectAttributes,
  118. POLICY_LOOKUP_NAMES,
  119. phLsaPolicy
  120. );
  121. if (ntStatus != STATUS_SUCCESS) {
  122. //
  123. // Irrespective of failure should retry if we have not already
  124. // tried with a NULL serverName.
  125. //
  126. if (!fNullServer) {
  127. fNullServer = TRUE;
  128. lsaSystemName.Buffer = NULL;
  129. lsaSystemName.Length = 0;
  130. lsaSystemName.MaximumLength = 0;
  131. ntStatus = LsaOpenPolicy(
  132. &lsaSystemName,
  133. &lsaObjectAttributes,
  134. POLICY_LOOKUP_NAMES,
  135. phLsaPolicy
  136. );
  137. }
  138. hr = HRESULT_FROM_WIN32(
  139. LsaNtStatusToWinError(ntStatus)
  140. );
  141. BAIL_ON_FAILURE(hr);
  142. }
  143. error:
  144. RRETURN(hr);
  145. }
  146. //+---------------------------------------------------------------------------
  147. // Function: GetNamesFromSids - helper routine.
  148. //
  149. // Synopsis: Simple helper routine that calls LsaLookupSids and if the
  150. // the error returned is ERROR_SOME_NOT_MAPPED, then the hr is
  151. // set S_OK.
  152. //
  153. // Arguments: hLsaPolicy - LSA_HANDLE to do the lookup on.
  154. // pSidArray - Array of sid's top lookup.
  155. // dwSidCount - Number of sids to translate.
  156. // ppLsaRefDomList - Ret value for domain list.
  157. // ppLsaNames - Ret value for name list.
  158. //
  159. // Returns: S_OK or any valid error code.
  160. //
  161. // Modifies: n/a.
  162. //
  163. //----------------------------------------------------------------------------
  164. HRESULT
  165. GetNamesFromSids(
  166. LSA_HANDLE hLsaPolicy,
  167. PSID *pSidArray,
  168. DWORD dwSidCount,
  169. PLSA_REFERENCED_DOMAIN_LIST *ppLsaRefDomList,
  170. PLSA_TRANSLATED_NAME *ppLsaNames
  171. )
  172. {
  173. HRESULT hr = S_OK;
  174. NTSTATUS ntStatus;
  175. ntStatus = LsaLookupSids(
  176. hLsaPolicy,
  177. dwSidCount,
  178. pSidArray,
  179. ppLsaRefDomList,
  180. ppLsaNames
  181. );
  182. // even if the above call fails, we don't want to bail out since even if all the name resolving fails
  183. // we still want to try to use the stringlized sid
  184. RRETURN(hr);
  185. }
  186. //+---------------------------------------------------------------------------
  187. // Function: GetNamesForSidFromArray - helper routine.
  188. //
  189. // Synopsis: Given the position of the ace and the retrun value from
  190. // LsaLookupSids, constructs the actual name of the trustee.
  191. //
  192. // Arguments: dwAceNumber - Position of the ace in the array.
  193. // pLsaRefDoms - List of reference domains.
  194. // pLsaNames - List of LSA names.
  195. // ppszFriendlyName - Return string pointer.
  196. //
  197. // Returns: S_OK or any valid error code.
  198. //
  199. // Modifies: n/a.
  200. //
  201. //----------------------------------------------------------------------------
  202. HRESULT
  203. GetNameForSidFromArray(
  204. DWORD dwAceNumber,
  205. LSA_REFERENCED_DOMAIN_LIST *pLsaRefDoms,
  206. LSA_TRANSLATED_NAME *pLsaNames,
  207. LPWSTR * ppszFriendlyName
  208. )
  209. {
  210. HRESULT hr = S_OK;
  211. DWORD dwLengthDomain;
  212. DWORD dwLengthName = 0;
  213. BOOL fDomainInvalid = FALSE;
  214. BOOL fNameInvalid = FALSE;
  215. LPWSTR pszName = NULL;
  216. *ppszFriendlyName = NULL;
  217. if (!pLsaNames) {
  218. RRETURN(hr = E_FAIL);
  219. }
  220. switch (pLsaNames[dwAceNumber].Use) {
  221. case SidTypeDomain:
  222. fNameInvalid = TRUE;
  223. break;
  224. case SidTypeInvalid:
  225. fNameInvalid = TRUE;
  226. fDomainInvalid = TRUE;
  227. break;
  228. case SidTypeUnknown:
  229. fNameInvalid = TRUE;
  230. fDomainInvalid = TRUE;
  231. break;
  232. case SidTypeWellKnownGroup:
  233. if (pLsaNames[dwAceNumber].DomainIndex < 0 ) {
  234. fDomainInvalid = TRUE;
  235. }
  236. break;
  237. default:
  238. //
  239. // Name and domain are valid.
  240. //
  241. fDomainInvalid = FALSE;
  242. fNameInvalid = FALSE;
  243. }
  244. if (!fNameInvalid) {
  245. dwLengthName = ((pLsaNames[dwAceNumber]).Name).Length + sizeof(WCHAR);
  246. }
  247. //
  248. // Process domain if valid.
  249. //
  250. if (!fDomainInvalid) {
  251. DWORD domainIndex = pLsaNames[dwAceNumber].DomainIndex;
  252. LSA_UNICODE_STRING lsaString;
  253. //
  254. // Need to make sure that the index is valid.
  255. //
  256. if (domainIndex > pLsaRefDoms->Entries) {
  257. BAIL_ON_FAILURE(hr = E_FAIL);
  258. }
  259. lsaString = ((pLsaRefDoms->Domains)[domainIndex]).Name;
  260. //
  261. // Add sizeof(WCHAR) for the trailing \0.
  262. //
  263. dwLengthDomain = lsaString.Length + sizeof(WCHAR);
  264. if (lsaString.Length > 0) {
  265. pszName = (LPWSTR) AllocADsMem( dwLengthDomain + dwLengthName);
  266. if (!pszName) {
  267. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  268. }
  269. memcpy(
  270. pszName,
  271. lsaString.Buffer,
  272. lsaString.Length
  273. );
  274. }
  275. }
  276. if (!fNameInvalid) {
  277. LSA_UNICODE_STRING lsaNameString = (pLsaNames[dwAceNumber]).Name;
  278. //
  279. // Length of pszName is zero if the group name is Everyone but
  280. // there is still a domain name component.
  281. //
  282. if (!fDomainInvalid
  283. && pszName
  284. && wcslen(pszName)
  285. ) {
  286. wcscat(pszName, L"\\");
  287. } else {
  288. pszName = (LPWSTR) AllocADsMem(dwLengthName);
  289. if (!pszName) {
  290. BAIL_ON_FAILURE (hr = E_OUTOFMEMORY);
  291. }
  292. }
  293. memcpy(
  294. fDomainInvalid ? pszName : (pszName + wcslen(pszName)),
  295. lsaNameString.Buffer,
  296. lsaNameString.Length
  297. );
  298. }
  299. *ppszFriendlyName = pszName;
  300. RRETURN(hr);
  301. error:
  302. if (pszName) {
  303. FreeADsMem(pszName);
  304. }
  305. RRETURN(hr);
  306. }
  307. HRESULT
  308. ConvertSecDescriptorToVariant(
  309. LPWSTR pszServerName,
  310. CCredentials& Credentials,
  311. PSECURITY_DESCRIPTOR pSecurityDescriptor,
  312. VARIANT * pVarSec,
  313. BOOL fNTDS
  314. )
  315. {
  316. IADsSecurityDescriptor * pSecDes = NULL;
  317. IDispatch * pDispatch = NULL;
  318. LPWSTR pszGroup = NULL;
  319. LPWSTR pszOwner = NULL;
  320. BOOL fOwnerDefaulted = 0;
  321. BOOL fGroupDefaulted = 0;
  322. BOOL fDaclDefaulted = 0;
  323. BOOL fSaclDefaulted = 0;
  324. BOOL fSaclPresent = 0;
  325. BOOL fDaclPresent = 0;
  326. LPBYTE pOwnerSidAddress = NULL;
  327. LPBYTE pGroupSidAddress = NULL;
  328. LPBYTE pDACLAddress = NULL;
  329. LPBYTE pSACLAddress = NULL;
  330. DWORD dwRet = 0;
  331. VARIANT varDACL;
  332. VARIANT varSACL;
  333. HRESULT hr = S_OK;
  334. DWORD dwRevision = 0;
  335. WORD wControl = 0;
  336. VariantInit(pVarSec);
  337. memset(&varSACL, 0, sizeof(VARIANT));
  338. memset(&varDACL, 0, sizeof(VARIANT));
  339. if (!pSecurityDescriptor) {
  340. RRETURN(E_FAIL);
  341. }
  342. //
  343. // Control & Revision
  344. //
  345. dwRet = GetSecurityDescriptorControl(
  346. pSecurityDescriptor,
  347. &wControl,
  348. &dwRevision
  349. );
  350. if (!dwRet){
  351. hr = HRESULT_FROM_WIN32(GetLastError());
  352. BAIL_ON_FAILURE(hr);
  353. }
  354. //
  355. // Owner
  356. //
  357. dwRet = GetSecurityDescriptorOwner(
  358. pSecurityDescriptor,
  359. (PSID *)&pOwnerSidAddress,
  360. &fOwnerDefaulted
  361. );
  362. if (!dwRet){
  363. hr = HRESULT_FROM_WIN32(GetLastError());
  364. BAIL_ON_FAILURE(hr);
  365. }
  366. if (pOwnerSidAddress) {
  367. //
  368. // For Owner and Group, we will convert the sid in old way without optimization
  369. //
  370. hr = ConvertSidToFriendlyName2(
  371. pszServerName,
  372. Credentials,
  373. pOwnerSidAddress,
  374. &pszOwner,
  375. fNTDS
  376. );
  377. BAIL_ON_FAILURE(hr);
  378. }
  379. //
  380. // Group
  381. //
  382. dwRet = GetSecurityDescriptorGroup(
  383. pSecurityDescriptor,
  384. (PSID *)&pGroupSidAddress,
  385. &fOwnerDefaulted
  386. );
  387. if (!dwRet){
  388. hr = HRESULT_FROM_WIN32(GetLastError());
  389. BAIL_ON_FAILURE(hr);
  390. }
  391. if (pGroupSidAddress) {
  392. //
  393. // For Owner and Group, we will convert the sid in old way without optimization
  394. //
  395. hr = ConvertSidToFriendlyName2(
  396. pszServerName,
  397. Credentials,
  398. pGroupSidAddress,
  399. &pszGroup,
  400. fNTDS
  401. );
  402. BAIL_ON_FAILURE(hr);
  403. }
  404. //
  405. // DACL
  406. //
  407. dwRet = GetSecurityDescriptorDacl(
  408. pSecurityDescriptor,
  409. &fDaclPresent,
  410. (PACL*)&pDACLAddress,
  411. &fDaclDefaulted
  412. );
  413. if (!dwRet){
  414. hr = HRESULT_FROM_WIN32(GetLastError());
  415. BAIL_ON_FAILURE(hr);
  416. }
  417. if (pDACLAddress) {
  418. hr = ConvertACLToVariant(
  419. pszServerName,
  420. Credentials,
  421. (PACL)pDACLAddress,
  422. &varDACL,
  423. fNTDS
  424. );
  425. BAIL_ON_FAILURE(hr);
  426. }
  427. //
  428. // SACL
  429. //
  430. dwRet = GetSecurityDescriptorSacl(
  431. pSecurityDescriptor,
  432. &fSaclPresent,
  433. (PACL *)&pSACLAddress,
  434. &fSaclDefaulted
  435. );
  436. if (!dwRet){
  437. hr = HRESULT_FROM_WIN32(GetLastError());
  438. BAIL_ON_FAILURE(hr);
  439. }
  440. if (pSACLAddress) {
  441. hr = ConvertACLToVariant(
  442. pszServerName,
  443. Credentials,
  444. (PACL)pSACLAddress,
  445. &varSACL,
  446. fNTDS
  447. );
  448. BAIL_ON_FAILURE(hr);
  449. }
  450. //
  451. // Construct an IADsSecurityDescriptor with the data
  452. // retrieved from the raw SD
  453. //
  454. hr = CoCreateInstance(
  455. CLSID_SecurityDescriptor,
  456. NULL,
  457. CLSCTX_INPROC_SERVER,
  458. IID_IADsSecurityDescriptor,
  459. (void **)&pSecDes
  460. );
  461. BAIL_ON_FAILURE(hr);
  462. hr = pSecDes->put_Owner(pszOwner);
  463. BAIL_ON_FAILURE(hr);
  464. hr = pSecDes->put_Group(pszGroup);
  465. BAIL_ON_FAILURE(hr);
  466. hr = pSecDes->put_Revision(dwRevision);
  467. BAIL_ON_FAILURE(hr);
  468. hr = pSecDes->put_Control((DWORD)wControl);
  469. BAIL_ON_FAILURE(hr);
  470. hr = pSecDes->put_DiscretionaryAcl(V_DISPATCH(&varDACL));
  471. BAIL_ON_FAILURE(hr);
  472. hr = pSecDes->put_SystemAcl(V_DISPATCH(&varSACL));
  473. BAIL_ON_FAILURE(hr);
  474. hr = pSecDes->QueryInterface(IID_IDispatch, (void**)&pDispatch);
  475. BAIL_ON_FAILURE(hr);
  476. //
  477. // Construct a VARIANT with the IADsSecurityDescriptor
  478. //
  479. V_VT(pVarSec) = VT_DISPATCH;
  480. V_DISPATCH(pVarSec) = pDispatch;
  481. error:
  482. VariantClear(&varSACL);
  483. VariantClear(&varDACL);
  484. if (pszOwner) {
  485. FreeADsStr(pszOwner);
  486. }
  487. if (pszGroup) {
  488. FreeADsStr(pszGroup);
  489. }
  490. if (pSecDes) {
  491. pSecDes->Release();
  492. }
  493. RRETURN(hr);
  494. }
  495. HRESULT
  496. ConvertSidToFriendlyName(
  497. LPWSTR pszServerName,
  498. CCredentials& Credentials,
  499. PSID pSid,
  500. LPWSTR * ppszAccountName,
  501. BOOL fNTDS
  502. )
  503. {
  504. HRESULT hr = S_OK;
  505. SID_NAME_USE eUse;
  506. WCHAR szAccountName[MAX_PATH];
  507. WCHAR szDomainName[MAX_PATH];
  508. WCHAR szServerName[MAX_PATH];
  509. DWORD dwLen = 0;
  510. DWORD dwRet = 0;
  511. LPWSTR pszAccountName = NULL;
  512. DWORD dwAcctLen = 0;
  513. DWORD dwDomainLen = 0;
  514. #if 0
  515. /**************************************************************
  516. //
  517. // parse Trustee and determine whether its NTDS or U2
  518. //
  519. if (fNTDS) {
  520. dwAcctLen = sizeof(szAccountName);
  521. dwDomainLen = sizeof(szDomainName);
  522. dwRet = LookupAccountSid(
  523. pszServerName,
  524. pSid,
  525. szAccountName,
  526. &dwAcctLen,
  527. szDomainName,
  528. &dwDomainLen,
  529. (PSID_NAME_USE)&eUse
  530. );
  531. //
  532. // Try with NULL server name if we have not already
  533. // done that for error cases.
  534. //
  535. if (!dwRet && pszServerName) {
  536. dwRet = LookupAccountSid(
  537. NULL,
  538. pSid,
  539. szAccountName,
  540. &dwAcctLen,
  541. szDomainName,
  542. &dwDomainLen,
  543. (PSID_NAME_USE)&eUse
  544. );
  545. }
  546. //
  547. // If using serverless paths, try it on the DC if it
  548. // failed (which will happen if we're trying to resolve
  549. // something like "BUILTIN\Print Operators" on a member
  550. // computer)
  551. //
  552. if (!dwRet && !pszServerName) {
  553. dwAcctLen = sizeof(szAccountName);
  554. dwDomainLen = sizeof(szDomainName);
  555. DWORD dwStatus = GetDomainDNSNameForDomain(
  556. NULL,
  557. FALSE, // don't force verify
  558. FALSE, // not writable
  559. szServerName,
  560. szDomainName
  561. );
  562. if (dwStatus == NO_ERROR) {
  563. dwRet = LookupAccountSid(
  564. szServerName,
  565. pSid,
  566. szAccountName,
  567. &dwAcctLen,
  568. szDomainName,
  569. &dwDomainLen,
  570. (PSID_NAME_USE)&eUse
  571. );
  572. //
  573. // If the lookup failed because the server was unavailable, try to get
  574. // the server again, this time forcing DsGetDcName to do rediscovery
  575. //
  576. if (!dwRet && (GetLastError() == RPC_S_SERVER_UNAVAILABLE)) {
  577. dwStatus = GetDomainDNSNameForDomain(
  578. NULL,
  579. TRUE, // force verify
  580. FALSE,// not writable
  581. szServerName,
  582. szDomainName
  583. );
  584. if (dwStatus == NO_ERROR) {
  585. dwRet = LookupAccountSid(
  586. szServerName,
  587. pSid,
  588. szAccountName,
  589. &dwAcctLen,
  590. szDomainName,
  591. &dwDomainLen,
  592. (PSID_NAME_USE)&eUse
  593. );
  594. }
  595. }
  596. }
  597. }
  598. if (!dwRet) {
  599. hr = HRESULT_FROM_WIN32(GetLastError());
  600. }else {
  601. dwLen = wcslen(szAccountName) + wcslen(szDomainName) + 1 + 1;
  602. pszAccountName = (LPWSTR)AllocADsMem(dwLen * sizeof(WCHAR));
  603. if (!pszAccountName) {
  604. hr = E_OUTOFMEMORY;
  605. BAIL_ON_FAILURE(hr);
  606. }
  607. if (szDomainName[0] && szAccountName[0]) {
  608. wsprintf(pszAccountName,L"%s\\%s",szDomainName, szAccountName);
  609. }else if (szAccountName[0]) {
  610. wsprintf(pszAccountName,L"%s", szAccountName);
  611. }
  612. *ppszAccountName = pszAccountName;
  613. }
  614. }else {
  615. *****************************************************************/
  616. #endif
  617. if (!fNTDS) {
  618. hr = ConvertSidToU2Trustee(
  619. pszServerName,
  620. Credentials,
  621. pSid,
  622. szAccountName
  623. );
  624. if (SUCCEEDED(hr)) {
  625. pszAccountName = AllocADsStr(szAccountName);
  626. if (!pszAccountName) {
  627. hr = E_OUTOFMEMORY;
  628. BAIL_ON_FAILURE(hr);
  629. }
  630. *ppszAccountName = pszAccountName;
  631. }
  632. }
  633. else {
  634. //
  635. // This is NTDS case where we need to stringize SID.
  636. //
  637. hr = E_FAIL;
  638. }
  639. if (FAILED(hr)) {
  640. hr = ConvertSidToString(
  641. pSid,
  642. szAccountName
  643. );
  644. BAIL_ON_FAILURE(hr);
  645. pszAccountName = AllocADsStr(szAccountName);
  646. if (!pszAccountName) {
  647. hr = E_OUTOFMEMORY;
  648. BAIL_ON_FAILURE(hr);
  649. }
  650. *ppszAccountName = pszAccountName;
  651. }
  652. error:
  653. RRETURN(hr);
  654. }
  655. HRESULT
  656. ConvertSidToFriendlyName2(
  657. LPWSTR pszServerName,
  658. CCredentials& Credentials,
  659. PSID pSid,
  660. LPWSTR * ppszAccountName,
  661. BOOL fNTDS
  662. )
  663. {
  664. HRESULT hr = S_OK;
  665. SID_NAME_USE eUse;
  666. WCHAR szAccountName[MAX_PATH];
  667. WCHAR szDomainName[MAX_PATH];
  668. WCHAR szServerName[MAX_PATH];
  669. DWORD dwLen = 0;
  670. DWORD dwRet = 0;
  671. LPWSTR pszAccountName = NULL;
  672. DWORD dwAcctLen = 0;
  673. DWORD dwDomainLen = 0;
  674. //
  675. // parse Trustee and determine whether its NTDS or U2
  676. //
  677. if (fNTDS) {
  678. dwAcctLen = MAX_PATH;
  679. dwDomainLen = MAX_PATH;
  680. //
  681. // Servername is specified
  682. //
  683. if (pszServerName) {
  684. dwRet = LookupAccountSid(
  685. pszServerName,
  686. pSid,
  687. szAccountName,
  688. &dwAcctLen,
  689. szDomainName,
  690. &dwDomainLen,
  691. (PSID_NAME_USE)&eUse
  692. );
  693. }
  694. //
  695. // Servername not specified
  696. //
  697. else {
  698. //
  699. // If using serverless paths, try it first on the DC
  700. //
  701. DWORD dwStatus = GetDomainDNSNameForDomain(
  702. NULL,
  703. FALSE, // don't force verify
  704. FALSE, // not writable
  705. szServerName,
  706. szDomainName
  707. );
  708. if (dwStatus == NO_ERROR) {
  709. dwRet = LookupAccountSid(
  710. szServerName,
  711. pSid,
  712. szAccountName,
  713. &dwAcctLen,
  714. szDomainName,
  715. &dwDomainLen,
  716. (PSID_NAME_USE)&eUse
  717. );
  718. //
  719. // If the lookup failed because the server was unavailable, try to get
  720. // the server again, this time forcing DsGetDcName to do rediscovery
  721. //
  722. if (!dwRet && (GetLastError() == RPC_S_SERVER_UNAVAILABLE)) {
  723. dwStatus = GetDomainDNSNameForDomain(
  724. NULL,
  725. TRUE, // force verify
  726. FALSE,// not writable
  727. szServerName,
  728. szDomainName
  729. );
  730. if (dwStatus == NO_ERROR) {
  731. dwRet = LookupAccountSid(
  732. szServerName,
  733. pSid,
  734. szAccountName,
  735. &dwAcctLen,
  736. szDomainName,
  737. &dwDomainLen,
  738. (PSID_NAME_USE)&eUse
  739. );
  740. }
  741. }
  742. }
  743. }
  744. //
  745. // At last try with NULL server name
  746. //
  747. if (!dwRet) {
  748. dwAcctLen = MAX_PATH;
  749. dwDomainLen = MAX_PATH;
  750. dwRet = LookupAccountSid(
  751. NULL,
  752. pSid,
  753. szAccountName,
  754. &dwAcctLen,
  755. szDomainName,
  756. &dwDomainLen,
  757. (PSID_NAME_USE)&eUse
  758. );
  759. }
  760. if (!dwRet) {
  761. hr = HRESULT_FROM_WIN32(GetLastError());
  762. }else {
  763. dwLen = wcslen(szAccountName) + wcslen(szDomainName) + 1 + 1;
  764. pszAccountName = (LPWSTR)AllocADsMem(dwLen * sizeof(WCHAR));
  765. if (!pszAccountName) {
  766. hr = E_OUTOFMEMORY;
  767. BAIL_ON_FAILURE(hr);
  768. }
  769. if (szDomainName[0] && szAccountName[0]) {
  770. wsprintf(pszAccountName,L"%s\\%s",szDomainName, szAccountName);
  771. }else if (szAccountName[0]) {
  772. wsprintf(pszAccountName,L"%s", szAccountName);
  773. }
  774. *ppszAccountName = pszAccountName;
  775. }
  776. }
  777. else {
  778. hr = ConvertSidToU2Trustee(
  779. pszServerName,
  780. Credentials,
  781. pSid,
  782. szAccountName
  783. );
  784. if (SUCCEEDED(hr)) {
  785. pszAccountName = AllocADsStr(szAccountName);
  786. if (!pszAccountName) {
  787. hr = E_OUTOFMEMORY;
  788. BAIL_ON_FAILURE(hr);
  789. }
  790. *ppszAccountName = pszAccountName;
  791. }
  792. }
  793. if (FAILED(hr)) {
  794. hr = ConvertSidToString(
  795. pSid,
  796. szAccountName
  797. );
  798. BAIL_ON_FAILURE(hr);
  799. pszAccountName = AllocADsStr(szAccountName);
  800. if (!pszAccountName) {
  801. hr = E_OUTOFMEMORY;
  802. BAIL_ON_FAILURE(hr);
  803. }
  804. *ppszAccountName = pszAccountName;
  805. }
  806. error:
  807. RRETURN(hr);
  808. }
  809. HRESULT
  810. ConvertACLToVariant(
  811. LPWSTR pszServerName,
  812. CCredentials& Credentials,
  813. PACL pACL,
  814. PVARIANT pvarACL,
  815. BOOL fNTDS
  816. )
  817. {
  818. IADsAccessControlList * pAccessControlList = NULL;
  819. IDispatch * pDispatch = NULL;
  820. LPWSTR pszFriendlyName = NULL;
  821. VARIANT varAce;
  822. DWORD dwAclSize = 0;
  823. DWORD dwAclRevision = 0;
  824. DWORD dwAceCount = 0;
  825. ACL_SIZE_INFORMATION AclSize;
  826. ACL_REVISION_INFORMATION AclRevision;
  827. DWORD dwStatus = 0;
  828. DWORD i = 0;
  829. DWORD dwNewAceCount = 0;
  830. HRESULT hr = S_OK;
  831. LPBYTE pAceAddress = NULL;
  832. LSA_HANDLE hLsaPolicy = NULL;
  833. PLSA_REFERENCED_DOMAIN_LIST pLsaRefDomList = NULL;
  834. PLSA_TRANSLATED_NAME pLsaNames = NULL;
  835. PSID *pSidArray = NULL;
  836. memset(&AclSize, 0, sizeof(ACL_SIZE_INFORMATION));
  837. memset(&AclRevision, 0, sizeof(ACL_REVISION_INFORMATION));
  838. dwStatus = GetAclInformation(
  839. pACL,
  840. &AclSize,
  841. sizeof(ACL_SIZE_INFORMATION),
  842. AclSizeInformation
  843. );
  844. //
  845. // Status should be nonzero for success
  846. //
  847. if (!dwStatus) {
  848. hr = HRESULT_FROM_WIN32(GetLastError());
  849. BAIL_ON_FAILURE(hr);
  850. }
  851. dwStatus = GetAclInformation(
  852. pACL,
  853. &AclRevision,
  854. sizeof(ACL_REVISION_INFORMATION),
  855. AclRevisionInformation
  856. );
  857. if (!dwStatus) {
  858. hr = HRESULT_FROM_WIN32(GetLastError());
  859. BAIL_ON_FAILURE(hr);
  860. }
  861. dwAceCount = AclSize.AceCount;
  862. dwAclRevision = AclRevision.AclRevision;
  863. VariantInit(pvarACL);
  864. hr = CoCreateInstance(
  865. CLSID_AccessControlList,
  866. NULL,
  867. CLSCTX_INPROC_SERVER,
  868. IID_IADsAccessControlList,
  869. (void **)&pAccessControlList
  870. );
  871. BAIL_ON_FAILURE(hr);
  872. //
  873. // Do this only when we actually have ACE
  874. //
  875. if(dwAceCount > 0) {
  876. //
  877. // Sid lookup can be optimized only for NT style SD's.
  878. // SiteServer style SD's will continue to be processed as before.
  879. //
  880. if (fNTDS) {
  881. //
  882. // To speed up the conversion of SID's to trustees, an array of
  883. // SID's to lookup is built and the whole array processed in one
  884. // shot. Then the result of the Lookup is used in contstructing
  885. // the individual ACE's.
  886. //
  887. pSidArray = (PSID*) AllocADsMem(sizeof(PSID) * dwAceCount);
  888. if (!pSidArray) {
  889. BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
  890. }
  891. for (i = 0; i < dwAceCount; i++) {
  892. dwStatus = GetAce(pACL, i , (void **) &pAceAddress);
  893. if (!dwStatus) {
  894. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
  895. }
  896. pSidArray[i] = ComputeSidFromAceAddress(pAceAddress);
  897. //
  898. // Sanity check we should always have valid data.
  899. //
  900. if (!pSidArray[i]) {
  901. BAIL_ON_FAILURE(hr = E_FAIL);
  902. }
  903. }
  904. hr = GetLsaPolicyHandle(
  905. pszServerName,
  906. Credentials,
  907. &hLsaPolicy
  908. );
  909. //
  910. // Should we just convert to string SID's ?
  911. //
  912. BAIL_ON_FAILURE(hr);
  913. hr = GetNamesFromSids(
  914. hLsaPolicy,
  915. pSidArray,
  916. dwAceCount,
  917. &pLsaRefDomList,
  918. &pLsaNames
  919. );
  920. BAIL_ON_FAILURE(hr);
  921. }
  922. for (i = 0; i < dwAceCount; i++) {
  923. if (pszFriendlyName) {
  924. FreeADsStr(pszFriendlyName);
  925. pszFriendlyName = NULL;
  926. }
  927. dwStatus = GetAce(pACL, i, (void **)&pAceAddress);
  928. //
  929. // Need to verify we got back the ace correctly.
  930. //
  931. if (!dwStatus) {
  932. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(GetLastError()));
  933. }
  934. if(fNTDS) {
  935. hr = GetNameForSidFromArray(
  936. i,
  937. pLsaRefDomList,
  938. pLsaNames,
  939. &pszFriendlyName
  940. );
  941. }
  942. //
  943. // We can ignore the failure.
  944. // On failure pszFriendlyName is set to NULL in which case
  945. // we will convert to stringised sid format (for NTDS of course).
  946. //
  947. hr = ConvertAceToVariant(
  948. pszServerName,
  949. pszFriendlyName,
  950. Credentials,
  951. pAceAddress,
  952. (PVARIANT)&varAce,
  953. fNTDS
  954. );
  955. //
  956. // If we cannot convert an ACE we should error out.
  957. //
  958. BAIL_ON_FAILURE(hr);
  959. hr = pAccessControlList->AddAce(V_DISPATCH(&varAce));
  960. VariantClear(&varAce);
  961. BAIL_ON_FAILURE(hr);
  962. dwNewAceCount++;
  963. }
  964. }
  965. pAccessControlList->put_AclRevision(dwAclRevision);
  966. pAccessControlList->put_AceCount(dwNewAceCount);
  967. hr = pAccessControlList->QueryInterface(
  968. IID_IDispatch,
  969. (void **)&pDispatch
  970. );
  971. V_VT(pvarACL) = VT_DISPATCH;
  972. V_DISPATCH(pvarACL) = pDispatch;
  973. error:
  974. if (pAccessControlList) {
  975. pAccessControlList->Release();
  976. }
  977. if (pszFriendlyName) {
  978. FreeADsStr(pszFriendlyName);
  979. }
  980. if (pLsaNames) {
  981. LsaFreeMemory(pLsaNames);
  982. }
  983. if (pLsaRefDomList) {
  984. LsaFreeMemory(pLsaRefDomList);
  985. }
  986. if (hLsaPolicy) {
  987. LsaClose(hLsaPolicy);
  988. }
  989. if(pSidArray) {
  990. FreeADsMem(pSidArray);
  991. }
  992. RRETURN(hr);
  993. }
  994. HRESULT
  995. ConvertAceToVariant(
  996. LPWSTR pszServerName,
  997. LPWSTR pszTrusteeName,
  998. CCredentials& Credentials,
  999. PBYTE pAce,
  1000. PVARIANT pvarAce,
  1001. BOOL fNTDS
  1002. )
  1003. {
  1004. IADsAccessControlEntry * pAccessControlEntry = NULL;
  1005. IDispatch * pDispatch = NULL;
  1006. IADsAcePrivate *pPrivAce = NULL;
  1007. DWORD dwAceType = 0;
  1008. DWORD dwAceFlags = 0;
  1009. DWORD dwAccessMask = 0;
  1010. DWORD dwLenSid = 0;
  1011. DWORD dwErr = 0;
  1012. LPWSTR pszAccountName = NULL;
  1013. PACE_HEADER pAceHeader = NULL;
  1014. LPBYTE pSidAddress = NULL;
  1015. LPBYTE pOffset = NULL;
  1016. DWORD dwFlags = 0;
  1017. GUID ObjectGUID;
  1018. GUID InheritedObjectGUID;
  1019. BSTR bstrObjectGUID = NULL;
  1020. BSTR bstrInheritedObjectGUID = NULL;
  1021. HRESULT hr = S_OK;
  1022. VariantInit(pvarAce);
  1023. hr = CoCreateInstance(
  1024. CLSID_AccessControlEntry,
  1025. NULL,
  1026. CLSCTX_INPROC_SERVER,
  1027. IID_IADsAccessControlEntry,
  1028. (void **)&pAccessControlEntry
  1029. );
  1030. BAIL_ON_FAILURE(hr);
  1031. pAceHeader = (ACE_HEADER *)pAce;
  1032. dwAceType = pAceHeader->AceType;
  1033. dwAceFlags = pAceHeader->AceFlags;
  1034. dwAccessMask = *(PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  1035. switch (dwAceType) {
  1036. case ACCESS_ALLOWED_ACE_TYPE:
  1037. case ACCESS_DENIED_ACE_TYPE:
  1038. case SYSTEM_AUDIT_ACE_TYPE:
  1039. case SYSTEM_ALARM_ACE_TYPE:
  1040. pSidAddress = (LPBYTE)pAceHeader + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK);
  1041. break;
  1042. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  1043. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  1044. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  1045. case SYSTEM_ALARM_OBJECT_ACE_TYPE:
  1046. pOffset = (LPBYTE)((LPBYTE)pAceHeader + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK));
  1047. dwFlags = (DWORD)(*(PDWORD)pOffset);
  1048. //
  1049. // Now advance by the size of the flags
  1050. //
  1051. pOffset += sizeof(ULONG);
  1052. if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
  1053. memcpy(&ObjectGUID, pOffset, sizeof(GUID));
  1054. hr = BuildADsGuid(ObjectGUID, &bstrObjectGUID);
  1055. BAIL_ON_FAILURE(hr);
  1056. pOffset += sizeof (GUID);
  1057. }
  1058. if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
  1059. memcpy(&InheritedObjectGUID, pOffset, sizeof(GUID));
  1060. hr = BuildADsGuid(InheritedObjectGUID, &bstrInheritedObjectGUID);
  1061. BAIL_ON_FAILURE(hr);
  1062. pOffset += sizeof (GUID);
  1063. }
  1064. pSidAddress = pOffset;
  1065. break;
  1066. default:
  1067. break;
  1068. }
  1069. if (pSidAddress) {
  1070. //
  1071. // Nt4 does not reset the last error correctly.
  1072. //
  1073. SetLastError(NO_ERROR);
  1074. dwLenSid = GetLengthSid(pSidAddress);
  1075. if ((dwErr = GetLastError()) != NO_ERROR) {
  1076. BAIL_ON_FAILURE(hr = HRESULT_FROM_WIN32(dwErr));
  1077. }
  1078. }
  1079. else {
  1080. //
  1081. // We should always have a valid sid address here.
  1082. // Should we be bailing here ? Or for that matter,
  1083. // should be bail on the default cluase of the switch ?
  1084. //
  1085. dwLenSid = 0;
  1086. }
  1087. //
  1088. // Call the old function only if we could not resolve the name
  1089. //
  1090. if (!pszTrusteeName) {
  1091. hr = ConvertSidToFriendlyName(
  1092. pszServerName,
  1093. Credentials,
  1094. pSidAddress,
  1095. &pszAccountName,
  1096. fNTDS
  1097. );
  1098. }
  1099. if (FAILED(hr)){
  1100. pszAccountName = AllocADsStr(L"Unknown Trustee");
  1101. if (!pszAccountName) {
  1102. hr = E_OUTOFMEMORY;
  1103. BAIL_ON_FAILURE(hr);
  1104. }
  1105. }
  1106. //
  1107. // Now set all the information in the Access Control Entry
  1108. //
  1109. hr = pAccessControlEntry->put_AccessMask(dwAccessMask);
  1110. hr = pAccessControlEntry->put_AceFlags(dwAceFlags);
  1111. hr = pAccessControlEntry->put_AceType(dwAceType);
  1112. //
  1113. // Extended ACE information
  1114. //
  1115. hr = pAccessControlEntry->put_Flags(dwFlags);
  1116. if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
  1117. //
  1118. // Add in the Object Type GUID
  1119. //
  1120. hr = pAccessControlEntry->put_ObjectType(bstrObjectGUID);
  1121. }
  1122. if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
  1123. //
  1124. // Add in the Inherited Object Type GUID
  1125. //
  1126. hr = pAccessControlEntry->put_InheritedObjectType(
  1127. bstrInheritedObjectGUID
  1128. );
  1129. }
  1130. //
  1131. // This is a string, so need to check the ecode. We use the
  1132. // friendlyName if that was set and if not the pszAccountName.
  1133. //
  1134. hr = pAccessControlEntry->put_Trustee(
  1135. pszTrusteeName ?
  1136. pszTrusteeName :
  1137. pszAccountName
  1138. );
  1139. BAIL_ON_FAILURE(hr);
  1140. if (pSidAddress) {
  1141. //
  1142. // We should now put the SID on this ACE for quick reverse lookup.
  1143. //
  1144. hr = pAccessControlEntry->QueryInterface(
  1145. IID_IADsAcePrivate,
  1146. (void **)&pPrivAce
  1147. );
  1148. if SUCCEEDED(hr) {
  1149. hr = pPrivAce->putSid(
  1150. pSidAddress,
  1151. dwLenSid
  1152. );
  1153. }
  1154. //
  1155. // No bail on failure here as it is not a critical failure
  1156. //
  1157. }
  1158. hr = pAccessControlEntry->QueryInterface(
  1159. IID_IDispatch,
  1160. (void **)&pDispatch
  1161. );
  1162. BAIL_ON_FAILURE(hr);
  1163. V_DISPATCH(pvarAce) = pDispatch;
  1164. V_VT(pvarAce) = VT_DISPATCH;
  1165. cleanup:
  1166. if (pszAccountName) {
  1167. FreeADsStr(pszAccountName);
  1168. }
  1169. if (pAccessControlEntry) {
  1170. pAccessControlEntry->Release();
  1171. }
  1172. if (pPrivAce) {
  1173. pPrivAce->Release();
  1174. }
  1175. if (bstrObjectGUID) {
  1176. ADsFreeString(bstrObjectGUID);
  1177. }
  1178. if (bstrInheritedObjectGUID) {
  1179. ADsFreeString(bstrInheritedObjectGUID);
  1180. }
  1181. RRETURN(hr);
  1182. error:
  1183. if (pDispatch) {
  1184. pDispatch->Release();
  1185. }
  1186. goto cleanup;
  1187. }
  1188. //+---------------------------------------------------------------------------
  1189. // Function: ComputeSidFromAceAddress - helper routine.
  1190. //
  1191. // Synopsis: Returns the pointer to the SID, given a ptr to an ACE.
  1192. //
  1193. // Arguments: pAce - ptr to the ACE.
  1194. //
  1195. // Returns: NULL on error or valid PSID.
  1196. //
  1197. // Modifies: N/A.
  1198. //
  1199. //----------------------------------------------------------------------------
  1200. PSID
  1201. ComputeSidFromAceAddress(
  1202. LPBYTE pAce
  1203. )
  1204. {
  1205. PSID pSidRetVal = NULL;
  1206. PACE_HEADER pAceHeader = NULL;
  1207. LPBYTE pOffset = NULL;
  1208. DWORD dwAceType, dwAceFlags, dwAccessMask;
  1209. DWORD dwFlags;
  1210. pAceHeader = (ACE_HEADER *)pAce;
  1211. dwAceType = pAceHeader->AceType;
  1212. dwAceFlags = pAceHeader->AceFlags;
  1213. dwAccessMask = *(PACCESS_MASK)((LPBYTE)pAceHeader + sizeof(ACE_HEADER));
  1214. switch (dwAceType) {
  1215. case ACCESS_ALLOWED_ACE_TYPE:
  1216. case ACCESS_DENIED_ACE_TYPE:
  1217. case SYSTEM_AUDIT_ACE_TYPE:
  1218. case SYSTEM_ALARM_ACE_TYPE:
  1219. pSidRetVal = (LPBYTE)pAceHeader
  1220. + sizeof(ACE_HEADER)
  1221. + sizeof(ACCESS_MASK);
  1222. break;
  1223. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  1224. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  1225. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  1226. case SYSTEM_ALARM_OBJECT_ACE_TYPE:
  1227. pOffset = (LPBYTE)((LPBYTE)pAceHeader
  1228. + sizeof(ACE_HEADER)
  1229. + sizeof(ACCESS_MASK)
  1230. );
  1231. dwFlags = (DWORD)(*(PDWORD)pOffset);
  1232. //
  1233. // Now advance by the size of the flags
  1234. //
  1235. pOffset += sizeof(ULONG);
  1236. if (dwFlags & ACE_OBJECT_TYPE_PRESENT) {
  1237. pOffset += sizeof (GUID);
  1238. }
  1239. if (dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT) {
  1240. pOffset += sizeof (GUID);
  1241. }
  1242. pSidRetVal = pOffset;
  1243. break;
  1244. default:
  1245. break;
  1246. } // end of switch case.
  1247. return pSidRetVal;
  1248. }