Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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