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.

589 lines
16 KiB

  1. /*++
  2. Microsoft Windows
  3. Copyright (C) Microsoft Corporation, 1981 - 1998
  4. Module Name:
  5. secpath.cxx
  6. Abstract:
  7. this file contains the code for the dialog that is used for associating
  8. security groups with paths.
  9. Author:
  10. Rahul Thombre (RahulTh) 4/14/1998
  11. Revision History:
  12. 4/14/1998 RahulTh
  13. Created this module.
  14. --*/
  15. #include "precomp.hxx"
  16. //
  17. //mapping between help ids and controls ids for this dialog
  18. //
  19. const DWORD g_aHelpIDMap_IDD_SECPATH[] =
  20. {
  21. IDC_SECPATH_ICON, IDH_DISABLEHELP,
  22. IDC_SECPATH_DESC, IDH_DISABLEHELP,
  23. IDC_SECPATH_SECGROUP, IDH_DISABLEHELP,
  24. IDC_EDIT_SECGROUP, IDH_EDIT_SECGROUP,
  25. IDC_BROWSE_SECGROUP, IDH_BROWSE_SECGROUP,
  26. IDC_SECPATH_TARGET, IDH_DISABLEHELP,
  27. 0, 0
  28. };
  29. ///////////////////////////
  30. /// Construction
  31. CSecGroupPath::CSecGroupPath (CWnd * pParent,
  32. UINT cookie,
  33. LPCTSTR szFolderName,
  34. LPCTSTR szGroupName /*=NULL*/,
  35. LPCTSTR szGroupSidStr /*=NULL*/,
  36. LPCTSTR szTarget /*= NULL*/)
  37. : CDialog(CSecGroupPath::IDD, pParent), m_redirPath (cookie), m_cookie (cookie)
  38. {
  39. m_szFolderName = szFolderName;
  40. m_szGroup = szGroupName;
  41. m_szSidStr = szGroupSidStr;
  42. m_szTarget = szTarget;
  43. if (! m_szTarget.IsEmpty())
  44. {
  45. m_szTarget.TrimLeft();
  46. m_szTarget.TrimRight();
  47. m_szTarget.TrimRight(L'\\');
  48. }
  49. m_bPathValid = FALSE;
  50. m_iCurrType = -1;
  51. }
  52. /////////////////////////
  53. ///Overrides
  54. void CSecGroupPath::DoDataExchange (CDataExchange* pDX)
  55. {
  56. CDialog::DoDataExchange(pDX);
  57. //{{AFX_DATA_MAP(CSecGroupPath)
  58. DDX_Control(pDX, IDC_EDIT_SECGROUP, m_EditSecGroup);
  59. DDX_Control(pDX, IDC_BROWSE_SECGROUP, m_btnBrowseSecGroup);
  60. DDX_Control(pDX, IDC_SECPATH_PLACEHOLDER, m_placeHolder);
  61. //}}AFX_DATA_MAP
  62. }
  63. /////////////////////
  64. /// Message maps
  65. BEGIN_MESSAGE_MAP(CSecGroupPath, CDialog)
  66. //{{AFX_MSG_MAP(CSecGroupPath)
  67. ON_BN_CLICKED (IDC_BROWSE_SECGROUP, OnBrowseGroups)
  68. ON_EN_UPDATE (IDC_EDIT_SECGROUP, OnSecGroupUpdate)
  69. ON_EN_KILLFOCUS (IDC_EDIT_SECGROUP, OnSecGroupKillFocus)
  70. ON_MESSAGE (WM_PATH_TWEAKED, OnPathTweak)
  71. ON_MESSAGE (WM_HELP, OnHelp)
  72. ON_MESSAGE (WM_CONTEXTMENU, OnContextMenu)
  73. //}AFX_MSG_MAP
  74. END_MESSAGE_MAP()
  75. BOOL CSecGroupPath::OnInitDialog ()
  76. {
  77. CError error (this);
  78. CDialog::OnInitDialog();
  79. //
  80. // Make sure that the supplied path is parseable into one of the known
  81. // types
  82. //
  83. if (! m_szTarget.IsEmpty())
  84. m_redirPath.Load ((LPCTSTR) m_szTarget); // This will always succeed if m_szTarget is not empty
  85. m_pathChooser.Instantiate (m_cookie,
  86. this,
  87. &m_placeHolder,
  88. (const CRedirPath *) &m_redirPath,
  89. SWP_SHOWWINDOW
  90. );
  91. m_EditSecGroup.SetWindowText (m_szGroup);
  92. m_EditSecGroup.SetSel (0, -1, FALSE);
  93. m_EditSecGroup.SetFocus();
  94. SetOKState();
  95. return FALSE; //returning FALSE since we are setting the focus to the edit box
  96. }
  97. void CSecGroupPath::OnOK ()
  98. {
  99. CError error(this);
  100. CString szRoot;
  101. CString szSuffix;
  102. CRedirPath newPath (m_cookie);
  103. BOOL bStatus = TRUE;
  104. UINT pathType;
  105. //first check if we have a valid group.
  106. OnSecGroupKillFocus();
  107. //if the target is not a UNC path, try to convert it to one.
  108. m_pathChooser.OnRootKillFocus();
  109. if (!m_fValidSid)
  110. {
  111. error.ShowMessage (IDS_NOSECURITY_INFO);
  112. return;
  113. }
  114. m_EditSecGroup.GetWindowText (m_szGroup);
  115. m_szGroup.TrimLeft();
  116. m_szGroup.TrimRight();
  117. m_szSidStr.TrimLeft();
  118. m_szSidStr.TrimRight();
  119. m_szSidStr.MakeLower();
  120. m_pathChooser.GetRoot (szRoot);
  121. pathType = m_pathChooser.GetType();
  122. bStatus = TRUE;
  123. if (m_redirPath.IsPathDifferent (pathType, (LPCTSTR)szRoot))
  124. {
  125. // The path has changed, so use the new suffix
  126. newPath.GenerateSuffix (szSuffix, m_cookie, pathType);
  127. bStatus = newPath.Load (pathType, (LPCTSTR) szRoot, (LPCTSTR) szSuffix);
  128. if (bStatus)
  129. newPath.GeneratePath (m_szTarget);
  130. }
  131. else
  132. {
  133. m_redirPath.GeneratePath (m_szTarget);
  134. }
  135. //check if all the data has been provided.
  136. if (! bStatus ||
  137. m_szTarget == TEXT("*") || //this particular check is very important -- see code for CFileInfo::LoadSection to see why
  138. m_szGroup.IsEmpty())
  139. {
  140. error.ShowMessage (IDS_INVALID_GROUPPATH);
  141. }
  142. else if (pathType != IDS_USERPROFILE_PATH &&
  143. ! PathIsUNC ((LPCTSTR) m_szTarget)
  144. )
  145. {
  146. error.SetStyle (MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2);
  147. error.SetTitle (IDS_DEFAULT_WARNING_TITLE);
  148. if (IDYES == error.ShowMessage (IDS_PATHNOTUNC_WARNING))
  149. {
  150. CDialog::OnOK();
  151. }
  152. }
  153. else
  154. {
  155. CDialog::OnOK();
  156. }
  157. }
  158. void
  159. CSecGroupPath::OnCancel (void)
  160. {
  161. m_pathChooser.OnCancel();
  162. CDialog::OnCancel();
  163. }
  164. //browse the security groups
  165. void CSecGroupPath::OnBrowseGroups ()
  166. {
  167. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  168. CError error(this);
  169. PCWSTR apwszAttribs[] =
  170. {
  171. L"ObjectSid"
  172. };
  173. DWORD dwError = ERROR_SUCCESS;
  174. HRESULT hr;
  175. IDsObjectPicker * pDsObjectPicker = NULL;
  176. DSOP_INIT_INFO InitInfo;
  177. const ULONG cbNumScopes = 3;
  178. DSOP_SCOPE_INIT_INFO ascopes[cbNumScopes];
  179. IDataObject * pdo = NULL;
  180. STGMEDIUM stgmedium = {
  181. TYMED_HGLOBAL,
  182. NULL
  183. };
  184. UINT cf = 0;
  185. PDS_SELECTION_LIST pDsSelList = NULL;
  186. FORMATETC formatetc = {
  187. (CLIPFORMAT)cf,
  188. NULL,
  189. DVASPECT_CONTENT,
  190. -1,
  191. TYMED_HGLOBAL
  192. };
  193. PDS_SELECTION pDsSelection = NULL;
  194. BOOL bAllocatedStgMedium = FALSE;
  195. SAFEARRAY * pVariantArr = NULL;
  196. PSID pSid = NULL;
  197. CString szDomain;
  198. CString szAcct;
  199. SID_NAME_USE eUse;
  200. hr = CoInitialize (NULL);
  201. if (SUCCEEDED (hr))
  202. {
  203. hr = CoCreateInstance (CLSID_DsObjectPicker,
  204. NULL,
  205. CLSCTX_INPROC_SERVER,
  206. IID_IDsObjectPicker,
  207. (void **) & pDsObjectPicker
  208. );
  209. }
  210. if (FAILED(hr))
  211. {
  212. dwError = IDS_OBJPICK_ERROR;
  213. goto BrwsGrp_Err;
  214. }
  215. //Initialize the scopes
  216. ZeroMemory (ascopes, cbNumScopes * sizeof (DSOP_SCOPE_INIT_INFO));
  217. ascopes[0].cbSize = sizeof (DSOP_SCOPE_INIT_INFO);
  218. ascopes[0].flType = DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN;
  219. ascopes[0].flScope = DSOP_SCOPE_FLAG_STARTING_SCOPE;
  220. ascopes[0].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_BUILTIN_GROUPS |
  221. DSOP_FILTER_UNIVERSAL_GROUPS_DL |
  222. DSOP_FILTER_UNIVERSAL_GROUPS_SE |
  223. DSOP_FILTER_GLOBAL_GROUPS_DL |
  224. DSOP_FILTER_GLOBAL_GROUPS_SE;
  225. ascopes[0].FilterFlags.Uplevel.flNativeModeOnly =
  226. DSOP_FILTER_DOMAIN_LOCAL_GROUPS_DL |
  227. DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE;
  228. ascopes[1].cbSize = sizeof (DSOP_SCOPE_INIT_INFO);
  229. ascopes[1].flType = DSOP_SCOPE_TYPE_GLOBAL_CATALOG;
  230. ascopes[1].FilterFlags.Uplevel.flBothModes =
  231. ascopes[0].FilterFlags.Uplevel.flBothModes;
  232. ascopes[1].FilterFlags.Uplevel.flNativeModeOnly =
  233. ascopes[0].FilterFlags.Uplevel.flNativeModeOnly;
  234. ascopes[2].cbSize = sizeof (DSOP_SCOPE_INIT_INFO);
  235. ascopes[2].flType = DSOP_SCOPE_TYPE_TARGET_COMPUTER;
  236. ascopes[2].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_LOCAL_GROUPS |
  237. DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS;
  238. //Populate the InitInfo structure that is used to initialize the object
  239. //picker.
  240. ZeroMemory (&InitInfo, sizeof (InitInfo));
  241. InitInfo.cbSize = sizeof (InitInfo);
  242. InitInfo.cDsScopeInfos = cbNumScopes;
  243. InitInfo.aDsScopeInfos = ascopes;
  244. InitInfo.cAttributesToFetch = 1;
  245. InitInfo.apwzAttributeNames = apwszAttribs;
  246. hr = pDsObjectPicker->Initialize (&InitInfo);
  247. if (FAILED (hr))
  248. {
  249. dwError = IDS_OBJPICK_ERROR;
  250. goto BrwsGrp_Err;
  251. }
  252. hr = pDsObjectPicker->InvokeDialog (this->m_hWnd, &pdo);
  253. if (FAILED(hr))
  254. {
  255. dwError = IDS_OBJPICK_ERROR;
  256. goto BrwsGrp_Err;
  257. }
  258. if (S_FALSE == hr) //the user hit cancel
  259. goto BrwsGrp_CleanupAndQuit;
  260. //if we are here, the user chose, OK, so find out what group was chosen
  261. cf = RegisterClipboardFormat (CFSTR_DSOP_DS_SELECTION_LIST);
  262. if (0 == cf)
  263. {
  264. dwError = IDS_NOSECURITY_INFO;
  265. goto BrwsGrp_Err;
  266. }
  267. //set the clipformat for the formatetc structure
  268. formatetc.cfFormat = (CLIPFORMAT)cf;
  269. hr = pdo->GetData (&formatetc, &stgmedium);
  270. if (FAILED (hr) )
  271. {
  272. dwError = IDS_NOSECURITY_INFO;
  273. goto BrwsGrp_Err;
  274. }
  275. bAllocatedStgMedium = TRUE;
  276. pDsSelList = (PDS_SELECTION_LIST) GlobalLock (stgmedium.hGlobal);
  277. if (NULL == pDsSelList)
  278. {
  279. dwError = IDS_NOSECURITY_INFO;
  280. goto BrwsGrp_Err;
  281. }
  282. if (!pDsSelList->cItems) //some item must have been selected
  283. {
  284. dwError = IDS_NOSECURITY_INFO;
  285. goto BrwsGrp_Err;
  286. }
  287. pDsSelection = &(pDsSelList->aDsSelection[0]);
  288. //we must get the ObjectSid attribute, otherwise we fail
  289. //so make sure that the attribute has been fetched.
  290. if (!pDsSelList->cFetchedAttributes ||
  291. (! (VT_ARRAY & pDsSelection->pvarFetchedAttributes->vt)))
  292. {
  293. dwError = IDS_NOSECURITY_INFO;
  294. goto BrwsGrp_Err;
  295. }
  296. pVariantArr = pDsSelection->pvarFetchedAttributes->parray;
  297. pSid = (PSID) pVariantArr->pvData;
  298. if (STATUS_SUCCESS != GetFriendlyNameFromSid (pSid, szDomain, szAcct, &eUse))
  299. {
  300. dwError = IDS_NOSECURITY_INFO;
  301. goto BrwsGrp_Err;
  302. }
  303. //store away the string representation of this sid
  304. if (STATUS_SUCCESS != GetStringFromSid(pSid, m_szSidStr))
  305. goto BrwsGrp_Err;
  306. m_szSidStr.MakeLower();
  307. if (!szDomain.IsEmpty())
  308. szAcct = szDomain + '\\' + szAcct;
  309. m_EditSecGroup.SetWindowText (szAcct);
  310. m_fValidSid = TRUE;
  311. goto BrwsGrp_CleanupAndQuit;
  312. BrwsGrp_Err:
  313. error.ShowMessage (dwError);
  314. BrwsGrp_CleanupAndQuit:
  315. if (pDsSelList)
  316. GlobalUnlock (stgmedium.hGlobal);
  317. if (bAllocatedStgMedium)
  318. ReleaseStgMedium (&stgmedium);
  319. if (pdo)
  320. pdo->Release();
  321. if (pDsObjectPicker)
  322. pDsObjectPicker->Release ();
  323. }
  324. void CSecGroupPath::SetOKState (void)
  325. {
  326. CString szGroup;
  327. CString szPath;
  328. BOOL bCheckPath = FALSE;
  329. m_EditSecGroup.GetWindowText(szGroup);
  330. szGroup.TrimLeft();
  331. szGroup.TrimRight();
  332. if (IDS_SPECIFIC_PATH == m_iCurrType ||
  333. IDS_PERUSER_PATH == m_iCurrType)
  334. {
  335. bCheckPath = TRUE;
  336. m_pathChooser.GetRoot (szPath);
  337. szPath.TrimLeft();
  338. szPath.TrimRight();
  339. szPath.TrimRight(L'\\');
  340. }
  341. if (szGroup.IsEmpty() || (bCheckPath && szPath.IsEmpty()))
  342. GetDescendantWindow(IDOK, FALSE)->EnableWindow(FALSE);
  343. else
  344. GetDescendantWindow(IDOK, FALSE)->EnableWindow(TRUE);
  345. }
  346. void CSecGroupPath::OnSecGroupUpdate()
  347. {
  348. //the group in the edit box is about to change.
  349. //this means we can no longer trust the sid that we may have
  350. m_fValidSid = FALSE;
  351. SetOKState();
  352. }
  353. //we try to get a sid and domain for the group specified
  354. //if we can't, we simply ignore the error and sit tight.
  355. void CSecGroupPath::OnSecGroupKillFocus()
  356. {
  357. BOOL bStatus;
  358. CString szGroup;
  359. WCHAR* szWindowText = NULL;
  360. WCHAR szDom[MAX_PATH];
  361. DWORD dwDomLen = MAX_PATH;
  362. WCHAR* szAcct;
  363. PSID Sid = NULL;
  364. DWORD dwSidLen = 0;
  365. SID_NAME_USE eUse;
  366. DWORD Status;
  367. CHourglass hourglass; //LookupAccountName takes a while
  368. BOOL fDomainSupplied = FALSE;
  369. //if we already have a valid sid, there is nothing to worry.
  370. if (m_fValidSid)
  371. goto KillFocusEnd;
  372. //we don't have a valid sid, so we try to get one from the data in the
  373. //group box
  374. m_EditSecGroup.GetWindowText (szGroup);
  375. szGroup.TrimLeft();
  376. szGroup.TrimRight();
  377. if (szGroup.IsEmpty())
  378. goto KillFocusEnd;
  379. ULONG ulNoChars;
  380. ulNoChars = wcslen( (LPCWSTR)szGroup )+1;
  381. szWindowText = new WCHAR[ulNoChars];
  382. if ( szWindowText == NULL )
  383. {
  384. goto KillFocusEnd;
  385. }
  386. //get the account name from the window
  387. HRESULT hr;
  388. hr = StringCchCopy (szWindowText, ulNoChars, (LPCWSTR) szGroup);
  389. ASSERT(SUCCEEDED(hr));
  390. szAcct = wcsrchr (szWindowText, '\\');
  391. if (!szAcct)
  392. {
  393. szAcct = szWindowText;
  394. }
  395. else
  396. {
  397. *szAcct++ = 0; //advance it so that it now points to the account
  398. //and szWindowText will now refer to the supplied domain
  399. fDomainSupplied = TRUE;
  400. }
  401. do
  402. {
  403. bStatus = LookupAccountName (NULL, szAcct, Sid, &dwSidLen,
  404. szDom, &dwDomLen, &eUse);
  405. if (!bStatus)
  406. {
  407. Status = GetLastError();
  408. if (ERROR_INSUFFICIENT_BUFFER != Status)
  409. goto KillFocusEnd; //we just ignore the error for now
  410. LocalFree(Sid);
  411. Sid = (PSID) LocalAlloc (LPTR, dwSidLen);
  412. if (NULL == Sid)
  413. goto KillFocusEnd; //we just ignore the error for now
  414. continue;
  415. }
  416. break;
  417. } while (1);
  418. //we have the sid if we are here
  419. //make sure it represents a group
  420. switch (eUse)
  421. {
  422. case SidTypeGroup:
  423. case SidTypeWellKnownGroup:
  424. case SidTypeAlias:
  425. break;
  426. default:
  427. goto KillFocusEnd;
  428. }
  429. //also make sure that if a domain was supplied, it matches what we
  430. //got back
  431. if (fDomainSupplied && (0 != lstrcmpi (szWindowText, szDom)))
  432. goto KillFocusEnd;
  433. //if we are here, then we have the sid for a group
  434. if (STATUS_SUCCESS != GetStringFromSid (Sid, m_szSidStr))
  435. goto KillFocusEnd;
  436. //we were finally successful in getting the sid in a string format
  437. m_szSidStr.MakeLower();
  438. szGroup = szDom;
  439. if (!szGroup.IsEmpty())
  440. szGroup += '\\';
  441. szGroup += szAcct;
  442. m_EditSecGroup.SetWindowText ((LPCTSTR) szGroup);
  443. m_fValidSid = TRUE;
  444. KillFocusEnd:
  445. LocalFree(Sid);
  446. if ( szWindowText != NULL )
  447. {
  448. delete [] szWindowText;
  449. }
  450. return;
  451. }
  452. void CSecGroupPath::OnPathTweak (WPARAM wParam, LPARAM lParam)
  453. {
  454. m_bPathValid = (BOOL) wParam;
  455. m_iCurrType = (LONG) lParam;
  456. SetOKState();
  457. }
  458. LONG CSecGroupPath::OnHelp (WPARAM wParam, LPARAM lParam)
  459. {
  460. LONG lResult = 0;
  461. CString szHelpFile;
  462. szHelpFile.LoadString(IDS_HELP_FILE);
  463. ::WinHelp((HWND)(((LPHELPINFO)lParam)->hItemHandle),
  464. (LPCTSTR) szHelpFile,
  465. HELP_WM_HELP,
  466. (ULONG_PTR)(LPTSTR)g_aHelpIDMap_IDD_SECPATH);
  467. return lResult;
  468. }
  469. LONG CSecGroupPath::OnContextMenu (WPARAM wParam, LPARAM lParam)
  470. {
  471. AFX_MANAGE_STATE (AfxGetStaticModuleState());
  472. LONG lResult = 0;
  473. CString szHelpFile;
  474. szHelpFile.LoadString(IDS_HELP_FILE);
  475. ::WinHelp((HWND)wParam,
  476. (LPCTSTR)szHelpFile,
  477. HELP_CONTEXTMENU,
  478. (ULONG_PTR)(LPVOID)g_aHelpIDMap_IDD_SECPATH);
  479. return lResult;
  480. }