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.

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