windows-nt/Source/XPSP1/NT/admin/snapin/wsecmgr/regdlg.cpp

870 lines
27 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation 1996-2001.
//
// File: regdlg.cpp
//
// Contents: implementation of CRegistryDialog
//
//----------------------------------------------------------------------------
#include "stdafx.h"
#include "wsecmgr.h"
#include "resource.h"
#include "util.h"
#include "servperm.h"
#include "addobj.h"
#include "RegDlg.h"
#include <accctrl.h>
#include <aclapi.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CRegistryDialog dialog
CRegistryDialog::CRegistryDialog()
: CHelpDialog(a177HelpIDs, IDD, 0)
{
//{{AFX_DATA_INIT(CRegistryDialog)
m_strReg = _T("");
//}}AFX_DATA_INIT
m_pConsole = NULL;
m_pTemplate = NULL;
m_dbHandle = NULL;
m_cookie = 0;
m_pIl = NULL;
m_pDataObj = NULL;
m_bNoUpdate = FALSE;
}
void CRegistryDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CRegistryDialog)
DDX_Control(pDX, IDC_REGTREE, m_tcReg);
DDX_Text(pDX, IDC_REGKEY, m_strReg);
//}}AFX_DATA_MAP
}
/*-------------------------------------------------------------------------------------------
Method: CreateKeyInfo
Synopsis: Create a new TI_KEYINFO structure and optionaly set its members
Arguments: [hKey] - Optional value to set the hKey member of TI_KEYINFO
default is zero
[Enum] - Optional value to set the Enum member of TI_KEYINFO
default is zero
Returns: a LPTI_KEYINFO pointer
---------------------------------------------------------------------------------------------*/
LPTI_KEYINFO CRegistryDialog::CreateKeyInfo(HKEY hKey, bool Enum)
{
LPTI_KEYINFO pInfo = NULL;
pInfo = new TI_KEYINFO;
if(pInfo){
pInfo->hKey = hKey;
pInfo->Enum = Enum;
}
return pInfo;
}
/*-------------------------------------------------------------------------------------------
Method: IsValidRegPath
Synopsis: Returns true if strReg path. We can't assume that this
HKEY exists in the current registry. We will only make
sure that the root node exists and each string in
between '\'s isn't blank.
Arguments: [strReg] - A string represending a registry path
subkeys are seperated by '\'s
Returns: TRUE if strReg is a valid path.
---------------------------------------------------------------------------------------------*/
BOOL CRegistryDialog::IsValidRegPath(LPCTSTR strReg)
{
ASSERT(this);
ASSERT(m_tcReg);
if(!strReg) return FALSE;
int iStr = 0; // Current position in strReg
CString strCheck; // String to check
LPTI_KEYINFO pkInfo; // Tree item key info.
//
// Find which root node this registry value is in.
//
while(strReg[iStr] && strReg[iStr] != _T('\\')) iStr++;
strCheck = strReg;
strCheck = strCheck.Left(iStr);
strCheck.MakeUpper();
// Get the HKEY value from the tree ctrl
HTREEITEM hTi = m_tcReg.GetRootItem();
while(hTi){
if(m_tcReg.GetItemText(hTi) == strCheck)
break;
hTi = m_tcReg.GetNextItem(hTi, TVGN_NEXT);
}
if(hTi == NULL) return FALSE;
// Get TI_KEYINFO for this root node
pkInfo = (LPTI_KEYINFO)m_tcReg.GetItemData(hTi);
// This value should never be NULL.
if(!pkInfo){
TRACE(TEXT("Tree item TI_KEYINFO is NULL for root node '%s'"), (LPCTSTR)strCheck);
return FALSE;
}
//
// Check the rest of the string to make sure that string's
// in between '\'s aren't blank
//
while(strReg[iStr]){
// Check to make sure that the string item before
// and after the '\' aren't spaces.
if(strReg[iStr] == _T('\\')){
if( strReg[iStr + 1] == _T(' ') ||
strReg[iStr + 1] == _T('\t') ||
//strReg[iStr + 1] == 0 ||
iStr > 0 &&
(
strReg[iStr - 1] == _T(' ') ||
strReg[iStr - 1] == _T('\t')
)
)
return FALSE;
}
iStr++;
}
return TRUE;
}
/*-------------------------------------------------------------------------------------------
Method: MakePathVisible
Synopsis:
Arguments: [strReg] - A string represending a registry path
subkeys are seperated by '\'s
Returns: TRUE if strReg is a valid path.
---------------------------------------------------------------------------------------------*/
void CRegistryDialog::MakePathVisible(LPCTSTR strReg)
{
ASSERT(this);
ASSERT(m_tcReg);
if(!strReg) return;
int iStr = 0; // Current position in strReg
CString strCheck; // String to check
LPTI_KEYINFO pkInfo; // Tree item key info.
//
// Find which root node this registry value is in.
//
while(strReg[iStr] && strReg[iStr] != _T('\\')) iStr++;
strCheck = strReg;
strCheck = strCheck.Left(iStr);
strCheck.MakeUpper();
// Get the HKEY value from the tree ctrl
HTREEITEM hTi = m_tcReg.GetRootItem();
while(hTi){
if(m_tcReg.GetItemText(hTi) == strCheck)
break;
hTi = m_tcReg.GetNextItem(hTi, TVGN_NEXT);
}
if(hTi == NULL) return;
// Get TI_KEYINFO for this root node
pkInfo = (LPTI_KEYINFO)m_tcReg.GetItemData(hTi);
// This value should never be NULL.
if(!pkInfo){
TRACE(TEXT("Tree item TI_KEYINFO is NULL for root node '%s'"), (LPCTSTR)strCheck);
return;
}
//
// Step through each sub item to see if it exists in the tree control
//
int iBegin = iStr + 1;
int iNotFound = -1;
while(strReg[iStr] && hTi){
iStr++;
if(strReg[iStr] == _T('\\') || strReg[iStr] == 0){
CString strItem;
//
// Make sure we have tree items we can use.
//
EnumerateChildren(hTi);
if(strReg[iStr] == 0 && strReg[iStr - 1] == _T('\\'))
m_tcReg.Expand(hTi, TVE_EXPAND);
//
// Parse out the subkeys name.
strCheck = strReg;
strCheck = strCheck.Mid(iBegin, iStr - iBegin);
strCheck.MakeUpper();
iBegin = iStr + 1;
//
// Find child item with this name.
//
hTi = m_tcReg.GetNextItem(hTi, TVGN_CHILD);
while(hTi){
strItem = m_tcReg.GetItemText(hTi);
strItem.MakeUpper();
iNotFound = lstrcmpiW(strItem, strCheck);
if(iNotFound >= 0)
break;
hTi = m_tcReg.GetNextItem(hTi, TVGN_NEXT);
}
if(strReg[iStr] != 0 && iNotFound != 0){
hTi = NULL;
break;
}
}
}
//
// Select and ensure visibility if the path was found
//
if(hTi){
if(strReg[iStr - 1] != _T('\\'))
m_tcReg.Expand(hTi, TVE_COLLAPSE);
if(!iNotFound){
m_tcReg.SelectItem(hTi);
}
m_tcReg.EnsureVisible(hTi);
}
}
/*-------------------------------------------------------------------------------------------
Method: EnumerateChildren
Synopsis: Enumerates a HKEY subkey and places them as children of 'hParent'
Arguments: [hParent] - HTREEITEM to enumerate.
Returns: void
---------------------------------------------------------------------------------------------*/
void CRegistryDialog::EnumerateChildren(HTREEITEM hParent)
{
ASSERT(this);
ASSERT(m_tcReg);
//
// We won't enumerate for the root.
//
if(!hParent || hParent == TVI_ROOT) return;
LPTI_KEYINFO hkeyParent; // Used if the item being expanded has an invalid HKEY value
LPTI_KEYINFO hkeyThis; // HKEY value of item expanding
int n = 0; // Counter
LPTSTR szName; // Used to acquire the name of a HKEY item
DWORD cchName; // Buffer size of szName
HTREEITEM hti;
TV_INSERTSTRUCT tvii;
TV_ITEM tviNew; // Expanding tree item
TV_ITEM tvi; // Used to add children to the expanding HTREEITEM
// pNMTreeView->itemNew is the TV_ITEM we're expanding.
hkeyThis = (LPTI_KEYINFO)m_tcReg.GetItemData(hParent);
// Exit if we have an invalid pointer.
if(!hkeyThis) return;
//
// Allocate buffer for HKEY name
//
szName = new TCHAR [200];
if(!szName) return;
cchName = 200;
//
// Get item text
//
ZeroMemory(&tviNew,sizeof(tviNew));
tviNew.hItem = hParent;
tviNew.mask = TVIF_TEXT;
tviNew.pszText = szName;
tviNew.cchTextMax = cchName;
m_tcReg.GetItem(&tviNew);
//
// Do we have an invalid HKEY value?
//
if (!hkeyThis->hKey) {
// Get HKEY value of parent
hti = m_tcReg.GetParentItem(hParent);
ZeroMemory(&tvi,sizeof(tvi));
tvi.hItem = hti;
tvi.mask = TVIF_PARAM;
m_tcReg.GetItem(&tvi);
hkeyParent = (LPTI_KEYINFO)tvi.lParam;
if(!hkeyParent){
TRACE(TEXT("Parent of %s has an does not have a valid TI_KEYINFO struct"), (LPCTSTR)tviNew.pszText);
delete [] szName;
return;
}
//
// If we can't open this key then set the parent item
// to have no children.
//
if (ERROR_SUCCESS != RegOpenKeyEx(hkeyParent->hKey,tviNew.pszText,0,KEY_ALL_ACCESS,&(hkeyThis->hKey))) {
tvi.mask = TVIF_CHILDREN;
tvi.cChildren = 0;
m_tcReg.SetItem(&tvi);
delete [] szName;
return;
}
//
// Set the HKEY value for the item
//
tvi.hItem = hParent;
tvi.lParam = (LPARAM) hkeyThis;
m_tcReg.SetItem(&tvi);
}
//
// Don't do anything if this item has already been enumerated or
// does not have a valid TI_KEYINFO structure
//
if( !hkeyThis->Enum ){
hkeyThis->Enum = true;
DWORD cSubKeys; // Used when quering for number of children.
HKEY hKey; // Used To querry sub keys.
//
// Prepare the TV_INSERTSTRUCT
//
ZeroMemory(&tvii, sizeof(TV_INSERTSTRUCT));
tvii.hParent = hParent;
tvii.hInsertAfter = TVI_LAST;
tvii.item.mask = TVIF_CHILDREN | TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvii.item.cChildren = 0;
tvii.item.iImage = CONFIG_REG_IDX;
tvii.item.iSelectedImage = CONFIG_REG_IDX;
//
// Add subkeys
//
while(ERROR_SUCCESS == RegEnumKeyEx(hkeyThis->hKey,n++, szName,&cchName,NULL,NULL,0,NULL)) {
// Open the key so we can query it for the count of children
if (ERROR_SUCCESS == RegOpenKeyEx(hkeyThis->hKey, szName, 0, KEY_ALL_ACCESS, &(hKey))) {
if(ERROR_SUCCESS == RegQueryInfoKey(hKey, NULL, NULL, 0, &cSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
tvii.item.cChildren = cSubKeys;
RegCloseKey(hKey);
}
else
tvii.item.cChildren = 0;
tvii.item.cchTextMax = cchName;
tvii.item.pszText = szName;
tvii.item.lParam = (LPARAM)CreateKeyInfo(0, false);
m_tcReg.InsertItem(&tvii);
cchName = 200;
}
//
// Sort children
//
m_tcReg.SortChildren(hParent);
}
delete [] szName;
}
/*-------------------------------------------------------------------------------------------
Method: SetProfileInfo
Synopsis: Sets either m_pTemplate;
Arguments: [pspi] - the PEDITTEMPLATE to save the results in
[ft] - Type of pointer 'pspi' is (unused)
returns: void
---------------------------------------------------------------------------------------------*/
void CRegistryDialog::SetProfileInfo(PEDITTEMPLATE pspi, FOLDER_TYPES ft)
{
m_pTemplate = (PEDITTEMPLATE)pspi;
}
/*-------------------------------------------------------------------------------------------
Method: SetConsole
Synopsis: Sets class variable 'm_pConsole'
returns: void
---------------------------------------------------------------------------------------------*/
void CRegistryDialog::SetConsole(LPCONSOLE pConsole)
{
m_pConsole = pConsole;
}
/*-------------------------------------------------------------------------------------------
Method: SetComponentData
Synopsis: Sets class varaible 'm_pComponentData'
returns: void
---------------------------------------------------------------------------------------------*/
void CRegistryDialog::SetComponentData(CComponentDataImpl *pComponentData)
{
m_pComponentData = pComponentData;
}
/*-------------------------------------------------------------------------------------------
Method: SetCookie
Synopsis: Sets class variable 'm_cookie'
returns: void
---------------------------------------------------------------------------------------------*/
void CRegistryDialog::SetCookie(MMC_COOKIE cookie)
{
m_cookie = cookie;
}
BEGIN_MESSAGE_MAP(CRegistryDialog, CHelpDialog)
//{{AFX_MSG_MAP(CRegistryDialog)
ON_NOTIFY(TVN_ITEMEXPANDING, IDC_REGTREE, OnItemexpandingRegtree)
ON_NOTIFY(TVN_DELETEITEM, IDC_REGTREE, OnDeleteitemRegtree)
ON_NOTIFY(TVN_SELCHANGED, IDC_REGTREE, OnSelchangedRegtree)
ON_EN_CHANGE(IDC_REGKEY, OnChangeRegkey)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CRegistryDialog message handlers
/*-------------------------------------------------------------------------------------------
Method: OnOK
Synopsis: Message handler for the IDOK button,
**BUG** Creating the new configuration item should happen outside of
the dialog.
Returns: void
---------------------------------------------------------------------------------------------*/
void CRegistryDialog::OnOK()
{
UpdateData(TRUE);
if (!m_strReg.IsEmpty()) {
int nCont=0;
CFolder *pFolder = (CFolder *)m_cookie;
if ( m_cookie && AREA_REGISTRY_ANALYSIS == pFolder->GetType() ) {
//
// add a key to analysis area
//
if ( m_dbHandle ) {
nCont = 1;
}
} else if ( m_pTemplate && m_pTemplate->pTemplate ) {
nCont = 2;
//
// if no object is in the buffer, create it with count = 0
// this buffer will be freed when the template is freed
//
if ( !m_pTemplate->pTemplate->pRegistryKeys.pAllNodes ) {
PSCE_OBJECT_ARRAY pTemp = (PSCE_OBJECT_ARRAY)LocalAlloc(0, sizeof(SCE_OBJECT_ARRAY));
if ( pTemp ) {
pTemp->Count = 0;
pTemp->pObjectArray = NULL;
m_pTemplate->pTemplate->pRegistryKeys.pAllNodes = pTemp;
} else
nCont = 0;
}
}
HRESULT hr=E_FAIL;
if ( nCont ) {
PSECURITY_DESCRIPTOR pSelSD=NULL;
SECURITY_INFORMATION SelSeInfo = 0;
BYTE ConfigStatus = 0;
if (m_pComponentData) {
if ( m_pComponentData->GetAddObjectSecurity(
GetSafeHwnd(),
m_strReg,
TRUE,
SE_REGISTRY_KEY,
pSelSD,
SelSeInfo,
ConfigStatus
) == E_FAIL ) {
return;
}
} else {
return;
}
hr = S_OK;
if ( pSelSD && SelSeInfo ) {
if ( 1 == nCont ) {
//
// add to the engine directly
//
SCESTATUS sceStatus=SCESTATUS_SUCCESS;
BYTE AnalStatus;
//
// start the transaction if it's not started
//
if ( m_pComponentData->EngineTransactionStarted() ) {
sceStatus = SceUpdateObjectInfo(
m_dbHandle,
AREA_REGISTRY_SECURITY,
(LPTSTR)(LPCTSTR)m_strReg,
m_strReg.GetLength(), // number of characters
ConfigStatus,
TRUE,
pSelSD,
SelSeInfo,
&AnalStatus
);
if ( SCESTATUS_SUCCESS == sceStatus ) {
hr = m_pComponentData->UpdateScopeResultObject(m_pDataObj,
m_cookie,
AREA_REGISTRY_SECURITY);
m_pTemplate->SetDirty(AREA_REGISTRY_SECURITY);
}
} else {
//
// can't start transaction
//
hr = E_FAIL;
}
} else {
//
// add to configuration template
//
PSCE_OBJECT_ARRAY poa;
unsigned int i;
poa = m_pTemplate->pTemplate->pRegistryKeys.pAllNodes;
// Make sure this key isn't already in the list:
for (i=0;i < poa->Count;i++) {
if (lstrcmpi(poa->pObjectArray[i]->Name,m_strReg) == 0) {
LocalFree(pSelSD);
return;
}
}
PSCE_OBJECT_SECURITY *pCopy;
// For some reason the LocalReAlloc version of this keeps giving out of memory
// errors, but allocing & copying everything works fine.
pCopy = (PSCE_OBJECT_SECURITY *)LocalAlloc(LPTR,(poa->Count+1)*sizeof(PSCE_OBJECT_SECURITY));
if (pCopy) {
for (i=0; i<poa->Count; i++) {
pCopy[i] = poa->pObjectArray[i];
}
pCopy[poa->Count] = (PSCE_OBJECT_SECURITY) LocalAlloc(LPTR,sizeof(SCE_OBJECT_SECURITY));
if ( pCopy[poa->Count] ) {
pCopy[poa->Count]->Name = (PWSTR) LocalAlloc(LPTR,(m_strReg.GetLength()+1)*sizeof(TCHAR));
if ( pCopy[poa->Count]->Name ) {
lstrcpy(pCopy[poa->Count]->Name,m_strReg);
pCopy[poa->Count]->pSecurityDescriptor = pSelSD;
pCopy[poa->Count]->SeInfo = SelSeInfo;
pCopy[poa->Count]->Status = ConfigStatus;
pCopy[poa->Count]->IsContainer = TRUE;
pSelSD = NULL;
poa->Count++;
if ( poa->pObjectArray ) {
LocalFree(poa->pObjectArray);
}
poa->pObjectArray = pCopy;
m_pTemplate->SetDirty(AREA_REGISTRY_SECURITY);
((CFolder *)m_cookie)->RemoveAllResultItems();
m_pConsole->UpdateAllViews(NULL ,m_cookie, UAV_RESULTITEM_UPDATEALL);
hr = S_OK;
} else {
LocalFree(pCopy[poa->Count]);
LocalFree(pCopy);
}
} else
LocalFree(pCopy);
}
}
if ( pSelSD ) {
LocalFree(pSelSD);
}
}
}
if ( FAILED(hr) ) {
CString str;
str.LoadString(IDS_CANT_ADD_KEY);
AfxMessageBox(str);
}
}
CDialog::OnOK();
}
/*-------------------------------------------------------------------------------------------
Method: OnInitDialog
Synopsis: Create root HKEY entries HKEY_LOCAL_MACHINE, HKEY_CLASSES_ROOT,
and HKEY_USERS in the tree control.
Returns: return TRUE
---------------------------------------------------------------------------------------------*/
BOOL CRegistryDialog::OnInitDialog()
{
CString strRegKeyName; // Used to load string resources
// for name of the HTREEITEM
HTREEITEM hti;
TV_INSERTSTRUCT tvi;
CDialog::OnInitDialog();
//
// Create image list for tree control
//
CThemeContextActivator activator; //Bug 424909, Yanggao, 6/29/2001
m_pIl.Create(IDB_ICON16,16,1,RGB(255,0,255));
m_tcReg.SetImageList (CImageList::FromHandle (m_pIl), TVSIL_NORMAL);
//
// Add Root HKEY items.
//
ZeroMemory(&tvi,sizeof(tvi));
tvi.hParent = TVI_ROOT;
tvi.hInsertAfter = TVI_LAST;
tvi.item.mask = TVIF_CHILDREN | TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvi.item.cChildren = 1; // Initial UI +
tvi.item.iImage = CONFIG_REG_IDX;
tvi.item.iSelectedImage = CONFIG_REG_IDX;
// Insert HKEY_CLASSES_ROOT
strRegKeyName.LoadString(IDS_HKCR);
tvi.item.cchTextMax = strRegKeyName.GetLength()+1;
tvi.item.pszText = strRegKeyName.LockBuffer();
tvi.item.lParam = (LPARAM)CreateKeyInfo(HKEY_CLASSES_ROOT, false);
hti = m_tcReg.InsertItem(&tvi);
strRegKeyName.UnlockBuffer();
// Insert HKEY_LOCAL_MACHINE
strRegKeyName.LoadString(IDS_HKLM);
tvi.item.cchTextMax = strRegKeyName.GetLength()+1;
tvi.item.pszText = strRegKeyName.LockBuffer();
tvi.item.lParam = (LPARAM)CreateKeyInfo(HKEY_LOCAL_MACHINE, false);
hti = m_tcReg.InsertItem(&tvi);
strRegKeyName.UnlockBuffer();
// Insert HKEY_USERS
strRegKeyName.LoadString(IDS_HKU);
tvi.item.cchTextMax = strRegKeyName.GetLength()+1;
tvi.item.pszText = strRegKeyName.LockBuffer();
tvi.item.lParam = (LPARAM)CreateKeyInfo(HKEY_USERS, false);
hti = m_tcReg.InsertItem(&tvi);
strRegKeyName.UnlockBuffer();
// Sort the tree control
m_tcReg.SortChildren(NULL);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
/*-------------------------------------------------------------------------------------------
Method: OnItemexpandingRegtree
Synopsis: MFC OnNotify TVN_ITEMEXPANDING message handler. The lParam member of
the HTREEITEM is a pointer to a TI_KEYINFO structure. When
a tree item is expanded for the first time, we must enumerate all
its children. The function will set the TI_KEYINFO.Enum = true after
enumeration.
returns: void
---------------------------------------------------------------------------------------------*/
void CRegistryDialog::OnItemexpandingRegtree(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
*pResult = 0;
EnumerateChildren(pNMTreeView->itemNew.hItem);
}
/*-------------------------------------------------------------------------------------------
Method: OnDeleteitemRegtree
Synopsis: MFC OnNotify TVN_DELETEITEM message handler. Delete the TI_KEYINFO
structure associated with 'itemOld' and close
the regestry key.
returns: void
---------------------------------------------------------------------------------------------*/
void CRegistryDialog::OnDeleteitemRegtree(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
LPTI_KEYINFO pInfo = (LPTI_KEYINFO)pNMTreeView->itemOld.lParam;
if(pInfo){
// Close registry key
if(pInfo->hKey && (INT_PTR)(pInfo->hKey) != -1)
RegCloseKey(pInfo->hKey);
// delete the TI_KEYINFO
delete pInfo;
}
*pResult = 0;
}
/*-------------------------------------------------------------------------------------------
Method: ~CRegistryDialog
Synopsis: Release memory used by this class
returns: void
---------------------------------------------------------------------------------------------*/
CRegistryDialog::~CRegistryDialog()
{
m_pIl.Destroy(); //Bug 424909, Yanggao, 6/29/2001
}
/*-------------------------------------------------------------------------------------------
Method: OnSelchangedRegtree
Synopsis: MFC OnNotify TVN_SELCHANGED message handler. Updates 'm_strReg' to
the full path of the HKEY item
returns: void
---------------------------------------------------------------------------------------------*/
void CRegistryDialog::OnSelchangedRegtree(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
*pResult = 0;
//
// Sometime we don't want to be updated.
//
if(m_bNoUpdate) return;
TV_ITEM tvi; // Used to get information about tree items
CString strSel; // Used to build the path to the selected item
LPTSTR szBuf; // Name of tree item
DWORD cchBuf; // size of szBuf
cchBuf = 500;
szBuf = new TCHAR [ cchBuf ];
if(!szBuf) return;
// Get the selected items text
tvi.hItem = pNMTreeView->itemNew.hItem;
tvi.mask = TVIF_TEXT | TVIF_PARAM;
tvi.pszText = szBuf;
tvi.cchTextMax = cchBuf;
m_tcReg.GetItem(&tvi);
strSel = tvi.pszText;
// Retrieve text of all parent items.
while(tvi.hItem = m_tcReg.GetParentItem(tvi.hItem)) {
m_tcReg.GetItem(&tvi);
strSel = L"\\" + strSel;
strSel = tvi.pszText + strSel;
}
m_strReg = strSel;
UpdateData(FALSE);
delete[] szBuf;
// Enable the OK button
if(GetDlgItem(IDOK)) GetDlgItem(IDOK)->EnableWindow(TRUE);
}
/*-------------------------------------------------------------------------------------------
Method: OnChangeRegkey
Synopsis: IDC_REGKEY edit control EN_CHANGE handler.
returns: void
---------------------------------------------------------------------------------------------*/
void CRegistryDialog::OnChangeRegkey()
{
UpdateData(TRUE);
if(IsValidRegPath(m_strReg) && GetDlgItem(IDOK)) {
GetDlgItem(IDOK)->EnableWindow(TRUE);
m_bNoUpdate = TRUE;
MakePathVisible(m_strReg);
m_bNoUpdate = FALSE;
}
else {
GetDlgItem(IDOK)->EnableWindow(FALSE);
}
}