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.

3084 lines
94 KiB

  1. //+---------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1993 - 1997.
  5. //
  6. // File: util.cpp
  7. //
  8. // Contents: Implements the utility class CUtility
  9. //
  10. // Classes:
  11. //
  12. // Methods: CUtility::CkForAccessDenied
  13. // CUtility::CkAccessRights
  14. // CUtility::PostErrorMessage (x2)
  15. // CUtility::WriteRegSzNamedValue
  16. // CUtility::WriteRegDwordNamedValue
  17. // CUtility::WriteRegSingleACL
  18. // CUtility::WriteRegKeyACL
  19. // CUtility::WriteRegKeyACL2
  20. // CUtility::WriteLsaPassword
  21. // CUtility::DeleteRegKey
  22. // CUtility::DeleteRegValue
  23. // CUtility::WriteSrvIdentity
  24. // CUtility::ACLEditor
  25. // CUtility::ACLEditor2
  26. // CUtility::InvokeUserBrowser
  27. // CUtility::InvokeMachineBrowser
  28. // CUtility::StringFromGUID
  29. // CUtility::IsEqualGuid
  30. // CUtility::AdjustPrivilege
  31. // CUtility::VerifyRemoteMachine
  32. // CUtility::RetrieveUserPassword
  33. // CUtility::StoreUserPassword
  34. // CUtility::LookupProcessInfo
  35. // CUtility::MakeSecDesc
  36. // CUtility::CheckForValidSD
  37. // CUtility::SDisIAC
  38. // CUtility::CheckSDForCOM_RIGHTS_EXECUTE
  39. // CUtility::ChangeService
  40. // CUtility::UpdateDCOMInfo(void)
  41. // CUtility::FixHelp
  42. // CUtility::CopySD
  43. // CUtility::SetInheritanceFlags
  44. //
  45. // Functons: callBackFunc
  46. // ControlFixProc
  47. //
  48. // History: 23-Apr-96 BruceMa Created.
  49. //
  50. //----------------------------------------------------------------------
  51. #include "stdafx.h"
  52. #include "assert.h"
  53. #include "resource.h"
  54. #include "afxtempl.h"
  55. #include "types.h"
  56. #include "datapkt.h"
  57. #include "clspsht.h"
  58. #if !defined(STANDALONE_BUILD)
  59. extern "C"
  60. {
  61. #include <getuser.h>
  62. }
  63. #endif
  64. #include "util.h"
  65. #include "virtreg.h"
  66. extern "C"
  67. {
  68. #if !defined(STANDALONE_BUILD)
  69. #include <ntlsa.h>
  70. #include <ntseapi.h>
  71. #include <sedapi.h>
  72. #endif
  73. #include <winnetwk.h>
  74. #if !defined(STANDALONE_BUILD)
  75. #include <uiexport.h>
  76. #include <lm.h>
  77. #endif
  78. #include <rpc.h>
  79. #include <rpcdce.h>
  80. #include <aclapi.h>
  81. }
  82. #include <objsel.h>
  83. #ifdef _DEBUG
  84. #define new DEBUG_NEW
  85. #undef THIS_FILE
  86. static char BASED_CODE THIS_FILE[] = __FILE__;
  87. #endif
  88. const IID IID_IAccessControl = {0xEEDD23E0,0x8410,0x11CE,{0xA1,0xC3,0x08,0x00,0x2B,0x2B,0x8D,0x8F}};
  89. static const BYTE GuidMap[] = { 3, 2, 1, 0, '-', 5, 4, '-', 7, 6, '-',
  90. 8, 9, '-', 10, 11, 12, 13, 14, 15 };
  91. static const WCHAR wszDigits[] = L"0123456789ABCDEF";
  92. static const DWORD SIZEOF_SID = 44;
  93. // This leaves space for 2 access allowed ACEs in the ACL.
  94. const DWORD SIZEOF_ACL = sizeof(ACL) + 2 * sizeof(ACCESS_ALLOWED_ACE) +
  95. 2 * SIZEOF_SID;
  96. static const DWORD SIZEOF_TOKEN_USER = sizeof(TOKEN_USER) + SIZEOF_SID;
  97. static const SID LOCAL_SYSTEM_SID = {SID_REVISION, 1, {0,0,0,0,0,5},
  98. SECURITY_LOCAL_SYSTEM_RID };
  99. static const DWORD NUM_SEC_PKG = 8;
  100. // These are required for the method CUtility::UpdateDCOMInfo which invokes
  101. // an RPC proxy which expects the following
  102. extern "C" void * _stdcall MIDL_user_allocate(size_t size)
  103. {
  104. return new BYTE[size];
  105. }
  106. extern "C" void _stdcall MIDL_user_free(void *p)
  107. {
  108. delete p;
  109. }
  110. CUtility::CUtility(void)
  111. {
  112. HRESULT hr = OleInitialize(NULL);
  113. m_bCheckedDC = NULL; // have we checked if we're on a BDC yet ?
  114. m_bIsBdc = FALSE;
  115. m_pszDomainController = NULL;
  116. }
  117. CUtility::~CUtility(void)
  118. {
  119. #if !defined(STANDALONE_BUILD)
  120. if (m_pszDomainController)
  121. NetApiBufferFree(m_pszDomainController);
  122. #endif
  123. OleUninitialize();
  124. }
  125. void CUtility::CkForAccessDenied(int err)
  126. {
  127. if (err == ERROR_ACCESS_DENIED)
  128. {
  129. CString sMsg;
  130. CString sCaption;
  131. sMsg.LoadString(IDS_ACCESSDENIED);
  132. sCaption.LoadString(IDS_SYSTEMMESSAGE);
  133. MessageBox(NULL, sMsg, sCaption, MB_OK);
  134. }
  135. }
  136. BOOL CUtility::CkAccessRights(HKEY hRoot, LPCTSTR szKeyPath)
  137. {
  138. int err;
  139. HKEY hKey = NULL;
  140. BYTE aSid[256];
  141. DWORD cbSid = 256;
  142. PSECURITY_DESCRIPTOR pSid = (PSECURITY_DESCRIPTOR) aSid;
  143. BOOL fFreePsid = FALSE;
  144. // Open the specified key
  145. err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey);
  146. // The key may not exist
  147. if (err == ERROR_FILE_NOT_FOUND)
  148. {
  149. if (hKey != hRoot)
  150. {
  151. RegCloseKey(hKey);
  152. }
  153. return TRUE;
  154. }
  155. if (err == ERROR_SUCCESS)
  156. {
  157. // Fetch the security descriptor on this key
  158. err = RegGetKeySecurity(hKey,
  159. OWNER_SECURITY_INFORMATION |
  160. GROUP_SECURITY_INFORMATION |
  161. DACL_SECURITY_INFORMATION,
  162. (PSECURITY_DESCRIPTOR) aSid,
  163. &cbSid);
  164. if (err == ERROR_INSUFFICIENT_BUFFER)
  165. {
  166. pSid = (PSECURITY_DESCRIPTOR) malloc(cbSid);
  167. if (pSid == NULL)
  168. {
  169. if (hKey != hRoot)
  170. {
  171. RegCloseKey(hKey);
  172. }
  173. return FALSE;
  174. }
  175. fFreePsid = TRUE;
  176. err = RegGetKeySecurity(hKey,
  177. OWNER_SECURITY_INFORMATION |
  178. GROUP_SECURITY_INFORMATION |
  179. DACL_SECURITY_INFORMATION,
  180. (PSECURITY_DESCRIPTOR) pSid,
  181. &cbSid);
  182. }
  183. // We've read the security descriptor - now try to write it
  184. if (err == ERROR_SUCCESS)
  185. {
  186. err = RegSetKeySecurity(hKey,
  187. OWNER_SECURITY_INFORMATION |
  188. GROUP_SECURITY_INFORMATION |
  189. DACL_SECURITY_INFORMATION,
  190. pSid);
  191. }
  192. if (hKey != hRoot)
  193. {
  194. RegCloseKey(hKey);
  195. }
  196. }
  197. if (fFreePsid)
  198. {
  199. free(pSid);
  200. }
  201. return err == ERROR_SUCCESS ? TRUE : FALSE;
  202. }
  203. void CUtility::PostErrorMessage(void)
  204. {
  205. TCHAR szMessage[256];
  206. FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
  207. 0, szMessage, sizeof(szMessage) / sizeof(TCHAR), NULL);
  208. CString sCaption;
  209. sCaption.LoadString(IDS_SYSTEMMESSAGE);
  210. MessageBox(NULL, szMessage, sCaption, MB_OK);
  211. }
  212. void CUtility::PostErrorMessage(int err)
  213. {
  214. TCHAR szMessage[256];
  215. FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
  216. 0, szMessage, sizeof(szMessage) / sizeof(TCHAR), NULL);
  217. CString sCaption;
  218. sCaption.LoadString(IDS_SYSTEMMESSAGE);
  219. MessageBox(NULL, szMessage, sCaption, MB_OK);
  220. }
  221. // Write a named string value to the registry
  222. int CUtility::WriteRegSzNamedValue(HKEY hRoot,
  223. LPCTSTR szKeyPath,
  224. LPCTSTR szValueName,
  225. LPCTSTR szVal,
  226. DWORD dwSize)
  227. {
  228. int err;
  229. HKEY hKey;
  230. ULONG lSize;
  231. // Open the key
  232. err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey);
  233. // The key may not exist
  234. if (err == ERROR_FILE_NOT_FOUND)
  235. {
  236. DWORD dwDisp;
  237. err = RegCreateKeyEx(hRoot,
  238. szKeyPath,
  239. 0,
  240. NULL,
  241. REG_OPTION_NON_VOLATILE,
  242. KEY_ALL_ACCESS,
  243. NULL,
  244. &hKey,
  245. &dwDisp);
  246. }
  247. if (err != ERROR_SUCCESS)
  248. return err;
  249. // Attempt to write the named value
  250. lSize = _tcslen(szVal) + 1;
  251. err = RegSetValueEx(hKey, szValueName, NULL, REG_SZ, (BYTE *) szVal, lSize*sizeof(TCHAR));
  252. if (hKey != hRoot)
  253. RegCloseKey(hKey);
  254. return err;
  255. }
  256. // Write a named multi string value to the registry
  257. int CUtility::WriteRegMultiSzNamedValue(HKEY hRoot,
  258. LPCTSTR szKeyPath,
  259. LPCTSTR szValueName,
  260. LPCTSTR szVal,
  261. DWORD dwSize)
  262. {
  263. int err = ERROR_SUCCESS;
  264. HKEY hKey;
  265. // Open the key
  266. err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey);
  267. // The key may not exist
  268. if (err == ERROR_FILE_NOT_FOUND)
  269. {
  270. DWORD dwDisp;
  271. err = RegCreateKeyEx(hRoot,
  272. szKeyPath,
  273. 0,
  274. NULL,
  275. REG_OPTION_NON_VOLATILE,
  276. KEY_ALL_ACCESS,
  277. NULL,
  278. &hKey,
  279. &dwDisp);
  280. }
  281. if (err != ERROR_SUCCESS)
  282. return err;
  283. // Attempt to write the named value
  284. err = RegSetValueEx(hKey, szValueName, NULL, REG_MULTI_SZ, (BYTE *) szVal, dwSize*sizeof(TCHAR) );
  285. if (hKey != hRoot)
  286. RegCloseKey(hKey);
  287. return err;
  288. }
  289. // Write a named DWORD value to the registry
  290. int CUtility::WriteRegDwordNamedValue(HKEY hRoot,
  291. LPCTSTR szKeyPath,
  292. LPCTSTR szValueName,
  293. DWORD dwVal)
  294. {
  295. int err;
  296. HKEY hKey;
  297. // Open the key
  298. err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey);
  299. // The key may not exist
  300. if (err == ERROR_FILE_NOT_FOUND)
  301. {
  302. DWORD dwDisp;
  303. err = RegCreateKeyEx(hRoot,
  304. szKeyPath,
  305. 0,
  306. NULL,
  307. REG_OPTION_NON_VOLATILE,
  308. KEY_ALL_ACCESS,
  309. NULL,
  310. &hKey,
  311. &dwDisp);
  312. }
  313. if (err != ERROR_SUCCESS)
  314. return err;
  315. // Attempt to write the named value
  316. if (RegSetValueEx(hKey, szValueName, NULL, REG_DWORD, (BYTE *) &dwVal,
  317. sizeof(DWORD))
  318. != ERROR_SUCCESS)
  319. {
  320. if (hKey != hRoot)
  321. {
  322. RegCloseKey(hKey);
  323. }
  324. return GetLastError();
  325. }
  326. // Return the value
  327. if (hKey != hRoot)
  328. {
  329. RegCloseKey(hKey);
  330. }
  331. return ERROR_SUCCESS;
  332. }
  333. // Write an ACL as a registry named value
  334. int CUtility::WriteRegSingleACL(HKEY hRoot,
  335. LPCTSTR szKeyPath,
  336. LPCTSTR szValueName,
  337. PSECURITY_DESCRIPTOR pSec)
  338. {
  339. int err;
  340. HKEY hKey = hRoot;
  341. PSrSecurityDescriptor pSrSec;
  342. PSrAcl pDacl;
  343. // Open the key unless the key path is NULL
  344. if (szKeyPath)
  345. {
  346. if ((err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey))
  347. != ERROR_SUCCESS)
  348. {
  349. return err;
  350. }
  351. }
  352. ULONG cbLen;
  353. BOOL fIsIAC = SDisIAC((SECURITY_DESCRIPTOR * )pSec);
  354. // If there are no ACE's and this is DefaultAccessPermission, then
  355. // interpret this as activator access only which we indicate by
  356. // removing the named value
  357. if (!fIsIAC)
  358. {
  359. pSrSec = (PSrSecurityDescriptor) pSec;
  360. pDacl = (PSrAcl) (((BYTE *) pSec) + (pSrSec->Dacl));
  361. if (_tcscmp(szValueName, TEXT("DefaultAccessPermission")) == 0 &&
  362. pDacl->AceCount == 0)
  363. {
  364. err = RegDeleteValue(hKey, szValueName);
  365. return err;
  366. }
  367. cbLen = RtlLengthSecurityDescriptor(pSec);
  368. }
  369. else
  370. {
  371. cbLen = (ULONG) GlobalSize(pSec);
  372. }
  373. // Else write the ACL simply as a REG_SZ value
  374. err = RegSetValueEx(hKey,
  375. szValueName,
  376. 0,
  377. REG_BINARY,
  378. (BYTE *) pSec,
  379. cbLen);
  380. if (hKey != hRoot)
  381. {
  382. RegCloseKey(hKey);
  383. }
  384. return err;
  385. }
  386. // Write an ACL on a registry key
  387. int CUtility::WriteRegKeyACL(HKEY hKey,
  388. HKEY *phClsids,
  389. unsigned cClsids,
  390. PSECURITY_DESCRIPTOR pSec,
  391. PSECURITY_DESCRIPTOR pSecOrig)
  392. {
  393. int err;
  394. // The logic is somewhat different depending on whether we're starting
  395. // with HKEY_CLASSES_ROOT or a specific AppID
  396. if (hKey == HKEY_CLASSES_ROOT)
  397. {
  398. return WriteRegKeyACL2(hKey, hKey, pSec, pSecOrig);
  399. }
  400. // It's a specific AppID
  401. else
  402. {
  403. // Write the security on the AppID key
  404. if (err = RegSetKeySecurity(hKey,
  405. OWNER_SECURITY_INFORMATION |
  406. GROUP_SECURITY_INFORMATION |
  407. DACL_SECURITY_INFORMATION,
  408. pSec) != ERROR_SUCCESS)
  409. {
  410. return err;
  411. }
  412. // Iterate over the CLSID's covered by this AppID and recursively
  413. // write security on them and their subkeys
  414. for (UINT k = 0; k < cClsids; k++)
  415. {
  416. if (err = WriteRegKeyACL2(phClsids[k], phClsids[k], pSec, pSecOrig)
  417. != ERROR_SUCCESS)
  418. {
  419. return err;
  420. }
  421. }
  422. }
  423. return ERROR_SUCCESS;
  424. }
  425. // Write an ACL recursively on a registry key provided the current
  426. // security descriptor on the key is the same as the passed in
  427. // original security descriptor
  428. int CUtility::WriteRegKeyACL2(HKEY hRoot,
  429. HKEY hKey,
  430. PSECURITY_DESCRIPTOR pSec,
  431. PSECURITY_DESCRIPTOR pSecOrig)
  432. {
  433. BYTE aCurrSD[256] = {0};
  434. DWORD cbCurrSD = 256;
  435. PSECURITY_DESCRIPTOR pCurrSD = (PSECURITY_DESCRIPTOR) aCurrSD;
  436. BOOL fFreePCurrSD = FALSE;
  437. int err;
  438. BOOL fProceed;
  439. // Read the current security descriptor on this key
  440. err = RegGetKeySecurity(hKey,
  441. OWNER_SECURITY_INFORMATION |
  442. GROUP_SECURITY_INFORMATION |
  443. DACL_SECURITY_INFORMATION,
  444. aCurrSD,
  445. &cbCurrSD);
  446. if (err == ERROR_MORE_DATA || err == ERROR_INSUFFICIENT_BUFFER)
  447. {
  448. pCurrSD = (SECURITY_DESCRIPTOR *) GlobalAlloc(GMEM_FIXED, cbCurrSD);
  449. if (pCurrSD == NULL)
  450. {
  451. return ERROR_NOT_ENOUGH_MEMORY;
  452. }
  453. fFreePCurrSD = TRUE;
  454. }
  455. else if (err != ERROR_SUCCESS)
  456. {
  457. return err;
  458. }
  459. if ((err = RegGetKeySecurity(hKey,
  460. OWNER_SECURITY_INFORMATION |
  461. GROUP_SECURITY_INFORMATION |
  462. DACL_SECURITY_INFORMATION,
  463. pCurrSD,
  464. &cbCurrSD)
  465. != ERROR_SUCCESS))
  466. {
  467. if (fFreePCurrSD)
  468. {
  469. GlobalFree(pCurrSD);
  470. }
  471. return err;
  472. }
  473. // Only proceed down this subtree if the current SD and the
  474. // original SD are the same
  475. fProceed = CompareSDs((PSrSecurityDescriptor) pCurrSD,
  476. (PSrSecurityDescriptor) pSecOrig);
  477. // We're done with the current security descriptor
  478. if (fFreePCurrSD)
  479. {
  480. GlobalFree(pCurrSD);
  481. }
  482. if (!fProceed)
  483. {
  484. if (hKey != hRoot)
  485. {
  486. RegCloseKey(hKey);
  487. }
  488. return ERROR_SUCCESS;
  489. }
  490. // Write the top level ACL
  491. err = RegSetKeySecurity(hKey,
  492. OWNER_SECURITY_INFORMATION |
  493. GROUP_SECURITY_INFORMATION |
  494. DACL_SECURITY_INFORMATION,
  495. pSec);
  496. // Now enumerate the subkeys and write ACL's on them
  497. DWORD iSubKey;
  498. TCHAR szSubKeyName[128];
  499. HKEY hKey2;
  500. iSubKey = 0;
  501. while (err == ERROR_SUCCESS)
  502. {
  503. // Enumerate the next key
  504. err = RegEnumKey(hKey, iSubKey, szSubKeyName, 128);
  505. if (err != ERROR_SUCCESS)
  506. {
  507. break;
  508. }
  509. // Prepare for the next key
  510. iSubKey++;
  511. // Open this subkey and recursively write the ACL on it and
  512. // all of its subkeys
  513. if (RegOpenKeyEx(hKey, szSubKeyName, 0, KEY_ALL_ACCESS, &hKey2)
  514. == ERROR_SUCCESS)
  515. {
  516. err = WriteRegKeyACL2(hRoot, hKey2, pSec, pSecOrig);
  517. }
  518. }
  519. if (hKey != hRoot)
  520. {
  521. RegCloseKey(hKey);
  522. }
  523. return err == ERROR_NO_MORE_ITEMS ? ERROR_SUCCESS : err;
  524. }
  525. // Write a user's password to the private LSA database
  526. int CUtility::WriteLsaPassword(CLSID appid, LPCTSTR szPassword)
  527. {
  528. return ERROR_SUCCESS;
  529. }
  530. int CUtility::DeleteRegKey(HKEY hRoot, LPCTSTR szKeyPath)
  531. {
  532. return RegDeleteKey(hRoot, szKeyPath);
  533. }
  534. int CUtility::DeleteRegValue(HKEY hRoot, LPCTSTR szKeyPath, LPCTSTR szValueName)
  535. {
  536. int err;
  537. HKEY hKey;
  538. if ((err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey)) == ERROR_SUCCESS)
  539. {
  540. err = RegDeleteValue(hKey, szValueName);
  541. if (hRoot != hKey)
  542. RegCloseKey(hKey);
  543. }
  544. return err;
  545. }
  546. // Change the identity under which a service runs
  547. int CUtility::WriteSrvIdentity(LPCTSTR szService, LPCTSTR szIdentity)
  548. {
  549. return ERROR_SUCCESS;
  550. }
  551. DWORD __stdcall callBackFunc(HWND hwndParent,
  552. HANDLE hInstance,
  553. ULONG_PTR CallBackContext,
  554. PSECURITY_DESCRIPTOR SecDesc,
  555. PSECURITY_DESCRIPTOR SecDescNewObjects,
  556. BOOLEAN ApplyToSubContainers,
  557. BOOLEAN ApplyToSubObjects,
  558. LPDWORD StatusReturn)
  559. {
  560. int err = ERROR_SUCCESS;
  561. PCallBackContext pCallBackContext = (PCallBackContext) CallBackContext;
  562. SECURITY_DESCRIPTOR* pSD = (SECURITY_DESCRIPTOR*) SecDesc;
  563. SECURITY_DESCRIPTOR_RELATIVE* pSDr = (SECURITY_DESCRIPTOR_RELATIVE*) SecDesc;
  564. PSrAcl pDacl;
  565. PSrAce pAce;
  566. DWORD cbAces;
  567. // Check whether the security descriptor is self-relative
  568. if (!(pSD->Control & SE_SELF_RELATIVE))
  569. {
  570. pDacl = (PSrAcl) pSD->Dacl;
  571. }
  572. else
  573. {
  574. pDacl = (PSrAcl) (((BYTE *) pSDr) + (pSDr->Dacl));
  575. }
  576. if (pDacl)
  577. {
  578. // Do over the ACE's
  579. for (pAce = (PSrAce) (((BYTE *) pDacl) + sizeof(SSrAcl)),
  580. cbAces = pDacl->AceCount;cbAces;
  581. pAce = (PSrAce) (((BYTE *) pAce) + pAce->AceSize),cbAces--)
  582. {
  583. if (pAce->Type == 1 && pAce->AccessMask == GENERIC_ALL)
  584. {
  585. pAce->AccessMask = COM_RIGHTS_EXECUTE;
  586. }
  587. }
  588. }
  589. // Set the inheritance flags on the new security descriptor
  590. if (pCallBackContext->pktType == RegKeyACL)
  591. {
  592. g_util.SetInheritanceFlags((SECURITY_DESCRIPTOR *) SecDesc);
  593. }
  594. if (pCallBackContext->fIsIAC)
  595. {
  596. // try to convert to a serialized IAccessControl
  597. SECURITY_DESCRIPTOR * pNewSD = g_util.IACfromSD((SECURITY_DESCRIPTOR *)SecDesc);
  598. if (pNewSD)
  599. {
  600. SecDesc = pNewSD;
  601. }
  602. else
  603. {
  604. pCallBackContext->fIsIAC = FALSE; // failed so treat it as if it is an old-style SD
  605. CString sMsg;
  606. CString sCaption;
  607. sMsg.LoadString(IDS_CANTCONVERT);
  608. sCaption.LoadString(IDS_SYSTEMMESSAGE);
  609. MessageBox(NULL, sMsg, sCaption, MB_OK);
  610. }
  611. }
  612. else
  613. {
  614. SECURITY_DESCRIPTOR * pNewSD;
  615. // just copy the security descriptor to get it into Global Memory
  616. if (!g_util.CopySD((SECURITY_DESCRIPTOR *)SecDesc, &pNewSD))
  617. {
  618. *StatusReturn = ERROR_OUTOFMEMORY;
  619. return ERROR_OUTOFMEMORY;
  620. }
  621. SecDesc = pNewSD;
  622. }
  623. // Write the new or modified security descriptor
  624. if (*pCallBackContext->pIndex == -1)
  625. {
  626. if (pCallBackContext->pktType == SingleACL)
  627. {
  628. err = g_virtreg.NewRegSingleACL(
  629. pCallBackContext->info.single.hRoot,
  630. pCallBackContext->info.single.szKeyPath,
  631. pCallBackContext->info.single.szValueName,
  632. (SECURITY_DESCRIPTOR *) SecDesc,
  633. pCallBackContext->fIsIAC, // If it's an IAC then it's already SELF-RELATIVE
  634. pCallBackContext->pIndex);
  635. }
  636. else
  637. {
  638. err = g_virtreg.NewRegKeyACL(
  639. pCallBackContext->info.regKey.hKey,
  640. pCallBackContext->info.regKey.phClsids,
  641. pCallBackContext->info.regKey.cClsids,
  642. pCallBackContext->info.regKey.szTitle,
  643. pCallBackContext->origSD,
  644. (SECURITY_DESCRIPTOR *) SecDesc,
  645. pCallBackContext->fIsIAC, // If it's an IAC then it's already SELF-RELATIVE
  646. pCallBackContext->pIndex);
  647. }
  648. }
  649. else
  650. {
  651. g_virtreg.ChgRegACL(*pCallBackContext->pIndex,
  652. (SECURITY_DESCRIPTOR *) SecDesc,
  653. pCallBackContext->fIsIAC); // If it's an IAC then it's already SELF-RELATIVE
  654. }
  655. *StatusReturn = err;
  656. return err;
  657. }
  658. // Invoke the ACL editor on the specified named value. This method
  659. // writes an ACL data packet to the virtual registry. This method is for
  660. // Access and Launch security only (pktType SingleACL).
  661. int CUtility::ACLEditor(HWND hWnd,
  662. HKEY hRoot,
  663. LPCTSTR szKeyPath,
  664. LPCTSTR szValueName,
  665. int *pIndex,
  666. PACKETTYPE pktType,
  667. dcomAclType eAclType)
  668. {
  669. #if !defined(STANDALONE_BUILD)
  670. int err;
  671. HKEY hKey;
  672. BYTE aSD[128];
  673. DWORD cbSD = 128;
  674. DWORD dwType;
  675. SECURITY_DESCRIPTOR *pSD = (SECURITY_DESCRIPTOR *) aSD;
  676. BOOL fFreePSD = FALSE;
  677. SID *pSid;
  678. TCHAR szAllow[32];
  679. TCHAR szDeny[32];
  680. CString szAllow_;
  681. CString szDeny_;
  682. // Build the allow and deny strings
  683. switch (eAclType)
  684. {
  685. case dcomAclAccess:
  686. szAllow_.LoadString(IDS_ALLOW_ACCESS);
  687. szDeny_.LoadString(IDS_DENY_ACCESS);
  688. break;
  689. case dcomAclLaunch:
  690. szAllow_.LoadString(IDS_ALLOW_LAUNCH);
  691. szDeny_.LoadString(IDS_DENY_LAUNCH);
  692. break;
  693. case dcomAclConfig:
  694. szAllow_.LoadString(IDS_ALLOW_CONFIG);
  695. szDeny_.LoadString(IDS_DENY_CONFIG);
  696. break;
  697. }
  698. _tcscpy(szAllow, (LPCTSTR) szAllow_);
  699. _tcscpy(szDeny, (LPCTSTR) szDeny_);
  700. // Fetch the current SD, either from the registry, by default if the
  701. // named value doesn't exist or from the virtual registry
  702. if (*pIndex == -1)
  703. {
  704. // Open the specified key
  705. if ((err = RegOpenKeyEx(hRoot, szKeyPath, 0,
  706. KEY_ALL_ACCESS, &hKey))
  707. != ERROR_SUCCESS)
  708. {
  709. return err;
  710. }
  711. // Attempt to read the specified named value
  712. err = RegQueryValueEx(hKey, szValueName, 0, &dwType, (BYTE *) aSD,
  713. &cbSD);
  714. if (err == ERROR_MORE_DATA || err == ERROR_INSUFFICIENT_BUFFER)
  715. {
  716. pSD = (SECURITY_DESCRIPTOR *) GlobalAlloc(GMEM_FIXED, cbSD);
  717. if (pSD == NULL)
  718. {
  719. RegCloseKey(hKey);
  720. return ERROR_NOT_ENOUGH_MEMORY;
  721. }
  722. fFreePSD = TRUE;
  723. err = RegQueryValueEx(hKey, szValueName, 0, &dwType,
  724. (BYTE *) pSD, &cbSD);
  725. }
  726. // The named valued doesn't exist. If this is
  727. // \\HKEY_CLASSES_ROOT\...
  728. // then use the default named value if it exists
  729. else if (err != ERROR_SUCCESS)
  730. {
  731. if (hRoot != HKEY_LOCAL_MACHINE)
  732. {
  733. RegCloseKey(hKey);
  734. if (err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  735. TEXT("SOFTWARE\\Microsoft\\OLE"),
  736. 0,
  737. KEY_ALL_ACCESS,
  738. &hKey)
  739. != ERROR_SUCCESS)
  740. {
  741. return err;
  742. }
  743. // Attempt to read the specified named value
  744. TCHAR szDefault[32];
  745. _tcscpy(szDefault, TEXT("Default"));
  746. _tcscat(szDefault, szValueName);
  747. err = RegQueryValueEx(hKey, szDefault, 0, &dwType,
  748. (BYTE *) aSD, &cbSD);
  749. if (err == ERROR_MORE_DATA)
  750. {
  751. pSD = (SECURITY_DESCRIPTOR *) GlobalAlloc(GMEM_FIXED, cbSD);
  752. if (pSD == NULL)
  753. {
  754. RegCloseKey(hKey);
  755. return ERROR_NOT_ENOUGH_MEMORY;
  756. }
  757. fFreePSD = TRUE;
  758. err = RegQueryValueEx(hKey, szDefault, 0, &dwType,
  759. (BYTE *) pSD, &cbSD);
  760. }
  761. }
  762. }
  763. RegCloseKey(hKey);
  764. // If still don't have an SD, then simply create one
  765. if (err != ERROR_SUCCESS)
  766. {
  767. if (!g_util.LookupProcessInfo(&pSid, NULL))
  768. {
  769. return GetLastError();
  770. }
  771. if (!g_util.MakeSecDesc(pSid, &pSD))
  772. {
  773. delete pSid;
  774. return GetLastError();
  775. }
  776. fFreePSD = TRUE;
  777. }
  778. }
  779. // Fetch the most recently edited SD
  780. else
  781. {
  782. CDataPacket *pCdp = g_virtreg.GetAt(*pIndex);
  783. pSD = pCdp -> pkt.acl.pSec;
  784. }
  785. // Initialize the callback context
  786. m_sCallBackContext.pktType = pktType;
  787. m_sCallBackContext.pIndex = pIndex;
  788. m_sCallBackContext.origSD = pSD;
  789. m_sCallBackContext.info.single.hRoot = hRoot;
  790. m_sCallBackContext.info.single.szKeyPath = (TCHAR*)szKeyPath;
  791. m_sCallBackContext.info.single.szValueName = (TCHAR*)szValueName;
  792. // Invoke the ACL editor
  793. DWORD dwStatus;
  794. GENERIC_MAPPING genericMapping;
  795. CString szObjectType;
  796. szObjectType.LoadString(IDS_Registry_value);
  797. SED_HELP_INFO helpInfo =
  798. {
  799. TEXT("dcomcnfg.hlp"),
  800. {HC_MAIN_DLG,
  801. HC_MAIN_DLG,
  802. HC_MAIN_DLG,
  803. HC_MAIN_DLG,
  804. HC_MAIN_DLG,
  805. HC_MAIN_DLG,
  806. HC_MAIN_DLG}
  807. };
  808. SED_OBJECT_TYPE_DESCRIPTOR objTyp =
  809. {1, // Revision
  810. FALSE, // Is container?
  811. FALSE, // Allow new object perms?
  812. FALSE, // Specific to generic?
  813. &genericMapping, // Generic mapping
  814. NULL, // Generic mapping new
  815. (TCHAR *) ((LPCTSTR) szObjectType), // Object type name
  816. &helpInfo, // Help info
  817. TEXT(""), // Ckbox title
  818. TEXT(""), // Apply title
  819. TEXT(""), //
  820. NULL, // Special object access
  821. NULL // New special object access
  822. };
  823. SED_APPLICATION_ACCESS appAccess[] =
  824. {{SED_DESC_TYPE_RESOURCE, COM_RIGHTS_EXECUTE, 0, szAllow},
  825. {SED_DESC_TYPE_RESOURCE, 0, 0, szDeny}};
  826. SED_APPLICATION_ACCESSES appAccesses =
  827. {2, // Count of access groups
  828. appAccess, // Access array
  829. szAllow // Default access name
  830. };
  831. // Intialize the help contexts
  832. helpInfo.aulHelpContext[HC_MAIN_DLG] =
  833. IDH_REGISTRY_VALUE_PERMISSIONS;
  834. helpInfo.aulHelpContext[HC_SPECIAL_ACCESS_DLG] =
  835. IDH_SPECIAL_ACCESS_GLOBAL;
  836. helpInfo.aulHelpContext[HC_NEW_ITEM_SPECIAL_ACCESS_DLG] =
  837. IDH_SPECIAL_ACCESS_GLOBAL;
  838. helpInfo.aulHelpContext[HC_ADD_USER_DLG] =
  839. IDH_ADD_USERS_AND_GROUPS;
  840. helpInfo.aulHelpContext[HC_ADD_USER_MEMBERS_LG_DLG] =
  841. IDH_LOCAL_GROUP_MEMBERSHIP;
  842. helpInfo.aulHelpContext[HC_ADD_USER_MEMBERS_GG_DLG] =
  843. IDH_GLOBAL_GROUP_MEMBERSHIP;
  844. helpInfo.aulHelpContext[HC_ADD_USER_SEARCH_DLG] =
  845. IDH_FIND_ACCOUNT1;
  846. genericMapping.GenericRead = GENERIC_ALL;
  847. genericMapping.GenericWrite = GENERIC_ALL;
  848. genericMapping.GenericExecute = GENERIC_ALL;
  849. genericMapping.GenericAll = GENERIC_ALL;
  850. if (!CheckForValidSD(pSD))
  851. {
  852. // make a valid security descriptor so we can continue
  853. if (!g_util.LookupProcessInfo(&pSid, NULL))
  854. {
  855. return GetLastError();
  856. }
  857. if (!g_util.MakeSecDesc(pSid, &pSD))
  858. {
  859. delete pSid;
  860. return GetLastError();
  861. }
  862. fFreePSD = TRUE;
  863. }
  864. m_sCallBackContext.fIsIAC = SDisIAC(pSD);
  865. if (m_sCallBackContext.fIsIAC)
  866. {
  867. // convert to a true security descriptor
  868. SECURITY_DESCRIPTOR * pNewSD = SDfromIAC(pSD);
  869. if (!pNewSD)
  870. {
  871. // failed so pop up an error box
  872. CString sMsg, sCaption;
  873. sMsg.LoadString(IDS_BADSD);
  874. sCaption.LoadString(IDS_SYSTEMMESSAGE);
  875. MessageBox(NULL, sMsg, sCaption, MB_OK);
  876. // make a valid security descriptor so we can continue
  877. if (!g_util.LookupProcessInfo(&pSid, NULL))
  878. {
  879. return GetLastError();
  880. }
  881. if (!g_util.MakeSecDesc(pSid, &pNewSD))
  882. {
  883. delete pSid;
  884. return GetLastError();
  885. }
  886. }
  887. if (fFreePSD)
  888. {
  889. GlobalFree(pSD);
  890. }
  891. pSD=pNewSD;
  892. fFreePSD = TRUE;
  893. }
  894. // If this is for Access or Launch permissons then check that the
  895. // SD contains only allows and deny's for COM_RIGHTS_EXECUTE
  896. if (!CheckSDForCOM_RIGHTS_EXECUTE(pSD))
  897. {
  898. return IDCANCEL;
  899. }
  900. // Invoke the ACL editor
  901. SedDiscretionaryAclEditor(hWnd, // Owner hWnd
  902. GetModuleHandle(NULL), // Owner hInstance
  903. NULL, // Server
  904. &objTyp, // ObjectTyp,
  905. &appAccesses, // Application accesses
  906. (TCHAR*)szValueName, // Object name,
  907. callBackFunc, // Callback function
  908. (ULONG_PTR) &m_sCallBackContext, // Callback context
  909. pSD, // Security descriptor,
  910. FALSE, // Couldnt read Dacl,
  911. FALSE, // Can't write Dacl,
  912. &dwStatus, // SED status return,
  913. 0); // Flags
  914. // Check status return
  915. if (dwStatus != ERROR_SUCCESS)
  916. {
  917. // PostErrorMessage(dwStatus);
  918. }
  919. // We're done
  920. if (fFreePSD)
  921. {
  922. GlobalFree(pSD);
  923. }
  924. return dwStatus == 0 ? ERROR_SUCCESS : IDCANCEL;
  925. #else
  926. return IDCANCEL;
  927. #endif
  928. }
  929. // Invoke the ACL editor on the specified key. This method writes an ACL
  930. // data packet to the virtual registry. This method supports configuration
  931. // security only (pktType RegKeyACL).
  932. int CUtility::ACLEditor2(HWND hWnd,
  933. HKEY hKey,
  934. HKEY *phClsids,
  935. unsigned cClsids,
  936. TCHAR *szTitle,
  937. int *pIndex,
  938. PACKETTYPE pktType)
  939. {
  940. #if !defined(STANDALONE_BUILD)
  941. int err;
  942. BYTE aSD[128];
  943. DWORD cbSD = 128;
  944. SECURITY_DESCRIPTOR *pSD = (SECURITY_DESCRIPTOR *) aSD;
  945. BOOL fFreePSD = FALSE;
  946. TCHAR szKeyRead[32];
  947. CString szKeyRead_;
  948. TCHAR szHkeyClassesRoot[32];
  949. CString szHkeyClassesRoot_;
  950. // Initialize strings
  951. szKeyRead_.LoadString(IDS_Key_Read);
  952. _tcscpy(szKeyRead, (LPCTSTR) szKeyRead_);
  953. szHkeyClassesRoot_.LoadString(IDS_HKEY_CLASSES_ROOT);
  954. _tcscpy(szHkeyClassesRoot, (LPCTSTR) szHkeyClassesRoot_);
  955. if (*pIndex == -1)
  956. {
  957. // Read the security descriptor on this key
  958. err = RegGetKeySecurity(hKey,
  959. OWNER_SECURITY_INFORMATION |
  960. GROUP_SECURITY_INFORMATION |
  961. DACL_SECURITY_INFORMATION,
  962. aSD,
  963. &cbSD);
  964. if (err == ERROR_MORE_DATA || err == ERROR_INSUFFICIENT_BUFFER)
  965. {
  966. pSD = (SECURITY_DESCRIPTOR *) GlobalAlloc(GMEM_FIXED, cbSD);
  967. if (pSD == NULL)
  968. {
  969. return ERROR_NOT_ENOUGH_MEMORY;
  970. }
  971. fFreePSD = TRUE;
  972. }
  973. else if (err != ERROR_SUCCESS)
  974. {
  975. return err;
  976. }
  977. if ((err = RegGetKeySecurity(hKey,
  978. OWNER_SECURITY_INFORMATION |
  979. GROUP_SECURITY_INFORMATION |
  980. DACL_SECURITY_INFORMATION,
  981. pSD,
  982. &cbSD)
  983. != ERROR_SUCCESS))
  984. {
  985. if (fFreePSD)
  986. {
  987. GlobalFree(pSD);
  988. }
  989. return err;
  990. }
  991. }
  992. // Fetch the most recently edited SD
  993. else
  994. {
  995. CDataPacket *pCdp = g_virtreg.GetAt(*pIndex);
  996. pSD = pCdp -> pkt.racl.pSec;
  997. }
  998. // Initialize the callback context
  999. m_sCallBackContext.pktType = pktType;
  1000. m_sCallBackContext.pIndex = pIndex;
  1001. m_sCallBackContext.origSD = pSD;
  1002. m_sCallBackContext.info.regKey.hKey = hKey;
  1003. m_sCallBackContext.info.regKey.phClsids = phClsids;
  1004. m_sCallBackContext.info.regKey.cClsids = cClsids;
  1005. m_sCallBackContext.info.regKey.szTitle = szTitle;
  1006. // Invoke the ACL editor
  1007. DWORD dwStatus;
  1008. GENERIC_MAPPING genericMapping;
  1009. CString szObjectType;
  1010. szObjectType.LoadString(IDS_Registry_Key);
  1011. CString szQueryValue;
  1012. szQueryValue.LoadString(IDS_Query_Value);
  1013. CString szSetValue;
  1014. szSetValue.LoadString(IDS_Set_Value);
  1015. CString szCreateSubkeys;
  1016. szCreateSubkeys.LoadString(IDS_Create_Subkey);
  1017. CString szEnumerateSubkeys;
  1018. szEnumerateSubkeys.LoadString(IDS_Enumerate_Subkeys);
  1019. CString szNotify;
  1020. szNotify.LoadString(IDS_Notify);
  1021. CString szCreateLink;
  1022. szCreateLink.LoadString(IDS_Create_Link);
  1023. CString szDelete;
  1024. szDelete.LoadString(IDS_Delete);
  1025. CString szWriteDAC;
  1026. szWriteDAC.LoadString(IDS_Write_DAC);
  1027. CString szWriteOwner;
  1028. szWriteOwner.LoadString(IDS_Write_Owner);
  1029. CString szReadControl;
  1030. szReadControl.LoadString(IDS_Read_Control);
  1031. CString szRead;
  1032. szRead.LoadString(IDS_Read);
  1033. CString szFullControl;
  1034. szFullControl.LoadString(IDS_Full_Control);
  1035. CString szSpecialAccess;
  1036. szSpecialAccess.LoadString(IDS_Special_AccessDotDotDot);
  1037. SED_HELP_INFO helpInfo =
  1038. {
  1039. TEXT("dcomcnfg.hlp"),
  1040. {HC_MAIN_DLG,
  1041. HC_MAIN_DLG,
  1042. HC_MAIN_DLG,
  1043. HC_MAIN_DLG,
  1044. HC_MAIN_DLG,
  1045. HC_MAIN_DLG,
  1046. HC_MAIN_DLG}
  1047. };
  1048. SED_OBJECT_TYPE_DESCRIPTOR objTyp =
  1049. {SED_REVISION1, // Revision
  1050. FALSE, // Is container?
  1051. FALSE, // Allow new object perms?
  1052. FALSE, // Specific to generic?
  1053. &genericMapping, // Generic mapping
  1054. NULL, // Generic mapping new
  1055. (TCHAR *) ((LPCTSTR) szObjectType), // Object type name
  1056. &helpInfo, // Help info
  1057. TEXT(""), // Ckbox title
  1058. TEXT(""), // Apply title
  1059. TEXT(""), //
  1060. (TCHAR *) ((LPCTSTR) szSpecialAccess), // Special Access menu item
  1061. NULL // New special object access
  1062. };
  1063. SED_APPLICATION_ACCESS appAccess[] =
  1064. {
  1065. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_QUERY_VALUE, 0,
  1066. (TCHAR *) ((LPCTSTR) szQueryValue) },
  1067. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_SET_VALUE, 0,
  1068. (TCHAR *) ((LPCTSTR) szSetValue) },
  1069. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_CREATE_SUB_KEY, 0,
  1070. (TCHAR *) ((LPCTSTR) szCreateSubkeys) },
  1071. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_ENUMERATE_SUB_KEYS, 0,
  1072. (TCHAR *) ((LPCTSTR) szEnumerateSubkeys) },
  1073. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_NOTIFY, 0,
  1074. (TCHAR *) ((LPCTSTR) szNotify) },
  1075. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_CREATE_LINK, 0,
  1076. (TCHAR *) ((LPCTSTR) szCreateLink) },
  1077. { SED_DESC_TYPE_RESOURCE_SPECIAL, 0x00010000, /* DELETE, */ 0,
  1078. (TCHAR *) ((LPCTSTR) szDelete) },
  1079. { SED_DESC_TYPE_RESOURCE_SPECIAL, WRITE_DAC, 0,
  1080. (TCHAR *) ((LPCTSTR) szWriteDAC) },
  1081. { SED_DESC_TYPE_RESOURCE_SPECIAL, WRITE_OWNER, 0,
  1082. (TCHAR *) ((LPCTSTR) szWriteOwner) },
  1083. { SED_DESC_TYPE_RESOURCE_SPECIAL, READ_CONTROL, 0,
  1084. (TCHAR *) ((LPCTSTR) szReadControl) },
  1085. { SED_DESC_TYPE_RESOURCE, KEY_READ, 0,
  1086. (TCHAR *) ((LPCTSTR) szRead) },
  1087. { SED_DESC_TYPE_RESOURCE, GENERIC_ALL, /* KEY_ALL_ACCESS, */ 0,
  1088. (TCHAR *) ((LPCTSTR) szFullControl) }
  1089. };
  1090. SED_APPLICATION_ACCESSES appAccesses =
  1091. {12, // Count of access groups
  1092. appAccess, // Access array
  1093. szKeyRead // Default access name
  1094. };
  1095. // Intialize the help contexts
  1096. helpInfo.aulHelpContext[HC_MAIN_DLG] =
  1097. IDH_REGISTRY_KEY_PERMISSIONS;
  1098. if (hKey == HKEY_CLASSES_ROOT)
  1099. {
  1100. helpInfo.aulHelpContext[HC_SPECIAL_ACCESS_DLG] =
  1101. IDH_SPECIAL_ACCESS_GLOBAL;
  1102. helpInfo.aulHelpContext[HC_NEW_ITEM_SPECIAL_ACCESS_DLG] =
  1103. IDH_SPECIAL_ACCESS_GLOBAL;
  1104. }
  1105. else
  1106. {
  1107. helpInfo.aulHelpContext[HC_SPECIAL_ACCESS_DLG] =
  1108. IDH_SPECIAL_ACCESS_PER_APPID;
  1109. helpInfo.aulHelpContext[HC_NEW_ITEM_SPECIAL_ACCESS_DLG] =
  1110. IDH_SPECIAL_ACCESS_PER_APPID;
  1111. }
  1112. helpInfo.aulHelpContext[HC_ADD_USER_DLG] =
  1113. IDH_ADD_USERS_AND_GROUPS;
  1114. helpInfo.aulHelpContext[HC_ADD_USER_MEMBERS_LG_DLG] =
  1115. IDH_LOCAL_GROUP_MEMBERSHIP;
  1116. helpInfo.aulHelpContext[HC_ADD_USER_MEMBERS_GG_DLG] =
  1117. IDH_GLOBAL_GROUP_MEMBERSHIP;
  1118. helpInfo.aulHelpContext[HC_ADD_USER_SEARCH_DLG] =
  1119. IDH_FIND_ACCOUNT1;
  1120. genericMapping.GenericRead = KEY_READ;
  1121. genericMapping.GenericWrite = KEY_WRITE;
  1122. genericMapping.GenericExecute = KEY_READ;
  1123. genericMapping.GenericAll = KEY_ALL_ACCESS;
  1124. if (!CheckForValidSD(pSD))
  1125. {
  1126. return IDCANCEL;
  1127. }
  1128. m_sCallBackContext.fIsIAC = SDisIAC(pSD);
  1129. if (m_sCallBackContext.fIsIAC)
  1130. {
  1131. // convert to a true security descriptor
  1132. SECURITY_DESCRIPTOR * pNewSD = SDfromIAC(pSD);
  1133. if (!pNewSD)
  1134. {
  1135. // failed so pop up an error box
  1136. CString sMsg, sCaption;
  1137. sMsg.LoadString(IDS_BADSD);
  1138. sCaption.LoadString(IDS_SYSTEMMESSAGE);
  1139. MessageBox(NULL, sMsg, sCaption, MB_OK);
  1140. return IDCANCEL;
  1141. }
  1142. if (fFreePSD)
  1143. {
  1144. GlobalFree(pSD);
  1145. }
  1146. pSD=pNewSD;
  1147. fFreePSD = TRUE;
  1148. }
  1149. // Invoke the ACL editor
  1150. SedDiscretionaryAclEditor(hWnd, // Owner hWnd
  1151. GetModuleHandle(NULL), // Owner hInstance
  1152. NULL, // Server
  1153. &objTyp, // ObjectTyp,
  1154. &appAccesses, // Application accesses
  1155. szTitle ? szTitle : szHkeyClassesRoot,// Object name,
  1156. callBackFunc, // Callback function
  1157. (ULONG_PTR) &m_sCallBackContext, // Callback context
  1158. pSD, // Security descriptor,
  1159. FALSE, // Couldnt read Dacl,
  1160. FALSE, // Can't write Dacl,
  1161. &dwStatus, // SED status return,
  1162. 0); // Flags
  1163. // Check status return
  1164. if (dwStatus != ERROR_SUCCESS)
  1165. {
  1166. // PostErrorMessage(dwStatus);
  1167. }
  1168. // We're done
  1169. if (fFreePSD)
  1170. {
  1171. GlobalFree(pSD);
  1172. }
  1173. return dwStatus == 0 ? ERROR_SUCCESS : IDCANCEL;
  1174. #else
  1175. return IDCANCEL;
  1176. #endif
  1177. }
  1178. BOOL CUtility::InvokeUserBrowser(HWND hWnd, TCHAR *szUser)
  1179. {
  1180. BOOL fRet = FALSE;
  1181. #if !defined(STANDALONE_BUILD)
  1182. CString szTitle;
  1183. szTitle.LoadString(IDS_Browse_for_users);
  1184. IDsObjectPicker *pDsObjectPicker = NULL;
  1185. HRESULT hr = CoCreateInstance(CLSID_DsObjectPicker,
  1186. NULL,
  1187. CLSCTX_INPROC_SERVER,
  1188. IID_IDsObjectPicker,
  1189. (void**)&pDsObjectPicker);
  1190. if (SUCCEEDED(hr))
  1191. {
  1192. IDataObject *pDataObject = NULL;
  1193. // Fill in the structures necessary to init the dialog.
  1194. DSOP_SCOPE_INIT_INFO rgInitInfo[2];
  1195. ZeroMemory(rgInitInfo, sizeof(rgInitInfo));
  1196. rgInitInfo[0].cbSize = sizeof(DSOP_SCOPE_INIT_INFO);
  1197. rgInitInfo[0].flType = DSOP_SCOPE_TYPE_TARGET_COMPUTER;
  1198. rgInitInfo[0].flScope = DSOP_SCOPE_FLAG_STARTING_SCOPE |
  1199. DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT;
  1200. rgInitInfo[0].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS;
  1201. rgInitInfo[0].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS;
  1202. rgInitInfo[1].cbSize = sizeof(DSOP_SCOPE_INIT_INFO);
  1203. rgInitInfo[1].flType = DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN |
  1204. DSOP_SCOPE_TYPE_GLOBAL_CATALOG |
  1205. DSOP_SCOPE_TYPE_WORKGROUP |
  1206. DSOP_SCOPE_TYPE_USER_ENTERED_UPLEVEL_SCOPE |
  1207. DSOP_SCOPE_TYPE_USER_ENTERED_DOWNLEVEL_SCOPE |
  1208. DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN |
  1209. DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN;
  1210. rgInitInfo[1].flScope = DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT;
  1211. rgInitInfo[1].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS;
  1212. rgInitInfo[1].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS;
  1213. DSOP_INIT_INFO dsInitInfo = { sizeof(dsInitInfo) };
  1214. dsInitInfo.aDsScopeInfos = rgInitInfo;
  1215. dsInitInfo.cDsScopeInfos = sizeof(rgInitInfo) / sizeof(rgInitInfo[0]);
  1216. hr = pDsObjectPicker->Initialize(&dsInitInfo);
  1217. if (SUCCEEDED(hr))
  1218. {
  1219. hr = pDsObjectPicker->InvokeDialog(hWnd, &pDataObject);
  1220. }
  1221. // Yes, I mean S_OK. The return code is S_FALSE if the user hits CANCEL.
  1222. if (hr == S_OK)
  1223. {
  1224. // Why, yes, this DOES _s_u_c_k_!
  1225. CLIPFORMAT cfDsObjectPicker = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
  1226. STGMEDIUM stgMed = { TYMED_HGLOBAL,
  1227. NULL,
  1228. NULL };
  1229. FORMATETC fmtEtc = { cfDsObjectPicker,
  1230. NULL,
  1231. DVASPECT_CONTENT,
  1232. -1,
  1233. TYMED_HGLOBAL };
  1234. hr = pDataObject->GetData(&fmtEtc, &stgMed);
  1235. if (SUCCEEDED(hr))
  1236. {
  1237. PDS_SELECTION_LIST pSelList = (PDS_SELECTION_LIST)GlobalLock(stgMed.hGlobal);
  1238. // Only care about the first item (should be single select, see above).
  1239. assert(pSelList->cItems <= 1);
  1240. PWSTR pwszName = NULL;
  1241. PWSTR pwszDomain = NULL;
  1242. PWSTR pwszPath = pSelList->aDsSelection[0].pwzADsPath;
  1243. if (pwszPath && pwszPath[0])
  1244. {
  1245. // e.g. "WinNT://REDMOND/johndoty"
  1246. pwszName = wcsrchr(pwszPath, L'/');
  1247. assert(pwszName != NULL);
  1248. if (pwszName == NULL)
  1249. pwszName = pwszPath;
  1250. *pwszName = L'\0';
  1251. pwszDomain = wcsrchr(pwszPath, L'/');
  1252. assert(pwszDomain != NULL);
  1253. if (pwszDomain == NULL)
  1254. pwszDomain = pwszPath;
  1255. else
  1256. pwszDomain++;
  1257. pwszName++;
  1258. }
  1259. else
  1260. {
  1261. // e.g. "Everyone"
  1262. pwszName = pSelList->aDsSelection[0].pwzName;
  1263. }
  1264. if (pwszName && pwszName[0])
  1265. {
  1266. // Text buffer has already been allocated (*gulp*)
  1267. CString szBackslash;
  1268. szBackslash.LoadString(IDS_backslash);
  1269. if (pwszDomain)
  1270. _tcscpy(szUser, pwszDomain);
  1271. else
  1272. szUser[0] = L'\0';
  1273. _tcscat(szUser, (LPCTSTR) szBackslash);
  1274. _tcscat(szUser, pwszName);
  1275. fRet = TRUE;
  1276. }
  1277. ::GlobalUnlock(stgMed.hGlobal);
  1278. ReleaseStgMedium(&stgMed);
  1279. }
  1280. pDataObject->Release();
  1281. }
  1282. pDsObjectPicker->Release();
  1283. }
  1284. #endif
  1285. return fRet;
  1286. }
  1287. BOOL CUtility::InvokeMachineBrowser(TCHAR *szMachine)
  1288. {
  1289. #if !defined(STANDALONE_BUILD)
  1290. ///////////////////////////////////////////////////
  1291. // If we end up not wanting to use I_SystemFocusDialog, then the code below
  1292. // is the start for fetching machine resources ourselves
  1293. /*
  1294. DWORD dwErr;
  1295. NETRESOURCE aNetResource[1000];
  1296. HANDLE hNetwork;
  1297. DWORD dwEntries = 100;
  1298. DWORD dwBufSize = sizeof(aNetResource);
  1299. dwErr = WNetOpenEnum(RESOURCE_GLOBALNET,
  1300. RESOURCETYPE_ANY,
  1301. 0,
  1302. NULL,
  1303. &hNetwork);
  1304. if (dwErr == NO_ERROR)
  1305. {
  1306. dwEntries = 0xffffffff;
  1307. dwErr = WNetEnumResource(hNetwork,
  1308. &dwEntries,
  1309. aNetResource,
  1310. &dwBufSize);
  1311. }
  1312. WNetCloseEnum(hNetwork);
  1313. dwErr = WNetOpenEnum(RESOURCE_GLOBALNET,
  1314. RESOURCETYPE_ANY,
  1315. 0,
  1316. aNetResource,
  1317. &hNetwork);
  1318. if (dwErr == NO_ERROR)
  1319. {
  1320. dwEntries = 0xffffffff;
  1321. dwErr = WNetEnumResource(hNetwork,
  1322. &dwEntries,
  1323. &aNetResource[1],
  1324. &dwBufSize);
  1325. }
  1326. return dwErr == NO_ERROR ? TRUE : FALSE;
  1327. */
  1328. ///////////////////////////////////////////////////////
  1329. UINT err;
  1330. BOOL fOkPressed = FALSE;
  1331. err = I_SystemFocusDialog(GetForegroundWindow(),
  1332. // FOCUSDLG_BROWSE_LOGON_DOMAIN |
  1333. // FOCUSDLG_BROWSE_WKSTA_DOMAIN,
  1334. 0x30003,
  1335. szMachine,
  1336. 128,
  1337. &fOkPressed,
  1338. TEXT("dcomcnfg.hlp"),
  1339. IDH_SELECT_DOMAIN);
  1340. if (err == ERROR_SUCCESS && fOkPressed)
  1341. {
  1342. return TRUE;
  1343. }
  1344. else
  1345. {
  1346. return FALSE;
  1347. }
  1348. #else
  1349. return FALSE;
  1350. #endif
  1351. }
  1352. int CUtility::StringFromGUID(GUID &rguid, TCHAR *lpsz, int cbMax)
  1353. {
  1354. int i;
  1355. LPWSTR p = lpsz;
  1356. const BYTE * pBytes = (const BYTE *) &rguid;
  1357. *p++ = L'{';
  1358. for (i = 0; i < sizeof(GuidMap); i++)
  1359. {
  1360. if (GuidMap[i] == '-')
  1361. {
  1362. *p++ = L'-';
  1363. }
  1364. else
  1365. {
  1366. *p++ = wszDigits[ (pBytes[GuidMap[i]] & 0xF0) >> 4 ];
  1367. *p++ = wszDigits[ (pBytes[GuidMap[i]] & 0x0F) ];
  1368. }
  1369. }
  1370. *p++ = L'}';
  1371. *p = L'\0';
  1372. return GUIDSTR_MAX;
  1373. }
  1374. BOOL CUtility::IsEqualGuid(GUID &guid1, GUID &guid2)
  1375. {
  1376. return (
  1377. ((PLONG) &guid1)[0] == ((PLONG) &guid2)[0] &&
  1378. ((PLONG) &guid1)[1] == ((PLONG) &guid2)[1] &&
  1379. ((PLONG) &guid1)[2] == ((PLONG) &guid2)[2] &&
  1380. ((PLONG) &guid1)[3] == ((PLONG) &guid2)[3]);
  1381. }
  1382. BOOL CUtility::AdjustPrivilege(TCHAR *szPrivilege)
  1383. {
  1384. HANDLE hProcessToken = 0;
  1385. BOOL bOK = FALSE;
  1386. TOKEN_PRIVILEGES privileges;
  1387. if( !OpenProcessToken( GetCurrentProcess(),
  1388. TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
  1389. &hProcessToken ) )
  1390. {
  1391. return FALSE;
  1392. }
  1393. privileges.PrivilegeCount = 1;
  1394. privileges.Privileges[ 0 ].Attributes = SE_PRIVILEGE_ENABLED;
  1395. if( !LookupPrivilegeValue(NULL, szPrivilege,
  1396. &privileges.Privileges[ 0 ].Luid ) )
  1397. {
  1398. return FALSE;
  1399. }
  1400. if( !AdjustTokenPrivileges( hProcessToken, FALSE,
  1401. &privileges,
  1402. 0L, NULL, NULL ) )
  1403. {
  1404. return FALSE;
  1405. }
  1406. if( hProcessToken )
  1407. {
  1408. CloseHandle( hProcessToken );
  1409. }
  1410. return TRUE;
  1411. }
  1412. BOOL CUtility::VerifyRemoteMachine(TCHAR *szRemoteMachine)
  1413. {
  1414. NETRESOURCE sResource;
  1415. NETRESOURCE sResource2;
  1416. DWORD dwErr;
  1417. HANDLE hEnum;
  1418. DWORD cbEntries;
  1419. DWORD cbBfr;
  1420. // TODO: Get this function to work. Right now WNetEnumResource is
  1421. // screwing up the stack, causing an AV and anyway returns the error
  1422. // ERROR_NO_MORE_ITEMS which I don't understand.
  1423. //
  1424. // Also, it is not clear that we should verify the remote machine name.
  1425. // It may have different formats, e.g. IP address or a URL specification.
  1426. // It may not even be on an NT network. In any case it may be offline
  1427. // currently.
  1428. return TRUE;
  1429. sResource.dwScope = RESOURCE_GLOBALNET;
  1430. sResource.dwType = RESOURCETYPE_ANY;
  1431. sResource.dwDisplayType = RESOURCEDISPLAYTYPE_GENERIC;
  1432. sResource.dwUsage = RESOURCEUSAGE_CONTAINER;
  1433. sResource.lpLocalName = NULL;
  1434. sResource.lpRemoteName = szRemoteMachine;
  1435. sResource.lpComment = NULL;
  1436. sResource.lpProvider = NULL;
  1437. dwErr = WNetOpenEnum(RESOURCE_GLOBALNET,
  1438. RESOURCETYPE_ANY,
  1439. RESOURCEUSAGE_CONTAINER,
  1440. &sResource,
  1441. &hEnum);
  1442. if (dwErr == NO_ERROR)
  1443. {
  1444. cbEntries = 1;
  1445. cbBfr = sizeof(NETRESOURCE);
  1446. dwErr = WNetEnumResource(hEnum, &cbEntries, &sResource2, &cbBfr);
  1447. }
  1448. CloseHandle(hEnum);
  1449. return TRUE;
  1450. }
  1451. BOOL CUtility::RetrieveUserPassword(TCHAR *szAppid, CString &sPassword)
  1452. {
  1453. #if !defined(STANDALONE_BUILD)
  1454. LSA_OBJECT_ATTRIBUTES sObjAttributes;
  1455. HANDLE hPolicy = NULL;
  1456. LSA_UNICODE_STRING sKey;
  1457. PLSA_UNICODE_STRING psPassword;
  1458. TCHAR szKey[4 + GUIDSTR_MAX + 1];
  1459. // Formulate the access key
  1460. if (_tcslen(szAppid) > GUIDSTR_MAX)
  1461. return FALSE;
  1462. _tcscpy(szKey, TEXT("SCM:"));
  1463. _tcscat(szKey, szAppid);
  1464. // UNICODE_STRING length fields are in bytes and include the NULL
  1465. // terminator
  1466. sKey.Length = (_tcslen(szKey) + 1) * sizeof(TCHAR);
  1467. sKey.MaximumLength = (GUIDSTR_MAX + 5) * sizeof(TCHAR);
  1468. sKey.Buffer = szKey;
  1469. // Open the local security policy
  1470. InitializeObjectAttributes(&sObjAttributes, NULL, 0L, NULL, NULL);
  1471. if (!NT_SUCCESS(LsaOpenPolicy(NULL, &sObjAttributes,
  1472. POLICY_GET_PRIVATE_INFORMATION, &hPolicy)))
  1473. {
  1474. return FALSE;
  1475. }
  1476. // Read the user's password
  1477. if (!NT_SUCCESS(LsaRetrievePrivateData(hPolicy, &sKey, &psPassword)))
  1478. {
  1479. LsaClose(hPolicy);
  1480. return FALSE;
  1481. }
  1482. // Close the policy handle, we're done with it now.
  1483. LsaClose(hPolicy);
  1484. // Possible for LsaRetrievePrivateData to return success but with a NULL
  1485. // psPassword. If this happens we fail.
  1486. if (!psPassword)
  1487. {
  1488. return FALSE;
  1489. }
  1490. // Copy the password
  1491. sPassword = psPassword->Buffer;
  1492. // Clear and free lsa's buffer
  1493. SecureZeroMemory(psPassword->Buffer, psPassword->Length);
  1494. LsaFreeMemory( psPassword );
  1495. return TRUE;
  1496. #else
  1497. return FALSE;
  1498. #endif
  1499. }
  1500. BOOL CUtility::StoreUserPassword(TCHAR *szAppid, CString &szPassword)
  1501. {
  1502. #if !defined(STANDALONE_BUILD)
  1503. LSA_OBJECT_ATTRIBUTES sObjAttributes;
  1504. HANDLE hPolicy = NULL;
  1505. LSA_UNICODE_STRING sKey;
  1506. LSA_UNICODE_STRING sPassword;
  1507. TCHAR szKey[4 + GUIDSTR_MAX + 1];
  1508. // Formulate the access key
  1509. if (_tcslen(szAppid) > GUIDSTR_MAX)
  1510. return FALSE;
  1511. _tcscpy(szKey, TEXT("SCM:"));
  1512. _tcscat(szKey, szAppid);
  1513. // UNICODE_STRING length fields are in bytes and include the NULL
  1514. // terminator
  1515. sKey.Length = (_tcslen(szKey) + 1) * sizeof(TCHAR);
  1516. sKey.MaximumLength = (GUIDSTR_MAX + 5) * sizeof(TCHAR);
  1517. sKey.Buffer = szKey;
  1518. // Make the password a UNICODE string
  1519. sPassword.Length = (_tcslen(LPCTSTR(szPassword)) + 1) * sizeof(TCHAR);
  1520. sPassword.Buffer = (TCHAR *) LPCTSTR(szPassword);
  1521. sPassword.MaximumLength = sPassword.Length;
  1522. // Open the local security policy
  1523. InitializeObjectAttributes(&sObjAttributes, NULL, 0L, NULL, NULL);
  1524. if (!NT_SUCCESS(LsaOpenPolicy(NULL, &sObjAttributes,
  1525. POLICY_CREATE_SECRET, &hPolicy)))
  1526. {
  1527. return FALSE;
  1528. }
  1529. // Store the user's password
  1530. if (!NT_SUCCESS(LsaStorePrivateData(hPolicy, &sKey, &sPassword)))
  1531. {
  1532. g_util.PostErrorMessage();
  1533. LsaClose(hPolicy);
  1534. return FALSE;
  1535. }
  1536. // Close the policy handle, we're done with it now.
  1537. LsaClose(hPolicy);
  1538. return TRUE;
  1539. #else
  1540. return FALSE;
  1541. #endif
  1542. }
  1543. BOOL CUtility::LookupProcessInfo(SID **ppSid, TCHAR **ppszPrincName)
  1544. {
  1545. BYTE aMemory[SIZEOF_TOKEN_USER];
  1546. TOKEN_USER *pTokenUser = (TOKEN_USER *) &aMemory;
  1547. HANDLE hToken = NULL;
  1548. DWORD lIgnore;
  1549. DWORD lSidLen;
  1550. DWORD lNameLen = 0;
  1551. DWORD lDomainLen = 0;
  1552. TCHAR *pDomainName = NULL;
  1553. SID_NAME_USE sIgnore;
  1554. if (ppszPrincName != NULL)
  1555. *ppszPrincName = NULL;
  1556. // Open the process's token.
  1557. if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
  1558. {
  1559. // Lookup SID of process token.
  1560. if (GetTokenInformation( hToken, TokenUser, pTokenUser,
  1561. sizeof(aMemory), &lIgnore ))
  1562. {
  1563. // Allocate memory to hold the SID.
  1564. lSidLen = GetLengthSid( pTokenUser->User.Sid );
  1565. *ppSid = (SID *) new BYTE[lSidLen];
  1566. if (*ppSid == NULL)
  1567. {
  1568. return FALSE;
  1569. }
  1570. memcpy(*ppSid, pTokenUser->User.Sid, lSidLen);
  1571. // Stop now if the caller doesn't want the user name.
  1572. if (ppszPrincName != NULL)
  1573. {
  1574. // Find out how much memory to allocate for the name.
  1575. LookupAccountSid(NULL, pTokenUser->User.Sid, NULL, &lNameLen,
  1576. NULL, &lDomainLen, NULL );
  1577. if (lNameLen != 0)
  1578. {
  1579. // Allocate memory for the user's name.
  1580. *ppszPrincName =
  1581. (TCHAR *) new BYTE[lNameLen*sizeof(TCHAR)];
  1582. if (ppszPrincName == NULL)
  1583. {
  1584. CloseHandle( hToken );
  1585. return FALSE;
  1586. }
  1587. pDomainName = (TCHAR *) new BYTE[lDomainLen*sizeof(TCHAR)];
  1588. if (pDomainName == NULL)
  1589. {
  1590. delete ppszPrincName;
  1591. CloseHandle( hToken );
  1592. return FALSE;
  1593. }
  1594. // Find the user's name.
  1595. if (!LookupAccountSid( NULL, pTokenUser->User.Sid,
  1596. *ppszPrincName, &lNameLen,
  1597. pDomainName,
  1598. &lDomainLen, &sIgnore))
  1599. {
  1600. delete ppszPrincName;
  1601. delete pDomainName;
  1602. CloseHandle( hToken );
  1603. return FALSE;
  1604. }
  1605. }
  1606. delete ppszPrincName;
  1607. delete pDomainName;
  1608. }
  1609. }
  1610. CloseHandle( hToken );
  1611. }
  1612. return TRUE;
  1613. }
  1614. BOOL CUtility::MakeSecDesc(SID *pSid, SECURITY_DESCRIPTOR **ppSD)
  1615. {
  1616. ACL *pAcl;
  1617. DWORD lSidLen;
  1618. SID *pGroup;
  1619. SID *pOwner;
  1620. // In case we fail
  1621. *ppSD = NULL;
  1622. // Allocate the security descriptor.
  1623. lSidLen = GetLengthSid( pSid );
  1624. *ppSD = (SECURITY_DESCRIPTOR *) GlobalAlloc(GMEM_FIXED,
  1625. sizeof(SECURITY_DESCRIPTOR) + 2*lSidLen + SIZEOF_ACL);
  1626. if (*ppSD == NULL)
  1627. {
  1628. return FALSE;
  1629. }
  1630. pGroup = (SID *) (*ppSD + 1);
  1631. pOwner = (SID *) (((BYTE *) pGroup) + lSidLen);
  1632. pAcl = (ACL *) (((BYTE *) pOwner) + lSidLen);
  1633. // Initialize a new security descriptor.
  1634. if (!InitializeSecurityDescriptor(*ppSD, SECURITY_DESCRIPTOR_REVISION))
  1635. {
  1636. GlobalFree(*ppSD);
  1637. return FALSE;
  1638. }
  1639. // Initialize a new ACL.
  1640. if (!InitializeAcl(pAcl, SIZEOF_ACL, ACL_REVISION2))
  1641. {
  1642. GlobalFree(*ppSD);
  1643. return FALSE;
  1644. }
  1645. // Comment out this code because the only time we create a default SD is
  1646. // when attempting to edit
  1647. // \\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLE.DefaultAccessPermission
  1648. // which we want to start with 0 ACE's
  1649. /*
  1650. // Allow the current user access.
  1651. if (!AddAccessAllowedAce( pAcl, ACL_REVISION2, COM_RIGHTS_EXECUTE, pSid ))
  1652. {
  1653. GlobalFree(*ppSD);
  1654. return FALSE;
  1655. }
  1656. // Allow local system access.
  1657. if (!AddAccessAllowedAce( pAcl, ACL_REVISION2, COM_RIGHTS_EXECUTE,
  1658. (void *) &LOCAL_SYSTEM_SID ))
  1659. {
  1660. GlobalFree(*ppSD);
  1661. return FALSE;
  1662. }
  1663. */
  1664. // Add a new ACL to the security descriptor.
  1665. if (!SetSecurityDescriptorDacl( *ppSD, TRUE, pAcl, FALSE ))
  1666. {
  1667. GlobalFree(*ppSD);
  1668. return FALSE;
  1669. }
  1670. // Set the group.
  1671. memcpy( pGroup, pSid, lSidLen );
  1672. if (!SetSecurityDescriptorGroup( *ppSD, pGroup, FALSE ))
  1673. {
  1674. GlobalFree(*ppSD);
  1675. return FALSE;
  1676. }
  1677. // Set the owner.
  1678. memcpy( pOwner, pSid, lSidLen );
  1679. if (!SetSecurityDescriptorOwner( *ppSD, pOwner, FALSE ))
  1680. {
  1681. GlobalFree(*ppSD);
  1682. return FALSE;
  1683. }
  1684. // Check the security descriptor.
  1685. assert(IsValidSecurityDescriptor(*ppSD));
  1686. return TRUE;
  1687. }
  1688. // Accepts either a traditional security descriptor or an IAccessControl
  1689. BOOL CUtility::CheckForValidSD(SECURITY_DESCRIPTOR *pSD)
  1690. {
  1691. WORD dwType = 0;
  1692. if (pSD)
  1693. {
  1694. dwType = *((WORD *)pSD);
  1695. }
  1696. if ((dwType != 1) && (dwType != 2))
  1697. {
  1698. CString sMsg, sCaption;
  1699. sMsg.LoadString(IDS_BADSD);
  1700. sCaption.LoadString(IDS_SYSTEMMESSAGE);
  1701. MessageBox(NULL, sMsg, sCaption, MB_OK);
  1702. return FALSE;
  1703. }
  1704. return TRUE;
  1705. }
  1706. // Check to see if the security descriptor is really a serialized IAccessControl.
  1707. BOOL CUtility::SDisIAC(SECURITY_DESCRIPTOR *pSD)
  1708. {
  1709. WORD dwType = *((WORD *)pSD);
  1710. if (dwType == 2)
  1711. {
  1712. return TRUE;
  1713. }
  1714. return FALSE;
  1715. }
  1716. SECURITY_DESCRIPTOR * CUtility::SDfromIAC(SECURITY_DESCRIPTOR * pSD)
  1717. {
  1718. IStream * pStream;
  1719. IAccessControl * pIAC;
  1720. IPersistStream * pIPS;
  1721. HRESULT hr;
  1722. BOOL fReturn;
  1723. // Un-serialize the IAccessControl
  1724. hr = CreateStreamOnHGlobal((HGLOBAL)pSD, FALSE, &pStream);
  1725. if (FAILED(hr))
  1726. {
  1727. return NULL;
  1728. }
  1729. // skip version
  1730. DWORD dwVersion;
  1731. hr = pStream->Read(&dwVersion, sizeof(DWORD), NULL);
  1732. if (FAILED(hr) || dwVersion != 2)
  1733. {
  1734. return NULL;
  1735. }
  1736. // skip CLSID
  1737. CLSID clsid;
  1738. hr = pStream->Read(&clsid, sizeof(CLSID), NULL);
  1739. if (FAILED(hr))
  1740. {
  1741. return NULL;
  1742. }
  1743. // create and IAccessControl and get an IPersistStream
  1744. hr = CoCreateInstance(clsid,
  1745. NULL,
  1746. CLSCTX_INPROC_SERVER,
  1747. IID_IAccessControl,
  1748. (void **)&pIAC);
  1749. if (FAILED(hr))
  1750. {
  1751. pStream->Release();
  1752. return NULL;
  1753. }
  1754. hr = pIAC->QueryInterface(IID_IPersistStream, (void **) &pIPS);
  1755. if (FAILED(hr))
  1756. {
  1757. pIAC->Release();
  1758. pStream->Release();
  1759. return NULL;
  1760. }
  1761. hr = pIPS->Load(pStream);
  1762. pIPS->Release();
  1763. pStream->Release();
  1764. if (FAILED(hr))
  1765. {
  1766. pIAC->Release();
  1767. return NULL;
  1768. }
  1769. // Create an EXPLICIT_ACCESS list for each entry in the IAccessControl
  1770. DWORD cAces;
  1771. ACTRL_ACCESS_ENTRYW * rgAE;
  1772. ACTRL_ACCESS * pAccess;
  1773. // PTRUSTEE pOwner;
  1774. // PTRUSTEE pGroup;
  1775. // hr = pIAC->GetAllAccessRights(NULL, &pAccess, &pOwner, &pGroup);
  1776. hr = pIAC->GetAllAccessRights(NULL, &pAccess, NULL, NULL);
  1777. if (FAILED(hr) || (pAccess->cEntries == 0))
  1778. {
  1779. pIAC->Release();
  1780. return NULL;
  1781. }
  1782. // we're assuming only one property entry
  1783. cAces = pAccess->pPropertyAccessList->pAccessEntryList->cEntries;
  1784. rgAE = pAccess->pPropertyAccessList->pAccessEntryList->pAccessList;
  1785. EXPLICIT_ACCESS * rgEA = new EXPLICIT_ACCESS[cAces];
  1786. DWORD i;
  1787. for (i = cAces; i--;)
  1788. {
  1789. LPTSTR szName = rgAE[i].Trustee.ptstrName;
  1790. if (TRUSTEE_IS_NAME == rgAE[i].Trustee.TrusteeForm && 0 == wcscmp(rgAE[i].Trustee.ptstrName, L"*"))
  1791. {
  1792. szName = new WCHAR [wcslen(L"EVERYONE") + 1];
  1793. if (!szName)
  1794. {
  1795. pIAC->Release();
  1796. return NULL;
  1797. }
  1798. wcscpy(szName, L"EVERYONE");
  1799. }
  1800. DWORD dwAccessPermissions = rgAE[i].Access; // should always be COM_RIGHTS_EXECUTE or GENERIC_ALL
  1801. ACCESS_MODE AccessMode;
  1802. switch (rgAE[i].fAccessFlags)
  1803. {
  1804. case ACTRL_ACCESS_ALLOWED:
  1805. AccessMode = SET_ACCESS;
  1806. dwAccessPermissions = COM_RIGHTS_EXECUTE; // HACK! Required to get ACL editor to work.
  1807. break;
  1808. case ACTRL_ACCESS_DENIED:
  1809. default:
  1810. AccessMode = DENY_ACCESS;
  1811. dwAccessPermissions = GENERIC_ALL; // HACK! Required to get ACL editor to work.
  1812. break;
  1813. }
  1814. DWORD dwInheritance = rgAE[i].Inheritance; // Carefull. May not be allowed.
  1815. BuildExplicitAccessWithName(
  1816. &rgEA[i],
  1817. szName,
  1818. dwAccessPermissions,
  1819. AccessMode,
  1820. dwInheritance);
  1821. }
  1822. SECURITY_DESCRIPTOR * pSDNew = NULL;
  1823. ULONG cbSize = 0;
  1824. // create the new Security descriptor
  1825. hr = BuildSecurityDescriptor(NULL, //pOwner,
  1826. NULL, //pGroup,
  1827. cAces,
  1828. rgEA,
  1829. 0,
  1830. NULL,
  1831. NULL,
  1832. &cbSize,
  1833. (void **)&pSDNew);
  1834. if (ERROR_SUCCESS != hr)
  1835. {
  1836. // For some reason this may fail with this error even when it appears to have worked
  1837. // A subsequent call seems to have no affect (i.e. it doesn't work like
  1838. // other security descriptor calls that expect you to allocate the buffer yourself)
  1839. if (ERROR_INSUFFICIENT_BUFFER != hr)
  1840. {
  1841. return NULL;
  1842. }
  1843. }
  1844. SECURITY_DESCRIPTOR * pSDCopy = (SECURITY_DESCRIPTOR *)GlobalAlloc(GMEM_FIXED, cbSize);
  1845. if (!pSDCopy)
  1846. {
  1847. LocalFree(pSDNew);
  1848. return NULL;
  1849. }
  1850. memcpy(pSDCopy, pSDNew, cbSize);
  1851. LocalFree(pSDNew);
  1852. //delete [] rgAE;
  1853. pIAC->Release();
  1854. return pSDCopy;
  1855. }
  1856. SECURITY_DESCRIPTOR * CUtility::IACfromSD(SECURITY_DESCRIPTOR * pSD)
  1857. {
  1858. IAccessControl * pIAC = NULL;
  1859. // create new IAccessControl object
  1860. HRESULT hr;
  1861. hr = CoCreateInstance(CLSID_DCOMAccessControl,
  1862. NULL,
  1863. CLSCTX_INPROC_SERVER,
  1864. IID_IAccessControl,
  1865. (void **) &pIAC);
  1866. if (FAILED(hr))
  1867. {
  1868. return (NULL);
  1869. }
  1870. IPersistStream * pIPS;
  1871. hr = pIAC->QueryInterface(IID_IPersistStream, (void **) &pIPS);
  1872. if (FAILED(hr))
  1873. {
  1874. pIAC->Release();
  1875. return NULL;
  1876. }
  1877. hr = pIPS->Load(NULL);
  1878. if (FAILED(hr))
  1879. {
  1880. pIPS->Release();
  1881. pIAC->Release();
  1882. return NULL;
  1883. }
  1884. BOOL fReturn, fDaclPresent, fDaclDefaulted;
  1885. ACL * pDacl;
  1886. // get the ACL list
  1887. fReturn = GetSecurityDescriptorDacl(pSD, &fDaclPresent, &pDacl, &fDaclDefaulted);
  1888. if (fReturn && fDaclPresent)
  1889. {
  1890. PEXPLICIT_ACCESS rgEA;
  1891. ULONG cAces;
  1892. #if 0 // Set to 1 when GetExplicitEntriesFromAcl works
  1893. DWORD dwReturn = GetExplicitEntriesFromAcl(pDacl,
  1894. &cAces,
  1895. &rgEA);
  1896. // enumerate the ACL, building list of objects to add to IAccessControl object
  1897. if (dwReturn != ERROR_SUCCESS)
  1898. {
  1899. pIAC->Release();
  1900. return NULL;
  1901. }
  1902. ACTRL_ACCESSW stAccess;
  1903. ACTRL_PROPERTY_ENTRYW stProperty;
  1904. ACTRL_ACCESS_ENTRY_LISTW stAccessList;
  1905. stAccess.cEntries = 1;
  1906. stAccess.pPropertyAccessList = &stProperty;
  1907. stProperty.lpProperty = NULL;
  1908. stProperty.pAccessEntryList = &stAccessList;
  1909. stProperty.fListFlags = 0;
  1910. stAccessList.cEntries = cAces;
  1911. ACTRL_ACCESS_ENTRYW * rgAE = new ACTRL_ACCESS_ENTRYW[cAces];
  1912. stAccessList.pAccessList = rgAE;
  1913. ULONG i;
  1914. for (i = cAces; i--; )
  1915. {
  1916. rgAE[i].Trustee = rgEA[i].Trustee;
  1917. if (rgEA[i].Trustee.TrusteeForm == TRUSTEE_IS_SID)
  1918. {
  1919. // convert to a named trustee
  1920. rgAE[i].Trustee.TrusteeForm = TRUSTEE_IS_NAME;
  1921. SID * pSid = (SID *)rgEA[i].Trustee.ptstrName;
  1922. DWORD cbName = 0;
  1923. DWORD cbDomain = 0;
  1924. LPTSTR szName = NULL;
  1925. LPTSTR szDomain = NULL;
  1926. SID_NAME_USE snu;
  1927. fReturn = LookupAccountSid(NULL,
  1928. pSid,
  1929. szName,
  1930. &cbName,
  1931. szDomain,
  1932. &cbDomain,
  1933. &snu);
  1934. szName = (LPTSTR) new char [cbName];
  1935. szDomain = (LPTSTR) new char [cbDomain];
  1936. fReturn = LookupAccountSid(NULL,
  1937. pSid,
  1938. szName,
  1939. &cbName,
  1940. szDomain,
  1941. &cbDomain,
  1942. &snu);
  1943. CString * pcs = new CString;
  1944. (*pcs) = TEXT("\\\\");
  1945. (*pcs) += szDomain;
  1946. (*pcs) += TEXT("\\");
  1947. (*pcs) += szName;
  1948. rgAE[i].Trustee.ptstrName = (LPTSTR)(LPCTSTR)(*pcs);
  1949. }
  1950. else
  1951. {
  1952. #if 0 // REMOVE THIS HACK when GetExplicitEntriesFromAcl works as it should
  1953. if (rgAE[i].Trustee.TrusteeType < TRUSTEE_IS_WELL_KNOWN_GROUP)
  1954. {
  1955. rgAE[i].Trustee.TrusteeType = (enum _TRUSTEE_TYPE)((unsigned)rgAE[i].Trustee.TrusteeType + 1);
  1956. }
  1957. #endif
  1958. if (rgAE[i].Trustee.TrusteeType == TRUSTEE_IS_WELL_KNOWN_GROUP)
  1959. {
  1960. // IAccessControl::GrantAccessRights doesn't like TRUSTEE_IS_WELL_KNOWN_GROUP for some reason
  1961. rgAE[i].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  1962. }
  1963. }
  1964. // test for "the world"
  1965. if (TRUSTEE_IS_WELL_KNOWN_GROUP == rgAE[i].Trustee.TrusteeType &&
  1966. 0 == _wcsicmp(L"Everyone", rgAE[i].Trustee.ptstrName))
  1967. {
  1968. rgAE[i].Trustee.ptstrName[0] = L'*';
  1969. rgAE[i].Trustee.ptstrName[1] = 0;
  1970. }
  1971. rgAE[i].Access = rgEA[i].grfAccessPermissions;
  1972. rgAE[i].ProvSpecificAccess = 0;
  1973. rgAE[i].Inheritance = rgEA[i].grfInheritance;
  1974. rgAE[i].lpInheritProperty = NULL;
  1975. switch (rgEA[i].grfAccessMode)
  1976. {
  1977. case SET_ACCESS:
  1978. rgAE[i].fAccessFlags = ACTRL_ACCESS_ALLOWED;
  1979. break;
  1980. case DENY_ACCESS:
  1981. default:
  1982. rgAE[i].fAccessFlags = ACTRL_ACCESS_DENIED;
  1983. break;
  1984. }
  1985. }
  1986. #else
  1987. ACL_SIZE_INFORMATION aclInfo;
  1988. fReturn = GetAclInformation(pDacl, &aclInfo, sizeof(aclInfo), AclSizeInformation);
  1989. if (!fReturn)
  1990. {
  1991. pIPS->Release();
  1992. pIAC->Release();
  1993. return NULL;
  1994. }
  1995. cAces = aclInfo.AceCount;
  1996. ACE_HEADER * pAceHeader;
  1997. ACTRL_ACCESSW stAccess;
  1998. ACTRL_PROPERTY_ENTRYW stProperty;
  1999. ACTRL_ACCESS_ENTRY_LISTW stAccessList;
  2000. stAccess.cEntries = 1;
  2001. stAccess.pPropertyAccessList = &stProperty;
  2002. stProperty.lpProperty = NULL;
  2003. stProperty.pAccessEntryList = &stAccessList;
  2004. stProperty.fListFlags = 0;
  2005. stAccessList.cEntries = cAces;
  2006. ACTRL_ACCESS_ENTRYW * rgAE = new ACTRL_ACCESS_ENTRYW[cAces];
  2007. if (!rgAE)
  2008. {
  2009. pIPS->Release();
  2010. pIAC->Release();
  2011. return NULL;
  2012. }
  2013. stAccessList.pAccessList = rgAE;
  2014. ULONG i;
  2015. for (i = cAces; i--; )
  2016. {
  2017. rgAE[i].ProvSpecificAccess = 0;
  2018. rgAE[i].Inheritance = NO_INHERITANCE;
  2019. rgAE[i].lpInheritProperty = NULL;
  2020. rgAE[i].Trustee.pMultipleTrustee = NULL;
  2021. rgAE[i].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
  2022. rgAE[i].Trustee.TrusteeForm = TRUSTEE_IS_NAME;
  2023. rgAE[i].Access = COM_RIGHTS_EXECUTE;
  2024. fReturn = GetAce(pDacl, i, (LPVOID *)&pAceHeader);
  2025. if (!fReturn)
  2026. {
  2027. delete [] rgAE;
  2028. pIPS->Release();
  2029. pIAC->Release();
  2030. return NULL;
  2031. }
  2032. SID * pSid = NULL;
  2033. switch (pAceHeader->AceType)
  2034. {
  2035. case ACCESS_ALLOWED_ACE_TYPE:
  2036. {
  2037. rgAE[i].fAccessFlags = ACTRL_ACCESS_ALLOWED;
  2038. ACCESS_ALLOWED_ACE * pAce = (ACCESS_ALLOWED_ACE *)pAceHeader;
  2039. pSid = (SID *) &(pAce->SidStart);
  2040. }
  2041. break;
  2042. case ACCESS_DENIED_ACE_TYPE:
  2043. {
  2044. rgAE[i].fAccessFlags = ACTRL_ACCESS_DENIED;
  2045. ACCESS_DENIED_ACE * pAce = (ACCESS_DENIED_ACE *)pAceHeader;
  2046. pSid = (SID *) &(pAce->SidStart);
  2047. }
  2048. break;
  2049. default:
  2050. break;
  2051. }
  2052. TCHAR szName[MAX_PATH];
  2053. TCHAR szDomain[MAX_PATH];
  2054. DWORD cbName = MAX_PATH;
  2055. DWORD cbDomain = MAX_PATH;
  2056. SID_NAME_USE use;
  2057. if(pSid)
  2058. {
  2059. fReturn = LookupAccountSid(NULL,
  2060. pSid,
  2061. szName,
  2062. &cbName,
  2063. szDomain,
  2064. &cbDomain,
  2065. &use);
  2066. }
  2067. else
  2068. {
  2069. fReturn = FALSE; // i.e., we took default path above
  2070. }
  2071. if (!fReturn)
  2072. {
  2073. delete [] rgAE;
  2074. pIPS->Release();
  2075. pIAC->Release();
  2076. return NULL;
  2077. }
  2078. switch (use)
  2079. {
  2080. case SidTypeUser:
  2081. rgAE[i].Trustee.TrusteeType = TRUSTEE_IS_USER;
  2082. break;
  2083. case SidTypeGroup:
  2084. rgAE[i].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  2085. break;
  2086. case SidTypeAlias:
  2087. rgAE[i].Trustee.TrusteeType = TRUSTEE_IS_ALIAS;
  2088. break;
  2089. case SidTypeWellKnownGroup:
  2090. //rgAE[i].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  2091. rgAE[i].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  2092. break;
  2093. case SidTypeDeletedAccount:
  2094. rgAE[i].Trustee.TrusteeType = TRUSTEE_IS_DELETED;
  2095. break;
  2096. case SidTypeInvalid:
  2097. rgAE[i].Trustee.TrusteeType = TRUSTEE_IS_INVALID;
  2098. break;
  2099. case SidTypeDomain:
  2100. rgAE[i].Trustee.TrusteeType = TRUSTEE_IS_GROUP; //TRUSTEE_IS_DOMAIN;
  2101. break;
  2102. case SidTypeUnknown:
  2103. default:
  2104. rgAE[i].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
  2105. break;
  2106. }
  2107. CString sz;
  2108. // test for "the world"
  2109. if (0 == wcslen(szDomain) && 0 == _wcsicmp(L"Everyone", szName))
  2110. {
  2111. sz = "*";
  2112. }
  2113. else
  2114. {
  2115. sz = szDomain;
  2116. sz += "\\";
  2117. sz += szName;
  2118. }
  2119. WCHAR * wsz = new WCHAR[sz.GetLength() + 1];
  2120. wcscpy(wsz, (LPCWSTR)sz);
  2121. rgAE[i].Trustee.ptstrName = wsz;
  2122. }
  2123. #endif
  2124. delete [] rgAE;
  2125. hr = pIAC->GrantAccessRights(&stAccess);
  2126. if (FAILED(hr))
  2127. {
  2128. pIPS->Release();
  2129. pIAC->Release();
  2130. return NULL;
  2131. }
  2132. // free up structures
  2133. // LocalFree(rgEA);
  2134. }
  2135. // serialize the IAccessControl object
  2136. // Find out how big it is
  2137. ULARGE_INTEGER size;
  2138. hr = pIPS->GetSizeMax(&size);
  2139. if (FAILED(hr))
  2140. {
  2141. pIPS->Release();
  2142. pIAC->Release();
  2143. return NULL;
  2144. }
  2145. size.QuadPart += sizeof(DWORD) + sizeof (CLSID);
  2146. HANDLE hMem = GlobalAlloc(GMEM_FIXED, size.LowPart);
  2147. if (hMem != NULL)
  2148. {
  2149. IStream * pStream;
  2150. hr = CreateStreamOnHGlobal(hMem, FALSE, &pStream);
  2151. if (FAILED(hr))
  2152. {
  2153. pIPS->Release();
  2154. pIAC->Release();
  2155. return NULL;
  2156. }
  2157. DWORD dwVersion = 2;
  2158. CLSID clsid = CLSID_DCOMAccessControl;
  2159. hr = pStream->Write(&dwVersion, sizeof(DWORD), NULL);
  2160. if (FAILED(hr))
  2161. {
  2162. pStream->Release();
  2163. pIPS->Release();
  2164. pIAC->Release();
  2165. return NULL;
  2166. }
  2167. hr = pStream->Write(&clsid, sizeof(CLSID), NULL);
  2168. if (FAILED(hr))
  2169. {
  2170. pStream->Release();
  2171. pIPS->Release();
  2172. pIAC->Release();
  2173. return NULL;
  2174. }
  2175. hr = pIPS->Save(pStream, TRUE);
  2176. pStream->Release();
  2177. if (FAILED(hr))
  2178. {
  2179. pIPS->Release();
  2180. pIAC->Release();
  2181. return NULL;
  2182. }
  2183. }
  2184. pIPS->Release();
  2185. pIAC->Release();
  2186. return (SECURITY_DESCRIPTOR *) hMem;
  2187. }
  2188. BOOL CUtility::CheckSDForCOM_RIGHTS_EXECUTE(SECURITY_DESCRIPTOR *pSD)
  2189. {
  2190. PSrAcl pDacl;
  2191. PSrAce pAce;
  2192. DWORD cbAces;
  2193. SECURITY_DESCRIPTOR_RELATIVE* pSDr = (SECURITY_DESCRIPTOR_RELATIVE*) pSD;
  2194. // Check whether the security descriptor is self-relative
  2195. if (!(pSD->Control & SE_SELF_RELATIVE))
  2196. {
  2197. pDacl = (PSrAcl) pSD->Dacl;
  2198. // Check for a deny ALL
  2199. if (pDacl == NULL)
  2200. {
  2201. return TRUE;
  2202. }
  2203. }
  2204. else
  2205. {
  2206. // First check for a deny ALL
  2207. if (pSDr->Dacl == 0)
  2208. {
  2209. return TRUE;
  2210. }
  2211. pDacl = (PSrAcl) (((BYTE *) pSDr) + (pSDr->Dacl));
  2212. }
  2213. // Do over the ACE's
  2214. for (pAce = (PSrAce) (((BYTE *) pDacl) + sizeof(SSrAcl)),
  2215. cbAces = pDacl->AceCount;
  2216. cbAces;
  2217. pAce = (PSrAce) (((BYTE *) pAce) + pAce->AceSize),
  2218. cbAces--)
  2219. {
  2220. // workaround for the ACL editor bug. If the ACL editor sees a non GENERIC_ALL deny ACE, it
  2221. // complains. So we convert COM_RIGHTS_EXECUTE to GENERIC_ALL. On the way back we will
  2222. // do the reverse. See CallBackFunc for the other half of this fix.
  2223. if (pAce->Type == 1 && pAce->AccessMask == COM_RIGHTS_EXECUTE)
  2224. {
  2225. pAce->AccessMask = GENERIC_ALL;
  2226. }
  2227. // Check that it is
  2228. // a) an allow on COM_RIGHTS_EXECUTE
  2229. // b) a deny on GENERIC_ALL,
  2230. // c) a deny on COM_RIGHTS_EXECUTE,
  2231. // d) a deny ALL (handled above if the DACL is NULL) or
  2232. // e) an allow everyone (handled implicitly if cbAces == 0)
  2233. if (!(((pAce->Type == 0 && pAce->AccessMask == COM_RIGHTS_EXECUTE)
  2234. ||
  2235. (pAce->Type == 1 && pAce->AccessMask == GENERIC_ALL)
  2236. ||
  2237. (pAce->Type == 1 && pAce->AccessMask == COM_RIGHTS_EXECUTE))))
  2238. {
  2239. CString szText;
  2240. CString szTitle;
  2241. szText.LoadString(IDS_The_security_);
  2242. szTitle.LoadString(IDS_DCOM_Configuration_Warning);
  2243. if (MessageBox(GetForegroundWindow(),
  2244. (LPCTSTR) szText,
  2245. (LPCTSTR) szTitle,
  2246. MB_YESNO) == IDYES)
  2247. {
  2248. pAce->Flags = 0;
  2249. pAce->Type = 0;
  2250. pAce->AccessMask = COM_RIGHTS_EXECUTE;
  2251. }
  2252. else
  2253. {
  2254. return FALSE;
  2255. }
  2256. }
  2257. }
  2258. return TRUE;
  2259. }
  2260. BOOL CUtility::ChangeService(LPCTSTR szService,
  2261. LPCTSTR szIdentity,
  2262. LPCTSTR szPassword,
  2263. LPCTSTR szDisplay)
  2264. {
  2265. SC_HANDLE hSCManager;
  2266. SC_HANDLE hService;
  2267. QUERY_SERVICE_CONFIG qsc;
  2268. DWORD dwBytesNeeded = 0;
  2269. LPTSTR lpszTmpDisplay = (LPTSTR)szDisplay;
  2270. // Open the service control manager
  2271. if (hSCManager = OpenSCManager(NULL, NULL, GENERIC_READ | GENERIC_WRITE))
  2272. {
  2273. // Try to open a handle to the requested service
  2274. if (!(hService = OpenService(hSCManager,
  2275. szService,
  2276. GENERIC_READ | GENERIC_WRITE)))
  2277. {
  2278. g_util.PostErrorMessage();
  2279. CloseServiceHandle(hSCManager);
  2280. return FALSE;
  2281. }
  2282. // Close the service manager's database
  2283. CloseServiceHandle(hSCManager);
  2284. if (QueryServiceConfig(hService, &qsc, sizeof(qsc), &dwBytesNeeded))
  2285. lpszTmpDisplay = qsc.lpDisplayName;
  2286. // Change service identity parameters
  2287. if (ChangeServiceConfig(hService,
  2288. SERVICE_NO_CHANGE, // SERVICE_WIN32_OWN_PROCESS,
  2289. SERVICE_NO_CHANGE, // SERVICE_DEMAND_START,
  2290. SERVICE_NO_CHANGE,
  2291. NULL,
  2292. NULL,
  2293. NULL,
  2294. NULL,
  2295. szIdentity,
  2296. szPassword,
  2297. NULL))
  2298. {
  2299. // Return success
  2300. CloseServiceHandle(hService);
  2301. return TRUE;
  2302. }
  2303. else
  2304. {
  2305. g_util.PostErrorMessage();
  2306. CloseServiceHandle(hService);
  2307. return FALSE;
  2308. }
  2309. }
  2310. else
  2311. {
  2312. g_util.PostErrorMessage();
  2313. return FALSE;
  2314. }
  2315. }
  2316. // defined in ole32
  2317. extern "C" void UpdateDCOMSettings();
  2318. BOOL CUtility::UpdateDCOMInfo(void)
  2319. {
  2320. UpdateDCOMSettings();
  2321. return TRUE;
  2322. }
  2323. LRESULT CALLBACK ControlFixProc( HWND hwnd, UINT uMsg, WPARAM wParam,
  2324. LPARAM lParam);
  2325. // This is a work-around because there is a bug in msdev 4.1: Cannot get
  2326. // WM_HELP message processed by a control on which DDX_Control data exchange
  2327. // is done because of subclassing problem. See msdn Q145865 for a discussion
  2328. // plus work-around code.
  2329. void CUtility::FixHelp(CWnd* pWnd)
  2330. {
  2331. // search all child windows. If their window proc
  2332. // is AfxWndProc, then subclass with our window proc
  2333. CWnd* pWndChild = pWnd->GetWindow(GW_CHILD);
  2334. while(pWndChild != NULL)
  2335. {
  2336. if (GetWindowLongPtr(pWndChild->GetSafeHwnd(),
  2337. GWLP_WNDPROC) == (LONG_PTR)AfxWndProc)
  2338. {
  2339. SetWindowLongPtr(pWndChild->GetSafeHwnd(), GWLP_WNDPROC,
  2340. (LONG_PTR)ControlFixProc);
  2341. }
  2342. pWndChild = pWndChild->GetWindow(GW_HWNDNEXT);
  2343. }
  2344. }
  2345. LRESULT CALLBACK ControlFixProc(HWND hwnd, UINT uMsg, WPARAM wParam,
  2346. LPARAM lParam)
  2347. {
  2348. if (uMsg == WM_HELP)
  2349. {
  2350. // bypass MFC's handler, message will be sent to parent
  2351. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  2352. }
  2353. return AfxWndProc(hwnd,uMsg,wParam,lParam);
  2354. }
  2355. // Compare two security descriptors in self-relative form to
  2356. // determine if they're the same
  2357. BOOL CUtility::CompareSDs(PSrSecurityDescriptor pSD1,
  2358. PSrSecurityDescriptor pSD2)
  2359. {
  2360. PSID pSid1, pSid2;
  2361. PSrAcl pDacl1, pDacl2;
  2362. PSrAce pAce1, pAce2;
  2363. BYTE *p1, *p2;
  2364. // Compare the owners
  2365. pSid1 = (PSID) (((BYTE *) pSD1) + pSD1->Owner);
  2366. pSid2 = (PSID) (((BYTE *) pSD2) + pSD2->Owner);
  2367. if (!EqualSid(pSid1, pSid2))
  2368. {
  2369. return FALSE;
  2370. }
  2371. // Compare the groups
  2372. pSid1 = (PSID) (((BYTE *) pSD1) + pSD1->Group);
  2373. pSid2 = (PSID) (((BYTE *) pSD2) + pSD2->Group);
  2374. if (!EqualSid(pSid1, pSid2))
  2375. {
  2376. return FALSE;
  2377. }
  2378. // Compare the DACL's
  2379. pDacl1 = (PSrAcl) (((BYTE *) pSD1) + pSD1->Dacl);
  2380. pDacl2 = (PSrAcl) (((BYTE *) pSD2) + pSD2->Dacl);
  2381. // Check first that they are the same size and have the same
  2382. // number of ACE's
  2383. if (! (pDacl1->AclSize == pDacl2->AclSize &&
  2384. pDacl1->AceCount == pDacl2->AceCount))
  2385. {
  2386. return FALSE;
  2387. }
  2388. // Now compare the ACL ACE by ACE
  2389. pAce1 = (PSrAce) (((BYTE *) pDacl1) + sizeof(SSrAcl));
  2390. pAce2 = (PSrAce) (((BYTE *) pDacl2) + sizeof(SSrAcl));
  2391. for (int k = 0; k < pDacl1->AceCount; k++)
  2392. {
  2393. // Check the ACE headers
  2394. if (! (pAce1->Type == pAce2->Type &&
  2395. pAce1->AceSize == pAce2->AceSize &&
  2396. pAce1->AccessMask == pAce2->AccessMask))
  2397. {
  2398. return FALSE;
  2399. }
  2400. // Check the SID's
  2401. p1 = (BYTE *) (((BYTE *) pAce1) + sizeof(ACE_HEADER));
  2402. p2 = (BYTE *) (((BYTE *) pAce2) + sizeof(ACE_HEADER));
  2403. for (ULONG j = 0; j < pAce1->AceSize - sizeof(ACE_HEADER); j++)
  2404. {
  2405. if (p1[j] != p2[j])
  2406. {
  2407. return FALSE;
  2408. }
  2409. }
  2410. // Go to the next ACE
  2411. pAce1 = (PSrAce) (((BYTE *) pAce1) + pAce1->AceSize);
  2412. pAce2 = (PSrAce) (((BYTE *) pAce2) + pAce2->AceSize);
  2413. }
  2414. return TRUE;
  2415. }
  2416. int CUtility::SetAccountRights(LPCTSTR szUser, TCHAR *szPrivilege)
  2417. {
  2418. #if !defined(STANDALONE_BUILD)
  2419. int err;
  2420. LSA_HANDLE hPolicy;
  2421. LSA_OBJECT_ATTRIBUTES objAtt;
  2422. DWORD cbSid = 1;
  2423. TCHAR szDomain[MAX_PATH];
  2424. DWORD cbDomain = MAX_PATH * sizeof(TCHAR);
  2425. PSID pSid = NULL;
  2426. SID_NAME_USE snu;
  2427. LSA_UNICODE_STRING privStr;
  2428. // Fetch the SID for the specified user
  2429. if ((err = GetPrincipalSID(szUser, &pSid)) != ERROR_SUCCESS)
  2430. return err;
  2431. memset(&objAtt, 0, sizeof(LSA_OBJECT_ATTRIBUTES));
  2432. if (IsBackupDC()) {
  2433. TCHAR* pszPDC;
  2434. LSA_UNICODE_STRING lsaPDC;
  2435. pszPDC = PrimaryDCName();
  2436. lsaPDC.Length = _tcslen (pszPDC) * sizeof (TCHAR)-2;
  2437. lsaPDC.MaximumLength = lsaPDC.Length + sizeof (TCHAR);
  2438. lsaPDC.Buffer = &pszPDC[2];
  2439. err = LsaOpenPolicy(&lsaPDC, &objAtt, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION, &hPolicy);
  2440. }
  2441. else
  2442. err = LsaOpenPolicy(NULL, &objAtt, POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION, &hPolicy);
  2443. if (err != ERROR_SUCCESS) {
  2444. return GetLastError();
  2445. }
  2446. // Set the specified privilege on this account
  2447. privStr.Length = _tcslen(szPrivilege) * sizeof(TCHAR);
  2448. privStr.MaximumLength = privStr.Length + sizeof(TCHAR);
  2449. privStr.Buffer = szPrivilege;
  2450. err = LsaAddAccountRights(hPolicy, pSid, &privStr, 1);
  2451. // We're done
  2452. delete pSid;
  2453. LsaClose(hPolicy);
  2454. if (err != ERROR_SUCCESS) {
  2455. return GetLastError();
  2456. }
  2457. #endif
  2458. return ERROR_SUCCESS;
  2459. }
  2460. // NOTE: Cannot handle IAccessControl style SDs
  2461. void CUtility::CopyAbsoluteSD( SECURITY_DESCRIPTOR *pSDSrc, SECURITY_DESCRIPTOR **pSDDest)
  2462. {
  2463. (*pSDDest)->Revision = pSDSrc->Revision;
  2464. (*pSDDest)->Sbz1 = pSDSrc->Sbz1;
  2465. (*pSDDest)->Control = pSDSrc->Control;
  2466. (*pSDDest)->Group = (*pSDDest)->Owner = (*pSDDest)->Dacl = (*pSDDest)->Sacl = NULL;
  2467. BYTE* pOffSet=(BYTE*)(*pSDDest)+sizeof(SECURITY_DESCRIPTOR);
  2468. if (pSDSrc->Dacl != NULL)
  2469. {
  2470. memcpy(pOffSet,pSDSrc->Dacl,pSDSrc->Dacl->AclSize);
  2471. (*pSDDest)->Dacl = (PACL)pOffSet;
  2472. pOffSet += pSDSrc->Dacl->AclSize;
  2473. }
  2474. if (pSDSrc->Owner != NULL)
  2475. {
  2476. memcpy(pOffSet,pSDSrc->Owner,GetLengthSid(pSDSrc->Owner));
  2477. (*pSDDest)->Owner = (PSID)pOffSet;
  2478. pOffSet += GetLengthSid(pSDSrc->Owner);
  2479. }
  2480. if (pSDSrc->Group != NULL)
  2481. {
  2482. memcpy(pOffSet,pSDSrc->Group,GetLengthSid(pSDSrc->Group));
  2483. (*pSDDest)->Group = (PSID)pOffSet;
  2484. }
  2485. }
  2486. // This method is included only because in the debug version when using
  2487. // MFC they validate the C++ heap, whereas RtlCopySecurityDescriptor uses
  2488. // the standard process heap, causing MFC to throw a breakpoint
  2489. // The return value indicates the success or failure of the operation
  2490. // NTBUG 310004. This function is called to copy both self-relative and absolute
  2491. // SDs. In its previous incarnation, it corrupted heap when called to
  2492. // copy an absolute SD. Now I do the right thing.
  2493. // NOTE: This function can not handle IAccessControl style SDs despite
  2494. // appearances to the contrary. This is OK, because dcomcnfg.exe does
  2495. // not handle such SDs at all.
  2496. BOOL CUtility::CopySD(SECURITY_DESCRIPTOR *pSrc, SECURITY_DESCRIPTOR **pDest)
  2497. {
  2498. #if !defined(STANDALONE_BUILD)
  2499. ULONG cbLen;
  2500. *pDest = NULL;
  2501. if (IsValidSecurityDescriptor(pSrc))
  2502. {
  2503. if (SDisIAC(pSrc))
  2504. {
  2505. cbLen = (ULONG) GlobalSize(pSrc);
  2506. }
  2507. else
  2508. {
  2509. cbLen = RtlLengthSecurityDescriptor(pSrc);
  2510. }
  2511. *pDest = (SECURITY_DESCRIPTOR *) GlobalAlloc(GMEM_FIXED, cbLen);
  2512. if (*pDest)
  2513. {
  2514. // if the SD is already self-relative, just copy
  2515. if ((pSrc)->Control & SE_SELF_RELATIVE )
  2516. {
  2517. memcpy(*pDest, pSrc, cbLen);
  2518. return TRUE;
  2519. }
  2520. else
  2521. {
  2522. // workaround an ACLEDIT bug (NT 352977). When the DACL has no ACES,
  2523. // ACLEDIT returns incorrect AclSize, causing an AV
  2524. // when I copy it. So fix it here.
  2525. if ((pSrc)->Dacl != NULL && ((pSrc)->Dacl->AceCount == 0))
  2526. (pSrc)->Dacl->AclSize=sizeof(ACL);
  2527. CopyAbsoluteSD(pSrc,pDest);
  2528. return TRUE;
  2529. }
  2530. GlobalFree(*pDest);
  2531. }
  2532. }
  2533. #endif
  2534. return FALSE;
  2535. }
  2536. // Set the inheritance flags on a security descriptor so keys created
  2537. // under the key having this security descriptor will inherit all its
  2538. // ACE's. We do this as a utility routine rather than via the ACL
  2539. // editor because doing that adds check boxes and such to the ACL editor,
  2540. // so it's cleaner this way.
  2541. //
  2542. // Note. The security descriptor is expected to be in absolute form
  2543. void CUtility::SetInheritanceFlags(SECURITY_DESCRIPTOR *pSec)
  2544. {
  2545. PSrAcl pAcl = (PSrAcl) pSec->Dacl;
  2546. PSrAce pAce;
  2547. int k;
  2548. // Do over the ACE's this DACL
  2549. for (k = pAcl->AceCount, pAce = (PSrAce) (((BYTE *) pAcl) + sizeof(SSrAcl));
  2550. k;
  2551. k--, pAce = (PSrAce) (((BYTE *) pAce) + pAce->AceSize))
  2552. {
  2553. pAce->Flags |= CONTAINER_INHERIT_ACE;
  2554. }
  2555. }
  2556. HRESULT CUtility::GetPrincipalSID (LPCTSTR Principal, PSID *Sid)
  2557. {
  2558. DWORD sidSize = 0;
  2559. TCHAR refDomain [256];
  2560. DWORD refDomainSize = 0;
  2561. DWORD returnValue;
  2562. SID_NAME_USE snu;
  2563. BOOL bSuccess;
  2564. bSuccess = LookupAccountName (NULL,
  2565. Principal,
  2566. *Sid,
  2567. &sidSize,
  2568. refDomain,
  2569. &refDomainSize,
  2570. &snu);
  2571. // codework - we need to check if this is correct
  2572. // what about multisuer machines - ie hydra
  2573. if ((returnValue = GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
  2574. return returnValue;
  2575. if ((*Sid = new BYTE[sidSize]) == NULL)
  2576. return ERROR_OUTOFMEMORY;
  2577. if (!LookupAccountName (NULL,
  2578. Principal,
  2579. *Sid,
  2580. &sidSize,
  2581. refDomain,
  2582. &refDomainSize,
  2583. &snu))
  2584. {
  2585. delete *Sid;
  2586. *Sid = NULL;
  2587. return GetLastError();
  2588. }
  2589. return ERROR_SUCCESS;
  2590. }
  2591. // this method, on first execution, checks if the current machine is a backup domain controller and if so,
  2592. // caches the value and returns TRUE. Subsequent executions will use cached value.
  2593. BOOL CUtility::IsBackupDC()
  2594. {
  2595. #if !defined(STANDALONE_BUILD)
  2596. USER_MODALS_INFO_2 *umi2 = NULL;
  2597. SERVER_INFO_101 *si101 = NULL;
  2598. DWORD dw;
  2599. if (!m_bCheckedDC) {
  2600. if ((dw = NetServerGetInfo (NULL, 101, (LPBYTE *) &si101)) == 0)
  2601. {
  2602. if (si101->sv101_type & SV_TYPE_DOMAIN_BAKCTRL)
  2603. {
  2604. if ((dw = NetUserModalsGet (NULL, 2, (LPBYTE *) &umi2)) == 0)
  2605. {
  2606. if(umi2)
  2607. {
  2608. NetGetDCName (NULL, umi2->usrmod2_domain_name, (LPBYTE *) &m_pszDomainController);
  2609. NetApiBufferFree (umi2);
  2610. }
  2611. m_bIsBdc = TRUE;
  2612. }
  2613. }
  2614. }
  2615. m_bCheckedDC = TRUE;
  2616. if (si101)
  2617. NetApiBufferFree (si101);
  2618. }
  2619. return m_bIsBdc;
  2620. #else
  2621. return FALSE;
  2622. #endif
  2623. }
  2624. TCHAR* CUtility::PrimaryDCName()
  2625. {
  2626. static TCHAR s_tszUnknownDomainName[] = _T("UnknownDCName");
  2627. #if !defined(STANDALONE_BUILD)
  2628. if (IsBackupDC())
  2629. {
  2630. if(m_pszDomainController){
  2631. return m_pszDomainController;
  2632. }
  2633. else
  2634. {
  2635. return s_tszUnknownDomainName;
  2636. }
  2637. }
  2638. #endif
  2639. return NULL;
  2640. }