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.

869 lines
27 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation 1996-2001.
  5. //
  6. // File: regdlg.cpp
  7. //
  8. // Contents: implementation of CRegistryDialog
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. #include "wsecmgr.h"
  13. #include "resource.h"
  14. #include "util.h"
  15. #include "servperm.h"
  16. #include "addobj.h"
  17. #include "RegDlg.h"
  18. #include <accctrl.h>
  19. #include <aclapi.h>
  20. #ifdef _DEBUG
  21. #define new DEBUG_NEW
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25. /////////////////////////////////////////////////////////////////////////////
  26. // CRegistryDialog dialog
  27. CRegistryDialog::CRegistryDialog()
  28. : CHelpDialog(a177HelpIDs, IDD, 0)
  29. {
  30. //{{AFX_DATA_INIT(CRegistryDialog)
  31. m_strReg = _T("");
  32. //}}AFX_DATA_INIT
  33. m_pConsole = NULL;
  34. m_pTemplate = NULL;
  35. m_dbHandle = NULL;
  36. m_cookie = 0;
  37. m_pIl = NULL;
  38. m_pDataObj = NULL;
  39. m_bNoUpdate = FALSE;
  40. }
  41. void CRegistryDialog::DoDataExchange(CDataExchange* pDX)
  42. {
  43. CDialog::DoDataExchange(pDX);
  44. //{{AFX_DATA_MAP(CRegistryDialog)
  45. DDX_Control(pDX, IDC_REGTREE, m_tcReg);
  46. DDX_Text(pDX, IDC_REGKEY, m_strReg);
  47. //}}AFX_DATA_MAP
  48. }
  49. /*-------------------------------------------------------------------------------------------
  50. Method: CreateKeyInfo
  51. Synopsis: Create a new TI_KEYINFO structure and optionaly set its members
  52. Arguments: [hKey] - Optional value to set the hKey member of TI_KEYINFO
  53. default is zero
  54. [Enum] - Optional value to set the Enum member of TI_KEYINFO
  55. default is zero
  56. Returns: a LPTI_KEYINFO pointer
  57. ---------------------------------------------------------------------------------------------*/
  58. LPTI_KEYINFO CRegistryDialog::CreateKeyInfo(HKEY hKey, bool Enum)
  59. {
  60. LPTI_KEYINFO pInfo = NULL;
  61. pInfo = new TI_KEYINFO;
  62. if(pInfo){
  63. pInfo->hKey = hKey;
  64. pInfo->Enum = Enum;
  65. }
  66. return pInfo;
  67. }
  68. /*-------------------------------------------------------------------------------------------
  69. Method: IsValidRegPath
  70. Synopsis: Returns true if strReg path. We can't assume that this
  71. HKEY exists in the current registry. We will only make
  72. sure that the root node exists and each string in
  73. between '\'s isn't blank.
  74. Arguments: [strReg] - A string represending a registry path
  75. subkeys are seperated by '\'s
  76. Returns: TRUE if strReg is a valid path.
  77. ---------------------------------------------------------------------------------------------*/
  78. BOOL CRegistryDialog::IsValidRegPath(LPCTSTR strReg)
  79. {
  80. ASSERT(this);
  81. ASSERT(m_tcReg);
  82. if(!strReg) return FALSE;
  83. int iStr = 0; // Current position in strReg
  84. CString strCheck; // String to check
  85. LPTI_KEYINFO pkInfo; // Tree item key info.
  86. //
  87. // Find which root node this registry value is in.
  88. //
  89. while(strReg[iStr] && strReg[iStr] != _T('\\')) iStr++;
  90. strCheck = strReg;
  91. strCheck = strCheck.Left(iStr);
  92. strCheck.MakeUpper();
  93. // Get the HKEY value from the tree ctrl
  94. HTREEITEM hTi = m_tcReg.GetRootItem();
  95. while(hTi){
  96. if(m_tcReg.GetItemText(hTi) == strCheck)
  97. break;
  98. hTi = m_tcReg.GetNextItem(hTi, TVGN_NEXT);
  99. }
  100. if(hTi == NULL) return FALSE;
  101. // Get TI_KEYINFO for this root node
  102. pkInfo = (LPTI_KEYINFO)m_tcReg.GetItemData(hTi);
  103. // This value should never be NULL.
  104. if(!pkInfo){
  105. TRACE(TEXT("Tree item TI_KEYINFO is NULL for root node '%s'"), (LPCTSTR)strCheck);
  106. return FALSE;
  107. }
  108. //
  109. // Check the rest of the string to make sure that string's
  110. // in between '\'s aren't blank
  111. //
  112. while(strReg[iStr]){
  113. // Check to make sure that the string item before
  114. // and after the '\' aren't spaces.
  115. if(strReg[iStr] == _T('\\')){
  116. if( strReg[iStr + 1] == _T(' ') ||
  117. strReg[iStr + 1] == _T('\t') ||
  118. //strReg[iStr + 1] == 0 ||
  119. iStr > 0 &&
  120. (
  121. strReg[iStr - 1] == _T(' ') ||
  122. strReg[iStr - 1] == _T('\t')
  123. )
  124. )
  125. return FALSE;
  126. }
  127. iStr++;
  128. }
  129. return TRUE;
  130. }
  131. /*-------------------------------------------------------------------------------------------
  132. Method: MakePathVisible
  133. Synopsis:
  134. Arguments: [strReg] - A string represending a registry path
  135. subkeys are seperated by '\'s
  136. Returns: TRUE if strReg is a valid path.
  137. ---------------------------------------------------------------------------------------------*/
  138. void CRegistryDialog::MakePathVisible(LPCTSTR strReg)
  139. {
  140. ASSERT(this);
  141. ASSERT(m_tcReg);
  142. if(!strReg) return;
  143. int iStr = 0; // Current position in strReg
  144. CString strCheck; // String to check
  145. LPTI_KEYINFO pkInfo; // Tree item key info.
  146. //
  147. // Find which root node this registry value is in.
  148. //
  149. while(strReg[iStr] && strReg[iStr] != _T('\\')) iStr++;
  150. strCheck = strReg;
  151. strCheck = strCheck.Left(iStr);
  152. strCheck.MakeUpper();
  153. // Get the HKEY value from the tree ctrl
  154. HTREEITEM hTi = m_tcReg.GetRootItem();
  155. while(hTi){
  156. if(m_tcReg.GetItemText(hTi) == strCheck)
  157. break;
  158. hTi = m_tcReg.GetNextItem(hTi, TVGN_NEXT);
  159. }
  160. if(hTi == NULL) return;
  161. // Get TI_KEYINFO for this root node
  162. pkInfo = (LPTI_KEYINFO)m_tcReg.GetItemData(hTi);
  163. // This value should never be NULL.
  164. if(!pkInfo){
  165. TRACE(TEXT("Tree item TI_KEYINFO is NULL for root node '%s'"), (LPCTSTR)strCheck);
  166. return;
  167. }
  168. //
  169. // Step through each sub item to see if it exists in the tree control
  170. //
  171. int iBegin = iStr + 1;
  172. int iNotFound = -1;
  173. while(strReg[iStr] && hTi){
  174. iStr++;
  175. if(strReg[iStr] == _T('\\') || strReg[iStr] == 0){
  176. CString strItem;
  177. //
  178. // Make sure we have tree items we can use.
  179. //
  180. EnumerateChildren(hTi);
  181. if(strReg[iStr] == 0 && strReg[iStr - 1] == _T('\\'))
  182. m_tcReg.Expand(hTi, TVE_EXPAND);
  183. //
  184. // Parse out the subkeys name.
  185. strCheck = strReg;
  186. strCheck = strCheck.Mid(iBegin, iStr - iBegin);
  187. strCheck.MakeUpper();
  188. iBegin = iStr + 1;
  189. //
  190. // Find child item with this name.
  191. //
  192. hTi = m_tcReg.GetNextItem(hTi, TVGN_CHILD);
  193. while(hTi){
  194. strItem = m_tcReg.GetItemText(hTi);
  195. strItem.MakeUpper();
  196. iNotFound = lstrcmpiW(strItem, strCheck);
  197. if(iNotFound >= 0)
  198. break;
  199. hTi = m_tcReg.GetNextItem(hTi, TVGN_NEXT);
  200. }
  201. if(strReg[iStr] != 0 && iNotFound != 0){
  202. hTi = NULL;
  203. break;
  204. }
  205. }
  206. }
  207. //
  208. // Select and ensure visibility if the path was found
  209. //
  210. if(hTi){
  211. if(strReg[iStr - 1] != _T('\\'))
  212. m_tcReg.Expand(hTi, TVE_COLLAPSE);
  213. if(!iNotFound){
  214. m_tcReg.SelectItem(hTi);
  215. }
  216. m_tcReg.EnsureVisible(hTi);
  217. }
  218. }
  219. /*-------------------------------------------------------------------------------------------
  220. Method: EnumerateChildren
  221. Synopsis: Enumerates a HKEY subkey and places them as children of 'hParent'
  222. Arguments: [hParent] - HTREEITEM to enumerate.
  223. Returns: void
  224. ---------------------------------------------------------------------------------------------*/
  225. void CRegistryDialog::EnumerateChildren(HTREEITEM hParent)
  226. {
  227. ASSERT(this);
  228. ASSERT(m_tcReg);
  229. //
  230. // We won't enumerate for the root.
  231. //
  232. if(!hParent || hParent == TVI_ROOT) return;
  233. LPTI_KEYINFO hkeyParent; // Used if the item being expanded has an invalid HKEY value
  234. LPTI_KEYINFO hkeyThis; // HKEY value of item expanding
  235. int n = 0; // Counter
  236. LPTSTR szName; // Used to acquire the name of a HKEY item
  237. DWORD cchName; // Buffer size of szName
  238. HTREEITEM hti;
  239. TV_INSERTSTRUCT tvii;
  240. TV_ITEM tviNew; // Expanding tree item
  241. TV_ITEM tvi; // Used to add children to the expanding HTREEITEM
  242. // pNMTreeView->itemNew is the TV_ITEM we're expanding.
  243. hkeyThis = (LPTI_KEYINFO)m_tcReg.GetItemData(hParent);
  244. // Exit if we have an invalid pointer.
  245. if(!hkeyThis) return;
  246. //
  247. // Allocate buffer for HKEY name
  248. //
  249. szName = new TCHAR [200];
  250. if(!szName) return;
  251. cchName = 200;
  252. //
  253. // Get item text
  254. //
  255. ZeroMemory(&tviNew,sizeof(tviNew));
  256. tviNew.hItem = hParent;
  257. tviNew.mask = TVIF_TEXT;
  258. tviNew.pszText = szName;
  259. tviNew.cchTextMax = cchName;
  260. m_tcReg.GetItem(&tviNew);
  261. //
  262. // Do we have an invalid HKEY value?
  263. //
  264. if (!hkeyThis->hKey) {
  265. // Get HKEY value of parent
  266. hti = m_tcReg.GetParentItem(hParent);
  267. ZeroMemory(&tvi,sizeof(tvi));
  268. tvi.hItem = hti;
  269. tvi.mask = TVIF_PARAM;
  270. m_tcReg.GetItem(&tvi);
  271. hkeyParent = (LPTI_KEYINFO)tvi.lParam;
  272. if(!hkeyParent){
  273. TRACE(TEXT("Parent of %s has an does not have a valid TI_KEYINFO struct"), (LPCTSTR)tviNew.pszText);
  274. delete [] szName;
  275. return;
  276. }
  277. //
  278. // If we can't open this key then set the parent item
  279. // to have no children.
  280. //
  281. if (ERROR_SUCCESS != RegOpenKeyEx(hkeyParent->hKey,tviNew.pszText,0,KEY_ALL_ACCESS,&(hkeyThis->hKey))) {
  282. tvi.mask = TVIF_CHILDREN;
  283. tvi.cChildren = 0;
  284. m_tcReg.SetItem(&tvi);
  285. delete [] szName;
  286. return;
  287. }
  288. //
  289. // Set the HKEY value for the item
  290. //
  291. tvi.hItem = hParent;
  292. tvi.lParam = (LPARAM) hkeyThis;
  293. m_tcReg.SetItem(&tvi);
  294. }
  295. //
  296. // Don't do anything if this item has already been enumerated or
  297. // does not have a valid TI_KEYINFO structure
  298. //
  299. if( !hkeyThis->Enum ){
  300. hkeyThis->Enum = true;
  301. DWORD cSubKeys; // Used when quering for number of children.
  302. HKEY hKey; // Used To querry sub keys.
  303. //
  304. // Prepare the TV_INSERTSTRUCT
  305. //
  306. ZeroMemory(&tvii, sizeof(TV_INSERTSTRUCT));
  307. tvii.hParent = hParent;
  308. tvii.hInsertAfter = TVI_LAST;
  309. tvii.item.mask = TVIF_CHILDREN | TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
  310. tvii.item.cChildren = 0;
  311. tvii.item.iImage = CONFIG_REG_IDX;
  312. tvii.item.iSelectedImage = CONFIG_REG_IDX;
  313. //
  314. // Add subkeys
  315. //
  316. while(ERROR_SUCCESS == RegEnumKeyEx(hkeyThis->hKey,n++, szName,&cchName,NULL,NULL,0,NULL)) {
  317. // Open the key so we can query it for the count of children
  318. if (ERROR_SUCCESS == RegOpenKeyEx(hkeyThis->hKey, szName, 0, KEY_ALL_ACCESS, &(hKey))) {
  319. if(ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, 0, &cSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
  320. tvii.item.cChildren = cSubKeys;
  321. RegCloseKey(hKey);
  322. }
  323. else
  324. tvii.item.cChildren = 0;
  325. tvii.item.cchTextMax = cchName;
  326. tvii.item.pszText = szName;
  327. tvii.item.lParam = (LPARAM)CreateKeyInfo(0, false);
  328. m_tcReg.InsertItem(&tvii);
  329. cchName = 200;
  330. }
  331. //
  332. // Sort children
  333. //
  334. m_tcReg.SortChildren(hParent);
  335. }
  336. delete [] szName;
  337. }
  338. /*-------------------------------------------------------------------------------------------
  339. Method: SetProfileInfo
  340. Synopsis: Sets either m_pTemplate;
  341. Arguments: [pspi] - the PEDITTEMPLATE to save the results in
  342. [ft] - Type of pointer 'pspi' is (unused)
  343. returns: void
  344. ---------------------------------------------------------------------------------------------*/
  345. void CRegistryDialog::SetProfileInfo(PEDITTEMPLATE pspi, FOLDER_TYPES ft)
  346. {
  347. m_pTemplate = (PEDITTEMPLATE)pspi;
  348. }
  349. /*-------------------------------------------------------------------------------------------
  350. Method: SetConsole
  351. Synopsis: Sets class variable 'm_pConsole'
  352. returns: void
  353. ---------------------------------------------------------------------------------------------*/
  354. void CRegistryDialog::SetConsole(LPCONSOLE pConsole)
  355. {
  356. m_pConsole = pConsole;
  357. }
  358. /*-------------------------------------------------------------------------------------------
  359. Method: SetComponentData
  360. Synopsis: Sets class varaible 'm_pComponentData'
  361. returns: void
  362. ---------------------------------------------------------------------------------------------*/
  363. void CRegistryDialog::SetComponentData(CComponentDataImpl *pComponentData)
  364. {
  365. m_pComponentData = pComponentData;
  366. }
  367. /*-------------------------------------------------------------------------------------------
  368. Method: SetCookie
  369. Synopsis: Sets class variable 'm_cookie'
  370. returns: void
  371. ---------------------------------------------------------------------------------------------*/
  372. void CRegistryDialog::SetCookie(MMC_COOKIE cookie)
  373. {
  374. m_cookie = cookie;
  375. }
  376. BEGIN_MESSAGE_MAP(CRegistryDialog, CHelpDialog)
  377. //{{AFX_MSG_MAP(CRegistryDialog)
  378. ON_NOTIFY(TVN_ITEMEXPANDING, IDC_REGTREE, OnItemexpandingRegtree)
  379. ON_NOTIFY(TVN_DELETEITEM, IDC_REGTREE, OnDeleteitemRegtree)
  380. ON_NOTIFY(TVN_SELCHANGED, IDC_REGTREE, OnSelchangedRegtree)
  381. ON_EN_CHANGE(IDC_REGKEY, OnChangeRegkey)
  382. //}}AFX_MSG_MAP
  383. END_MESSAGE_MAP()
  384. /////////////////////////////////////////////////////////////////////////////
  385. // CRegistryDialog message handlers
  386. /*-------------------------------------------------------------------------------------------
  387. Method: OnOK
  388. Synopsis: Message handler for the IDOK button,
  389. **BUG** Creating the new configuration item should happen outside of
  390. the dialog.
  391. Returns: void
  392. ---------------------------------------------------------------------------------------------*/
  393. void CRegistryDialog::OnOK()
  394. {
  395. UpdateData(TRUE);
  396. if (!m_strReg.IsEmpty()) {
  397. int nCont=0;
  398. CFolder *pFolder = (CFolder *)m_cookie;
  399. if ( m_cookie && AREA_REGISTRY_ANALYSIS == pFolder->GetType() ) {
  400. //
  401. // add a key to analysis area
  402. //
  403. if ( m_dbHandle ) {
  404. nCont = 1;
  405. }
  406. } else if ( m_pTemplate && m_pTemplate->pTemplate ) {
  407. nCont = 2;
  408. //
  409. // if no object is in the buffer, create it with count = 0
  410. // this buffer will be freed when the template is freed
  411. //
  412. if ( !m_pTemplate->pTemplate->pRegistryKeys.pAllNodes ) {
  413. PSCE_OBJECT_ARRAY pTemp = (PSCE_OBJECT_ARRAY)LocalAlloc(0, sizeof(SCE_OBJECT_ARRAY));
  414. if ( pTemp ) {
  415. pTemp->Count = 0;
  416. pTemp->pObjectArray = NULL;
  417. m_pTemplate->pTemplate->pRegistryKeys.pAllNodes = pTemp;
  418. } else
  419. nCont = 0;
  420. }
  421. }
  422. HRESULT hr=E_FAIL;
  423. if ( nCont ) {
  424. PSECURITY_DESCRIPTOR pSelSD=NULL;
  425. SECURITY_INFORMATION SelSeInfo = 0;
  426. BYTE ConfigStatus = 0;
  427. if (m_pComponentData) {
  428. if ( m_pComponentData->GetAddObjectSecurity(
  429. GetSafeHwnd(),
  430. m_strReg,
  431. TRUE,
  432. SE_REGISTRY_KEY,
  433. pSelSD,
  434. SelSeInfo,
  435. ConfigStatus
  436. ) == E_FAIL ) {
  437. return;
  438. }
  439. } else {
  440. return;
  441. }
  442. hr = S_OK;
  443. if ( pSelSD && SelSeInfo ) {
  444. if ( 1 == nCont ) {
  445. //
  446. // add to the engine directly
  447. //
  448. SCESTATUS sceStatus=SCESTATUS_SUCCESS;
  449. BYTE AnalStatus;
  450. //
  451. // start the transaction if it's not started
  452. //
  453. if ( m_pComponentData->EngineTransactionStarted() ) {
  454. sceStatus = SceUpdateObjectInfo(
  455. m_dbHandle,
  456. AREA_REGISTRY_SECURITY,
  457. (LPTSTR)(LPCTSTR)m_strReg,
  458. m_strReg.GetLength(), // number of characters
  459. ConfigStatus,
  460. TRUE,
  461. pSelSD,
  462. SelSeInfo,
  463. &AnalStatus
  464. );
  465. if ( SCESTATUS_SUCCESS == sceStatus ) {
  466. hr = m_pComponentData->UpdateScopeResultObject(m_pDataObj,
  467. m_cookie,
  468. AREA_REGISTRY_SECURITY);
  469. m_pTemplate->SetDirty(AREA_REGISTRY_SECURITY);
  470. }
  471. } else {
  472. //
  473. // can't start transaction
  474. //
  475. hr = E_FAIL;
  476. }
  477. } else {
  478. //
  479. // add to configuration template
  480. //
  481. PSCE_OBJECT_ARRAY poa;
  482. unsigned int i;
  483. poa = m_pTemplate->pTemplate->pRegistryKeys.pAllNodes;
  484. // Make sure this key isn't already in the list:
  485. for (i=0;i < poa->Count;i++) {
  486. if (lstrcmpi(poa->pObjectArray[i]->Name,m_strReg) == 0) {
  487. LocalFree(pSelSD);
  488. return;
  489. }
  490. }
  491. PSCE_OBJECT_SECURITY *pCopy;
  492. // For some reason the LocalReAlloc version of this keeps giving out of memory
  493. // errors, but allocing & copying everything works fine.
  494. pCopy = (PSCE_OBJECT_SECURITY *)LocalAlloc(LPTR,(poa->Count+1)*sizeof(PSCE_OBJECT_SECURITY));
  495. if (pCopy) {
  496. for (i=0; i<poa->Count; i++) {
  497. pCopy[i] = poa->pObjectArray[i];
  498. }
  499. pCopy[poa->Count] = (PSCE_OBJECT_SECURITY) LocalAlloc(LPTR,sizeof(SCE_OBJECT_SECURITY));
  500. if ( pCopy[poa->Count] ) {
  501. pCopy[poa->Count]->Name = (PWSTR) LocalAlloc(LPTR,(m_strReg.GetLength()+1)*sizeof(TCHAR));
  502. if ( pCopy[poa->Count]->Name ) {
  503. lstrcpy(pCopy[poa->Count]->Name,m_strReg);
  504. pCopy[poa->Count]->pSecurityDescriptor = pSelSD;
  505. pCopy[poa->Count]->SeInfo = SelSeInfo;
  506. pCopy[poa->Count]->Status = ConfigStatus;
  507. pCopy[poa->Count]->IsContainer = TRUE;
  508. pSelSD = NULL;
  509. poa->Count++;
  510. if ( poa->pObjectArray ) {
  511. LocalFree(poa->pObjectArray);
  512. }
  513. poa->pObjectArray = pCopy;
  514. m_pTemplate->SetDirty(AREA_REGISTRY_SECURITY);
  515. ((CFolder *)m_cookie)->RemoveAllResultItems();
  516. m_pConsole->UpdateAllViews(NULL ,m_cookie, UAV_RESULTITEM_UPDATEALL);
  517. hr = S_OK;
  518. } else {
  519. LocalFree(pCopy[poa->Count]);
  520. LocalFree(pCopy);
  521. }
  522. } else
  523. LocalFree(pCopy);
  524. }
  525. }
  526. if ( pSelSD ) {
  527. LocalFree(pSelSD);
  528. }
  529. }
  530. }
  531. if ( FAILED(hr) ) {
  532. CString str;
  533. str.LoadString(IDS_CANT_ADD_KEY);
  534. AfxMessageBox(str);
  535. }
  536. }
  537. CDialog::OnOK();
  538. }
  539. /*-------------------------------------------------------------------------------------------
  540. Method: OnInitDialog
  541. Synopsis: Create root HKEY entries HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT,
  542. and HKEY_USERS in the tree control.
  543. Returns: return TRUE
  544. ---------------------------------------------------------------------------------------------*/
  545. BOOL CRegistryDialog::OnInitDialog()
  546. {
  547. CString strRegKeyName; // Used to load string resources
  548. // for name of the HTREEITEM
  549. HTREEITEM hti;
  550. TV_INSERTSTRUCT tvi;
  551. CDialog::OnInitDialog();
  552. //
  553. // Create image list for tree control
  554. //
  555. CThemeContextActivator activator; //Bug 424909, Yanggao, 6/29/2001
  556. m_pIl.Create(IDB_ICON16,16,1,RGB(255,0,255));
  557. m_tcReg.SetImageList (CImageList::FromHandle (m_pIl), TVSIL_NORMAL);
  558. //
  559. // Add Root HKEY items.
  560. //
  561. ZeroMemory(&tvi,sizeof(tvi));
  562. tvi.hParent = TVI_ROOT;
  563. tvi.hInsertAfter = TVI_LAST;
  564. tvi.item.mask = TVIF_CHILDREN | TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
  565. tvi.item.cChildren = 1; // Initial UI +
  566. tvi.item.iImage = CONFIG_REG_IDX;
  567. tvi.item.iSelectedImage = CONFIG_REG_IDX;
  568. // Insert HKEY_CLASSES_ROOT
  569. strRegKeyName.LoadString(IDS_HKCR);
  570. tvi.item.cchTextMax = strRegKeyName.GetLength()+1;
  571. tvi.item.pszText = strRegKeyName.LockBuffer();
  572. tvi.item.lParam = (LPARAM)CreateKeyInfo(HKEY_CLASSES_ROOT, false);
  573. hti = m_tcReg.InsertItem(&tvi);
  574. strRegKeyName.UnlockBuffer();
  575. // Insert HKEY_LOCAL_MACHINE
  576. strRegKeyName.LoadString(IDS_HKLM);
  577. tvi.item.cchTextMax = strRegKeyName.GetLength()+1;
  578. tvi.item.pszText = strRegKeyName.LockBuffer();
  579. tvi.item.lParam = (LPARAM)CreateKeyInfo(HKEY_LOCAL_MACHINE, false);
  580. hti = m_tcReg.InsertItem(&tvi);
  581. strRegKeyName.UnlockBuffer();
  582. // Insert HKEY_USERS
  583. strRegKeyName.LoadString(IDS_HKU);
  584. tvi.item.cchTextMax = strRegKeyName.GetLength()+1;
  585. tvi.item.pszText = strRegKeyName.LockBuffer();
  586. tvi.item.lParam = (LPARAM)CreateKeyInfo(HKEY_USERS, false);
  587. hti = m_tcReg.InsertItem(&tvi);
  588. strRegKeyName.UnlockBuffer();
  589. // Sort the tree control
  590. m_tcReg.SortChildren(NULL);
  591. return TRUE; // return TRUE unless you set the focus to a control
  592. // EXCEPTION: OCX Property Pages should return FALSE
  593. }
  594. /*-------------------------------------------------------------------------------------------
  595. Method: OnItemexpandingRegtree
  596. Synopsis: MFC OnNotify TVN_ITEMEXPANDING message handler. The lParam member of
  597. the HTREEITEM is a pointer to a TI_KEYINFO structure. When
  598. a tree item is expanded for the first time, we must enumerate all
  599. its children. The function will set the TI_KEYINFO.Enum = true after
  600. enumeration.
  601. returns: void
  602. ---------------------------------------------------------------------------------------------*/
  603. void CRegistryDialog::OnItemexpandingRegtree(NMHDR* pNMHDR, LRESULT* pResult)
  604. {
  605. NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
  606. *pResult = 0;
  607. EnumerateChildren(pNMTreeView->itemNew.hItem);
  608. }
  609. /*-------------------------------------------------------------------------------------------
  610. Method: OnDeleteitemRegtree
  611. Synopsis: MFC OnNotify TVN_DELETEITEM message handler. Delete the TI_KEYINFO
  612. structure associated with 'itemOld' and close
  613. the regestry key.
  614. returns: void
  615. ---------------------------------------------------------------------------------------------*/
  616. void CRegistryDialog::OnDeleteitemRegtree(NMHDR* pNMHDR, LRESULT* pResult)
  617. {
  618. NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
  619. LPTI_KEYINFO pInfo = (LPTI_KEYINFO)pNMTreeView->itemOld.lParam;
  620. if(pInfo){
  621. // Close registry key
  622. if(pInfo->hKey && (INT_PTR)(pInfo->hKey) != -1)
  623. RegCloseKey(pInfo->hKey);
  624. // delete the TI_KEYINFO
  625. delete pInfo;
  626. }
  627. *pResult = 0;
  628. }
  629. /*-------------------------------------------------------------------------------------------
  630. Method: ~CRegistryDialog
  631. Synopsis: Release memory used by this class
  632. returns: void
  633. ---------------------------------------------------------------------------------------------*/
  634. CRegistryDialog::~CRegistryDialog()
  635. {
  636. m_pIl.Destroy(); //Bug 424909, Yanggao, 6/29/2001
  637. }
  638. /*-------------------------------------------------------------------------------------------
  639. Method: OnSelchangedRegtree
  640. Synopsis: MFC OnNotify TVN_SELCHANGED message handler. Updates 'm_strReg' to
  641. the full path of the HKEY item
  642. returns: void
  643. ---------------------------------------------------------------------------------------------*/
  644. void CRegistryDialog::OnSelchangedRegtree(NMHDR* pNMHDR, LRESULT* pResult)
  645. {
  646. NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
  647. *pResult = 0;
  648. //
  649. // Sometime we don't want to be updated.
  650. //
  651. if(m_bNoUpdate) return;
  652. TV_ITEM tvi; // Used to get information about tree items
  653. CString strSel; // Used to build the path to the selected item
  654. LPTSTR szBuf; // Name of tree item
  655. DWORD cchBuf; // size of szBuf
  656. cchBuf = 500;
  657. szBuf = new TCHAR [ cchBuf ];
  658. if(!szBuf) return;
  659. // Get the selected items text
  660. tvi.hItem = pNMTreeView->itemNew.hItem;
  661. tvi.mask = TVIF_TEXT | TVIF_PARAM;
  662. tvi.pszText = szBuf;
  663. tvi.cchTextMax = cchBuf;
  664. m_tcReg.GetItem(&tvi);
  665. strSel = tvi.pszText;
  666. // Retrieve text of all parent items.
  667. while(tvi.hItem = m_tcReg.GetParentItem(tvi.hItem)) {
  668. m_tcReg.GetItem(&tvi);
  669. strSel = L"\\" + strSel;
  670. strSel = tvi.pszText + strSel;
  671. }
  672. m_strReg = strSel;
  673. UpdateData(FALSE);
  674. delete[] szBuf;
  675. // Enable the OK button
  676. if(GetDlgItem(IDOK)) GetDlgItem(IDOK)->EnableWindow(TRUE);
  677. }
  678. /*-------------------------------------------------------------------------------------------
  679. Method: OnChangeRegkey
  680. Synopsis: IDC_REGKEY edit control EN_CHANGE handler.
  681. returns: void
  682. ---------------------------------------------------------------------------------------------*/
  683. void CRegistryDialog::OnChangeRegkey()
  684. {
  685. UpdateData(TRUE);
  686. if(IsValidRegPath(m_strReg) && GetDlgItem(IDOK)) {
  687. GetDlgItem(IDOK)->EnableWindow(TRUE);
  688. m_bNoUpdate = TRUE;
  689. MakePathVisible(m_strReg);
  690. m_bNoUpdate = FALSE;
  691. }
  692. else {
  693. GetDlgItem(IDOK)->EnableWindow(FALSE);
  694. }
  695. }