1772 lines
54 KiB
C++
1772 lines
54 KiB
C++
//+--------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1994 - 2001.
|
|
//
|
|
// File: scopane.cpp
|
|
//
|
|
// Contents: Functions for handling the scope pane folder structure
|
|
//
|
|
// History: 12-12-1997 RobCap Split out from snapmgr.cpp
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "cookie.h"
|
|
#include "snapmgr.h"
|
|
#include "resource.h"
|
|
#include "wrapper.h"
|
|
#include "util.h"
|
|
#include <sceattch.h>
|
|
#include <io.h>
|
|
|
|
#ifdef INITGUID
|
|
#undef INITGUID
|
|
#include <gpedit.h>
|
|
#define INITGUID
|
|
#include "userenv.h"
|
|
#endif
|
|
|
|
|
|
//
|
|
// Array of folders to list in the scope pane
|
|
// The order of this array is important:
|
|
// All folders which appear at the same level must be adjacent
|
|
// to each other and the array and #defines need to be kept in
|
|
// sync
|
|
//
|
|
//
|
|
#define USE_KERBEROS 1
|
|
|
|
//
|
|
// Top level folders
|
|
//
|
|
#define ANALYSIS_FOLDER 0
|
|
#define CONFIGURATION_FOLDER (ANALYSIS_FOLDER +1)
|
|
|
|
//
|
|
// Profile level folders
|
|
//
|
|
#define PROFILE_ACCOUNT_FOLDER (CONFIGURATION_FOLDER +1)
|
|
#define PROFILE_LOCAL_FOLDER (PROFILE_ACCOUNT_FOLDER +1)
|
|
#define PROFILE_EVENTLOG_FOLDER (PROFILE_LOCAL_FOLDER +1)
|
|
#define PROFILE_GROUPS_FOLDER (PROFILE_EVENTLOG_FOLDER +1)
|
|
#define PROFILE_SERVICE_FOLDER (PROFILE_GROUPS_FOLDER +1)
|
|
#define PROFILE_REGISTRY_FOLDER (PROFILE_SERVICE_FOLDER +1)
|
|
#define PROFILE_FILESTORE_FOLDER (PROFILE_REGISTRY_FOLDER +1)
|
|
|
|
//
|
|
// Profile/Account level folders
|
|
//
|
|
#define ACCOUNT_PASSWORD_FOLDER (PROFILE_FILESTORE_FOLDER +1)
|
|
#define ACCOUNT_LOCKOUT_FOLDER (ACCOUNT_PASSWORD_FOLDER +1)
|
|
#define ACCOUNT_KERBEROS_FOLDER (ACCOUNT_LOCKOUT_FOLDER +1)
|
|
|
|
//
|
|
// Profile/Local level folders
|
|
//
|
|
#define LOCAL_AUDIT_FOLDER (ACCOUNT_KERBEROS_FOLDER +1)
|
|
#define LOCAL_PRIVILEGE_FOLDER (LOCAL_AUDIT_FOLDER +1)
|
|
#define LOCAL_OTHER_FOLDER (LOCAL_PRIVILEGE_FOLDER +1)
|
|
|
|
//
|
|
// Profile/Eventlog level folders
|
|
//
|
|
#define EVENTLOG_LOG_FOLDER (LOCAL_OTHER_FOLDER +1)
|
|
|
|
|
|
#define NUM_FOLDERS (LOCAL_OTHER_FOLDER +1)
|
|
//#define NUM_FOLDERS (EVENTLOG_LOG_FOLDER +1)
|
|
|
|
//
|
|
// #defines to identify which folders belong in which sections
|
|
//
|
|
#define FIRST_STATIC_FOLDER ANALYSIS_FOLDER
|
|
#define LAST_STATIC_FOLDER CONFIGURATION_FOLDER
|
|
#define FIRST_PROFILE_FOLDER PROFILE_ACCOUNT_FOLDER
|
|
#define LAST_PROFILE_FOLDER PROFILE_DSOBJECT_FOLDER
|
|
#define LAST_PROFILE_NODS_FOLDER PROFILE_FILESTORE_FOLDER
|
|
#define LAST_LOCALPOL_FOLDER PROFILE_LOCAL_FOLDER
|
|
#define FIRST_ACCOUNT_FOLDER ACCOUNT_PASSWORD_FOLDER
|
|
#define LAST_ACCOUNT_NODS_FOLDER ACCOUNT_LOCKOUT_FOLDER
|
|
//
|
|
// remove kerberos section from NT5 for now
|
|
//
|
|
#if defined(_NT4BACK_PORT) || !defined(USE_KERBEROS)
|
|
#define LAST_ACCOUNT_FOLDER ACCOUNT_LOCKOUT_FOLDER
|
|
#else
|
|
#define LAST_ACCOUNT_FOLDER ACCOUNT_KERBEROS_FOLDER
|
|
#endif
|
|
#define FIRST_LOCAL_FOLDER LOCAL_AUDIT_FOLDER
|
|
#define LAST_LOCAL_FOLDER LOCAL_OTHER_FOLDER
|
|
#define FIRST_EVENTLOG_FOLDER EVENTLOG_LOG_FOLDER
|
|
#define LAST_EVENTLOG_FOLDER EVENTLOG_LOG_FOLDER
|
|
|
|
//
|
|
// The actual folder data
|
|
// This must be kept in sync with the above #defines
|
|
// should be initialized based on the #defines rather than
|
|
// independantly on them. Let the compiler keep things
|
|
// accurate for us
|
|
//
|
|
FOLDER_DATA SecmgrFolders[NUM_FOLDERS] =
|
|
{
|
|
{ IDS_ANALYZE, IDS_ANALYZE_DESC, ANALYSIS},
|
|
{ IDS_CONFIGURE, IDS_CONFIGURE_DESC, CONFIGURATION},
|
|
{ IDS_ACCOUNT_POLICY, IDS_ACCOUNT_DESC, POLICY_ACCOUNT},
|
|
{ IDS_LOCAL_POLICY, IDS_LOCAL_DESC, POLICY_LOCAL},
|
|
{ IDS_EVENT_LOG, IDS_EVENT_LOG, POLICY_LOG},
|
|
{ IDS_GROUPS, IDS_GROUPS_DESC, AREA_GROUPS},
|
|
{ IDS_SERVICE, IDS_SERVICE_DESC, AREA_SERVICE},
|
|
{ IDS_REGISTRY, IDS_REGISTRY_DESC, AREA_REGISTRY},
|
|
{ IDS_FILESTORE, IDS_FILESTORE_DESC, AREA_FILESTORE},
|
|
{ IDS_PASSWORD_CATEGORY, IDS_PASSWORD_CATEGORY, POLICY_PASSWORD},
|
|
{ IDS_LOCKOUT_CATEGORY, IDS_LOCKOUT_CATEGORY, POLICY_LOCKOUT},
|
|
{ IDS_KERBEROS_CATEGORY, IDS_KERBEROS_CATEGORY, POLICY_KERBEROS},
|
|
{ IDS_EVENT_AUDIT, IDS_EVENT_AUDIT, POLICY_AUDIT},
|
|
{ IDS_PRIVILEGE, IDS_PRIVILEGE_DESC, AREA_PRIVILEGE},
|
|
{ IDS_OTHER_CATEGORY, IDS_OTHER_CATEGORY, POLICY_OTHER},
|
|
};
|
|
|
|
#define ARRAYLEN(x) (sizeof(x) / sizeof((x)[0]))
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: AddLocationsToFolderList
|
|
//
|
|
// Synopsis: Adds the locations from a given registry key to the
|
|
// folder list. Returns the number of locations added.
|
|
// Helper function for CreateFolderList
|
|
//
|
|
// Arguments: [hKey] - the key holding the locations
|
|
// [dwMode] - the mode SCAT is running in
|
|
// [bCheckForDupes] - TRUE to check for duplicates before adding
|
|
// [pPos] - output only
|
|
//
|
|
// Returns: *[pPos] - the position in m_pScopeItemList of the first
|
|
// folder created
|
|
// the number of child folders created
|
|
//
|
|
// Modifies: CComponentDataImpl::m_pScopeItemList
|
|
//
|
|
// History: 7-26-l999 RobCap broken out from CreateFolderList
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
INT
|
|
CComponentDataImpl::AddLocationsToFolderList(HKEY hKey,
|
|
DWORD dwMode,
|
|
BOOL bCheckForDupes,
|
|
POSITION *pPos) {
|
|
LPTSTR tmpstr=NULL;
|
|
WCHAR pBuf[MAX_PATH];
|
|
DWORD BufSize = MAX_PATH;
|
|
WCHAR pExpanded[MAX_PATH];
|
|
FILETIME LastWriteTime;
|
|
PWSTR Desc=NULL;
|
|
CFolder *folder =NULL;
|
|
INT nCount = 0;
|
|
DWORD status = 0;
|
|
HRESULT hr = S_OK;
|
|
//
|
|
// enumerate all subkeys of the key
|
|
//
|
|
int iTotal = 0;
|
|
do {
|
|
memset(pBuf, '\0', MAX_PATH*sizeof(WCHAR));
|
|
BufSize = MAX_PATH;
|
|
|
|
status = RegEnumKeyEx(hKey,
|
|
nCount,
|
|
pBuf,
|
|
&BufSize,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&LastWriteTime);
|
|
|
|
if ( NO_ERROR == status ) {
|
|
//
|
|
// get description of this location (subkey)
|
|
//
|
|
MyRegQueryValue( hKey,
|
|
pBuf,
|
|
L"Description", // Value name (not localized)
|
|
(PVOID*)&Desc,
|
|
&BufSize );
|
|
|
|
//
|
|
// replace '/' with '\' because Registry does not
|
|
// take '\' in a single key
|
|
//
|
|
tmpstr = wcschr(pBuf, L'/');
|
|
while (tmpstr) {
|
|
*tmpstr = L'\\';
|
|
tmpstr = wcschr(tmpstr, L'/');
|
|
}
|
|
|
|
if (!ExpandEnvironmentStrings(pBuf,pExpanded,MAX_PATH)) {
|
|
wcsncpy(pExpanded,pBuf,BufSize);
|
|
}
|
|
|
|
if (bCheckForDupes) {
|
|
//
|
|
// Make sure we haven't already added this directory
|
|
//
|
|
POSITION pos;
|
|
BOOL bDuplicate = FALSE;
|
|
pos = m_scopeItemList.GetHeadPosition();
|
|
for (int i=0;i < m_scopeItemList.GetCount(); i++) {
|
|
folder = m_scopeItemList.GetAt(pos);
|
|
if (folder && (0 == lstrcmp(folder->GetName(),pExpanded))) {
|
|
bDuplicate = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bDuplicate) {
|
|
if ( Desc )
|
|
LocalFree(Desc);
|
|
Desc = NULL;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
folder = new CFolder();
|
|
|
|
if (folder) {
|
|
if( _wchdir( pExpanded ) ){
|
|
folder->SetState( CFolder::state_InvalidTemplate );
|
|
}
|
|
//
|
|
// Create the folder objects with static data
|
|
//
|
|
hr = folder->Create(pExpanded, // Name
|
|
Desc, // Description
|
|
NULL, // inf file name
|
|
CONFIG_FOLDER_IDX, // closed icon index
|
|
CONFIG_FOLDER_IDX, // open icon index
|
|
LOCATIONS, // folder type
|
|
TRUE, // has children
|
|
dwMode, // SCE mode
|
|
NULL); // Extra Data
|
|
if (SUCCEEDED(hr)) {
|
|
m_scopeItemList.AddTail(folder);
|
|
|
|
if ( iTotal == 0 && NULL != pPos && !bCheckForDupes) {
|
|
*pPos = m_scopeItemList.GetTailPosition();
|
|
}
|
|
} else { // if can't create, then quit doing it anymore, no more reason to continue
|
|
delete folder;
|
|
if ( Desc )
|
|
LocalFree(Desc);
|
|
Desc = NULL;
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
hr = E_OUTOFMEMORY;
|
|
if ( Desc )
|
|
LocalFree(Desc);
|
|
Desc = NULL;
|
|
break;
|
|
}
|
|
|
|
if ( Desc ) {
|
|
LocalFree(Desc);
|
|
}
|
|
Desc = NULL;
|
|
|
|
nCount++;
|
|
iTotal++;
|
|
}
|
|
} while ( status != ERROR_NO_MORE_ITEMS );
|
|
|
|
return nCount;
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: CreateFolderList
|
|
//
|
|
// Synopsis: Adds the children folders of pFolder to m_pScopeItemList
|
|
// and returns the location of the first such folder and the
|
|
// number added
|
|
//
|
|
// Arguments: [pFolder] - the folder whose children we want to find
|
|
// [type] - the type of that folder
|
|
// [pPos] - output only
|
|
// [Count] - output only
|
|
//
|
|
// Returns: *[pPos] - the position in m_pScopeItemList of the first
|
|
// folder created
|
|
// *[Count] - the number of child folders created
|
|
//
|
|
// Modifies: CComponentDataImpl::m_pScopeItemList
|
|
//
|
|
// History: 12-15-1997 RobCap made dynamic based on mode
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
HRESULT
|
|
CComponentDataImpl::CreateFolderList(CFolder *pFolder, // Optional, In
|
|
FOLDER_TYPES type, // In
|
|
POSITION *pPos, // Optional, Out
|
|
INT *Count) // Optional, Out,
|
|
{
|
|
CFolder* folder = 0;
|
|
|
|
INT nStart = 0;
|
|
INT nCount = 0;
|
|
BOOL bHasChildren = FALSE;
|
|
struct _wfinddata_t findData;
|
|
intptr_t hFile = 0;
|
|
WCHAR pBuf[MAX_PATH];
|
|
HKEY hKey = 0;
|
|
DWORD BufSize = 0;
|
|
DWORD status = 0;
|
|
PWSTR Desc=NULL;
|
|
LPTSTR tmpstr=NULL;
|
|
HRESULT hr = S_OK;
|
|
DWORD dwErr = 0;
|
|
|
|
SCESTATUS rc = 0;
|
|
PSCE_OBJECT_CHILDREN ObjectList=NULL;
|
|
PSCE_OBJECT_LIST pObject = 0;
|
|
PSCE_ERROR_LOG_INFO ErrBuf=NULL;
|
|
CString StrErr;
|
|
PSCE_PROFILE_INFO pProfileInfo=NULL;
|
|
FOLDER_TYPES newType;
|
|
PEDITTEMPLATE pet = 0;
|
|
|
|
//
|
|
// initialize dwMode and ModeBits
|
|
//
|
|
|
|
DWORD dwMode=0;
|
|
DWORD ModeBits=0;
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
if (Count)
|
|
*Count = 0;
|
|
|
|
if (pFolder)
|
|
{
|
|
dwMode = pFolder->GetMode();
|
|
ModeBits = pFolder->GetModeBits();
|
|
}
|
|
|
|
//
|
|
// This could take some time, so create a wait curser
|
|
//
|
|
CWaitCursor wc;
|
|
|
|
switch ( type )
|
|
{
|
|
case ROOT:
|
|
//
|
|
// Initial standalone mode root mode
|
|
//
|
|
|
|
folder = new CFolder();
|
|
|
|
if (!folder)
|
|
return E_OUTOFMEMORY;
|
|
|
|
if ( GetImplType() == SCE_IMPL_TYPE_SAV )
|
|
{
|
|
dwMode = SCE_MODE_VIEWER;
|
|
newType = ANALYSIS;
|
|
}
|
|
else if ( GetImplType() == SCE_IMPL_TYPE_SCE )
|
|
{
|
|
dwMode = SCE_MODE_EDITOR;
|
|
newType = CONFIGURATION;
|
|
}
|
|
else if ( GetImplType() == SCE_IMPL_TYPE_LS)
|
|
{
|
|
dwMode = SCE_MODE_LOCALSEC;
|
|
newType = LOCALPOL;
|
|
}
|
|
else
|
|
{
|
|
dwMode = 0;
|
|
newType = CONFIGURATION;
|
|
}
|
|
//
|
|
// Create the folder objects with static data
|
|
// MMC pulls in the name from the data object
|
|
//
|
|
hr = folder->Create(L"", // Name
|
|
L"", // Description
|
|
NULL, // inf file name
|
|
SCE_IMAGE_IDX, // closed icon index
|
|
SCE_IMAGE_IDX, // open icon index
|
|
newType, // folder type
|
|
TRUE, // has children
|
|
dwMode, // SCE Mode
|
|
NULL); // Extra Data
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
folder->SetCookie(NULL);
|
|
switch (m_Mode)
|
|
{
|
|
case SCE_MODE_DOMAIN_COMPUTER:
|
|
case SCE_MODE_OU_COMPUTER:
|
|
case SCE_MODE_LOCAL_COMPUTER:
|
|
case SCE_MODE_REMOTE_COMPUTER:
|
|
m_computerModeBits = folder->GetModeBits();
|
|
break;
|
|
|
|
case SCE_MODE_REMOTE_USER:
|
|
case SCE_MODE_LOCAL_USER:
|
|
case SCE_MODE_DOMAIN_USER:
|
|
case SCE_MODE_OU_USER:
|
|
m_userModeBits = folder->GetModeBits();
|
|
break;
|
|
|
|
default:
|
|
m_computerModeBits = folder->GetModeBits();
|
|
break;
|
|
}
|
|
|
|
m_scopeItemList.AddTail(folder);
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
delete folder;
|
|
return hr;
|
|
}
|
|
|
|
|
|
case ANALYSIS:
|
|
pFolder->SetInfFile(GT_COMPUTER_TEMPLATE);
|
|
m_AnalFolder = pFolder;
|
|
//
|
|
// Very first time initialization of the sad name.
|
|
// Ask the user to get a sad name if none exists.
|
|
//
|
|
if(!m_AnalFolder && SadName.IsEmpty() )
|
|
OnOpenDataBase();
|
|
//
|
|
// enumerate security areas for analysis
|
|
//
|
|
if ( !SadHandle )
|
|
LoadSadInfo(TRUE);
|
|
|
|
//
|
|
// The data under the Analysis node is not valid right now,
|
|
// so don't display any folders
|
|
//
|
|
if (m_bIsLocked)
|
|
return S_OK;
|
|
|
|
//
|
|
// We weren't able to load the Analysis data even though we're
|
|
// not in the middle of an action that should be blocking it
|
|
//
|
|
if ( SadErrored != ERROR_SUCCESS || !SadHandle)
|
|
return E_FAIL;
|
|
|
|
nStart = FIRST_PROFILE_FOLDER;
|
|
|
|
//
|
|
// Display all but the DS Objects folder
|
|
//
|
|
nCount = LAST_PROFILE_NODS_FOLDER - FIRST_PROFILE_FOLDER +1;
|
|
bHasChildren = FALSE;
|
|
break;
|
|
|
|
case AREA_REGISTRY_ANALYSIS:
|
|
case AREA_FILESTORE_ANALYSIS:
|
|
if ( SadHandle == NULL )
|
|
{
|
|
//
|
|
// We shouldn't be able to get this far without a SadHandle
|
|
//
|
|
ASSERT(FALSE);
|
|
return E_FAIL;
|
|
}
|
|
|
|
if (m_bIsLocked)
|
|
{
|
|
//
|
|
// We shouldn't be able to get this far if we're locked
|
|
//
|
|
ASSERT(FALSE);
|
|
return E_FAIL;
|
|
}
|
|
|
|
switch ( type )
|
|
{
|
|
case AREA_REGISTRY_ANALYSIS:
|
|
status = AREA_REGISTRY_SECURITY; // use status temporatorily
|
|
newType = REG_OBJECTS;
|
|
break;
|
|
|
|
case AREA_FILESTORE_ANALYSIS:
|
|
status = AREA_FILE_SECURITY;
|
|
newType = FILE_OBJECTS;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
//
|
|
// get the object roots
|
|
//
|
|
pet = GetTemplate(GT_LAST_INSPECTION,status,&dwErr);
|
|
if (!pet)
|
|
{
|
|
CString strErr;
|
|
strErr.LoadString(dwErr);
|
|
AfxMessageBox(strErr);
|
|
return E_FAIL;
|
|
}
|
|
pProfileInfo = pet->pTemplate;
|
|
|
|
if ( pProfileInfo )
|
|
{
|
|
//
|
|
// add the object roots
|
|
//
|
|
if ( type == AREA_REGISTRY_ANALYSIS)
|
|
pObject = pProfileInfo->pRegistryKeys.pOneLevel;
|
|
else if ( type == AREA_FILESTORE_ANALYSIS )
|
|
pObject = pProfileInfo->pFiles.pOneLevel;
|
|
else
|
|
pObject = pProfileInfo->pDsObjects.pOneLevel;
|
|
|
|
for (; pObject!=NULL; pObject=pObject->Next)
|
|
{
|
|
CString strRoot;
|
|
strRoot = (LPCTSTR)pObject->Name;
|
|
if (AREA_FILESTORE_ANALYSIS == type)
|
|
{
|
|
//
|
|
// We want c:\, not c: here.
|
|
//
|
|
strRoot += L"\\";
|
|
}
|
|
//
|
|
// These are the roots of the objects.
|
|
// They are always containers
|
|
//
|
|
|
|
if (SCE_STATUS_NO_ACL_SUPPORT == pObject->Status)
|
|
{
|
|
folder = CreateAndAddOneNode(pFolder,
|
|
// pObject->Name,
|
|
strRoot,
|
|
pBuf,
|
|
newType,
|
|
FALSE,
|
|
GT_COMPUTER_TEMPLATE,
|
|
pObject,
|
|
pObject->Status);
|
|
}
|
|
else
|
|
{
|
|
folder = CreateAndAddOneNode(
|
|
pFolder, // Parent folder
|
|
// pObject->Name, // Name
|
|
strRoot,
|
|
pBuf, // Description
|
|
newType, // Folder Type
|
|
TRUE, // Has Children?
|
|
GT_COMPUTER_TEMPLATE, // INF File
|
|
pObject, // Extra Data: the object
|
|
pObject->Status); // Status
|
|
}
|
|
|
|
if(folder)
|
|
folder->SetDesc( pObject->Status, pObject->Count );
|
|
}
|
|
}
|
|
return S_OK;
|
|
|
|
case REG_OBJECTS:
|
|
case FILE_OBJECTS:
|
|
if ( SadHandle == NULL )
|
|
{
|
|
|
|
//
|
|
// We shouldn't be able to get this far without a SadHandle
|
|
//
|
|
ASSERT(FALSE);
|
|
return E_FAIL;
|
|
}
|
|
|
|
if ( type == REG_OBJECTS)
|
|
status = AREA_REGISTRY_SECURITY;
|
|
else if ( type == FILE_OBJECTS )
|
|
status = AREA_FILE_SECURITY;
|
|
else
|
|
{
|
|
ASSERT(FALSE);
|
|
return E_FAIL;
|
|
}
|
|
|
|
//
|
|
// get the next level objects
|
|
//
|
|
rc = SceGetObjectChildren(SadHandle, // hProfile
|
|
SCE_ENGINE_SAP, // Profile type
|
|
(AREA_INFORMATION)status, // Area
|
|
(LPTSTR)(pFolder->GetName()),// Object prefix
|
|
&ObjectList, // Object list [out]
|
|
&ErrBuf); // Error list [out]
|
|
if ( ErrBuf )
|
|
{ // rc != SCESTATUS_SUCCESS ) {
|
|
MyFormatResMessage(rc, IDS_ERROR_GETTING_LAST_ANALYSIS, ErrBuf, StrErr);
|
|
|
|
SceFreeMemory((PVOID)ErrBuf, SCE_STRUCT_ERROR_LOG_INFO);
|
|
ErrBuf = NULL;
|
|
}
|
|
if ( rc == SCESTATUS_SUCCESS &&
|
|
ObjectList )
|
|
{
|
|
BOOL bContainer = FALSE;
|
|
//
|
|
// add the objects
|
|
//
|
|
PSCE_OBJECT_CHILDREN_NODE *pObjNode = &(ObjectList->arrObject);
|
|
|
|
for (DWORD i=0; i<ObjectList->nCount;i++)
|
|
{
|
|
//
|
|
// These are the next level objects
|
|
//
|
|
if ( pObjNode[i] == NULL ||
|
|
pObjNode[i]->Name == NULL )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (SCE_STATUS_NO_ACL_SUPPORT == pObjNode[i]->Status)
|
|
{
|
|
// No ACL support, so don't add sub objects
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// If there are any mismatched child objects then we know
|
|
// that this is a container, otherwise we have to check the
|
|
// object on the system to find out if it is a container
|
|
//
|
|
if ( pObjNode[i]->Count > 0 )
|
|
bContainer = TRUE;
|
|
else
|
|
{
|
|
if (FILE_OBJECTS == type)
|
|
{
|
|
//
|
|
// Check if a file object is a container
|
|
//
|
|
CString strPath;
|
|
DWORD dwAttr = 0;
|
|
|
|
strPath = pFolder->GetName();
|
|
if (strPath.Right(1) != L"\\")
|
|
{
|
|
strPath += L"\\";
|
|
}
|
|
strPath += pObjNode[i]->Name;
|
|
|
|
dwAttr = GetFileAttributes(strPath);
|
|
if (0xFFFFFFFF == dwAttr)
|
|
bContainer = FALSE;
|
|
else
|
|
bContainer = dwAttr & FILE_ATTRIBUTE_DIRECTORY;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Always treat Registry Keys and DS Objects as containers
|
|
//
|
|
bContainer = TRUE;
|
|
}
|
|
}
|
|
if (bContainer)
|
|
{
|
|
StrErr = pFolder->GetName();
|
|
if (StrErr.Right(1) != L"\\")
|
|
StrErr += L"\\";
|
|
|
|
StrErr += pObjNode[i]->Name;
|
|
folder = CreateAndAddOneNode(
|
|
pFolder, // Parent folder
|
|
(LPTSTR)((LPCTSTR)StrErr), // Name
|
|
pBuf, // Description
|
|
type, // Folder Type
|
|
TRUE, // Has Children?
|
|
GT_COMPUTER_TEMPLATE, // INF File
|
|
NULL,
|
|
pObjNode[i]->Status); // Object Status
|
|
if(folder)
|
|
{
|
|
folder->SetDesc( pObjNode[i]->Status,
|
|
pObjNode[i]->Count );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ObjectList )
|
|
SceFreeMemory((PVOID)ObjectList, SCE_STRUCT_OBJECT_CHILDREN );
|
|
|
|
return S_OK;
|
|
|
|
case CONFIGURATION:
|
|
{
|
|
//
|
|
// enumerate profile locations in registry
|
|
//
|
|
CString strLocations;
|
|
|
|
m_ConfigFolder = pFolder;
|
|
nCount = 0;
|
|
|
|
if (strLocations.LoadString(IDS_TEMPLATE_LOCATION_KEY))
|
|
{
|
|
//
|
|
// Bug 375324 - Merge HKCU locations with HKLM locations
|
|
//
|
|
status = RegOpenKeyEx( HKEY_CURRENT_USER,
|
|
strLocations,
|
|
0, KEY_READ, &hKey);
|
|
|
|
if ( NO_ERROR == status )
|
|
{
|
|
nCount += AddLocationsToFolderList(hKey,dwMode,FALSE,pPos);
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
if ( 0 == nCount )
|
|
{
|
|
//
|
|
// Empty location list, so add a default
|
|
//
|
|
CString strDefLoc;
|
|
CString strDefLocEx;
|
|
strDefLoc.LoadString(IDS_DEFAULT_LOCATION);
|
|
int iLen = strDefLoc.GetLength()+MAX_PATH;
|
|
LPWSTR pBuffer = strDefLocEx.GetBuffer(iLen);
|
|
if (ExpandEnvironmentStrings(strDefLoc, pBuffer, iLen))
|
|
{
|
|
//
|
|
// must use pBuffer here since strDefLocEx has not been released
|
|
//
|
|
AddTemplateLocation(pFolder,pBuffer,FALSE,TRUE);
|
|
}
|
|
else
|
|
AddTemplateLocation(pFolder,strDefLoc,FALSE,TRUE);
|
|
|
|
strDefLocEx.ReleaseBuffer();
|
|
}
|
|
}
|
|
|
|
if ( Count != NULL )
|
|
*Count = nCount;
|
|
|
|
return hr;
|
|
}
|
|
|
|
case LOCATIONS:
|
|
//
|
|
// enumerate available profiles under the location (*.inf files)
|
|
//
|
|
|
|
//
|
|
// pFolder is required in this case
|
|
//
|
|
if (!pFolder)
|
|
return E_INVALIDARG;
|
|
|
|
swprintf(pBuf, L"%s\\*.inf",
|
|
(LPTSTR)(pFolder->GetName()));
|
|
bHasChildren = FALSE;
|
|
|
|
hFile = _wfindfirst(pBuf, &findData);
|
|
|
|
if ( hFile != -1)
|
|
{
|
|
do {
|
|
//
|
|
// Don't add this item to the node if it is a subdirectory.
|
|
//
|
|
CString strDisplay;
|
|
strDisplay.Format(
|
|
TEXT("%s\\%s"),
|
|
(LPCTSTR)(pFolder->GetName()),
|
|
findData.name);
|
|
|
|
if( findData.attrib & _A_SUBDIR )
|
|
continue;
|
|
|
|
//
|
|
// get template's description
|
|
//
|
|
strDisplay = findData.name;
|
|
//
|
|
// GetLength has to be at least 4, since we searched on *.inf
|
|
//
|
|
strDisplay = strDisplay.Left(strDisplay.GetLength() - 4);
|
|
swprintf(pBuf,
|
|
L"%s\\%s",
|
|
(LPTSTR)(pFolder->GetName()),
|
|
findData.name);
|
|
if (! GetProfileDescription(pBuf, &Desc) )
|
|
Desc = NULL;
|
|
else
|
|
{
|
|
//
|
|
// No problem; we just won't display a description
|
|
//
|
|
}
|
|
|
|
nCount++;
|
|
folder = new CFolder();
|
|
|
|
if (folder)
|
|
{
|
|
//
|
|
// Create the folder objects
|
|
// save full file name her
|
|
//
|
|
hr = folder->Create((LPCTSTR)strDisplay, // Name
|
|
Desc, // Description
|
|
pBuf, // inf file name
|
|
TEMPLATES_IDX, // closed icon index
|
|
TEMPLATES_IDX, // open icon index
|
|
PROFILE, // folder type
|
|
bHasChildren, // has children
|
|
dwMode, // SCE Mode
|
|
NULL); // Extra Data
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_scopeItemList.AddTail(folder);
|
|
|
|
if ( nCount == 1 && NULL != pPos )
|
|
{
|
|
*pPos = m_scopeItemList.GetTailPosition();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
delete folder;
|
|
folder = NULL;
|
|
}
|
|
}
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
if (Desc)
|
|
{
|
|
LocalFree(Desc);
|
|
Desc = NULL;
|
|
}
|
|
} while ( _wfindnext(hFile, &findData) == 0 );
|
|
}
|
|
|
|
_findclose(hFile);
|
|
|
|
if ( Count != NULL )
|
|
*Count = nCount;
|
|
|
|
return hr;
|
|
|
|
case PROFILE:
|
|
{
|
|
TCHAR pszGPTPath[MAX_PATH*5];
|
|
SCESTATUS scestatus = 0;
|
|
//
|
|
// enumerate security areas for this profile
|
|
//
|
|
|
|
if (ModeBits & MB_NO_NATIVE_NODES)
|
|
{
|
|
//
|
|
//
|
|
//
|
|
nStart = nCount = 0;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Find the path to the SCE template within the GPT template
|
|
//
|
|
if (ModeBits & MB_GROUP_POLICY)
|
|
{
|
|
//
|
|
// get GPT root path
|
|
//
|
|
hr = m_pGPTInfo->GetFileSysPath(GPO_SECTION_MACHINE,
|
|
pszGPTPath,
|
|
ARRAYSIZE(pszGPTPath));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (NULL == m_szSingleTemplateName)
|
|
{
|
|
//
|
|
// Allocate memory for the pszGPTPath + <backslash> + GPTSCE_TEMPLATE + <trailing nul>
|
|
//
|
|
m_szSingleTemplateName = (LPTSTR) LocalAlloc(LPTR,(lstrlen(pszGPTPath)+lstrlen(GPTSCE_TEMPLATE)+2)*sizeof(TCHAR));
|
|
}
|
|
if (NULL != m_szSingleTemplateName)
|
|
{
|
|
lstrcpy(m_szSingleTemplateName,pszGPTPath);
|
|
lstrcat(m_szSingleTemplateName,L"\\" GPTSCE_TEMPLATE);
|
|
|
|
PSCE_PROFILE_INFO spi = NULL;
|
|
//
|
|
// Create a new template there if there isn't one already
|
|
//
|
|
if (!CreateNewProfile(m_szSingleTemplateName,&spi))
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
if (!GetTemplate(m_szSingleTemplateName) && spi)
|
|
{
|
|
//
|
|
// bug 265996
|
|
//
|
|
// The first time a GPO's Security Settings are opened we create
|
|
// the file, but if it's on a remote machine it may not have been
|
|
// created yet when we try to open it
|
|
//
|
|
// Since we know what's going to be in it once it's created we
|
|
// can skip the open step and just shove our template into the
|
|
// cache
|
|
|
|
//
|
|
// Allocate space for key.
|
|
//
|
|
LPTSTR szKey = new TCHAR[ lstrlen( m_szSingleTemplateName ) + 1];
|
|
if(!szKey)
|
|
{
|
|
return NULL;
|
|
}
|
|
lstrcpy(szKey, m_szSingleTemplateName);
|
|
_wcslwr( szKey );
|
|
|
|
//
|
|
// Create a new CEditTemplate
|
|
//
|
|
|
|
CEditTemplate *pTemplateInfo = new CEditTemplate;
|
|
if (pTemplateInfo)
|
|
{
|
|
pTemplateInfo->SetInfFile(m_szSingleTemplateName);
|
|
pTemplateInfo->SetNotificationWindow(m_pNotifier);
|
|
pTemplateInfo->pTemplate = spi;
|
|
//
|
|
// This is a brand new template; ergo everything's loaded
|
|
//
|
|
pTemplateInfo->AddArea(AREA_ALL);
|
|
|
|
|
|
//
|
|
// Stick it in the cache
|
|
//
|
|
m_Templates.SetAt(szKey, pTemplateInfo);
|
|
|
|
//
|
|
// expand registry value section based on registry values list on local machine
|
|
//
|
|
SceRegEnumAllValues(
|
|
&(pTemplateInfo->pTemplate->RegValueCount),
|
|
&(pTemplateInfo->pTemplate->aRegValues));
|
|
}
|
|
|
|
if (szKey)
|
|
delete[] szKey;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
nStart = FIRST_PROFILE_FOLDER;
|
|
|
|
//
|
|
// Display all but the DS Objects folder
|
|
//
|
|
nCount = LAST_PROFILE_NODS_FOLDER - FIRST_PROFILE_FOLDER +1;
|
|
|
|
|
|
bHasChildren = FALSE;
|
|
tmpstr = pFolder->GetInfFile(); // inf file full path name
|
|
//
|
|
// If this folder is in a write-through mode then set that
|
|
// on the template
|
|
//
|
|
PEDITTEMPLATE pie;
|
|
pie = GetTemplate(tmpstr);
|
|
if ( pie )
|
|
{
|
|
if (ModeBits & MB_WRITE_THROUGH)
|
|
{
|
|
pie->SetWriteThrough(TRUE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Mark as bad template.
|
|
//
|
|
pFolder->SetState( CFolder::state_InvalidTemplate );
|
|
nCount = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case LOCALPOL:
|
|
{
|
|
nStart = FIRST_PROFILE_FOLDER;
|
|
nCount = LAST_LOCALPOL_FOLDER - FIRST_PROFILE_FOLDER +1;
|
|
bHasChildren = FALSE;
|
|
pFolder->SetInfFile(GT_LOCAL_POLICY);
|
|
break;
|
|
}
|
|
|
|
case POLICY_ACCOUNT:
|
|
if (!pFolder)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
tmpstr = pFolder->GetInfFile();
|
|
}
|
|
// fall through;
|
|
case LOCALPOL_ACCOUNT:
|
|
case POLICY_ACCOUNT_ANALYSIS:
|
|
nStart = FIRST_ACCOUNT_FOLDER;
|
|
if (ModeBits & MB_DS_OBJECTS_SECTION)
|
|
{
|
|
//
|
|
// Include the DC Specific folders
|
|
//
|
|
nCount = LAST_ACCOUNT_FOLDER - FIRST_ACCOUNT_FOLDER + 1;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Display all but the DC Specific folders
|
|
//
|
|
nCount = LAST_ACCOUNT_NODS_FOLDER - FIRST_ACCOUNT_FOLDER +1;
|
|
}
|
|
bHasChildren = FALSE;
|
|
break;
|
|
|
|
case POLICY_LOCAL:
|
|
if (!pFolder)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
tmpstr = pFolder->GetInfFile();
|
|
}
|
|
// fall through;
|
|
case LOCALPOL_LOCAL:
|
|
case POLICY_LOCAL_ANALYSIS:
|
|
nStart = FIRST_LOCAL_FOLDER;
|
|
nCount = LAST_LOCAL_FOLDER - FIRST_LOCAL_FOLDER +1;
|
|
bHasChildren = FALSE;
|
|
break;
|
|
|
|
case POLICY_EVENTLOG:
|
|
if (!pFolder)
|
|
return E_INVALIDARG;
|
|
else
|
|
tmpstr = pFolder->GetInfFile();
|
|
// fall through;
|
|
case LOCALPOL_EVENTLOG:
|
|
case POLICY_EVENTLOG_ANALYSIS:
|
|
nStart = FIRST_EVENTLOG_FOLDER;
|
|
nCount = LAST_EVENTLOG_FOLDER - FIRST_EVENTLOG_FOLDER +1;
|
|
bHasChildren = FALSE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
|
|
if ( Count != NULL )
|
|
*Count = nCount;
|
|
|
|
CString cStrName;
|
|
CString cStrDesc;
|
|
|
|
|
|
for (int i=nStart; i < nStart+nCount; i++)
|
|
{
|
|
folder = new CFolder();
|
|
|
|
if (!folder)
|
|
{
|
|
//
|
|
// What about other folders that we've created?
|
|
//
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
if (!cStrName.LoadString(SecmgrFolders[i].ResID) ||
|
|
!cStrDesc.LoadString(SecmgrFolders[i].DescID))
|
|
{
|
|
delete folder;
|
|
return E_FAIL;
|
|
}
|
|
|
|
//
|
|
// Create the folder objects with static data
|
|
//
|
|
if (type == ANALYSIS ||
|
|
type == AREA_POLICY_ANALYSIS ||
|
|
type == POLICY_ACCOUNT_ANALYSIS ||
|
|
type == POLICY_LOCAL_ANALYSIS ||
|
|
type == POLICY_EVENTLOG_ANALYSIS )
|
|
{
|
|
if (m_bIsLocked)
|
|
{
|
|
nCount = 0;
|
|
|
|
|
|
delete folder;
|
|
// Should display an "in use" message in result pane
|
|
|
|
//
|
|
// We're not adding anything, but we're not actually failing
|
|
//
|
|
return S_OK;
|
|
}
|
|
|
|
switch (SecmgrFolders[i].type)
|
|
{
|
|
case AREA_POLICY:
|
|
newType = AREA_POLICY_ANALYSIS;
|
|
break;
|
|
|
|
case AREA_PRIVILEGE:
|
|
newType = AREA_PRIVILEGE_ANALYSIS;
|
|
break;
|
|
|
|
case AREA_GROUPS:
|
|
newType = AREA_GROUPS_ANALYSIS;
|
|
break;
|
|
|
|
case AREA_SERVICE:
|
|
newType = AREA_SERVICE_ANALYSIS;
|
|
tmpstr = GT_COMPUTER_TEMPLATE;
|
|
break;
|
|
|
|
case AREA_REGISTRY:
|
|
newType = AREA_REGISTRY_ANALYSIS;
|
|
break;
|
|
|
|
case AREA_FILESTORE:
|
|
newType = AREA_FILESTORE_ANALYSIS;
|
|
break;
|
|
|
|
case POLICY_ACCOUNT:
|
|
newType = POLICY_ACCOUNT_ANALYSIS;
|
|
break;
|
|
|
|
case POLICY_LOCAL:
|
|
newType = POLICY_LOCAL_ANALYSIS;
|
|
break;
|
|
|
|
case POLICY_EVENTLOG:
|
|
newType = POLICY_EVENTLOG_ANALYSIS;
|
|
break;
|
|
|
|
case POLICY_PASSWORD:
|
|
newType = POLICY_PASSWORD_ANALYSIS;
|
|
break;
|
|
|
|
case POLICY_KERBEROS:
|
|
newType = POLICY_KERBEROS_ANALYSIS;
|
|
break;
|
|
|
|
case POLICY_LOCKOUT:
|
|
newType = POLICY_LOCKOUT_ANALYSIS;
|
|
break;
|
|
|
|
case POLICY_AUDIT:
|
|
newType = POLICY_AUDIT_ANALYSIS;
|
|
break;
|
|
|
|
case POLICY_OTHER:
|
|
newType = POLICY_OTHER_ANALYSIS;
|
|
break;
|
|
|
|
case POLICY_LOG:
|
|
newType = POLICY_LOG_ANALYSIS;
|
|
break;
|
|
|
|
default:
|
|
newType = SecmgrFolders[i].type;
|
|
break;
|
|
}
|
|
|
|
int nImage = GetScopeImageIndex(newType);
|
|
|
|
hr = folder->Create(cStrName.GetBuffer(2), // Name
|
|
cStrDesc.GetBuffer(2), // Description
|
|
tmpstr, // inf file name
|
|
nImage, // closed icon index
|
|
nImage, // open icon index
|
|
newType, // folder type
|
|
bHasChildren, // has children
|
|
dwMode, // SCE Mode
|
|
NULL); // Extra Data
|
|
}
|
|
else if (type == LOCALPOL ||
|
|
type == AREA_LOCALPOL ||
|
|
type == LOCALPOL_ACCOUNT ||
|
|
type == LOCALPOL_LOCAL ||
|
|
type == LOCALPOL_EVENTLOG )
|
|
{
|
|
if (m_bIsLocked)
|
|
{
|
|
nCount = 0;
|
|
|
|
delete folder;
|
|
// Should display an "in use" message in result pane
|
|
|
|
//
|
|
// We're not adding anything, but we're not actually failing
|
|
//
|
|
return S_OK;
|
|
}
|
|
|
|
tmpstr = GT_LOCAL_POLICY;
|
|
switch (SecmgrFolders[i].type)
|
|
{
|
|
case AREA_POLICY:
|
|
newType = AREA_LOCALPOL;
|
|
break;
|
|
|
|
case POLICY_ACCOUNT:
|
|
newType = LOCALPOL_ACCOUNT;
|
|
break;
|
|
|
|
case POLICY_LOCAL:
|
|
newType = LOCALPOL_LOCAL;
|
|
break;
|
|
|
|
case POLICY_EVENTLOG:
|
|
newType = LOCALPOL_EVENTLOG;
|
|
break;
|
|
|
|
case POLICY_PASSWORD:
|
|
newType = LOCALPOL_PASSWORD;
|
|
break;
|
|
|
|
case POLICY_KERBEROS:
|
|
newType = LOCALPOL_KERBEROS;
|
|
break;
|
|
|
|
case POLICY_LOCKOUT:
|
|
newType = LOCALPOL_LOCKOUT;
|
|
break;
|
|
|
|
case POLICY_AUDIT:
|
|
newType = LOCALPOL_AUDIT;
|
|
break;
|
|
|
|
case POLICY_OTHER:
|
|
newType = LOCALPOL_OTHER;
|
|
break;
|
|
|
|
case POLICY_LOG:
|
|
newType = LOCALPOL_LOG;
|
|
break;
|
|
|
|
case AREA_PRIVILEGE:
|
|
newType = LOCALPOL_PRIVILEGE;
|
|
break;
|
|
|
|
default:
|
|
newType = SecmgrFolders[i].type;
|
|
break;
|
|
}
|
|
|
|
int nImage = GetScopeImageIndex(newType);
|
|
|
|
hr = folder->Create(cStrName.GetBuffer(2), // Name
|
|
cStrDesc.GetBuffer(2), // Description
|
|
tmpstr, // inf file name
|
|
nImage, // closed icon index
|
|
nImage, // open icon index
|
|
newType, // folder type
|
|
bHasChildren, // has children
|
|
dwMode, // SCE Mode
|
|
NULL); // Extra Data
|
|
}
|
|
else
|
|
{
|
|
int nImage = GetScopeImageIndex(SecmgrFolders[i].type);
|
|
|
|
hr = folder->Create(cStrName.GetBuffer(2), // Name
|
|
cStrDesc.GetBuffer(2), // Description
|
|
tmpstr, // inf file name
|
|
nImage, // closed icon index
|
|
nImage, // open icon index
|
|
SecmgrFolders[i].type, // folder type
|
|
bHasChildren, // has children
|
|
dwMode, // SCE Mode
|
|
NULL); // Extra Data
|
|
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_scopeItemList.AddTail(folder);
|
|
if ( i == nStart && NULL != pPos )
|
|
{
|
|
*pPos = m_scopeItemList.GetTailPosition();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
delete folder;
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Method: EnumerateScopePane
|
|
//
|
|
// Synopsis: Add the child folders of cookie/pParent to MMC's scope pane tree
|
|
//
|
|
// Arguments: [cookie] - The cookie representing the node's who we
|
|
// are enumerating
|
|
// [pParent] - The id of the node we are enumerating
|
|
// [dwMode] - The mode SCE is operating under (only allowed for
|
|
// initial enumeration)
|
|
//
|
|
// Returns: none
|
|
//
|
|
// Modifies: m_ScopeItemList (via CreateFolderList)
|
|
//
|
|
// History: 12-15-1997 Robcap
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void CComponentDataImpl::EnumerateScopePane(MMC_COOKIE cookie, HSCOPEITEM pParent)
|
|
{
|
|
int i = 0;
|
|
ASSERT(m_pScope != NULL); // make sure we QI'ed for the interface
|
|
if (NULL == m_pScope)
|
|
return;
|
|
|
|
|
|
|
|
m_bEnumerateScopePaneCalled = true;
|
|
|
|
|
|
//
|
|
// Enumerate the scope pane
|
|
//
|
|
|
|
// Note - Each cookie in the scope pane represents a folder.
|
|
// A released product may have more then one level of children.
|
|
// This sample assumes the parent node is one level deep.
|
|
|
|
ASSERT(pParent != 0);
|
|
if (0 == pParent)
|
|
return;
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
if (m_scopeItemList.GetCount() == 0 )
|
|
{
|
|
CreateFolderList(NULL, ROOT, NULL, NULL);
|
|
}
|
|
|
|
//
|
|
// Enumerate the scope pane
|
|
// return the folder object that represents the cookie
|
|
// Note - for large list, use dictionary
|
|
//
|
|
CFolder* pThis = FindObject(cookie, NULL);
|
|
if (NULL == pThis)
|
|
pThis = m_AnalFolder;
|
|
|
|
ASSERT(pThis);
|
|
if ( NULL == pThis )
|
|
return;
|
|
|
|
//
|
|
// Note - Each cookie in the scope pane represents a folder.
|
|
//
|
|
|
|
//
|
|
// If we've already enumerated this folder then don't do it again
|
|
//
|
|
if ( pThis->IsEnumerated() )
|
|
return;
|
|
|
|
POSITION pos = NULL;
|
|
int nCount = 0;
|
|
CFolder *pFolder = 0;
|
|
|
|
|
|
//
|
|
// the pParent is the enumerated node's item ID, not its parent ID
|
|
//
|
|
pThis->GetScopeItem()->ID = pParent;
|
|
if (SUCCEEDED(CreateFolderList( pThis,
|
|
pThis->GetType(),
|
|
&pos,
|
|
&nCount )))
|
|
{
|
|
for (i=0; (i < nCount) && (pos != NULL); i++ )
|
|
{
|
|
pFolder = m_scopeItemList.GetNext(pos);
|
|
|
|
ASSERT(NULL != pFolder);
|
|
if ( pFolder == NULL )
|
|
{
|
|
continue;
|
|
}
|
|
LPSCOPEDATAITEM pScope;
|
|
pScope = pFolder->GetScopeItem();
|
|
|
|
ASSERT(NULL != pScope);
|
|
|
|
//
|
|
// Set the parent
|
|
//
|
|
pScope->relativeID = pParent;
|
|
|
|
//
|
|
// Set the folder as the cookie
|
|
//
|
|
pScope->mask |= SDI_PARAM;
|
|
pScope->lParam = reinterpret_cast<LPARAM>(pFolder);
|
|
pFolder->SetCookie(reinterpret_cast<MMC_COOKIE>(pFolder));
|
|
m_pScope->InsertItem(pScope);
|
|
|
|
//
|
|
// Note - On return, the ID member of 'm_pScopeItem'
|
|
// contains the handle to the newly inserted item!
|
|
//
|
|
ASSERT(pScope->ID != NULL);
|
|
}
|
|
|
|
// This was commented out, but is needed to fix
|
|
// 249158: SCE UI: Every time analysis is performed, another set of node appears
|
|
// This flag will prevent the nodes from being re-enumerated.
|
|
// If this doesn't work, then all the child nodes should be deleted before
|
|
// reenumeration
|
|
pThis->Set(TRUE); // folder has been enumerated
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Error creating folder list. Make sure the folder isn't
|
|
// marked as opened so that we can try to expand it again later
|
|
//
|
|
SCOPEDATAITEM item;
|
|
|
|
ZeroMemory (&item, sizeof (item));
|
|
item.mask = SDI_STATE;
|
|
item.nState = 0;
|
|
item.ID = pThis->GetScopeItem()->ID;
|
|
//
|
|
// Nothing else we can do if this returns a failure, so
|
|
// don't worry about it
|
|
//
|
|
(void)m_pScope->SetItem (&item);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------------------------
|
|
CComponentDataImpl::GetColumnInfo
|
|
|
|
Synopsis: Returns the column info for a folder type.
|
|
|
|
Arguments: [fType] - The type of the CFolder item.
|
|
|
|
Returns: a pointer to an int * where int[0] = the resource descritption into g_columnInfo.
|
|
int[1] = the number of columns this array describes.
|
|
NULL - If there is no matching key.
|
|
------------------------------------------------------------------------------------------*/
|
|
PSCE_COLINFOARRAY CComponentDataImpl::GetColumnInfo( FOLDER_TYPES fType )
|
|
{
|
|
PSCE_COLINFOARRAY pRet = NULL;
|
|
if( m_mapColumns.Lookup(fType, pRet) )
|
|
{
|
|
return pRet;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------------------
|
|
CComponentDataImpl::SetColumnInfo
|
|
|
|
Synopsis: Sets the column info for a certain type of folder.
|
|
|
|
Arguments: [fType] - The type of the CFolder item.
|
|
[pInfo] - The new column info.
|
|
------------------------------------------------------------------------------------------*/
|
|
void CComponentDataImpl::SetColumnInfo( FOLDER_TYPES fType, PSCE_COLINFOARRAY pInfo)
|
|
{
|
|
PSCE_COLINFOARRAY pCur = GetColumnInfo(fType);
|
|
|
|
if(pCur)
|
|
{
|
|
LocalFree(pCur);
|
|
}
|
|
m_mapColumns.SetAt(fType, pInfo);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------------------
|
|
CComponentDataImpl::UpdateObjectStatus
|
|
|
|
Synopsis: Updates the status of all objects under the child and parents if bUpdateThis
|
|
is TRUE.
|
|
|
|
Arguments: [pParent] - The Object to set status on
|
|
[bUpdateThis] - Weather to update the object or not.
|
|
------------------------------------------------------------------------------------------*/
|
|
DWORD CComponentDataImpl::UpdateObjectStatus(
|
|
CFolder *pParent,
|
|
BOOL bUpdateThis)
|
|
{
|
|
if(!pParent)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
DWORD status = 0;
|
|
TCHAR szBuf[50];
|
|
|
|
switch(pParent->GetType())
|
|
{
|
|
case REG_OBJECTS:
|
|
status = AREA_REGISTRY_SECURITY;
|
|
break;
|
|
|
|
case FILE_OBJECTS:
|
|
status = AREA_FILE_SECURITY;
|
|
break;
|
|
|
|
default:
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
PSCE_OBJECT_CHILDREN ObjectList = NULL;
|
|
PSCE_ERROR_LOG_INFO ErrBuf = NULL;
|
|
SCESTATUS rc = 0;
|
|
CString StrErr;
|
|
SCOPEDATAITEM sci;
|
|
|
|
HSCOPEITEM hItem = NULL;
|
|
LONG_PTR pCookie = NULL;
|
|
|
|
ZeroMemory(&sci, sizeof(SCOPEDATAITEM));
|
|
sci.mask = SDI_STR | SDI_PARAM;
|
|
|
|
#define UPDATE_STATUS( X, O ) X->SetDesc( O->Status, O->Count );\
|
|
X->GetScopeItem()->nImage = GetScopeImageIndex( X->GetType(), O->Status);\
|
|
X->GetScopeItem()->nOpenImage = X->GetScopeItem()->nImage;
|
|
|
|
LPCTSTR pszParent = NULL;
|
|
if (bUpdateThis)
|
|
{
|
|
CFolder *pCurrent = pParent;
|
|
|
|
pParent->RemoveAllResultItems();
|
|
m_pConsole->UpdateAllViews(NULL, (MMC_COOKIE)pParent, UAV_RESULTITEM_UPDATEALL);
|
|
hItem = pCurrent->GetScopeItem()->ID;
|
|
do {
|
|
|
|
//
|
|
// Walk up the items parent and update the items status.
|
|
//
|
|
if( m_pScope->GetParentItem( hItem, &hItem, &pCookie) == S_OK)
|
|
{
|
|
pszParent = (LPCTSTR)((CFolder *)pCookie)->GetName();
|
|
}
|
|
else
|
|
break;
|
|
|
|
if(!pCookie)
|
|
break;
|
|
|
|
//
|
|
// We are finished going up the parent.
|
|
//
|
|
|
|
switch( ((CFolder *)pCookie)->GetType() )
|
|
{
|
|
case AREA_REGISTRY_ANALYSIS:
|
|
case AREA_FILESTORE_ANALYSIS:
|
|
pszParent = NULL;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
//
|
|
// We have to get object information from the parent to the count parameter.
|
|
//
|
|
rc = SceGetObjectChildren(SadHandle, // hProfile
|
|
SCE_ENGINE_SAP, // Profile type
|
|
(AREA_INFORMATION)status, // Area
|
|
(LPTSTR)pszParent, // Object prefix
|
|
&ObjectList, // Object list [out]
|
|
&ErrBuf);
|
|
if(ErrBuf)
|
|
{
|
|
SceFreeMemory((PVOID)ErrBuf, SCE_STRUCT_ERROR_LOG_INFO);
|
|
ErrBuf = NULL;
|
|
}
|
|
|
|
if(SCESTATUS_SUCCESS != rc)
|
|
break;
|
|
|
|
//
|
|
// Find object in link list.
|
|
//
|
|
DWORD i=0;
|
|
|
|
sci.lParam = (LONG_PTR)pCurrent;
|
|
GetDisplayInfo( &sci );
|
|
|
|
PSCE_OBJECT_CHILDREN_NODE *pObjNode = &(ObjectList->arrObject);
|
|
|
|
while(ObjectList && i<ObjectList->nCount)
|
|
{
|
|
if( pObjNode[i] &&
|
|
pObjNode[i]->Name &&
|
|
!lstrcmpi(sci.displayname, pObjNode[i]->Name) )
|
|
{
|
|
UPDATE_STATUS(pCurrent, pObjNode[i]);
|
|
//
|
|
// Update scopeItem.
|
|
//
|
|
m_pScope->SetItem(pCurrent->GetScopeItem());
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
if ( ObjectList )
|
|
{
|
|
SceFreeMemory((PVOID)ObjectList, SCE_STRUCT_OBJECT_CHILDREN );
|
|
ObjectList = NULL;
|
|
}
|
|
|
|
pCurrent = (CFolder *)pCookie;
|
|
} while( pszParent && hItem );
|
|
}
|
|
|
|
|
|
ObjectList = NULL;
|
|
ErrBuf = NULL;
|
|
|
|
//
|
|
// Get Object children.
|
|
//
|
|
pszParent = pParent->GetName();
|
|
rc = SceGetObjectChildren(SadHandle, // hProfile
|
|
SCE_ENGINE_SAP, // Profile type
|
|
(AREA_INFORMATION)status, // Area
|
|
(LPTSTR)pszParent, // Object prefix
|
|
&ObjectList, // Object list [out]
|
|
&ErrBuf);
|
|
//
|
|
// Error list [out]
|
|
//
|
|
if ( ErrBuf )
|
|
{
|
|
MyFormatResMessage(rc, IDS_ERROR_GETTING_LAST_ANALYSIS, ErrBuf, StrErr);
|
|
|
|
SceFreeMemory((PVOID)ErrBuf, SCE_STRUCT_ERROR_LOG_INFO);
|
|
ErrBuf = NULL;
|
|
}
|
|
|
|
if ( SCESTATUS_SUCCESS == rc)
|
|
{
|
|
//
|
|
// Update all the children.
|
|
//
|
|
if( m_pScope->GetChildItem(pParent->GetScopeItem()->ID, &hItem, &pCookie) == S_OK && pCookie)
|
|
{
|
|
sci.lParam = (LONG_PTR)pCookie;
|
|
|
|
GetDisplayInfo(&sci);
|
|
while(hItem)
|
|
{
|
|
pParent = reinterpret_cast<CFolder *>(pCookie);
|
|
//
|
|
// Find object in object list.
|
|
//
|
|
DWORD i=0;
|
|
while( ObjectList && i<ObjectList->nCount )
|
|
{
|
|
if( (&(ObjectList->arrObject))[i] &&
|
|
(&(ObjectList->arrObject))[i]->Name &&
|
|
!lstrcmpi((&(ObjectList->arrObject))[i]->Name, (LPCTSTR)sci.displayname) )
|
|
{
|
|
UPDATE_STATUS(pParent, (&(ObjectList->arrObject))[i]);
|
|
//
|
|
// Update this objects children.
|
|
//
|
|
UpdateObjectStatus( pParent, FALSE );
|
|
|
|
//
|
|
// Update the name space
|
|
//
|
|
pParent->RemoveAllResultItems();
|
|
m_pConsole->UpdateAllViews(NULL, (MMC_COOKIE)pParent, UAV_RESULTITEM_UPDATEALL);
|
|
m_pScope->SetItem(pParent->GetScopeItem());
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
if(ObjectList == NULL || i >= ObjectList->nCount)
|
|
{
|
|
//
|
|
// Couldn't find the item, so just stop.
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Next Scope item
|
|
//
|
|
if( m_pScope->GetNextItem(hItem, &hItem, &pCookie) != S_OK)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ObjectList )
|
|
SceFreeMemory((PVOID)ObjectList, SCE_STRUCT_OBJECT_CHILDREN );
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|