//+-------------------------------------------------------------------------- // // 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 #include #ifdef INITGUID #undef INITGUID #include #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; inCount;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 + + GPTSCE_TEMPLATE + // 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(pFolder); pFolder->SetCookie(reinterpret_cast(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 && inCount) { 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(pCookie); // // Find object in object list. // DWORD i=0; while( ObjectList && inCount ) { 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; }