Есть программа -- огромный кусок кода, который оказывается не хочет скролироваться под win98 (выше ок). Ясно почему: большое количество скролирований приводит к частой перерисовке, а она к утечкам ресурсов, которые заметны почему-то только под win98.
Попробовал написать перехват API функций, но не смог перехватить GDI-шные функции у MFC42.dll (inline функции импортируеются в программу остальные же так и остаются обрамленными MFC42.dll). Как быть? Есть ли уже написанные утилиты, которые тестят утечку и неправильное использование GDI ресурсов?
Если самому писать, то в чем неправда, в написанном коде подмены (см. код ниже).
//функция которой передается имя модуля и заготовка (массив) функций которые нужно подставить
bool CCounter::install(LPCTSTR _szModule,CThunk* _pthunk)
{
m_log.Empty();
m_log.Format(_T("Install API intercepter module for %s\n")
,_szModule?_szModule:_T("NULL"));
int i;
for(i=0;i<m_thunkvec.size();i++)m_thunkvec[i] = NULL;
VERIFY_EXIT1(_pthunk!=NULL,false);
LPBYTE pimage = (LPBYTE)::GetModuleHandle(_szModule);
if(!pimage) return false;
IMAGE_DOS_HEADER *idh;
IMAGE_OPTIONAL_HEADER *ioh;
IMAGE_SECTION_HEADER *ish;
IMAGE_IMPORT_DESCRIPTOR *iid;
idh = (IMAGE_DOS_HEADER*)pimage;
ioh = (IMAGE_OPTIONAL_HEADER*)(pimage + idh->e_lfanew
+ 4 + sizeof(IMAGE_FILE_HEADER));
ish = (IMAGE_SECTION_HEADER*)((BYTE*)ioh + sizeof(IMAGE_OPTIONAL_HEADER));
if(idh->e_magic!=0x5A4D) return false;
for(i=0; i<16; i++) {if(_stricmp((char*)((ish+i)->Name) , ".idata") == 0) break;}
//для mfc42.dll не можут найти ".idata" секцию
//поэтому выходит.
if(i==16) return false;
iid = (IMAGE_IMPORT_DESCRIPTOR*)(pimage + (ish +i)->VirtualAddress);
for(;*_pthunk;_pthunk++)
{
CThunk* pthunk = new CThunk;
*pthunk = *_pthunk;
if(!pthunk->install(pimage,iid))
{
delete pthunk;
continue;
}
installed(_szModule,*pthunk);
}
m_binitialized = true;
m_module = _szModule;
return true;
}
bool CThunk::install(LPBYTE _pimage,IMAGE_IMPORT_DESCRIPTOR* _iid)
{
m_pRVAThunk = NULL;
VERIFY_EXIT1(NULL!=m_szModule && NULL!=m_szFuncName,false);
VERIFY_EXIT1(NULL!=m_func && NULL==m_oldfunc,false);
VERIFY_EXIT1(NULL!=_pimage && NULL !=_iid,false);
m_oldfunc = GetProcAddress(GetModuleHandle(m_szModule),m_szFuncName);
if(!m_oldfunc) return false; //can`t get module fucntion address
for(;_iid->Name;_iid++){if(_stricmp((char*)_pimage + _iid->Name,m_szModule)) break;}
if(!_iid->Name) return false; //no mudule
//IMAGE_THUNK_DATA* pOrigThunk = (IMAGE_THUNK_DATA*)(_pimage + (DWORD)_iid->OriginalFirstThunk);
IMAGE_THUNK_DATA* pRealThunk = (IMAGE_THUNK_DATA*)(_pimage + (DWORD)_iid->FirstThunk);
for(;*(LPDWORD)pRealThunk;pRealThunk++)
{
if(pRealThunk->u1.Function!=m_oldfunc) continue;
//intercept fucntion address;
DWORD buf = (DWORD)m_func;
DWORD op=0;
VirtualProtect((LPVOID)pRealThunk,4,PAGE_READWRITE,&op);
DWORD written = 0;
WriteProcessMemory(GetCurrentProcess(),(LPVOID)pRealThunk,(LPVOID)&buf,4,&written);
VirtualProtect((LPVOID)pRealThunk,4,op,&op);
if(4!=written) return false;
m_pRVAThunk = pRealThunk;
return true;
}
return false;//can`t find fucntion in import list
}