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.

2198 lines
64 KiB

  1. //+---------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1993 - 1994.
  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::CheckSDForCOM_RIGHTS_EXECUTE
  37. // CUtility::ChangeService
  38. // CUtility::UpdateDCOMInfo(void)
  39. // CUtility::FixHelp
  40. // CUtility::CopySD
  41. // CUtility::SetInheritanceFlags
  42. //
  43. // Functons: callBackFunc
  44. // ControlFixProc
  45. //
  46. // History: 23-Apr-96 BruceMa Created.
  47. //
  48. //----------------------------------------------------------------------
  49. #include "stdafx.h"
  50. #include "assert.h"
  51. #include "resource.h"
  52. #include "afxtempl.h"
  53. #include "types.h"
  54. #include "datapkt.h"
  55. #include "clspsht.h"
  56. extern "C"
  57. {
  58. #include <getuser.h>
  59. }
  60. #include "util.h"
  61. #include "virtreg.h"
  62. extern "C"
  63. {
  64. #include <ntlsa.h>
  65. #include <ntseapi.h>
  66. #include <sedapi.h>
  67. #include <winnetwk.h>
  68. #include <uiexport.h>
  69. #include <rpc.h>
  70. #include <rpcdce.h>
  71. }
  72. extern "C"
  73. {
  74. int _stdcall UpdateActivationSettings(HANDLE hRpc, RPC_STATUS *status);
  75. }
  76. static const BYTE GuidMap[] = { 3, 2, 1, 0, '-', 5, 4, '-', 7, 6, '-',
  77. 8, 9, '-', 10, 11, 12, 13, 14, 15 };
  78. static const TCHAR szDigits[] = TEXT("0123456789ABCDEF");
  79. static const DWORD SIZEOF_SID = 44;
  80. // This leaves space for 2 access allowed ACEs in the ACL.
  81. const DWORD SIZEOF_ACL = sizeof(ACL) + 2 * sizeof(ACCESS_ALLOWED_ACE) +
  82. 2 * SIZEOF_SID;
  83. static const DWORD SIZEOF_TOKEN_USER = sizeof(TOKEN_USER) + SIZEOF_SID;
  84. static const SID LOCAL_SYSTEM_SID = {SID_REVISION, 1, {0,0,0,0,0,5},
  85. SECURITY_LOCAL_SYSTEM_RID };
  86. static const DWORD NUM_SEC_PKG = 8;
  87. // These are required for the method CUtility::UpdateDCOMInfo which invokes
  88. // an RPC proxy which expects the following
  89. extern "C" void * _stdcall MIDL_user_allocate(size_t size)
  90. {
  91. return new BYTE[size];
  92. }
  93. extern "C" void _stdcall MIDL_user_free(void *p)
  94. {
  95. delete p;
  96. }
  97. CUtility::CUtility(void)
  98. {
  99. m_hRpc = NULL;
  100. }
  101. CUtility::~CUtility(void)
  102. {
  103. if (m_hRpc != NULL)
  104. {
  105. RpcBindingFree(&m_hRpc);
  106. }
  107. }
  108. void CUtility::CkForAccessDenied(int err)
  109. {
  110. if (err == ERROR_ACCESS_DENIED)
  111. {
  112. CString sMsg;
  113. CString sCaption;
  114. sMsg.LoadString(IDS_ACCESSDENIED);
  115. sCaption.LoadString(IDS_SYSTEMMESSAGE);
  116. MessageBox(NULL, sMsg, sCaption, MB_OK);
  117. }
  118. }
  119. BOOL CUtility::CkAccessRights(HKEY hRoot, TCHAR *szKeyPath)
  120. {
  121. int err;
  122. HKEY hKey;
  123. BYTE aSid[256];
  124. DWORD cbSid = 256;
  125. PSECURITY_DESCRIPTOR pSid = (PSECURITY_DESCRIPTOR) aSid;
  126. BOOL fFreePsid = FALSE;
  127. // Open the specified key
  128. err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey);
  129. // The key may not exist
  130. if (err == ERROR_FILE_NOT_FOUND)
  131. {
  132. return TRUE;
  133. }
  134. if (err == ERROR_SUCCESS)
  135. {
  136. // Fetch the security descriptor on this key
  137. err = RegGetKeySecurity(hKey,
  138. OWNER_SECURITY_INFORMATION |
  139. GROUP_SECURITY_INFORMATION |
  140. DACL_SECURITY_INFORMATION,
  141. (PSECURITY_DESCRIPTOR) aSid,
  142. &cbSid);
  143. if (err == ERROR_INSUFFICIENT_BUFFER)
  144. {
  145. pSid = (PSECURITY_DESCRIPTOR) malloc(cbSid);
  146. if (pSid == NULL)
  147. {
  148. return FALSE;
  149. }
  150. fFreePsid = TRUE;
  151. err = RegGetKeySecurity(hKey,
  152. OWNER_SECURITY_INFORMATION |
  153. GROUP_SECURITY_INFORMATION |
  154. DACL_SECURITY_INFORMATION,
  155. (PSECURITY_DESCRIPTOR) pSid,
  156. &cbSid);
  157. }
  158. // We've read the security descriptor - now try to write it
  159. if (err == ERROR_SUCCESS)
  160. {
  161. err = RegSetKeySecurity(hKey,
  162. OWNER_SECURITY_INFORMATION |
  163. GROUP_SECURITY_INFORMATION |
  164. DACL_SECURITY_INFORMATION,
  165. pSid);
  166. }
  167. if (hKey != hRoot)
  168. {
  169. RegCloseKey(hKey);
  170. }
  171. }
  172. return err == ERROR_SUCCESS ? TRUE : FALSE;
  173. }
  174. void CUtility::PostErrorMessage(void)
  175. {
  176. TCHAR szMessage[256];
  177. FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
  178. 0, szMessage, sizeof( szMessage ), NULL);
  179. CString sCaption;
  180. sCaption.LoadString(IDS_SYSTEMMESSAGE);
  181. MessageBox(NULL, szMessage, sCaption, MB_OK);
  182. }
  183. void CUtility::PostErrorMessage(int err)
  184. {
  185. TCHAR szMessage[256];
  186. FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
  187. 0, szMessage, sizeof( szMessage ), NULL);
  188. CString sCaption;
  189. sCaption.LoadString(IDS_SYSTEMMESSAGE);
  190. MessageBox(NULL, szMessage, sCaption, MB_OK);
  191. }
  192. // Write a named string value to the registry
  193. int CUtility::WriteRegSzNamedValue(HKEY hRoot,
  194. TCHAR *szKeyPath,
  195. TCHAR *szValueName,
  196. TCHAR *szVal,
  197. DWORD dwSize)
  198. {
  199. int err;
  200. HKEY hKey;
  201. ULONG lSize;
  202. // Open the key
  203. if ((err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey)) != ERROR_SUCCESS)
  204. {
  205. return err;
  206. }
  207. // Attempt to write the named value
  208. lSize = _tcslen(szVal) + 1;
  209. if ((err = RegSetValueEx(hKey, szValueName, NULL, REG_SZ, (BYTE *) szVal,
  210. lSize*sizeof(TCHAR) ))
  211. != ERROR_SUCCESS)
  212. {
  213. if (hKey != hRoot)
  214. {
  215. RegCloseKey(hKey);
  216. }
  217. return err;
  218. }
  219. // Successful
  220. if (hKey != hRoot)
  221. {
  222. RegCloseKey(hKey);
  223. }
  224. return ERROR_SUCCESS;
  225. }
  226. // Write a named DWORD value to the registry
  227. int CUtility::WriteRegDwordNamedValue(HKEY hRoot,
  228. TCHAR *szKeyPath,
  229. TCHAR *szValueName,
  230. DWORD dwVal)
  231. {
  232. int err;
  233. HKEY hKey;
  234. // Open the key
  235. if ((err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey))
  236. != ERROR_SUCCESS)
  237. {
  238. return err;
  239. }
  240. // Attempt to write the named value
  241. if (RegSetValueEx(hKey, szValueName, NULL, REG_DWORD, (BYTE *) &dwVal,
  242. sizeof(DWORD))
  243. != ERROR_SUCCESS)
  244. {
  245. if (hKey != hRoot)
  246. {
  247. RegCloseKey(hKey);
  248. }
  249. return GetLastError();
  250. }
  251. // Return the value
  252. if (hKey != hRoot)
  253. {
  254. RegCloseKey(hKey);
  255. }
  256. return ERROR_SUCCESS;
  257. }
  258. // Write an ACL as a registry named value
  259. int CUtility::WriteRegSingleACL(HKEY hRoot,
  260. TCHAR *szKeyPath,
  261. TCHAR *szValueName,
  262. PSECURITY_DESCRIPTOR pSec)
  263. {
  264. int err;
  265. HKEY hKey = hRoot;
  266. PSrSecurityDescriptor pSrSec;
  267. PSrAcl pDacl;
  268. // Open the key unless the key path is NULL
  269. if (szKeyPath)
  270. {
  271. if ((err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey))
  272. != ERROR_SUCCESS)
  273. {
  274. return err;
  275. }
  276. }
  277. // If there are no ACE's and this is DefaultAccessPermission, then
  278. // interpret this as activator access only which we indicate by
  279. // removing the named value
  280. pSrSec = (PSrSecurityDescriptor) pSec;
  281. pDacl = (PSrAcl) (((BYTE *) pSec) + (pSrSec->Dacl));
  282. if (_tcscmp(szValueName, TEXT("DefaultAccessPermission")) == 0 &&
  283. pDacl->AceCount == 0)
  284. {
  285. RegDeleteValue(hKey, szValueName);
  286. }
  287. // Else write the ACL simply as a REG_SZ value
  288. else
  289. {
  290. err = RegSetValueEx(hKey,
  291. szValueName,
  292. 0,
  293. REG_BINARY,
  294. (BYTE *) pSec,
  295. #if 0
  296. RtlLengthSecurityDescriptor(pSec));
  297. #else
  298. 10);
  299. #endif
  300. }
  301. if (hKey != hRoot)
  302. {
  303. RegCloseKey(hKey);
  304. }
  305. return err;
  306. }
  307. // Write an ACL on a registry key
  308. int CUtility::WriteRegKeyACL(HKEY hKey,
  309. HKEY *phClsids,
  310. unsigned cClsids,
  311. PSECURITY_DESCRIPTOR pSec,
  312. PSECURITY_DESCRIPTOR pSecOrig)
  313. {
  314. int err;
  315. // The logic is somewhat different depending on whether we're starting
  316. // with HKEY_CLASSES_ROOT or a specific AppID
  317. if (hKey == HKEY_CLASSES_ROOT)
  318. {
  319. return WriteRegKeyACL2(hKey, hKey, pSec, pSecOrig);
  320. }
  321. // It's a specific AppID
  322. else
  323. {
  324. // Write the security on the AppID key
  325. if (err = RegSetKeySecurity(hKey,
  326. OWNER_SECURITY_INFORMATION |
  327. GROUP_SECURITY_INFORMATION |
  328. DACL_SECURITY_INFORMATION,
  329. pSec) != ERROR_SUCCESS)
  330. {
  331. return err;
  332. }
  333. // Iterate over the CLSID's covered by this AppID and recursively
  334. // write security on them and their subkeys
  335. for (UINT k = 0; k < cClsids; k++)
  336. {
  337. if (err = WriteRegKeyACL2(phClsids[k], phClsids[k], pSec, pSecOrig)
  338. != ERROR_SUCCESS)
  339. {
  340. return err;
  341. }
  342. }
  343. }
  344. return ERROR_SUCCESS;
  345. }
  346. // Write an ACL recursively on a registry key provided the current
  347. // security descriptor on the key is the same as the passed in
  348. // original security descriptor
  349. int CUtility::WriteRegKeyACL2(HKEY hRoot,
  350. HKEY hKey,
  351. PSECURITY_DESCRIPTOR pSec,
  352. PSECURITY_DESCRIPTOR pSecOrig)
  353. {
  354. BYTE aCurrSD[256];
  355. DWORD cbCurrSD = 256;
  356. PSECURITY_DESCRIPTOR pCurrSD = (PSECURITY_DESCRIPTOR) aCurrSD;
  357. BOOL fFreePCurrSD = FALSE;
  358. int err;
  359. BOOL fProceed;
  360. // Read the current security descriptor on this key
  361. err = RegGetKeySecurity(hKey,
  362. OWNER_SECURITY_INFORMATION |
  363. GROUP_SECURITY_INFORMATION |
  364. DACL_SECURITY_INFORMATION,
  365. aCurrSD,
  366. &cbCurrSD);
  367. if (err == ERROR_MORE_DATA || err == ERROR_INSUFFICIENT_BUFFER)
  368. {
  369. pCurrSD = (SECURITY_DESCRIPTOR *) new BYTE[cbCurrSD];
  370. if (pCurrSD == NULL)
  371. {
  372. return ERROR_NOT_ENOUGH_MEMORY;
  373. }
  374. fFreePCurrSD = TRUE;
  375. }
  376. else if (err != ERROR_SUCCESS)
  377. {
  378. return err;
  379. }
  380. if ((err = RegGetKeySecurity(hKey,
  381. OWNER_SECURITY_INFORMATION |
  382. GROUP_SECURITY_INFORMATION |
  383. DACL_SECURITY_INFORMATION,
  384. pCurrSD,
  385. &cbCurrSD)
  386. != ERROR_SUCCESS))
  387. {
  388. if (fFreePCurrSD)
  389. {
  390. delete pCurrSD;
  391. }
  392. return err;
  393. }
  394. // Only proceed down this subtree if the current SD and the
  395. // original SD are the same
  396. fProceed = CompareSDs((PSrSecurityDescriptor) pCurrSD,
  397. (PSrSecurityDescriptor) pSecOrig);
  398. // We're done with the current security descriptor
  399. if (fFreePCurrSD)
  400. {
  401. delete pCurrSD;
  402. }
  403. if (!fProceed)
  404. {
  405. if (hKey != hRoot)
  406. {
  407. RegCloseKey(hKey);
  408. }
  409. return ERROR_SUCCESS;
  410. }
  411. // Write the top level ACL
  412. err = RegSetKeySecurity(hKey,
  413. OWNER_SECURITY_INFORMATION |
  414. GROUP_SECURITY_INFORMATION |
  415. DACL_SECURITY_INFORMATION,
  416. pSec);
  417. // Now enumerate the subkeys and write ACL's on them
  418. DWORD iSubKey;
  419. TCHAR szSubKeyName[128];
  420. HKEY hKey2;
  421. iSubKey = 0;
  422. while (err == ERROR_SUCCESS)
  423. {
  424. // Enumerate the next key
  425. err = RegEnumKey(hKey, iSubKey, szSubKeyName, 128);
  426. if (err != ERROR_SUCCESS)
  427. {
  428. break;
  429. }
  430. // Prepare for the next key
  431. iSubKey++;
  432. // Open this subkey and recursively write the ACL on it and
  433. // all of its subkeys
  434. if (RegOpenKeyEx(hKey, szSubKeyName, 0, KEY_ALL_ACCESS, &hKey2)
  435. == ERROR_SUCCESS)
  436. {
  437. err = WriteRegKeyACL2(hRoot, hKey2, pSec, pSecOrig);
  438. }
  439. }
  440. if (hKey != hRoot)
  441. {
  442. RegCloseKey(hKey);
  443. }
  444. return err == ERROR_NO_MORE_ITEMS ? ERROR_SUCCESS : err;
  445. }
  446. // Write a user's password to the private LSA database
  447. int CUtility::WriteLsaPassword(CLSID appid, TCHAR *szPassword)
  448. {
  449. return ERROR_SUCCESS;
  450. }
  451. int CUtility::DeleteRegKey(HKEY hRoot, TCHAR *szKeyPath)
  452. {
  453. return RegDeleteKey(hRoot, szKeyPath);
  454. }
  455. int CUtility::DeleteRegValue(HKEY hRoot, TCHAR *szKeyPath, TCHAR *szValueName)
  456. {
  457. int err;
  458. HKEY hKey;
  459. if ((err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey)) == ERROR_SUCCESS)
  460. {
  461. err = RegDeleteValue(hKey, szValueName);
  462. if (hRoot != hKey)
  463. RegCloseKey(hKey);
  464. }
  465. return err;
  466. }
  467. // Change the identity under which a service runs
  468. int CUtility::WriteSrvIdentity(TCHAR *szService, TCHAR *szIdentity)
  469. {
  470. return ERROR_SUCCESS;
  471. }
  472. DWORD __stdcall callBackFunc(HWND hwndParent,
  473. HANDLE hInstance,
  474. ULONG CallBackContext,
  475. PSECURITY_DESCRIPTOR SecDesc,
  476. PSECURITY_DESCRIPTOR SecDescNewObjects,
  477. BOOLEAN ApplyToSubContainers,
  478. BOOLEAN ApplyToSubObjects,
  479. LPDWORD StatusReturn)
  480. {
  481. int err = ERROR_SUCCESS;
  482. PCallBackContext pCallBackContext = (PCallBackContext) CallBackContext;
  483. // Set the inheritance flags on the new security descriptor
  484. if (pCallBackContext->pktType == RegKeyACL)
  485. {
  486. g_util.SetInheritanceFlags((SECURITY_DESCRIPTOR *) SecDesc);
  487. }
  488. // Write the new or modified security descriptor
  489. if (*pCallBackContext->pIndex == -1)
  490. {
  491. if (pCallBackContext->pktType == SingleACL)
  492. {
  493. err = g_virtreg.NewRegSingleACL(
  494. pCallBackContext->info.single.hRoot,
  495. pCallBackContext->info.single.szKeyPath,
  496. pCallBackContext->info.single.szValueName,
  497. (SECURITY_DESCRIPTOR *) SecDesc,
  498. FALSE,
  499. pCallBackContext->pIndex);
  500. }
  501. else
  502. {
  503. err = g_virtreg.NewRegKeyACL(
  504. pCallBackContext->info.regKey.hKey,
  505. pCallBackContext->info.regKey.phClsids,
  506. pCallBackContext->info.regKey.cClsids,
  507. pCallBackContext->info.regKey.szTitle,
  508. pCallBackContext->origSD,
  509. (SECURITY_DESCRIPTOR *) SecDesc,
  510. FALSE,
  511. pCallBackContext->pIndex);
  512. }
  513. }
  514. else
  515. {
  516. g_virtreg.ChgRegACL(*pCallBackContext->pIndex,
  517. (SECURITY_DESCRIPTOR *) SecDesc,
  518. FALSE);
  519. }
  520. *StatusReturn = err;
  521. return err;
  522. }
  523. // Invoke the ACL editor on the specified named value. This method
  524. // writes an ACL data packet to the virtual registry. This method is for
  525. // Access and Launch security only (pktType SingleACL).
  526. int CUtility::ACLEditor(HWND hWnd,
  527. HKEY hRoot,
  528. TCHAR *szKeyPath,
  529. TCHAR *szValueName,
  530. int *pIndex,
  531. PACKETTYPE pktType,
  532. TCHAR *szPermType)
  533. {
  534. int err;
  535. HKEY hKey;
  536. BYTE aSD[128];
  537. DWORD cbSD = 128;
  538. DWORD dwType;
  539. SECURITY_DESCRIPTOR *pSD = (SECURITY_DESCRIPTOR *) aSD;
  540. BOOL fFreePSD = FALSE;
  541. SID *pSid;
  542. TCHAR szAllow[32];
  543. TCHAR szDeny[32];
  544. CString szAllow_;
  545. CString szDeny_;
  546. szAllow_.LoadString(IDS_Allow_);
  547. szDeny_.LoadString(IDS_Deny_);
  548. // Build the allow and deny strings
  549. _tcscpy(szAllow, (LPCTSTR) szAllow_);
  550. _tcscat(szAllow, szPermType);
  551. _tcscpy(szDeny, (LPCTSTR) szDeny_);
  552. _tcscat(szDeny, szPermType);
  553. // Fetch the current SD, either from the registry, by default if the
  554. // named value doesn't exist or from the virtual registry
  555. if (*pIndex == -1)
  556. {
  557. // Open the specified key
  558. if ((err = RegOpenKeyEx(hRoot, szKeyPath, 0,
  559. KEY_ALL_ACCESS, &hKey))
  560. != ERROR_SUCCESS)
  561. {
  562. return err;
  563. }
  564. // Attempt to read the specified named value
  565. err = RegQueryValueEx(hKey, szValueName, 0, &dwType, (BYTE *) aSD,
  566. &cbSD);
  567. if (err == ERROR_MORE_DATA || err == ERROR_INSUFFICIENT_BUFFER)
  568. {
  569. pSD = (SECURITY_DESCRIPTOR *) new BYTE[cbSD];
  570. if (pSD == NULL)
  571. {
  572. return ERROR_NOT_ENOUGH_MEMORY;
  573. }
  574. fFreePSD = TRUE;
  575. err = RegQueryValueEx(hKey, szValueName, 0, &dwType,
  576. (BYTE *) pSD, &cbSD);
  577. }
  578. // The named valued doesn't exist. If this is
  579. // \\HKEY_CLASSES_ROOT\...
  580. // then use the default named value if it exists
  581. else if (err != ERROR_SUCCESS)
  582. {
  583. if (hRoot != HKEY_LOCAL_MACHINE)
  584. {
  585. if (err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  586. TEXT("SOFTWARE\\Microsoft\\OLE"),
  587. 0,
  588. KEY_ALL_ACCESS,
  589. &hKey)
  590. != ERROR_SUCCESS)
  591. {
  592. return err;
  593. }
  594. // Attempt to read the specified named value
  595. TCHAR szDefault[32];
  596. _tcscpy(szDefault, TEXT("Default"));
  597. _tcscat(szDefault, szValueName);
  598. err = RegQueryValueEx(hKey, szDefault, 0, &dwType,
  599. (BYTE *) aSD, &cbSD);
  600. if (err == ERROR_MORE_DATA)
  601. {
  602. pSD = (SECURITY_DESCRIPTOR *) new BYTE[cbSD];
  603. if (pSD == NULL)
  604. {
  605. return ERROR_NOT_ENOUGH_MEMORY;
  606. }
  607. fFreePSD = TRUE;
  608. err = RegQueryValueEx(hKey, szDefault, 0, &dwType,
  609. (BYTE *) pSD, &cbSD);
  610. }
  611. RegCloseKey(hKey);
  612. }
  613. }
  614. // If still don't have an SD, then simply create one
  615. if (err != ERROR_SUCCESS)
  616. {
  617. if (!g_util.LookupProcessInfo(&pSid, NULL))
  618. {
  619. return GetLastError();
  620. }
  621. if (!g_util.MakeSecDesc(pSid, &pSD))
  622. {
  623. delete pSid;
  624. return GetLastError();
  625. }
  626. fFreePSD = TRUE;
  627. }
  628. }
  629. // Fetch the most recently edited SD
  630. else
  631. {
  632. CDataPacket *pCdp = g_virtreg.GetAt(*pIndex);
  633. pSD = pCdp -> pkt.acl.pSec;
  634. }
  635. // Initialize the callback context
  636. m_sCallBackContext.pktType = pktType;
  637. m_sCallBackContext.pIndex = pIndex;
  638. m_sCallBackContext.origSD = pSD;
  639. m_sCallBackContext.info.single.hRoot = hRoot;
  640. m_sCallBackContext.info.single.szKeyPath = szKeyPath;
  641. m_sCallBackContext.info.single.szValueName = szValueName;
  642. // Invoke the ACL editor
  643. DWORD dwStatus = 0;
  644. GENERIC_MAPPING genericMapping;
  645. CString szObjectType;
  646. szObjectType.LoadString(IDS_Registry_value);
  647. SED_HELP_INFO helpInfo =
  648. {
  649. L"dcomcnfg.hlp",
  650. {HC_MAIN_DLG,
  651. HC_MAIN_DLG,
  652. HC_MAIN_DLG,
  653. HC_MAIN_DLG,
  654. HC_MAIN_DLG,
  655. HC_MAIN_DLG,
  656. HC_MAIN_DLG}
  657. };
  658. #ifndef UNICODE
  659. WCHAR * wszObjectType = new WCHAR[szObjectType.GetLength() + 1];
  660. mbstowcs(wszObjectType, szObjectType, szObjectType.GetLength() + 1);
  661. #endif
  662. SED_OBJECT_TYPE_DESCRIPTOR objTyp =
  663. {1, // Revision
  664. FALSE, // Is container?
  665. FALSE, // Allow new object perms?
  666. FALSE, // Specific to generic?
  667. &genericMapping, // Generic mapping
  668. NULL, // Generic mapping new
  669. #ifdef UNICODE
  670. (TCHAR *) ((LPCTSTR) szObjectType), // Object type name
  671. #else
  672. (WCHAR *) ((LPCWSTR) wszObjectType), // Object type name
  673. #endif
  674. &helpInfo, // Help info
  675. L"", // Ckbox title
  676. L"", // Apply title
  677. L"", //
  678. NULL, // Special object access
  679. NULL // New special object access
  680. };
  681. #ifndef UNICODE
  682. WCHAR wszAllow[32];
  683. mbstowcs(wszAllow, szAllow, 32);
  684. WCHAR wszDeny[32];
  685. mbstowcs(wszDeny, szDeny, 32);
  686. SED_APPLICATION_ACCESS appAccess[] =
  687. {{SED_DESC_TYPE_RESOURCE, COM_RIGHTS_EXECUTE, 0, wszAllow},
  688. {SED_DESC_TYPE_RESOURCE, 0, 0, wszDeny}};
  689. SED_APPLICATION_ACCESSES appAccesses =
  690. {2, // Count of access groups
  691. appAccess, // Access array
  692. wszAllow // Default access name
  693. };
  694. #else
  695. SED_APPLICATION_ACCESS appAccess[] =
  696. {{SED_DESC_TYPE_RESOURCE, COM_RIGHTS_EXECUTE, 0, szAllow},
  697. {SED_DESC_TYPE_RESOURCE, 0, 0, szDeny}};
  698. SED_APPLICATION_ACCESSES appAccesses =
  699. {2, // Count of access groups
  700. appAccess, // Access array
  701. szAllow // Default access name
  702. };
  703. #endif
  704. // Intialize the help contexts
  705. helpInfo.aulHelpContext[HC_MAIN_DLG] =
  706. IDH_REGISTRY_VALUE_PERMISSIONS;
  707. helpInfo.aulHelpContext[HC_SPECIAL_ACCESS_DLG] =
  708. IDH_SPECIAL_ACCESS_GLOBAL;
  709. helpInfo.aulHelpContext[HC_NEW_ITEM_SPECIAL_ACCESS_DLG] =
  710. IDH_SPECIAL_ACCESS_GLOBAL;
  711. helpInfo.aulHelpContext[HC_ADD_USER_DLG] =
  712. IDH_ADD_USERS_AND_GROUPS;
  713. helpInfo.aulHelpContext[HC_ADD_USER_MEMBERS_LG_DLG] =
  714. IDH_LOCAL_GROUP_MEMBERSHIP;
  715. helpInfo.aulHelpContext[HC_ADD_USER_MEMBERS_GG_DLG] =
  716. IDH_GLOBAL_GROUP_MEMBERSHIP;
  717. helpInfo.aulHelpContext[HC_ADD_USER_SEARCH_DLG] =
  718. IDH_FIND_ACCOUNT1;
  719. genericMapping.GenericRead = GENERIC_ALL;
  720. genericMapping.GenericWrite = GENERIC_ALL;
  721. genericMapping.GenericExecute = GENERIC_ALL;
  722. genericMapping.GenericAll = GENERIC_ALL;
  723. // If this is for Access or Launch permissons then check that the
  724. // SD contains only allows and deny's for COM_RIGHTS_EXECUTE
  725. if (!CheckSDForCOM_RIGHTS_EXECUTE(pSD))
  726. {
  727. return IDCANCEL;
  728. }
  729. // Invoke the ACL editor
  730. // SedDiscretionaryAclEditor(hWnd, // Owner hWnd
  731. // GetModuleHandle(NULL), // Owner hInstance
  732. // NULL, // Server
  733. // &objTyp, // ObjectTyp,
  734. // &appAccesses, // Application accesses
  735. // szValueName, // Object name,
  736. // callBackFunc, // Callback function
  737. // (ULONG) &m_sCallBackContext, // Callback context
  738. // pSD, // Security descriptor,
  739. // FALSE, // Couldnt read Dacl,
  740. // FALSE, // Can't write Dacl,
  741. // &dwStatus, // SED status return,
  742. // 0); // Flags
  743. // Check status return
  744. if (dwStatus != ERROR_SUCCESS)
  745. {
  746. // PostErrorMessage(dwStatus);
  747. }
  748. // We're done
  749. if (fFreePSD)
  750. {
  751. delete pSD;
  752. }
  753. return dwStatus == 0 ? ERROR_SUCCESS : IDCANCEL;
  754. }
  755. // Invoke the ACL editor on the specified key. This method writes an ACL
  756. // data packet to the virtual registry. This method supports configuration
  757. // security only (pktType RegKeyACL).
  758. int CUtility::ACLEditor2(HWND hWnd,
  759. HKEY hKey,
  760. HKEY *phClsids,
  761. unsigned cClsids,
  762. TCHAR *szTitle,
  763. int *pIndex,
  764. PACKETTYPE pktType)
  765. {
  766. int err;
  767. BYTE aSD[128];
  768. DWORD cbSD = 128;
  769. SECURITY_DESCRIPTOR *pSD = (SECURITY_DESCRIPTOR *) aSD;
  770. BOOL fFreePSD = FALSE;
  771. TCHAR szKeyRead[32];
  772. CString szKeyRead_;
  773. TCHAR szHkeyClassesRoot[32];
  774. CString szHkeyClassesRoot_;
  775. // Initialize strings
  776. szKeyRead_.LoadString(IDS_Key_Read);
  777. _tcscpy(szKeyRead, (LPCTSTR) szKeyRead_);
  778. szHkeyClassesRoot_.LoadString(IDS_HKEY_CLASSES_ROOT);
  779. _tcscpy(szHkeyClassesRoot, (LPCTSTR) szHkeyClassesRoot_);
  780. if (*pIndex == -1)
  781. {
  782. // Read the security descriptor on this key
  783. err = RegGetKeySecurity(hKey,
  784. OWNER_SECURITY_INFORMATION |
  785. GROUP_SECURITY_INFORMATION |
  786. DACL_SECURITY_INFORMATION,
  787. aSD,
  788. &cbSD);
  789. if (err == ERROR_MORE_DATA || err == ERROR_INSUFFICIENT_BUFFER)
  790. {
  791. pSD = (SECURITY_DESCRIPTOR *) new BYTE[cbSD];
  792. if (pSD == NULL)
  793. {
  794. return ERROR_NOT_ENOUGH_MEMORY;
  795. }
  796. fFreePSD = TRUE;
  797. }
  798. else if (err != ERROR_SUCCESS)
  799. {
  800. return err;
  801. }
  802. if ((err = RegGetKeySecurity(hKey,
  803. OWNER_SECURITY_INFORMATION |
  804. GROUP_SECURITY_INFORMATION |
  805. DACL_SECURITY_INFORMATION,
  806. pSD,
  807. &cbSD)
  808. != ERROR_SUCCESS))
  809. {
  810. if (fFreePSD)
  811. {
  812. delete pSD;
  813. }
  814. return err;
  815. }
  816. }
  817. // Fetch the most recently edited SD
  818. else
  819. {
  820. CDataPacket *pCdp = g_virtreg.GetAt(*pIndex);
  821. pSD = pCdp -> pkt.racl.pSec;
  822. }
  823. // Initialize the callback context
  824. m_sCallBackContext.pktType = pktType;
  825. m_sCallBackContext.pIndex = pIndex;
  826. m_sCallBackContext.origSD = pSD;
  827. m_sCallBackContext.info.regKey.hKey = hKey;
  828. m_sCallBackContext.info.regKey.phClsids = phClsids;
  829. m_sCallBackContext.info.regKey.cClsids = cClsids;
  830. m_sCallBackContext.info.regKey.szTitle = szTitle;
  831. // Invoke the ACL editor
  832. DWORD dwStatus = 0;
  833. GENERIC_MAPPING genericMapping;
  834. CString szObjectType;
  835. szObjectType.LoadString(IDS_Registry_Key);
  836. CString szQueryValue;
  837. szQueryValue.LoadString(IDS_Query_Value);
  838. CString szSetValue;
  839. szSetValue.LoadString(IDS_Set_Value);
  840. CString szCreateSubkeys;
  841. szCreateSubkeys.LoadString(IDS_Create_Subkey);
  842. CString szEnumerateSubkeys;
  843. szEnumerateSubkeys.LoadString(IDS_Enumerate_Subkeys);
  844. CString szNotify;
  845. szNotify.LoadString(IDS_Notify);
  846. CString szCreateLink;
  847. szCreateLink.LoadString(IDS_Create_Link);
  848. CString szDelete;
  849. szDelete.LoadString(IDS_Delete);
  850. CString szWriteDAC;
  851. szWriteDAC.LoadString(IDS_Write_DAC);
  852. CString szWriteOwner;
  853. szWriteOwner.LoadString(IDS_Write_Owner);
  854. CString szReadControl;
  855. szReadControl.LoadString(IDS_Read_Control);
  856. CString szRead;
  857. szRead.LoadString(IDS_Read);
  858. CString szFullControl;
  859. szFullControl.LoadString(IDS_Full_Control);
  860. CString szSpecialAccess;
  861. szSpecialAccess.LoadString(IDS_Special_AccessDotDotDot);
  862. SED_HELP_INFO helpInfo =
  863. {
  864. L"dcomcnfg.hlp",
  865. {HC_MAIN_DLG,
  866. HC_MAIN_DLG,
  867. HC_MAIN_DLG,
  868. HC_MAIN_DLG,
  869. HC_MAIN_DLG,
  870. HC_MAIN_DLG,
  871. HC_MAIN_DLG}
  872. };
  873. #ifndef UNICODE
  874. WCHAR * wszObjectType = new WCHAR[szObjectType.GetLength() + 1];
  875. mbstowcs(wszObjectType, szObjectType, szObjectType.GetLength() + 1);
  876. WCHAR * wszSpecialAccess = new WCHAR[szSpecialAccess.GetLength() + 1];
  877. mbstowcs(wszSpecialAccess, szSpecialAccess, szSpecialAccess.GetLength() + 1);
  878. #endif
  879. SED_OBJECT_TYPE_DESCRIPTOR objTyp =
  880. {SED_REVISION1, // Revision
  881. FALSE, // Is container?
  882. FALSE, // Allow new object perms?
  883. FALSE, // Specific to generic?
  884. &genericMapping, // Generic mapping
  885. NULL, // Generic mapping new
  886. #ifdef UNICODE
  887. (TCHAR *) ((LPCTSTR) szObjectType), // Object type name
  888. #else
  889. (WCHAR *) ((LPCWSTR) wszObjectType), // Object type name
  890. #endif
  891. &helpInfo, // Help info
  892. L"", // Ckbox title
  893. L"", // Apply title
  894. L"", //
  895. #ifdef UNICODE
  896. (TCHAR *) ((LPCTSTR) szSpecialAccess), // Special Access menu item
  897. #else
  898. (WCHAR *) ((LPCWSTR) wszSpecialAccess), // Special Access menu item
  899. #endif
  900. NULL // New special object access
  901. };
  902. #ifdef UNICODE
  903. SED_APPLICATION_ACCESS appAccess[] =
  904. {
  905. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_QUERY_VALUE, 0,
  906. (TCHAR *) ((LPCTSTR) szQueryValue) },
  907. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_SET_VALUE, 0,
  908. (TCHAR *) ((LPCTSTR) szSetValue) },
  909. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_CREATE_SUB_KEY, 0,
  910. (TCHAR *) ((LPCTSTR) szCreateSubkeys) },
  911. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_ENUMERATE_SUB_KEYS, 0,
  912. (TCHAR *) ((LPCTSTR) szEnumerateSubkeys) },
  913. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_NOTIFY, 0,
  914. (TCHAR *) ((LPCTSTR) szNotify) },
  915. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_CREATE_LINK, 0,
  916. (TCHAR *) ((LPCTSTR) szCreateLink) },
  917. { SED_DESC_TYPE_RESOURCE_SPECIAL, 0x00010000, /* DELETE, */ 0,
  918. (TCHAR *) ((LPCTSTR) szDelete) },
  919. { SED_DESC_TYPE_RESOURCE_SPECIAL, WRITE_DAC, 0,
  920. (TCHAR *) ((LPCTSTR) szWriteDAC) },
  921. { SED_DESC_TYPE_RESOURCE_SPECIAL, WRITE_OWNER, 0,
  922. (TCHAR *) ((LPCTSTR) szWriteOwner) },
  923. { SED_DESC_TYPE_RESOURCE_SPECIAL, READ_CONTROL, 0,
  924. (TCHAR *) ((LPCTSTR) szReadControl) },
  925. { SED_DESC_TYPE_RESOURCE, KEY_READ, 0,
  926. (TCHAR *) ((LPCTSTR) szRead) },
  927. { SED_DESC_TYPE_RESOURCE, GENERIC_ALL, /* KEY_ALL_ACCESS, */ 0,
  928. (TCHAR *) ((LPCTSTR) szFullControl) }
  929. };
  930. SED_APPLICATION_ACCESSES appAccesses =
  931. {12, // Count of access groups
  932. appAccess, // Access array
  933. szKeyRead // Default access name
  934. };
  935. #else
  936. WCHAR * wszQueryValue = new WCHAR[szQueryValue.GetLength() + 1];
  937. mbstowcs(wszQueryValue, szQueryValue, szQueryValue.GetLength() + 1);
  938. WCHAR * wszSetValue = new WCHAR[szSetValue.GetLength() + 1];
  939. mbstowcs(wszSetValue, szSetValue, szSetValue.GetLength() + 1);
  940. WCHAR * wszCreateSubkeys = new WCHAR[szCreateSubkeys.GetLength() + 1];
  941. mbstowcs(wszCreateSubkeys, szCreateSubkeys, szCreateSubkeys.GetLength() + 1);
  942. WCHAR * wszEnumerateSubkeys = new WCHAR[szEnumerateSubkeys.GetLength() + 1];
  943. mbstowcs(wszEnumerateSubkeys, szEnumerateSubkeys, szEnumerateSubkeys.GetLength() + 1);
  944. WCHAR * wszNotify = new WCHAR[szNotify.GetLength() + 1];
  945. mbstowcs(wszNotify, szNotify, szNotify.GetLength() + 1);
  946. WCHAR * wszCreateLink = new WCHAR[szCreateLink.GetLength() + 1];
  947. mbstowcs(wszCreateLink, szCreateLink, szCreateLink.GetLength() + 1);
  948. WCHAR * wszDelete = new WCHAR[szDelete.GetLength() + 1];
  949. mbstowcs(wszDelete, szDelete, szDelete.GetLength() + 1);
  950. WCHAR * wszWriteDAC = new WCHAR[szWriteDAC.GetLength() + 1];
  951. mbstowcs(wszWriteDAC, szWriteDAC, szWriteDAC.GetLength() + 1);
  952. WCHAR * wszWriteOwner = new WCHAR[szWriteOwner.GetLength() + 1];
  953. mbstowcs(wszWriteOwner, szWriteOwner, szWriteOwner.GetLength() + 1);
  954. WCHAR * wszReadControl = new WCHAR[szReadControl.GetLength() + 1];
  955. mbstowcs(wszReadControl, szReadControl, szReadControl.GetLength() + 1);
  956. WCHAR * wszRead = new WCHAR[szRead.GetLength() + 1];
  957. mbstowcs(wszRead, szRead, szRead.GetLength() + 1);
  958. WCHAR * wszFullControl = new WCHAR[szFullControl.GetLength() + 1];
  959. mbstowcs(wszFullControl, szFullControl, szFullControl.GetLength() + 1);
  960. SED_APPLICATION_ACCESS appAccess[] =
  961. {
  962. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_QUERY_VALUE, 0,
  963. (WCHAR *) ((LPCWSTR) wszQueryValue) },
  964. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_SET_VALUE, 0,
  965. (WCHAR *) ((LPCWSTR) wszSetValue) },
  966. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_CREATE_SUB_KEY, 0,
  967. (WCHAR *) ((LPCWSTR) wszCreateSubkeys) },
  968. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_ENUMERATE_SUB_KEYS, 0,
  969. (WCHAR *) ((LPCWSTR) wszEnumerateSubkeys) },
  970. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_NOTIFY, 0,
  971. (WCHAR *) ((LPCWSTR) wszNotify) },
  972. { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_CREATE_LINK, 0,
  973. (WCHAR *) ((LPCWSTR) wszCreateLink) },
  974. { SED_DESC_TYPE_RESOURCE_SPECIAL, 0x00010000, /* DELETE, */ 0,
  975. (WCHAR *) ((LPCWSTR) wszDelete) },
  976. { SED_DESC_TYPE_RESOURCE_SPECIAL, WRITE_DAC, 0,
  977. (WCHAR *) ((LPCWSTR) wszWriteDAC) },
  978. { SED_DESC_TYPE_RESOURCE_SPECIAL, WRITE_OWNER, 0,
  979. (WCHAR *) ((LPCWSTR) wszWriteOwner) },
  980. { SED_DESC_TYPE_RESOURCE_SPECIAL, READ_CONTROL, 0,
  981. (WCHAR *) ((LPCWSTR) wszReadControl) },
  982. { SED_DESC_TYPE_RESOURCE, KEY_READ, 0,
  983. (WCHAR *) ((LPCWSTR) wszRead) },
  984. { SED_DESC_TYPE_RESOURCE, GENERIC_ALL, /* KEY_ALL_ACCESS, */ 0,
  985. (WCHAR *) ((LPCWSTR) wszFullControl) }
  986. };
  987. WCHAR wszKeyRead[32];
  988. mbstowcs(wszKeyRead, szKeyRead, 32);
  989. SED_APPLICATION_ACCESSES appAccesses =
  990. {12, // Count of access groups
  991. appAccess, // Access array
  992. wszKeyRead // Default access name
  993. };
  994. #endif
  995. // Intialize the help contexts
  996. helpInfo.aulHelpContext[HC_MAIN_DLG] =
  997. IDH_REGISTRY_KEY_PERMISSIONS;
  998. if (hKey == HKEY_CLASSES_ROOT)
  999. {
  1000. helpInfo.aulHelpContext[HC_SPECIAL_ACCESS_DLG] =
  1001. IDH_SPECIAL_ACCESS_GLOBAL;
  1002. helpInfo.aulHelpContext[HC_NEW_ITEM_SPECIAL_ACCESS_DLG] =
  1003. IDH_SPECIAL_ACCESS_GLOBAL;
  1004. }
  1005. else
  1006. {
  1007. helpInfo.aulHelpContext[HC_SPECIAL_ACCESS_DLG] =
  1008. IDH_SPECIAL_ACCESS_PER_APPID;
  1009. helpInfo.aulHelpContext[HC_NEW_ITEM_SPECIAL_ACCESS_DLG] =
  1010. IDH_SPECIAL_ACCESS_PER_APPID;
  1011. }
  1012. helpInfo.aulHelpContext[HC_ADD_USER_DLG] =
  1013. IDH_ADD_USERS_AND_GROUPS;
  1014. helpInfo.aulHelpContext[HC_ADD_USER_MEMBERS_LG_DLG] =
  1015. IDH_LOCAL_GROUP_MEMBERSHIP;
  1016. helpInfo.aulHelpContext[HC_ADD_USER_MEMBERS_GG_DLG] =
  1017. IDH_GLOBAL_GROUP_MEMBERSHIP;
  1018. helpInfo.aulHelpContext[HC_ADD_USER_SEARCH_DLG] =
  1019. IDH_FIND_ACCOUNT1;
  1020. genericMapping.GenericRead = KEY_READ;
  1021. genericMapping.GenericWrite = KEY_WRITE;
  1022. genericMapping.GenericExecute = KEY_READ;
  1023. genericMapping.GenericAll = KEY_ALL_ACCESS;
  1024. // Invoke the ACL editor
  1025. // SedDiscretionaryAclEditor(hWnd, // Owner hWnd
  1026. // GetModuleHandle(NULL), // Owner hInstance
  1027. // NULL, // Server
  1028. // &objTyp, // ObjectTyp,
  1029. // &appAccesses, // Application accesses
  1030. // szTitle ? szTitle : szHkeyClassesRoot,// Object name,
  1031. // callBackFunc, // Callback function
  1032. // (ULONG) &m_sCallBackContext, // Callback context
  1033. // pSD, // Security descriptor,
  1034. // FALSE, // Couldnt read Dacl,
  1035. // FALSE, // Can't write Dacl,
  1036. // &dwStatus, // SED status return,
  1037. // 0); // Flags
  1038. // Check status return
  1039. if (dwStatus != ERROR_SUCCESS)
  1040. {
  1041. // PostErrorMessage(dwStatus);
  1042. }
  1043. // We're done
  1044. if (fFreePSD)
  1045. {
  1046. delete pSD;
  1047. }
  1048. return dwStatus == 0 ? ERROR_SUCCESS : IDCANCEL;
  1049. }
  1050. BOOL CUtility::InvokeUserBrowser(HWND hWnd, TCHAR *szUser)
  1051. {
  1052. BOOL fRet = FALSE;
  1053. HUSERBROW hUser;
  1054. USERBROWSER sUserBrowser;
  1055. SUserDetailsPlus sUserDetailsPlus;
  1056. ULONG ulSize = USER_DETAILS_BUFFER_SIZE;
  1057. CString szTitle;
  1058. szTitle.LoadString(IDS_Browse_for_users);
  1059. sUserBrowser.ulStructSize = sizeof(USERBROWSER);
  1060. sUserBrowser.fUserCancelled = FALSE;
  1061. sUserBrowser.fExpandNames = TRUE;
  1062. sUserBrowser.hwndOwner = hWnd;
  1063. #ifdef UNICODE
  1064. sUserBrowser.pszTitle = (TCHAR *) ((LPCTSTR) szTitle);
  1065. #else
  1066. WCHAR * wszTitle = new WCHAR[szTitle.GetLength() + 1];
  1067. mbstowcs(wszTitle, szTitle, szTitle.GetLength() + 1);
  1068. sUserBrowser.pszTitle = (WCHAR *) ((LPCWSTR) wszTitle);
  1069. #endif
  1070. sUserBrowser.pszInitialDomain = NULL;
  1071. sUserBrowser.Flags = USRBROWS_DONT_SHOW_COMPUTER |
  1072. USRBROWS_SINGLE_SELECT |
  1073. USRBROWS_INCL_ALL |
  1074. USRBROWS_SHOW_USERS;
  1075. sUserBrowser.ulHelpContext = IDH_BROWSE_FOR_USERS;
  1076. sUserBrowser.pszHelpFileName = L"dcomcnfg.hlp";
  1077. #if 0
  1078. hUser = OpenUserBrowser(&sUserBrowser);
  1079. if (hUser == NULL)
  1080. {
  1081. return FALSE;
  1082. }
  1083. else
  1084. {
  1085. CString szBackslash;
  1086. szBackslash.LoadString(IDS_backslash);
  1087. if (EnumUserBrowserSelection(hUser,
  1088. &sUserDetailsPlus.sUserDetails,
  1089. &ulSize))
  1090. {
  1091. _tcscpy(szUser, sUserDetailsPlus.sUserDetails.pszDomainName);
  1092. _tcscat(szUser, (LPCTSTR) szBackslash);
  1093. _tcscat(szUser, sUserDetailsPlus.sUserDetails.pszAccountName);
  1094. fRet = TRUE;
  1095. }
  1096. }
  1097. CloseUserBrowser(hUser);
  1098. #endif
  1099. return fRet;
  1100. }
  1101. BOOL CUtility::InvokeMachineBrowser(TCHAR *szMachine)
  1102. {
  1103. ///////////////////////////////////////////////////
  1104. // If we end up not wanting to use I_SystemFocusDialog, then the code below
  1105. // is the start for fetching machine resources ourselves
  1106. #if 1
  1107. DWORD dwErr;
  1108. NETRESOURCE aNetResource[1000];
  1109. HANDLE hNetwork;
  1110. DWORD dwEntries = 100;
  1111. DWORD dwBufSize = sizeof(aNetResource);
  1112. dwErr = WNetOpenEnum(RESOURCE_GLOBALNET,
  1113. RESOURCETYPE_ANY,
  1114. 0,
  1115. NULL,
  1116. &hNetwork);
  1117. if (dwErr == NO_ERROR)
  1118. {
  1119. dwEntries = 0xffffffff;
  1120. dwErr = WNetEnumResource(hNetwork,
  1121. &dwEntries,
  1122. aNetResource,
  1123. &dwBufSize);
  1124. }
  1125. WNetCloseEnum(hNetwork);
  1126. dwErr = WNetOpenEnum(RESOURCE_GLOBALNET,
  1127. RESOURCETYPE_ANY,
  1128. 0,
  1129. aNetResource,
  1130. &hNetwork);
  1131. if (dwErr == NO_ERROR)
  1132. {
  1133. dwEntries = 0xffffffff;
  1134. dwErr = WNetEnumResource(hNetwork,
  1135. &dwEntries,
  1136. &aNetResource[1],
  1137. &dwBufSize);
  1138. }
  1139. return dwErr == NO_ERROR ? TRUE : FALSE;
  1140. #else
  1141. ///////////////////////////////////////////////////////
  1142. UINT err;
  1143. BOOL fOkPressed = FALSE;
  1144. err = I_SystemFocusDialog(GetForegroundWindow(),
  1145. // FOCUSDLG_BROWSE_LOGON_DOMAIN |
  1146. // FOCUSDLG_BROWSE_WKSTA_DOMAIN,
  1147. 0x30003,
  1148. szMachine,
  1149. 128,
  1150. &fOkPressed,
  1151. TEXT("dcomcnfg.hlp"),
  1152. IDH_SELECT_DOMAIN);
  1153. if (err == ERROR_SUCCESS && fOkPressed)
  1154. {
  1155. return TRUE;
  1156. }
  1157. else
  1158. {
  1159. return FALSE;
  1160. }
  1161. #endif
  1162. }
  1163. int CUtility::StringFromGUID(GUID &rguid, TCHAR *lpsz, int cbMax)
  1164. {
  1165. int i;
  1166. LPTSTR p = lpsz;
  1167. const BYTE * pBytes = (const BYTE *) &rguid;
  1168. *p++ = L'{';
  1169. for (i = 0; i < sizeof(GuidMap); i++)
  1170. {
  1171. if (GuidMap[i] == '-')
  1172. {
  1173. *p++ = L'-';
  1174. }
  1175. else
  1176. {
  1177. *p++ = szDigits[ (pBytes[GuidMap[i]] & 0xF0) >> 4 ];
  1178. *p++ = szDigits[ (pBytes[GuidMap[i]] & 0x0F) ];
  1179. }
  1180. }
  1181. *p++ = L'}';
  1182. *p = L'\0';
  1183. return GUIDSTR_MAX;
  1184. }
  1185. BOOL CUtility::IsEqualGuid(GUID &guid1, GUID &guid2)
  1186. {
  1187. return (
  1188. ((PLONG) &guid1)[0] == ((PLONG) &guid2)[0] &&
  1189. ((PLONG) &guid1)[1] == ((PLONG) &guid2)[1] &&
  1190. ((PLONG) &guid1)[2] == ((PLONG) &guid2)[2] &&
  1191. ((PLONG) &guid1)[3] == ((PLONG) &guid2)[3]);
  1192. }
  1193. BOOL CUtility::AdjustPrivilege(TCHAR *szPrivilege)
  1194. {
  1195. HANDLE hProcessToken = 0;
  1196. BOOL bOK = FALSE;
  1197. TOKEN_PRIVILEGES privileges;
  1198. if( !OpenProcessToken( GetCurrentProcess(),
  1199. TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
  1200. &hProcessToken ) )
  1201. {
  1202. return FALSE;
  1203. }
  1204. privileges.PrivilegeCount = 1;
  1205. privileges.Privileges[ 0 ].Attributes = SE_PRIVILEGE_ENABLED;
  1206. if( !LookupPrivilegeValue(NULL, szPrivilege,
  1207. &privileges.Privileges[ 0 ].Luid ) )
  1208. {
  1209. return FALSE;
  1210. }
  1211. if( !AdjustTokenPrivileges( hProcessToken, FALSE,
  1212. &privileges,
  1213. 0L, NULL, NULL ) )
  1214. {
  1215. return FALSE;
  1216. }
  1217. if( hProcessToken )
  1218. {
  1219. CloseHandle( hProcessToken );
  1220. }
  1221. return TRUE;
  1222. }
  1223. BOOL CUtility::VerifyRemoteMachine(TCHAR *szRemoteMachine)
  1224. {
  1225. NETRESOURCE sResource;
  1226. NETRESOURCE sResource2;
  1227. DWORD dwErr;
  1228. HANDLE hEnum;
  1229. DWORD cbEntries;
  1230. DWORD cbBfr;
  1231. // TODO: Get this function to work. Right now WNetEnumResource is
  1232. // screwing up the stack, causing an AV and anyway returns the error
  1233. // ERROR_NO_MORE_ITEMS which I don't understand.
  1234. //
  1235. // Also, it is not clear that we should verify the remote machine name.
  1236. // It may have different formats, e.g. IP address or a URL specification.
  1237. // It may not even be on an NT network. In any case it may be offline
  1238. // currently.
  1239. return TRUE;
  1240. sResource.dwScope = RESOURCE_GLOBALNET;
  1241. sResource.dwType = RESOURCETYPE_ANY;
  1242. sResource.dwDisplayType = RESOURCEDISPLAYTYPE_GENERIC;
  1243. sResource.dwUsage = RESOURCEUSAGE_CONTAINER;
  1244. sResource.lpLocalName = NULL;
  1245. sResource.lpRemoteName = szRemoteMachine;
  1246. sResource.lpComment = NULL;
  1247. sResource.lpProvider = NULL;
  1248. dwErr = WNetOpenEnum(RESOURCE_GLOBALNET,
  1249. RESOURCETYPE_ANY,
  1250. RESOURCEUSAGE_CONTAINER,
  1251. &sResource,
  1252. &hEnum);
  1253. if (dwErr == NO_ERROR)
  1254. {
  1255. cbEntries = 1;
  1256. cbBfr = sizeof(NETRESOURCE);
  1257. dwErr = WNetEnumResource(hEnum, &cbEntries, &sResource2, &cbBfr);
  1258. }
  1259. CloseHandle(hEnum);
  1260. return TRUE;
  1261. }
  1262. BOOL CUtility::RetrieveUserPassword(TCHAR *szAppid, CString &sPassword)
  1263. {
  1264. #ifdef UNICODE
  1265. LSA_OBJECT_ATTRIBUTES sObjAttributes;
  1266. HANDLE hPolicy = NULL;
  1267. LSA_UNICODE_STRING sKey;
  1268. PLSA_UNICODE_STRING psPassword;
  1269. TCHAR szKey[4 + GUIDSTR_MAX + 1];
  1270. // Formulate the access key
  1271. _tcscpy(szKey, TEXT("SCM:"));
  1272. _tcscat(szKey, szAppid);
  1273. // UNICODE_STRING length fields are in bytes and include the NULL
  1274. // terminator
  1275. sKey.Length = (_tcslen(szKey) + 1) * sizeof(WCHAR);
  1276. sKey.MaximumLength = (GUIDSTR_MAX + 5) * sizeof(WCHAR);
  1277. sKey.Buffer = szKey;
  1278. // Open the local security policy
  1279. InitializeObjectAttributes(&sObjAttributes, NULL, 0L, NULL, NULL);
  1280. if (!NT_SUCCESS(LsaOpenPolicy(NULL, &sObjAttributes,
  1281. POLICY_GET_PRIVATE_INFORMATION, &hPolicy)))
  1282. {
  1283. return FALSE;
  1284. }
  1285. // Read the user's password
  1286. if (!NT_SUCCESS(LsaRetrievePrivateData(hPolicy, &sKey, &psPassword)))
  1287. {
  1288. LsaClose(hPolicy);
  1289. return FALSE;
  1290. }
  1291. // Close the policy handle, we're done with it now.
  1292. LsaClose(hPolicy);
  1293. // Copy the password
  1294. sPassword = psPassword->Buffer;
  1295. #endif
  1296. return TRUE;
  1297. }
  1298. BOOL CUtility::StoreUserPassword(TCHAR *szAppid, CString &szPassword)
  1299. {
  1300. #ifdef UNICODE
  1301. LSA_OBJECT_ATTRIBUTES sObjAttributes;
  1302. HANDLE hPolicy = NULL;
  1303. LSA_UNICODE_STRING sKey;
  1304. LSA_UNICODE_STRING sPassword;
  1305. TCHAR szKey[4 + GUIDSTR_MAX + 1];
  1306. // Formulate the access key
  1307. _tcscpy(szKey, TEXT("SCM:"));
  1308. _tcscat(szKey, szAppid);
  1309. // UNICODE_STRING length fields are in bytes and include the NULL
  1310. // terminator
  1311. sKey.Length = (_tcslen(szKey) + 1) * sizeof(WCHAR);
  1312. sKey.MaximumLength = (GUIDSTR_MAX + 5) * sizeof(WCHAR);
  1313. sKey.Buffer = szKey;
  1314. // Make the password a UNICODE string
  1315. sPassword.Length = (_tcslen(LPCTSTR(szPassword)) + 1) * sizeof(WCHAR);
  1316. sPassword.Buffer = (TCHAR *) LPCTSTR(szPassword);
  1317. sPassword.MaximumLength = sPassword.Length;
  1318. // Open the local security policy
  1319. InitializeObjectAttributes(&sObjAttributes, NULL, 0L, NULL, NULL);
  1320. if (!NT_SUCCESS(LsaOpenPolicy(NULL, &sObjAttributes,
  1321. POLICY_CREATE_SECRET, &hPolicy)))
  1322. {
  1323. return FALSE;
  1324. }
  1325. // Store the user's password
  1326. if (!NT_SUCCESS(LsaStorePrivateData(hPolicy, &sKey, &sPassword)))
  1327. {
  1328. g_util.PostErrorMessage();
  1329. LsaClose(hPolicy);
  1330. return FALSE;
  1331. }
  1332. // Close the policy handle, we're done with it now.
  1333. LsaClose(hPolicy);
  1334. #endif
  1335. return TRUE;
  1336. }
  1337. BOOL CUtility::LookupProcessInfo(SID **ppSid, TCHAR **ppszPrincName)
  1338. {
  1339. BYTE aMemory[SIZEOF_TOKEN_USER];
  1340. TOKEN_USER *pTokenUser = (TOKEN_USER *) &aMemory;
  1341. HANDLE hToken = NULL;
  1342. DWORD lIgnore;
  1343. DWORD lSidLen;
  1344. DWORD lNameLen = 0;
  1345. DWORD lDomainLen = 0;
  1346. TCHAR *pDomainName = NULL;
  1347. SID_NAME_USE sIgnore;
  1348. if (ppszPrincName != NULL)
  1349. *ppszPrincName = NULL;
  1350. // Open the process's token.
  1351. if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
  1352. {
  1353. // Lookup SID of process token.
  1354. if (GetTokenInformation( hToken, TokenUser, pTokenUser,
  1355. sizeof(aMemory), &lIgnore ))
  1356. {
  1357. // Allocate memory to hold the SID.
  1358. lSidLen = GetLengthSid( pTokenUser->User.Sid );
  1359. *ppSid = (SID *) new BYTE[lSidLen];
  1360. if (*ppSid == NULL)
  1361. {
  1362. return FALSE;
  1363. }
  1364. memcpy(*ppSid, pTokenUser->User.Sid, lSidLen);
  1365. // Stop now if the caller doesn't want the user name.
  1366. if (ppszPrincName != NULL)
  1367. {
  1368. // Find out how much memory to allocate for the name.
  1369. LookupAccountSid(NULL, pTokenUser->User.Sid, NULL, &lNameLen,
  1370. NULL, &lDomainLen, NULL );
  1371. if (lNameLen != 0)
  1372. {
  1373. // Allocate memory for the user's name.
  1374. *ppszPrincName =
  1375. (TCHAR *) new BYTE[lNameLen*sizeof(TCHAR)];
  1376. if (ppszPrincName == NULL)
  1377. {
  1378. CloseHandle( hToken );
  1379. return FALSE;
  1380. }
  1381. pDomainName = (TCHAR *) new BYTE[lDomainLen*sizeof(TCHAR)];
  1382. if (pDomainName == NULL)
  1383. {
  1384. delete ppszPrincName;
  1385. CloseHandle( hToken );
  1386. return FALSE;
  1387. }
  1388. // Find the user's name.
  1389. if (!LookupAccountSid( NULL, pTokenUser->User.Sid,
  1390. *ppszPrincName, &lNameLen,
  1391. pDomainName,
  1392. &lDomainLen, &sIgnore))
  1393. {
  1394. delete ppszPrincName;
  1395. delete pDomainName;
  1396. CloseHandle( hToken );
  1397. return FALSE;
  1398. }
  1399. }
  1400. delete ppszPrincName;
  1401. delete pDomainName;
  1402. }
  1403. }
  1404. CloseHandle( hToken );
  1405. }
  1406. return TRUE;
  1407. }
  1408. BOOL CUtility::MakeSecDesc(SID *pSid, SECURITY_DESCRIPTOR **ppSD)
  1409. {
  1410. ACL *pAcl;
  1411. DWORD lSidLen;
  1412. SID *pGroup;
  1413. SID *pOwner;
  1414. // In case we fail
  1415. *ppSD = NULL;
  1416. // Allocate the security descriptor.
  1417. lSidLen = GetLengthSid( pSid );
  1418. *ppSD = (SECURITY_DESCRIPTOR *) new BYTE[
  1419. sizeof(SECURITY_DESCRIPTOR) + 2*lSidLen + SIZEOF_ACL];
  1420. if (*ppSD == NULL)
  1421. {
  1422. return FALSE;
  1423. }
  1424. pGroup = (SID *) (*ppSD + 1);
  1425. pOwner = (SID *) (((BYTE *) pGroup) + lSidLen);
  1426. pAcl = (ACL *) (((BYTE *) pOwner) + lSidLen);
  1427. // Initialize a new security descriptor.
  1428. if (!InitializeSecurityDescriptor(*ppSD, SECURITY_DESCRIPTOR_REVISION))
  1429. {
  1430. delete *ppSD;
  1431. return FALSE;
  1432. }
  1433. // Initialize a new ACL.
  1434. if (!InitializeAcl(pAcl, SIZEOF_ACL, ACL_REVISION2))
  1435. {
  1436. delete *ppSD;
  1437. return FALSE;
  1438. }
  1439. // Comment out this code because the only time we create a default SD is
  1440. // when attempting to edit
  1441. // \\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLE.DefaultAccessPermission
  1442. // which we want to start with 0 ACE's
  1443. /*
  1444. // Allow the current user access.
  1445. if (!AddAccessAllowedAce( pAcl, ACL_REVISION2, COM_RIGHTS_EXECUTE, pSid ))
  1446. {
  1447. delete *ppSD;
  1448. return FALSE;
  1449. }
  1450. // Allow local system access.
  1451. if (!AddAccessAllowedAce( pAcl, ACL_REVISION2, COM_RIGHTS_EXECUTE,
  1452. (void *) &LOCAL_SYSTEM_SID ))
  1453. {
  1454. delete *ppSD;
  1455. return FALSE;
  1456. }
  1457. */
  1458. // Add a new ACL to the security descriptor.
  1459. if (!SetSecurityDescriptorDacl( *ppSD, TRUE, pAcl, FALSE ))
  1460. {
  1461. delete *ppSD;
  1462. return FALSE;
  1463. }
  1464. // Set the group.
  1465. memcpy( pGroup, pSid, lSidLen );
  1466. if (!SetSecurityDescriptorGroup( *ppSD, pGroup, FALSE ))
  1467. {
  1468. delete *ppSD;
  1469. return FALSE;
  1470. }
  1471. // Set the owner.
  1472. memcpy( pOwner, pSid, lSidLen );
  1473. if (!SetSecurityDescriptorOwner( *ppSD, pOwner, FALSE ))
  1474. {
  1475. delete *ppSD;
  1476. return FALSE;
  1477. }
  1478. // Check the security descriptor.
  1479. assert(IsValidSecurityDescriptor(*ppSD));
  1480. return TRUE;
  1481. }
  1482. BOOL CUtility::CheckSDForCOM_RIGHTS_EXECUTE(SECURITY_DESCRIPTOR *pSD)
  1483. {
  1484. PSrSecurityDescriptor pSrSD = (PSrSecurityDescriptor) pSD;
  1485. PSrAcl pDacl;
  1486. PSrAce pAce;
  1487. DWORD cbAces;
  1488. // Check whether the security descriptor is self-relative
  1489. if (pSrSD->Dacl > 0x1000)
  1490. {
  1491. pDacl = (PSrAcl) pSrSD->Dacl;
  1492. // Check for a deny ALL
  1493. if (pDacl == NULL)
  1494. {
  1495. return TRUE;
  1496. }
  1497. }
  1498. else
  1499. {
  1500. // First check for a deny ALL
  1501. if (pSrSD->Dacl == 0)
  1502. {
  1503. return TRUE;
  1504. }
  1505. pDacl = (PSrAcl) (((BYTE *) pSrSD) + (pSrSD->Dacl));
  1506. }
  1507. // Do over the ACE's
  1508. for (pAce = (PSrAce) (((BYTE *) pDacl) + sizeof(SSrAcl)),
  1509. cbAces = pDacl->AceCount;
  1510. cbAces;
  1511. pAce = (PSrAce) (((BYTE *) pAce) + pAce->AceSize),
  1512. cbAces--)
  1513. {
  1514. // Check that it is
  1515. // a) an allow on COM_RIGHTS_EXECUTE
  1516. // b) a deny on GENERIC_ALL,
  1517. // c) a deny on COM_RIGHTS_EXECUTE,
  1518. // d) a deny ALL (handled above if the DACL is NULL) or
  1519. // e) an allow everyone (handled implicitly if cbAces == 0)
  1520. if (!(((pAce->Type == 0 && pAce->AccessMask == COM_RIGHTS_EXECUTE)
  1521. ||
  1522. (pAce->Type == 1 && pAce->AccessMask == GENERIC_ALL)
  1523. ||
  1524. (pAce->Type == 1 && pAce->AccessMask == COM_RIGHTS_EXECUTE))))
  1525. {
  1526. CString szText;
  1527. CString szTitle;
  1528. szText.LoadString(IDS_The_security_);
  1529. szTitle.LoadString(IDS_DCOM_Configuration_Warning);
  1530. if (MessageBox(GetForegroundWindow(),
  1531. (LPCTSTR) szText,
  1532. (LPCTSTR) szTitle,
  1533. MB_YESNO) == IDYES)
  1534. {
  1535. pAce->Flags = 0;
  1536. pAce->Type = 0;
  1537. pAce->AccessMask = COM_RIGHTS_EXECUTE;
  1538. }
  1539. else
  1540. {
  1541. return FALSE;
  1542. }
  1543. }
  1544. }
  1545. return TRUE;
  1546. }
  1547. BOOL CUtility::ChangeService(const TCHAR *szService,
  1548. const TCHAR *szIdentity,
  1549. const TCHAR *szPassword,
  1550. const TCHAR *szDisplay)
  1551. {
  1552. SC_HANDLE hSCManager;
  1553. SC_HANDLE hService;
  1554. // Open the service control manager
  1555. if (hSCManager = OpenSCManager(NULL, NULL, GENERIC_READ | GENERIC_WRITE))
  1556. {
  1557. // Try to open a handle to the requested service
  1558. if (!(hService = OpenService(hSCManager,
  1559. szService,
  1560. GENERIC_READ | GENERIC_WRITE)))
  1561. {
  1562. g_util.PostErrorMessage();
  1563. CloseServiceHandle(hSCManager);
  1564. return FALSE;
  1565. }
  1566. // Close the service manager's database
  1567. CloseServiceHandle(hSCManager);
  1568. // Change service identity parameters
  1569. if (ChangeServiceConfig(hService,
  1570. SERVICE_WIN32_OWN_PROCESS,
  1571. SERVICE_DEMAND_START,
  1572. SERVICE_NO_CHANGE,
  1573. NULL,
  1574. NULL,
  1575. NULL,
  1576. NULL,
  1577. szIdentity,
  1578. szPassword,
  1579. szDisplay))
  1580. {
  1581. // Return success
  1582. CloseServiceHandle(hService);
  1583. return TRUE;
  1584. }
  1585. else
  1586. {
  1587. g_util.PostErrorMessage();
  1588. CloseServiceHandle(hService);
  1589. return FALSE;
  1590. }
  1591. }
  1592. else
  1593. {
  1594. g_util.PostErrorMessage();
  1595. return FALSE;
  1596. }
  1597. }
  1598. BOOL CUtility::UpdateDCOMInfo(void)
  1599. {
  1600. RPC_STATUS status;
  1601. #ifdef UNICODE
  1602. TCHAR *pszBindString;
  1603. #else
  1604. unsigned char * pszBindString;
  1605. #endif
  1606. // Get a binding handle to the SCM if we haven't yet
  1607. if (m_hRpc == NULL)
  1608. {
  1609. #ifdef UNICODE
  1610. status = RpcStringBindingCompose(NULL,
  1611. TEXT("ncalrpc"),
  1612. NULL,
  1613. TEXT("epmapper"),
  1614. NULL,
  1615. &pszBindString);
  1616. #else
  1617. status = RpcStringBindingCompose(NULL,
  1618. (unsigned char *)"ncalrpc",
  1619. NULL,
  1620. (unsigned char *)"epmapper",
  1621. NULL,
  1622. &pszBindString);
  1623. #endif
  1624. if (status != RPC_S_OK)
  1625. {
  1626. return status;
  1627. }
  1628. status = RpcBindingFromStringBinding(pszBindString, &m_hRpc);
  1629. RpcStringFree(&pszBindString);
  1630. if (status != ERROR_SUCCESS)
  1631. {
  1632. return status;
  1633. }
  1634. }
  1635. // Call over to the SCM to get the global registry values read
  1636. // into memory
  1637. UpdateActivationSettings(m_hRpc, &status);
  1638. return status;
  1639. }
  1640. LRESULT CALLBACK ControlFixProc( HWND hwnd, UINT uMsg, WPARAM wParam,
  1641. LPARAM lParam);
  1642. // This is a work-around because there is a bug in msdev 4.1: Cannot get
  1643. // WM_HELP message processed by a control on which DDX_Control data exchange
  1644. // is done because of subclassing problem. See msdn Q145865 for a discussion
  1645. // plus work-around code.
  1646. void CUtility::FixHelp(CWnd* pWnd)
  1647. {
  1648. // search all child windows. If their window proc
  1649. // is AfxWndProc, then subclass with our window proc
  1650. CWnd* pWndChild = pWnd->GetWindow(GW_CHILD);
  1651. while(pWndChild != NULL)
  1652. {
  1653. if (GetWindowLong(pWndChild->GetSafeHwnd(),
  1654. GWL_WNDPROC) == (LONG)AfxWndProc)
  1655. {
  1656. SetWindowLong(pWndChild->GetSafeHwnd(), GWL_WNDPROC,
  1657. (LONG)ControlFixProc);
  1658. }
  1659. pWndChild = pWndChild->GetWindow(GW_HWNDNEXT);
  1660. }
  1661. }
  1662. LRESULT CALLBACK ControlFixProc(HWND hwnd, UINT uMsg, WPARAM wParam,
  1663. LPARAM lParam)
  1664. {
  1665. if (uMsg == WM_HELP)
  1666. {
  1667. // bypass MFC's handler, message will be sent to parent
  1668. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  1669. }
  1670. return AfxWndProc(hwnd,uMsg,wParam,lParam);
  1671. }
  1672. // Compare two security descriptors in self-relative form to
  1673. // determine if they're the same
  1674. BOOL CUtility::CompareSDs(PSrSecurityDescriptor pSD1,
  1675. PSrSecurityDescriptor pSD2)
  1676. {
  1677. PSID pSid1, pSid2;
  1678. PSrAcl pDacl1, pDacl2;
  1679. PSrAce pAce1, pAce2;
  1680. BYTE *p1, *p2;
  1681. // Compare the owners
  1682. pSid1 = (PSID) (((BYTE *) pSD1) + pSD1->Owner);
  1683. pSid2 = (PSID) (((BYTE *) pSD2) + pSD2->Owner);
  1684. if (!EqualSid(pSid1, pSid2))
  1685. {
  1686. return FALSE;
  1687. }
  1688. // Compare the groups
  1689. pSid1 = (PSID) (((BYTE *) pSD1) + pSD1->Group);
  1690. pSid2 = (PSID) (((BYTE *) pSD2) + pSD2->Group);
  1691. if (!EqualSid(pSid1, pSid2))
  1692. {
  1693. return FALSE;
  1694. }
  1695. // Compare the DACL's
  1696. pDacl1 = (PSrAcl) (((BYTE *) pSD1) + pSD1->Dacl);
  1697. pDacl2 = (PSrAcl) (((BYTE *) pSD2) + pSD2->Dacl);
  1698. // Check first that they are the same size and have the same
  1699. // number of ACE's
  1700. if (! (pDacl1->AclSize == pDacl2->AclSize &&
  1701. pDacl1->AceCount == pDacl2->AceCount))
  1702. {
  1703. return FALSE;
  1704. }
  1705. // Now compare the ACL ACE by ACE
  1706. pAce1 = (PSrAce) (((BYTE *) pDacl1) + sizeof(SSrAcl));
  1707. pAce2 = (PSrAce) (((BYTE *) pDacl2) + sizeof(SSrAcl));
  1708. for (int k = 0; k < pDacl1->AceCount; k++)
  1709. {
  1710. // Check the ACE headers
  1711. if (! (pAce1->Type == pAce2->Type &&
  1712. pAce1->AceSize == pAce2->AceSize &&
  1713. pAce1->AccessMask == pAce2->AccessMask))
  1714. {
  1715. return FALSE;
  1716. }
  1717. // Check the SID's
  1718. p1 = (BYTE *) (((BYTE *) pAce1) + sizeof(ACE_HEADER));
  1719. p2 = (BYTE *) (((BYTE *) pAce2) + sizeof(ACE_HEADER));
  1720. for (ULONG j = 0; j < pAce1->AceSize - sizeof(ACE_HEADER); j++)
  1721. {
  1722. if (p1[j] != p2[j])
  1723. {
  1724. return FALSE;
  1725. }
  1726. }
  1727. // Go to the next ACE
  1728. pAce1 = (PSrAce) (((BYTE *) pAce1) + pAce1->AceSize);
  1729. pAce2 = (PSrAce) (((BYTE *) pAce2) + pAce2->AceSize);
  1730. }
  1731. return TRUE;
  1732. }
  1733. int CUtility::SetAccountRights(const TCHAR *szUser, TCHAR *szPrivilege)
  1734. {
  1735. #if UNICODE
  1736. int err;
  1737. LSA_HANDLE hPolicy;
  1738. LSA_OBJECT_ATTRIBUTES objAtt;
  1739. DWORD cbSid = 1;
  1740. TCHAR szDomain[128];
  1741. DWORD cbDomain = 128;
  1742. PSID pSid = NULL;
  1743. SID_NAME_USE snu;
  1744. LSA_UNICODE_STRING privStr;
  1745. // Get a policy handle
  1746. memset(&objAtt, 0, sizeof(LSA_OBJECT_ATTRIBUTES));
  1747. if (!NT_SUCCESS(LsaOpenPolicy(NULL,
  1748. &objAtt,
  1749. POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
  1750. &hPolicy)))
  1751. {
  1752. return GetLastError();
  1753. }
  1754. // Fetch the SID for the specified user
  1755. LookupAccountName(NULL, szUser, pSid, &cbSid, szDomain, &cbDomain, &snu);
  1756. if ((err = GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
  1757. {
  1758. LsaClose(hPolicy);
  1759. return err;
  1760. }
  1761. pSid = new BYTE[cbSid];
  1762. if (pSid == NULL)
  1763. {
  1764. LsaClose(hPolicy);
  1765. return ERROR_OUTOFMEMORY;
  1766. }
  1767. if (!LookupAccountName(NULL, szUser, pSid, &cbSid,
  1768. szDomain, &cbDomain, &snu))
  1769. {
  1770. LsaClose(hPolicy);
  1771. return GetLastError();
  1772. }
  1773. // Set the specified privilege on this account
  1774. privStr.Length = _tcslen(szPrivilege) * sizeof(WCHAR);
  1775. privStr.MaximumLength = privStr.Length + sizeof(WCHAR);
  1776. privStr.Buffer = szPrivilege;
  1777. if (!NT_SUCCESS(LsaAddAccountRights(hPolicy, pSid, &privStr, 1)))
  1778. {
  1779. LsaClose(hPolicy);
  1780. return GetLastError();
  1781. }
  1782. // We're done
  1783. delete pSid;
  1784. LsaClose(hPolicy);
  1785. #endif
  1786. return ERROR_SUCCESS;
  1787. }
  1788. // This method is included only because in the debug version when using
  1789. // MFC they validate the C++ heap, whereas RtlCopySecurityDescriptor uses
  1790. // the standard process heap, causing MFC to throw a breakpoint
  1791. void CUtility::CopySD(SECURITY_DESCRIPTOR *pSrc, SECURITY_DESCRIPTOR **pDest)
  1792. {
  1793. ULONG cbLen;
  1794. SECURITY_DESCRIPTOR *pSD;
  1795. #if 0
  1796. cbLen = RtlLengthSecurityDescriptor(pSrc);
  1797. #else
  1798. cbLen = 10;
  1799. #endif
  1800. pSD = (SECURITY_DESCRIPTOR *) new BYTE[cbLen];
  1801. *pDest = pSD;
  1802. if (pSD)
  1803. {
  1804. memcpy(pSD, pSrc, cbLen);
  1805. }
  1806. }
  1807. // Set the inheritance flags on a security descriptor so keys created
  1808. // under the key having this security descriptor will inherit all its
  1809. // ACE's. We do this as a utility routine rather than via the ACL
  1810. // editor because doing that adds check boxes and such to the ACL editor,
  1811. // so it's cleaner this way.
  1812. //
  1813. // Note. The security descriptor is expected to be in absolute form
  1814. void CUtility::SetInheritanceFlags(SECURITY_DESCRIPTOR *pSec)
  1815. {
  1816. PSrAcl pAcl = (PSrAcl) pSec->Dacl;
  1817. PSrAce pAce;
  1818. int k;
  1819. // Do over the ACE's this DACL
  1820. for (k = pAcl->AceCount, pAce = (PSrAce) (((BYTE *) pAcl) + sizeof(SSrAcl));
  1821. k;
  1822. k--, pAce = (PSrAce) (((BYTE *) pAce) + pAce->AceSize))
  1823. {
  1824. pAce->Flags |= CONTAINER_INHERIT_ACE;
  1825. }
  1826. }