Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

506 lines
16 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: pagebase.cpp
  8. //
  9. // This file contains the implementation of the CSecurityPage base class.
  10. //
  11. //--------------------------------------------------------------------------
  12. #include "aclpriv.h"
  13. CSecurityPage::CSecurityPage( LPSECURITYINFO psi, SI_PAGE_TYPE siType )
  14. : m_siPageType(siType), m_psi(psi), m_psi2(NULL),m_pei(NULL), m_pObjectPicker(NULL),
  15. m_psoti(NULL),
  16. m_flLastOPOptions(DWORD(-1))
  17. {
  18. ZeroMemory(&m_siObjectInfo, sizeof(m_siObjectInfo));
  19. // Initialize COM incase our client hasn't
  20. m_hrComInit = CoInitialize(NULL);
  21. if (m_psi != NULL)
  22. {
  23. m_psi->AddRef();
  24. // It's normal for this to fail
  25. m_psi->QueryInterface(IID_ISecurityInformation2, (LPVOID*)&m_psi2);
  26. m_psi->QueryInterface(IID_IEffectivePermission, (LPVOID*)&m_pei);
  27. m_psi->QueryInterface(IID_ISecurityObjectTypeInfo, (LPVOID*)&m_psoti);
  28. }
  29. }
  30. CSecurityPage::~CSecurityPage( void )
  31. {
  32. DoRelease(m_psi);
  33. DoRelease(m_psi2);
  34. DoRelease(m_pObjectPicker);
  35. DoRelease(m_pei);
  36. DoRelease(m_psoti);
  37. if (SUCCEEDED(m_hrComInit))
  38. CoUninitialize();
  39. }
  40. HPROPSHEETPAGE
  41. CSecurityPage::CreatePropSheetPage(LPCTSTR pszDlgTemplate, LPCTSTR pszDlgTitle)
  42. {
  43. PROPSHEETPAGE psp;
  44. psp.dwSize = sizeof(psp);
  45. psp.dwFlags = PSP_USECALLBACK ;
  46. psp.hInstance = ::hModule;
  47. psp.pszTemplate = pszDlgTemplate;
  48. psp.pszTitle = pszDlgTitle;
  49. psp.pfnDlgProc = CSecurityPage::_DlgProc;
  50. psp.lParam = (LPARAM)this;
  51. psp.pfnCallback = CSecurityPage::_PSPageCallback;
  52. if (pszDlgTitle != NULL)
  53. psp.dwFlags |= PSP_USETITLE;
  54. return CreatePropertySheetPage(&psp);
  55. }
  56. HRESULT
  57. CSecurityPage::GetObjectPicker(IDsObjectPicker **ppObjectPicker)
  58. {
  59. HRESULT hr = S_OK;
  60. if (!m_pObjectPicker)
  61. {
  62. if (!m_psi)
  63. return E_UNEXPECTED;
  64. // See if the object supports IDsObjectPicker
  65. hr = m_psi->QueryInterface(IID_IDsObjectPicker, (LPVOID*)&m_pObjectPicker);
  66. // If the object doesn't support IDsObjectPicker, create one.
  67. if (FAILED(hr))
  68. {
  69. hr = CoCreateInstance(CLSID_DsObjectPicker,
  70. NULL,
  71. CLSCTX_INPROC_SERVER,
  72. IID_IDsObjectPicker,
  73. (LPVOID*)&m_pObjectPicker);
  74. }
  75. }
  76. if (ppObjectPicker)
  77. {
  78. *ppObjectPicker = m_pObjectPicker;
  79. // Return a reference (caller must Release)
  80. if (m_pObjectPicker)
  81. m_pObjectPicker->AddRef();
  82. }
  83. return hr;
  84. }
  85. //
  86. // Stuff used for initializing the Object Picker below
  87. //
  88. #define DSOP_FILTER_COMMON1 ( DSOP_FILTER_INCLUDE_ADVANCED_VIEW \
  89. | DSOP_FILTER_USERS \
  90. | DSOP_FILTER_UNIVERSAL_GROUPS_SE \
  91. | DSOP_FILTER_GLOBAL_GROUPS_SE \
  92. | DSOP_FILTER_COMPUTERS \
  93. )
  94. #define DSOP_FILTER_COMMON2 ( DSOP_FILTER_COMMON1 \
  95. | DSOP_FILTER_WELL_KNOWN_PRINCIPALS \
  96. | DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE\
  97. )
  98. #define DSOP_FILTER_COMMON3 ( DSOP_FILTER_COMMON2 \
  99. | DSOP_FILTER_BUILTIN_GROUPS \
  100. )
  101. #define DSOP_FILTER_DL_COMMON1 ( DSOP_DOWNLEVEL_FILTER_USERS \
  102. | DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS \
  103. )
  104. #define DSOP_FILTER_DL_COMMON2 ( DSOP_FILTER_DL_COMMON1 \
  105. | DSOP_DOWNLEVEL_FILTER_ALL_WELLKNOWN_SIDS \
  106. )
  107. #define DSOP_FILTER_DL_COMMON3 ( DSOP_FILTER_DL_COMMON2 \
  108. | DSOP_DOWNLEVEL_FILTER_LOCAL_GROUPS \
  109. )
  110. #if 0
  111. { // DSOP_SCOPE_INIT_INFO
  112. cbSize,
  113. flType,
  114. flScope,
  115. { // DSOP_FILTER_FLAGS
  116. { // DSOP_UPLEVEL_FILTER_FLAGS
  117. flBothModes,
  118. flMixedModeOnly,
  119. flNativeModeOnly
  120. },
  121. flDownlevel
  122. },
  123. pwzDcName,
  124. pwzADsPath,
  125. hr // OUT
  126. }
  127. #endif
  128. #define DECLARE_SCOPE(t,f,b,m,n,d) \
  129. { sizeof(DSOP_SCOPE_INIT_INFO), (t), (f|DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS|DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS), { { (b), (m), (n) }, (d) }, NULL, NULL, S_OK }
  130. // The domain to which the target computer is joined.
  131. // Make 2 scopes, one for uplevel domains, the other for downlevel.
  132. #define JOINED_DOMAIN_SCOPE(f) \
  133. DECLARE_SCOPE(DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN,(f),0,(DSOP_FILTER_COMMON2 & ~(DSOP_FILTER_UNIVERSAL_GROUPS_SE|DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE)),DSOP_FILTER_COMMON2,0), \
  134. DECLARE_SCOPE(DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN,(f),0,0,0,DSOP_FILTER_DL_COMMON2)
  135. // The domain for which the target computer is a Domain Controller.
  136. // Make 2 scopes, one for uplevel domains, the other for downlevel.
  137. #define JOINED_DOMAIN_SCOPE_DC(f) \
  138. DECLARE_SCOPE(DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN,(f),0,(DSOP_FILTER_COMMON3 & ~DSOP_FILTER_UNIVERSAL_GROUPS_SE),DSOP_FILTER_COMMON3,0), \
  139. DECLARE_SCOPE(DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN,(f),0,0,0,DSOP_FILTER_DL_COMMON3)
  140. // Target computer scope. Computer scopes are always treated as
  141. // downlevel (i.e., they use the WinNT provider).
  142. #define TARGET_COMPUTER_SCOPE(f)\
  143. DECLARE_SCOPE(DSOP_SCOPE_TYPE_TARGET_COMPUTER,(f),0,0,0,DSOP_FILTER_DL_COMMON3)
  144. // The Global Catalog
  145. #define GLOBAL_CATALOG_SCOPE(f) \
  146. DECLARE_SCOPE(DSOP_SCOPE_TYPE_GLOBAL_CATALOG,(f),DSOP_FILTER_COMMON1|DSOP_FILTER_WELL_KNOWN_PRINCIPALS,0,0,0)
  147. // The domains in the same forest (enterprise) as the domain to which
  148. // the target machine is joined. Note these can only be DS-aware
  149. #define ENTERPRISE_SCOPE(f) \
  150. DECLARE_SCOPE(DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN,(f),DSOP_FILTER_COMMON1,0,0,0)
  151. // Domains external to the enterprise but trusted directly by the
  152. // domain to which the target machine is joined.
  153. #define EXTERNAL_SCOPE(f) \
  154. DECLARE_SCOPE(DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN|DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN,\
  155. (f),DSOP_FILTER_COMMON1,0,0,DSOP_DOWNLEVEL_FILTER_USERS|DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS)
  156. // Workgroup scope. Only valid if the target computer is not joined
  157. // to a domain.
  158. #define WORKGROUP_SCOPE(f) \
  159. DECLARE_SCOPE(DSOP_SCOPE_TYPE_WORKGROUP,(f),0,0,0, DSOP_FILTER_DL_COMMON1|DSOP_DOWNLEVEL_FILTER_LOCAL_GROUPS )
  160. //
  161. // Array of Default Scopes
  162. //
  163. static const DSOP_SCOPE_INIT_INFO g_aDefaultScopes[] =
  164. {
  165. JOINED_DOMAIN_SCOPE(DSOP_SCOPE_FLAG_STARTING_SCOPE),
  166. TARGET_COMPUTER_SCOPE(0),
  167. GLOBAL_CATALOG_SCOPE(0),
  168. ENTERPRISE_SCOPE(0),
  169. EXTERNAL_SCOPE(0),
  170. };
  171. //
  172. // Same as above, but without the Target Computer
  173. // Used when the target is a Domain Controller
  174. //
  175. static const DSOP_SCOPE_INIT_INFO g_aDCScopes[] =
  176. {
  177. JOINED_DOMAIN_SCOPE_DC(DSOP_SCOPE_FLAG_STARTING_SCOPE),
  178. GLOBAL_CATALOG_SCOPE(0),
  179. ENTERPRISE_SCOPE(0),
  180. EXTERNAL_SCOPE(0),
  181. };
  182. //
  183. // Array of scopes for standalone machines
  184. //
  185. static const DSOP_SCOPE_INIT_INFO g_aStandAloneScopes[] =
  186. {
  187. //
  188. //On Standalone machine Both User And Groups are selected by default
  189. //
  190. TARGET_COMPUTER_SCOPE(DSOP_SCOPE_FLAG_STARTING_SCOPE|DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS),
  191. };
  192. //
  193. // Attributes that we want the Object Picker to retrieve
  194. //
  195. static const LPCTSTR g_aszOPAttributes[] =
  196. {
  197. TEXT("ObjectSid"),
  198. TEXT("userAccountControl"),
  199. };
  200. HRESULT
  201. CSecurityPage::InitObjectPicker(BOOL bMultiSelect)
  202. {
  203. HRESULT hr = S_OK;
  204. DSOP_INIT_INFO InitInfo;
  205. PCDSOP_SCOPE_INIT_INFO pScopes;
  206. ULONG cScopes;
  207. USES_CONVERSION;
  208. TraceEnter(TRACE_MISC, "InitObjectPicker");
  209. hr = GetObjectPicker();
  210. if (FAILED(hr))
  211. TraceLeaveResult(hr);
  212. TraceAssert(m_pObjectPicker != NULL);
  213. InitInfo.cbSize = sizeof(InitInfo);
  214. // We do the DC check at WM_INITDIALOG
  215. InitInfo.flOptions = DSOP_FLAG_SKIP_TARGET_COMPUTER_DC_CHECK;
  216. if (bMultiSelect)
  217. InitInfo.flOptions |= DSOP_FLAG_MULTISELECT;
  218. // flOptions is the only thing that changes from call to call,
  219. // so optimize this by only reinitializing if flOptions changes.
  220. if (m_flLastOPOptions == InitInfo.flOptions)
  221. TraceLeaveResult(S_OK); // Already initialized
  222. m_flLastOPOptions = (DWORD)-1;
  223. pScopes = g_aDefaultScopes;
  224. cScopes = ARRAYSIZE(g_aDefaultScopes);
  225. if (m_bStandalone)
  226. {
  227. cScopes = ARRAYSIZE(g_aStandAloneScopes);
  228. pScopes = g_aStandAloneScopes;
  229. }
  230. else if (m_siObjectInfo.dwFlags & SI_SERVER_IS_DC)
  231. {
  232. cScopes = ARRAYSIZE(g_aDCScopes);
  233. pScopes = g_aDCScopes;
  234. }
  235. //
  236. // The pwzTargetComputer member allows the object picker to be
  237. // retargetted to a different computer. It will behave as if it
  238. // were being run ON THAT COMPUTER.
  239. //
  240. InitInfo.pwzTargetComputer = T2CW(m_siObjectInfo.pszServerName);
  241. InitInfo.cDsScopeInfos = cScopes;
  242. InitInfo.aDsScopeInfos = (PDSOP_SCOPE_INIT_INFO)LocalAlloc(LPTR, sizeof(*pScopes)*cScopes);
  243. if (!InitInfo.aDsScopeInfos)
  244. TraceLeaveResult(E_OUTOFMEMORY);
  245. CopyMemory(InitInfo.aDsScopeInfos, pScopes, sizeof(*pScopes)*cScopes);
  246. InitInfo.cAttributesToFetch = ARRAYSIZE(g_aszOPAttributes);
  247. InitInfo.apwzAttributeNames = (LPCTSTR*)g_aszOPAttributes;
  248. if (m_siObjectInfo.dwFlags & SI_SERVER_IS_DC)
  249. {
  250. for (ULONG i = 0; i < cScopes; i++)
  251. {
  252. // Set the DC name if appropriate
  253. if ((m_siObjectInfo.dwFlags & SI_SERVER_IS_DC) &&
  254. (InitInfo.aDsScopeInfos[i].flType & DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN))
  255. {
  256. InitInfo.aDsScopeInfos[i].pwzDcName = InitInfo.pwzTargetComputer;
  257. }
  258. }
  259. }
  260. hr = m_pObjectPicker->Initialize(&InitInfo);
  261. if (SUCCEEDED(hr))
  262. {
  263. // Remember the Options for next time
  264. m_flLastOPOptions = InitInfo.flOptions;
  265. }
  266. LocalFree(InitInfo.aDsScopeInfos);
  267. TraceLeaveResult(hr);
  268. }
  269. HRESULT
  270. CSecurityPage::GetUserGroup(HWND hDlg, BOOL bMultiSelect, PUSER_LIST *ppUserList)
  271. {
  272. HRESULT hr;
  273. LPDATAOBJECT pdoSelection = NULL;
  274. STGMEDIUM medium = {0};
  275. FORMATETC fe = { (CLIPFORMAT)g_cfDsSelectionList, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  276. PDS_SELECTION_LIST pDsSelList = NULL;
  277. HCURSOR hcur = NULL;
  278. PSIDCACHE pSidCache = NULL;
  279. UINT idErrorMsg = IDS_GET_USER_FAILED;
  280. TraceEnter(TRACE_MISC, "GetUserGroup");
  281. TraceAssert(ppUserList != NULL);
  282. *ppUserList = NULL;
  283. //
  284. // Create and initialize the Object Picker object
  285. //
  286. hr = InitObjectPicker(bMultiSelect);
  287. FailGracefully(hr, "Unable to initialize Object Picker object");
  288. //
  289. // Create the global sid cache object, if necessary
  290. //
  291. pSidCache = GetSidCache();
  292. if (pSidCache == NULL)
  293. ExitGracefully(hr, E_OUTOFMEMORY, "Unable to create SID cache");
  294. //
  295. // Bring up the object picker dialog
  296. //
  297. hr = m_pObjectPicker->InvokeDialog(hDlg, &pdoSelection);
  298. FailGracefully(hr, "IDsObjectPicker->Invoke failed");
  299. if (S_FALSE == hr)
  300. ExitGracefully(hr, S_FALSE, "IDsObjectPicker->Invoke cancelled by user");
  301. hr = pdoSelection->GetData(&fe, &medium);
  302. FailGracefully(hr, "Unable to get CFSTR_DSOP_DS_SELECTION_LIST from DataObject");
  303. pDsSelList = (PDS_SELECTION_LIST)GlobalLock(medium.hGlobal);
  304. if (!pDsSelList)
  305. ExitGracefully(hr, E_FAIL, "Unable to lock stgmedium.hGlobal");
  306. TraceAssert(pDsSelList->cItems > 0);
  307. Trace((TEXT("%d items selected"), pDsSelList->cItems));
  308. hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  309. //Check if there is any disabled items
  310. if(!DoDisabledCheck(hDlg,
  311. pDsSelList))
  312. {
  313. return S_FALSE;
  314. }
  315. //
  316. // Lookup the names/sids and cache them
  317. //
  318. if (!pSidCache->LookupNames(pDsSelList,
  319. m_siObjectInfo.pszServerName,
  320. ppUserList,
  321. m_bStandalone))
  322. {
  323. hr = E_FAIL;
  324. idErrorMsg = IDS_SID_LOOKUP_FAILED;
  325. }
  326. SetCursor(hcur);
  327. exit_gracefully:
  328. if (pSidCache)
  329. pSidCache->Release();
  330. if (FAILED(hr))
  331. {
  332. SysMsgPopup(hDlg,
  333. MAKEINTRESOURCE(idErrorMsg),
  334. MAKEINTRESOURCE(IDS_SECURITY),
  335. MB_OK | MB_ICONERROR,
  336. ::hModule,
  337. hr);
  338. }
  339. if (pDsSelList)
  340. GlobalUnlock(medium.hGlobal);
  341. ReleaseStgMedium(&medium);
  342. DoRelease(pdoSelection);
  343. TraceLeaveResult(hr);
  344. }
  345. UINT
  346. CSecurityPage::PSPageCallback(HWND hwnd,
  347. UINT uMsg,
  348. LPPROPSHEETPAGE /*ppsp*/)
  349. {
  350. m_hrLastPSPCallbackResult = E_FAIL;
  351. if (m_psi != NULL)
  352. {
  353. m_hrLastPSPCallbackResult = m_psi->PropertySheetPageCallback(hwnd, uMsg, m_siPageType);
  354. if (m_hrLastPSPCallbackResult == E_NOTIMPL)
  355. m_hrLastPSPCallbackResult = S_OK;
  356. }
  357. return SUCCEEDED(m_hrLastPSPCallbackResult);
  358. }
  359. INT_PTR
  360. CALLBACK
  361. CSecurityPage::_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  362. {
  363. LPSECURITYPAGE pThis = (LPSECURITYPAGE)GetWindowLongPtr(hDlg, DWLP_USER);
  364. // The following messages arrive before WM_INITDIALOG
  365. // which means pThis is NULL for them. We don't need these
  366. // messages so let DefDlgProc handle them.
  367. //
  368. // WM_SETFONT
  369. // WM_NOTIFYFORMAT
  370. // WM_NOTIFY (LVN_HEADERCREATED)
  371. if (uMsg == WM_INITDIALOG)
  372. {
  373. pThis = (LPSECURITYPAGE)(((LPPROPSHEETPAGE)lParam)->lParam);
  374. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pThis);
  375. if (pThis)
  376. {
  377. if (!pThis->PSPageCallback(hDlg, PSPCB_SI_INITDIALOG, NULL))
  378. pThis->m_bAbortPage = TRUE;
  379. if (pThis->m_psi)
  380. {
  381. BOOL bIsDC = FALSE;
  382. pThis->m_psi->GetObjectInformation(&pThis->m_siObjectInfo);
  383. pThis->m_bStandalone = IsStandalone(pThis->m_siObjectInfo.pszServerName, &bIsDC);
  384. if (bIsDC)
  385. pThis->m_siObjectInfo.dwFlags |= SI_SERVER_IS_DC;
  386. }
  387. }
  388. }
  389. if (pThis != NULL)
  390. return pThis->DlgProc(hDlg, uMsg, wParam, lParam);
  391. return FALSE;
  392. }
  393. UINT
  394. CALLBACK
  395. CSecurityPage::_PSPageCallback(HWND hWnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
  396. {
  397. LPSECURITYPAGE pThis = (LPSECURITYPAGE)ppsp->lParam;
  398. if (pThis)
  399. {
  400. UINT nResult = pThis->PSPageCallback(hWnd, uMsg, ppsp);
  401. switch (uMsg)
  402. {
  403. case PSPCB_CREATE:
  404. if (!nResult)
  405. pThis->m_bAbortPage = TRUE;
  406. break;
  407. case PSPCB_RELEASE:
  408. delete pThis;
  409. break;
  410. }
  411. }
  412. //
  413. // Always return non-zero or else our tab will disappear and whichever
  414. // property page becomes active won't repaint properly. Instead, use
  415. // the m_bAbortPage flag during WM_INITDIALOG to disable the page if
  416. // the callback failed.
  417. //
  418. return 1;
  419. }