Изначальная проблема: Есть модуль достаточно большой чтобы в нем было тяжело отслеживать GDI лики на глаз. Т.е. необходимо хотябы средство для опеределения есть ли лики или их нет, есть ли нюансы с GDI ресурсами. Причем, и что то вроде Код (Text): { CPen ppen,*poldpen; ppen.CreatePen(...); poldpen = pDC->SelectObject(&ppen); poldpen->DeleteObject(); } // ну и далее deselect ppen-а не производиться. Хотя он удаляется так как вызывается деструктор CPen-а. Этот нюанс BoundsChecker правда достаточно старый не отловил. Начал писать сам с помощью перехвата API функций, но обнаружилось, что во всех описанных методах, не учитывается, что ".idata" может и не быть(в частности такое и наблюдается в MFC42.dll. Почему нужно перехватывать функции не только в главном модуле, но и в этой дллке? Т.к. большинство не inline GDI функций вызываются через нее). Вопрос: Как перехватывать API функции у модулей без ".idata" а также вопрос. есть ли уже написанные freeware утилиты для контроля утечек www.deleaker.com не подходит т.к. проект написан не под VC7.0 а еще под VC5.0 ;( Код (Text): 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 } /* Передается имя модуля в которов будет осуществляться перехват и массив функций для перехвата */ 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;} if(i==16) return false; /*!!!!Вот здесь код кончает работу для MFC42.dll, потому как нет ".idata" !!!!*/ 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; }
DevPartner вроде неплохо отлавливает учетки и ошибки. Правда, немало и ложных срабатываний. А MFC::CPen в деструкторе не удаляет объект или мне показалось? WTL и то умнее..