//----------------------------------------------------------------------------- // Name: MakeStats // Object: compute statistics and add them to listview // Parameters : // in : // out : // return : //----------------------------------------------------------------------------- void CLogsStatsUI::MakeStats() { CLinkListItem* pItemLogList; CLinkListItem* pItemStatList; CLinkList* pStatList; LOG_LIST_ENTRY* pLogEntry; STATSTRUCT* pStat; STATSTRUCT Stat; BOOL bFoundInStatList; TCHAR** ppc=new TCHAR*[4]; TCHAR pszCallCount[12]; TCHAR pszAverageDuration[12]; DWORD AverageDuration; HCURSOR hOldCursor; // create a list of STATSTRUCT pStatList=new CLinkList(sizeof(STATSTRUCT)); // store original cursor hOldCursor=GetCursor(); // set cusor to wait cursor SetCursor(LoadCursor(NULL,IDC_WAIT)); // for each item in pLogList pLogList->Lock(TRUE); for (pItemLogList=pLogList->Head;pItemLogList;pItemLogList=pItemLogList->NextItem) { pLogEntry=(LOG_LIST_ENTRY*)pItemLogList->ItemData; // if pLogEntry is an user message, go to next entry if (pLogEntry->Type!=ENTRY_LOG) continue; bFoundInStatList=FALSE; // a function is defined by it's api name and module name // so try to find an item in pStatList with same api name and module name pStatList->Lock(); for (pItemStatList=pStatList->Head;pItemStatList;pItemStatList=pItemStatList->NextItem) { pStat=(STATSTRUCT*)pItemStatList->ItemData; // compare api and module name if (_tcsicmp(pStat->ApiName,pLogEntry->pLog->pszApiName)==0) { if(_tcsicmp(pStat->ModuleName,pLogEntry->pLog->pszModuleName)==0) { // the func is already in stat list, so update it's stat values // update count pStat->Count++; // update DurationSum (trying to avoid buffer overflow) if (0xFFFFFFFF-pLogEntry->pLog->pHookInfos->dwCallDuration<=pStat->DurationSum) pStat->DurationSum=0xFFFFFFFF; else pStat->DurationSum+=pLogEntry->pLog->pHookInfos->dwCallDuration; // we have found item bFoundInStatList=TRUE; break; } } } pStatList->Unlock(); // if item was not in state list, add it to stat list if (!bFoundInStatList) { _tcscpy(Stat.ApiName,pLogEntry->pLog->pszApiName); _tcscpy(Stat.ModuleName,pLogEntry->pLog->pszModuleName); Stat.Count=1; Stat.DurationSum=pLogEntry->pLog->pHookInfos->dwCallDuration; pStatList->AddItem(&Stat); } } pLogList->Unlock(); // for each item of pStatList pStatList->Lock(); for (pItemStatList=pStatList->Head;pItemStatList;pItemStatList=pItemStatList->NextItem) { // add item to list view pStat=(STATSTRUCT*)pItemStatList->ItemData; // api name ppc[0]=pStat->ApiName; // module name ppc[1]=pStat->ModuleName; // call count _stprintf(pszCallCount,_T("%u"),pStat->Count); ppc[2]=pszCallCount; // average duration AverageDuration=pStat->DurationSum/pStat->Count; if (pStat->DurationSum==0xFFFFFFFF) _stprintf(pszAverageDuration,_T(">%u"),AverageDuration); else _stprintf(pszAverageDuration,_T("%u"),AverageDuration); ppc[3]=pszAverageDuration; this->pListview->AddItemAndSubItems(4,ppc,FALSE); } pStatList->Unlock(); // free allocated memory delete[] ppc; delete pStatList; // restore original cursor SetCursor(hOldCursor); }
//----------------------------------------------------------------------------- // Name: ParseCOMMonitoringFileLine // Object: COM monitoring file line parser // Parameters : // in : // out : // return : //----------------------------------------------------------------------------- BOOL CComShowMethodsAddress::ParseCOMMonitoringFileLine(TCHAR* pszFileName,TCHAR* Line,DWORD dwLineNumber,LPVOID UserParam) { CMethodInfo* pMethodInfo; TCHAR* pszFunctionDefinition; TCHAR* psz; HOOK_DEFINITION_INFOS HookDefinitionInfos; BOOL bAlreadyExisting; SHOWMETHODSADDRESS_PARSE_COM_MONITORING_FILE_LINE_PARAM* pParam; pParam=(SHOWMETHODSADDRESS_PARSE_COM_MONITORING_FILE_LINE_PARAM*)UserParam; CTrimString::TrimString(Line); // if empty or commented line (WARNING we keep monitoring disabled lines !!!) if ((*Line==0)||(*Line==';')) // continue parsing return TRUE; if (*Line=='!') { Line++; CTrimString::TrimString(Line); } // line is like // vtbl hooking info|function definition|optional parameters // find first splitter (between vtbl hooking info definition and function definition) pszFunctionDefinition=_tcschr(Line,FIELDS_SEPARATOR); if (pszFunctionDefinition) { // ends line --> line contain only vtbl hooking info *pszFunctionDefinition=0; // point to function definition pszFunctionDefinition++; } // get vtbl hooking info definition if(!GetHookDefinitionInfo(Line,pParam->pIid,&HookDefinitionInfos)) { return ReportParsingError(pszFileName,dwLineNumber); } // if we need a full iid spying, the matching IID file needs to be loaded if (HookDefinitionInfos.VTBLInfoType==VTBL_INFO_TYPE_OBJECT_FULL_IID) { CLinkList* mpLinkListOfBaseInterfacesID; if (pParam->pLinkListOfBaseInterfacesID) mpLinkListOfBaseInterfacesID=pParam->pLinkListOfBaseInterfacesID; else mpLinkListOfBaseInterfacesID=new CLinkList(sizeof(IID)); CLinkListItem* pItem=mpLinkListOfBaseInterfacesID->AddItem(&HookDefinitionInfos.InterfaceID); pParam->pComShowMethodsAddress->ParseInterfaceDefinitionFile(pParam->pHookedClass, pParam->pIid, pParam->pInterfaceAssociatedToIID, pParam->pHookedObject, &HookDefinitionInfos.InterfaceID, mpLinkListOfBaseInterfacesID ); mpLinkListOfBaseInterfacesID->RemoveItem(pItem); if (!pParam->pLinkListOfBaseInterfacesID) delete mpLinkListOfBaseInterfacesID; // continue parsing return TRUE; } if (!pszFunctionDefinition) { return ReportParsingError(pszFileName,dwLineNumber); } // get function name (avoid HookComInfos.ParseFunctionDescription to avoid to load APIOverride dll) // search end of function name psz=_tcschr(pszFunctionDefinition, '('); if (psz) *psz=0; // remove return type in function name if any or WINAPI, __cdecl keywords // search last space in function name psz=_tcsrchr(pszFunctionDefinition,' '); // keep only data after last space if (psz) { psz++;// point to char after space pszFunctionDefinition=psz; } // get method info (this will auto add pMethodInfo object to matching interface) if (!pParam->pHookedClass->GetMethodInfoForHook(pParam->pHookedObject, pParam->pInterfaceAssociatedToIID, pParam->pLinkListOfBaseInterfacesID, &HookDefinitionInfos, pszFunctionDefinition, pszFileName, dwLineNumber, HOOK_TYPE_MONITORING, TRUE,// act like auto hooking &pMethodInfo, &bAlreadyExisting)) { // continue parsing return TRUE; } // copy api name into pMethodInfo pMethodInfo->SetName(pszFunctionDefinition); // continue parsing return TRUE; }