1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072 |
- {**************************************************************************************************}
- { }
- { Project JEDI Code Library (JCL) }
- { }
- { The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); }
- { you may not use this file except in compliance with the License. You may obtain a copy of the }
- { License at http://www.mozilla.org/MPL/ }
- { }
- { Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF }
- { ANY KIND, either express or implied. See the License for the specific language governing rights }
- { and limitations under the License. }
- { }
- { The Original Code is JclPeImage.pas. }
- { }
- { The Initial Developer of the Original Code is Petr Vones. Portions created by Petr Vones are }
- { Copyright (C) Petr Vones. All Rights Reserved. }
- { }
- { Contributor(s): }
- { Marcel van Brakel }
- { Robert Marquardt (marquardt) }
- { Uwe Schuster (uschuster) }
- { Matthias Thoma (mthoma) }
- { Petr Vones (pvones) }
- { Hallvard Vassbotn }
- { Jean-Fabien Connault (cycocrew) }
- { }
- {**************************************************************************************************}
- { }
- { This unit contains various classes and support routines to read the contents of portable }
- { executable (PE) files. You can use these classes to, for example examine the contents of the }
- { imports section of an executable. In addition the unit contains support for Borland specific }
- { structures and name unmangling. }
- { }
- {**************************************************************************************************}
- { }
- { Last modified: $Date:: $ }
- { Revision: $Rev:: $ }
- { Author: $Author:: $ }
- { }
- {**************************************************************************************************}
- unit JclPeImage;
- {$I jcl.inc}
- {$I windowsonly.inc}
- interface
- uses
- {$IFDEF UNITVERSIONING}
- JclUnitVersioning,
- {$ENDIF UNITVERSIONING}
- {$IFDEF HAS_UNITSCOPE}
- Winapi.Windows, System.Classes, System.SysUtils, System.TypInfo, System.Contnrs,
- {$ELSE ~HAS_UNITSCOPE}
- Windows, Classes, SysUtils, TypInfo, Contnrs,
- {$ENDIF ~HAS_UNITSCOPE}
- JclBase, {$IFNDEF WINSCP}JclDateTime,{$ENDIF ~WINSCP} JclFileUtils, JclWin32;
- type
- // Smart name compare function
- TJclSmartCompOption = (scSimpleCompare, scIgnoreCase);
- TJclSmartCompOptions = set of TJclSmartCompOption;
- function PeStripFunctionAW(const FunctionName: string): string;
- function PeSmartFunctionNameSame(const ComparedName, FunctionName: string;
- Options: TJclSmartCompOptions = []): Boolean;
- type
- // Base list
- EJclPeImageError = class(EJclError);
- TJclPeImage = class;
- TJclPeImageClass = class of TJclPeImage;
- TJclPeImageBaseList = class(TObjectList)
- private
- FImage: TJclPeImage;
- public
- constructor Create(AImage: TJclPeImage);
- property Image: TJclPeImage read FImage;
- end;
- // Images cache
- TJclPeImagesCache = class(TObject)
- private
- FList: TStringList;
- function GetCount: Integer;
- function GetImages(const FileName: TFileName): TJclPeImage;
- protected
- function GetPeImageClass: TJclPeImageClass; virtual;
- public
- constructor Create;
- destructor Destroy; override;
- procedure Clear;
- property Images[const FileName: TFileName]: TJclPeImage read GetImages; default;
- property Count: Integer read GetCount;
- end;
- // Import section related classes
- TJclPeImportSort = (isName, isOrdinal, isHint, isLibImport);
- TJclPeImportLibSort = (ilName, ilIndex);
- TJclPeImportKind = (ikImport, ikDelayImport, ikBoundImport);
- TJclPeResolveCheck = (icNotChecked, icResolved, icUnresolved);
- TJclPeLinkerProducer = (lrBorland, lrMicrosoft);
- // lrBorland -> Delphi PE files
- // lrMicrosoft -> MSVC and BCB PE files
- TJclPeImportLibItem = class;
- // Created from a IMAGE_THUNK_DATA64 or IMAGE_THUNK_DATA32 record
- TJclPeImportFuncItem = class(TObject)
- private
- FOrdinal: Word; // word in 32/64
- FHint: Word;
- FImportLib: TJclPeImportLibItem;
- FIndirectImportName: Boolean;
- FName: string;
- FResolveCheck: TJclPeResolveCheck;
- function GetIsByOrdinal: Boolean;
- protected
- procedure SetName(const Value: string);
- procedure SetIndirectImportName(const Value: string);
- procedure SetResolveCheck(Value: TJclPeResolveCheck);
- public
- constructor Create(AImportLib: TJclPeImportLibItem; AOrdinal: Word;
- AHint: Word; const AName: string);
- property Ordinal: Word read FOrdinal;
- property Hint: Word read FHint;
- property ImportLib: TJclPeImportLibItem read FImportLib;
- property IndirectImportName: Boolean read FIndirectImportName;
- property IsByOrdinal: Boolean read GetIsByOrdinal;
- property Name: string read FName;
- property ResolveCheck: TJclPeResolveCheck read FResolveCheck;
- end;
- // Created from a IMAGE_IMPORT_DESCRIPTOR
- TJclPeImportLibItem = class(TJclPeImageBaseList)
- private
- FImportDescriptor: Pointer;
- FImportDirectoryIndex: Integer;
- FImportKind: TJclPeImportKind;
- FLastSortType: TJclPeImportSort;
- FLastSortDescending: Boolean;
- FName: string;
- FSorted: Boolean;
- FUseRVA: Boolean;
- FTotalResolveCheck: TJclPeResolveCheck;
- FThunk: Pointer;
- FThunkData: Pointer;
- function GetCount: Integer;
- function GetFileName: TFileName;
- function GetItems(Index: Integer): TJclPeImportFuncItem;
- function GetName: string;
- function GetThunkData32: PImageThunkData32;
- function GetThunkData64: PImageThunkData64;
- protected
- procedure CheckImports(ExportImage: TJclPeImage);
- procedure CreateList;
- procedure SetImportDirectoryIndex(Value: Integer);
- procedure SetImportKind(Value: TJclPeImportKind);
- procedure SetSorted(Value: Boolean);
- procedure SetThunk(Value: Pointer);
- public
- constructor Create(AImage: TJclPeImage; AImportDescriptor: Pointer;
- AImportKind: TJclPeImportKind; const AName: string; AThunk: Pointer; AUseRVA: Boolean = True);
- procedure SortList(SortType: TJclPeImportSort; Descending: Boolean = False);
- property Count: Integer read GetCount;
- property FileName: TFileName read GetFileName;
- property ImportDescriptor: Pointer read FImportDescriptor;
- property ImportDirectoryIndex: Integer read FImportDirectoryIndex;
- property ImportKind: TJclPeImportKind read FImportKind;
- property Items[Index: Integer]: TJclPeImportFuncItem read GetItems; default;
- property Name: string read GetName;
- property OriginalName: string read FName;
- // use the following properties
- // property ThunkData: PImageThunkData
- property ThunkData32: PImageThunkData32 read GetThunkData32;
- property ThunkData64: PImageThunkData64 read GetThunkData64;
- property TotalResolveCheck: TJclPeResolveCheck read FTotalResolveCheck;
- end;
- TJclPeImportList = class(TJclPeImageBaseList)
- private
- FAllItemsList: TList;
- FFilterModuleName: string;
- FLastAllSortType: TJclPeImportSort;
- FLastAllSortDescending: Boolean;
- FLinkerProducer: TJclPeLinkerProducer;
- FParallelImportTable: array of Pointer;
- FUniqueNamesList: TStringList;
- function GetAllItemCount: Integer;
- function GetAllItems(Index: Integer): TJclPeImportFuncItem;
- function GetItems(Index: Integer): TJclPeImportLibItem;
- function GetUniqueLibItemCount: Integer;
- function GetUniqueLibItems(Index: Integer): TJclPeImportLibItem;
- function GetUniqueLibNames(Index: Integer): string;
- function GetUniqueLibItemFromName(const Name: string): TJclPeImportLibItem;
- procedure SetFilterModuleName(const Value: string);
- protected
- procedure CreateList;
- procedure RefreshAllItems;
- public
- constructor Create(AImage: TJclPeImage);
- destructor Destroy; override;
- procedure CheckImports(PeImageCache: TJclPeImagesCache = nil);
- function MakeBorlandImportTableForMappedImage: Boolean;
- function SmartFindName(const CompareName, LibName: string; Options: TJclSmartCompOptions = []): TJclPeImportFuncItem;
- procedure SortAllItemsList(SortType: TJclPeImportSort; Descending: Boolean = False);
- procedure SortList(SortType: TJclPeImportLibSort);
- procedure TryGetNamesForOrdinalImports;
- property AllItems[Index: Integer]: TJclPeImportFuncItem read GetAllItems;
- property AllItemCount: Integer read GetAllItemCount;
- property FilterModuleName: string read FFilterModuleName write SetFilterModuleName;
- property Items[Index: Integer]: TJclPeImportLibItem read GetItems; default;
- property LinkerProducer: TJclPeLinkerProducer read FLinkerProducer;
- property UniqueLibItemCount: Integer read GetUniqueLibItemCount;
- property UniqueLibItemFromName[const Name: string]: TJclPeImportLibItem read GetUniqueLibItemFromName;
- property UniqueLibItems[Index: Integer]: TJclPeImportLibItem read GetUniqueLibItems;
- property UniqueLibNames[Index: Integer]: string read GetUniqueLibNames;
- end;
- // Export section related classes
- TJclPeExportSort = (esName, esOrdinal, esHint, esAddress, esForwarded, esAddrOrFwd, esSection);
- TJclPeExportFuncList = class;
- // Created from a IMAGE_EXPORT_DIRECTORY
- TJclPeExportFuncItem = class(TObject)
- private
- FAddress: DWORD;
- FExportList: TJclPeExportFuncList;
- FForwardedName: string;
- FForwardedDotPos: string;
- FHint: Word;
- FName: string;
- FOrdinal: Word;
- FResolveCheck: TJclPeResolveCheck;
- function GetAddressOrForwardStr: string;
- function GetForwardedFuncName: string;
- function GetForwardedLibName: string;
- function GetForwardedFuncOrdinal: DWORD;
- function GetIsExportedVariable: Boolean;
- function GetIsForwarded: Boolean;
- function GetSectionName: string;
- function GetMappedAddress: Pointer;
- protected
- procedure SetResolveCheck(Value: TJclPeResolveCheck);
- public
- constructor Create(AExportList: TJclPeExportFuncList; const AName, AForwardedName: string;
- AAddress: DWORD; AHint: Word; AOrdinal: Word; AResolveCheck: TJclPeResolveCheck);
- property Address: DWORD read FAddress;
- property AddressOrForwardStr: string read GetAddressOrForwardStr;
- property IsExportedVariable: Boolean read GetIsExportedVariable;
- property IsForwarded: Boolean read GetIsForwarded;
- property ForwardedName: string read FForwardedName;
- property ForwardedLibName: string read GetForwardedLibName;
- property ForwardedFuncOrdinal: DWORD read GetForwardedFuncOrdinal;
- property ForwardedFuncName: string read GetForwardedFuncName;
- property Hint: Word read FHint;
- property MappedAddress: Pointer read GetMappedAddress;
- property Name: string read FName;
- property Ordinal: Word read FOrdinal;
- property ResolveCheck: TJclPeResolveCheck read FResolveCheck;
- property SectionName: string read GetSectionName;
- end;
- TJclPeExportFuncList = class(TJclPeImageBaseList)
- private
- FAnyForwards: Boolean;
- FBase: DWORD;
- FExportDir: PImageExportDirectory;
- FForwardedLibsList: TStringList;
- FFunctionCount: DWORD;
- FLastSortType: TJclPeExportSort;
- FLastSortDescending: Boolean;
- FSorted: Boolean;
- FTotalResolveCheck: TJclPeResolveCheck;
- function GetForwardedLibsList: TStrings;
- function GetItems(Index: Integer): TJclPeExportFuncItem;
- function GetItemFromAddress(Address: DWORD): TJclPeExportFuncItem;
- function GetItemFromOrdinal(Ordinal: DWORD): TJclPeExportFuncItem;
- function GetItemFromName(const Name: string): TJclPeExportFuncItem;
- function GetName: string;
- protected
- function CanPerformFastNameSearch: Boolean;
- procedure CreateList;
- property LastSortType: TJclPeExportSort read FLastSortType;
- property LastSortDescending: Boolean read FLastSortDescending;
- property Sorted: Boolean read FSorted;
- public
- constructor Create(AImage: TJclPeImage);
- destructor Destroy; override;
- procedure CheckForwards(PeImageCache: TJclPeImagesCache = nil);
- class function ItemName(Item: TJclPeExportFuncItem): string;
- function OrdinalValid(Ordinal: DWORD): Boolean;
- procedure PrepareForFastNameSearch;
- function SmartFindName(const CompareName: string; Options: TJclSmartCompOptions = []): TJclPeExportFuncItem;
- procedure SortList(SortType: TJclPeExportSort; Descending: Boolean = False);
- property AnyForwards: Boolean read FAnyForwards;
- property Base: DWORD read FBase;
- property ExportDir: PImageExportDirectory read FExportDir;
- property ForwardedLibsList: TStrings read GetForwardedLibsList;
- property FunctionCount: DWORD read FFunctionCount;
- property Items[Index: Integer]: TJclPeExportFuncItem read GetItems; default;
- property ItemFromAddress[Address: DWORD]: TJclPeExportFuncItem read GetItemFromAddress;
- property ItemFromName[const Name: string]: TJclPeExportFuncItem read GetItemFromName;
- property ItemFromOrdinal[Ordinal: DWORD]: TJclPeExportFuncItem read GetItemFromOrdinal;
- property Name: string read GetName;
- property TotalResolveCheck: TJclPeResolveCheck read FTotalResolveCheck;
- end;
- // Resource section related classes
- TJclPeResourceKind = (
- rtUnknown0,
- rtCursorEntry,
- rtBitmap,
- rtIconEntry,
- rtMenu,
- rtDialog,
- rtString,
- rtFontDir,
- rtFont,
- rtAccelerators,
- rtRCData,
- rtMessageTable,
- rtCursor,
- rtUnknown13,
- rtIcon,
- rtUnknown15,
- rtVersion,
- rtDlgInclude,
- rtUnknown18,
- rtPlugPlay,
- rtVxd,
- rtAniCursor,
- rtAniIcon,
- rtHmtl,
- rtManifest,
- rtUserDefined);
- TJclPeResourceList = class;
- TJclPeResourceItem = class;
- TJclPeResourceRawStream = class(TCustomMemoryStream)
- public
- constructor Create(AResourceItem: TJclPeResourceItem);
- function Write(const Buffer; Count: Longint): Longint; override;
- end;
- TJclPeResourceItem = class(TObject)
- private
- FEntry: PImageResourceDirectoryEntry;
- FImage: TJclPeImage;
- FList: TJclPeResourceList;
- FLevel: Byte;
- FParentItem: TJclPeResourceItem;
- FNameCache: string;
- function GetDataEntry: PImageResourceDataEntry;
- function GetIsDirectory: Boolean;
- function GetIsName: Boolean;
- function GetLangID: LANGID;
- function GetList: TJclPeResourceList;
- function GetName: string;
- function GetParameterName: string;
- function GetRawEntryData: Pointer;
- function GetRawEntryDataSize: Integer;
- function GetResourceType: TJclPeResourceKind;
- function GetResourceTypeStr: string;
- protected
- function OffsetToRawData(Ofs: DWORD): TJclAddr;
- function Level1Item: TJclPeResourceItem;
- function SubDirData: PImageResourceDirectory;
- public
- constructor Create(AImage: TJclPeImage; AParentItem: TJclPeResourceItem;
- AEntry: PImageResourceDirectoryEntry);
- destructor Destroy; override;
- function CompareName(AName: PChar): Boolean;
- property DataEntry: PImageResourceDataEntry read GetDataEntry;
- property Entry: PImageResourceDirectoryEntry read FEntry;
- property Image: TJclPeImage read FImage;
- property IsDirectory: Boolean read GetIsDirectory;
- property IsName: Boolean read GetIsName;
- property LangID: LANGID read GetLangID;
- property List: TJclPeResourceList read GetList;
- property Level: Byte read FLevel;
- property Name: string read GetName;
- property ParameterName: string read GetParameterName;
- property ParentItem: TJclPeResourceItem read FParentItem;
- property RawEntryData: Pointer read GetRawEntryData;
- property RawEntryDataSize: Integer read GetRawEntryDataSize;
- property ResourceType: TJclPeResourceKind read GetResourceType;
- property ResourceTypeStr: string read GetResourceTypeStr;
- end;
- TJclPeResourceList = class(TJclPeImageBaseList)
- private
- FDirectory: PImageResourceDirectory;
- FParentItem: TJclPeResourceItem;
- function GetItems(Index: Integer): TJclPeResourceItem;
- protected
- procedure CreateList(AParentItem: TJclPeResourceItem);
- public
- constructor Create(AImage: TJclPeImage; AParentItem: TJclPeResourceItem;
- ADirectory: PImageResourceDirectory);
- function FindName(const Name: string): TJclPeResourceItem;
- property Directory: PImageResourceDirectory read FDirectory;
- property Items[Index: Integer]: TJclPeResourceItem read GetItems; default;
- property ParentItem: TJclPeResourceItem read FParentItem;
- end;
- TJclPeRootResourceList = class(TJclPeResourceList)
- private
- FManifestContent: TStringList;
- function GetManifestContent: TStrings;
- public
- destructor Destroy; override;
- function FindResource(ResourceType: TJclPeResourceKind;
- const ResourceName: string = ''): TJclPeResourceItem; overload;
- function FindResource(const ResourceType: PChar;
- const ResourceName: PChar = nil): TJclPeResourceItem; overload;
- function ListResourceNames(ResourceType: TJclPeResourceKind; const Strings: TStrings): Boolean;
- property ManifestContent: TStrings read GetManifestContent;
- end;
- // Relocation section related classes
- TJclPeRelocation = record
- Address: Word;
- RelocType: Byte;
- VirtualAddress: DWORD;
- end;
- TJclPeRelocEntry = class(TObject)
- private
- FChunk: PImageBaseRelocation;
- FCount: Integer;
- function GetRelocations(Index: Integer): TJclPeRelocation;
- function GetSize: DWORD;
- function GetVirtualAddress: DWORD;
- public
- constructor Create(AChunk: PImageBaseRelocation; ACount: Integer);
- property Count: Integer read FCount;
- property Relocations[Index: Integer]: TJclPeRelocation read GetRelocations; default;
- property Size: DWORD read GetSize;
- property VirtualAddress: DWORD read GetVirtualAddress;
- end;
- TJclPeRelocList = class(TJclPeImageBaseList)
- private
- FAllItemCount: Integer;
- function GetItems(Index: Integer): TJclPeRelocEntry;
- function GetAllItems(Index: Integer): TJclPeRelocation;
- protected
- procedure CreateList;
- public
- constructor Create(AImage: TJclPeImage);
- property AllItems[Index: Integer]: TJclPeRelocation read GetAllItems;
- property AllItemCount: Integer read FAllItemCount;
- property Items[Index: Integer]: TJclPeRelocEntry read GetItems; default;
- end;
- // Debug section related classes
- TJclPeDebugList = class(TJclPeImageBaseList)
- private
- function GetItems(Index: Integer): TImageDebugDirectory;
- function IsTD32DebugInfo(DebugDir: PImageDebugDirectory): Boolean;
- protected
- procedure CreateList;
- public
- constructor Create(AImage: TJclPeImage);
- property Items[Index: Integer]: TImageDebugDirectory read GetItems; default;
- end;
- // Certificates section related classes
- TJclPeCertificate = class(TObject)
- private
- FData: Pointer;
- FHeader: TWinCertificate;
- public
- constructor Create(AHeader: TWinCertificate; AData: Pointer);
- property Data: Pointer read FData;
- property Header: TWinCertificate read FHeader;
- end;
- TJclPeCertificateList = class(TJclPeImageBaseList)
- private
- function GetItems(Index: Integer): TJclPeCertificate;
- protected
- procedure CreateList;
- public
- constructor Create(AImage: TJclPeImage);
- property Items[Index: Integer]: TJclPeCertificate read GetItems; default;
- end;
- // Common Language Runtime section related classes
- TJclPeCLRHeader = class(TObject)
- private
- FHeader: TImageCor20Header;
- FImage: TJclPeImage;
- function GetVersionString: string;
- function GetHasMetadata: Boolean;
- protected
- procedure ReadHeader;
- public
- constructor Create(AImage: TJclPeImage);
- property HasMetadata: Boolean read GetHasMetadata;
- property Header: TImageCor20Header read FHeader;
- property VersionString: string read GetVersionString;
- property Image: TJclPeImage read FImage;
- end;
- // PE Image
- TJclPeHeader = (
- JclPeHeader_Signature,
- JclPeHeader_Machine,
- JclPeHeader_NumberOfSections,
- JclPeHeader_TimeDateStamp,
- JclPeHeader_PointerToSymbolTable,
- JclPeHeader_NumberOfSymbols,
- JclPeHeader_SizeOfOptionalHeader,
- JclPeHeader_Characteristics,
- JclPeHeader_Magic,
- JclPeHeader_LinkerVersion,
- JclPeHeader_SizeOfCode,
- JclPeHeader_SizeOfInitializedData,
- JclPeHeader_SizeOfUninitializedData,
- JclPeHeader_AddressOfEntryPoint,
- JclPeHeader_BaseOfCode,
- JclPeHeader_BaseOfData,
- JclPeHeader_ImageBase,
- JclPeHeader_SectionAlignment,
- JclPeHeader_FileAlignment,
- JclPeHeader_OperatingSystemVersion,
- JclPeHeader_ImageVersion,
- JclPeHeader_SubsystemVersion,
- JclPeHeader_Win32VersionValue,
- JclPeHeader_SizeOfImage,
- JclPeHeader_SizeOfHeaders,
- JclPeHeader_CheckSum,
- JclPeHeader_Subsystem,
- JclPeHeader_DllCharacteristics,
- JclPeHeader_SizeOfStackReserve,
- JclPeHeader_SizeOfStackCommit,
- JclPeHeader_SizeOfHeapReserve,
- JclPeHeader_SizeOfHeapCommit,
- JclPeHeader_LoaderFlags,
- JclPeHeader_NumberOfRvaAndSizes);
- TJclLoadConfig = (
- JclLoadConfig_Characteristics, { TODO : rename to Size? }
- JclLoadConfig_TimeDateStamp,
- JclLoadConfig_Version,
- JclLoadConfig_GlobalFlagsClear,
- JclLoadConfig_GlobalFlagsSet,
- JclLoadConfig_CriticalSectionDefaultTimeout,
- JclLoadConfig_DeCommitFreeBlockThreshold,
- JclLoadConfig_DeCommitTotalFreeThreshold,
- JclLoadConfig_LockPrefixTable,
- JclLoadConfig_MaximumAllocationSize,
- JclLoadConfig_VirtualMemoryThreshold,
- JclLoadConfig_ProcessHeapFlags,
- JclLoadConfig_ProcessAffinityMask,
- JclLoadConfig_CSDVersion,
- JclLoadConfig_Reserved1,
- JclLoadConfig_EditList,
- JclLoadConfig_Reserved { TODO : extend to the new fields? }
- );
- TJclPeFileProperties = record
- Size: DWORD;
- CreationTime: TDateTime;
- LastAccessTime: TDateTime;
- LastWriteTime: TDateTime;
- Attributes: Integer;
- end;
- TJclPeImageStatus = (stNotLoaded, stOk, stNotPE, stNotSupported, stNotFound, stError);
- TJclPeTarget = (taUnknown, taWin32, taWin64);
- TJclPeImage = class(TObject)
- private
- FAttachedImage: Boolean;
- FCertificateList: TJclPeCertificateList;
- FCLRHeader: TJclPeCLRHeader;
- FDebugList: TJclPeDebugList;
- FFileName: TFileName;
- FImageSections: TStringList;
- FLoadedImage: TLoadedImage;
- FExportList: TJclPeExportFuncList;
- FImportList: TJclPeImportList;
- FNoExceptions: Boolean;
- FReadOnlyAccess: Boolean;
- FRelocationList: TJclPeRelocList;
- FResourceList: TJclPeRootResourceList;
- FResourceVA: TJclAddr;
- FStatus: TJclPeImageStatus;
- FTarget: TJclPeTarget;
- FVersionInfo: TJclFileVersionInfo;
- FStringTable: TStringList;
- function GetCertificateList: TJclPeCertificateList;
- function GetCLRHeader: TJclPeCLRHeader;
- function GetDebugList: TJclPeDebugList;
- function GetDescription: string;
- function GetDirectories(Directory: Word): TImageDataDirectory;
- function GetDirectoryExists(Directory: Word): Boolean;
- function GetExportList: TJclPeExportFuncList;
- {$IFNDEF WINSCP}
- function GetFileProperties: TJclPeFileProperties;
- {$ENDIF ~WINSCP}
- function GetImageSectionCount: Integer;
- function GetImageSectionHeaders(Index: Integer): TImageSectionHeader;
- function GetImageSectionNames(Index: Integer): string;
- function GetImageSectionNameFromRva(const Rva: DWORD): string;
- function GetImportList: TJclPeImportList;
- function GetHeaderValues(Index: TJclPeHeader): string;
- function GetLoadConfigValues(Index: TJclLoadConfig): string;
- function GetMappedAddress: TJclAddr;
- function GetOptionalHeader32: TImageOptionalHeader32;
- function GetOptionalHeader64: TImageOptionalHeader64;
- function GetRelocationList: TJclPeRelocList;
- function GetResourceList: TJclPeRootResourceList;
- function GetUnusedHeaderBytes: TImageDataDirectory;
- function GetVersionInfo: TJclFileVersionInfo;
- function GetVersionInfoAvailable: Boolean;
- procedure ReadImageSections;
- procedure ReadStringTable;
- procedure SetFileName(const Value: TFileName);
- function GetStringTableCount: Integer;
- function GetStringTableItem(Index: Integer): string;
- function GetImageSectionFullNames(Index: Integer): string;
- protected
- procedure AfterOpen; dynamic;
- procedure CheckNotAttached;
- procedure Clear; dynamic;
- function ExpandModuleName(const ModuleName: string): TFileName;
- procedure RaiseStatusException;
- function ResourceItemCreate(AEntry: PImageResourceDirectoryEntry;
- AParentItem: TJclPeResourceItem): TJclPeResourceItem; virtual;
- function ResourceListCreate(ADirectory: PImageResourceDirectory;
- AParentItem: TJclPeResourceItem): TJclPeResourceList; virtual;
- property NoExceptions: Boolean read FNoExceptions;
- public
- constructor Create(ANoExceptions: Boolean = False); virtual;
- destructor Destroy; override;
- procedure AttachLoadedModule(const Handle: HMODULE);
- function CalculateCheckSum: DWORD;
- function DirectoryEntryToData(Directory: Word): Pointer;
- function GetSectionHeader(const SectionName: string; out Header: PImageSectionHeader): Boolean;
- function GetSectionName(Header: PImageSectionHeader): string;
- function GetNameInStringTable(Offset: ULONG): string;
- function IsBrokenFormat: Boolean;
- function IsCLR: Boolean;
- function IsSystemImage: Boolean;
- // RVA are always DWORD
- function RawToVa(Raw: DWORD): Pointer; overload;
- function RvaToSection(Rva: DWORD): PImageSectionHeader; overload;
- function RvaToVa(Rva: DWORD): Pointer; overload;
- function ImageAddressToRva(Address: DWORD): DWORD;
- function StatusOK: Boolean;
- procedure TryGetNamesForOrdinalImports;
- function VerifyCheckSum: Boolean;
- class function DebugTypeNames(DebugType: DWORD): string;
- class function DirectoryNames(Directory: Word): string;
- class function ExpandBySearchPath(const ModuleName, BasePath: string): TFileName;
- class function HeaderNames(Index: TJclPeHeader): string;
- class function LoadConfigNames(Index: TJclLoadConfig): string;
- class function ShortSectionInfo(Characteristics: DWORD): string;
- class function DateTimeToStamp(const DateTime: TDateTime): DWORD;
- class function StampToDateTime(TimeDateStamp: DWORD): TDateTime;
- property AttachedImage: Boolean read FAttachedImage;
- property CertificateList: TJclPeCertificateList read GetCertificateList;
- property CLRHeader: TJclPeCLRHeader read GetCLRHeader;
- property DebugList: TJclPeDebugList read GetDebugList;
- property Description: string read GetDescription;
- property Directories[Directory: Word]: TImageDataDirectory read GetDirectories;
- property DirectoryExists[Directory: Word]: Boolean read GetDirectoryExists;
- property ExportList: TJclPeExportFuncList read GetExportList;
- property FileName: TFileName read FFileName write SetFileName;
- {$IFNDEF WINSCP}
- property FileProperties: TJclPeFileProperties read GetFileProperties;
- {$ENDIF ~WINSCP}
- property HeaderValues[Index: TJclPeHeader]: string read GetHeaderValues;
- property ImageSectionCount: Integer read GetImageSectionCount;
- property ImageSectionHeaders[Index: Integer]: TImageSectionHeader read GetImageSectionHeaders;
- property ImageSectionNames[Index: Integer]: string read GetImageSectionNames;
- property ImageSectionFullNames[Index: Integer]: string read GetImageSectionFullNames;
- property ImageSectionNameFromRva[const Rva: DWORD]: string read GetImageSectionNameFromRva;
- property ImportList: TJclPeImportList read GetImportList;
- property LoadConfigValues[Index: TJclLoadConfig]: string read GetLoadConfigValues;
- property LoadedImage: TLoadedImage read FLoadedImage;
- property MappedAddress: TJclAddr read GetMappedAddress;
- property StringTableCount: Integer read GetStringTableCount;
- property StringTable[Index: Integer]: string read GetStringTableItem;
- // use the following properties
- // property OptionalHeader: TImageOptionalHeader
- property OptionalHeader32: TImageOptionalHeader32 read GetOptionalHeader32;
- property OptionalHeader64: TImageOptionalHeader64 read GetOptionalHeader64;
- property ReadOnlyAccess: Boolean read FReadOnlyAccess write FReadOnlyAccess;
- property RelocationList: TJclPeRelocList read GetRelocationList;
- property ResourceVA: TJclAddr read FResourceVA;
- property ResourceList: TJclPeRootResourceList read GetResourceList;
- property Status: TJclPeImageStatus read FStatus;
- property Target: TJclPeTarget read FTarget;
- property UnusedHeaderBytes: TImageDataDirectory read GetUnusedHeaderBytes;
- property VersionInfo: TJclFileVersionInfo read GetVersionInfo;
- property VersionInfoAvailable: Boolean read GetVersionInfoAvailable;
- end;
- {$IFDEF BORLAND}
- TJclPeBorImage = class;
- TJclPeBorImagesCache = class(TJclPeImagesCache)
- private
- function GetImages(const FileName: TFileName): TJclPeBorImage;
- protected
- function GetPeImageClass: TJclPeImageClass; override;
- public
- property Images[const FileName: TFileName]: TJclPeBorImage read GetImages; default;
- end;
- // Borland Delphi PE Image specific information
- TJclPePackageInfo = class(TObject)
- private
- FAvailable: Boolean;
- FContains: TStringList;
- FDcpName: string;
- FRequires: TStringList;
- FFlags: Integer;
- FDescription: string;
- FEnsureExtension: Boolean;
- FSorted: Boolean;
- function GetContains: TStrings;
- function GetContainsCount: Integer;
- function GetContainsFlags(Index: Integer): Byte;
- function GetContainsNames(Index: Integer): string;
- function GetRequires: TStrings;
- function GetRequiresCount: Integer;
- function GetRequiresNames(Index: Integer): string;
- protected
- procedure ReadPackageInfo(ALibHandle: THandle);
- procedure SetDcpName(const Value: string);
- public
- constructor Create(ALibHandle: THandle);
- destructor Destroy; override;
- class function PackageModuleTypeToString(Flags: Cardinal): string;
- class function PackageOptionsToString(Flags: Cardinal): string;
- class function ProducerToString(Flags: Cardinal): string;
- class function UnitInfoFlagsToString(UnitFlags: Byte): string;
- property Available: Boolean read FAvailable;
- property Contains: TStrings read GetContains;
- property ContainsCount: Integer read GetContainsCount;
- property ContainsNames[Index: Integer]: string read GetContainsNames;
- property ContainsFlags[Index: Integer]: Byte read GetContainsFlags;
- property Description: string read FDescription;
- property DcpName: string read FDcpName;
- property EnsureExtension: Boolean read FEnsureExtension write FEnsureExtension;
- property Flags: Integer read FFlags;
- property Requires: TStrings read GetRequires;
- property RequiresCount: Integer read GetRequiresCount;
- property RequiresNames[Index: Integer]: string read GetRequiresNames;
- property Sorted: Boolean read FSorted write FSorted;
- end;
- TJclPeBorForm = class(TObject)
- private
- FFormFlags: TFilerFlags;
- FFormClassName: string;
- FFormObjectName: string;
- FFormPosition: Integer;
- FResItem: TJclPeResourceItem;
- function GetDisplayName: string;
- public
- constructor Create(AResItem: TJclPeResourceItem; AFormFlags: TFilerFlags;
- AFormPosition: Integer; const AFormClassName, AFormObjectName: string);
- procedure ConvertFormToText(const Stream: TStream); overload;
- procedure ConvertFormToText(const Strings: TStrings); overload;
- property FormClassName: string read FFormClassName;
- property FormFlags: TFilerFlags read FFormFlags;
- property FormObjectName: string read FFormObjectName;
- property FormPosition: Integer read FFormPosition;
- property DisplayName: string read GetDisplayName;
- property ResItem: TJclPeResourceItem read FResItem;
- end;
- TJclPeBorImage = class(TJclPeImage)
- private
- FForms: TObjectList;
- FIsPackage: Boolean;
- FIsBorlandImage: Boolean;
- FLibHandle: THandle;
- FPackageInfo: TJclPePackageInfo;
- FPackageInfoSorted: Boolean;
- FPackageCompilerVersion: Integer;
- function GetFormCount: Integer;
- function GetForms(Index: Integer): TJclPeBorForm;
- function GetFormFromName(const FormClassName: string): TJclPeBorForm;
- function GetLibHandle: THandle;
- function GetPackageCompilerVersion: Integer;
- function GetPackageInfo: TJclPePackageInfo;
- protected
- procedure AfterOpen; override;
- procedure Clear; override;
- procedure CreateFormsList;
- public
- constructor Create(ANoExceptions: Boolean = False); override;
- destructor Destroy; override;
- function DependedPackages(List: TStrings; FullPathName, Descriptions: Boolean): Boolean;
- function FreeLibHandle: Boolean;
- property Forms[Index: Integer]: TJclPeBorForm read GetForms;
- property FormCount: Integer read GetFormCount;
- property FormFromName[const FormClassName: string]: TJclPeBorForm read GetFormFromName;
- property IsBorlandImage: Boolean read FIsBorlandImage;
- property IsPackage: Boolean read FIsPackage;
- property LibHandle: THandle read GetLibHandle;
- property PackageCompilerVersion: Integer read GetPackageCompilerVersion;
- property PackageInfo: TJclPePackageInfo read GetPackageInfo;
- property PackageInfoSorted: Boolean read FPackageInfoSorted write FPackageInfoSorted;
- end;
- {$ENDIF BORLAND}
- // Threaded function search
- TJclPeNameSearchOption = (seImports, seDelayImports, seBoundImports, seExports);
- TJclPeNameSearchOptions = set of TJclPeNameSearchOption;
- TJclPeNameSearchNotifyEvent = procedure (Sender: TObject; PeImage: TJclPeImage;
- var Process: Boolean) of object;
- TJclPeNameSearchFoundEvent = procedure (Sender: TObject; const FileName: TFileName;
- const FunctionName: string; Option: TJclPeNameSearchOption) of object;
- TJclPeNameSearch = class(TThread)
- private
- F_FileName: TFileName;
- F_FunctionName: string;
- F_Option: TJclPeNameSearchOption;
- F_Process: Boolean;
- FFunctionName: string;
- FOptions: TJclPeNameSearchOptions;
- FPath: string;
- FPeImage: TJclPeImage;
- FOnFound: TJclPeNameSearchFoundEvent;
- FOnProcessFile: TJclPeNameSearchNotifyEvent;
- protected
- function CompareName(const FunctionName, ComparedName: string): Boolean; virtual;
- procedure DoFound;
- procedure DoProcessFile;
- procedure Execute; override;
- public
- constructor Create(const FunctionName, Path: string; Options: TJclPeNameSearchOptions = [seImports, seExports]);
- procedure Start;
- property OnFound: TJclPeNameSearchFoundEvent read FOnFound write FOnFound;
- property OnProcessFile: TJclPeNameSearchNotifyEvent read FOnProcessFile write FOnProcessFile;
- end;
- // PE Image miscellaneous functions
- type
- TJclRebaseImageInfo32 = record
- OldImageSize: DWORD;
- OldImageBase: TJclAddr32;
- NewImageSize: DWORD;
- NewImageBase: TJclAddr32;
- end;
- TJclRebaseImageInfo64 = record
- OldImageSize: DWORD;
- OldImageBase: TJclAddr64;
- NewImageSize: DWORD;
- NewImageBase: TJclAddr64;
- end;
- // renamed
- // TJclRebaseImageInfo = TJclRebaseImageInfo32;
- { Image validity }
- function IsValidPeFile(const FileName: TFileName): Boolean;
- // use PeGetNtHeaders32 for backward compatibility
- // function PeGetNtHeaders(const FileName: TFileName; out NtHeaders: TImageNtHeaders): Boolean;
- function PeGetNtHeaders32(const FileName: TFileName; out NtHeaders: TImageNtHeaders32): Boolean;
- function PeGetNtHeaders64(const FileName: TFileName; out NtHeaders: TImageNtHeaders64): Boolean;
- { Image modifications }
- function PeCreateNameHintTable(const FileName: TFileName): Boolean;
- // use PeRebaseImage32
- //function PeRebaseImage(const ImageName: TFileName; NewBase: DWORD = 0; TimeStamp: DWORD = 0;
- // MaxNewSize: DWORD = 0): TJclRebaseImageInfo;
- function PeRebaseImage32(const ImageName: TFileName; NewBase: TJclAddr32 = 0; TimeStamp: DWORD = 0;
- MaxNewSize: DWORD = 0): TJclRebaseImageInfo32;
- function PeRebaseImage64(const ImageName: TFileName; NewBase: TJclAddr64 = 0; TimeStamp: DWORD = 0;
- MaxNewSize: DWORD = 0): TJclRebaseImageInfo64;
- function PeUpdateLinkerTimeStamp(const FileName: TFileName; const Time: TDateTime): Boolean;
- function PeReadLinkerTimeStamp(const FileName: TFileName): TDateTime;
- function PeInsertSection(const FileName: TFileName; SectionStream: TStream; SectionName: string): Boolean;
- { Image Checksum }
- function PeVerifyCheckSum(const FileName: TFileName): Boolean;
- function PeClearCheckSum(const FileName: TFileName): Boolean;
- function PeUpdateCheckSum(const FileName: TFileName): Boolean;
- // Various simple PE Image searching and listing routines
- { Exports searching }
- function PeDoesExportFunction(const FileName: TFileName; const FunctionName: string;
- Options: TJclSmartCompOptions = []): Boolean;
- function PeIsExportFunctionForwardedEx(const FileName: TFileName; const FunctionName: string;
- out ForwardedName: string; Options: TJclSmartCompOptions = []): Boolean;
- function PeIsExportFunctionForwarded(const FileName: TFileName; const FunctionName: string;
- Options: TJclSmartCompOptions = []): Boolean;
- { Imports searching }
- function PeDoesImportFunction(const FileName: TFileName; const FunctionName: string;
- const LibraryName: string = ''; Options: TJclSmartCompOptions = []): Boolean;
- function PeDoesImportLibrary(const FileName: TFileName; const LibraryName: string;
- Recursive: Boolean = False): Boolean;
- { Imports listing }
- function PeImportedLibraries(const FileName: TFileName; const LibrariesList: TStrings;
- Recursive: Boolean = False; FullPathName: Boolean = False): Boolean;
- function PeImportedFunctions(const FileName: TFileName; const FunctionsList: TStrings;
- const LibraryName: string = ''; IncludeLibNames: Boolean = False): Boolean;
- { Exports listing }
- function PeExportedFunctions(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
- function PeExportedNames(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
- function PeExportedVariables(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
- { Resources listing }
- function PeResourceKindNames(const FileName: TFileName; ResourceType: TJclPeResourceKind;
- const NamesList: TStrings): Boolean;
- { Borland packages specific }
- {$IFDEF BORLAND}
- function PeBorFormNames(const FileName: TFileName; const NamesList: TStrings): Boolean;
- function PeBorDependedPackages(const FileName: TFileName; PackagesList: TStrings;
- FullPathName, Descriptions: Boolean): Boolean;
- {$ENDIF BORLAND}
- // Missing imports checking routines
- function PeFindMissingImports(const FileName: TFileName; MissingImportsList: TStrings): Boolean; overload;
- function PeFindMissingImports(RequiredImportsList, MissingImportsList: TStrings): Boolean; overload;
- function PeCreateRequiredImportList(const FileName: TFileName; RequiredImportsList: TStrings): Boolean;
- // Mapped or loaded image related routines
- // use PeMapImgNtHeaders32
- // function PeMapImgNtHeaders(const BaseAddress: Pointer): PImageNtHeaders;
- function PeMapImgNtHeaders32(const BaseAddress: Pointer): PImageNtHeaders32; overload;
- function PeMapImgNtHeaders32(Stream: TStream; const BasePosition: Int64; out NtHeaders32: TImageNtHeaders32): Int64; overload;
- function PeMapImgNtHeaders64(const BaseAddress: Pointer): PImageNtHeaders64; overload;
- function PeMapImgNtHeaders64(Stream: TStream; const BasePosition: Int64; out NtHeaders64: TImageNtHeaders64): Int64; overload;
- function PeMapImgLibraryName(const BaseAddress: Pointer): string;
- function PeMapImgLibraryName32(const BaseAddress: Pointer): string;
- function PeMapImgLibraryName64(const BaseAddress: Pointer): string;
- function PeMapImgSize(const BaseAddress: Pointer): DWORD; overload;
- function PeMapImgSize(Stream: TStream; const BasePosition: Int64): DWORD; overload;
- function PeMapImgSize32(const BaseAddress: Pointer): DWORD; overload;
- function PeMapImgSize32(Stream: TStream; const BasePosition: Int64): DWORD; overload;
- function PeMapImgSize64(const BaseAddress: Pointer): DWORD; overload;
- function PeMapImgSize64(Stream: TStream; const BasePosition: Int64): DWORD; overload;
- function PeMapImgTarget(const BaseAddress: Pointer): TJclPeTarget; overload;
- function PeMapImgTarget(Stream: TStream; const BasePosition: Int64): TJclPeTarget; overload;
- type
- TImageSectionHeaderArray = array of TImageSectionHeader;
- // use PeMapImgSections32
- // function PeMapImgSections(NtHeaders: PImageNtHeaders): PImageSectionHeader;
- function PeMapImgSections32(NtHeaders: PImageNtHeaders32): PImageSectionHeader; overload;
- function PeMapImgSections32(Stream: TStream; const NtHeaders32Position: Int64; const NtHeaders32: TImageNtHeaders32;
- out ImageSectionHeaders: TImageSectionHeaderArray): Int64; overload;
- function PeMapImgSections64(NtHeaders: PImageNtHeaders64): PImageSectionHeader; overload;
- function PeMapImgSections64(Stream: TStream; const NtHeaders64Position: Int64; const NtHeaders64: TImageNtHeaders64;
- out ImageSectionHeaders: TImageSectionHeaderArray): Int64; overload;
- // use PeMapImgFindSection32
- // function PeMapImgFindSection(NtHeaders: PImageNtHeaders;
- // const SectionName: string): PImageSectionHeader;
- function PeMapImgFindSection32(NtHeaders: PImageNtHeaders32;
- const SectionName: string): PImageSectionHeader;
- function PeMapImgFindSection64(NtHeaders: PImageNtHeaders64;
- const SectionName: string): PImageSectionHeader;
- function PeMapImgFindSection(const ImageSectionHeaders: TImageSectionHeaderArray;
- const SectionName: string): SizeInt;
- function PeMapImgFindSectionFromModule(const BaseAddress: Pointer;
- const SectionName: string): PImageSectionHeader;
- function PeMapImgExportedVariables(const Module: HMODULE; const VariablesList: TStrings): Boolean;
- function PeMapImgResolvePackageThunk(Address: Pointer): Pointer;
- function PeMapFindResource(const Module: HMODULE; const ResourceType: PChar;
- const ResourceName: string): Pointer;
- type
- TJclPeSectionStream = class(TCustomMemoryStream)
- private
- FInstance: HMODULE;
- FSectionHeader: TImageSectionHeader;
- procedure Initialize(Instance: HMODULE; const ASectionName: string);
- public
- constructor Create(Instance: HMODULE; const ASectionName: string);
- function Write(const Buffer; Count: Longint): Longint; override;
- property Instance: HMODULE read FInstance;
- property SectionHeader: TImageSectionHeader read FSectionHeader;
- end;
- // API hooking classes
- type
- TJclPeMapImgHookItem = class(TObject)
- private
- FBaseAddress: Pointer;
- FFunctionName: string;
- FModuleName: string;
- FNewAddress: Pointer;
- FOriginalAddress: Pointer;
- FList: TObjectList;
- protected
- function InternalUnhook: Boolean;
- public
- constructor Create(AList: TObjectList; const AFunctionName: string;
- const AModuleName: string; ABaseAddress, ANewAddress, AOriginalAddress: Pointer);
- destructor Destroy; override;
- function Unhook: Boolean;
- property BaseAddress: Pointer read FBaseAddress;
- property FunctionName: string read FFunctionName;
- property ModuleName: string read FModuleName;
- property NewAddress: Pointer read FNewAddress;
- property OriginalAddress: Pointer read FOriginalAddress;
- end;
- TJclPeMapImgHooks = class(TObjectList)
- private
- function GetItems(Index: Integer): TJclPeMapImgHookItem;
- function GetItemFromOriginalAddress(OriginalAddress: Pointer): TJclPeMapImgHookItem;
- function GetItemFromNewAddress(NewAddress: Pointer): TJclPeMapImgHookItem;
- public
- function HookImport(Base: Pointer; const ModuleName: string;
- const FunctionName: string; NewAddress: Pointer; var OriginalAddress: Pointer): Boolean;
- class function IsWin9xDebugThunk(P: Pointer): Boolean;
- class function ReplaceImport(Base: Pointer; const ModuleName: string; FromProc, ToProc: Pointer): Boolean;
- class function SystemBase: Pointer;
- procedure UnhookAll;
- function UnhookByNewAddress(NewAddress: Pointer): Boolean;
- procedure UnhookByBaseAddress(BaseAddress: Pointer);
- property Items[Index: Integer]: TJclPeMapImgHookItem read GetItems; default;
- property ItemFromOriginalAddress[OriginalAddress: Pointer]: TJclPeMapImgHookItem read GetItemFromOriginalAddress;
- property ItemFromNewAddress[NewAddress: Pointer]: TJclPeMapImgHookItem read GetItemFromNewAddress;
- end;
- // Image access under a debbuger
- function PeDbgImgNtHeaders32(ProcessHandle: THandle; BaseAddress: TJclAddr32;
- var NtHeaders: TImageNtHeaders32): Boolean;
- // TODO 64 bit version
- //function PeDbgImgNtHeaders64(ProcessHandle: THandle; BaseAddress: TJclAddr64;
- // var NtHeaders: TImageNtHeaders64): Boolean;
- function PeDbgImgLibraryName32(ProcessHandle: THandle; BaseAddress: TJclAddr32;
- var Name: string): Boolean;
- //function PeDbgImgLibraryName64(ProcessHandle: THandle; BaseAddress: TJclAddr64;
- // var Name: string): Boolean;
- // Borland BPL packages name unmangling
- type
- TJclBorUmSymbolKind = (skData, skFunction, skConstructor, skDestructor, skRTTI, skVTable);
- TJclBorUmSymbolModifier = (smQualified, smLinkProc);
- TJclBorUmSymbolModifiers = set of TJclBorUmSymbolModifier;
- TJclBorUmDescription = record
- Kind: TJclBorUmSymbolKind;
- Modifiers: TJclBorUmSymbolModifiers;
- end;
- TJclBorUmResult = (urOk, urNotMangled, urMicrosoft, urError);
- TJclPeUmResult = (umNotMangled, umBorland, umMicrosoft);
- function PeBorUnmangleName(const Name: string; out Unmangled: string;
- out Description: TJclBorUmDescription; out BasePos: Integer): TJclBorUmResult; overload;
- function PeBorUnmangleName(const Name: string; out Unmangled: string;
- out Description: TJclBorUmDescription): TJclBorUmResult; overload;
- function PeBorUnmangleName(const Name: string; out Unmangled: string): TJclBorUmResult; overload;
- function PeBorUnmangleName(const Name: string): string; overload;
- function PeIsNameMangled(const Name: string): TJclPeUmResult;
- function UndecorateSymbolName(const DecoratedName: string; out UnMangled: string; Flags: DWORD): Boolean;
- function PeUnmangleName(const Name: string; out Unmangled: string): TJclPeUmResult;
- {$IFDEF UNITVERSIONING}
- const
- UnitVersioning: TUnitVersionInfo = (
- RCSfile: '$URL$';
- Revision: '$Revision$';
- Date: '$Date$';
- LogPath: 'JCL\source\windows';
- Extra: '';
- Data: nil
- );
- {$ENDIF UNITVERSIONING}
- implementation
- uses
- {$IFDEF HAS_UNITSCOPE}
- System.RTLConsts,
- System.Types, // for inlining TList.Remove
- {$IFDEF HAS_UNIT_CHARACTER}
- System.Character,
- {$ENDIF HAS_UNIT_CHARACTER}
- {$ELSE ~HAS_UNITSCOPE}
- RTLConsts,
- {$IFDEF HAS_UNIT_CHARACTER}
- Character,
- {$ENDIF HAS_UNIT_CHARACTER}
- {$ENDIF ~HAS_UNITSCOPE}
- {$IFNDEF WINSCP}JclLogic,{$ELSE}Math, System.AnsiStrings, {$ENDIF ~WINSCP} JclResources, JclSysUtils, JclAnsiStrings, JclStrings{$IFNDEF WINSCP}, JclStringConversions{$ENDIF ~WINSCP}, JclTD32;
- const
- MANIFESTExtension = '.manifest';
- DebugSectionName = '.debug';
- ReadOnlySectionName = '.rdata';
- BinaryExtensionLibrary = '.dll';
- {$IFDEF BORLAND}
- CompilerExtensionDCP = '.dcp';
- BinaryExtensionPackage = '.bpl';
- PackageInfoResName = 'PACKAGEINFO';
- DescriptionResName = 'DESCRIPTION';
- PackageOptionsResName = 'PACKAGEOPTIONS';
- DVclAlResName = 'DVCLAL';
- {$ENDIF BORLAND}
- {$IFDEF WINSCP}
- // Stubs for JclStringConversions functions
- function TryUTF8ToString(const S: TUTF8String; out D: string): Boolean;
- begin
- Result := False;
- end;
- function TryStringToUTF8(const S: string; out D: TUTF8String): Boolean;
- begin
- Result := False;
- end;
- // stub for JclDateTime constant
- const
- UnixTimeStart = UnixDateDelta;
- {$ENDIF}
- // Helper routines
- function AddFlagTextRes(var Text: string; const FlagText: PResStringRec; const Value, Mask: Cardinal): Boolean;
- begin
- Result := (Value and Mask <> 0);
- if Result then
- begin
- if Length(Text) > 0 then
- Text := Text + ', ';
- Text := Text + LoadResString(FlagText);
- end;
- end;
- function CompareResourceName(T1, T2: PChar): Boolean;
- var
- Long1, Long2: LongRec;
- begin
- {$IFDEF CPU64}
- Long1 := LongRec(Int64Rec(T1).Lo);
- Long2 := LongRec(Int64Rec(T2).Lo);
- if (Int64Rec(T1).Hi = 0) and (Int64Rec(T2).Hi = 0) and (Long1.Hi = 0) and (Long2.Hi = 0) then
- {$ENDIF CPU64}
- {$IFDEF CPU32}
- Long1 := LongRec(T1);
- Long2 := LongRec(T2);
- if (Long1.Hi = 0) or (Long2.Hi = 0) then
- {$ENDIF CPU32}
- Result := Long1.Lo = Long2.Lo
- else
- Result := (StrIComp(T1, T2) = 0);
- end;
- function CreatePeImage(const FileName: TFileName): TJclPeImage;
- begin
- Result := TJclPeImage.Create(True);
- Result.FileName := FileName;
- end;
- function InternalImportedLibraries(const FileName: TFileName;
- Recursive, FullPathName: Boolean; ExternalCache: TJclPeImagesCache): TStringList;
- var
- Cache: TJclPeImagesCache;
- procedure ProcessLibraries(const AFileName: TFileName);
- var
- I: Integer;
- S: TFileName;
- ImportLib: TJclPeImportLibItem;
- begin
- with Cache[AFileName].ImportList do
- for I := 0 to Count - 1 do
- begin
- ImportLib := Items[I];
- if FullPathName then
- S := ImportLib.FileName
- else
- S := TFileName(ImportLib.Name);
- if Result.IndexOf(S) = -1 then
- begin
- Result.Add(S);
- if Recursive then
- ProcessLibraries(ImportLib.FileName);
- end;
- end;
- end;
- begin
- if ExternalCache = nil then
- Cache := TJclPeImagesCache.Create
- else
- Cache := ExternalCache;
- try
- Result := TStringList.Create;
- try
- Result.Sorted := True;
- Result.Duplicates := dupIgnore;
- ProcessLibraries(FileName);
- except
- FreeAndNil(Result);
- raise;
- end;
- finally
- if ExternalCache = nil then
- Cache.Free;
- end;
- end;
- // Smart name compare function
- function PeStripFunctionAW(const FunctionName: string): string;
- var
- L: Integer;
- begin
- Result := FunctionName;
- L := Length(Result);
- if (L > 1) then
- case Result[L] of
- 'A', 'W':
- if CharIsValidIdentifierLetter(Result[L - 1]) then
- Delete(Result, L, 1);
- end;
- end;
- function PeSmartFunctionNameSame(const ComparedName, FunctionName: string;
- Options: TJclSmartCompOptions): Boolean;
- var
- S: string;
- begin
- if scIgnoreCase in Options then
- Result := CompareText(FunctionName, ComparedName) = 0
- else
- Result := (FunctionName = ComparedName);
- if (not Result) and not (scSimpleCompare in Options) then
- begin
- if Length(FunctionName) > 0 then
- begin
- S := PeStripFunctionAW(FunctionName);
- if scIgnoreCase in Options then
- Result := CompareText(S, ComparedName) = 0
- else
- Result := (S = ComparedName);
- end
- else
- Result := False;
- end;
- end;
- //=== { TJclPeImagesCache } ==================================================
- constructor TJclPeImagesCache.Create;
- begin
- inherited Create;
- FList := TStringList.Create;
- FList.Sorted := True;
- FList.Duplicates := dupIgnore;
- end;
- destructor TJclPeImagesCache.Destroy;
- begin
- Clear;
- FreeAndNil(FList);
- inherited Destroy;
- end;
- procedure TJclPeImagesCache.Clear;
- var
- I: Integer;
- begin
- with FList do
- for I := 0 to Count - 1 do
- Objects[I].Free;
- FList.Clear;
- end;
- function TJclPeImagesCache.GetCount: Integer;
- begin
- Result := FList.Count;
- end;
- function TJclPeImagesCache.GetImages(const FileName: TFileName): TJclPeImage;
- var
- I: Integer;
- begin
- I := FList.IndexOf(FileName);
- if I = -1 then
- begin
- Result := GetPeImageClass.Create(True);
- Result.FileName := FileName;
- FList.AddObject(FileName, Result);
- end
- else
- Result := TJclPeImage(FList.Objects[I]);
- end;
- function TJclPeImagesCache.GetPeImageClass: TJclPeImageClass;
- begin
- Result := TJclPeImage;
- end;
- //=== { TJclPeImageBaseList } ================================================
- constructor TJclPeImageBaseList.Create(AImage: TJclPeImage);
- begin
- inherited Create(True);
- FImage := AImage;
- end;
- // Import sort functions
- function ImportSortByName(Item1, Item2: Pointer): Integer;
- begin
- Result := CompareStr(TJclPeImportFuncItem(Item1).Name, TJclPeImportFuncItem(Item2).Name);
- if Result = 0 then
- Result := CompareStr(TJclPeImportFuncItem(Item1).ImportLib.Name, TJclPeImportFuncItem(Item2).ImportLib.Name);
- if Result = 0 then
- Result := TJclPeImportFuncItem(Item1).Ordinal - TJclPeImportFuncItem(Item2).Ordinal;
- end;
- function ImportSortByNameDESC(Item1, Item2: Pointer): Integer;
- begin
- Result := ImportSortByName(Item2, Item1);
- end;
- function ImportSortByHint(Item1, Item2: Pointer): Integer;
- begin
- Result := TJclPeImportFuncItem(Item1).Hint - TJclPeImportFuncItem(Item2).Hint;
- end;
- function ImportSortByHintDESC(Item1, Item2: Pointer): Integer;
- begin
- Result := ImportSortByHint(Item2, Item1);
- end;
- function ImportSortByDll(Item1, Item2: Pointer): Integer;
- begin
- Result := CompareStr(TJclPeImportFuncItem(Item1).ImportLib.Name,
- TJclPeImportFuncItem(Item2).ImportLib.Name);
- if Result = 0 then
- Result := ImportSortByName(Item1, Item2);
- end;
- function ImportSortByDllDESC(Item1, Item2: Pointer): Integer;
- begin
- Result := ImportSortByDll(Item2, Item1);
- end;
- function ImportSortByOrdinal(Item1, Item2: Pointer): Integer;
- begin
- Result := CompareStr(TJclPeImportFuncItem(Item1).ImportLib.Name,
- TJclPeImportFuncItem(Item2).ImportLib.Name);
- if Result = 0 then
- Result := TJclPeImportFuncItem(Item1).Ordinal - TJclPeImportFuncItem(Item2).Ordinal;
- end;
- function ImportSortByOrdinalDESC(Item1, Item2: Pointer): Integer;
- begin
- Result := ImportSortByOrdinal(Item2, Item1);
- end;
- function GetImportSortFunction(SortType: TJclPeImportSort; Descending: Boolean): TListSortCompare;
- const
- SortFunctions: array [TJclPeImportSort, Boolean] of TListSortCompare =
- ((ImportSortByName, ImportSortByNameDESC),
- (ImportSortByOrdinal, ImportSortByOrdinalDESC),
- (ImportSortByHint, ImportSortByHintDESC),
- (ImportSortByDll, ImportSortByDllDESC)
- );
- begin
- Result := SortFunctions[SortType, Descending];
- end;
- function ImportLibSortByIndex(Item1, Item2: Pointer): Integer;
- begin
- Result := TJclPeImportLibItem(Item1).ImportDirectoryIndex -
- TJclPeImportLibItem(Item2).ImportDirectoryIndex;
- end;
- function ImportLibSortByName(Item1, Item2: Pointer): Integer;
- begin
- Result := AnsiCompareStr(TJclPeImportLibItem(Item1).Name, TJclPeImportLibItem(Item2).Name);
- if Result = 0 then
- Result := ImportLibSortByIndex(Item1, Item2);
- end;
- function GetImportLibSortFunction(SortType: TJclPeImportLibSort): TListSortCompare;
- const
- SortFunctions: array [TJclPeImportLibSort] of TListSortCompare =
- (ImportLibSortByName, ImportLibSortByIndex);
- begin
- Result := SortFunctions[SortType];
- end;
- //=== { TJclPeImportFuncItem } ===============================================
- constructor TJclPeImportFuncItem.Create(AImportLib: TJclPeImportLibItem;
- AOrdinal: Word; AHint: Word; const AName: string);
- begin
- inherited Create;
- FImportLib := AImportLib;
- FOrdinal := AOrdinal;
- FHint := AHint;
- FName := AName;
- FResolveCheck := icNotChecked;
- FIndirectImportName := False;
- end;
- function TJclPeImportFuncItem.GetIsByOrdinal: Boolean;
- begin
- Result := FOrdinal <> 0;
- end;
- procedure TJclPeImportFuncItem.SetIndirectImportName(const Value: string);
- begin
- FName := Value;
- FIndirectImportName := True;
- end;
- procedure TJclPeImportFuncItem.SetName(const Value: string);
- begin
- FName := Value;
- FIndirectImportName := False;
- end;
- procedure TJclPeImportFuncItem.SetResolveCheck(Value: TJclPeResolveCheck);
- begin
- FResolveCheck := Value;
- end;
- //=== { TJclPeImportLibItem } ================================================
- constructor TJclPeImportLibItem.Create(AImage: TJclPeImage;
- AImportDescriptor: Pointer; AImportKind: TJclPeImportKind; const AName: string;
- AThunk: Pointer; AUseRVA: Boolean = True);
- begin
- inherited Create(AImage);
- FTotalResolveCheck := icNotChecked;
- FImportDescriptor := AImportDescriptor;
- FImportKind := AImportKind;
- FName := AName;
- FThunk := AThunk;
- FThunkData := AThunk;
- FUseRVA := AUseRVA;
- end;
- procedure TJclPeImportLibItem.CheckImports(ExportImage: TJclPeImage);
- var
- I: Integer;
- ExportList: TJclPeExportFuncList;
- begin
- if ExportImage.StatusOK then
- begin
- FTotalResolveCheck := icResolved;
- ExportList := ExportImage.ExportList;
- for I := 0 to Count - 1 do
- begin
- with Items[I] do
- if IsByOrdinal then
- begin
- if ExportList.OrdinalValid(Ordinal) then
- SetResolveCheck(icResolved)
- else
- begin
- SetResolveCheck(icUnresolved);
- Self.FTotalResolveCheck := icUnresolved;
- end;
- end
- else
- begin
- if ExportList.ItemFromName[Items[I].Name] <> nil then
- SetResolveCheck(icResolved)
- else
- begin
- SetResolveCheck(icUnresolved);
- Self.FTotalResolveCheck := icUnresolved;
- end;
- end;
- end;
- end
- else
- begin
- FTotalResolveCheck := icUnresolved;
- for I := 0 to Count - 1 do
- Items[I].SetResolveCheck(icUnresolved);
- end;
- end;
- procedure TJclPeImportLibItem.CreateList;
- procedure CreateList32;
- var
- Thunk32: PImageThunkData32;
- OrdinalName: PImageImportByName;
- Ordinal, Hint: Word;
- Name: PAnsiChar;
- ImportName: string;
- AddressOfData: DWORD;
- begin
- Thunk32 := PImageThunkData32(FThunk);
- while Thunk32^.Function_ <> 0 do
- begin
- Ordinal := 0;
- Hint := 0;
- Name := nil;
- if Thunk32^.Ordinal and IMAGE_ORDINAL_FLAG32 = 0 then
- begin
- case ImportKind of
- ikImport, ikBoundImport:
- begin
- OrdinalName := PImageImportByName(Image.RvaToVa(Thunk32^.AddressOfData));
- if OrdinalName <> nil then
- begin
- Hint := OrdinalName.Hint;
- Name := OrdinalName.Name;
- end;
- end;
- ikDelayImport:
- begin
- AddressOfData := Thunk32^.AddressOfData;
- if not FUseRVA then
- AddressOfData := Image.ImageAddressToRva(AddressOfData);
- OrdinalName := PImageImportByName(Image.RvaToVa(AddressOfData));
- if OrdinalName <> nil then
- begin
- Hint := OrdinalName.Hint;
- Name := OrdinalName.Name;
- end;
- end;
- end;
- end
- else
- Ordinal := IMAGE_ORDINAL32(Thunk32^.Ordinal);
- if (Ordinal <> 0) or (Hint <> 0) or (Name <> nil) then
- begin
- if not TryUTF8ToString(Name, ImportName) then
- ImportName := string(Name);
- Add(TJclPeImportFuncItem.Create(Self, Ordinal, Hint, ImportName));
- end;
- Inc(Thunk32);
- end;
- end;
- procedure CreateList64;
- var
- Thunk64: PImageThunkData64;
- OrdinalName: PImageImportByName;
- Ordinal, Hint: Word;
- Name: PAnsiChar;
- ImportName: string;
- begin
- Thunk64 := PImageThunkData64(FThunk);
- while Thunk64^.Function_ <> 0 do
- begin
- Ordinal := 0;
- Hint := 0;
- Name := nil;
- if Thunk64^.Ordinal and IMAGE_ORDINAL_FLAG64 = 0 then
- begin
- case ImportKind of
- ikImport, ikBoundImport:
- begin
- OrdinalName := PImageImportByName(Image.RvaToVa(Thunk64^.AddressOfData));
- if OrdinalName <> nil then
- begin
- Hint := OrdinalName.Hint;
- Name := OrdinalName.Name;
- end;
- end;
- ikDelayImport:
- begin
- OrdinalName := PImageImportByName(Image.RvaToVa(Thunk64^.AddressOfData));
- if OrdinalName <> nil then
- begin
- Hint := OrdinalName.Hint;
- Name := OrdinalName.Name;
- end;
- end;
- end;
- end
- else
- Ordinal := IMAGE_ORDINAL64(Thunk64^.Ordinal);
- if (Ordinal <> 0) or (Hint <> 0) or (Name <> nil) then
- begin
- if not TryUTF8ToString(Name, ImportName) then
- ImportName := string(Name);
- Add(TJclPeImportFuncItem.Create(Self, Ordinal, Hint, ImportName));
- end;
- Inc(Thunk64);
- end;
- end;
- begin
- if FThunk = nil then
- Exit;
- case Image.Target of
- taWin32:
- CreateList32;
- taWin64:
- CreateList64;
- end;
- FThunk := nil;
- end;
- function TJclPeImportLibItem.GetCount: Integer;
- begin
- if FThunk <> nil then
- CreateList;
- Result := inherited Count;
- end;
- function TJclPeImportLibItem.GetFileName: TFileName;
- begin
- Result := Image.ExpandModuleName(Name);
- end;
- function TJclPeImportLibItem.GetItems(Index: Integer): TJclPeImportFuncItem;
- begin
- Result := TJclPeImportFuncItem(Get(Index));
- end;
- function TJclPeImportLibItem.GetName: string;
- begin
- Result := AnsiLowerCase(OriginalName);
- end;
- function TJclPeImportLibItem.GetThunkData32: PImageThunkData32;
- begin
- if Image.Target = taWin32 then
- Result := FThunkData
- else
- Result := nil;
- end;
- function TJclPeImportLibItem.GetThunkData64: PImageThunkData64;
- begin
- if Image.Target = taWin64 then
- Result := FThunkData
- else
- Result := nil;
- end;
- procedure TJclPeImportLibItem.SetImportDirectoryIndex(Value: Integer);
- begin
- FImportDirectoryIndex := Value;
- end;
- procedure TJclPeImportLibItem.SetImportKind(Value: TJclPeImportKind);
- begin
- FImportKind := Value;
- end;
- procedure TJclPeImportLibItem.SetSorted(Value: Boolean);
- begin
- FSorted := Value;
- end;
- procedure TJclPeImportLibItem.SetThunk(Value: Pointer);
- begin
- FThunk := Value;
- FThunkData := Value;
- end;
- procedure TJclPeImportLibItem.SortList(SortType: TJclPeImportSort; Descending: Boolean);
- begin
- if not FSorted or (SortType <> FLastSortType) or (Descending <> FLastSortDescending) then
- begin
- GetCount; // create list if it wasn't created
- Sort(GetImportSortFunction(SortType, Descending));
- FLastSortType := SortType;
- FLastSortDescending := Descending;
- FSorted := True;
- end;
- end;
- //=== { TJclPeImportList } ===================================================
- constructor TJclPeImportList.Create(AImage: TJclPeImage);
- begin
- inherited Create(AImage);
- FAllItemsList := TList.Create;
- FAllItemsList.Capacity := 256;
- FUniqueNamesList := TStringList.Create;
- FUniqueNamesList.Sorted := True;
- FUniqueNamesList.Duplicates := dupIgnore;
- FLastAllSortType := isName;
- FLastAllSortDescending := False;
- CreateList;
- end;
- destructor TJclPeImportList.Destroy;
- var
- I: Integer;
- begin
- FreeAndNil(FAllItemsList);
- FreeAndNil(FUniqueNamesList);
- for I := 0 to Length(FparallelImportTable) - 1 do
- FreeMem(FparallelImportTable[I]);
- inherited Destroy;
- end;
- procedure TJclPeImportList.CheckImports(PeImageCache: TJclPeImagesCache);
- var
- I: Integer;
- ExportPeImage: TJclPeImage;
- begin
- Image.CheckNotAttached;
- if PeImageCache <> nil then
- ExportPeImage := nil // to make the compiler happy
- else
- ExportPeImage := TJclPeImage.Create(True);
- try
- for I := 0 to Count - 1 do
- if Items[I].TotalResolveCheck = icNotChecked then
- begin
- if PeImageCache <> nil then
- ExportPeImage := PeImageCache[Items[I].FileName]
- else
- ExportPeImage.FileName := Items[I].FileName;
- ExportPeImage.ExportList.PrepareForFastNameSearch;
- Items[I].CheckImports(ExportPeImage);
- end;
- finally
- if PeImageCache = nil then
- ExportPeImage.Free;
- end;
- end;
- procedure TJclPeImportList.CreateList;
- procedure CreateDelayImportList32(DelayImportDesc: PImgDelayDescrV1);
- const
- ATTRS_RVA = 1;
- var
- LibItem: TJclPeImportLibItem;
- UTF8Name: TUTF8String;
- LibName: string;
- P, Thunk: Pointer;
- UseRVA: Boolean;
- begin
- // 2010, XE use addresses whereas XE2 and newer use the RVA mode
- while DelayImportDesc^.szName <> nil do
- begin
- UseRVA := DelayImportDesc^.grAttrs and ATTRS_RVA <> 0;
- Thunk := DelayImportDesc^.pINT;
- P := DelayImportDesc^.szName;
- if not UseRVA then
- begin
- Thunk := Pointer(Image.ImageAddressToRva(DWORD(DelayImportDesc^.pINT)));
- P := Pointer(Image.ImageAddressToRva(DWORD(DelayImportDesc^.szName)));
- end;
- UTF8Name := PAnsiChar(Image.RvaToVa(DWORD(P)));
- if not TryUTF8ToString(UTF8Name, LibName) then
- LibName := string(UTF8Name);
- LibItem := TJclPeImportLibItem.Create(Image, DelayImportDesc, ikDelayImport,
- LibName, Image.RvaToVa(DWORD(Thunk)), UseRVA);
- Add(LibItem);
- FUniqueNamesList.AddObject(AnsiLowerCase(LibItem.Name), LibItem);
- Inc(DelayImportDesc);
- end;
- end;
- procedure CreateDelayImportList64(DelayImportDesc: PImgDelayDescrV2);
- var
- LibItem: TJclPeImportLibItem;
- UTF8Name: TUTF8String;
- LibName: string;
- begin
- // 64 bit always uses RVA mode
- while DelayImportDesc^.rvaDLLName <> 0 do
- begin
- UTF8Name := PAnsiChar(Image.RvaToVa(DelayImportDesc^.rvaDLLName));
- if not TryUTF8ToString(UTF8Name, LibName) then
- LibName := string(UTF8Name);
- LibItem := TJclPeImportLibItem.Create(Image, DelayImportDesc, ikDelayImport,
- LibName, Image.RvaToVa(DelayImportDesc^.rvaINT));
- Add(LibItem);
- FUniqueNamesList.AddObject(AnsiLowerCase(LibItem.Name), LibItem);
- Inc(DelayImportDesc);
- end;
- end;
- var
- ImportDesc: PImageImportDescriptor;
- LibItem: TJclPeImportLibItem;
- UTF8Name: TUTF8String;
- LibName, ModuleName: string;
- DelayImportDesc: Pointer;
- BoundImports, BoundImport: PImageBoundImportDescriptor;
- S: string;
- I: Integer;
- Thunk: Pointer;
- begin
- SetCapacity(100);
- with Image do
- begin
- if not StatusOK then
- Exit;
- ImportDesc := DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_IMPORT);
- if ImportDesc <> nil then
- while ImportDesc^.Name <> 0 do
- begin
- if ImportDesc^.Union.Characteristics = 0 then
- begin
- if AttachedImage then // Borland images doesn't have two parallel arrays
- Thunk := nil // see MakeBorlandImportTableForMappedImage method
- else
- Thunk := RvaToVa(ImportDesc^.FirstThunk);
- FLinkerProducer := lrBorland;
- end
- else
- begin
- Thunk := RvaToVa(ImportDesc^.Union.Characteristics);
- FLinkerProducer := lrMicrosoft;
- end;
- UTF8Name := PAnsiChar(RvaToVa(ImportDesc^.Name));
- if not TryUTF8ToString(UTF8Name, LibName) then
- LibName := string(UTF8Name);
- LibItem := TJclPeImportLibItem.Create(Image, ImportDesc, ikImport, LibName, Thunk);
- Add(LibItem);
- FUniqueNamesList.AddObject(AnsiLowerCase(LibItem.Name), LibItem);
- Inc(ImportDesc);
- end;
- DelayImportDesc := DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
- if DelayImportDesc <> nil then
- begin
- try
- case Target of
- taWin32:
- CreateDelayImportList32(DelayImportDesc);
- taWin64:
- CreateDelayImportList64(DelayImportDesc);
- end;
- except
- on E: EAccessViolation do // Mantis #6177. Some users seem to have module loaded that is broken
- ; // ignore
- end;
- end;
- BoundImports := DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT);
- if BoundImports <> nil then
- begin
- BoundImport := BoundImports;
- while BoundImport^.OffsetModuleName <> 0 do
- begin
- UTF8Name := PAnsiChar(TJclAddr(BoundImports) + BoundImport^.OffsetModuleName);
- if not TryUTF8ToString(UTF8Name, ModuleName) then
- ModuleName := string(UTF8Name);
- S := AnsiLowerCase(ModuleName);
- I := FUniqueNamesList.IndexOf(S);
- if I >= 0 then
- TJclPeImportLibItem(FUniqueNamesList.Objects[I]).SetImportKind(ikBoundImport);
- for I := 1 to BoundImport^.NumberOfModuleForwarderRefs do
- Inc(PImageBoundForwarderRef(BoundImport)); // skip forward information
- Inc(BoundImport);
- end;
- end;
- end;
- for I := 0 to Count - 1 do
- Items[I].SetImportDirectoryIndex(I);
- end;
- function TJclPeImportList.GetAllItemCount: Integer;
- begin
- Result := FAllItemsList.Count;
- if Result = 0 then // we haven't created the list yet -> create unsorted list
- begin
- RefreshAllItems;
- Result := FAllItemsList.Count;
- end;
- end;
- function TJclPeImportList.GetAllItems(Index: Integer): TJclPeImportFuncItem;
- begin
- Result := TJclPeImportFuncItem(FAllItemsList[Index]);
- end;
- function TJclPeImportList.GetItems(Index: Integer): TJclPeImportLibItem;
- begin
- Result := TJclPeImportLibItem(Get(Index));
- end;
- function TJclPeImportList.GetUniqueLibItemCount: Integer;
- begin
- Result := FUniqueNamesList.Count;
- end;
- function TJclPeImportList.GetUniqueLibItemFromName(const Name: string): TJclPeImportLibItem;
- var
- I: Integer;
- begin
- I := FUniqueNamesList.IndexOf(Name);
- if I = -1 then
- Result := nil
- else
- Result := TJclPeImportLibItem(FUniqueNamesList.Objects[I]);
- end;
- function TJclPeImportList.GetUniqueLibItems(Index: Integer): TJclPeImportLibItem;
- begin
- Result := TJclPeImportLibItem(FUniqueNamesList.Objects[Index]);
- end;
- function TJclPeImportList.GetUniqueLibNames(Index: Integer): string;
- begin
- Result := FUniqueNamesList[Index];
- end;
- function TJclPeImportList.MakeBorlandImportTableForMappedImage: Boolean;
- var
- FileImage: TJclPeImage;
- I, TableSize: Integer;
- begin
- if Image.AttachedImage and (LinkerProducer = lrBorland) and
- (Length(FParallelImportTable) = 0) then
- begin
- FileImage := TJclPeImage.Create(True);
- try
- FileImage.FileName := Image.FileName;
- Result := FileImage.StatusOK;
- if Result then
- begin
- SetLength(FParallelImportTable, FileImage.ImportList.Count);
- for I := 0 to FileImage.ImportList.Count - 1 do
- begin
- Assert(Items[I].ImportKind = ikImport); // Borland doesn't have Delay load or Bound imports
- TableSize := (FileImage.ImportList[I].Count + 1);
- case Image.Target of
- taWin32:
- begin
- TableSize := TableSize * SizeOf(TImageThunkData32);
- GetMem(FParallelImportTable[I], TableSize);
- System.Move(FileImage.ImportList[I].ThunkData32^, FParallelImportTable[I]^, TableSize);
- Items[I].SetThunk(FParallelImportTable[I]);
- end;
- taWin64:
- begin
- TableSize := TableSize * SizeOf(TImageThunkData64);
- GetMem(FParallelImportTable[I], TableSize);
- System.Move(FileImage.ImportList[I].ThunkData64^, FParallelImportTable[I]^, TableSize);
- Items[I].SetThunk(FParallelImportTable[I]);
- end;
- end;
- end;
- end;
- finally
- FileImage.Free;
- end;
- end
- else
- Result := True;
- end;
- procedure TJclPeImportList.RefreshAllItems;
- var
- L, I: Integer;
- LibItem: TJclPeImportLibItem;
- begin
- FAllItemsList.Clear;
- for L := 0 to Count - 1 do
- begin
- LibItem := Items[L];
- if (Length(FFilterModuleName) = 0) or (AnsiCompareText(LibItem.Name, FFilterModuleName) = 0) then
- for I := 0 to LibItem.Count - 1 do
- FAllItemsList.Add(LibItem[I]);
- end;
- end;
- procedure TJclPeImportList.SetFilterModuleName(const Value: string);
- begin
- if (FFilterModuleName <> Value) or (FAllItemsList.Count = 0) then
- begin
- FFilterModuleName := Value;
- RefreshAllItems;
- FAllItemsList.Sort(GetImportSortFunction(FLastAllSortType, FLastAllSortDescending));
- end;
- end;
- function TJclPeImportList.SmartFindName(const CompareName, LibName: string;
- Options: TJclSmartCompOptions): TJclPeImportFuncItem;
- var
- L, I: Integer;
- LibItem: TJclPeImportLibItem;
- begin
- Result := nil;
- for L := 0 to Count - 1 do
- begin
- LibItem := Items[L];
- if (Length(LibName) = 0) or (AnsiCompareText(LibItem.Name, LibName) = 0) then
- for I := 0 to LibItem.Count - 1 do
- if PeSmartFunctionNameSame(CompareName, LibItem[I].Name, Options) then
- begin
- Result := LibItem[I];
- Break;
- end;
- end;
- end;
- procedure TJclPeImportList.SortAllItemsList(SortType: TJclPeImportSort; Descending: Boolean);
- begin
- GetAllItemCount; // create list if it wasn't created
- FAllItemsList.Sort(GetImportSortFunction(SortType, Descending));
- FLastAllSortType := SortType;
- FLastAllSortDescending := Descending;
- end;
- procedure TJclPeImportList.SortList(SortType: TJclPeImportLibSort);
- begin
- Sort(GetImportLibSortFunction(SortType));
- end;
- procedure TJclPeImportList.TryGetNamesForOrdinalImports;
- var
- LibNamesList: TStringList;
- L, I: Integer;
- LibPeDump: TJclPeImage;
- procedure TryGetNames(const ModuleName: string);
- var
- Item: TJclPeImportFuncItem;
- I, L: Integer;
- ImportLibItem: TJclPeImportLibItem;
- ExportItem: TJclPeExportFuncItem;
- ExportList: TJclPeExportFuncList;
- begin
- if Image.AttachedImage then
- LibPeDump.AttachLoadedModule(GetModuleHandle(PChar(ModuleName)))
- else
- LibPeDump.FileName := Image.ExpandModuleName(ModuleName);
- if not LibPeDump.StatusOK then
- Exit;
- ExportList := LibPeDump.ExportList;
- for L := 0 to Count - 1 do
- begin
- ImportLibItem := Items[L];
- if AnsiCompareText(ImportLibItem.Name, ModuleName) = 0 then
- begin
- for I := 0 to ImportLibItem.Count - 1 do
- begin
- Item := ImportLibItem[I];
- if Item.IsByOrdinal then
- begin
- ExportItem := ExportList.ItemFromOrdinal[Item.Ordinal];
- if (ExportItem <> nil) and (ExportItem.Name <> '') then
- Item.SetIndirectImportName(ExportItem.Name);
- end;
- end;
- ImportLibItem.SetSorted(False);
- end;
- end;
- end;
- begin
- LibNamesList := TStringList.Create;
- try
- LibNamesList.Sorted := True;
- LibNamesList.Duplicates := dupIgnore;
- for L := 0 to Count - 1 do
- with Items[L] do
- for I := 0 to Count - 1 do
- if Items[I].IsByOrdinal then
- LibNamesList.Add(AnsiUpperCase(Name));
- LibPeDump := TJclPeImage.Create(True);
- try
- for I := 0 to LibNamesList.Count - 1 do
- TryGetNames(LibNamesList[I]);
- finally
- LibPeDump.Free;
- end;
- SortAllItemsList(FLastAllSortType, FLastAllSortDescending);
- finally
- LibNamesList.Free;
- end;
- end;
- //=== { TJclPeExportFuncItem } ===============================================
- constructor TJclPeExportFuncItem.Create(AExportList: TJclPeExportFuncList;
- const AName, AForwardedName: string; AAddress: DWORD; AHint: Word;
- AOrdinal: Word; AResolveCheck: TJclPeResolveCheck);
- var
- DotPos: Integer;
- begin
- inherited Create;
- FExportList := AExportList;
- FName := AName;
- FForwardedName := AForwardedName;
- FAddress := AAddress;
- FHint := AHint;
- FOrdinal := AOrdinal;
- FResolveCheck := AResolveCheck;
- DotPos := AnsiPos('.', ForwardedName);
- if DotPos > 0 then
- FForwardedDotPos := Copy(ForwardedName, DotPos + 1, Length(ForwardedName) - DotPos)
- else
- FForwardedDotPos := '';
- end;
- function TJclPeExportFuncItem.GetAddressOrForwardStr: string;
- begin
- if IsForwarded then
- Result := ForwardedName
- else
- FmtStr(Result, '%.8x', [Address]);
- end;
- function TJclPeExportFuncItem.GetForwardedFuncName: string;
- begin
- if (Length(FForwardedDotPos) > 0) and (FForwardedDotPos[1] <> '#') then
- Result := FForwardedDotPos
- else
- Result := '';
- end;
- function TJclPeExportFuncItem.GetForwardedFuncOrdinal: DWORD;
- begin
- if (Length(FForwardedDotPos) > 0) and (FForwardedDotPos[1] = '#') then
- Result := StrToIntDef(FForwardedDotPos, 0)
- else
- Result := 0;
- end;
- function TJclPeExportFuncItem.GetForwardedLibName: string;
- begin
- if Length(FForwardedDotPos) = 0 then
- Result := ''
- else
- Result := AnsiLowerCase(Copy(FForwardedName, 1, Length(FForwardedName) - Length(FForwardedDotPos) - 1)) + BinaryExtensionLibrary;
- end;
- function TJclPeExportFuncItem.GetIsExportedVariable: Boolean;
- begin
- case FExportList.Image.Target of
- taWin32:
- begin
- {$IFDEF DELPHI64_TEMPORARY}
- System.Error(rePlatformNotImplemented);//there is no BaseOfData in the 32-bit header for Win64
- Result := False;
- {$ELSE ~DELPHI64_TEMPORARY}
- Result := (Address >= FExportList.Image.OptionalHeader32.BaseOfData);
- {$ENDIF ~DELPHI64_TEMPORARY}
- end;
- taWin64:
- Result := False;
- // TODO equivalent for 64-bit modules
- //Result := (Address >= FExportList.Image.OptionalHeader64.BaseOfData);
- else
- Result := False;
- end;
- end;
- function TJclPeExportFuncItem.GetIsForwarded: Boolean;
- begin
- Result := Length(FForwardedName) <> 0;
- end;
- function TJclPeExportFuncItem.GetMappedAddress: Pointer;
- begin
- Result := FExportList.Image.RvaToVa(FAddress);
- end;
- function TJclPeExportFuncItem.GetSectionName: string;
- begin
- if IsForwarded then
- Result := ''
- else
- with FExportList.Image do
- Result := ImageSectionNameFromRva[Address];
- end;
- procedure TJclPeExportFuncItem.SetResolveCheck(Value: TJclPeResolveCheck);
- begin
- FResolveCheck := Value;
- end;
- // Export sort functions
- function ExportSortByName(Item1, Item2: Pointer): Integer;
- begin
- Result := CompareStr(TJclPeExportFuncItem(Item1).Name, TJclPeExportFuncItem(Item2).Name);
- end;
- function ExportSortByNameDESC(Item1, Item2: Pointer): Integer;
- begin
- Result := ExportSortByName(Item2, Item1);
- end;
- function ExportSortByOrdinal(Item1, Item2: Pointer): Integer;
- begin
- Result := TJclPeExportFuncItem(Item1).Ordinal - TJclPeExportFuncItem(Item2).Ordinal;
- end;
- function ExportSortByOrdinalDESC(Item1, Item2: Pointer): Integer;
- begin
- Result := ExportSortByOrdinal(Item2, Item1);
- end;
- function ExportSortByHint(Item1, Item2: Pointer): Integer;
- begin
- Result := TJclPeExportFuncItem(Item1).Hint - TJclPeExportFuncItem(Item2).Hint;
- end;
- function ExportSortByHintDESC(Item1, Item2: Pointer): Integer;
- begin
- Result := ExportSortByHint(Item2, Item1);
- end;
- function ExportSortByAddress(Item1, Item2: Pointer): Integer;
- begin
- Result := INT_PTR(TJclPeExportFuncItem(Item1).Address) - INT_PTR(TJclPeExportFuncItem(Item2).Address);
- if Result = 0 then
- Result := ExportSortByName(Item1, Item2);
- end;
- function ExportSortByAddressDESC(Item1, Item2: Pointer): Integer;
- begin
- Result := ExportSortByAddress(Item2, Item1);
- end;
- function ExportSortByForwarded(Item1, Item2: Pointer): Integer;
- begin
- Result := CompareStr(TJclPeExportFuncItem(Item1).ForwardedName, TJclPeExportFuncItem(Item2).ForwardedName);
- if Result = 0 then
- Result := ExportSortByName(Item1, Item2);
- end;
- function ExportSortByForwardedDESC(Item1, Item2: Pointer): Integer;
- begin
- Result := ExportSortByForwarded(Item2, Item1);
- end;
- function ExportSortByAddrOrFwd(Item1, Item2: Pointer): Integer;
- begin
- Result := CompareStr(TJclPeExportFuncItem(Item1).AddressOrForwardStr, TJclPeExportFuncItem(Item2).AddressOrForwardStr);
- end;
- function ExportSortByAddrOrFwdDESC(Item1, Item2: Pointer): Integer;
- begin
- Result := ExportSortByAddrOrFwd(Item2, Item1);
- end;
- function ExportSortBySection(Item1, Item2: Pointer): Integer;
- begin
- Result := CompareStr(TJclPeExportFuncItem(Item1).SectionName, TJclPeExportFuncItem(Item2).SectionName);
- if Result = 0 then
- Result := ExportSortByName(Item1, Item2);
- end;
- function ExportSortBySectionDESC(Item1, Item2: Pointer): Integer;
- begin
- Result := ExportSortBySection(Item2, Item1);
- end;
- //=== { TJclPeExportFuncList } ===============================================
- constructor TJclPeExportFuncList.Create(AImage: TJclPeImage);
- begin
- inherited Create(AImage);
- FTotalResolveCheck := icNotChecked;
- CreateList;
- end;
- destructor TJclPeExportFuncList.Destroy;
- begin
- FreeAndNil(FForwardedLibsList);
- inherited Destroy;
- end;
- function TJclPeExportFuncList.CanPerformFastNameSearch: Boolean;
- begin
- Result := FSorted and (FLastSortType = esName) and not FLastSortDescending;
- end;
- procedure TJclPeExportFuncList.CheckForwards(PeImageCache: TJclPeImagesCache);
- var
- I: Integer;
- FullFileName: TFileName;
- ForwardPeImage: TJclPeImage;
- ModuleResolveCheck: TJclPeResolveCheck;
- procedure PerformCheck(const ModuleName: string);
- var
- I: Integer;
- Item: TJclPeExportFuncItem;
- EL: TJclPeExportFuncList;
- begin
- EL := ForwardPeImage.ExportList;
- EL.PrepareForFastNameSearch;
- ModuleResolveCheck := icResolved;
- for I := 0 to Count - 1 do
- begin
- Item := Items[I];
- if (not Item.IsForwarded) or (Item.ResolveCheck <> icNotChecked) or
- (Item.ForwardedLibName <> ModuleName) then
- Continue;
- if EL.ItemFromName[Item.ForwardedFuncName] = nil then
- begin
- Item.SetResolveCheck(icUnresolved);
- ModuleResolveCheck := icUnresolved;
- end
- else
- Item.SetResolveCheck(icResolved);
- end;
- end;
- begin
- if not AnyForwards then
- Exit;
- FTotalResolveCheck := icResolved;
- if PeImageCache <> nil then
- ForwardPeImage := nil // to make the compiler happy
- else
- ForwardPeImage := TJclPeImage.Create(True);
- try
- for I := 0 to ForwardedLibsList.Count - 1 do
- begin
- FullFileName := Image.ExpandModuleName(ForwardedLibsList[I]);
- if PeImageCache <> nil then
- ForwardPeImage := PeImageCache[FullFileName]
- else
- ForwardPeImage.FileName := FullFileName;
- if ForwardPeImage.StatusOK then
- PerformCheck(ForwardedLibsList[I])
- else
- ModuleResolveCheck := icUnresolved;
- FForwardedLibsList.Objects[I] := Pointer(ModuleResolveCheck);
- if ModuleResolveCheck = icUnresolved then
- FTotalResolveCheck := icUnresolved;
- end;
- finally
- if PeImageCache = nil then
- ForwardPeImage.Free;
- end;
- end;
- procedure TJclPeExportFuncList.CreateList;
- var
- Functions: Pointer;
- Address, NameCount: DWORD;
- NameOrdinals: PWORD;
- Names: PDWORD;
- I: Integer;
- ExportItem: TJclPeExportFuncItem;
- ExportVABegin, ExportVAEnd: DWORD;
- UTF8Name: TUTF8String;
- ForwardedName, ExportName: string;
- begin
- with Image do
- begin
- if not StatusOK then
- Exit;
- with Directories[IMAGE_DIRECTORY_ENTRY_EXPORT] do
- begin
- ExportVABegin := VirtualAddress;
- ExportVAEnd := VirtualAddress + TJclAddr(Size);
- end;
- FExportDir := DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_EXPORT);
- if FExportDir <> nil then
- begin
- FBase := FExportDir^.Base;
- FFunctionCount := FExportDir^.NumberOfFunctions;
- Functions := RvaToVa(FExportDir^.AddressOfFunctions);
- NameOrdinals := RvaToVa(FExportDir^.AddressOfNameOrdinals);
- Names := RvaToVa(FExportDir^.AddressOfNames);
- NameCount := FExportDir^.NumberOfNames;
- Count := FExportDir^.NumberOfFunctions;
- for I := 0 to Count - 1 do
- begin
- Address := PDWORD(TJclAddr(Functions) + TJclAddr(I) * SizeOf(DWORD))^;
- if (Address >= ExportVABegin) and (Address <= ExportVAEnd) then
- begin
- FAnyForwards := True;
- UTF8Name := PAnsiChar(RvaToVa(Address));
- if not TryUTF8ToString(UTF8Name, ForwardedName) then
- ForwardedName := string(UTF8Name);
- end
- else
- ForwardedName := '';
- ExportItem := TJclPeExportFuncItem.Create(Self, '',
- ForwardedName, Address, $FFFF, TJclAddr(I) + FBase, icNotChecked);
- List{$IFNDEF RTL230_UP}^{$ENDIF !RTL230_UP}[I] := ExportItem;
- end;
- if NameCount > 0 then
- begin
- for I := 0 to NameCount - 1 do
- begin
- // named function
- UTF8Name := PAnsiChar(RvaToVa(Names^));
- if not TryUTF8ToString(UTF8Name, ExportName) then
- ExportName := string(UTF8Name);
- ExportItem := TJclPeExportFuncItem(List{$IFNDEF RTL230_UP}^{$ENDIF !RTL230_UP}[NameOrdinals^]);
- ExportItem.FName := ExportName;
- ExportItem.FHint := I;
- Inc(NameOrdinals);
- Inc(Names);
- end;
- end;
- end;
- end;
- end;
- function TJclPeExportFuncList.GetForwardedLibsList: TStrings;
- var
- I: Integer;
- begin
- if FForwardedLibsList = nil then
- begin
- FForwardedLibsList := TStringList.Create;
- FForwardedLibsList.Sorted := True;
- FForwardedLibsList.Duplicates := dupIgnore;
- if FAnyForwards then
- for I := 0 to Count - 1 do
- with Items[I] do
- if IsForwarded then
- FForwardedLibsList.AddObject(ForwardedLibName, Pointer(icNotChecked));
- end;
- Result := FForwardedLibsList;
- end;
- function TJclPeExportFuncList.GetItemFromAddress(Address: DWORD): TJclPeExportFuncItem;
- var
- I: Integer;
- begin
- Result := nil;
- for I := 0 to Count - 1 do
- if Items[I].Address = Address then
- begin
- Result := Items[I];
- Break;
- end;
- end;
- function TJclPeExportFuncList.GetItemFromName(const Name: string): TJclPeExportFuncItem;
- var
- L, H, I, C: Integer;
- B: Boolean;
- begin
- Result := nil;
- if CanPerformFastNameSearch then
- begin
- L := 0;
- H := Count - 1;
- B := False;
- while L <= H do
- begin
- I := (L + H) shr 1;
- C := CompareStr(Items[I].Name, Name);
- if C < 0 then
- L := I + 1
- else
- begin
- H := I - 1;
- if C = 0 then
- begin
- B := True;
- L := I;
- end;
- end;
- end;
- if B then
- Result := Items[L];
- end
- else
- for I := 0 to Count - 1 do
- if Items[I].Name = Name then
- begin
- Result := Items[I];
- Break;
- end;
- end;
- function TJclPeExportFuncList.GetItemFromOrdinal(Ordinal: DWORD): TJclPeExportFuncItem;
- var
- I: Integer;
- begin
- Result := nil;
- for I := 0 to Count - 1 do
- if Items[I].Ordinal = Ordinal then
- begin
- Result := Items[I];
- Break;
- end;
- end;
- function TJclPeExportFuncList.GetItems(Index: Integer): TJclPeExportFuncItem;
- begin
- Result := TJclPeExportFuncItem(Get(Index));
- end;
- function TJclPeExportFuncList.GetName: string;
- var
- UTF8ExportName: TUTF8String;
- begin
- if (FExportDir = nil) or (FExportDir^.Name = 0) then
- Result := ''
- else
- begin
- UTF8ExportName := PAnsiChar(Image.RvaToVa(FExportDir^.Name));
- if not TryUTF8ToString(UTF8ExportName, Result) then
- Result := string(UTF8ExportName);
- end;
- end;
- class function TJclPeExportFuncList.ItemName(Item: TJclPeExportFuncItem): string;
- begin
- if Item = nil then
- Result := ''
- else
- Result := Item.Name;
- end;
- function TJclPeExportFuncList.OrdinalValid(Ordinal: DWORD): Boolean;
- begin
- Result := (FExportDir <> nil) and (Ordinal >= Base) and
- (Ordinal < FunctionCount + Base);
- end;
- procedure TJclPeExportFuncList.PrepareForFastNameSearch;
- begin
- if not CanPerformFastNameSearch then
- SortList(esName, False);
- end;
- function TJclPeExportFuncList.SmartFindName(const CompareName: string;
- Options: TJclSmartCompOptions): TJclPeExportFuncItem;
- var
- I: Integer;
- begin
- Result := nil;
- for I := 0 to Count - 1 do
- begin
- if PeSmartFunctionNameSame(CompareName, Items[I].Name, Options) then
- begin
- Result := Items[I];
- Break;
- end;
- end;
- end;
- procedure TJclPeExportFuncList.SortList(SortType: TJclPeExportSort; Descending: Boolean);
- const
- SortFunctions: array [TJclPeExportSort, Boolean] of TListSortCompare =
- ((ExportSortByName, ExportSortByNameDESC),
- (ExportSortByOrdinal, ExportSortByOrdinalDESC),
- (ExportSortByHint, ExportSortByHintDESC),
- (ExportSortByAddress, ExportSortByAddressDESC),
- (ExportSortByForwarded, ExportSortByForwardedDESC),
- (ExportSortByAddrOrFwd, ExportSortByAddrOrFwdDESC),
- (ExportSortBySection, ExportSortBySectionDESC)
- );
- begin
- if not FSorted or (SortType <> FLastSortType) or (Descending <> FLastSortDescending) then
- begin
- Sort(SortFunctions[SortType, Descending]);
- FLastSortType := SortType;
- FLastSortDescending := Descending;
- FSorted := True;
- end;
- end;
- //=== { TJclPeResourceRawStream } ============================================
- constructor TJclPeResourceRawStream.Create(AResourceItem: TJclPeResourceItem);
- begin
- Assert(not AResourceItem.IsDirectory);
- inherited Create;
- SetPointer(AResourceItem.RawEntryData, AResourceItem.RawEntryDataSize);
- end;
- function TJclPeResourceRawStream.Write(const Buffer; Count: Integer): Longint;
- begin
- raise EJclPeImageError.CreateRes(@RsPeReadOnlyStream);
- end;
- //=== { TJclPeResourceItem } =================================================
- constructor TJclPeResourceItem.Create(AImage: TJclPeImage;
- AParentItem: TJclPeResourceItem; AEntry: PImageResourceDirectoryEntry);
- begin
- inherited Create;
- FImage := AImage;
- FEntry := AEntry;
- FParentItem := AParentItem;
- if AParentItem = nil then
- FLevel := 1
- else
- FLevel := AParentItem.Level + 1;
- end;
- destructor TJclPeResourceItem.Destroy;
- begin
- FreeAndNil(FList);
- inherited Destroy;
- end;
- function TJclPeResourceItem.CompareName(AName: PChar): Boolean;
- var
- P: PChar;
- begin
- if IsName then
- P := PChar(Name)
- else
- P := PChar(FEntry^.Name and $FFFF); // Integer encoded in a PChar
- Result := CompareResourceName(AName, P);
- end;
- function TJclPeResourceItem.GetDataEntry: PImageResourceDataEntry;
- begin
- if GetIsDirectory then
- Result := nil
- else
- Result := PImageResourceDataEntry(OffsetToRawData(FEntry^.OffsetToData));
- end;
- function TJclPeResourceItem.GetIsDirectory: Boolean;
- begin
- Result := FEntry^.OffsetToData and IMAGE_RESOURCE_DATA_IS_DIRECTORY <> 0;
- end;
- function TJclPeResourceItem.GetIsName: Boolean;
- begin
- Result := FEntry^.Name and IMAGE_RESOURCE_NAME_IS_STRING <> 0;
- end;
- function TJclPeResourceItem.GetLangID: LANGID;
- begin
- if IsDirectory then
- begin
- GetList;
- if FList.Count = 1 then
- Result := StrToIntDef(FList[0].Name, 0)
- else
- Result := 0;
- end
- else
- Result := StrToIntDef(Name, 0);
- end;
- function TJclPeResourceItem.GetList: TJclPeResourceList;
- begin
- if not IsDirectory then
- begin
- if Image.NoExceptions then
- begin
- Result := nil;
- Exit;
- end
- else
- raise EJclPeImageError.CreateRes(@RsPeNotResDir);
- end;
- if FList = nil then
- FList := FImage.ResourceListCreate(SubDirData, Self);
- Result := FList;
- end;
- function TJclPeResourceItem.GetName: string;
- begin
- if IsName then
- begin
- if FNameCache = '' then
- begin
- with PImageResourceDirStringU(OffsetToRawData(FEntry^.Name))^ do
- FNameCache := WideCharLenToString(NameString, Length);
- StrResetLength(FNameCache);
- end;
- Result := FNameCache;
- end
- else
- Result := IntToStr(FEntry^.Name and $FFFF);
- end;
- function TJclPeResourceItem.GetParameterName: string;
- begin
- if IsName then
- Result := Name
- else
- Result := Format('#%d', [FEntry^.Name and $FFFF]);
- end;
- function TJclPeResourceItem.GetRawEntryData: Pointer;
- begin
- if GetIsDirectory then
- Result := nil
- else
- Result := FImage.RvaToVa(GetDataEntry^.OffsetToData);
- end;
- function TJclPeResourceItem.GetRawEntryDataSize: Integer;
- begin
- if GetIsDirectory then
- Result := -1
- else
- Result := PImageResourceDataEntry(OffsetToRawData(FEntry^.OffsetToData))^.Size;
- end;
- function TJclPeResourceItem.GetResourceType: TJclPeResourceKind;
- begin
- with Level1Item do
- begin
- if FEntry^.Name < Cardinal(High(TJclPeResourceKind)) then
- Result := TJclPeResourceKind(FEntry^.Name)
- else
- Result := rtUserDefined
- end;
- end;
- function TJclPeResourceItem.GetResourceTypeStr: string;
- begin
- with Level1Item do
- begin
- if FEntry^.Name < Cardinal(High(TJclPeResourceKind)) then
- Result := Copy(GetEnumName(TypeInfo(TJclPeResourceKind), Ord(FEntry^.Name)), 3, 30)
- else
- Result := Name;
- end;
- end;
- function TJclPeResourceItem.Level1Item: TJclPeResourceItem;
- begin
- Result := Self;
- while Result.FParentItem <> nil do
- Result := Result.FParentItem;
- end;
- function TJclPeResourceItem.OffsetToRawData(Ofs: DWORD): TJclAddr;
- begin
- Result := (Ofs and $7FFFFFFF) + Image.ResourceVA;
- end;
- function TJclPeResourceItem.SubDirData: PImageResourceDirectory;
- begin
- Result := Pointer(OffsetToRawData(FEntry^.OffsetToData));
- end;
- //=== { TJclPeResourceList } =================================================
- constructor TJclPeResourceList.Create(AImage: TJclPeImage;
- AParentItem: TJclPeResourceItem; ADirectory: PImageResourceDirectory);
- begin
- inherited Create(AImage);
- FDirectory := ADirectory;
- FParentItem := AParentItem;
- CreateList(AParentItem);
- end;
- procedure TJclPeResourceList.CreateList(AParentItem: TJclPeResourceItem);
- var
- Entry: PImageResourceDirectoryEntry;
- DirItem: TJclPeResourceItem;
- I: Integer;
- begin
- if FDirectory = nil then
- Exit;
- Entry := Pointer(TJclAddr(FDirectory) + SizeOf(TImageResourceDirectory));
- for I := 1 to DWORD(FDirectory^.NumberOfNamedEntries) + DWORD(FDirectory^.NumberOfIdEntries) do
- begin
- DirItem := Image.ResourceItemCreate(Entry, AParentItem);
- Add(DirItem);
- Inc(Entry);
- end;
- end;
- function TJclPeResourceList.FindName(const Name: string): TJclPeResourceItem;
- var
- I: Integer;
- begin
- Result := nil;
- for I := 0 to Count - 1 do
- if StrSame(Items[I].Name, Name) then
- begin
- Result := Items[I];
- Break;
- end;
- end;
- function TJclPeResourceList.GetItems(Index: Integer): TJclPeResourceItem;
- begin
- Result := TJclPeResourceItem(Get(Index));
- end;
- //=== { TJclPeRootResourceList } =============================================
- destructor TJclPeRootResourceList.Destroy;
- begin
- FreeAndNil(FManifestContent);
- inherited Destroy;
- end;
- function TJclPeRootResourceList.FindResource(ResourceType: TJclPeResourceKind;
- const ResourceName: string): TJclPeResourceItem;
- var
- I: Integer;
- TypeItem: TJclPeResourceItem;
- begin
- Result := nil;
- TypeItem := nil;
- for I := 0 to Count - 1 do
- begin
- if Items[I].ResourceType = ResourceType then
- begin
- TypeItem := Items[I];
- Break;
- end;
- end;
- if TypeItem <> nil then
- if ResourceName = '' then
- Result := TypeItem
- else
- with TypeItem.List do
- for I := 0 to Count - 1 do
- if Items[I].Name = ResourceName then
- begin
- Result := Items[I];
- Break;
- end;
- end;
- function TJclPeRootResourceList.FindResource(const ResourceType: PChar;
- const ResourceName: PChar): TJclPeResourceItem;
- var
- I: Integer;
- TypeItem: TJclPeResourceItem;
- begin
- Result := nil;
- TypeItem := nil;
- for I := 0 to Count - 1 do
- if Items[I].CompareName(ResourceType) then
- begin
- TypeItem := Items[I];
- Break;
- end;
- if TypeItem <> nil then
- if ResourceName = nil then
- Result := TypeItem
- else
- with TypeItem.List do
- for I := 0 to Count - 1 do
- if Items[I].CompareName(ResourceName) then
- begin
- Result := Items[I];
- Break;
- end;
- end;
- function TJclPeRootResourceList.GetManifestContent: TStrings;
- var
- ManifestFileName: string;
- ResItem: TJclPeResourceItem;
- ResStream: TJclPeResourceRawStream;
- begin
- if FManifestContent = nil then
- begin
- FManifestContent := TStringList.Create;
- ResItem := FindResource(RT_MANIFEST, CREATEPROCESS_MANIFEST_RESOURCE_ID);
- if ResItem = nil then
- begin
- ManifestFileName := Image.FileName + MANIFESTExtension;
- if FileExists(ManifestFileName) then
- FManifestContent.LoadFromFile(ManifestFileName);
- end
- else
- begin
- ResStream := TJclPeResourceRawStream.Create(ResItem.List[0]);
- try
- FManifestContent.LoadFromStream(ResStream);
- finally
- ResStream.Free;
- end;
- end;
- end;
- Result := FManifestContent;
- end;
- function TJclPeRootResourceList.ListResourceNames(ResourceType: TJclPeResourceKind;
- const Strings: TStrings): Boolean;
- var
- ResTypeItem, TempItem: TJclPeResourceItem;
- I: Integer;
- begin
- ResTypeItem := FindResource(ResourceType, '');
- Result := (ResTypeItem <> nil);
- if Result then
- begin
- Strings.BeginUpdate;
- try
- with ResTypeItem.List do
- for I := 0 to Count - 1 do
- begin
- TempItem := Items[I];
- Strings.AddObject(TempItem.Name, Pointer(TempItem.IsName));
- end;
- finally
- Strings.EndUpdate;
- end;
- end;
- end;
- //=== { TJclPeRelocEntry } ===================================================
- constructor TJclPeRelocEntry.Create(AChunk: PImageBaseRelocation; ACount: Integer);
- begin
- inherited Create;
- FChunk := AChunk;
- FCount := ACount;
- end;
- function TJclPeRelocEntry.GetRelocations(Index: Integer): TJclPeRelocation;
- var
- Temp: Word;
- begin
- Temp := PWord(TJclAddr(FChunk) + SizeOf(TImageBaseRelocation) + DWORD(Index) * SizeOf(Word))^;
- Result.Address := Temp and $0FFF;
- Result.RelocType := (Temp and $F000) shr 12;
- Result.VirtualAddress := TJclAddr(Result.Address) + VirtualAddress;
- end;
- function TJclPeRelocEntry.GetSize: DWORD;
- begin
- Result := FChunk^.SizeOfBlock;
- end;
- function TJclPeRelocEntry.GetVirtualAddress: DWORD;
- begin
- Result := FChunk^.VirtualAddress;
- end;
- //=== { TJclPeRelocList } ====================================================
- constructor TJclPeRelocList.Create(AImage: TJclPeImage);
- begin
- inherited Create(AImage);
- CreateList;
- end;
- procedure TJclPeRelocList.CreateList;
- var
- Chunk: PImageBaseRelocation;
- Item: TJclPeRelocEntry;
- RelocCount: Integer;
- begin
- with Image do
- begin
- if not StatusOK then
- Exit;
- Chunk := DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_BASERELOC);
- if Chunk = nil then
- Exit;
- FAllItemCount := 0;
- while Chunk^.SizeOfBlock <> 0 do
- begin
- RelocCount := (Chunk^.SizeOfBlock - SizeOf(TImageBaseRelocation)) div SizeOf(Word);
- Item := TJclPeRelocEntry.Create(Chunk, RelocCount);
- Inc(FAllItemCount, RelocCount);
- Add(Item);
- Chunk := Pointer(TJclAddr(Chunk) + Chunk^.SizeOfBlock);
- end;
- end;
- end;
- function TJclPeRelocList.GetAllItems(Index: Integer): TJclPeRelocation;
- var
- I, N, C: Integer;
- begin
- N := Index;
- for I := 0 to Count - 1 do
- begin
- C := Items[I].Count;
- Dec(N, C);
- if N < 0 then
- begin
- Result := Items[I][N + C];
- Break;
- end;
- end;
- end;
- function TJclPeRelocList.GetItems(Index: Integer): TJclPeRelocEntry;
- begin
- Result := TJclPeRelocEntry(Get(Index));
- end;
- //=== { TJclPeDebugList } ====================================================
- constructor TJclPeDebugList.Create(AImage: TJclPeImage);
- begin
- inherited Create(AImage);
- OwnsObjects := False;
- CreateList;
- end;
- function TJclPeDebugList.IsTD32DebugInfo(DebugDir: PImageDebugDirectory): Boolean;
- var
- Base: Pointer;
- begin
- Base := Image.RvaToVa(DebugDir^.AddressOfRawData);
- Result := TJclTD32InfoParser.IsTD32DebugInfoValid(Base, DebugDir^.SizeOfData);
- end;
- procedure TJclPeDebugList.CreateList;
- var
- DebugImageDir: TImageDataDirectory;
- DebugDir: PImageDebugDirectory;
- Header: PImageSectionHeader;
- FormatCount, I: Integer;
- begin
- with Image do
- begin
- if not StatusOK then
- Exit;
- DebugImageDir := Directories[IMAGE_DIRECTORY_ENTRY_DEBUG];
- if DebugImageDir.VirtualAddress = 0 then
- Exit;
- if GetSectionHeader(DebugSectionName, Header) and
- (Header^.VirtualAddress = DebugImageDir.VirtualAddress) and
- (IsTD32DebugInfo(RvaToVa(DebugImageDir.VirtualAddress))) then
- begin
- // TD32 debug image directory is broken...size should be in bytes, not count.
- FormatCount := DebugImageDir.Size;
- end
- else
- begin
- FormatCount := DebugImageDir.Size div SizeOf(TImageDebugDirectory);
- end;
- DebugDir := RvaToVa(DebugImageDir.VirtualAddress);
- for I := 1 to FormatCount do
- begin
- Add(TObject(DebugDir));
- Inc(DebugDir);
- end;
- end;
- end;
- function TJclPeDebugList.GetItems(Index: Integer): TImageDebugDirectory;
- begin
- Result := PImageDebugDirectory(Get(Index))^;
- end;
- //=== { TJclPeCertificate } ==================================================
- constructor TJclPeCertificate.Create(AHeader: TWinCertificate; AData: Pointer);
- begin
- inherited Create;
- FHeader := AHeader;
- FData := AData;
- end;
- //=== { TJclPeCertificateList } ==============================================
- constructor TJclPeCertificateList.Create(AImage: TJclPeImage);
- begin
- inherited Create(AImage);
- CreateList;
- end;
- procedure TJclPeCertificateList.CreateList;
- var
- Directory: TImageDataDirectory;
- CertPtr: PChar;
- TotalSize: Integer;
- Item: TJclPeCertificate;
- begin
- Directory := Image.Directories[IMAGE_DIRECTORY_ENTRY_SECURITY];
- if Directory.VirtualAddress = 0 then
- Exit;
- CertPtr := Image.RawToVa(Directory.VirtualAddress); // Security directory is a raw offset
- TotalSize := Directory.Size;
- while TotalSize >= SizeOf(TWinCertificate) do
- begin
- Item := TJclPeCertificate.Create(PWinCertificate(CertPtr)^, CertPtr + SizeOf(TWinCertificate));
- Dec(TotalSize, Item.Header.dwLength);
- Add(Item);
- end;
- end;
- function TJclPeCertificateList.GetItems(Index: Integer): TJclPeCertificate;
- begin
- Result := TJclPeCertificate(Get(Index));
- end;
- //=== { TJclPeCLRHeader } ====================================================
- constructor TJclPeCLRHeader.Create(AImage: TJclPeImage);
- begin
- FImage := AImage;
- ReadHeader;
- end;
- function TJclPeCLRHeader.GetHasMetadata: Boolean;
- const
- METADATA_SIGNATURE = $424A5342; // Reference: Partition II Metadata.doc - 23.2.1 Metadata root
- begin
- with Header.MetaData do
- Result := (VirtualAddress <> 0) and (PDWORD(FImage.RvaToVa(VirtualAddress))^ = METADATA_SIGNATURE);
- end;
- { TODO -cDOC : "Flier Lu" <flier_lu att yahoo dott com dott cn> }
- function TJclPeCLRHeader.GetVersionString: string;
- begin
- Result := FormatVersionString(Header.MajorRuntimeVersion, Header.MinorRuntimeVersion);
- end;
- procedure TJclPeCLRHeader.ReadHeader;
- var
- HeaderPtr: PImageCor20Header;
- begin
- HeaderPtr := Image.DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR);
- if (HeaderPtr <> nil) and (HeaderPtr^.cb >= SizeOf(TImageCor20Header)) then
- FHeader := HeaderPtr^;
- end;
- //=== { TJclPeImage } ========================================================
- constructor TJclPeImage.Create(ANoExceptions: Boolean);
- begin
- FNoExceptions := ANoExceptions;
- FReadOnlyAccess := True;
- FImageSections := TStringList.Create;
- FStringTable := TStringList.Create;
- end;
- destructor TJclPeImage.Destroy;
- begin
- Clear;
- FreeAndNil(FImageSections);
- FStringTable.Free;
- inherited Destroy;
- end;
- procedure TJclPeImage.AfterOpen;
- begin
- end;
- procedure TJclPeImage.AttachLoadedModule(const Handle: HMODULE);
- procedure AttachLoadedModule32;
- var
- NtHeaders: PImageNtHeaders32;
- begin
- NtHeaders := PeMapImgNtHeaders32(Pointer(Handle));
- if NtHeaders = nil then
- FStatus := stNotPE
- else
- begin
- FStatus := stOk;
- FAttachedImage := True;
- FFileName := GetModulePath(Handle);
- // OF: possible loss of data
- FLoadedImage.ModuleName := PAnsiChar(AnsiString(FFileName));
- FLoadedImage.hFile := INVALID_HANDLE_VALUE;
- FLoadedImage.MappedAddress := Pointer(Handle);
- FLoadedImage.FileHeader := PImageNtHeaders(NtHeaders);
- FLoadedImage.NumberOfSections := NtHeaders^.FileHeader.NumberOfSections;
- FLoadedImage.Sections := PeMapImgSections32(NtHeaders);
- FLoadedImage.LastRvaSection := FLoadedImage.Sections;
- FLoadedImage.Characteristics := NtHeaders^.FileHeader.Characteristics;
- FLoadedImage.fSystemImage := (FLoadedImage.Characteristics and IMAGE_FILE_SYSTEM <> 0);
- FLoadedImage.fDOSImage := False;
- FLoadedImage.SizeOfImage := NtHeaders^.OptionalHeader.SizeOfImage;
- ReadImageSections;
- ReadStringTable;
- AfterOpen;
- end;
- RaiseStatusException;
- end;
- procedure AttachLoadedModule64;
- var
- NtHeaders: PImageNtHeaders64;
- begin
- NtHeaders := PeMapImgNtHeaders64(Pointer(Handle));
- if NtHeaders = nil then
- FStatus := stNotPE
- else
- begin
- FStatus := stOk;
- FAttachedImage := True;
- FFileName := GetModulePath(Handle);
- // OF: possible loss of data
- FLoadedImage.ModuleName := PAnsiChar(AnsiString(FFileName));
- FLoadedImage.hFile := INVALID_HANDLE_VALUE;
- FLoadedImage.MappedAddress := Pointer(Handle);
- FLoadedImage.FileHeader := PImageNtHeaders(NtHeaders);
- FLoadedImage.NumberOfSections := NtHeaders^.FileHeader.NumberOfSections;
- FLoadedImage.Sections := PeMapImgSections64(NtHeaders);
- FLoadedImage.LastRvaSection := FLoadedImage.Sections;
- FLoadedImage.Characteristics := NtHeaders^.FileHeader.Characteristics;
- FLoadedImage.fSystemImage := (FLoadedImage.Characteristics and IMAGE_FILE_SYSTEM <> 0);
- FLoadedImage.fDOSImage := False;
- FLoadedImage.SizeOfImage := NtHeaders^.OptionalHeader.SizeOfImage;
- ReadImageSections;
- ReadStringTable;
- AfterOpen;
- end;
- RaiseStatusException;
- end;
- begin
- Clear;
- if Handle = 0 then
- Exit;
- FTarget := PeMapImgTarget(Pointer(Handle));
- case Target of
- taWin32:
- AttachLoadedModule32;
- taWin64:
- AttachLoadedModule64;
- taUnknown:
- FStatus := stNotSupported;
- end;
- end;
- function TJclPeImage.CalculateCheckSum: DWORD;
- var
- C: DWORD;
- begin
- if StatusOK then
- begin
- CheckNotAttached;
- if CheckSumMappedFile(FLoadedImage.MappedAddress, FLoadedImage.SizeOfImage,
- C, Result) = nil then
- RaiseLastOSError;
- end
- else
- Result := 0;
- end;
- procedure TJclPeImage.CheckNotAttached;
- begin
- if FAttachedImage then
- raise EJclPeImageError.CreateRes(@RsPeNotAvailableForAttached);
- end;
- procedure TJclPeImage.Clear;
- begin
- FImageSections.Clear;
- FStringTable.Clear;
- FreeAndNil(FCertificateList);
- FreeAndNil(FCLRHeader);
- FreeAndNil(FDebugList);
- FreeAndNil(FImportList);
- FreeAndNil(FExportList);
- FreeAndNil(FRelocationList);
- FreeAndNil(FResourceList);
- FreeAndNil(FVersionInfo);
- if not FAttachedImage and StatusOK then
- UnMapAndLoad(FLoadedImage);
- ResetMemory(FLoadedImage, SizeOf(FLoadedImage));
- FStatus := stNotLoaded;
- FAttachedImage := False;
- end;
- class function TJclPeImage.DateTimeToStamp(const DateTime: TDateTime): DWORD;
- begin
- Result := Round((DateTime - UnixTimeStart) * SecsPerDay);
- end;
- class function TJclPeImage.DebugTypeNames(DebugType: DWORD): string;
- begin
- case DebugType of
- IMAGE_DEBUG_TYPE_UNKNOWN:
- Result := LoadResString(@RsPeDEBUG_UNKNOWN);
- IMAGE_DEBUG_TYPE_COFF:
- Result := LoadResString(@RsPeDEBUG_COFF);
- IMAGE_DEBUG_TYPE_CODEVIEW:
- Result := LoadResString(@RsPeDEBUG_CODEVIEW);
- IMAGE_DEBUG_TYPE_FPO:
- Result := LoadResString(@RsPeDEBUG_FPO);
- IMAGE_DEBUG_TYPE_MISC:
- Result := LoadResString(@RsPeDEBUG_MISC);
- IMAGE_DEBUG_TYPE_EXCEPTION:
- Result := LoadResString(@RsPeDEBUG_EXCEPTION);
- IMAGE_DEBUG_TYPE_FIXUP:
- Result := LoadResString(@RsPeDEBUG_FIXUP);
- IMAGE_DEBUG_TYPE_OMAP_TO_SRC:
- Result := LoadResString(@RsPeDEBUG_OMAP_TO_SRC);
- IMAGE_DEBUG_TYPE_OMAP_FROM_SRC:
- Result := LoadResString(@RsPeDEBUG_OMAP_FROM_SRC);
- else
- Result := LoadResString(@RsPeDEBUG_UNKNOWN);
- end;
- end;
- function TJclPeImage.DirectoryEntryToData(Directory: Word): Pointer;
- var
- Size: DWORD;
- begin
- Size := 0;
- Result := ImageDirectoryEntryToData(FLoadedImage.MappedAddress, FAttachedImage, Directory, Size);
- end;
- class function TJclPeImage.DirectoryNames(Directory: Word): string;
- begin
- case Directory of
- IMAGE_DIRECTORY_ENTRY_EXPORT:
- Result := LoadResString(@RsPeImg_00);
- IMAGE_DIRECTORY_ENTRY_IMPORT:
- Result := LoadResString(@RsPeImg_01);
- IMAGE_DIRECTORY_ENTRY_RESOURCE:
- Result := LoadResString(@RsPeImg_02);
- IMAGE_DIRECTORY_ENTRY_EXCEPTION:
- Result := LoadResString(@RsPeImg_03);
- IMAGE_DIRECTORY_ENTRY_SECURITY:
- Result := LoadResString(@RsPeImg_04);
- IMAGE_DIRECTORY_ENTRY_BASERELOC:
- Result := LoadResString(@RsPeImg_05);
- IMAGE_DIRECTORY_ENTRY_DEBUG:
- Result := LoadResString(@RsPeImg_06);
- IMAGE_DIRECTORY_ENTRY_COPYRIGHT:
- Result := LoadResString(@RsPeImg_07);
- IMAGE_DIRECTORY_ENTRY_GLOBALPTR:
- Result := LoadResString(@RsPeImg_08);
- IMAGE_DIRECTORY_ENTRY_TLS:
- Result := LoadResString(@RsPeImg_09);
- IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG:
- Result := LoadResString(@RsPeImg_10);
- IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT:
- Result := LoadResString(@RsPeImg_11);
- IMAGE_DIRECTORY_ENTRY_IAT:
- Result := LoadResString(@RsPeImg_12);
- IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT:
- Result := LoadResString(@RsPeImg_13);
- IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR:
- Result := LoadResString(@RsPeImg_14);
- else
- Result := Format(LoadResString(@RsPeImg_Reserved), [Directory]);
- end;
- end;
- class function TJclPeImage.ExpandBySearchPath(const ModuleName, BasePath: string): TFileName;
- var
- FullName: array [0..MAX_PATH] of Char;
- FilePart: PChar;
- begin
- Result := PathAddSeparator(ExtractFilePath(BasePath)) + ModuleName;
- if FileExists(Result) then
- Exit;
- FilePart := nil;
- if SearchPath(nil, PChar(ModuleName), nil, Length(FullName), FullName, FilePart) = 0 then
- Result := ModuleName
- else
- Result := FullName;
- end;
- function TJclPeImage.ExpandModuleName(const ModuleName: string): TFileName;
- begin
- Result := ExpandBySearchPath(ModuleName, ExtractFilePath(FFileName));
- end;
- function TJclPeImage.GetCertificateList: TJclPeCertificateList;
- begin
- if FCertificateList = nil then
- FCertificateList := TJclPeCertificateList.Create(Self);
- Result := FCertificateList;
- end;
- function TJclPeImage.GetCLRHeader: TJclPeCLRHeader;
- begin
- if FCLRHeader = nil then
- FCLRHeader := TJclPeCLRHeader.Create(Self);
- Result := FCLRHeader;
- end;
- function TJclPeImage.GetDebugList: TJclPeDebugList;
- begin
- if FDebugList = nil then
- FDebugList := TJclPeDebugList.Create(Self);
- Result := FDebugList;
- end;
- function TJclPeImage.GetDescription: string;
- var
- UTF8DescriptionName: TUTF8String;
- begin
- if DirectoryExists[IMAGE_DIRECTORY_ENTRY_COPYRIGHT] then
- begin
- UTF8DescriptionName := PAnsiChar(DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_COPYRIGHT));
- if not TryUTF8ToString(UTF8DescriptionName, Result) then
- Result := string(UTF8DescriptionName);
- end
- else
- Result := '';
- end;
- function TJclPeImage.GetDirectories(Directory: Word): TImageDataDirectory;
- begin
- if StatusOK then
- begin
- case Target of
- taWin32:
- Result := PImageNtHeaders32(FLoadedImage.FileHeader)^.OptionalHeader.DataDirectory[Directory];
- taWin64:
- Result := PImageNtHeaders64(FLoadedImage.FileHeader)^.OptionalHeader.DataDirectory[Directory];
- else
- Result.VirtualAddress := 0;
- Result.Size := 0;
- end
- end
- else
- begin
- Result.VirtualAddress := 0;
- Result.Size := 0;
- end;
- end;
- function TJclPeImage.GetDirectoryExists(Directory: Word): Boolean;
- begin
- Result := (Directories[Directory].VirtualAddress <> 0);
- end;
- function TJclPeImage.GetExportList: TJclPeExportFuncList;
- begin
- if FExportList = nil then
- FExportList := TJclPeExportFuncList.Create(Self);
- Result := FExportList;
- end;
- {$IFNDEF WINSCP}
- function TJclPeImage.GetFileProperties: TJclPeFileProperties;
- var
- FileAttributesEx: WIN32_FILE_ATTRIBUTE_DATA;
- Size: TJclULargeInteger;
- begin
- ResetMemory(Result, SizeOf(Result));
- if GetFileAttributesEx(PChar(FileName), GetFileExInfoStandard, @FileAttributesEx) then
- begin
- Size.LowPart := FileAttributesEx.nFileSizeLow;
- Size.HighPart := FileAttributesEx.nFileSizeHigh;
- Result.Size := Size.QuadPart;
- Result.CreationTime := FileTimeToLocalDateTime(FileAttributesEx.ftCreationTime);
- Result.LastAccessTime := FileTimeToLocalDateTime(FileAttributesEx.ftLastAccessTime);
- Result.LastWriteTime := FileTimeToLocalDateTime(FileAttributesEx.ftLastWriteTime);
- Result.Attributes := FileAttributesEx.dwFileAttributes;
- end;
- end;
- {$ENDIF ~WINSCP}
- function TJclPeImage.GetHeaderValues(Index: TJclPeHeader): string;
- function GetMachineString(Value: DWORD): string;
- begin
- case Value of
- IMAGE_FILE_MACHINE_UNKNOWN:
- Result := LoadResString(@RsPeMACHINE_UNKNOWN);
- IMAGE_FILE_MACHINE_I386:
- Result := LoadResString(@RsPeMACHINE_I386);
- IMAGE_FILE_MACHINE_R3000:
- Result := LoadResString(@RsPeMACHINE_R3000);
- IMAGE_FILE_MACHINE_R4000:
- Result := LoadResString(@RsPeMACHINE_R4000);
- IMAGE_FILE_MACHINE_R10000:
- Result := LoadResString(@RsPeMACHINE_R10000);
- IMAGE_FILE_MACHINE_WCEMIPSV2:
- Result := LoadResString(@RsPeMACHINE_WCEMIPSV2);
- IMAGE_FILE_MACHINE_ALPHA:
- Result := LoadResString(@RsPeMACHINE_ALPHA);
- IMAGE_FILE_MACHINE_SH3:
- Result := LoadResString(@RsPeMACHINE_SH3); // SH3 little-endian
- IMAGE_FILE_MACHINE_SH3DSP:
- Result := LoadResString(@RsPeMACHINE_SH3DSP);
- IMAGE_FILE_MACHINE_SH3E:
- Result := LoadResString(@RsPeMACHINE_SH3E); // SH3E little-endian
- IMAGE_FILE_MACHINE_SH4:
- Result := LoadResString(@RsPeMACHINE_SH4); // SH4 little-endian
- IMAGE_FILE_MACHINE_SH5:
- Result := LoadResString(@RsPeMACHINE_SH5); // SH5
- IMAGE_FILE_MACHINE_ARM:
- Result := LoadResString(@RsPeMACHINE_ARM); // ARM Little-Endian
- IMAGE_FILE_MACHINE_THUMB:
- Result := LoadResString(@RsPeMACHINE_THUMB);
- IMAGE_FILE_MACHINE_AM33:
- Result := LoadResString(@RsPeMACHINE_AM33);
- IMAGE_FILE_MACHINE_POWERPC:
- Result := LoadResString(@RsPeMACHINE_POWERPC);
- IMAGE_FILE_MACHINE_POWERPCFP:
- Result := LoadResString(@RsPeMACHINE_POWERPCFP);
- IMAGE_FILE_MACHINE_IA64:
- Result := LoadResString(@RsPeMACHINE_IA64); // Intel 64
- IMAGE_FILE_MACHINE_MIPS16:
- Result := LoadResString(@RsPeMACHINE_MIPS16); // MIPS
- IMAGE_FILE_MACHINE_ALPHA64:
- Result := LoadResString(@RsPeMACHINE_AMPHA64); // ALPHA64
- //IMAGE_FILE_MACHINE_AXP64
- IMAGE_FILE_MACHINE_MIPSFPU:
- Result := LoadResString(@RsPeMACHINE_MIPSFPU); // MIPS
- IMAGE_FILE_MACHINE_MIPSFPU16:
- Result := LoadResString(@RsPeMACHINE_MIPSFPU16); // MIPS
- IMAGE_FILE_MACHINE_TRICORE:
- Result := LoadResString(@RsPeMACHINE_TRICORE); // Infineon
- IMAGE_FILE_MACHINE_CEF:
- Result := LoadResString(@RsPeMACHINE_CEF);
- IMAGE_FILE_MACHINE_EBC:
- Result := LoadResString(@RsPeMACHINE_EBC); // EFI Byte Code
- IMAGE_FILE_MACHINE_AMD64:
- Result := LoadResString(@RsPeMACHINE_AMD64); // AMD64 (K8)
- IMAGE_FILE_MACHINE_M32R:
- Result := LoadResString(@RsPeMACHINE_M32R); // M32R little-endian
- IMAGE_FILE_MACHINE_CEE:
- Result := LoadResString(@RsPeMACHINE_CEE);
- else
- Result := Format('[%.8x]', [Value]);
- end;
- end;
- function GetSubsystemString(Value: DWORD): string;
- begin
- case Value of
- IMAGE_SUBSYSTEM_UNKNOWN:
- Result := LoadResString(@RsPeSUBSYSTEM_UNKNOWN);
- IMAGE_SUBSYSTEM_NATIVE:
- Result := LoadResString(@RsPeSUBSYSTEM_NATIVE);
- IMAGE_SUBSYSTEM_WINDOWS_GUI:
- Result := LoadResString(@RsPeSUBSYSTEM_WINDOWS_GUI);
- IMAGE_SUBSYSTEM_WINDOWS_CUI:
- Result := LoadResString(@RsPeSUBSYSTEM_WINDOWS_CUI);
- IMAGE_SUBSYSTEM_OS2_CUI:
- Result := LoadResString(@RsPeSUBSYSTEM_OS2_CUI);
- IMAGE_SUBSYSTEM_POSIX_CUI:
- Result := LoadResString(@RsPeSUBSYSTEM_POSIX_CUI);
- IMAGE_SUBSYSTEM_RESERVED8:
- Result := LoadResString(@RsPeSUBSYSTEM_RESERVED8);
- else
- Result := Format('[%.8x]', [Value]);
- end;
- end;
- function GetHeaderValues32(Index: TJclPeHeader): string;
- var
- OptionalHeader: TImageOptionalHeader32;
- begin
- OptionalHeader := OptionalHeader32;
- case Index of
- JclPeHeader_Magic:
- Result := IntToHex(OptionalHeader.Magic, 4);
- JclPeHeader_LinkerVersion:
- Result := FormatVersionString(OptionalHeader.MajorLinkerVersion, OptionalHeader.MinorLinkerVersion);
- JclPeHeader_SizeOfCode:
- Result := IntToHex(OptionalHeader.SizeOfCode, 8);
- JclPeHeader_SizeOfInitializedData:
- Result := IntToHex(OptionalHeader.SizeOfInitializedData, 8);
- JclPeHeader_SizeOfUninitializedData:
- Result := IntToHex(OptionalHeader.SizeOfUninitializedData, 8);
- JclPeHeader_AddressOfEntryPoint:
- Result := IntToHex(OptionalHeader.AddressOfEntryPoint, 8);
- JclPeHeader_BaseOfCode:
- Result := IntToHex(OptionalHeader.BaseOfCode, 8);
- JclPeHeader_BaseOfData:
- {$IFDEF DELPHI64_TEMPORARY}
- System.Error(rePlatformNotImplemented);
- {$ELSE ~DELPHI64_TEMPORARY}
- Result := IntToHex(OptionalHeader.BaseOfData, 8);
- {$ENDIF ~DELPHI64_TEMPORARY}
- JclPeHeader_ImageBase:
- Result := IntToHex(OptionalHeader.ImageBase, 8);
- JclPeHeader_SectionAlignment:
- Result := IntToHex(OptionalHeader.SectionAlignment, 8);
- JclPeHeader_FileAlignment:
- Result := IntToHex(OptionalHeader.FileAlignment, 8);
- JclPeHeader_OperatingSystemVersion:
- Result := FormatVersionString(OptionalHeader.MajorOperatingSystemVersion, OptionalHeader.MinorOperatingSystemVersion);
- JclPeHeader_ImageVersion:
- Result := FormatVersionString(OptionalHeader.MajorImageVersion, OptionalHeader.MinorImageVersion);
- JclPeHeader_SubsystemVersion:
- Result := FormatVersionString(OptionalHeader.MajorSubsystemVersion, OptionalHeader.MinorSubsystemVersion);
- JclPeHeader_Win32VersionValue:
- Result := IntToHex(OptionalHeader.Win32VersionValue, 8);
- JclPeHeader_SizeOfImage:
- Result := IntToHex(OptionalHeader.SizeOfImage, 8);
- JclPeHeader_SizeOfHeaders:
- Result := IntToHex(OptionalHeader.SizeOfHeaders, 8);
- JclPeHeader_CheckSum:
- Result := IntToHex(OptionalHeader.CheckSum, 8);
- JclPeHeader_Subsystem:
- Result := GetSubsystemString(OptionalHeader.Subsystem);
- JclPeHeader_DllCharacteristics:
- Result := IntToHex(OptionalHeader.DllCharacteristics, 4);
- JclPeHeader_SizeOfStackReserve:
- Result := IntToHex(OptionalHeader.SizeOfStackReserve, 8);
- JclPeHeader_SizeOfStackCommit:
- Result := IntToHex(OptionalHeader.SizeOfStackCommit, 8);
- JclPeHeader_SizeOfHeapReserve:
- Result := IntToHex(OptionalHeader.SizeOfHeapReserve, 8);
- JclPeHeader_SizeOfHeapCommit:
- Result := IntToHex(OptionalHeader.SizeOfHeapCommit, 8);
- JclPeHeader_LoaderFlags:
- Result := IntToHex(OptionalHeader.LoaderFlags, 8);
- JclPeHeader_NumberOfRvaAndSizes:
- Result := IntToHex(OptionalHeader.NumberOfRvaAndSizes, 8);
- end;
- end;
- function GetHeaderValues64(Index: TJclPeHeader): string;
- var
- OptionalHeader: TImageOptionalHeader64;
- begin
- OptionalHeader := OptionalHeader64;
- case Index of
- JclPeHeader_Magic:
- Result := IntToHex(OptionalHeader.Magic, 4);
- JclPeHeader_LinkerVersion:
- Result := FormatVersionString(OptionalHeader.MajorLinkerVersion, OptionalHeader.MinorLinkerVersion);
- JclPeHeader_SizeOfCode:
- Result := IntToHex(OptionalHeader.SizeOfCode, 8);
- JclPeHeader_SizeOfInitializedData:
- Result := IntToHex(OptionalHeader.SizeOfInitializedData, 8);
- JclPeHeader_SizeOfUninitializedData:
- Result := IntToHex(OptionalHeader.SizeOfUninitializedData, 8);
- JclPeHeader_AddressOfEntryPoint:
- Result := IntToHex(OptionalHeader.AddressOfEntryPoint, 8);
- JclPeHeader_BaseOfCode:
- Result := IntToHex(OptionalHeader.BaseOfCode, 8);
- JclPeHeader_BaseOfData:
- Result := ''; // IntToHex(OptionalHeader.BaseOfData, 8);
- JclPeHeader_ImageBase:
- Result := IntToHex(OptionalHeader.ImageBase, 16);
- JclPeHeader_SectionAlignment:
- Result := IntToHex(OptionalHeader.SectionAlignment, 8);
- JclPeHeader_FileAlignment:
- Result := IntToHex(OptionalHeader.FileAlignment, 8);
- JclPeHeader_OperatingSystemVersion:
- Result := FormatVersionString(OptionalHeader.MajorOperatingSystemVersion, OptionalHeader.MinorOperatingSystemVersion);
- JclPeHeader_ImageVersion:
- Result := FormatVersionString(OptionalHeader.MajorImageVersion, OptionalHeader.MinorImageVersion);
- JclPeHeader_SubsystemVersion:
- Result := FormatVersionString(OptionalHeader.MajorSubsystemVersion, OptionalHeader.MinorSubsystemVersion);
- JclPeHeader_Win32VersionValue:
- Result := IntToHex(OptionalHeader.Win32VersionValue, 8);
- JclPeHeader_SizeOfImage:
- Result := IntToHex(OptionalHeader.SizeOfImage, 8);
- JclPeHeader_SizeOfHeaders:
- Result := IntToHex(OptionalHeader.SizeOfHeaders, 8);
- JclPeHeader_CheckSum:
- Result := IntToHex(OptionalHeader.CheckSum, 8);
- JclPeHeader_Subsystem:
- Result := GetSubsystemString(OptionalHeader.Subsystem);
- JclPeHeader_DllCharacteristics:
- Result := IntToHex(OptionalHeader.DllCharacteristics, 4);
- JclPeHeader_SizeOfStackReserve:
- Result := IntToHex(OptionalHeader.SizeOfStackReserve, 16);
- JclPeHeader_SizeOfStackCommit:
- Result := IntToHex(OptionalHeader.SizeOfStackCommit, 16);
- JclPeHeader_SizeOfHeapReserve:
- Result := IntToHex(OptionalHeader.SizeOfHeapReserve, 16);
- JclPeHeader_SizeOfHeapCommit:
- Result := IntToHex(OptionalHeader.SizeOfHeapCommit, 16);
- JclPeHeader_LoaderFlags:
- Result := IntToHex(OptionalHeader.LoaderFlags, 8);
- JclPeHeader_NumberOfRvaAndSizes:
- Result := IntToHex(OptionalHeader.NumberOfRvaAndSizes, 8);
- end;
- end;
- begin
- if StatusOK then
- with FLoadedImage.FileHeader^ do
- case Index of
- JclPeHeader_Signature:
- Result := IntToHex(Signature, 8);
- JclPeHeader_Machine:
- Result := GetMachineString(FileHeader.Machine);
- JclPeHeader_NumberOfSections:
- Result := IntToHex(FileHeader.NumberOfSections, 4);
- JclPeHeader_TimeDateStamp:
- Result := IntToHex(FileHeader.TimeDateStamp, 8);
- JclPeHeader_PointerToSymbolTable:
- Result := IntToHex(FileHeader.PointerToSymbolTable, 8);
- JclPeHeader_NumberOfSymbols:
- Result := IntToHex(FileHeader.NumberOfSymbols, 8);
- JclPeHeader_SizeOfOptionalHeader:
- Result := IntToHex(FileHeader.SizeOfOptionalHeader, 4);
- JclPeHeader_Characteristics:
- Result := IntToHex(FileHeader.Characteristics, 4);
- JclPeHeader_Magic..JclPeHeader_NumberOfRvaAndSizes:
- case Target of
- taWin32:
- Result := GetHeaderValues32(Index);
- taWin64:
- Result := GetHeaderValues64(Index);
- //taUnknown:
- else
- Result := '';
- end;
- else
- Result := '';
- end
- else
- Result := '';
- end;
- function TJclPeImage.GetImageSectionCount: Integer;
- begin
- Result := FImageSections.Count;
- end;
- function TJclPeImage.GetImageSectionFullNames(Index: Integer): string;
- var
- Offset: Integer;
- begin
- Result := ImageSectionNames[Index];
- if (Length(Result) > 0) and (Result[1] = '/') and TryStrToInt(Copy(Result, 2, MaxInt), Offset) then
- Result := GetNameInStringTable(Offset);
- end;
- function TJclPeImage.GetImageSectionHeaders(Index: Integer): TImageSectionHeader;
- begin
- Result := PImageSectionHeader(FImageSections.Objects[Index])^;
- end;
- function TJclPeImage.GetImageSectionNameFromRva(const Rva: DWORD): string;
- begin
- Result := GetSectionName(RvaToSection(Rva));
- end;
- function TJclPeImage.GetImageSectionNames(Index: Integer): string;
- begin
- Result := FImageSections[Index];
- end;
- function TJclPeImage.GetImportList: TJclPeImportList;
- begin
- if FImportList = nil then
- FImportList := TJclPeImportList.Create(Self);
- Result := FImportList;
- end;
- function TJclPeImage.GetLoadConfigValues(Index: TJclLoadConfig): string;
- function GetLoadConfigValues32(Index: TJclLoadConfig): string;
- var
- LoadConfig: PIMAGE_LOAD_CONFIG_DIRECTORY32;
- begin
- LoadConfig := DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG);
- if LoadConfig <> nil then
- with LoadConfig^ do
- case Index of
- JclLoadConfig_Characteristics:
- Result := IntToHex(Size, 8);
- JclLoadConfig_TimeDateStamp:
- Result := IntToHex(TimeDateStamp, 8);
- JclLoadConfig_Version:
- Result := FormatVersionString(MajorVersion, MinorVersion);
- JclLoadConfig_GlobalFlagsClear:
- Result := IntToHex(GlobalFlagsClear, 8);
- JclLoadConfig_GlobalFlagsSet:
- Result := IntToHex(GlobalFlagsSet, 8);
- JclLoadConfig_CriticalSectionDefaultTimeout:
- Result := IntToHex(CriticalSectionDefaultTimeout, 8);
- JclLoadConfig_DeCommitFreeBlockThreshold:
- Result := IntToHex(DeCommitFreeBlockThreshold, 8);
- JclLoadConfig_DeCommitTotalFreeThreshold:
- Result := IntToHex(DeCommitTotalFreeThreshold, 8);
- JclLoadConfig_LockPrefixTable:
- Result := IntToHex(LockPrefixTable, 8);
- JclLoadConfig_MaximumAllocationSize:
- Result := IntToHex(MaximumAllocationSize, 8);
- JclLoadConfig_VirtualMemoryThreshold:
- Result := IntToHex(VirtualMemoryThreshold, 8);
- JclLoadConfig_ProcessHeapFlags:
- Result := IntToHex(ProcessHeapFlags, 8);
- JclLoadConfig_ProcessAffinityMask:
- Result := IntToHex(ProcessAffinityMask, 8);
- JclLoadConfig_CSDVersion:
- Result := IntToHex(CSDVersion, 4);
- JclLoadConfig_Reserved1:
- Result := IntToHex(Reserved1, 4);
- JclLoadConfig_EditList:
- Result := IntToHex(EditList, 8);
- JclLoadConfig_Reserved:
- Result := LoadResString(@RsPeReserved);
- end;
- end;
- function GetLoadConfigValues64(Index: TJclLoadConfig): string;
- var
- LoadConfig: PIMAGE_LOAD_CONFIG_DIRECTORY64;
- begin
- LoadConfig := DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG);
- if LoadConfig <> nil then
- with LoadConfig^ do
- case Index of
- JclLoadConfig_Characteristics:
- Result := IntToHex(Size, 8);
- JclLoadConfig_TimeDateStamp:
- Result := IntToHex(TimeDateStamp, 8);
- JclLoadConfig_Version:
- Result := FormatVersionString(MajorVersion, MinorVersion);
- JclLoadConfig_GlobalFlagsClear:
- Result := IntToHex(GlobalFlagsClear, 8);
- JclLoadConfig_GlobalFlagsSet:
- Result := IntToHex(GlobalFlagsSet, 8);
- JclLoadConfig_CriticalSectionDefaultTimeout:
- Result := IntToHex(CriticalSectionDefaultTimeout, 8);
- JclLoadConfig_DeCommitFreeBlockThreshold:
- Result := IntToHex(DeCommitFreeBlockThreshold, 16);
- JclLoadConfig_DeCommitTotalFreeThreshold:
- Result := IntToHex(DeCommitTotalFreeThreshold, 16);
- JclLoadConfig_LockPrefixTable:
- Result := IntToHex(LockPrefixTable, 16);
- JclLoadConfig_MaximumAllocationSize:
- Result := IntToHex(MaximumAllocationSize, 16);
- JclLoadConfig_VirtualMemoryThreshold:
- Result := IntToHex(VirtualMemoryThreshold, 16);
- JclLoadConfig_ProcessHeapFlags:
- Result := IntToHex(ProcessHeapFlags, 8);
- JclLoadConfig_ProcessAffinityMask:
- Result := IntToHex(ProcessAffinityMask, 16);
- JclLoadConfig_CSDVersion:
- Result := IntToHex(CSDVersion, 4);
- JclLoadConfig_Reserved1:
- Result := IntToHex(Reserved1, 4);
- JclLoadConfig_EditList:
- Result := IntToHex(EditList, 16);
- JclLoadConfig_Reserved:
- Result := LoadResString(@RsPeReserved);
- end;
- end;
- begin
- Result := '';
- case Target of
- taWin32:
- Result := GetLoadConfigValues32(Index);
- taWin64:
- Result := GetLoadConfigValues64(Index);
- end;
- end;
- function TJclPeImage.GetMappedAddress: TJclAddr;
- begin
- if StatusOK then
- Result := TJclAddr(LoadedImage.MappedAddress)
- else
- Result := 0;
- end;
- function TJclPeImage.GetNameInStringTable(Offset: ULONG): string;
- var
- Index: Integer;
- begin
- Dec(Offset, SizeOf(ULONG));
- Index := 0;
- while (Offset > 0) and (Index < FStringTable.Count) do
- begin
- Dec(Offset, Length(FStringTable[Index]) + 1);
- if Offset > 0 then
- Inc(Index);
- end;
- if Offset = 0 then
- Result := FStringTable[Index]
- else
- Result := '';
- end;
- function TJclPeImage.GetOptionalHeader32: TImageOptionalHeader32;
- begin
- if Target = taWin32 then
- Result := PImageNtHeaders32(FLoadedImage.FileHeader)^.OptionalHeader
- else
- ZeroMemory(@Result, SizeOf(Result));
- end;
- function TJclPeImage.GetOptionalHeader64: TImageOptionalHeader64;
- begin
- if Target = taWin64 then
- Result := PImageNtHeaders64(FLoadedImage.FileHeader)^.OptionalHeader
- else
- ZeroMemory(@Result, SizeOf(Result));
- end;
- function TJclPeImage.GetRelocationList: TJclPeRelocList;
- begin
- if FRelocationList = nil then
- FRelocationList := TJclPeRelocList.Create(Self);
- Result := FRelocationList;
- end;
- function TJclPeImage.GetResourceList: TJclPeRootResourceList;
- begin
- if FResourceList = nil then
- begin
- FResourceVA := Directories[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
- if FResourceVA <> 0 then
- FResourceVA := TJclAddr(RvaToVa(FResourceVA));
- FResourceList := TJclPeRootResourceList.Create(Self, nil, PImageResourceDirectory(FResourceVA));
- end;
- Result := FResourceList;
- end;
- function TJclPeImage.GetSectionHeader(const SectionName: string;
- out Header: PImageSectionHeader): Boolean;
- var
- I: Integer;
- begin
- I := FImageSections.IndexOf(SectionName);
- if I = -1 then
- begin
- Header := nil;
- Result := False;
- end
- else
- begin
- Header := PImageSectionHeader(FImageSections.Objects[I]);
- Result := True;
- end;
- end;
- function TJclPeImage.GetSectionName(Header: PImageSectionHeader): string;
- var
- I: Integer;
- begin
- I := FImageSections.IndexOfObject(TObject(Header));
- if I = -1 then
- Result := ''
- else
- Result := FImageSections[I];
- end;
- function TJclPeImage.GetStringTableCount: Integer;
- begin
- Result := FStringTable.Count;
- end;
- function TJclPeImage.GetStringTableItem(Index: Integer): string;
- begin
- Result := FStringTable[Index];
- end;
- function TJclPeImage.GetUnusedHeaderBytes: TImageDataDirectory;
- begin
- CheckNotAttached;
- Result.Size := 0;
- Result.VirtualAddress := GetImageUnusedHeaderBytes(FLoadedImage, Result.Size);
- if Result.VirtualAddress = 0 then
- RaiseLastOSError;
- end;
- function TJclPeImage.GetVersionInfo: TJclFileVersionInfo;
- var
- VersionInfoResource: TJclPeResourceItem;
- begin
- if (FVersionInfo = nil) and VersionInfoAvailable then
- begin
- VersionInfoResource := ResourceList.FindResource(rtVersion, '1').List[0];
- with VersionInfoResource do
- try
- FVersionInfo := TJclFileVersionInfo.Attach(RawEntryData, RawEntryDataSize);
- except
- FreeAndNil(FVersionInfo);
- end;
- end;
- Result := FVersionInfo;
- end;
- function TJclPeImage.GetVersionInfoAvailable: Boolean;
- begin
- Result := StatusOK and (ResourceList.FindResource(rtVersion, '1') <> nil);
- end;
- class function TJclPeImage.HeaderNames(Index: TJclPeHeader): string;
- begin
- case Index of
- JclPeHeader_Signature:
- Result := LoadResString(@RsPeSignature);
- JclPeHeader_Machine:
- Result := LoadResString(@RsPeMachine);
- JclPeHeader_NumberOfSections:
- Result := LoadResString(@RsPeNumberOfSections);
- JclPeHeader_TimeDateStamp:
- Result := LoadResString(@RsPeTimeDateStamp);
- JclPeHeader_PointerToSymbolTable:
- Result := LoadResString(@RsPePointerToSymbolTable);
- JclPeHeader_NumberOfSymbols:
- Result := LoadResString(@RsPeNumberOfSymbols);
- JclPeHeader_SizeOfOptionalHeader:
- Result := LoadResString(@RsPeSizeOfOptionalHeader);
- JclPeHeader_Characteristics:
- Result := LoadResString(@RsPeCharacteristics);
- JclPeHeader_Magic:
- Result := LoadResString(@RsPeMagic);
- JclPeHeader_LinkerVersion:
- Result := LoadResString(@RsPeLinkerVersion);
- JclPeHeader_SizeOfCode:
- Result := LoadResString(@RsPeSizeOfCode);
- JclPeHeader_SizeOfInitializedData:
- Result := LoadResString(@RsPeSizeOfInitializedData);
- JclPeHeader_SizeOfUninitializedData:
- Result := LoadResString(@RsPeSizeOfUninitializedData);
- JclPeHeader_AddressOfEntryPoint:
- Result := LoadResString(@RsPeAddressOfEntryPoint);
- JclPeHeader_BaseOfCode:
- Result := LoadResString(@RsPeBaseOfCode);
- JclPeHeader_BaseOfData:
- Result := LoadResString(@RsPeBaseOfData);
- JclPeHeader_ImageBase:
- Result := LoadResString(@RsPeImageBase);
- JclPeHeader_SectionAlignment:
- Result := LoadResString(@RsPeSectionAlignment);
- JclPeHeader_FileAlignment:
- Result := LoadResString(@RsPeFileAlignment);
- JclPeHeader_OperatingSystemVersion:
- Result := LoadResString(@RsPeOperatingSystemVersion);
- JclPeHeader_ImageVersion:
- Result := LoadResString(@RsPeImageVersion);
- JclPeHeader_SubsystemVersion:
- Result := LoadResString(@RsPeSubsystemVersion);
- JclPeHeader_Win32VersionValue:
- Result := LoadResString(@RsPeWin32VersionValue);
- JclPeHeader_SizeOfImage:
- Result := LoadResString(@RsPeSizeOfImage);
- JclPeHeader_SizeOfHeaders:
- Result := LoadResString(@RsPeSizeOfHeaders);
- JclPeHeader_CheckSum:
- Result := LoadResString(@RsPeCheckSum);
- JclPeHeader_Subsystem:
- Result := LoadResString(@RsPeSubsystem);
- JclPeHeader_DllCharacteristics:
- Result := LoadResString(@RsPeDllCharacteristics);
- JclPeHeader_SizeOfStackReserve:
- Result := LoadResString(@RsPeSizeOfStackReserve);
- JclPeHeader_SizeOfStackCommit:
- Result := LoadResString(@RsPeSizeOfStackCommit);
- JclPeHeader_SizeOfHeapReserve:
- Result := LoadResString(@RsPeSizeOfHeapReserve);
- JclPeHeader_SizeOfHeapCommit:
- Result := LoadResString(@RsPeSizeOfHeapCommit);
- JclPeHeader_LoaderFlags:
- Result := LoadResString(@RsPeLoaderFlags);
- JclPeHeader_NumberOfRvaAndSizes:
- Result := LoadResString(@RsPeNumberOfRvaAndSizes);
- else
- Result := '';
- end;
- end;
- function TJclPeImage.IsBrokenFormat: Boolean;
- function IsBrokenFormat32: Boolean;
- var
- OptionalHeader: TImageOptionalHeader32;
- begin
- OptionalHeader := OptionalHeader32;
- Result := not ((OptionalHeader.AddressOfEntryPoint = 0) or IsCLR);
- if Result then
- begin
- Result := (ImageSectionCount = 0);
- if not Result then
- with ImageSectionHeaders[0] do
- Result := (VirtualAddress <> OptionalHeader.BaseOfCode) or (SizeOfRawData = 0) or
- (OptionalHeader.AddressOfEntryPoint > VirtualAddress + Misc.VirtualSize) or
- (Characteristics and (IMAGE_SCN_CNT_CODE or IMAGE_SCN_MEM_WRITE) <> IMAGE_SCN_CNT_CODE);
- end;
- end;
- function IsBrokenFormat64: Boolean;
- var
- OptionalHeader: TImageOptionalHeader64;
- begin
- OptionalHeader := OptionalHeader64;
- Result := not ((OptionalHeader.AddressOfEntryPoint = 0) or IsCLR);
- if Result then
- begin
- Result := (ImageSectionCount = 0);
- if not Result then
- with ImageSectionHeaders[0] do
- Result := (VirtualAddress <> OptionalHeader.BaseOfCode) or (SizeOfRawData = 0) or
- (OptionalHeader.AddressOfEntryPoint > VirtualAddress + Misc.VirtualSize) or
- (Characteristics and (IMAGE_SCN_CNT_CODE or IMAGE_SCN_MEM_WRITE) <> IMAGE_SCN_CNT_CODE);
- end;
- end;
- begin
- case Target of
- taWin32:
- Result := IsBrokenFormat32;
- taWin64:
- Result := IsBrokenFormat64;
- //taUnknown:
- else
- Result := False; // don't know how to check it
- end;
- end;
- function TJclPeImage.IsCLR: Boolean;
- begin
- Result := DirectoryExists[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR] and CLRHeader.HasMetadata;
- end;
- function TJclPeImage.IsSystemImage: Boolean;
- begin
- Result := StatusOK and FLoadedImage.fSystemImage;
- end;
- class function TJclPeImage.LoadConfigNames(Index: TJclLoadConfig): string;
- begin
- case Index of
- JclLoadConfig_Characteristics:
- Result := LoadResString(@RsPeCharacteristics);
- JclLoadConfig_TimeDateStamp:
- Result := LoadResString(@RsPeTimeDateStamp);
- JclLoadConfig_Version:
- Result := LoadResString(@RsPeVersion);
- JclLoadConfig_GlobalFlagsClear:
- Result := LoadResString(@RsPeGlobalFlagsClear);
- JclLoadConfig_GlobalFlagsSet:
- Result := LoadResString(@RsPeGlobalFlagsSet);
- JclLoadConfig_CriticalSectionDefaultTimeout:
- Result := LoadResString(@RsPeCriticalSectionDefaultTimeout);
- JclLoadConfig_DeCommitFreeBlockThreshold:
- Result := LoadResString(@RsPeDeCommitFreeBlockThreshold);
- JclLoadConfig_DeCommitTotalFreeThreshold:
- Result := LoadResString(@RsPeDeCommitTotalFreeThreshold);
- JclLoadConfig_LockPrefixTable:
- Result := LoadResString(@RsPeLockPrefixTable);
- JclLoadConfig_MaximumAllocationSize:
- Result := LoadResString(@RsPeMaximumAllocationSize);
- JclLoadConfig_VirtualMemoryThreshold:
- Result := LoadResString(@RsPeVirtualMemoryThreshold);
- JclLoadConfig_ProcessHeapFlags:
- Result := LoadResString(@RsPeProcessHeapFlags);
- JclLoadConfig_ProcessAffinityMask:
- Result := LoadResString(@RsPeProcessAffinityMask);
- JclLoadConfig_CSDVersion:
- Result := LoadResString(@RsPeCSDVersion);
- JclLoadConfig_Reserved1:
- Result := LoadResString(@RsPeReserved);
- JclLoadConfig_EditList:
- Result := LoadResString(@RsPeEditList);
- JclLoadConfig_Reserved:
- Result := LoadResString(@RsPeReserved);
- else
- Result := '';
- end;
- end;
- procedure TJclPeImage.RaiseStatusException;
- begin
- if not FNoExceptions then
- case FStatus of
- stNotPE:
- raise EJclPeImageError.CreateRes(@RsPeNotPE);
- stNotFound:
- raise EJclPeImageError.CreateResFmt(@RsPeCantOpen, [FFileName]);
- stNotSupported:
- raise EJclPeImageError.CreateRes(@RsPeUnknownTarget);
- stError:
- RaiseLastOSError;
- end;
- end;
- function TJclPeImage.RawToVa(Raw: DWORD): Pointer;
- begin
- Result := Pointer(TJclAddr(FLoadedImage.MappedAddress) + Raw);
- end;
- procedure TJclPeImage.ReadImageSections;
- var
- I: Integer;
- Header: PImageSectionHeader;
- UTF8Name: TUTF8String;
- SectionName: string;
- begin
- if not StatusOK then
- Exit;
- Header := FLoadedImage.Sections;
- for I := 0 to FLoadedImage.NumberOfSections - 1 do
- begin
- SetLength(UTF8Name, IMAGE_SIZEOF_SHORT_NAME);
- Move(Header.Name[0], UTF8Name[1], IMAGE_SIZEOF_SHORT_NAME * SizeOf(AnsiChar));
- StrResetLength(UTF8Name);
- if not TryUTF8ToString(UTF8Name, SectionName) then
- SectionName := string(UTF8Name);
- FImageSections.AddObject(SectionName, Pointer(Header));
- Inc(Header);
- end;
- end;
- procedure TJclPeImage.ReadStringTable;
- var
- SymbolTable: DWORD;
- StringTablePtr: PAnsiChar;
- Ptr: PAnsiChar;
- ByteSize: ULONG;
- Start: PAnsiChar;
- StringEntry: AnsiString;
- begin
- SymbolTable := LoadedImage.FileHeader.FileHeader.PointerToSymbolTable;
- if SymbolTable = 0 then
- Exit;
- StringTablePtr := PAnsiChar(LoadedImage.MappedAddress) +
- SymbolTable +
- (LoadedImage.FileHeader.FileHeader.NumberOfSymbols * SizeOf(IMAGE_SYMBOL));
- ByteSize := PULONG(StringTablePtr)^;
- Ptr := StringTablePtr + SizeOf(ByteSize);
- while Ptr < StringTablePtr + ByteSize do
- begin
- Start := Ptr;
- while (Ptr^ <> #0) and (Ptr < StringTablePtr + ByteSize) do
- Inc(Ptr);
- if Start <> Ptr then
- begin
- SetLength(StringEntry, Ptr - Start);
- Move(Start^, StringEntry[1], Ptr - Start);
- FStringTable.Add(string(StringEntry));
- end;
- Inc(Ptr); // to skip the #0 character
- end;
- end;
- function TJclPeImage.ResourceItemCreate(AEntry: PImageResourceDirectoryEntry;
- AParentItem: TJclPeResourceItem): TJclPeResourceItem;
- begin
- Result := TJclPeResourceItem.Create(Self, AParentItem, AEntry);
- end;
- function TJclPeImage.ResourceListCreate(ADirectory: PImageResourceDirectory;
- AParentItem: TJclPeResourceItem): TJclPeResourceList;
- begin
- Result := TJclPeResourceList.Create(Self, AParentItem, ADirectory);
- end;
- function TJclPeImage.RvaToSection(Rva: DWORD): PImageSectionHeader;
- var
- I: Integer;
- SectionHeader: PImageSectionHeader;
- EndRVA: DWORD;
- begin
- Result := ImageRvaToSection(FLoadedImage.FileHeader, FLoadedImage.MappedAddress, Rva);
- if Result = nil then
- for I := 0 to FImageSections.Count - 1 do
- begin
- SectionHeader := PImageSectionHeader(FImageSections.Objects[I]);
- if SectionHeader^.SizeOfRawData = 0 then
- EndRVA := SectionHeader^.Misc.VirtualSize
- else
- EndRVA := SectionHeader^.SizeOfRawData;
- Inc(EndRVA, SectionHeader^.VirtualAddress);
- if (SectionHeader^.VirtualAddress <= Rva) and (EndRVA >= Rva) then
- begin
- Result := SectionHeader;
- Break;
- end;
- end;
- end;
- function TJclPeImage.RvaToVa(Rva: DWORD): Pointer;
- begin
- if FAttachedImage then
- Result := Pointer(TJclAddr(FLoadedImage.MappedAddress) + Rva)
- else
- Result := ImageRvaToVa(FLoadedImage.FileHeader, FLoadedImage.MappedAddress, Rva, nil);
- end;
- function TJclPeImage.ImageAddressToRva(Address: DWORD): DWORD;
- var
- ImageBase32: DWORD;
- ImageBase64: Int64;
- begin
- case Target of
- taWin32:
- begin
- ImageBase32 := PImageNtHeaders32(FLoadedImage.FileHeader)^.OptionalHeader.ImageBase;
- Result := Address - ImageBase32;
- end;
- taWin64:
- begin
- ImageBase64 := PImageNtHeaders64(FLoadedImage.FileHeader)^.OptionalHeader.ImageBase;
- Result := DWORD(Address - ImageBase64);
- end;
- //taUnknown:
- else
- Result := 0;
- end;
- end;
- procedure TJclPeImage.SetFileName(const Value: TFileName);
- begin
- if FFileName <> Value then
- begin
- Clear;
- FFileName := Value;
- if FFileName = '' then
- Exit;
- // OF: possible loss of data
- if MapAndLoad(PAnsiChar(AnsiString(FFileName)), nil, FLoadedImage, True, FReadOnlyAccess) then
- begin
- FTarget := PeMapImgTarget(FLoadedImage.MappedAddress);
- if FTarget <> taUnknown then
- begin
- FStatus := stOk;
- ReadImageSections;
- ReadStringTable;
- AfterOpen;
- end
- else
- FStatus := stNotSupported;
- end
- else
- case GetLastError of
- ERROR_SUCCESS:
- FStatus := stNotPE;
- ERROR_FILE_NOT_FOUND:
- FStatus := stNotFound;
- else
- FStatus := stError;
- end;
- RaiseStatusException;
- end;
- end;
- class function TJclPeImage.ShortSectionInfo(Characteristics: DWORD): string;
- type
- TSectionCharacteristics = packed record
- Mask: DWORD;
- InfoChar: Char;
- end;
- const
- Info: array [1..8] of TSectionCharacteristics = (
- (Mask: IMAGE_SCN_CNT_CODE; InfoChar: 'C'),
- (Mask: IMAGE_SCN_MEM_EXECUTE; InfoChar: 'E'),
- (Mask: IMAGE_SCN_MEM_READ; InfoChar: 'R'),
- (Mask: IMAGE_SCN_MEM_WRITE; InfoChar: 'W'),
- (Mask: IMAGE_SCN_CNT_INITIALIZED_DATA; InfoChar: 'I'),
- (Mask: IMAGE_SCN_CNT_UNINITIALIZED_DATA; InfoChar: 'U'),
- (Mask: IMAGE_SCN_MEM_SHARED; InfoChar: 'S'),
- (Mask: IMAGE_SCN_MEM_DISCARDABLE; InfoChar: 'D')
- );
- var
- I: Integer;
- begin
- SetLength(Result, High(Info));
- Result := '';
- for I := Low(Info) to High(Info) do
- with Info[I] do
- if (Characteristics and Mask) = Mask then
- Result := Result + InfoChar;
- end;
- function TJclPeImage.StatusOK: Boolean;
- begin
- Result := (FStatus = stOk);
- end;
- class function TJclPeImage.StampToDateTime(TimeDateStamp: DWORD): TDateTime;
- begin
- Result := TimeDateStamp / SecsPerDay + UnixTimeStart
- end;
- procedure TJclPeImage.TryGetNamesForOrdinalImports;
- begin
- if StatusOK then
- begin
- GetImportList;
- FImportList.TryGetNamesForOrdinalImports;
- end;
- end;
- function TJclPeImage.VerifyCheckSum: Boolean;
- function VerifyCheckSum32: Boolean;
- var
- OptionalHeader: TImageOptionalHeader32;
- begin
- OptionalHeader := OptionalHeader32;
- Result := StatusOK and ((OptionalHeader.CheckSum = 0) or (CalculateCheckSum = OptionalHeader.CheckSum));
- end;
- function VerifyCheckSum64: Boolean;
- var
- OptionalHeader: TImageOptionalHeader64;
- begin
- OptionalHeader := OptionalHeader64;
- Result := StatusOK and ((OptionalHeader.CheckSum = 0) or (CalculateCheckSum = OptionalHeader.CheckSum));
- end;
- begin
- CheckNotAttached;
- case Target of
- taWin32:
- Result := VerifyCheckSum32;
- taWin64:
- Result := VerifyCheckSum64;
- //taUnknown: ;
- else
- Result := True;
- end;
- end;
- {$IFDEF BORLAND}
- //=== { TJclPeBorImagesCache } ===============================================
- function TJclPeBorImagesCache.GetImages(const FileName: TFileName): TJclPeBorImage;
- begin
- Result := TJclPeBorImage(inherited Images[FileName]);
- end;
- function TJclPeBorImagesCache.GetPeImageClass: TJclPeImageClass;
- begin
- Result := TJclPeBorImage;
- end;
- //=== { TJclPePackageInfo } ==================================================
- constructor TJclPePackageInfo.Create(ALibHandle: THandle);
- begin
- FContains := TStringList.Create;
- FRequires := TStringList.Create;
- FEnsureExtension := True;
- FSorted := True;
- ReadPackageInfo(ALibHandle);
- end;
- destructor TJclPePackageInfo.Destroy;
- begin
- FreeAndNil(FContains);
- FreeAndNil(FRequires);
- inherited Destroy;
- end;
- function TJclPePackageInfo.GetContains: TStrings;
- begin
- Result := FContains;
- end;
- function TJclPePackageInfo.GetContainsCount: Integer;
- begin
- Result := Contains.Count;
- end;
- function TJclPePackageInfo.GetContainsFlags(Index: Integer): Byte;
- begin
- Result := Byte(Contains.Objects[Index]);
- end;
- function TJclPePackageInfo.GetContainsNames(Index: Integer): string;
- begin
- Result := Contains[Index];
- end;
- function TJclPePackageInfo.GetRequires: TStrings;
- begin
- Result := FRequires;
- end;
- function TJclPePackageInfo.GetRequiresCount: Integer;
- begin
- Result := Requires.Count;
- end;
- function TJclPePackageInfo.GetRequiresNames(Index: Integer): string;
- begin
- Result := Requires[Index];
- if FEnsureExtension then
- StrEnsureSuffix(BinaryExtensionPackage, Result);
- end;
- class function TJclPePackageInfo.PackageModuleTypeToString(Flags: Cardinal): string;
- begin
- case Flags and pfModuleTypeMask of
- pfExeModule, pfModuleTypeMask:
- Result := LoadResString(@RsPePkgExecutable);
- pfPackageModule:
- Result := LoadResString(@RsPePkgPackage);
- pfLibraryModule:
- Result := LoadResString(@PsPePkgLibrary);
- else
- Result := '';
- end;
- end;
- class function TJclPePackageInfo.PackageOptionsToString(Flags: Cardinal): string;
- begin
- Result := '';
- AddFlagTextRes(Result, @RsPePkgNeverBuild, Flags, pfNeverBuild);
- AddFlagTextRes(Result, @RsPePkgDesignOnly, Flags, pfDesignOnly);
- AddFlagTextRes(Result, @RsPePkgRunOnly, Flags, pfRunOnly);
- AddFlagTextRes(Result, @RsPePkgIgnoreDupUnits, Flags, pfIgnoreDupUnits);
- end;
- class function TJclPePackageInfo.ProducerToString(Flags: Cardinal): string;
- begin
- case Flags and pfProducerMask of
- pfV3Produced:
- Result := LoadResString(@RsPePkgV3Produced);
- pfProducerUndefined:
- Result := LoadResString(@RsPePkgProducerUndefined);
- pfBCB4Produced:
- Result := LoadResString(@RsPePkgBCB4Produced);
- pfDelphi4Produced:
- Result := LoadResString(@RsPePkgDelphi4Produced);
- else
- Result := '';
- end;
- end;
- procedure PackageInfoProc(const Name: string; NameType: TNameType; AFlags: Byte; Param: Pointer);
- begin
- with TJclPePackageInfo(Param) do
- case NameType of
- ntContainsUnit:
- Contains.AddObject(Name, Pointer(AFlags));
- ntRequiresPackage:
- Requires.Add(Name);
- ntDcpBpiName:
- SetDcpName(Name);
- end;
- end;
- procedure TJclPePackageInfo.ReadPackageInfo(ALibHandle: THandle);
- var
- DescrResInfo: HRSRC;
- DescrResData: HGLOBAL;
- begin
- FAvailable := FindResource(ALibHandle, PackageInfoResName, RT_RCDATA) <> 0;
- if FAvailable then
- begin
- GetPackageInfo(ALibHandle, Self, FFlags, PackageInfoProc);
- if FDcpName = '' then
- FDcpName := PathExtractFileNameNoExt(GetModulePath(ALibHandle)) + CompilerExtensionDCP;
- if FSorted then
- begin
- FContains.Sort;
- FRequires.Sort;
- end;
- end;
- DescrResInfo := FindResource(ALibHandle, DescriptionResName, RT_RCDATA);
- if DescrResInfo <> 0 then
- begin
- DescrResData := LoadResource(ALibHandle, DescrResInfo);
- if DescrResData <> 0 then
- begin
- FDescription := WideCharLenToString(LockResource(DescrResData),
- SizeofResource(ALibHandle, DescrResInfo));
- StrResetLength(FDescription);
- end;
- end;
- end;
- procedure TJclPePackageInfo.SetDcpName(const Value: string);
- begin
- FDcpName := Value;
- end;
- class function TJclPePackageInfo.UnitInfoFlagsToString(UnitFlags: Byte): string;
- begin
- Result := '';
- AddFlagTextRes(Result, @RsPePkgMain, UnitFlags, ufMainUnit);
- AddFlagTextRes(Result, @RsPePkgPackage, UnitFlags, ufPackageUnit);
- AddFlagTextRes(Result, @RsPePkgWeak, UnitFlags, ufWeakUnit);
- AddFlagTextRes(Result, @RsPePkgOrgWeak, UnitFlags, ufOrgWeakUnit);
- AddFlagTextRes(Result, @RsPePkgImplicit, UnitFlags, ufImplicitUnit);
- end;
- //=== { TJclPeBorForm } ======================================================
- constructor TJclPeBorForm.Create(AResItem: TJclPeResourceItem;
- AFormFlags: TFilerFlags; AFormPosition: Integer;
- const AFormClassName, AFormObjectName: string);
- begin
- inherited Create;
- FResItem := AResItem;
- FFormFlags := AFormFlags;
- FFormPosition := AFormPosition;
- FFormClassName := AFormClassName;
- FFormObjectName := AFormObjectName;
- end;
- procedure TJclPeBorForm.ConvertFormToText(const Stream: TStream);
- var
- SourceStream: TJclPeResourceRawStream;
- begin
- SourceStream := TJclPeResourceRawStream.Create(ResItem);
- try
- ObjectBinaryToText(SourceStream, Stream);
- finally
- SourceStream.Free;
- end;
- end;
- procedure TJclPeBorForm.ConvertFormToText(const Strings: TStrings);
- var
- TempStream: TMemoryStream;
- begin
- TempStream := TMemoryStream.Create;
- try
- ConvertFormToText(TempStream);
- TempStream.Seek(0, soFromBeginning);
- Strings.LoadFromStream(TempStream);
- finally
- TempStream.Free;
- end;
- end;
- function TJclPeBorForm.GetDisplayName: string;
- begin
- if FFormObjectName <> '' then
- Result := FFormObjectName + ': '
- else
- Result := '';
- Result := Result + FFormClassName;
- end;
- //=== { TJclPeBorImage } =====================================================
- constructor TJclPeBorImage.Create(ANoExceptions: Boolean);
- begin
- FForms := TObjectList.Create(True);
- FPackageInfoSorted := True;
- inherited Create(ANoExceptions);
- end;
- destructor TJclPeBorImage.Destroy;
- begin
- inherited Destroy;
- FreeAndNil(FForms);
- end;
- procedure TJclPeBorImage.AfterOpen;
- var
- HasDVCLAL, HasPACKAGEINFO, HasPACKAGEOPTIONS: Boolean;
- begin
- inherited AfterOpen;
- if StatusOK then
- with ResourceList do
- begin
- HasDVCLAL := (FindResource(rtRCData, DVclAlResName) <> nil);
- HasPACKAGEINFO := (FindResource(rtRCData, PackageInfoResName) <> nil);
- HasPACKAGEOPTIONS := (FindResource(rtRCData, PackageOptionsResName) <> nil);
- FIsPackage := HasPACKAGEINFO and HasPACKAGEOPTIONS;
- FIsBorlandImage := HasDVCLAL or FIsPackage;
- end;
- end;
- procedure TJclPeBorImage.Clear;
- begin
- FForms.Clear;
- FreeAndNil(FPackageInfo);
- FreeLibHandle;
- inherited Clear;
- FIsBorlandImage := False;
- FIsPackage := False;
- FPackageCompilerVersion := 0;
- end;
- procedure TJclPeBorImage.CreateFormsList;
- var
- ResTypeItem: TJclPeResourceItem;
- I: Integer;
- procedure ProcessListItem(DfmResItem: TJclPeResourceItem);
- const
- FilerSignature: array [1..4] of AnsiChar = string('TPF0');
- var
- SourceStream: TJclPeResourceRawStream;
- Reader: TReader;
- FormFlags: TFilerFlags;
- FormPosition: Integer;
- ClassName, FormName: string;
- begin
- SourceStream := TJclPeResourceRawStream.Create(DfmResItem);
- try
- if (SourceStream.Size > SizeOf(FilerSignature)) and
- (PInteger(SourceStream.Memory)^ = Integer(FilerSignature)) then
- begin
- Reader := TReader.Create(SourceStream, 4096);
- try
- Reader.ReadSignature;
- Reader.ReadPrefix(FormFlags, FormPosition);
- ClassName := Reader.ReadStr;
- FormName := Reader.ReadStr;
- FForms.Add(TJclPeBorForm.Create(DfmResItem, FormFlags, FormPosition,
- ClassName, FormName));
- finally
- Reader.Free;
- end;
- end;
- finally
- SourceStream.Free;
- end;
- end;
- begin
- if StatusOK then
- with ResourceList do
- begin
- ResTypeItem := FindResource(rtRCData, '');
- if ResTypeItem <> nil then
- with ResTypeItem.List do
- for I := 0 to Count - 1 do
- ProcessListItem(Items[I].List[0]);
- end;
- end;
- function TJclPeBorImage.DependedPackages(List: TStrings; FullPathName, Descriptions: Boolean): Boolean;
- var
- ImportList: TStringList;
- I: Integer;
- Name: string;
- begin
- Result := IsBorlandImage;
- if not Result then
- Exit;
- ImportList := InternalImportedLibraries(FileName, True, FullPathName, nil);
- List.BeginUpdate;
- try
- for I := 0 to ImportList.Count - 1 do
- begin
- Name := ImportList[I];
- if StrSame(ExtractFileExt(Name), BinaryExtensionPackage) then
- begin
- if Descriptions then
- List.Add(Name + '=' + GetPackageDescription(PChar(Name)))
- else
- List.Add(Name);
- end;
- end;
- finally
- ImportList.Free;
- List.EndUpdate;
- end;
- end;
- function TJclPeBorImage.FreeLibHandle: Boolean;
- begin
- if FLibHandle <> 0 then
- begin
- Result := FreeLibrary(FLibHandle);
- FLibHandle := 0;
- end
- else
- Result := True;
- end;
- function TJclPeBorImage.GetFormCount: Integer;
- begin
- if FForms.Count = 0 then
- CreateFormsList;
- Result := FForms.Count;
- end;
- function TJclPeBorImage.GetFormFromName(const FormClassName: string): TJclPeBorForm;
- var
- I: Integer;
- begin
- Result := nil;
- for I := 0 to FormCount - 1 do
- if StrSame(FormClassName, Forms[I].FormClassName) then
- begin
- Result := Forms[I];
- Break;
- end;
- end;
- function TJclPeBorImage.GetForms(Index: Integer): TJclPeBorForm;
- begin
- Result := TJclPeBorForm(FForms[Index]);
- end;
- function TJclPeBorImage.GetLibHandle: THandle;
- begin
- if StatusOK and (FLibHandle = 0) then
- begin
- FLibHandle := LoadLibraryEx(PChar(FileName), 0, LOAD_LIBRARY_AS_DATAFILE);
- if FLibHandle = 0 then
- RaiseLastOSError;
- end;
- Result := FLibHandle;
- end;
- function TJclPeBorImage.GetPackageCompilerVersion: Integer;
- var
- I: Integer;
- ImportName: string;
- function CheckName: Boolean;
- begin
- Result := False;
- ImportName := AnsiUpperCase(ImportName);
- if StrSame(ExtractFileExt(ImportName), BinaryExtensionPackage) then
- begin
- ImportName := PathExtractFileNameNoExt(ImportName);
- if (Length(ImportName) = 5) and
- CharIsDigit(ImportName[4]) and CharIsDigit(ImportName[5]) and
- ((Pos('RTL', ImportName) = 1) or (Pos('VCL', ImportName) = 1)) then
- begin
- FPackageCompilerVersion := StrToIntDef(Copy(ImportName, 4, 2), 0);
- Result := True;
- end;
- end;
- end;
- begin
- if (FPackageCompilerVersion = 0) and IsPackage then
- begin
- with ImportList do
- for I := 0 to UniqueLibItemCount - 1 do
- begin
- ImportName := UniqueLibNames[I];
- if CheckName then
- Break;
- end;
- if FPackageCompilerVersion = 0 then
- begin
- ImportName := ExtractFileName(FileName);
- CheckName;
- end;
- end;
- Result := FPackageCompilerVersion;
- end;
- function TJclPeBorImage.GetPackageInfo: TJclPePackageInfo;
- begin
- if StatusOK and (FPackageInfo = nil) then
- begin
- GetLibHandle;
- FPackageInfo := TJclPePackageInfo.Create(FLibHandle);
- FPackageInfo.Sorted := FPackageInfoSorted;
- FreeLibHandle;
- end;
- Result := FPackageInfo;
- end;
- {$ENDIF BORLAND}
- //=== { TJclPeNameSearch } ===================================================
- constructor TJclPeNameSearch.Create(const FunctionName, Path: string; Options: TJclPeNameSearchOptions);
- begin
- inherited Create(True);
- FFunctionName := FunctionName;
- FOptions := Options;
- FPath := Path;
- FreeOnTerminate := True;
- end;
- function TJclPeNameSearch.CompareName(const FunctionName, ComparedName: string): Boolean;
- begin
- Result := PeSmartFunctionNameSame(ComparedName, FunctionName, [scIgnoreCase]);
- end;
- procedure TJclPeNameSearch.DoFound;
- begin
- if Assigned(FOnFound) then
- FOnFound(Self, F_FileName, F_FunctionName, F_Option);
- end;
- procedure TJclPeNameSearch.DoProcessFile;
- begin
- if Assigned(FOnProcessFile) then
- FOnProcessFile(Self, FPeImage, F_Process);
- end;
- procedure TJclPeNameSearch.Execute;
- var
- PathList: TStringList;
- I: Integer;
- function CompareNameAndNotify(const S: string): Boolean;
- begin
- Result := CompareName(S, FFunctionName);
- if Result and not Terminated then
- begin
- F_FunctionName := S;
- Synchronize(DoFound);
- end;
- end;
- procedure ProcessDirectorySearch(const DirName: string);
- var
- Se: TSearchRec;
- SearchResult: Integer;
- ImportList: TJclPeImportList;
- ExportList: TJclPeExportFuncList;
- I: Integer;
- begin
- SearchResult := FindFirst(DirName, faArchive + faReadOnly, Se);
- try
- while not Terminated and (SearchResult = 0) do
- begin
- F_FileName := PathAddSeparator(ExtractFilePath(DirName)) + Se.Name;
- F_Process := True;
- FPeImage.FileName := F_FileName;
- if Assigned(FOnProcessFile) then
- Synchronize(DoProcessFile);
- if F_Process and FPeImage.StatusOK then
- begin
- if seExports in FOptions then
- begin
- ExportList := FPeImage.ExportList;
- F_Option := seExports;
- for I := 0 to ExportList.Count - 1 do
- begin
- if Terminated then
- Break;
- CompareNameAndNotify(ExportList[I].Name);
- end;
- end;
- if FOptions * [seImports, seDelayImports, seBoundImports] <> [] then
- begin
- ImportList := FPeImage.ImportList;
- FPeImage.TryGetNamesForOrdinalImports;
- for I := 0 to ImportList.AllItemCount - 1 do
- with ImportList.AllItems[I] do
- begin
- if Terminated then
- Break;
- case ImportLib.ImportKind of
- ikImport:
- if seImports in FOptions then
- begin
- F_Option := seImports;
- CompareNameAndNotify(Name);
- end;
- ikDelayImport:
- if seDelayImports in FOptions then
- begin
- F_Option := seDelayImports;
- CompareNameAndNotify(Name);
- end;
- ikBoundImport:
- if seDelayImports in FOptions then
- begin
- F_Option := seBoundImports;
- CompareNameAndNotify(Name);
- end;
- end;
- end;
- end;
- end;
- SearchResult := FindNext(Se);
- end;
- finally
- FindClose(Se);
- end;
- end;
- begin
- FPeImage := TJclPeImage.Create(True);
- PathList := TStringList.Create;
- try
- PathList.Sorted := True;
- PathList.Duplicates := dupIgnore;
- StrToStrings(FPath, ';', PathList);
- for I := 0 to PathList.Count - 1 do
- ProcessDirectorySearch(PathAddSeparator(Trim(PathList[I])) + '*.*');
- finally
- PathList.Free;
- FPeImage.Free;
- end;
- end;
- procedure TJclPeNameSearch.Start;
- begin
- {$IFDEF RTL210_UP}
- Suspended := False;
- {$ELSE ~RTL210_UP}
- Resume;
- {$ENDIF ~RTL210_UP}
- end;
- //=== PE Image miscellaneous functions =======================================
- function IsValidPeFile(const FileName: TFileName): Boolean;
- var
- NtHeaders: TImageNtHeaders32;
- begin
- Result := PeGetNtHeaders32(FileName, NtHeaders);
- end;
- function InternalGetNtHeaders32(const FileName: TFileName; out NtHeaders): Boolean;
- var
- FileHandle: THandle;
- Mapping: TJclFileMapping;
- View: TJclFileMappingView;
- HeadersPtr: PImageNtHeaders32;
- begin
- Result := False;
- ResetMemory(NtHeaders, SizeOf(TImageNtHeaders32));
- FileHandle := FileOpen(FileName, fmOpenRead or fmShareDenyWrite);
- if FileHandle = INVALID_HANDLE_VALUE then
- Exit;
- try
- if GetSizeOfFile(FileHandle) >= SizeOf(TImageDosHeader) then
- begin
- Mapping := TJclFileMapping.Create(FileHandle, '', PAGE_READONLY, 0, nil);
- try
- View := TJclFileMappingView.Create(Mapping, FILE_MAP_READ, 0, 0);
- HeadersPtr := PeMapImgNtHeaders32(View.Memory);
- if HeadersPtr <> nil then
- begin
- Result := True;
- TImageNtHeaders32(NtHeaders) := HeadersPtr^;
- end;
- finally
- Mapping.Free;
- end;
- end;
- finally
- FileClose(FileHandle);
- end;
- end;
- function PeGetNtHeaders32(const FileName: TFileName; out NtHeaders: TImageNtHeaders32): Boolean;
- begin
- Result := InternalGetNtHeaders32(FileName, NtHeaders);
- end;
- function PeGetNtHeaders64(const FileName: TFileName; out NtHeaders: TImageNtHeaders64): Boolean;
- var
- FileHandle: THandle;
- Mapping: TJclFileMapping;
- View: TJclFileMappingView;
- HeadersPtr: PImageNtHeaders64;
- begin
- Result := False;
- ResetMemory(NtHeaders, SizeOf(NtHeaders));
- FileHandle := FileOpen(FileName, fmOpenRead or fmShareDenyWrite);
- if FileHandle = INVALID_HANDLE_VALUE then
- Exit;
- try
- if GetSizeOfFile(FileHandle) >= SizeOf(TImageDosHeader) then
- begin
- Mapping := TJclFileMapping.Create(FileHandle, '', PAGE_READONLY, 0, nil);
- try
- View := TJclFileMappingView.Create(Mapping, FILE_MAP_READ, 0, 0);
- HeadersPtr := PeMapImgNtHeaders64(View.Memory);
- if HeadersPtr <> nil then
- begin
- Result := True;
- NtHeaders := HeadersPtr^;
- end;
- finally
- Mapping.Free;
- end;
- end;
- finally
- FileClose(FileHandle);
- end;
- end;
- function PeCreateNameHintTable(const FileName: TFileName): Boolean;
- var
- PeImage, ExportsImage: TJclPeImage;
- I: Integer;
- ImportItem: TJclPeImportLibItem;
- Thunk32: PImageThunkData32;
- Thunk64: PImageThunkData64;
- OrdinalName: PImageImportByName;
- ExportItem: TJclPeExportFuncItem;
- Cache: TJclPeImagesCache;
- ImageBase32: TJclAddr32;
- ImageBase64: TJclAddr64;
- UTF8Name: TUTF8String;
- ExportName: string;
- begin
- Cache := TJclPeImagesCache.Create;
- try
- PeImage := TJclPeImage.Create(False);
- try
- PeImage.ReadOnlyAccess := False;
- PeImage.FileName := FileName;
- Result := PeImage.ImportList.Count > 0;
- for I := 0 to PeImage.ImportList.Count - 1 do
- begin
- ImportItem := PeImage.ImportList[I];
- if ImportItem.ImportKind = ikBoundImport then
- Continue;
- ExportsImage := Cache[ImportItem.FileName];
- ExportsImage.ExportList.PrepareForFastNameSearch;
- case PEImage.Target of
- taWin32:
- begin
- Thunk32 := ImportItem.ThunkData32;
- ImageBase32 := PeImage.OptionalHeader32.ImageBase;
- while Thunk32^.Function_ <> 0 do
- begin
- if Thunk32^.Ordinal and IMAGE_ORDINAL_FLAG32 = 0 then
- begin
- case ImportItem.ImportKind of
- ikImport:
- OrdinalName := PImageImportByName(PeImage.RvaToVa(Thunk32^.AddressOfData));
- ikDelayImport:
- OrdinalName := PImageImportByName(PeImage.RvaToVa(Thunk32^.AddressOfData - ImageBase32));
- else
- OrdinalName := nil;
- end;
- UTF8Name := PAnsiChar(@OrdinalName.Name);
- if not TryUTF8ToString(UTF8Name, ExportName) then
- ExportName := string(UTF8Name);
- ExportItem := ExportsImage.ExportList.ItemFromName[ExportName];
- if ExportItem <> nil then
- OrdinalName.Hint := ExportItem.Hint
- else
- OrdinalName.Hint := 0;
- end;
- Inc(Thunk32);
- end;
- end;
- taWin64:
- begin
- Thunk64 := ImportItem.ThunkData64;
- ImageBase64 := PeImage.OptionalHeader64.ImageBase;
- while Thunk64^.Function_ <> 0 do
- begin
- if Thunk64^.Ordinal and IMAGE_ORDINAL_FLAG64 = 0 then
- begin
- case ImportItem.ImportKind of
- ikImport:
- OrdinalName := PImageImportByName(PeImage.RvaToVa(Thunk64^.AddressOfData));
- ikDelayImport:
- OrdinalName := PImageImportByName(PeImage.RvaToVa(Thunk64^.AddressOfData - ImageBase64));
- else
- OrdinalName := nil;
- end;
- UTF8Name := PAnsiChar(@OrdinalName.Name);
- if not TryUTF8ToString(UTF8Name, ExportName) then
- ExportName := string(UTF8Name);
- ExportItem := ExportsImage.ExportList.ItemFromName[ExportName];
- if ExportItem <> nil then
- OrdinalName.Hint := ExportItem.Hint
- else
- OrdinalName.Hint := 0;
- end;
- Inc(Thunk64);
- end;
- end;
- end;
- end;
- finally
- PeImage.Free;
- end;
- finally
- Cache.Free;
- end;
- end;
- function PeRebaseImage32(const ImageName: TFileName; NewBase: TJclAddr32;
- TimeStamp, MaxNewSize: DWORD): TJclRebaseImageInfo32;
- function CalculateBaseAddress: TJclAddr32;
- var
- FirstChar: Char;
- ModuleName: string;
- begin
- ModuleName := ExtractFileName(ImageName);
- if Length(ModuleName) > 0 then
- FirstChar := UpCase(ModuleName[1])
- else
- FirstChar := NativeNull;
- if not CharIsUpper(FirstChar) then
- FirstChar := 'A';
- Result := $60000000 + (((Ord(FirstChar) - Ord('A')) div 3) * $1000000);
- end;
- {$IFDEF CPU64}
- {$IFNDEF DELPHI64_TEMPORARY}
- var
- NewIB, OldIB: QWord;
- {$ENDIF CPU64}
- {$ENDIF ~DELPHI64_TEMPORARY}
- begin
- if NewBase = 0 then
- NewBase := CalculateBaseAddress;
- with Result do
- begin
- NewImageBase := NewBase;
- // OF: possible loss of data
- {$IFDEF CPU32}
- Win32Check(ReBaseImage(PAnsiChar(AnsiString(ImageName)), nil, True, False, False, MaxNewSize,
- OldImageSize, OldImageBase, NewImageSize, NewImageBase, TimeStamp));
- {$ENDIF CPU32}
- {$IFDEF CPU64}
- {$IFDEF DELPHI64_TEMPORARY}
- System.Error(rePlatformNotImplemented);
- {$ELSE ~DELPHI64_TEMPORARY}
- NewIB := NewImageBase;
- OldIB := OldImageBase;
- Win32Check(ReBaseImage(PAnsiChar(AnsiString(ImageName)), nil, True, False, False, MaxNewSize,
- OldImageSize, OldIB, NewImageSize, NewIB, TimeStamp));
- NewImageBase := NewIB;
- OldImageBase := OldIB;
- {$ENDIF ~DELPHI64_TEMPORARY}
- {$ENDIF CPU64}
- end;
- end;
- function PeRebaseImage64(const ImageName: TFileName; NewBase: TJclAddr64;
- TimeStamp, MaxNewSize: DWORD): TJclRebaseImageInfo64;
- function CalculateBaseAddress: TJclAddr64;
- var
- FirstChar: Char;
- ModuleName: string;
- begin
- ModuleName := ExtractFileName(ImageName);
- if Length(ModuleName) > 0 then
- FirstChar := UpCase(ModuleName[1])
- else
- FirstChar := NativeNull;
- if not CharIsUpper(FirstChar) then
- FirstChar := 'A';
- Result := $60000000 + (((Ord(FirstChar) - Ord('A')) div 3) * $1000000);
- Result := Result shl 32;
- end;
- begin
- if NewBase = 0 then
- NewBase := CalculateBaseAddress;
- with Result do
- begin
- NewImageBase := NewBase;
- // OF: possible loss of data
- Win32Check(ReBaseImage64(PAnsiChar(AnsiString(ImageName)), nil, True, False, False, MaxNewSize,
- OldImageSize, OldImageBase, NewImageSize, NewImageBase, TimeStamp));
- end;
- end;
- function PeUpdateLinkerTimeStamp(const FileName: TFileName; const Time: TDateTime): Boolean;
- var
- Mapping: TJclFileMapping;
- View: TJclFileMappingView;
- Headers: PImageNtHeaders32; // works with 64-bit binaries too
- // only the optional field differs
- begin
- Mapping := TJclFileMapping.Create(FileName, fmOpenReadWrite, '', PAGE_READWRITE, 0, nil);
- try
- View := TJclFileMappingView.Create(Mapping, FILE_MAP_WRITE, 0, 0);
- Headers := PeMapImgNtHeaders32(View.Memory);
- Result := (Headers <> nil);
- if Result then
- Headers^.FileHeader.TimeDateStamp := TJclPeImage.DateTimeToStamp(Time);
- finally
- Mapping.Free;
- end;
- end;
- function PeReadLinkerTimeStamp(const FileName: TFileName): TDateTime;
- var
- Mapping: TJclFileMappingStream;
- Headers: PImageNtHeaders32; // works with 64-bit binaries too
- // only the optional field differs
- begin
- Mapping := TJclFileMappingStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
- try
- Headers := PeMapImgNtHeaders32(Mapping.Memory);
- if Headers <> nil then
- Result := TJclPeImage.StampToDateTime(Headers^.FileHeader.TimeDateStamp)
- else
- Result := -1;
- finally
- Mapping.Free;
- end;
- end;
- { TODO -cHelp : Author: Uwe Schuster(just a generic version of JclDebug.InsertDebugDataIntoExecutableFile) }
- function PeInsertSection(const FileName: TFileName; SectionStream: TStream; SectionName: string): Boolean;
- procedure RoundUpToAlignment(var Value: DWORD; Alignment: DWORD);
- begin
- if (Value mod Alignment) <> 0 then
- Value := ((Value div Alignment) + 1) * Alignment;
- end;
- function PeInsertSection32(ImageStream: TMemoryStream): Boolean;
- var
- NtHeaders: PImageNtHeaders32;
- Sections, LastSection, NewSection: PImageSectionHeader;
- VirtualAlignedSize: DWORD;
- I, X, NeedFill: Integer;
- SectionDataSize: Integer;
- UTF8Name: TUTF8String;
- begin
- Result := True;
- try
- SectionDataSize := SectionStream.Size;
- NtHeaders := PeMapImgNtHeaders32(ImageStream.Memory);
- Assert(NtHeaders <> nil);
- Sections := PeMapImgSections32(NtHeaders);
- Assert(Sections <> nil);
- // Check whether there is not a section with the name already. If so, return True (#0000069)
- if PeMapImgFindSection32(NtHeaders, SectionName) <> nil then
- begin
- Result := True;
- Exit;
- end;
- LastSection := Sections;
- Inc(LastSection, NtHeaders^.FileHeader.NumberOfSections - 1);
- NewSection := LastSection;
- Inc(NewSection);
- // Increase the number of sections
- Inc(NtHeaders^.FileHeader.NumberOfSections);
- ResetMemory(NewSection^, SizeOf(TImageSectionHeader));
- // JCLDEBUG Virtual Address
- NewSection^.VirtualAddress := LastSection^.VirtualAddress + LastSection^.Misc.VirtualSize;
- RoundUpToAlignment(NewSection^.VirtualAddress, NtHeaders^.OptionalHeader.SectionAlignment);
- // JCLDEBUG Physical Offset
- NewSection^.PointerToRawData := LastSection^.PointerToRawData + LastSection^.SizeOfRawData;
- RoundUpToAlignment(NewSection^.PointerToRawData, NtHeaders^.OptionalHeader.FileAlignment);
- // JCLDEBUG Section name
- if not TryStringToUTF8(SectionName, UTF8Name) then
- UTF8Name := TUTF8String(SectionName);
- StrPLCopyA(PAnsiChar(@NewSection^.Name), UTF8Name, IMAGE_SIZEOF_SHORT_NAME);
- // JCLDEBUG Characteristics flags
- NewSection^.Characteristics := IMAGE_SCN_MEM_READ or IMAGE_SCN_CNT_INITIALIZED_DATA;
- // Size of virtual data area
- NewSection^.Misc.VirtualSize := SectionDataSize;
- VirtualAlignedSize := SectionDataSize;
- RoundUpToAlignment(VirtualAlignedSize, NtHeaders^.OptionalHeader.SectionAlignment);
- // Update Size of Image
- Inc(NtHeaders^.OptionalHeader.SizeOfImage, VirtualAlignedSize);
- // Raw data size
- NewSection^.SizeOfRawData := SectionDataSize;
- RoundUpToAlignment(NewSection^.SizeOfRawData, NtHeaders^.OptionalHeader.FileAlignment);
- // Update Initialized data size
- Inc(NtHeaders^.OptionalHeader.SizeOfInitializedData, NewSection^.SizeOfRawData);
- // Fill data to alignment
- NeedFill := INT_PTR(NewSection^.SizeOfRawData) - SectionDataSize;
- // Note: Delphi linker seems to generate incorrect (unaligned) size of
- // the executable when adding TD32 debug data so the position could be
- // behind the size of the file then.
- ImageStream.Seek(NewSection^.PointerToRawData, soBeginning);
- ImageStream.CopyFrom(SectionStream, 0);
- X := 0;
- for I := 1 to NeedFill do
- ImageStream.WriteBuffer(X, 1);
- except
- Result := False;
- end;
- end;
- function PeInsertSection64(ImageStream: TMemoryStream): Boolean;
- var
- NtHeaders: PImageNtHeaders64;
- Sections, LastSection, NewSection: PImageSectionHeader;
- VirtualAlignedSize: DWORD;
- I, X, NeedFill: Integer;
- SectionDataSize: Integer;
- UTF8Name: TUTF8String;
- begin
- Result := True;
- try
- SectionDataSize := SectionStream.Size;
- NtHeaders := PeMapImgNtHeaders64(ImageStream.Memory);
- Assert(NtHeaders <> nil);
- Sections := PeMapImgSections64(NtHeaders);
- Assert(Sections <> nil);
- // Check whether there is not a section with the name already. If so, return True (#0000069)
- if PeMapImgFindSection64(NtHeaders, SectionName) <> nil then
- begin
- Result := True;
- Exit;
- end;
- LastSection := Sections;
- Inc(LastSection, NtHeaders^.FileHeader.NumberOfSections - 1);
- NewSection := LastSection;
- Inc(NewSection);
- // Increase the number of sections
- Inc(NtHeaders^.FileHeader.NumberOfSections);
- ResetMemory(NewSection^, SizeOf(TImageSectionHeader));
- // JCLDEBUG Virtual Address
- NewSection^.VirtualAddress := LastSection^.VirtualAddress + LastSection^.Misc.VirtualSize;
- RoundUpToAlignment(NewSection^.VirtualAddress, NtHeaders^.OptionalHeader.SectionAlignment);
- // JCLDEBUG Physical Offset
- NewSection^.PointerToRawData := LastSection^.PointerToRawData + LastSection^.SizeOfRawData;
- RoundUpToAlignment(NewSection^.PointerToRawData, NtHeaders^.OptionalHeader.FileAlignment);
- // JCLDEBUG Section name
- if not TryStringToUTF8(SectionName, UTF8Name) then
- UTF8Name := TUTF8String(SectionName);
- StrPLCopyA(PAnsiChar(@NewSection^.Name), UTF8Name, IMAGE_SIZEOF_SHORT_NAME);
- // JCLDEBUG Characteristics flags
- NewSection^.Characteristics := IMAGE_SCN_MEM_READ or IMAGE_SCN_CNT_INITIALIZED_DATA;
- // Size of virtual data area
- NewSection^.Misc.VirtualSize := SectionDataSize;
- VirtualAlignedSize := SectionDataSize;
- RoundUpToAlignment(VirtualAlignedSize, NtHeaders^.OptionalHeader.SectionAlignment);
- // Update Size of Image
- Inc(NtHeaders^.OptionalHeader.SizeOfImage, VirtualAlignedSize);
- // Raw data size
- NewSection^.SizeOfRawData := SectionDataSize;
- RoundUpToAlignment(NewSection^.SizeOfRawData, NtHeaders^.OptionalHeader.FileAlignment);
- // Update Initialized data size
- Inc(NtHeaders^.OptionalHeader.SizeOfInitializedData, NewSection^.SizeOfRawData);
- // Fill data to alignment
- NeedFill := INT_PTR(NewSection^.SizeOfRawData) - SectionDataSize;
- // Note: Delphi linker seems to generate incorrect (unaligned) size of
- // the executable when adding TD32 debug data so the position could be
- // behind the size of the file then.
- ImageStream.Seek(NewSection^.PointerToRawData, soBeginning);
- ImageStream.CopyFrom(SectionStream, 0);
- X := 0;
- for I := 1 to NeedFill do
- ImageStream.WriteBuffer(X, 1);
- except
- Result := False;
- end;
- end;
- var
- ImageStream: TMemoryStream;
- begin
- Result := Assigned(SectionStream) and (SectionName <> '');
- if not Result then
- Exit;
- ImageStream := TMemoryStream.Create;
- try
- ImageStream.LoadFromFile(FileName);
- case PeMapImgTarget(ImageStream.Memory) of
- taWin32:
- Result := PeInsertSection32(ImageStream);
- taWin64:
- Result := PeInsertSection64(ImageStream);
- //taUnknown:
- else
- Result := False;
- end;
- if Result then
- ImageStream.SaveToFile(FileName);
- finally
- ImageStream.Free;
- end;
- end;
- function PeVerifyCheckSum(const FileName: TFileName): Boolean;
- begin
- with CreatePeImage(FileName) do
- try
- Result := VerifyCheckSum;
- finally
- Free;
- end;
- end;
- function PeClearCheckSum(const FileName: TFileName): Boolean;
- function PeClearCheckSum32(ModuleAddress: Pointer): Boolean;
- var
- Headers: PImageNtHeaders32;
- begin
- Headers := PeMapImgNtHeaders32(ModuleAddress);
- Result := (Headers <> nil);
- if Result then
- Headers^.OptionalHeader.CheckSum := 0;
- end;
- function PeClearCheckSum64(ModuleAddress: Pointer): Boolean;
- var
- Headers: PImageNtHeaders64;
- begin
- Headers := PeMapImgNtHeaders64(ModuleAddress);
- Result := (Headers <> nil);
- if Result then
- Headers^.OptionalHeader.CheckSum := 0;
- end;
- var
- Mapping: TJclFileMapping;
- View: TJclFileMappingView;
- begin
- Mapping := TJclFileMapping.Create(FileName, fmOpenReadWrite, '', PAGE_READWRITE, 0, nil);
- try
- View := TJclFileMappingView.Create(Mapping, FILE_MAP_WRITE, 0, 0);
- case PeMapImgTarget(View.Memory) of
- taWin32:
- Result := PeClearCheckSum32(View.Memory);
- taWin64:
- Result := PeClearCheckSum64(View.Memory);
- //taUnknown:
- else
- Result := False;
- end;
- finally
- Mapping.Free;
- end;
- end;
- function PeUpdateCheckSum(const FileName: TFileName): Boolean;
- var
- LI: TLoadedImage;
- begin
- LI.ModuleName := nil;
- // OF: possible loss of data
- Result := MapAndLoad(PAnsiChar(AnsiString(FileName)), nil, LI, True, False);
- if Result then
- Result := UnMapAndLoad(LI);
- end;
- // Various simple PE Image searching and listing routines
- function PeDoesExportFunction(const FileName: TFileName; const FunctionName: string;
- Options: TJclSmartCompOptions): Boolean;
- begin
- with CreatePeImage(FileName) do
- try
- Result := StatusOK and Assigned(ExportList.SmartFindName(FunctionName, Options));
- finally
- Free;
- end;
- end;
- function PeIsExportFunctionForwardedEx(const FileName: TFileName; const FunctionName: string;
- out ForwardedName: string; Options: TJclSmartCompOptions): Boolean;
- var
- ExportItem: TJclPeExportFuncItem;
- begin
- with CreatePeImage(FileName) do
- try
- Result := StatusOK;
- if Result then
- begin
- ExportItem := ExportList.SmartFindName(FunctionName, Options);
- if ExportItem <> nil then
- begin
- Result := ExportItem.IsForwarded;
- ForwardedName := ExportItem.ForwardedName;
- end
- else
- begin
- Result := False;
- ForwardedName := '';
- end;
- end;
- finally
- Free;
- end;
- end;
- function PeIsExportFunctionForwarded(const FileName: TFileName; const FunctionName: string;
- Options: TJclSmartCompOptions): Boolean;
- var
- Dummy: string;
- begin
- Result := PeIsExportFunctionForwardedEx(FileName, FunctionName, Dummy, Options);
- end;
- function PeDoesImportFunction(const FileName: TFileName; const FunctionName: string;
- const LibraryName: string; Options: TJclSmartCompOptions): Boolean;
- begin
- with CreatePeImage(FileName) do
- try
- Result := StatusOK;
- if Result then
- with ImportList do
- begin
- TryGetNamesForOrdinalImports;
- Result := SmartFindName(FunctionName, LibraryName, Options) <> nil;
- end;
- finally
- Free;
- end;
- end;
- function PeDoesImportLibrary(const FileName: TFileName; const LibraryName: string;
- Recursive: Boolean): Boolean;
- var
- SL: TStringList;
- begin
- with CreatePeImage(FileName) do
- try
- Result := StatusOK;
- if Result then
- begin
- SL := InternalImportedLibraries(FileName, Recursive, False, nil);
- try
- Result := SL.IndexOf(LibraryName) > -1;
- finally
- SL.Free;
- end;
- end;
- finally
- Free;
- end;
- end;
- function PeImportedLibraries(const FileName: TFileName; const LibrariesList: TStrings;
- Recursive, FullPathName: Boolean): Boolean;
- var
- SL: TStringList;
- begin
- with CreatePeImage(FileName) do
- try
- Result := StatusOK;
- if Result then
- begin
- SL := InternalImportedLibraries(FileName, Recursive, FullPathName, nil);
- try
- LibrariesList.Assign(SL);
- finally
- SL.Free;
- end;
- end;
- finally
- Free;
- end;
- end;
- function PeImportedFunctions(const FileName: TFileName; const FunctionsList: TStrings;
- const LibraryName: string; IncludeLibNames: Boolean): Boolean;
- var
- I: Integer;
- begin
- with CreatePeImage(FileName) do
- try
- Result := StatusOK;
- if Result then
- with ImportList do
- begin
- TryGetNamesForOrdinalImports;
- FunctionsList.BeginUpdate;
- try
- for I := 0 to AllItemCount - 1 do
- with AllItems[I] do
- if ((Length(LibraryName) = 0) or StrSame(ImportLib.Name, LibraryName)) and
- (Name <> '') then
- begin
- if IncludeLibNames then
- FunctionsList.Add(ImportLib.Name + '=' + Name)
- else
- FunctionsList.Add(Name);
- end;
- finally
- FunctionsList.EndUpdate;
- end;
- end;
- finally
- Free;
- end;
- end;
- function PeExportedFunctions(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
- var
- I: Integer;
- begin
- with CreatePeImage(FileName) do
- try
- Result := StatusOK;
- if Result then
- begin
- FunctionsList.BeginUpdate;
- try
- with ExportList do
- for I := 0 to Count - 1 do
- with Items[I] do
- if not IsExportedVariable then
- FunctionsList.Add(Name);
- finally
- FunctionsList.EndUpdate;
- end;
- end;
- finally
- Free;
- end;
- end;
- function PeExportedNames(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
- var
- I: Integer;
- begin
- with CreatePeImage(FileName) do
- try
- Result := StatusOK;
- if Result then
- begin
- FunctionsList.BeginUpdate;
- try
- with ExportList do
- for I := 0 to Count - 1 do
- FunctionsList.Add(Items[I].Name);
- finally
- FunctionsList.EndUpdate;
- end;
- end;
- finally
- Free;
- end;
- end;
- function PeExportedVariables(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
- var
- I: Integer;
- begin
- with CreatePeImage(FileName) do
- try
- Result := StatusOK;
- if Result then
- begin
- FunctionsList.BeginUpdate;
- try
- with ExportList do
- for I := 0 to Count - 1 do
- with Items[I] do
- if IsExportedVariable then
- FunctionsList.AddObject(Name, Pointer(Address));
- finally
- FunctionsList.EndUpdate;
- end;
- end;
- finally
- Free;
- end;
- end;
- function PeResourceKindNames(const FileName: TFileName; ResourceType: TJclPeResourceKind;
- const NamesList: TStrings): Boolean;
- begin
- with CreatePeImage(FileName) do
- try
- Result := StatusOK and ResourceList.ListResourceNames(ResourceType, NamesList);
- finally
- Free;
- end;
- end;
- {$IFDEF BORLAND}
- function PeBorFormNames(const FileName: TFileName; const NamesList: TStrings): Boolean;
- var
- I: Integer;
- BorImage: TJclPeBorImage;
- BorForm: TJclPeBorForm;
- begin
- BorImage := TJclPeBorImage.Create(True);
- try
- BorImage.FileName := FileName;
- Result := BorImage.IsBorlandImage;
- if Result then
- begin
- NamesList.BeginUpdate;
- try
- for I := 0 to BorImage.FormCount - 1 do
- begin
- BorForm := BorImage.Forms[I];
- NamesList.AddObject(BorForm.DisplayName, Pointer(BorForm.ResItem.RawEntryDataSize));
- end;
- finally
- NamesList.EndUpdate;
- end;
- end;
- finally
- BorImage.Free;
- end;
- end;
- function PeBorDependedPackages(const FileName: TFileName; PackagesList: TStrings;
- FullPathName, Descriptions: Boolean): Boolean;
- var
- BorImage: TJclPeBorImage;
- begin
- BorImage := TJclPeBorImage.Create(True);
- try
- BorImage.FileName := FileName;
- Result := BorImage.DependedPackages(PackagesList, FullPathName, Descriptions);
- finally
- BorImage.Free;
- end;
- end;
- {$ENDIF BORLAND}
- // Missing imports checking routines
- function PeFindMissingImports(const FileName: TFileName; MissingImportsList: TStrings): Boolean;
- var
- Cache: TJclPeImagesCache;
- FileImage, LibImage: TJclPeImage;
- L, I: Integer;
- LibItem: TJclPeImportLibItem;
- List: TStringList;
- begin
- Result := False;
- List := nil;
- Cache := TJclPeImagesCache.Create;
- try
- List := TStringList.Create;
- List.Duplicates := dupIgnore;
- List.Sorted := True;
- FileImage := Cache[FileName];
- if FileImage.StatusOK then
- begin
- for L := 0 to FileImage.ImportList.Count - 1 do
- begin
- LibItem := FileImage.ImportList[L];
- LibImage := Cache[LibItem.FileName];
- if LibImage.StatusOK then
- begin
- LibImage.ExportList.PrepareForFastNameSearch;
- for I := 0 to LibItem.Count - 1 do
- if LibImage.ExportList.ItemFromName[LibItem[I].Name] = nil then
- List.Add(LibItem.Name + '=' + LibItem[I].Name);
- end
- else
- List.Add(LibItem.Name + '=');
- end;
- MissingImportsList.Assign(List);
- Result := List.Count > 0;
- end;
- finally
- List.Free;
- Cache.Free;
- end;
- end;
- function PeFindMissingImports(RequiredImportsList, MissingImportsList: TStrings): Boolean;
- var
- Cache: TJclPeImagesCache;
- LibImage: TJclPeImage;
- I, SepPos: Integer;
- List: TStringList;
- S, LibName, ImportName: string;
- begin
- List := nil;
- Cache := TJclPeImagesCache.Create;
- try
- List := TStringList.Create;
- List.Duplicates := dupIgnore;
- List.Sorted := True;
- for I := 0 to RequiredImportsList.Count - 1 do
- begin
- S := RequiredImportsList[I];
- SepPos := Pos('=', S);
- if SepPos = 0 then
- Continue;
- LibName := StrLeft(S, SepPos - 1);
- LibImage := Cache[LibName];
- if LibImage.StatusOK then
- begin
- LibImage.ExportList.PrepareForFastNameSearch;
- ImportName := StrRestOf(S, SepPos + 1);
- if LibImage.ExportList.ItemFromName[ImportName] = nil then
- List.Add(LibName + '=' + ImportName);
- end
- else
- List.Add(LibName + '=');
- end;
- MissingImportsList.Assign(List);
- Result := List.Count > 0;
- finally
- List.Free;
- Cache.Free;
- end;
- end;
- function PeCreateRequiredImportList(const FileName: TFileName; RequiredImportsList: TStrings): Boolean;
- begin
- Result := PeImportedFunctions(FileName, RequiredImportsList, '', True);
- end;
- // Mapped or loaded image related functions
- function PeMapImgNtHeaders32(const BaseAddress: Pointer): PImageNtHeaders32;
- begin
- Result := nil;
- if IsBadReadPtr(BaseAddress, SizeOf(TImageDosHeader)) then
- Exit;
- if (PImageDosHeader(BaseAddress)^.e_magic <> IMAGE_DOS_SIGNATURE) or
- (PImageDosHeader(BaseAddress)^._lfanew = 0) then
- Exit;
- Result := PImageNtHeaders32(TJclAddr(BaseAddress) + DWORD(PImageDosHeader(BaseAddress)^._lfanew));
- if IsBadReadPtr(Result, SizeOf(TImageNtHeaders32)) or
- (Result^.Signature <> IMAGE_NT_SIGNATURE) then
- Result := nil
- end;
- function PeMapImgNtHeaders32(Stream: TStream; const BasePosition: Int64; out NtHeaders32: TImageNtHeaders32): Int64;
- var
- ImageDosHeader: TImageDosHeader;
- begin
- ResetMemory(NtHeaders32, SizeOf(NtHeaders32));
- Result := -1;
- if (Stream.Seek(BasePosition, soBeginning) <> BasePosition) or
- (Stream.Read(ImageDosHeader, SizeOf(ImageDosHeader)) <> SizeOf(ImageDosHeader)) then
- raise EJclPeImageError.CreateRes(@SReadError);
- if (ImageDosHeader.e_magic <> IMAGE_DOS_SIGNATURE) or
- (ImageDosHeader._lfanew = 0) then
- Exit;
- Result := BasePosition + DWORD(ImageDosHeader._lfanew);
- if (Stream.Seek(Result, soBeginning) <> Result) or
- (Stream.Read(NtHeaders32, SizeOf(NtHeaders32)) <> SizeOf(NtHeaders32)) then
- raise EJclPeImageError.CreateRes(@SReadError);
- if NtHeaders32.Signature <> IMAGE_NT_SIGNATURE then
- Result := -1;
- end;
- function PeMapImgNtHeaders64(const BaseAddress: Pointer): PImageNtHeaders64;
- begin
- Result := nil;
- if IsBadReadPtr(BaseAddress, SizeOf(TImageDosHeader)) then
- Exit;
- if (PImageDosHeader(BaseAddress)^.e_magic <> IMAGE_DOS_SIGNATURE) or
- (PImageDosHeader(BaseAddress)^._lfanew = 0) then
- Exit;
- Result := PImageNtHeaders64(TJclAddr(BaseAddress) + DWORD(PImageDosHeader(BaseAddress)^._lfanew));
- if IsBadReadPtr(Result, SizeOf(TImageNtHeaders64)) or
- (Result^.Signature <> IMAGE_NT_SIGNATURE) then
- Result := nil
- end;
- function PeMapImgNtHeaders64(Stream: TStream; const BasePosition: Int64; out NtHeaders64: TImageNtHeaders64): Int64;
- var
- ImageDosHeader: TImageDosHeader;
- begin
- ResetMemory(NtHeaders64, SizeOf(NtHeaders64));
- Result := -1;
- if (Stream.Seek(BasePosition, soBeginning) <> BasePosition) or
- (Stream.Read(ImageDosHeader, SizeOf(ImageDosHeader)) <> SizeOf(ImageDosHeader)) then
- raise EJclPeImageError.CreateRes(@SReadError);
- if (ImageDosHeader.e_magic <> IMAGE_DOS_SIGNATURE) or
- (ImageDosHeader._lfanew = 0) then
- Exit;
- Result := BasePosition + DWORD(ImageDosHeader._lfanew);
- if (Stream.Seek(Result, soBeginning) <> Result) or
- (Stream.Read(NtHeaders64, SizeOf(NtHeaders64)) <> SizeOf(NtHeaders64)) then
- raise EJclPeImageError.CreateRes(@SReadError);
- if NtHeaders64.Signature <> IMAGE_NT_SIGNATURE then
- Result := -1;
- end;
- function PeMapImgSize(const BaseAddress: Pointer): DWORD;
- begin
- case PeMapImgTarget(BaseAddress) of
- taWin32:
- Result := PeMapImgSize32(BaseAddress);
- taWin64:
- Result := PeMapImgSize64(BaseAddress);
- //taUnknown:
- else
- Result := 0;
- end;
- end;
- function PeMapImgSize(Stream: TStream; const BasePosition: Int64): DWORD;
- begin
- case PeMapImgTarget(Stream, BasePosition) of
- taWin32:
- Result := PeMapImgSize32(Stream, BasePosition);
- taWin64:
- Result := PeMapImgSize64(Stream, BasePosition);
- //taUnknown:
- else
- Result := 0;
- end;
- end;
- function PeMapImgSize32(const BaseAddress: Pointer): DWORD;
- var
- NtHeaders32: PImageNtHeaders32;
- begin
- Result := 0;
- NtHeaders32 := PeMapImgNtHeaders32(BaseAddress);
- if Assigned(NtHeaders32) then
- Result := NtHeaders32^.OptionalHeader.SizeOfImage;
- end;
- function PeMapImgSize32(Stream: TStream; const BasePosition: Int64): DWORD;
- var
- NtHeaders32: TImageNtHeaders32;
- begin
- Result := 0;
- if PeMapImgNtHeaders32(Stream, BasePosition, NtHeaders32) <> -1 then
- Result := NtHeaders32.OptionalHeader.SizeOfImage;
- end;
- function PeMapImgSize64(const BaseAddress: Pointer): DWORD;
- var
- NtHeaders64: PImageNtHeaders64;
- begin
- Result := 0;
- NtHeaders64 := PeMapImgNtHeaders64(BaseAddress);
- if Assigned(NtHeaders64) then
- Result := NtHeaders64^.OptionalHeader.SizeOfImage;
- end;
- function PeMapImgSize64(Stream: TStream; const BasePosition: Int64): DWORD;
- var
- NtHeaders64: TImageNtHeaders64;
- begin
- Result := 0;
- if PeMapImgNtHeaders64(Stream, BasePosition, NtHeaders64) <> -1 then
- Result := NtHeaders64.OptionalHeader.SizeOfImage;
- end;
- function PeMapImgLibraryName(const BaseAddress: Pointer): string;
- begin
- case PeMapImgTarget(BaseAddress) of
- taWin32:
- Result := PeMapImgLibraryName32(BaseAddress);
- taWin64:
- Result := PeMapImgLibraryName64(BaseAddress);
- //taUnknown:
- else
- Result := '';
- end;
- end;
- function PeMapImgLibraryName32(const BaseAddress: Pointer): string;
- var
- NtHeaders: PImageNtHeaders32;
- DataDir: TImageDataDirectory;
- ExportDir: PImageExportDirectory;
- UTF8Name: TUTF8String;
- begin
- Result := '';
- NtHeaders := PeMapImgNtHeaders32(BaseAddress);
- if NtHeaders = nil then
- Exit;
- DataDir := NtHeaders^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
- if DataDir.Size = 0 then
- Exit;
- ExportDir := PImageExportDirectory(TJclAddr(BaseAddress) + DataDir.VirtualAddress);
- if IsBadReadPtr(ExportDir, SizeOf(TImageExportDirectory)) or (ExportDir^.Name = 0) then
- Exit;
- UTF8Name := PAnsiChar(TJclAddr(BaseAddress) + ExportDir^.Name);
- if not TryUTF8ToString(UTF8Name, Result) then
- Result := string(UTF8Name);
- end;
- function PeMapImgLibraryName64(const BaseAddress: Pointer): string;
- var
- NtHeaders: PImageNtHeaders64;
- DataDir: TImageDataDirectory;
- ExportDir: PImageExportDirectory;
- UTF8Name: TUTF8String;
- begin
- Result := '';
- NtHeaders := PeMapImgNtHeaders64(BaseAddress);
- if NtHeaders = nil then
- Exit;
- DataDir := NtHeaders^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
- if DataDir.Size = 0 then
- Exit;
- ExportDir := PImageExportDirectory(TJclAddr(BaseAddress) + DataDir.VirtualAddress);
- if IsBadReadPtr(ExportDir, SizeOf(TImageExportDirectory)) or (ExportDir^.Name = 0) then
- Exit;
- UTF8Name := PAnsiChar(TJclAddr(BaseAddress) + ExportDir^.Name);
- if not TryUTF8ToString(UTF8Name, Result) then
- Result := string(UTF8Name);
- end;
- function PeMapImgTarget(const BaseAddress: Pointer): TJclPeTarget;
- var
- ImageNtHeaders: PImageNtHeaders32;
- begin
- Result := taUnknown;
- ImageNtHeaders := PeMapImgNtHeaders32(BaseAddress);
- if Assigned(ImageNtHeaders) then
- case ImageNtHeaders.FileHeader.Machine of
- IMAGE_FILE_MACHINE_I386:
- Result := taWin32;
- IMAGE_FILE_MACHINE_AMD64:
- Result := taWin64;
- end;
- end;
- function PeMapImgTarget(Stream: TStream; const BasePosition: Int64): TJclPeTarget;
- var
- ImageNtHeaders: TImageNtHeaders32;
- begin
- Result := taUnknown;
- if PeMapImgNtHeaders32(Stream, BasePosition, ImageNtHeaders) <> -1 then
- begin
- case ImageNtHeaders.FileHeader.Machine of
- IMAGE_FILE_MACHINE_I386:
- Result := taWin32;
- IMAGE_FILE_MACHINE_AMD64:
- Result := taWin64;
- end;
- end;
- end;
- function PeMapImgSections32(NtHeaders: PImageNtHeaders32): PImageSectionHeader;
- begin
- if NtHeaders = nil then
- Result := nil
- else
- Result := PImageSectionHeader(TJclAddr(@NtHeaders^.OptionalHeader) +
- NtHeaders^.FileHeader.SizeOfOptionalHeader);
- end;
- function PeMapImgSections32(Stream: TStream; const NtHeaders32Position: Int64; const NtHeaders32: TImageNtHeaders32;
- out ImageSectionHeaders: TImageSectionHeaderArray): Int64;
- var
- SectionSize: Integer;
- begin
- if NtHeaders32Position = -1 then
- begin
- SetLength(ImageSectionHeaders, 0);
- Result := -1;
- end
- else
- begin
- SetLength(ImageSectionHeaders, NtHeaders32.FileHeader.NumberOfSections);
- Result := NtHeaders32Position + SizeOf(NtHeaders32.Signature) + SizeOf(NtHeaders32.FileHeader) + NtHeaders32.FileHeader.SizeOfOptionalHeader;
- SectionSize := SizeOf(ImageSectionHeaders[0]) * Length(ImageSectionHeaders);
- if (Stream.Seek(Result, soBeginning) <> Result) or
- (Stream.Read(ImageSectionHeaders[0], SectionSize) <> SectionSize) then
- raise EJclPeImageError.CreateRes(@SReadError);
- end;
- end;
- function PeMapImgSections64(NtHeaders: PImageNtHeaders64): PImageSectionHeader;
- begin
- if NtHeaders = nil then
- Result := nil
- else
- Result := PImageSectionHeader(TJclAddr(@NtHeaders^.OptionalHeader) +
- NtHeaders^.FileHeader.SizeOfOptionalHeader);
- end;
- function PeMapImgSections64(Stream: TStream; const NtHeaders64Position: Int64; const NtHeaders64: TImageNtHeaders64;
- out ImageSectionHeaders: TImageSectionHeaderArray): Int64;
- var
- SectionSize: Integer;
- begin
- if NtHeaders64Position = -1 then
- begin
- SetLength(ImageSectionHeaders, 0);
- Result := -1;
- end
- else
- begin
- SetLength(ImageSectionHeaders, NtHeaders64.FileHeader.NumberOfSections);
- Result := NtHeaders64Position + SizeOf(NtHeaders64.Signature) + SizeOf(NtHeaders64.FileHeader) + NtHeaders64.FileHeader.SizeOfOptionalHeader;
- SectionSize := SizeOf(ImageSectionHeaders[0]) * Length(ImageSectionHeaders);
- if (Stream.Seek(Result, soBeginning) <> Result) or
- (Stream.Read(ImageSectionHeaders[0], SectionSize) <> SectionSize) then
- raise EJclPeImageError.CreateRes(@SReadError);
- end;
- end;
- function PeMapImgFindSection32(NtHeaders: PImageNtHeaders32;
- const SectionName: string): PImageSectionHeader;
- var
- Header: PImageSectionHeader;
- I: Integer;
- P: PAnsiChar;
- UTF8Name: TUTF8String;
- begin
- Result := nil;
- if NtHeaders <> nil then
- begin
- if not TryStringToUTF8(SectionName, UTF8Name) then
- UTF8Name := TUTF8String(SectionName);
- P := PAnsiChar(UTF8Name);
- Header := PeMapImgSections32(NtHeaders);
- for I := 1 to NtHeaders^.FileHeader.NumberOfSections do
- if StrLCompA(PAnsiChar(@Header^.Name), P, IMAGE_SIZEOF_SHORT_NAME) = 0 then
- begin
- Result := Header;
- Break;
- end
- else
- Inc(Header);
- end;
- end;
- function PeMapImgFindSection64(NtHeaders: PImageNtHeaders64;
- const SectionName: string): PImageSectionHeader;
- var
- Header: PImageSectionHeader;
- I: Integer;
- P: PAnsiChar;
- UTF8Name: TUTF8String;
- begin
- Result := nil;
- if NtHeaders <> nil then
- begin
- if not TryStringToUTF8(SectionName, UTF8Name) then
- UTF8Name := TUTF8String(SectionName);
- P := PAnsiChar(UTF8Name);
- Header := PeMapImgSections64(NtHeaders);
- for I := 1 to NtHeaders^.FileHeader.NumberOfSections do
- if StrLCompA(PAnsiChar(@Header^.Name), P, IMAGE_SIZEOF_SHORT_NAME) = 0 then
- begin
- Result := Header;
- Break;
- end
- else
- Inc(Header);
- end;
- end;
- function PeMapImgFindSection(const ImageSectionHeaders: TImageSectionHeaderArray;
- const SectionName: string): SizeInt;
- var
- P: PAnsiChar;
- UTF8Name: TUTF8String;
- begin
- if Length(ImageSectionHeaders) > 0 then
- begin
- if not TryStringToUTF8(SectionName, UTF8Name) then
- UTF8Name := TUTF8String(SectionName);
- P := PAnsiChar(UTF8Name);
- for Result := Low(ImageSectionHeaders) to High(ImageSectionHeaders) do
- if StrLCompA(PAnsiChar(@ImageSectionHeaders[Result].Name), P, IMAGE_SIZEOF_SHORT_NAME) = 0 then
- Exit;
- end;
- Result := -1;
- end;
- function PeMapImgFindSectionFromModule(const BaseAddress: Pointer;
- const SectionName: string): PImageSectionHeader;
- function PeMapImgFindSectionFromModule32(const BaseAddress: Pointer;
- const SectionName: string): PImageSectionHeader;
- var
- NtHeaders32: PImageNtHeaders32;
- begin
- Result := nil;
- NtHeaders32 := PeMapImgNtHeaders32(BaseAddress);
- if Assigned(NtHeaders32) then
- Result := PeMapImgFindSection32(NtHeaders32, SectionName);
- end;
- function PeMapImgFindSectionFromModule64(const BaseAddress: Pointer;
- const SectionName: string): PImageSectionHeader;
- var
- NtHeaders64: PImageNtHeaders64;
- begin
- Result := nil;
- NtHeaders64 := PeMapImgNtHeaders64(BaseAddress);
- if Assigned(NtHeaders64) then
- Result := PeMapImgFindSection64(NtHeaders64, SectionName);
- end;
- begin
- case PeMapImgTarget(BaseAddress) of
- taWin32:
- Result := PeMapImgFindSectionFromModule32(BaseAddress, SectionName);
- taWin64:
- Result := PeMapImgFindSectionFromModule64(BaseAddress, SectionName);
- //taUnknown:
- else
- Result := nil;
- end;
- end;
- function PeMapImgExportedVariables(const Module: HMODULE; const VariablesList: TStrings): Boolean;
- var
- I: Integer;
- begin
- with TJclPeImage.Create(True) do
- try
- AttachLoadedModule(Module);
- Result := StatusOK;
- if Result then
- begin
- VariablesList.BeginUpdate;
- try
- with ExportList do
- for I := 0 to Count - 1 do
- with Items[I] do
- if IsExportedVariable then
- VariablesList.AddObject(Name, MappedAddress);
- finally
- VariablesList.EndUpdate;
- end;
- end;
- finally
- Free;
- end;
- end;
- function PeMapImgResolvePackageThunk(Address: Pointer): Pointer;
- {$IFDEF BORLAND}
- const
- JmpInstructionCode = $25FF;
- type
- PPackageThunk = ^TPackageThunk;
- TPackageThunk = packed record
- JmpInstruction: Word;
- {$IFDEF CPU32}
- JmpAddress: PPointer;
- {$ENDIF CPU32}
- {$IFDEF CPU64}
- JmpOffset: Int32;
- {$ENDIF CPU64}
- end;
- begin
- if not IsCompiledWithPackages then
- Result := Address
- else
- if not IsBadReadPtr(Address, SizeOf(TPackageThunk)) and
- (PPackageThunk(Address)^.JmpInstruction = JmpInstructionCode) then
- {$IFDEF CPU32}
- Result := PPackageThunk(Address)^.JmpAddress^
- {$ENDIF CPU32}
- {$IFDEF CPU64}
- Result := PPointer(PByte(Address) + SizeOf(TPackageThunk) +
- PPackageThunk(Address)^.JmpOffset)^
- {$ENDIF CPU64}
- else
- Result := nil;
- end;
- {$ENDIF BORLAND}
- {$IFDEF FPC}
- begin
- Result := Address;
- end;
- {$ENDIF FPC}
- function PeMapFindResource(const Module: HMODULE; const ResourceType: PChar;
- const ResourceName: string): Pointer;
- var
- ResItem: TJclPeResourceItem;
- begin
- Result := nil;
- with TJclPeImage.Create(True) do
- try
- AttachLoadedModule(Module);
- if StatusOK then
- begin
- ResItem := ResourceList.FindResource(ResourceType, PChar(ResourceName));
- if (ResItem <> nil) and ResItem.IsDirectory then
- Result := ResItem.List[0].RawEntryData;
- end;
- finally
- Free;
- end;
- end;
- //=== { TJclPeSectionStream } ================================================
- constructor TJclPeSectionStream.Create(Instance: HMODULE; const ASectionName: string);
- begin
- inherited Create;
- Initialize(Instance, ASectionName);
- end;
- procedure TJclPeSectionStream.Initialize(Instance: HMODULE; const ASectionName: string);
- var
- Header: PImageSectionHeader;
- NtHeaders32: PImageNtHeaders32;
- NtHeaders64: PImageNtHeaders64;
- DataSize: Integer;
- begin
- FInstance := Instance;
- case PeMapImgTarget(Pointer(Instance)) of
- taWin32:
- begin
- NtHeaders32 := PeMapImgNtHeaders32(Pointer(Instance));
- if NtHeaders32 = nil then
- raise EJclPeImageError.CreateRes(@RsPeNotPE);
- Header := PeMapImgFindSection32(NtHeaders32, ASectionName);
- end;
- taWin64:
- begin
- NtHeaders64 := PeMapImgNtHeaders64(Pointer(Instance));
- if NtHeaders64 = nil then
- raise EJclPeImageError.CreateRes(@RsPeNotPE);
- Header := PeMapImgFindSection64(NtHeaders64, ASectionName);
- end;
- //toUnknown:
- else
- raise EJclPeImageError.CreateRes(@RsPeUnknownTarget);
- end;
- if Header = nil then
- raise EJclPeImageError.CreateResFmt(@RsPeSectionNotFound, [ASectionName]);
- // Borland and Microsoft seems to have swapped the meaning of this items.
- DataSize := Min(Header^.SizeOfRawData, Header^.Misc.VirtualSize);
- SetPointer(Pointer(FInstance + Header^.VirtualAddress), DataSize);
- FSectionHeader := Header^;
- end;
- function TJclPeSectionStream.Write(const Buffer; Count: Integer): Longint;
- begin
- raise EJclPeImageError.CreateRes(@RsPeReadOnlyStream);
- end;
- //=== { TJclPeMapImgHookItem } ===============================================
- constructor TJclPeMapImgHookItem.Create(AList: TObjectList;
- const AFunctionName: string; const AModuleName: string;
- ABaseAddress, ANewAddress, AOriginalAddress: Pointer);
- begin
- inherited Create;
- FList := AList;
- FFunctionName := AFunctionName;
- FModuleName := AModuleName;
- FBaseAddress := ABaseAddress;
- FNewAddress := ANewAddress;
- FOriginalAddress := AOriginalAddress;
- end;
- destructor TJclPeMapImgHookItem.Destroy;
- begin
- if FBaseAddress <> nil then
- InternalUnhook;
- inherited Destroy;
- end;
- function TJclPeMapImgHookItem.InternalUnhook: Boolean;
- var
- Buf: TMemoryBasicInformation;
- begin
- Buf.AllocationBase := nil;
- if (VirtualQuery(FBaseAddress, Buf, SizeOf(Buf)) = SizeOf(Buf)) and (Buf.State and MEM_FREE = 0) then
- Result := TJclPeMapImgHooks.ReplaceImport(FBaseAddress, ModuleName, NewAddress, OriginalAddress)
- else
- Result := True; // PE image is not available anymore (DLL got unloaded)
- if Result then
- FBaseAddress := nil;
- end;
- function TJclPeMapImgHookItem.Unhook: Boolean;
- begin
- Result := InternalUnhook;
- if Result then
- FList.Remove(Self);
- end;
- //=== { TJclPeMapImgHooks } ==================================================
- type
- PWin9xDebugThunk32 = ^TWin9xDebugThunk32;
- TWin9xDebugThunk32 = packed record
- PUSH: Byte; // PUSH instruction opcode ($68)
- Addr: DWORD; // The actual address of the DLL routine
- JMP: Byte; // JMP instruction opcode ($E9)
- Rel: DWORD; // Relative displacement (a Kernel32 address)
- end;
- function TJclPeMapImgHooks.GetItemFromNewAddress(NewAddress: Pointer): TJclPeMapImgHookItem;
- var
- I: Integer;
- begin
- Result := nil;
- for I := 0 to Count - 1 do
- if Items[I].NewAddress = NewAddress then
- begin
- Result := Items[I];
- Break;
- end;
- end;
- function TJclPeMapImgHooks.GetItemFromOriginalAddress(OriginalAddress: Pointer): TJclPeMapImgHookItem;
- var
- I: Integer;
- begin
- Result := nil;
- for I := 0 to Count - 1 do
- if Items[I].OriginalAddress = OriginalAddress then
- begin
- Result := Items[I];
- Break;
- end;
- end;
- function TJclPeMapImgHooks.GetItems(Index: Integer): TJclPeMapImgHookItem;
- begin
- Result := TJclPeMapImgHookItem(Get(Index));
- end;
- function TJclPeMapImgHooks.HookImport(Base: Pointer; const ModuleName: string;
- const FunctionName: string; NewAddress: Pointer; var OriginalAddress: Pointer): Boolean;
- var
- ModuleHandle: THandle;
- OriginalItem: TJclPeMapImgHookItem;
- UTF8Name: TUTF8String;
- begin
- ModuleHandle := GetModuleHandle(PChar(ModuleName));
- Result := (ModuleHandle <> 0);
- if not Result then
- begin
- SetLastError(ERROR_MOD_NOT_FOUND);
- Exit;
- end;
- if not TryStringToUTF8(FunctionName, UTF8Name) then
- UTF8Name := TUTF8String(FunctionName);
- OriginalAddress := GetProcAddress(ModuleHandle, PAnsiChar(UTF8Name));
- Result := (OriginalAddress <> nil);
- if not Result then
- begin
- SetLastError(ERROR_PROC_NOT_FOUND);
- Exit;
- end;
- OriginalItem := ItemFromOriginalAddress[OriginalAddress];
- Result := ((OriginalItem = nil) or (OriginalItem.ModuleName = ModuleName)) and
- (NewAddress <> nil) and (OriginalAddress <> NewAddress);
- if not Result then
- begin
- SetLastError(ERROR_ALREADY_EXISTS);
- Exit;
- end;
- if Result then
- Result := ReplaceImport(Base, ModuleName, OriginalAddress, NewAddress);
- if Result then
- begin
- Add(TJclPeMapImgHookItem.Create(Self, FunctionName, ModuleName, Base,
- NewAddress, OriginalAddress));
- end
- else
- SetLastError(ERROR_INVALID_PARAMETER);
- end;
- class function TJclPeMapImgHooks.IsWin9xDebugThunk(P: Pointer): Boolean;
- begin
- with PWin9xDebugThunk32(P)^ do
- Result := (PUSH = $68) and (JMP = $E9);
- end;
- class function TJclPeMapImgHooks.ReplaceImport(Base: Pointer; const ModuleName: string;
- FromProc, ToProc: Pointer): Boolean;
- var
- {$IFDEF CPU32}
- FromProcDebugThunk32, ImportThunk32: PWin9xDebugThunk32;
- IsThunked: Boolean;
- NtHeader: PImageNtHeaders32;
- ImportEntry: PImageThunkData32;
- {$ENDIF CPU32}
- {$IFDEF CPU64}
- NtHeader: PImageNtHeaders64;
- ImportEntry: PImageThunkData64;
- {$ENDIF CPU64}
- ImportDir: TImageDataDirectory;
- ImportDesc: PImageImportDescriptor;
- CurrName, RefName: PAnsiChar;
- FoundProc: Boolean;
- WrittenBytes: Cardinal;
- UTF8Name: TUTF8String;
- begin
- Result := False;
- {$IFDEF CPU32}
- FromProcDebugThunk32 := PWin9xDebugThunk32(FromProc);
- IsThunked := (Win32Platform <> VER_PLATFORM_WIN32_NT) and IsWin9xDebugThunk(FromProcDebugThunk32);
- NtHeader := PeMapImgNtHeaders32(Base);
- {$ENDIF CPU32}
- {$IFDEF CPU64}
- NtHeader := PeMapImgNtHeaders64(Base);
- {$ENDIF CPU64}
- if NtHeader = nil then
- Exit;
- ImportDir := NtHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
- if ImportDir.VirtualAddress = 0 then
- Exit;
- ImportDesc := PImageImportDescriptor(TJclAddr(Base) + ImportDir.VirtualAddress);
- if not TryStringToUTF8(ModuleName, UTF8Name) then
- UTF8Name := TUTF8String(ModuleName);
- RefName := PAnsiChar(UTF8Name);
- while ImportDesc^.Name <> 0 do
- begin
- CurrName := PAnsiChar(Base) + ImportDesc^.Name;
- if StrICompA(CurrName, RefName) = 0 then
- begin
- {$IFDEF CPU32}
- ImportEntry := PImageThunkData32(TJclAddr(Base) + ImportDesc^.FirstThunk);
- {$ENDIF CPU32}
- {$IFDEF CPU64}
- ImportEntry := PImageThunkData64(TJclAddr(Base) + ImportDesc^.FirstThunk);
- {$ENDIF CPU64}
- while ImportEntry^.Function_ <> 0 do
- begin
- {$IFDEF CPU32}
- if IsThunked then
- begin
- ImportThunk32 := PWin9xDebugThunk32(ImportEntry^.Function_);
- FoundProc := IsWin9xDebugThunk(ImportThunk32) and (ImportThunk32^.Addr = FromProcDebugThunk32^.Addr);
- end
- else
- {$ENDIF CPU32}
- FoundProc := Pointer(ImportEntry^.Function_) = FromProc;
- if FoundProc then
- Result := WriteProtectedMemory(@ImportEntry^.Function_, @ToProc, SizeOf(ToProc), WrittenBytes);
- Inc(ImportEntry);
- end;
- end;
- Inc(ImportDesc);
- end;
- end;
- class function TJclPeMapImgHooks.SystemBase: Pointer;
- begin
- Result := Pointer(SystemTObjectInstance);
- end;
- procedure TJclPeMapImgHooks.UnhookAll;
- var
- I: Integer;
- begin
- I := 0;
- while I < Count do
- if not Items[I].Unhook then
- Inc(I);
- end;
- function TJclPeMapImgHooks.UnhookByNewAddress(NewAddress: Pointer): Boolean;
- var
- Item: TJclPeMapImgHookItem;
- begin
- Item := ItemFromNewAddress[NewAddress];
- Result := (Item <> nil) and Item.Unhook;
- end;
- procedure TJclPeMapImgHooks.UnhookByBaseAddress(BaseAddress: Pointer);
- var
- I: Integer;
- begin
- for I := Count - 1 downto 0 do
- if Items[I].BaseAddress = BaseAddress then
- Items[I].Unhook;
- end;
- // Image access under a debbuger
- {$IFDEF USE_64BIT_TYPES}
- function InternalReadProcMem(ProcessHandle: THandle; Address: DWORD;
- Buffer: Pointer; Size: SIZE_T): Boolean;
- var
- BR: SIZE_T;
- {$ELSE}
- function InternalReadProcMem(ProcessHandle: THandle; Address: DWORD;
- Buffer: Pointer; Size: Integer): Boolean;
- var
- BR: DWORD;
- {$ENDIF}
- begin
- BR := 0;
- Result := ReadProcessMemory(ProcessHandle, Pointer(Address), Buffer, Size, BR);
- end;
- // TODO: 64 bit version
- function PeDbgImgNtHeaders32(ProcessHandle: THandle; BaseAddress: TJclAddr32;
- var NtHeaders: TImageNtHeaders32): Boolean;
- var
- DosHeader: TImageDosHeader;
- begin
- Result := False;
- ResetMemory(NtHeaders, SizeOf(NtHeaders));
- ResetMemory(DosHeader, SizeOf(DosHeader));
- if not InternalReadProcMem(ProcessHandle, TJclAddr32(BaseAddress), @DosHeader, SizeOf(DosHeader)) then
- Exit;
- if DosHeader.e_magic <> IMAGE_DOS_SIGNATURE then
- Exit;
- Result := InternalReadProcMem(ProcessHandle, TJclAddr32(BaseAddress) + TJclAddr32(DosHeader._lfanew),
- @NtHeaders, SizeOf(TImageNtHeaders32));
- end;
- // TODO: 64 bit version
- function PeDbgImgLibraryName32(ProcessHandle: THandle; BaseAddress: TJclAddr32;
- var Name: string): Boolean;
- var
- NtHeaders32: TImageNtHeaders32;
- DataDir: TImageDataDirectory;
- ExportDir: TImageExportDirectory;
- UTF8Name: TUTF8String;
- begin
- Name := '';
- NtHeaders32.Signature := 0;
- Result := PeDbgImgNtHeaders32(ProcessHandle, BaseAddress, NtHeaders32);
- if not Result then
- Exit;
- DataDir := NtHeaders32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
- if DataDir.Size = 0 then
- Exit;
- if not InternalReadProcMem(ProcessHandle, TJclAddr(BaseAddress) + DataDir.VirtualAddress,
- @ExportDir, SizeOf(ExportDir)) then
- Exit;
- if ExportDir.Name = 0 then
- Exit;
- SetLength(UTF8Name, MAX_PATH);
- if InternalReadProcMem(ProcessHandle, TJclAddr(BaseAddress) + ExportDir.Name, PAnsiChar(UTF8Name), MAX_PATH) then
- begin
- StrResetLength(UTF8Name);
- if not TryUTF8ToString(UTF8Name, Name) then
- Name := string(UTF8Name);
- end
- else
- Name := '';
- end;
- // Borland BPL packages name unmangling
- {$IFDEF CPU64}
- function PeBorUnmangleName(const Name: string; out Unmangled: string;
- out Description: TJclBorUmDescription; out BasePos: Integer): TJclBorUmResult;
- var
- CurPos: Integer;
- EndPos: Integer;
- Len: Integer;
- PrevBasePos: Integer;
- begin
- if (Length(Name) > 3) and (Name[1] = '_') and (Name[2] = 'Z') and (Name[3] = 'N') then
- begin
- Result := urOk;
- CurPos := 4;
- BasePos := 0;
- PrevBasePos := 0;
- while CurPos < Length(Name) do
- begin
- EndPos := CurPos;
- while CharInSet(Name[EndPos], ['0'..'9']) do
- Inc(EndPos);
- if not TryStrToInt(Copy(Name, CurPos, EndPos - CurPos), Len) then
- Break;
- BasePos := PrevBasePos;
- PrevBasePos := Length(Unmangled);
- if Unmangled <> '' then
- Unmangled := Unmangled + '.';
- Unmangled := Unmangled + Copy(Name, EndPos, Len);
- CurPos := EndPos + Len;
- end;
- if BasePos = 0 then
- BasePos := PrevBasePos + 2
- else
- BasePos := BasePos + 2;
- Description.Kind := skFunction;
- Description.Modifiers := [];
- end
- else
- Result := urNotMangled;
- end;
- {$ENDIF CPU64}
- {$IFDEF CPU32}
- function PeBorUnmangleName(const Name: string; out Unmangled: string;
- out Description: TJclBorUmDescription; out BasePos: Integer): TJclBorUmResult;
- var
- NameP, NameU, NameUFirst: PAnsiChar;
- QualifierFound, LinkProcFound: Boolean;
- UTF8Unmangled, UTF8Name: TUTF8String;
- procedure MarkQualifier;
- begin
- if not QualifierFound then
- begin
- QualifierFound := True;
- BasePos := NameU - NameUFirst + 2;
- end;
- end;
- procedure ReadSpecialSymbol;
- var
- SymbolLength: Integer;
- begin
- SymbolLength := 0;
- while CharIsDigit(Char(NameP^)) do
- begin
- SymbolLength := SymbolLength * 10 + Ord(NameP^) - 48;
- Inc(NameP);
- end;
- while (SymbolLength > 0) and (NameP^ <> #0) do
- begin
- if NameP^ = '@' then
- begin
- MarkQualifier;
- NameU^ := '.';
- end
- else
- NameU^ := NameP^;
- Inc(NameP);
- Inc(NameU);
- Dec(SymbolLength);
- end;
- end;
- procedure ReadRTTI;
- begin
- if StrLCompA(NameP, '$xp$', 4) = 0 then
- begin
- Inc(NameP, 4);
- Description.Kind := skRTTI;
- QualifierFound := False;
- ReadSpecialSymbol;
- if QualifierFound then
- Include(Description.Modifiers, smQualified);
- end
- else
- Result := urError;
- end;
- procedure ReadNameSymbol;
- begin
- if NameP^ = '@' then
- begin
- LinkProcFound := True;
- Inc(NameP);
- end;
- while CharIsValidIdentifierLetter(Char(NameP^)) do
- begin
- NameU^ := NameP^;
- Inc(NameP);
- Inc(NameU);
- end;
- end;
- procedure ReadName;
- begin
- Description.Kind := skData;
- QualifierFound := False;
- LinkProcFound := False;
- repeat
- ReadNameSymbol;
- if LinkProcFound and not QualifierFound then
- LinkProcFound := False;
- case NameP^ of
- '@':
- case (NameP + 1)^ of
- #0:
- begin
- Description.Kind := skVTable;
- Break;
- end;
- '$':
- begin
- if (NameP + 2)^ = 'b' then
- begin
- case (NameP + 3)^ of
- 'c':
- Description.Kind := skConstructor;
- 'd':
- Description.Kind := skDestructor;
- end;
- Inc(NameP, 6);
- end
- else
- Description.Kind := skFunction;
- Break; // no parameters unmangling yet
- end;
- else
- MarkQualifier;
- NameU^ := '.';
- Inc(NameU);
- Inc(NameP);
- end;
- '$':
- begin
- Description.Kind := skFunction;
- Break; // no parameters unmangling yet
- end;
- else
- Break;
- end;
- until False;
- if QualifierFound then
- Include(Description.Modifiers, smQualified);
- if LinkProcFound then
- Include(Description.Modifiers, smLinkProc);
- end;
- begin
- if not TryStringToUTF8(Name, UTF8Name) then
- UTF8Name := TUTF8String(Name);
- NameP := PAnsiChar(UTF8Name);
- Result := urError;
- case NameP^ of
- '@':
- Result := urOk;
- '?':
- Result := urMicrosoft;
- '_', 'A'..'Z', 'a'..'z':
- Result := urNotMangled;
- end;
- if Result <> urOk then
- Exit;
- Inc(NameP);
- SetLength(UTF8UnMangled, 1024);
- NameU := PAnsiChar(UTF8UnMangled);
- NameUFirst := NameU;
- Description.Modifiers := [];
- BasePos := 1;
- case NameP^ of
- '$':
- ReadRTTI;
- '_', 'A'..'Z', 'a'..'z':
- ReadName;
- else
- Result := urError;
- end;
- NameU^ := #0;
- SetLength(UTF8Unmangled, StrLenA(PAnsiChar(UTF8Unmangled))); // SysUtils prefix due to compiler bug
- if not TryUTF8ToString(UTF8Unmangled, Unmangled) then
- Unmangled := string(UTF8Unmangled);
- end;
- {$ENDIF CPU32}
- function PeBorUnmangleName(const Name: string; out Unmangled: string;
- out Description: TJclBorUmDescription): TJclBorUmResult;
- var
- BasePos: Integer;
- begin
- Result := PeBorUnmangleName(Name, Unmangled, Description, BasePos);
- end;
- function PeBorUnmangleName(const Name: string; out Unmangled: string): TJclBorUmResult;
- var
- Description: TJclBorUmDescription;
- BasePos: Integer;
- begin
- Result := PeBorUnmangleName(Name, Unmangled, Description, BasePos);
- end;
- function PeBorUnmangleName(const Name: string): string;
- var
- Unmangled: string;
- Description: TJclBorUmDescription;
- BasePos: Integer;
- begin
- if PeBorUnmangleName(Name, Unmangled, Description, BasePos) = urOk then
- Result := Unmangled
- else
- Result := '';
- end;
- function PeIsNameMangled(const Name: string): TJclPeUmResult; {$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}
- begin
- Result := umNotMangled;
- if Length(Name) > 0 then
- case Name[1] of
- '@':
- Result := umBorland;
- '?':
- Result := umMicrosoft;
- {$IFDEF CPU64}
- '_':
- if (Length(Name) > 3) and (Name[2] = 'Z') and (Name[3] = 'N') then
- Result := umBorland;
- {$ENDIF CPU64}
- end;
- end;
- type
- TUndecorateSymbolNameA = function (DecoratedName: PAnsiChar;
- UnDecoratedName: PAnsiChar; UndecoratedLength: DWORD; Flags: DWORD): DWORD; stdcall;
- // 'imagehlp.dll' 'UnDecorateSymbolName'
- TUndecorateSymbolNameW = function (DecoratedName: PWideChar;
- UnDecoratedName: PWideChar; UndecoratedLength: DWORD; Flags: DWORD): DWORD; stdcall;
- // 'imagehlp.dll' 'UnDecorateSymbolNameW'
- var
- UndecorateSymbolNameA: TUndecorateSymbolNameA = nil;
- UndecorateSymbolNameAFailed: Boolean = False;
- UndecorateSymbolNameW: TUndecorateSymbolNameW = nil;
- UndecorateSymbolNameWFailed: Boolean = False;
- function UndecorateSymbolName(const DecoratedName: string; out UnMangled: string; Flags: DWORD): Boolean;
- const
- ModuleName = 'imagehlp.dll';
- BufferSize = 512;
- var
- ModuleHandle: HMODULE;
- WideBuffer: WideString;
- AnsiBuffer: AnsiString;
- Res: DWORD;
- begin
- Result := False;
- if ((not Assigned(UndecorateSymbolNameA)) and (not UndecorateSymbolNameAFailed)) or
- ((not Assigned(UndecorateSymbolNameW)) and (not UndecorateSymbolNameWFailed)) then
- begin
- ModuleHandle := GetModuleHandle(ModuleName);
- if ModuleHandle = 0 then
- begin
- ModuleHandle := SafeLoadLibrary(ModuleName);
- if ModuleHandle = 0 then
- Exit;
- end;
- UndecorateSymbolNameA := GetProcAddress(ModuleHandle, 'UnDecorateSymbolName');
- UndecorateSymbolNameAFailed := not Assigned(UndecorateSymbolNameA);
- UndecorateSymbolNameW := GetProcAddress(ModuleHandle, 'UnDecorateSymbolNameW');
- UndecorateSymbolNameWFailed := not Assigned(UndecorateSymbolNameW);
- end;
- if Assigned(UndecorateSymbolNameW) then
- begin
- SetLength(WideBuffer, BufferSize);
- Res := UnDecorateSymbolNameW(PWideChar({$IFNDEF UNICODE}WideString{$ENDIF}(DecoratedName)), PWideChar(WideBuffer), BufferSize, Flags);
- if Res > 0 then
- begin
- StrResetLength(WideBuffer);
- UnMangled := string(WideBuffer);
- Result := True;
- end;
- end
- else
- if Assigned(UndecorateSymbolNameA) then
- begin
- SetLength(AnsiBuffer, BufferSize);
- Res := UnDecorateSymbolNameA(PAnsiChar(AnsiString(DecoratedName)), PAnsiChar(AnsiBuffer), BufferSize, Flags);
- if Res > 0 then
- begin
- StrResetLength(AnsiBuffer);
- UnMangled := string(AnsiBuffer);
- Result := True;
- end;
- end;
- // For some functions UnDecorateSymbolName returns 'long'
- if Result and (UnMangled = 'long') then
- UnMangled := DecoratedName;
- end;
- function PeUnmangleName(const Name: string; out Unmangled: string): TJclPeUmResult;
- begin
- Result := umNotMangled;
- case PeBorUnmangleName(Name, Unmangled) of
- urOk:
- Result := umBorland;
- urMicrosoft:
- if UndecorateSymbolName(Name, Unmangled, UNDNAME_NAME_ONLY) then
- Result := umMicrosoft;
- end;
- if Result = umNotMangled then
- Unmangled := Name;
- end;
- {$IFDEF UNITVERSIONING}
- initialization
- RegisterUnitVersion(HInstance, UnitVersioning);
- finalization
- UnregisterUnitVersion(HInstance);
- {$ENDIF UNITVERSIONING}
- end.
|