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.

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