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.

614 lines
18 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation 1996-2001.
  5. //
  6. // File: uithread.cpp
  7. //
  8. // Contents: implementation of CUIThread
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. #include "wsecmgr.h"
  13. #include "resource.h"
  14. #include <accctrl.h>
  15. #include "servperm.h"
  16. #include "stdafx.h"
  17. #include "wsecmgr.h"
  18. #include "snapmgr.h"
  19. #include "util.h"
  20. #include "UIThread.h"
  21. #include "attr.h"
  22. #include "aaudit.h"
  23. #include "aenable.h"
  24. #include "AMember.h"
  25. #include "anumber.h"
  26. #include "AObject.h"
  27. #include "ARet.h"
  28. #include "ARight.h"
  29. #include "aservice.h"
  30. #include "astring.h"
  31. #include "CAudit.h"
  32. #include "CEnable.h"
  33. #include "CGroup.h"
  34. #include "CName.h"
  35. #include "CNumber.h"
  36. #include "cobject.h"
  37. #include "CPrivs.h"
  38. #include "CRet.h"
  39. #include "cservice.h"
  40. #include "regvldlg.h"
  41. #include "perfanal.h"
  42. #include "applcnfg.h"
  43. #include "wrapper.h"
  44. #include "locdesc.h"
  45. #include "profdesc.h"
  46. #include "newprof.h"
  47. #include "laudit.h"
  48. #include "lenable.h"
  49. #include "lret.h"
  50. #include "lnumber.h"
  51. #include "lstring.h"
  52. #include "lright.h"
  53. #include "achoice.h"
  54. #include "cchoice.h"
  55. #include "lchoice.h"
  56. #include "dattrs.h"
  57. #include "lflags.h"
  58. #include "aflags.h"
  59. #include "multisz.h"
  60. #ifdef _DEBUG
  61. #define new DEBUG_NEW
  62. #undef THIS_FILE
  63. static char THIS_FILE[] = __FILE__;
  64. #endif
  65. /////////////////////////////////////////////////////////////////////////////
  66. // CUIThread
  67. IMPLEMENT_DYNCREATE(CUIThread, CWinThread)
  68. CUIThread::CUIThread()
  69. {
  70. }
  71. CUIThread::~CUIThread()
  72. {
  73. }
  74. BOOL CUIThread::InitInstance()
  75. {
  76. // TODO: perform and per-thread initialization here
  77. return TRUE;
  78. }
  79. int CUIThread::ExitInstance()
  80. {
  81. // TODO: perform any per-thread cleanup here
  82. return CWinThread::ExitInstance();
  83. }
  84. BEGIN_MESSAGE_MAP(CUIThread, CWinThread)
  85. //{{AFX_MSG_MAP(CUIThread)
  86. // NOTE - the ClassWizard will add and remove mapping macros here.
  87. //}}AFX_MSG_MAP
  88. ON_THREAD_MESSAGE( SCEM_APPLY_PROFILE, OnApplyProfile)
  89. ON_THREAD_MESSAGE( SCEM_ANALYZE_PROFILE, OnAnalyzeProfile)
  90. ON_THREAD_MESSAGE( SCEM_DESCRIBE_PROFILE, OnDescribeProfile)
  91. ON_THREAD_MESSAGE( SCEM_DESCRIBE_LOCATION, OnDescribeLocation)
  92. ON_THREAD_MESSAGE( SCEM_DESTROY_DIALOG, OnDestroyDialog)
  93. ON_THREAD_MESSAGE( SCEM_NEW_CONFIGURATION, OnNewConfiguration)
  94. ON_THREAD_MESSAGE( SCEM_ADD_PROPSHEET, OnAddPropSheet)
  95. END_MESSAGE_MAP()
  96. /////////////////////////////////////////////////////////////////////////////
  97. // CUIThread message handlers
  98. //+--------------------------------------------------------------------------
  99. //
  100. // Method: DefaultLogFile
  101. //
  102. // Synopsis: Find the default log file for the inf file last applied
  103. // pass back the log file via the out parameter strLogFile
  104. //
  105. //---------------------------------------------------------------------------
  106. void
  107. CUIThread::DefaultLogFile(CComponentDataImpl *pCDI,GWD_TYPES LogID,LPCTSTR szBase, CString& strLogFile)
  108. {
  109. //
  110. // Base log file on the db passed in
  111. //
  112. CString strDefExt;
  113. strDefExt.LoadString(IDS_LOGFILE_DEF_EXT);
  114. // make sure that the extension includes '.'
  115. if (strDefExt.GetLength() > 0 && strDefExt[0] != L'.')
  116. {
  117. CString tempExt = strDefExt;
  118. strDefExt = L'.';
  119. strDefExt += tempExt;
  120. }
  121. CString strInfFile = szBase;
  122. //
  123. // Get the default working directory
  124. //
  125. LPTSTR szDir = NULL;
  126. if (pCDI->GetWorkingDir(LogID,
  127. &szDir,
  128. FALSE,
  129. FALSE)) {
  130. strLogFile = szDir;
  131. LocalFree(szDir);
  132. szDir = NULL;
  133. }
  134. if (strLogFile.Right(1) != TEXT("\\")) {
  135. strLogFile += L"\\";
  136. }
  137. if ( strInfFile.GetLength() < 5) {
  138. //
  139. // The default log file.
  140. //
  141. strLogFile += TEXT("SceStus") + strDefExt;
  142. } else {
  143. int nFilePartIndex = 0;
  144. int nFilePartCount = 0;
  145. //
  146. // +1 to change index base from 0 to 1 for the Mid
  147. //
  148. nFilePartIndex = strInfFile.ReverseFind(L'\\') +1;
  149. nFilePartCount = strInfFile.ReverseFind(L'.') - nFilePartIndex;
  150. strLogFile += strInfFile.Mid(nFilePartIndex,nFilePartCount) + strDefExt;
  151. }
  152. }
  153. //+--------------------------------------------------------------------------
  154. //
  155. // Method: OnApplyProfile
  156. //
  157. // Synopsis: Create and display a dialog for applying a profile to the
  158. // system
  159. //
  160. // Arguments: [uParam] - A string with the name of the database to assign to
  161. // [lParam] - A pointer to the CComponentDataImpl
  162. //
  163. //---------------------------------------------------------------------------
  164. void
  165. CUIThread::OnApplyProfile(WPARAM uParam, LPARAM lParam) {
  166. CComponentDataImpl *pCDI = NULL;
  167. CApplyConfiguration *pAP = NULL;
  168. CWnd cwndParent;
  169. pCDI = reinterpret_cast<CComponentDataImpl*>(lParam);
  170. //
  171. // Look for a preexisting version of this dialog in pCDI's cache.
  172. // If it's not there then create a new one and add it.
  173. //
  174. pAP = (CApplyConfiguration *)pCDI->GetPopupDialog(IDM_APPLY);
  175. if (NULL == pAP) {
  176. pAP = new CApplyConfiguration;
  177. if (NULL == pAP) {
  178. return;
  179. }
  180. pCDI->AddPopupDialog(IDM_APPLY,pAP);
  181. }
  182. pAP->m_strDataBase = reinterpret_cast<LPCTSTR>(uParam);
  183. DefaultLogFile(pCDI,GWD_CONFIGURE_LOG, pAP->m_strDataBase, pAP->m_strLogFile);
  184. pAP->SetComponentData(pCDI);
  185. if (!pAP->GetSafeHwnd())
  186. {
  187. cwndParent.Attach(pCDI->GetParentWindow());
  188. CThemeContextActivator activator;
  189. pAP->Create(IDD_APPLY_CONFIGURATION,&cwndParent);
  190. cwndParent.Detach();
  191. }
  192. pAP->UpdateData(FALSE);
  193. pAP->BringWindowToTop();
  194. pAP->ShowWindow(SW_SHOWNORMAL);
  195. }
  196. //+--------------------------------------------------------------------------
  197. //
  198. // Method: OnAnalyzeProfile
  199. //
  200. // Synopsis: Create and display a dialog for applying a profile to the
  201. // system
  202. //
  203. // Arguments: [uParam] - A string with the name of the database to assign to
  204. // [lParam] - A pointer to the CComponentDataImpl
  205. //
  206. //---------------------------------------------------------------------------
  207. void
  208. CUIThread::OnAnalyzeProfile(WPARAM uParam, LPARAM lParam) {
  209. CComponentDataImpl *pCDI = NULL;
  210. CPerformAnalysis *pPA = NULL;
  211. CWnd cwndParent;
  212. pCDI = reinterpret_cast<CComponentDataImpl*>(lParam);
  213. //
  214. // Look for a preexisting version of this dialog in pCDI's cache.
  215. // If it's not there then create a new one and add it.
  216. //
  217. pPA = (CPerformAnalysis *)pCDI->GetPopupDialog(IDM_ANALYZE);
  218. if (NULL == pPA) {
  219. pPA = new CPerformAnalysis (0, 0);
  220. if (NULL == pPA) {
  221. return;
  222. }
  223. pPA->m_strDataBase = reinterpret_cast<LPCTSTR>(uParam);
  224. DefaultLogFile(pCDI,GWD_ANALYSIS_LOG, pPA->m_strDataBase, pPA->m_strLogFile);
  225. pPA->SetComponentData(pCDI);
  226. pCDI->AddPopupDialog(IDM_ANALYZE,pPA);
  227. }
  228. if (!pPA->GetSafeHwnd())
  229. {
  230. cwndParent.Attach(pCDI->GetParentWindow());
  231. CThemeContextActivator activator;
  232. pPA->Create(IDD_PERFORM_ANALYSIS,&cwndParent);
  233. cwndParent.Detach();
  234. }
  235. pPA->BringWindowToTop();
  236. pPA->ShowWindow(SW_SHOWNORMAL);
  237. }
  238. //+--------------------------------------------------------------------------
  239. //
  240. // Method: OnDescribeProfile
  241. //
  242. // Synopsis: Create and display a dialog for editing a profile's description
  243. //
  244. // Arguments: [uParam] - A pointer to the CFolder for the object
  245. // [lParam] - The CComponentDataImpl owning the scope pane
  246. //
  247. //---------------------------------------------------------------------------
  248. void
  249. CUIThread::OnDescribeProfile(WPARAM uParam, LPARAM lParam)
  250. {
  251. CSetProfileDescription *pSPD;
  252. CFolder *pFolder;
  253. CComponentDataImpl *pCDI;
  254. CWnd cwndParent;
  255. LPTSTR szDesc;
  256. pFolder = reinterpret_cast<CFolder*>(uParam);
  257. pCDI = reinterpret_cast<CComponentDataImpl*>(lParam);
  258. LONG_PTR dwKey = DLG_KEY(pFolder, CSetProfileDescription::IDD);
  259. //
  260. // Look for a preexisting version of this dialog in pCDI's cache.
  261. // If it's not there then create a new one and add it.
  262. //
  263. pSPD = (CSetProfileDescription *)pCDI->GetPopupDialog( dwKey );
  264. if (NULL == pSPD) {
  265. pSPD = new CSetProfileDescription;
  266. if (NULL == pSPD) {
  267. return;
  268. }
  269. pCDI->AddPopupDialog( dwKey, pSPD);
  270. }
  271. if (!pSPD->GetSafeHwnd())
  272. {
  273. if (GetProfileDescription(pFolder->GetInfFile(),&szDesc))
  274. pSPD->m_strDesc = szDesc;
  275. pSPD->Initialize(pFolder,pCDI);
  276. cwndParent.Attach(pCDI->GetParentWindow());
  277. CThemeContextActivator activator;
  278. pSPD->Create(IDD_SET_DESCRIPTION,&cwndParent);
  279. cwndParent.Detach();
  280. }
  281. pSPD->UpdateData(FALSE);
  282. pSPD->BringWindowToTop();
  283. pSPD->ShowWindow(SW_SHOWNORMAL);
  284. }
  285. //+--------------------------------------------------------------------------
  286. //
  287. // Method: OnDescribeLocation
  288. //
  289. // Synopsis: Create and display a dialog for editing a Location's description
  290. //
  291. // Arguments: [uParam] - A pointer to the CFolder for the object
  292. // [lParam] - The CComponentDataImpl owning the scope pane
  293. //
  294. //---------------------------------------------------------------------------
  295. void
  296. CUIThread::OnDescribeLocation(WPARAM uParam, LPARAM lParam) {
  297. CSetLocationDescription *pSPD;
  298. CFolder *pFolder;
  299. CComponentDataImpl *pCDI;
  300. CWnd cwndParent;
  301. LPTSTR szDesc;
  302. pFolder = reinterpret_cast<CFolder*>(uParam);
  303. pCDI = reinterpret_cast<CComponentDataImpl*>(lParam);
  304. LONG_PTR dwKey = DLG_KEY(pFolder, CSetLocationDescription::IDD);
  305. //
  306. // Look for a preexisting version of this dialog in pCDI's cache.
  307. // If it's not there then create a new one and add it.
  308. //
  309. pSPD = (CSetLocationDescription *)pCDI->GetPopupDialog( dwKey );
  310. if (NULL == pSPD) {
  311. pSPD = new CSetLocationDescription;
  312. if (NULL == pSPD) {
  313. return;
  314. }
  315. pCDI->AddPopupDialog(dwKey ,pSPD);
  316. }
  317. // pSPD->Initialize(pFolder,pCDI);
  318. if (!pSPD->GetSafeHwnd())
  319. {
  320. pSPD->Initialize(pFolder,pCDI);
  321. cwndParent.Attach(pCDI->GetParentWindow());
  322. CThemeContextActivator activator;
  323. pSPD->Create(IDD_SET_DESCRIPTION,&cwndParent);
  324. pSPD->SetWindowText(pFolder->GetName());
  325. cwndParent.Detach();
  326. }
  327. pSPD->UpdateData(FALSE);
  328. pSPD->BringWindowToTop();
  329. pSPD->ShowWindow(SW_SHOWNORMAL);
  330. }
  331. /*-----------------------------------------------------------------------------------
  332. Method: OnDestroyDialog
  333. Synopsis: Destroys and deletes the CAttribute object associated with [pDlg]
  334. Arguments: [pDlg] - Is a pointer to the object to delete.
  335. Histroy:
  336. -----------------------------------------------------------------------------------*/
  337. void CUIThread::OnDestroyDialog(WPARAM pDlg, LPARAM)
  338. {
  339. if(pDlg){
  340. CAttribute *pAttr = reinterpret_cast<CAttribute *>(pDlg);
  341. delete pAttr;
  342. }
  343. }
  344. //+--------------------------------------------------------------------------
  345. //
  346. // Method: OnNewConfiguration
  347. //
  348. // Synopsis: Create and display a dialog for adding a new configuration file
  349. //
  350. // Arguments: [uParam] - A pointer to the CFolder parent of the new config file
  351. // [lParam] - A pointer to the CComponentDataItem
  352. //
  353. //---------------------------------------------------------------------------
  354. void
  355. CUIThread::OnNewConfiguration(WPARAM uParam, LPARAM lParam)
  356. {
  357. CNewProfile *pNP;
  358. CFolder *pFolder;
  359. CComponentDataImpl *pCDI;
  360. CWnd cwndParent;
  361. LPTSTR szDesc;
  362. pFolder = reinterpret_cast<CFolder*>(uParam);
  363. pCDI = reinterpret_cast<CComponentDataImpl*>(lParam);
  364. LONG_PTR dwKey = DLG_KEY(pFolder, CNewProfile::IDD);
  365. //
  366. // Look for a preexisting version of this dialog in pCDI's cache.
  367. // If it's not there then create a new one and add it.
  368. //
  369. pNP = (CNewProfile *)pCDI->GetPopupDialog( dwKey);
  370. if (NULL == pNP) {
  371. pNP = new CNewProfile;
  372. if (NULL == pNP) {
  373. return;
  374. }
  375. pCDI->AddPopupDialog( dwKey, pNP);
  376. }
  377. // pNP->Initialize(pFolder,pCDI);
  378. if (!pNP->GetSafeHwnd()) {
  379. pNP->Initialize(pFolder,pCDI);
  380. cwndParent.Attach(pCDI->GetParentWindow());
  381. CThemeContextActivator activator;
  382. pNP->Create(IDD_NEW_PROFILE,&cwndParent);
  383. pNP->SetWindowText(pFolder->GetName());
  384. cwndParent.Detach();
  385. }
  386. pNP->UpdateData(FALSE);
  387. pNP->BringWindowToTop();
  388. pNP->ShowWindow(SW_SHOWNORMAL);
  389. }
  390. //+--------------------------------------------------------------------------
  391. // Method: OnAddPropsheet
  392. //
  393. // Synopsis: Adds a property sheet to the list of sheets to which to pass messages
  394. // in PreTranslateMessage
  395. //
  396. // Arguments: [wParam] - HWND of the added property sheet
  397. // [lParam] - unused
  398. //
  399. //---------------------------------------------------------------------------
  400. void CUIThread::OnAddPropSheet(WPARAM wParam, LPARAM lParam)
  401. {
  402. if (IsWindow((HWND)wParam)) {
  403. m_PSHwnds.AddHead((HWND)wParam);
  404. }
  405. }
  406. BOOL CUIThread::PreTranslateMessage(MSG* pMsg)
  407. {
  408. //
  409. // check PropSheet_GetCurrentPageHwnd to see if we need to destroy
  410. // one of our modeless property sheets
  411. //
  412. POSITION pos;
  413. POSITION posCur;
  414. HWND hwnd;
  415. pos= m_PSHwnds.GetHeadPosition();
  416. while (pos) {
  417. posCur = pos;
  418. hwnd = m_PSHwnds.GetNext(pos);
  419. if (!IsWindow(hwnd)) {
  420. m_PSHwnds.RemoveAt(posCur);
  421. } else if (NULL == PropSheet_GetCurrentPageHwnd(hwnd)) {
  422. //
  423. // hwnd is a closed property sheet. destroy it and remove it from the list
  424. //
  425. DestroyWindow(hwnd);
  426. m_PSHwnds.RemoveAt(posCur);
  427. }
  428. if (PropSheet_IsDialogMessage(hwnd,pMsg)) {
  429. //
  430. // Message has been handled, so don't do anything else with it
  431. //
  432. return TRUE;
  433. }
  434. }
  435. return CWinThread::PreTranslateMessage(pMsg);
  436. }
  437. /////////////////////////////////////////////////////////////////////////////
  438. // CModelessDlgUIThread implementation
  439. IMPLEMENT_DYNCREATE(CModelessDlgUIThread, CUIThread)
  440. //------------------------------------------------------------------------------
  441. //------------------------------------------------------------------------------
  442. CModelessDlgUIThread::CModelessDlgUIThread()
  443. {
  444. m_hReadyForMsg = ::CreateEvent(NULL, TRUE, FALSE, NULL); //This is a safe usage. It creates a unnamed event.
  445. }
  446. //------------------------------------------------------------------------------
  447. //------------------------------------------------------------------------------
  448. CModelessDlgUIThread::~CModelessDlgUIThread()
  449. {
  450. if (NULL != m_hReadyForMsg)
  451. ::CloseHandle(m_hReadyForMsg);
  452. }
  453. BEGIN_MESSAGE_MAP(CModelessDlgUIThread, CUIThread)
  454. //{{AFX_MSG_MAP(CModelessDlgUIThread)
  455. // NOTE - the ClassWizard will add and remove mapping macros here.
  456. //}}AFX_MSG_MAP
  457. ON_THREAD_MESSAGE( SCEM_CREATE_MODELESS_SHEET, OnCreateModelessSheet)
  458. ON_THREAD_MESSAGE( SCEM_DESTROY_WINDOW, OnDestroyWindow)
  459. END_MESSAGE_MAP()
  460. //------------------------------------------------------------------------------
  461. //------------------------------------------------------------------------------
  462. int CModelessDlgUIThread::Run()
  463. {
  464. if (m_hReadyForMsg)
  465. ::SetEvent(m_hReadyForMsg);
  466. return CWinThread::Run();
  467. }
  468. //------------------------------------------------------------------------------
  469. // wparam is PMLSHEET_DATA, and lparam is not used and can be used in the future
  470. // for telling what property sheet is to be created (right now, it only works
  471. // for ACL editor)
  472. //------------------------------------------------------------------------------
  473. void CModelessDlgUIThread::OnCreateModelessSheet(WPARAM wparam, LPARAM lparam)
  474. {
  475. PMLSHEET_DATA pSheetData = (PMLSHEET_DATA)wparam;
  476. if (pSheetData)
  477. {
  478. HWND hSheet = (HWND)MyCreateSecurityPage2(pSheetData->bIsContainer,
  479. pSheetData->ppSeDescriptor,
  480. pSheetData->pSeInfo,
  481. pSheetData->strObjectName,
  482. pSheetData->SeType,
  483. pSheetData->flag,
  484. pSheetData->hwndParent,
  485. TRUE);
  486. *(pSheetData->phwndSheet) = hSheet;
  487. OnAddPropSheet((WPARAM)hSheet, 0);
  488. }
  489. }
  490. //------------------------------------------------------------------------------
  491. // wparam is the window handle and lparam is not used at this time
  492. // Since destroying a window must happen on the thread where it is contructed,
  493. // this is necessary. Basic window management rules must be followed, e.g.,
  494. // don't ask this thread to destroy windows that is not created by it
  495. //------------------------------------------------------------------------------
  496. void CModelessDlgUIThread::OnDestroyWindow(WPARAM wparam, LPARAM lparam)
  497. {
  498. if (::IsWindow((HWND)wparam))
  499. {
  500. DestroyWindow((HWND)wparam);
  501. }
  502. }
  503. //------------------------------------------------------------------------------
  504. // immediately after this thread object is created, creating thread needs to
  505. // wait by calling this function so that the newly created thread has a chance
  506. // to be scheduled to run.
  507. //------------------------------------------------------------------------------
  508. void CModelessDlgUIThread::WaitTillRun()
  509. {
  510. if (NULL != m_hReadyForMsg)
  511. {
  512. // $UNDONE:shawnwu I found that MMC runs at THREAD_PRIORITY_ABOVE_NORMAL (or higher) priority
  513. // becaues only when I run this UI thread at THREAD_PRIORITY_HIGHEST will this thread schedule to run.
  514. // But running at that level of priority makes me feel a little bit nervous. I thus
  515. // leave this sleep(10) code here. Up to the UI team to decide.
  516. ::Sleep(10);
  517. ::WaitForSingleObject(m_hReadyForMsg, INFINITE); // don't care about result of this waiting
  518. // now the event is useless. To reduce resource overhead, close the handle
  519. ::CloseHandle(m_hReadyForMsg);
  520. m_hReadyForMsg = NULL;
  521. }
  522. }