/*++ Copyright (C) 1998-1999 Microsoft Corporation Module Name: ctrsprop.cpp Abstract: Implementation of the counters general property page. --*/ #include "stdafx.h" #include #include #include #include "smlogs.h" #include "smcfgmsg.h" #include "smctrqry.h" #include "ctrsprop.h" #include "smlogres.h" #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif USE_HANDLE_MACROS("SMLOGCFG(ctrsprop.cpp)"); static ULONG s_aulHelpIds[] = { IDC_CTRS_COUNTER_LIST, IDH_CTRS_COUNTER_LIST, IDC_CTRS_ADD_BTN, IDH_CTRS_ADD_BTN, IDC_CTRS_ADD_OBJ_BTN, IDH_CTRS_ADD_OBJ_BTN, IDC_CTRS_REMOVE_BTN, IDH_CTRS_REMOVE_BTN, IDC_CTRS_FILENAME_DISPLAY, IDH_CTRS_FILENAME_DISPLAY, IDC_CTRS_SAMPLE_SPIN, IDH_CTRS_SAMPLE_EDIT, IDC_CTRS_SAMPLE_EDIT, IDH_CTRS_SAMPLE_EDIT, IDC_CTRS_SAMPLE_UNITS_COMBO,IDH_CTRS_SAMPLE_UNITS_COMBO, IDC_RUNAS_EDIT, IDH_RUNAS_EDIT, IDC_SETPWD_BTN, IDH_SETPWD_BTN, 0,0 }; ///////////////////////////////////////////////////////////////////////////// // CCountersProperty property page IMPLEMENT_DYNCREATE(CCountersProperty, CSmPropertyPage) CCountersProperty::CCountersProperty(MMC_COOKIE mmcCookie, LONG_PTR hConsole) : CSmPropertyPage ( CCountersProperty::IDD, hConsole ) // lCookie is really the pointer to the Log Query object { //::OutputDebugStringA("\nCCountersProperty::CCountersProperty"); // save pointers from arg list m_pCtrLogQuery = reinterpret_cast (mmcCookie); ASSERT ( m_pCtrLogQuery->CastToCounterLogQuery() ); m_pQuery = dynamic_cast (m_pCtrLogQuery); ZeroMemory ( &m_dlgConfig, sizeof(m_dlgConfig) ); m_szCounterListBuffer = NULL; m_dwCounterListBufferSize = 0; m_lCounterListHasStars = 0; m_dwMaxHorizListExtent = 0; memset(&m_HashTable, 0, sizeof(m_HashTable)); // EnableAutomation(); //{{AFX_DATA_INIT(CCountersProperty) m_nSampleUnits = 0; //}}AFX_DATA_INIT } CCountersProperty::CCountersProperty() : CSmPropertyPage ( CCountersProperty::IDD ) { ASSERT (FALSE); // the constructor w/ args should be used instead } CCountersProperty::~CCountersProperty() { // ::OutputDebugStringA("\nCCountersProperty::~CCountersProperty"); if (m_szCounterListBuffer != NULL) { delete [] m_szCounterListBuffer; } ClearCountersHashTable(); } void CCountersProperty::OnFinalRelease() { // When the last reference for an automation object is released // OnFinalRelease is called. The base class will automatically // deletes the object. Add additional cleanup required for your // object before calling the base class. CPropertyPage::OnFinalRelease(); } void CCountersProperty::DoDataExchange(CDataExchange* pDX) { CString strTemp; AFX_MANAGE_STATE(AfxGetStaticModuleState( )); CPropertyPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(CCountersProperty) DDX_Text(pDX, IDC_CTRS_LOG_SCHED_TEXT, m_strStartDisplay); ValidateTextEdit(pDX, IDC_CTRS_SAMPLE_EDIT, 6, &m_SharedData.stiSampleTime.dwValue, eMinSampleInterval, eMaxSampleInterval); DDX_CBIndex(pDX, IDC_CTRS_SAMPLE_UNITS_COMBO, m_nSampleUnits); DDX_Text(pDX, IDC_RUNAS_EDIT, m_strUserDisplay ); //}}AFX_DATA_MAP if ( pDX->m_bSaveAndValidate ) { m_SharedData.stiSampleTime.dwUnitType = (DWORD)((CComboBox *)GetDlgItem(IDC_CTRS_SAMPLE_UNITS_COMBO))-> GetItemData(m_nSampleUnits); } } BEGIN_MESSAGE_MAP(CCountersProperty, CSmPropertyPage) //{{AFX_MSG_MAP(CCountersProperty) ON_BN_CLICKED(IDC_CTRS_ADD_BTN, OnCtrsAddBtn) ON_BN_CLICKED(IDC_CTRS_ADD_OBJ_BTN, OnCtrsAddObjBtn) ON_BN_CLICKED(IDC_CTRS_REMOVE_BTN, OnCtrsRemoveBtn) ON_LBN_DBLCLK(IDC_CTRS_COUNTER_LIST, OnDblclkCtrsCounterList) ON_EN_CHANGE(IDC_CTRS_SAMPLE_EDIT, OnKillfocusSchedSampleEdit) ON_EN_KILLFOCUS(IDC_CTRS_SAMPLE_EDIT, OnKillfocusSchedSampleEdit) ON_EN_CHANGE( IDC_RUNAS_EDIT, OnChangeUser ) ON_NOTIFY(UDN_DELTAPOS, IDC_CTRS_SAMPLE_SPIN, OnDeltaposSchedSampleSpin) ON_CBN_SELENDOK(IDC_CTRS_SAMPLE_UNITS_COMBO, OnSelendokSampleUnitsCombo) ON_BN_CLICKED(IDC_SETPWD_BTN, OnPwdBtn) ON_WM_DESTROY() //}}AFX_MSG_MAP END_MESSAGE_MAP() BEGIN_DISPATCH_MAP(CCountersProperty, CSmPropertyPage) //{{AFX_DISPATCH_MAP(CCountersProperty) // NOTE - the ClassWizard will add and remove mapping macros here. //}}AFX_DISPATCH_MAP END_DISPATCH_MAP() // Note: we add support for IID_ICountersProperty to support typesafe binding // from VBA. This IID must match the GUID that is attached to the // dispinterface in the .ODL file. // {65154EA9-BDBE-11D1-BF99-00C04F94A83A} static const IID IID_ICountersProperty = { 0x65154ea9, 0xbdbe, 0x11d1, { 0xbf, 0x99, 0x0, 0xc0, 0x4f, 0x94, 0xa8, 0x3a } }; BEGIN_INTERFACE_MAP(CCountersProperty, CSmPropertyPage) INTERFACE_PART(CCountersProperty, IID_ICountersProperty, Dispatch) END_INTERFACE_MAP() ULONG CCountersProperty::HashCounter( LPWSTR szCounterName ) { ULONG h = 0; ULONG a = 31415; //a, b, k are primes const ULONG k = 16381; const ULONG b = 27183; LPWSTR szThisChar; if (szCounterName) { for (szThisChar = szCounterName; * szThisChar; szThisChar ++) { h = (a * h + ((ULONG) (* szThisChar))) % k; a = a * b % (k - 1); } } return (h % eHashTableSize); } //++ // Description: // Remove a counter path from hash table. One counter // path must exactly match the given one in order to be // removed, even it is one with wildcard // // Parameters: // pszCounterPath - Pointer to counter path to be removed // // Return: // Return TRUE if the counter path is removed, otherwis return FALSE //-- BOOL CCountersProperty::RemoveCounterFromHashTable( LPWSTR szCounterName, PPDH_COUNTER_PATH_ELEMENTS pCounterPath ) { ULONG lHashValue; PHASH_ENTRY pEntry = NULL; PHASH_ENTRY pPrev = NULL; BOOL bReturn = FALSE; SetLastError(ERROR_SUCCESS); if (szCounterName == NULL || pCounterPath == NULL) { SetLastError(ERROR_INVALID_PARAMETER); goto ErrorOut; } lHashValue = HashCounter(szCounterName); pEntry = m_HashTable[lHashValue]; // // Check if there is a counter path which is exactly the same // as the given one // while (pEntry) { if (pEntry->pCounter == pCounterPath) break; pPrev = pEntry; pEntry = pEntry->pNext; } // // If we found it, remove it // if (pEntry) { if (pPrev == NULL) { m_HashTable[lHashValue] = pEntry->pNext; } else { pPrev->pNext = pEntry->pNext; } G_FREE(pEntry->pCounter); G_FREE(pEntry); bReturn = TRUE; } ErrorOut: return bReturn; } //++ // Description: // Insert a counter path into hash table. // // Parameters: // pszCounterPath - Pointer to counter path to be inserted // // Return: // Return the pointer to new inserted PDH_COUNTER_PATH_ELEMENTS structure //-- PPDH_COUNTER_PATH_ELEMENTS CCountersProperty::InsertCounterToHashTable( LPWSTR pszCounterPath ) { ULONG lHashValue; PHASH_ENTRY pNewEntry = NULL; PPDH_COUNTER_PATH_ELEMENTS pCounter = NULL; PDH_STATUS pdhStatus; if (pszCounterPath == NULL) { SetLastError(ERROR_INVALID_PARAMETER); goto ErrorOut; } pdhStatus = AllocInitCounterPath ( pszCounterPath, &pCounter ); if (pdhStatus != ERROR_SUCCESS) { SetLastError( pdhStatus ); goto ErrorOut; } // // Insert at head of bucket list // lHashValue = HashCounter(pszCounterPath); pNewEntry = (PHASH_ENTRY) G_ALLOC(sizeof(HASH_ENTRY)); if (pNewEntry == NULL) { SetLastError( ERROR_OUTOFMEMORY ); goto ErrorOut; } pNewEntry->pCounter = pCounter; pNewEntry->pNext = m_HashTable[lHashValue]; m_HashTable[lHashValue] = pNewEntry; return pCounter; ErrorOut: if (pCounter != NULL) G_FREE (pCounter); return NULL; } //++ // Description: // Check if the new counter path overlaps with a existing // one in logical sense // // Parameters: // pCounter - Pointer to counter path to be inserted // // Return: // Return the relation between the new and existing counter // paths. Possible relation is as following: // ERROR_SUCCESS - The two counter paths are different // SMCFG_DUPL_FIRST_IS_WILD - The first counter path has wildcard name // SMCFG_DUPL_SECOND_IS_WILD - The second counter path has wildcard name // SMCFG_DUPL_SINGLE_PATH - The two counter paths are the same(may // contain wildcard) //-- DWORD CCountersProperty::CheckDuplicate( PPDH_COUNTER_PATH_ELEMENTS pCounter) { ULONG lHashValue; PHASH_ENTRY pHead; PHASH_ENTRY pEntry; DWORD dwStatus = ERROR_SUCCESS; for (lHashValue = 0; lHashValue < eHashTableSize; lHashValue++) { pHead = m_HashTable[lHashValue]; if (pHead == NULL) continue; pEntry = pHead; while (pEntry) { dwStatus = CheckDuplicateCounterPaths ( pEntry->pCounter, pCounter ); if ( dwStatus != ERROR_SUCCESS ) { return dwStatus; } pEntry = pEntry->pNext; } } return dwStatus; } //++ // Description: // The function clears all the entries in hash table // and set hash-table-not-set-up flag // // Parameters: // None // // Return: // None //-- void CCountersProperty::ClearCountersHashTable( void ) { ULONG i; PHASH_ENTRY pEntry; PHASH_ENTRY pNext; for (i = 0; i < eHashTableSize; i ++) { pNext = m_HashTable[i]; while (pNext != NULL) { pEntry = pNext; pNext = pEntry->pNext; G_FREE(pEntry->pCounter); G_FREE(pEntry); pEntry = NULL; } } } static PDH_FUNCTION DialogCallBack(CCountersProperty *pDlg) { // add strings in buffer to list box LPWSTR szNewCounterName; INT iListIndex; INT iItemCnt; PDH_STATUS pdhStatus = ERROR_SUCCESS; DWORD dwReturnStatus = ERROR_SUCCESS; CListBox *pCounterList; DWORD dwItemExtent; DWORD dwStatus = ERROR_SUCCESS; BOOL bAtLeastOneCounterRemoved = FALSE; BOOL bAtLeastOneCounterNotAdded = FALSE; LPWSTR szCounterPath = NULL; LONG lSize = 0; PPDH_COUNTER_PATH_ELEMENTS pPathInfoNew = NULL; CDC* pCDC = NULL; ResourceStateManager rsm; #define CTRBUFLIMIT (0x7fffffff) if ( PDH_MORE_DATA == pDlg->m_dlgConfig.CallBackStatus ) { if ( pDlg->m_dlgConfig.cchReturnPathLength < CTRBUFLIMIT ) { pDlg->m_dwCounterListBufferSize *= 2; delete [] pDlg->m_szCounterListBuffer; pDlg->m_szCounterListBuffer = NULL; try { pDlg->m_szCounterListBuffer = new WCHAR[pDlg->m_dwCounterListBufferSize]; } catch ( ... ) { pDlg->m_dwCounterListBufferSize = 0; pDlg->m_dlgConfig.CallBackStatus = PDH_MEMORY_ALLOCATION_FAILURE; dwReturnStatus = PDH_MEMORY_ALLOCATION_FAILURE; } if ( ERROR_SUCCESS == dwReturnStatus ) { // clear buffer memset ( pDlg->m_szCounterListBuffer, 0, pDlg->m_dwCounterListBufferSize * sizeof(WCHAR) ); pDlg->m_dlgConfig.szReturnPathBuffer = pDlg->m_szCounterListBuffer; pDlg->m_dlgConfig.cchReturnPathLength = pDlg->m_dwCounterListBufferSize; pDlg->m_dlgConfig.CallBackStatus = PDH_RETRY; dwReturnStatus = PDH_RETRY; } } else { pDlg->m_dlgConfig.CallBackStatus = PDH_MEMORY_ALLOCATION_FAILURE; dwReturnStatus = PDH_MEMORY_ALLOCATION_FAILURE; } } else if ( ERROR_SUCCESS == pDlg->m_dlgConfig.CallBackStatus ) { pCounterList = (CListBox *)pDlg->GetDlgItem(IDC_CTRS_COUNTER_LIST); if ( NULL != pCounterList ) { pCDC = pCounterList->GetDC(); } if ( NULL != pCDC ) { for (szNewCounterName = pDlg->m_szCounterListBuffer; *szNewCounterName != 0; szNewCounterName += (lstrlen(szNewCounterName) + 1)) { // // Parse new pathname // pdhStatus = pDlg->AllocInitCounterPath ( szNewCounterName, &pPathInfoNew ); // // Check for duplicate // if (pdhStatus == ERROR_SUCCESS && NULL != pPathInfoNew ) { dwStatus = pDlg->CheckDuplicate( pPathInfoNew); if ( ERROR_SUCCESS != dwStatus ) { if ( SMCFG_DUPL_SINGLE_PATH == dwStatus || SMCFG_DUPL_FIRST_IS_WILD == dwStatus ) { // NOTE: This includes case where both first // and second are wild. bAtLeastOneCounterNotAdded = TRUE; } else { ASSERT( dwStatus == SMCFG_DUPL_SECOND_IS_WILD); } } } // // Check if there is a valid counter to add to the list // if ( ERROR_SUCCESS == pdhStatus && ( NULL != pPathInfoNew ) && ( ERROR_SUCCESS == dwStatus || SMCFG_DUPL_SECOND_IS_WILD == dwStatus)) { if ( SMCFG_DUPL_SECOND_IS_WILD == dwStatus ) { // // Scan for the duplicated items in the list box and // remove them // iItemCnt = pCounterList->GetCount(); szCounterPath = new WCHAR [MAX_PATH+1]; if (szCounterPath == NULL) { return PDH_MEMORY_ALLOCATION_FAILURE; } lSize = MAX_PATH; for (iListIndex = iItemCnt-1; iListIndex >= 0; iListIndex--) { PPDH_COUNTER_PATH_ELEMENTS pPathInfoExist; if (pCounterList->GetTextLen(iListIndex) > lSize) { delete [] szCounterPath; lSize = max(pCounterList->GetTextLen(iListIndex) + 1, lSize*2); szCounterPath = new WCHAR [lSize]; if (szCounterPath == NULL) { return PDH_MEMORY_ALLOCATION_FAILURE; } } if ( 0 < pCounterList->GetText( iListIndex, szCounterPath ) ) { pPathInfoExist = (PPDH_COUNTER_PATH_ELEMENTS) pCounterList->GetItemDataPtr(iListIndex); if (pPathInfoExist == NULL) continue; dwStatus = CheckDuplicateCounterPaths ( pPathInfoExist, pPathInfoNew ); if (dwStatus != ERROR_SUCCESS ) { ASSERT( dwStatus == SMCFG_DUPL_SECOND_IS_WILD ); pDlg->RemoveCounterFromHashTable(szCounterPath, pPathInfoExist); pCounterList->DeleteString(iListIndex); } } } if (szCounterPath) { delete [] szCounterPath; } bAtLeastOneCounterRemoved = TRUE; } // // Add new counter name and select the current entry in the list box // iListIndex = pCounterList->AddString(szNewCounterName); if (iListIndex != LB_ERR) { if (pDlg->m_lCounterListHasStars != PDLCNFIG_LISTBOX_STARS_YES) { // save a string compare if this value is already set if (wcsstr (szNewCounterName, L"*") == NULL) { pDlg->m_lCounterListHasStars = PDLCNFIG_LISTBOX_STARS_YES; } } if (! bAtLeastOneCounterRemoved) { // update list box extent if ( NULL != pCDC ) { dwItemExtent = (DWORD)(pCDC->GetTextExtent (szNewCounterName)).cx; if (dwItemExtent > pDlg->m_dwMaxHorizListExtent) { pDlg->m_dwMaxHorizListExtent = dwItemExtent; pCounterList->SetHorizontalExtent(dwItemExtent); } } } pCounterList->SetSel (-1, FALSE); // cancel existing selections pCounterList->SetSel (iListIndex); pCounterList->SetCaretIndex (iListIndex); pCounterList->SetItemDataPtr(iListIndex, (void*)pDlg->InsertCounterToHashTable(szNewCounterName)); } } if ( ERROR_SUCCESS != pdhStatus ) { // Message box Pdh error message, go on to next CString strMsg; CString strPdhMessage; FormatSystemMessage ( pdhStatus, strPdhMessage ); MFC_TRY strMsg.Format ( IDS_CTRS_PDH_ERROR, szNewCounterName ); strMsg += strPdhMessage; MFC_CATCH_MINIMUM ::AfxMessageBox( strMsg, MB_OK|MB_ICONERROR, 0 ); } // Go on to next path to add dwStatus = ERROR_SUCCESS; } } else { dwReturnStatus = PDH_MEMORY_ALLOCATION_FAILURE; } if ( ERROR_SUCCESS == dwReturnStatus && bAtLeastOneCounterRemoved) { // // Clear the max extent and recalculate // pDlg->m_dwMaxHorizListExtent = 0; for ( iListIndex = 0; iListIndex < pCounterList->GetCount(); iListIndex++ ) { pCounterList->GetText(iListIndex, szCounterPath); if ( NULL != pCDC ) { dwItemExtent = (DWORD)(pCDC->GetTextExtent(szCounterPath)).cx; if (dwItemExtent > pDlg->m_dwMaxHorizListExtent) { pDlg->m_dwMaxHorizListExtent = dwItemExtent; } } } pCounterList->SetHorizontalExtent(pDlg->m_dwMaxHorizListExtent); } if ( NULL != pCDC ) { pCounterList->ReleaseDC(pCDC); pCDC = NULL; } // Message box re: duplicates not added, or duplicates were removed. if ( bAtLeastOneCounterRemoved ) { CString strMsg; strMsg.LoadString ( IDS_CTRS_DUPL_PATH_DELETED ); ::AfxMessageBox ( strMsg, MB_OK | MB_ICONWARNING, 0); } if ( bAtLeastOneCounterNotAdded ) { CString strMsg; strMsg.LoadString ( IDS_CTRS_DUPL_PATH_NOT_ADDED ); ::AfxMessageBox( strMsg, MB_OK|MB_ICONWARNING, 0 ); } // clear buffer memset (pDlg->m_szCounterListBuffer, 0, pDlg->m_dwCounterListBufferSize); dwReturnStatus = ERROR_SUCCESS; } else { // Not successful dwReturnStatus = pDlg->m_dlgConfig.CallBackStatus; } return dwReturnStatus; } void CCountersProperty::OnPwdBtn() { CString strTempUser; UpdateData(TRUE); if (!m_bCanAccessRemoteWbem) { ConnectRemoteWbemFail(m_pCtrLogQuery, TRUE); return; } MFC_TRY strTempUser = m_strUserDisplay; m_strUserDisplay.TrimLeft(); m_strUserDisplay.TrimRight(); m_pCtrLogQuery->m_strUser = m_strUserDisplay; SetRunAs(m_pCtrLogQuery); m_strUserDisplay = m_pCtrLogQuery->m_strUser; if ( 0 != strTempUser.CompareNoCase ( m_strUserDisplay ) ) { SetDlgItemText ( IDC_RUNAS_EDIT, m_strUserDisplay ); } MFC_CATCH_MINIMUM; } BOOL CCountersProperty::IsValidLocalData() { BOOL bIsValid = TRUE; CListBox * pCounterList = (CListBox *)GetDlgItem(IDC_CTRS_COUNTER_LIST); long lNumCounters; ResourceStateManager rsm; lNumCounters = pCounterList->GetCount(); if ( 0 == lNumCounters ) { CString strMsg; bIsValid = FALSE; strMsg.LoadString ( IDS_CTRS_REQUIRED ); MessageBox ( strMsg, m_pCtrLogQuery->GetLogName(), MB_OK | MB_ICONERROR); GetDlgItem ( IDC_CTRS_ADD_BTN )->SetFocus(); } if (bIsValid) { // Validate sample interval value bIsValid = ValidateDWordInterval(IDC_CTRS_SAMPLE_EDIT, m_pCtrLogQuery->GetLogName(), (long) m_SharedData.stiSampleTime.dwValue, eMinSampleInterval, eMaxSampleInterval); } if (bIsValid) { // Validate sample interval value and unit type bIsValid = SampleIntervalIsInRange( m_SharedData.stiSampleTime, m_pCtrLogQuery->GetLogName() ); if ( !bIsValid ) { GetDlgItem ( IDC_CTRS_SAMPLE_EDIT )->SetFocus(); } } return bIsValid; } ///////////////////////////////////////////////////////////////////////////// // CCountersProperty message handlers void CCountersProperty::OnChangeUser() { // // If you can not access remote WBEM, you can not modify RunAs info, // changing the user name is not allowed. // if (m_bCanAccessRemoteWbem) { // // When the user hits OK in the password dialog, // the user name might not have changed. // UpdateData ( TRUE ); m_strUserDisplay.TrimLeft(); m_strUserDisplay.TrimRight(); if ( 0 != m_strUserSaved.Compare ( m_strUserDisplay ) ) { m_pCtrLogQuery->m_fDirtyPassword = PASSWORD_DIRTY; SetModifiedPage(TRUE); } else { m_pCtrLogQuery->m_fDirtyPassword &= ~PASSWORD_DIRTY; } // // If default user is typed, never need to set password // if (m_strUserDisplay.IsEmpty() || m_strUserDisplay.GetAt(0) == L'<') { if (m_bPwdButtonEnabled) { GetDlgItem(IDC_SETPWD_BTN)->EnableWindow(FALSE); m_bPwdButtonEnabled = FALSE; } } else { if (!m_bPwdButtonEnabled) { GetDlgItem(IDC_SETPWD_BTN)->EnableWindow(TRUE); m_bPwdButtonEnabled = TRUE; } } } else { // // We can not modify the RunAs info, then display // an error message and retore the original user name in RunAs // UpdateData(TRUE); if (ConnectRemoteWbemFail(m_pCtrLogQuery, FALSE)) { GetDlgItem(IDC_RUNAS_EDIT)->SetWindowText(m_strUserSaved); } } } void CCountersProperty::OnCtrsAddBtn() { ImplementAdd( FALSE ); } void CCountersProperty::OnCtrsAddObjBtn() { ImplementAdd( TRUE ); } void CCountersProperty::OnCtrsRemoveBtn() { CListBox *pCounterList; LONG lThisItem; BOOL bDone; LONG lOrigCaret; LONG lItemStatus; LONG lItemCount; BOOL bChanged = FALSE; DWORD dwItemExtent; CString strItemText; PPDH_COUNTER_PATH_ELEMENTS pCounter; CDC* pCDC = NULL; pCounterList = (CListBox *)GetDlgItem(IDC_CTRS_COUNTER_LIST); if ( NULL == pCounterList ) { return; } // delete all selected items in the list box and // set the cursor to the item above the original caret position // or the first or last if that is out of the new range lOrigCaret = pCounterList->GetCaretIndex(); lThisItem = 0; bDone = FALSE; // clear the max extent m_dwMaxHorizListExtent = 0; // clear the value and see if any non deleted items have a star, if so // then set the flag back pCDC = pCounterList->GetDC(); if ( NULL != pCDC ) { do { lItemStatus = pCounterList->GetSel(lThisItem); if (lItemStatus > 0) { // then it's selected so delete it pCounterList->GetText(lThisItem, strItemText); pCounter = (PPDH_COUNTER_PATH_ELEMENTS) pCounterList->GetItemDataPtr(lThisItem); if (RemoveCounterFromHashTable(strItemText.GetBuffer(1), pCounter) == FALSE) { ClearCountersHashTable (); } pCounterList->DeleteString(lThisItem); bChanged = TRUE; } else if (lItemStatus == 0) { // get the text length of this item since it will stay pCounterList->GetText(lThisItem, strItemText); if (m_lCounterListHasStars != PDLCNFIG_LISTBOX_STARS_YES) { // save a string compare if this value is already set if (wcsstr (strItemText, L"*") == NULL) { m_lCounterListHasStars = PDLCNFIG_LISTBOX_STARS_YES; } } dwItemExtent = (DWORD)(pCDC->GetTextExtent(strItemText)).cx; if (dwItemExtent > m_dwMaxHorizListExtent) { m_dwMaxHorizListExtent = dwItemExtent; } // then it's not selected so go to the next one lThisItem++; } else { // we've run out so exit bDone = TRUE; } } while (!bDone); } if ( NULL != pCDC ) { pCounterList->ReleaseDC(pCDC); pCDC = NULL; } if ( bDone ) { // update the text extent of the list box pCounterList->SetHorizontalExtent(m_dwMaxHorizListExtent); } // see how many entries are left and update the // caret position and the remove button state lItemCount = pCounterList->GetCount(); if (lItemCount > 0) { // the update the caret if (lOrigCaret >= lItemCount) { lOrigCaret = lItemCount-1; } else { // caret should be within the list } pCounterList->SetSel(lOrigCaret); pCounterList->SetCaretIndex(lOrigCaret); } else { // the list is empty so remove caret, selection // disable the remove button and activate the // add button pCounterList->SetSel(-1); } SetButtonState(); SetModifiedPage(bChanged); } void CCountersProperty::OnDblclkCtrsCounterList() { ImplementAdd( FALSE ); } BOOL CCountersProperty::OnSetActive() { BOOL bReturn; bReturn = CSmPropertyPage::OnSetActive(); if (bReturn) { ResourceStateManager rsm; m_pCtrLogQuery->GetPropPageSharedData ( &m_SharedData ); UpdateFileNameString(); UpdateLogStartString(); m_strUserDisplay = m_pCtrLogQuery->m_strUser; UpdateData(FALSE); //to load the edit & combo box } return bReturn; } BOOL CCountersProperty::OnKillActive() { BOOL bContinue = TRUE; ResourceStateManager rsm; bContinue = CPropertyPage::OnKillActive(); if ( bContinue ) { m_pCtrLogQuery->m_strUser = m_strUserDisplay; bContinue = IsValidData(m_pCtrLogQuery, VALIDATE_FOCUS); if ( bContinue ) { m_pCtrLogQuery->SetPropPageSharedData ( &m_SharedData ); SetIsActive ( FALSE ); } } return bContinue; } void CCountersProperty::OnCancel() { m_pCtrLogQuery->SyncPropPageSharedData(); // clear memory shared between property pages. } BOOL CCountersProperty::OnApply() { CListBox * pCounterList = (CListBox *)GetDlgItem(IDC_CTRS_COUNTER_LIST); long lThisCounter; BOOL bContinue = TRUE; LPWSTR szCounterPath = NULL; LONG lSize = 0; ResourceStateManager rsm; bContinue = UpdateData(TRUE); if ( bContinue ) { bContinue = IsValidData(m_pCtrLogQuery, VALIDATE_APPLY ); } if ( bContinue ) { bContinue = SampleTimeIsLessThanSessionTime ( m_pCtrLogQuery ); if ( !bContinue ) { SetFocusAnyPage ( IDC_CTRS_SAMPLE_EDIT ); } } // Write data to the query object. if ( bContinue ) { ASSERT ( 0 < pCounterList->GetCount() ); // update the counter MSZ string using the counters from the list box m_pCtrLogQuery->ResetCounterList(); // clear the old counter list szCounterPath = new WCHAR [MAX_PATH+1]; if (szCounterPath == NULL) { return FALSE; } lSize = MAX_PATH; for ( lThisCounter = 0; lThisCounter < pCounterList->GetCount(); lThisCounter++ ) { if (pCounterList->GetTextLen(lThisCounter) > lSize) { delete [] szCounterPath; lSize = max(pCounterList->GetTextLen(lThisCounter) + 1, lSize*2); szCounterPath = new WCHAR [lSize]; if (szCounterPath == NULL) { bContinue = FALSE; break; } } pCounterList->GetText(lThisCounter, szCounterPath); m_pCtrLogQuery->AddCounter(szCounterPath); } if (szCounterPath != NULL) delete [] szCounterPath; if ( bContinue ) { // Sample interval ASSERT ( SLQ_TT_TTYPE_SAMPLE == m_SharedData.stiSampleTime.wTimeType ); ASSERT ( SLQ_TT_DTYPE_UNITS == m_SharedData.stiSampleTime.wDataType ); bContinue = m_pCtrLogQuery->SetLogTime (&m_SharedData.stiSampleTime, (DWORD)m_SharedData.stiSampleTime.wTimeType); // Save property page shared data. m_pCtrLogQuery->UpdatePropPageSharedData(); if ( bContinue ) { // ApplyRunAs must be called before UpdateService bContinue = ApplyRunAs(m_pCtrLogQuery); } if ( bContinue ) { bContinue = UpdateService( m_pCtrLogQuery, TRUE ); } } } if ( bContinue ){ bContinue = CSmPropertyPage::OnApply(); } return bContinue; } void CCountersProperty::UpdateLogStartString () { eStartType eCurrentStartType; int nResId = 0; ResourceStateManager rsm; eCurrentStartType = DetermineCurrentStartType(); if ( eStartManually == eCurrentStartType ) { nResId = IDS_LOG_START_MANUALLY; } else if ( eStartImmediately == eCurrentStartType ) { nResId = IDS_LOG_START_IMMED; } else if ( eStartSched == eCurrentStartType ) { nResId = IDS_LOG_START_SCHED; } if ( 0 != nResId ) { m_strStartDisplay.LoadString(nResId); } else { m_strStartDisplay.Empty(); } return; } void CCountersProperty::UpdateFileNameString () { m_strFileNameDisplay.Empty(); // Todo: Handle failure status // Todo: Check pointers CreateSampleFileName ( m_pCtrLogQuery->GetLogName(), m_pCtrLogQuery->GetLogService()->GetMachineName(), m_SharedData.strFolderName, m_SharedData.strFileBaseName, m_SharedData.strSqlName, m_SharedData.dwSuffix, m_SharedData.dwLogFileType, m_SharedData.dwSerialNumber, m_strFileNameDisplay ); SetDlgItemText( IDC_CTRS_FILENAME_DISPLAY, m_strFileNameDisplay ); // Clear the selection ((CEdit*)GetDlgItem( IDC_CTRS_FILENAME_DISPLAY ))->SetSel ( -1, FALSE ); return; } BOOL CCountersProperty::OnInitDialog() { LPWSTR szCounterName; CListBox * pCounterList = (CListBox *)GetDlgItem(IDC_CTRS_COUNTER_LIST); CComboBox *pCombo; int nIndex; CString strComboBoxString; int nResult; DWORD dwItemExtent; PPDH_COUNTER_PATH_ELEMENTS pCounterPath; CDC* pCDC = NULL; ResourceStateManager rsm; // // Here m_pCtrLogQuery should not be NULL, if it is, // There must be something wrong. // if ( NULL == m_pCtrLogQuery ) { return TRUE; } m_pCtrLogQuery->TranslateCounterListToLocale(); m_bCanAccessRemoteWbem = m_pCtrLogQuery->GetLogService()->CanAccessWbemRemote(); MFC_TRY m_pCtrLogQuery->SetActivePropertyPage( this ); //load counter list box from string in counter list pCounterList->ResetContent(); ClearCountersHashTable(); szCounterName = (LPWSTR)m_pCtrLogQuery->GetFirstCounter(); pCDC = pCounterList->GetDC(); while (szCounterName != NULL) { nIndex = pCounterList->AddString(szCounterName); if (nIndex < 0) continue; // // Insert counter path into hash table // pCounterPath = InsertCounterToHashTable(szCounterName); if (pCounterPath == NULL) { pCounterList->DeleteString(nIndex); continue; } pCounterList->SetItemDataPtr(nIndex, (void*)pCounterPath); // update list box extent if ( NULL != pCDC ) { dwItemExtent = (DWORD)(pCDC->GetTextExtent (szCounterName)).cx; if (dwItemExtent > m_dwMaxHorizListExtent) { m_dwMaxHorizListExtent = dwItemExtent; } } szCounterName = (LPWSTR)m_pCtrLogQuery->GetNextCounter(); } if ( NULL != pCDC ) { pCounterList->ReleaseDC(pCDC); pCDC = NULL; } if (m_dwMaxHorizListExtent != 0) { pCounterList->SetHorizontalExtent(m_dwMaxHorizListExtent); } if (pCounterList->GetCount() > 0) { // select first entry pCounterList->SetSel (0, TRUE); pCounterList->SetCaretIndex (0, TRUE); } // Load the shared data to get the sample unit type selection. m_pCtrLogQuery->GetPropPageSharedData ( &m_SharedData ); // load combo boxes pCombo = (CComboBox *)(GetDlgItem(IDC_CTRS_SAMPLE_UNITS_COMBO)); pCombo->ResetContent(); for (nIndex = 0; nIndex < (int)dwTimeUnitComboEntries; nIndex++) { strComboBoxString.LoadString( TimeUnitCombo[nIndex].nResId ); nResult = pCombo->InsertString (nIndex, (LPCWSTR)strComboBoxString); ASSERT (nResult != CB_ERR); nResult = pCombo->SetItemData (nIndex, (DWORD)TimeUnitCombo[nIndex].nData); ASSERT (nResult != CB_ERR); // set selected in combo box here if ( m_SharedData.stiSampleTime.dwUnitType == (DWORD)(TimeUnitCombo[nIndex].nData)) { m_nSampleUnits = nIndex; nResult = pCombo->SetCurSel(nIndex); ASSERT (nResult != CB_ERR); } } CSmPropertyPage::OnInitDialog(); Initialize( m_pCtrLogQuery ); m_strUserDisplay = m_pCtrLogQuery->m_strUser; m_strUserSaved = m_strUserDisplay; if (m_pCtrLogQuery->GetLogService()->TargetOs() == OS_WIN2K) { GetDlgItem(IDC_RUNAS_STATIC)->EnableWindow(FALSE); GetDlgItem(IDC_RUNAS_EDIT)->EnableWindow(FALSE); } if ( m_pCtrLogQuery->GetLogService()->TargetOs() == OS_WIN2K || m_strUserDisplay.IsEmpty() || m_strUserDisplay.GetAt(0) == L'<') { GetDlgItem(IDC_SETPWD_BTN)->EnableWindow(FALSE); m_bPwdButtonEnabled = FALSE; } SetHelpIds ( (DWORD*)&s_aulHelpIds ); SetButtonState(); MFC_CATCH_MINIMUM; return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CCountersProperty::OnDeltaposSchedSampleSpin(NMHDR* pNMHDR, LRESULT* pResult) { OnDeltaposSpin(pNMHDR, pResult, &m_SharedData.stiSampleTime.dwValue, eMinSampleInterval, eMaxSampleInterval); } void CCountersProperty::OnSelendokSampleUnitsCombo() { int nSel; nSel = ((CComboBox *)GetDlgItem(IDC_CTRS_SAMPLE_UNITS_COMBO))->GetCurSel(); if ((nSel != LB_ERR) && (nSel != m_nSampleUnits)) { UpdateData ( TRUE ); SetModifiedPage ( TRUE ); } } void CCountersProperty::OnKillfocusSchedSampleEdit() { DWORD dwOldValue; dwOldValue = m_SharedData.stiSampleTime.dwValue; UpdateData ( TRUE ); if (dwOldValue != m_SharedData.stiSampleTime.dwValue ) { SetModifiedPage(TRUE); } } void CCountersProperty::PostNcDestroy() { // delete this; if ( NULL != m_pCtrLogQuery ) { m_pCtrLogQuery->SetActivePropertyPage( NULL ); } CPropertyPage::PostNcDestroy(); } // // Helper functions. // void CCountersProperty::ImplementAdd( BOOL bShowObjects ) { CListBox *pCounterList; LONG lBeforeCount; LONG lAfterCount; CString strBrowseTitle; ResourceStateManager rsm; static DWORD sdwDefaultBufferListSize = 0x4000; if (m_szCounterListBuffer == NULL) { CString strDefaultPath; CString strObjCounter; try { strObjCounter.LoadString ( IDS_DEFAULT_PATH_OBJ_CTR ); m_dwCounterListBufferSize = sdwDefaultBufferListSize; m_szCounterListBuffer = new WCHAR[m_dwCounterListBufferSize]; if ( ((CSmLogService*)m_pCtrLogQuery->GetLogService())->IsLocalMachine() ) { strDefaultPath = L"\\"; } else { strDefaultPath = L"\\\\"; strDefaultPath += ((CSmLogService*)m_pCtrLogQuery->GetLogService())->GetMachineName(); } strDefaultPath += strObjCounter; StringCchCopy ( m_szCounterListBuffer, m_dwCounterListBufferSize, strDefaultPath ); } catch ( ... ) { m_dwCounterListBufferSize = 0; return; } } m_dlgConfig.bIncludeInstanceIndex = 1; m_dlgConfig.bSingleCounterPerAdd = 0; m_dlgConfig.bSingleCounterPerDialog = 0; m_dlgConfig.bLocalCountersOnly = 0; // allow wild cards. // the log service should expand them if necessary. m_dlgConfig.bWildCardInstances = 1; m_dlgConfig.bHideDetailBox = 1; m_dlgConfig.bInitializePath = 1; m_dlgConfig.bDisableMachineSelection = 0; m_dlgConfig.bIncludeCostlyObjects = 0; m_dlgConfig.bReserved = 0; m_dlgConfig.hWndOwner = this->m_hWnd; m_dlgConfig.szDataSource = NULL; m_dlgConfig.szReturnPathBuffer = m_szCounterListBuffer; m_dlgConfig.cchReturnPathLength = m_dwCounterListBufferSize; m_dlgConfig.pCallBack = (CounterPathCallBack)DialogCallBack; m_dlgConfig.dwDefaultDetailLevel = PERF_DETAIL_WIZARD; m_dlgConfig.dwCallBackArg = (UINT_PTR)this; m_dlgConfig.CallBackStatus = ERROR_SUCCESS; m_dlgConfig.bShowObjectBrowser = (bShowObjects ? 1 : 0); strBrowseTitle.LoadString (bShowObjects ? IDS_ADD_OBJECTS : IDS_ADD_COUNTERS); m_dlgConfig.szDialogBoxCaption = strBrowseTitle.GetBuffer( strBrowseTitle.GetLength() ); pCounterList = (CListBox *)GetDlgItem(IDC_CTRS_COUNTER_LIST); // get count of items in the list box before calling the browser lBeforeCount = pCounterList->GetCount(); PdhBrowseCounters (&m_dlgConfig); strBrowseTitle.ReleaseBuffer(); // get count of items in the list box After calling the browser // to see if the Apply button should enabled lAfterCount = pCounterList->GetCount(); if (lAfterCount > lBeforeCount) SetModifiedPage(TRUE); // see if the remove button should be enabled SetButtonState(); delete [] m_szCounterListBuffer; m_szCounterListBuffer = NULL; m_dwCounterListBufferSize = 0; } void CCountersProperty::SetButtonState () { BOOL bCountersExist; CListBox *pCounterList; pCounterList = (CListBox *)GetDlgItem(IDC_CTRS_COUNTER_LIST); bCountersExist = ( 0 < pCounterList->GetCount()) ? TRUE : FALSE; GetDlgItem(IDC_CTRS_SAMPLE_CAPTION)->EnableWindow(bCountersExist); GetDlgItem(IDC_CTRS_SAMPLE_INTERVAL_CAPTION)->EnableWindow(bCountersExist); GetDlgItem(IDC_CTRS_SAMPLE_EDIT)->EnableWindow(bCountersExist); GetDlgItem(IDC_CTRS_SAMPLE_SPIN)->EnableWindow(bCountersExist); GetDlgItem(IDC_CTRS_SAMPLE_UNITS_CAPTION)->EnableWindow(bCountersExist); GetDlgItem(IDC_CTRS_SAMPLE_UNITS_COMBO)->EnableWindow(bCountersExist); GetDlgItem(IDC_CTRS_REMOVE_BTN)->EnableWindow(bCountersExist); if ( bCountersExist ) { GetDlgItem(IDC_CTRS_ADD_BTN)->SetFocus(); } }