Утечка GDI ресурсов.
От: klizardin  
Дата: 30.06.06 13:48
Оценка:
Есть программа -- огромный кусок кода, который оказывается не хочет скролироваться под 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
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.