JclPeImage.pas 225 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094
  1. {**************************************************************************************************}
  2. { }
  3. { Project JEDI Code Library (JCL) }
  4. { }
  5. { The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); }
  6. { you may not use this file except in compliance with the License. You may obtain a copy of the }
  7. { License at http://www.mozilla.org/MPL/ }
  8. { }
  9. { Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF }
  10. { ANY KIND, either express or implied. See the License for the specific language governing rights }
  11. { and limitations under the License. }
  12. { }
  13. { The Original Code is JclPeImage.pas. }
  14. { }
  15. { The Initial Developer of the Original Code is Petr Vones. Portions created by Petr Vones are }
  16. { Copyright (C) Petr Vones. All Rights Reserved. }
  17. { }
  18. { Contributor(s): }
  19. { Marcel van Brakel }
  20. { Robert Marquardt (marquardt) }
  21. { Uwe Schuster (uschuster) }
  22. { Matthias Thoma (mthoma) }
  23. { Petr Vones (pvones) }
  24. { Hallvard Vassbotn }
  25. { Jean-Fabien Connault (cycocrew) }
  26. { }
  27. {**************************************************************************************************}
  28. { }
  29. { This unit contains various classes and support routines to read the contents of portable }
  30. { executable (PE) files. You can use these classes to, for example examine the contents of the }
  31. { imports section of an executable. In addition the unit contains support for Borland specific }
  32. { structures and name unmangling. }
  33. { }
  34. {**************************************************************************************************}
  35. { }
  36. { Last modified: $Date:: $ }
  37. { Revision: $Rev:: $ }
  38. { Author: $Author:: $ }
  39. { }
  40. {**************************************************************************************************}
  41. unit JclPeImage;
  42. {$I jcl.inc}
  43. {$I windowsonly.inc}
  44. interface
  45. uses
  46. {$IFDEF UNITVERSIONING}
  47. JclUnitVersioning,
  48. {$ENDIF UNITVERSIONING}
  49. {$IFDEF HAS_UNITSCOPE}
  50. Winapi.Windows, System.Classes, System.SysUtils, System.TypInfo, System.Contnrs,
  51. {$ELSE ~HAS_UNITSCOPE}
  52. Windows, Classes, SysUtils, TypInfo, Contnrs,
  53. {$ENDIF ~HAS_UNITSCOPE}
  54. JclBase, {$IFNDEF WINSCP}JclDateTime,{$ENDIF ~WINSCP} JclFileUtils, JclWin32;
  55. type
  56. // Smart name compare function
  57. TJclSmartCompOption = (scSimpleCompare, scIgnoreCase);
  58. TJclSmartCompOptions = set of TJclSmartCompOption;
  59. function PeStripFunctionAW(const FunctionName: string): string;
  60. function PeSmartFunctionNameSame(const ComparedName, FunctionName: string;
  61. Options: TJclSmartCompOptions = []): Boolean;
  62. type
  63. // Base list
  64. EJclPeImageError = class(EJclError);
  65. TJclPeImage = class;
  66. TJclPeImageClass = class of TJclPeImage;
  67. TJclPeImageBaseList = class(TObjectList)
  68. private
  69. FImage: TJclPeImage;
  70. public
  71. constructor Create(AImage: TJclPeImage);
  72. property Image: TJclPeImage read FImage;
  73. end;
  74. // Images cache
  75. TJclPeImagesCache = class(TObject)
  76. private
  77. FList: TStringList;
  78. function GetCount: Integer;
  79. function GetImages(const FileName: TFileName): TJclPeImage;
  80. protected
  81. function GetPeImageClass: TJclPeImageClass; virtual;
  82. public
  83. constructor Create;
  84. destructor Destroy; override;
  85. procedure Clear;
  86. property Images[const FileName: TFileName]: TJclPeImage read GetImages; default;
  87. property Count: Integer read GetCount;
  88. end;
  89. // Import section related classes
  90. TJclPeImportSort = (isName, isOrdinal, isHint, isLibImport);
  91. TJclPeImportLibSort = (ilName, ilIndex);
  92. TJclPeImportKind = (ikImport, ikDelayImport, ikBoundImport);
  93. TJclPeResolveCheck = (icNotChecked, icResolved, icUnresolved);
  94. TJclPeLinkerProducer = (lrBorland, lrMicrosoft);
  95. // lrBorland -> Delphi PE files
  96. // lrMicrosoft -> MSVC and BCB PE files
  97. TJclPeImportLibItem = class;
  98. // Created from a IMAGE_THUNK_DATA64 or IMAGE_THUNK_DATA32 record
  99. TJclPeImportFuncItem = class(TObject)
  100. private
  101. FOrdinal: Word; // word in 32/64
  102. FHint: Word;
  103. FImportLib: TJclPeImportLibItem;
  104. FIndirectImportName: Boolean;
  105. FName: string;
  106. FResolveCheck: TJclPeResolveCheck;
  107. function GetIsByOrdinal: Boolean;
  108. protected
  109. procedure SetName(const Value: string);
  110. procedure SetIndirectImportName(const Value: string);
  111. procedure SetResolveCheck(Value: TJclPeResolveCheck);
  112. public
  113. constructor Create(AImportLib: TJclPeImportLibItem; AOrdinal: Word;
  114. AHint: Word; const AName: string);
  115. property Ordinal: Word read FOrdinal;
  116. property Hint: Word read FHint;
  117. property ImportLib: TJclPeImportLibItem read FImportLib;
  118. property IndirectImportName: Boolean read FIndirectImportName;
  119. property IsByOrdinal: Boolean read GetIsByOrdinal;
  120. property Name: string read FName;
  121. property ResolveCheck: TJclPeResolveCheck read FResolveCheck;
  122. end;
  123. // Created from a IMAGE_IMPORT_DESCRIPTOR
  124. TJclPeImportLibItem = class(TJclPeImageBaseList)
  125. private
  126. FImportDescriptor: Pointer;
  127. FImportDirectoryIndex: Integer;
  128. FImportKind: TJclPeImportKind;
  129. FLastSortType: TJclPeImportSort;
  130. FLastSortDescending: Boolean;
  131. FName: string;
  132. FSorted: Boolean;
  133. FUseRVA: Boolean;
  134. FTotalResolveCheck: TJclPeResolveCheck;
  135. FThunk: Pointer;
  136. FThunkData: Pointer;
  137. function GetCount: Integer;
  138. function GetFileName: TFileName;
  139. function GetItems(Index: Integer): TJclPeImportFuncItem;
  140. function GetName: string;
  141. function GetThunkData32: PImageThunkData32;
  142. function GetThunkData64: PImageThunkData64;
  143. protected
  144. procedure CheckImports(ExportImage: TJclPeImage);
  145. procedure CreateList;
  146. procedure SetImportDirectoryIndex(Value: Integer);
  147. procedure SetImportKind(Value: TJclPeImportKind);
  148. procedure SetSorted(Value: Boolean);
  149. procedure SetThunk(Value: Pointer);
  150. public
  151. constructor Create(AImage: TJclPeImage; AImportDescriptor: Pointer;
  152. AImportKind: TJclPeImportKind; const AName: string; AThunk: Pointer; AUseRVA: Boolean = True);
  153. procedure SortList(SortType: TJclPeImportSort; Descending: Boolean = False);
  154. property Count: Integer read GetCount;
  155. property FileName: TFileName read GetFileName;
  156. property ImportDescriptor: Pointer read FImportDescriptor;
  157. property ImportDirectoryIndex: Integer read FImportDirectoryIndex;
  158. property ImportKind: TJclPeImportKind read FImportKind;
  159. property Items[Index: Integer]: TJclPeImportFuncItem read GetItems; default;
  160. property Name: string read GetName;
  161. property OriginalName: string read FName;
  162. // use the following properties
  163. // property ThunkData: PImageThunkData
  164. property ThunkData32: PImageThunkData32 read GetThunkData32;
  165. property ThunkData64: PImageThunkData64 read GetThunkData64;
  166. property TotalResolveCheck: TJclPeResolveCheck read FTotalResolveCheck;
  167. end;
  168. TJclPeImportList = class(TJclPeImageBaseList)
  169. private
  170. FAllItemsList: TList;
  171. FFilterModuleName: string;
  172. FLastAllSortType: TJclPeImportSort;
  173. FLastAllSortDescending: Boolean;
  174. FLinkerProducer: TJclPeLinkerProducer;
  175. FParallelImportTable: array of Pointer;
  176. FUniqueNamesList: TStringList;
  177. function GetAllItemCount: Integer;
  178. function GetAllItems(Index: Integer): TJclPeImportFuncItem;
  179. function GetItems(Index: Integer): TJclPeImportLibItem;
  180. function GetUniqueLibItemCount: Integer;
  181. function GetUniqueLibItems(Index: Integer): TJclPeImportLibItem;
  182. function GetUniqueLibNames(Index: Integer): string;
  183. function GetUniqueLibItemFromName(const Name: string): TJclPeImportLibItem;
  184. procedure SetFilterModuleName(const Value: string);
  185. protected
  186. procedure CreateList;
  187. procedure RefreshAllItems;
  188. public
  189. constructor Create(AImage: TJclPeImage);
  190. destructor Destroy; override;
  191. procedure CheckImports(PeImageCache: TJclPeImagesCache = nil);
  192. function MakeBorlandImportTableForMappedImage: Boolean;
  193. function SmartFindName(const CompareName, LibName: string; Options: TJclSmartCompOptions = []): TJclPeImportFuncItem;
  194. procedure SortAllItemsList(SortType: TJclPeImportSort; Descending: Boolean = False);
  195. procedure SortList(SortType: TJclPeImportLibSort);
  196. procedure TryGetNamesForOrdinalImports;
  197. property AllItems[Index: Integer]: TJclPeImportFuncItem read GetAllItems;
  198. property AllItemCount: Integer read GetAllItemCount;
  199. property FilterModuleName: string read FFilterModuleName write SetFilterModuleName;
  200. property Items[Index: Integer]: TJclPeImportLibItem read GetItems; default;
  201. property LinkerProducer: TJclPeLinkerProducer read FLinkerProducer;
  202. property UniqueLibItemCount: Integer read GetUniqueLibItemCount;
  203. property UniqueLibItemFromName[const Name: string]: TJclPeImportLibItem read GetUniqueLibItemFromName;
  204. property UniqueLibItems[Index: Integer]: TJclPeImportLibItem read GetUniqueLibItems;
  205. property UniqueLibNames[Index: Integer]: string read GetUniqueLibNames;
  206. end;
  207. // Export section related classes
  208. TJclPeExportSort = (esName, esOrdinal, esHint, esAddress, esForwarded, esAddrOrFwd, esSection);
  209. TJclPeExportFuncList = class;
  210. // Created from a IMAGE_EXPORT_DIRECTORY
  211. TJclPeExportFuncItem = class(TObject)
  212. private
  213. FAddress: DWORD;
  214. FExportList: TJclPeExportFuncList;
  215. FForwardedName: string;
  216. FForwardedDotPos: string;
  217. FHint: Word;
  218. FName: string;
  219. FOrdinal: Word;
  220. FResolveCheck: TJclPeResolveCheck;
  221. function GetAddressOrForwardStr: string;
  222. function GetForwardedFuncName: string;
  223. function GetForwardedLibName: string;
  224. function GetForwardedFuncOrdinal: DWORD;
  225. function GetIsExportedVariable: Boolean;
  226. function GetIsForwarded: Boolean;
  227. function GetSectionName: string;
  228. function GetMappedAddress: Pointer;
  229. protected
  230. procedure SetResolveCheck(Value: TJclPeResolveCheck);
  231. public
  232. constructor Create(AExportList: TJclPeExportFuncList; const AName, AForwardedName: string;
  233. AAddress: DWORD; AHint: Word; AOrdinal: Word; AResolveCheck: TJclPeResolveCheck);
  234. property Address: DWORD read FAddress;
  235. property AddressOrForwardStr: string read GetAddressOrForwardStr;
  236. property IsExportedVariable: Boolean read GetIsExportedVariable;
  237. property IsForwarded: Boolean read GetIsForwarded;
  238. property ForwardedName: string read FForwardedName;
  239. property ForwardedLibName: string read GetForwardedLibName;
  240. property ForwardedFuncOrdinal: DWORD read GetForwardedFuncOrdinal;
  241. property ForwardedFuncName: string read GetForwardedFuncName;
  242. property Hint: Word read FHint;
  243. property MappedAddress: Pointer read GetMappedAddress;
  244. property Name: string read FName;
  245. property Ordinal: Word read FOrdinal;
  246. property ResolveCheck: TJclPeResolveCheck read FResolveCheck;
  247. property SectionName: string read GetSectionName;
  248. end;
  249. TJclPeExportFuncList = class(TJclPeImageBaseList)
  250. private
  251. FAnyForwards: Boolean;
  252. FBase: DWORD;
  253. FExportDir: PImageExportDirectory;
  254. FForwardedLibsList: TStringList;
  255. FFunctionCount: DWORD;
  256. FLastSortType: TJclPeExportSort;
  257. FLastSortDescending: Boolean;
  258. FSorted: Boolean;
  259. FTotalResolveCheck: TJclPeResolveCheck;
  260. function GetForwardedLibsList: TStrings;
  261. function GetItems(Index: Integer): TJclPeExportFuncItem;
  262. function GetItemFromAddress(Address: DWORD): TJclPeExportFuncItem;
  263. function GetItemFromOrdinal(Ordinal: DWORD): TJclPeExportFuncItem;
  264. function GetItemFromName(const Name: string): TJclPeExportFuncItem;
  265. function GetName: string;
  266. protected
  267. function CanPerformFastNameSearch: Boolean;
  268. procedure CreateList;
  269. property LastSortType: TJclPeExportSort read FLastSortType;
  270. property LastSortDescending: Boolean read FLastSortDescending;
  271. property Sorted: Boolean read FSorted;
  272. public
  273. constructor Create(AImage: TJclPeImage);
  274. destructor Destroy; override;
  275. procedure CheckForwards(PeImageCache: TJclPeImagesCache = nil);
  276. class function ItemName(Item: TJclPeExportFuncItem): string;
  277. function OrdinalValid(Ordinal: DWORD): Boolean;
  278. procedure PrepareForFastNameSearch;
  279. function SmartFindName(const CompareName: string; Options: TJclSmartCompOptions = []): TJclPeExportFuncItem;
  280. procedure SortList(SortType: TJclPeExportSort; Descending: Boolean = False);
  281. property AnyForwards: Boolean read FAnyForwards;
  282. property Base: DWORD read FBase;
  283. property ExportDir: PImageExportDirectory read FExportDir;
  284. property ForwardedLibsList: TStrings read GetForwardedLibsList;
  285. property FunctionCount: DWORD read FFunctionCount;
  286. property Items[Index: Integer]: TJclPeExportFuncItem read GetItems; default;
  287. property ItemFromAddress[Address: DWORD]: TJclPeExportFuncItem read GetItemFromAddress;
  288. property ItemFromName[const Name: string]: TJclPeExportFuncItem read GetItemFromName;
  289. property ItemFromOrdinal[Ordinal: DWORD]: TJclPeExportFuncItem read GetItemFromOrdinal;
  290. property Name: string read GetName;
  291. property TotalResolveCheck: TJclPeResolveCheck read FTotalResolveCheck;
  292. end;
  293. // Resource section related classes
  294. TJclPeResourceKind = (
  295. rtUnknown0,
  296. rtCursorEntry,
  297. rtBitmap,
  298. rtIconEntry,
  299. rtMenu,
  300. rtDialog,
  301. rtString,
  302. rtFontDir,
  303. rtFont,
  304. rtAccelerators,
  305. rtRCData,
  306. rtMessageTable,
  307. rtCursor,
  308. rtUnknown13,
  309. rtIcon,
  310. rtUnknown15,
  311. rtVersion,
  312. rtDlgInclude,
  313. rtUnknown18,
  314. rtPlugPlay,
  315. rtVxd,
  316. rtAniCursor,
  317. rtAniIcon,
  318. rtHmtl,
  319. rtManifest,
  320. rtUserDefined);
  321. TJclPeResourceList = class;
  322. TJclPeResourceItem = class;
  323. TJclPeResourceRawStream = class(TCustomMemoryStream)
  324. public
  325. constructor Create(AResourceItem: TJclPeResourceItem);
  326. function Write(const Buffer; Count: Longint): Longint; override;
  327. end;
  328. TJclPeResourceItem = class(TObject)
  329. private
  330. FEntry: PImageResourceDirectoryEntry;
  331. FImage: TJclPeImage;
  332. FList: TJclPeResourceList;
  333. FLevel: Byte;
  334. FParentItem: TJclPeResourceItem;
  335. FNameCache: string;
  336. function GetDataEntry: PImageResourceDataEntry;
  337. function GetIsDirectory: Boolean;
  338. function GetIsName: Boolean;
  339. function GetLangID: LANGID;
  340. function GetList: TJclPeResourceList;
  341. function GetName: string;
  342. function GetParameterName: string;
  343. function GetRawEntryData: Pointer;
  344. function GetRawEntryDataSize: Integer;
  345. function GetResourceType: TJclPeResourceKind;
  346. function GetResourceTypeStr: string;
  347. protected
  348. function OffsetToRawData(Ofs: DWORD): TJclAddr;
  349. function Level1Item: TJclPeResourceItem;
  350. function SubDirData: PImageResourceDirectory;
  351. public
  352. constructor Create(AImage: TJclPeImage; AParentItem: TJclPeResourceItem;
  353. AEntry: PImageResourceDirectoryEntry);
  354. destructor Destroy; override;
  355. function CompareName(AName: PChar): Boolean;
  356. property DataEntry: PImageResourceDataEntry read GetDataEntry;
  357. property Entry: PImageResourceDirectoryEntry read FEntry;
  358. property Image: TJclPeImage read FImage;
  359. property IsDirectory: Boolean read GetIsDirectory;
  360. property IsName: Boolean read GetIsName;
  361. property LangID: LANGID read GetLangID;
  362. property List: TJclPeResourceList read GetList;
  363. property Level: Byte read FLevel;
  364. property Name: string read GetName;
  365. property ParameterName: string read GetParameterName;
  366. property ParentItem: TJclPeResourceItem read FParentItem;
  367. property RawEntryData: Pointer read GetRawEntryData;
  368. property RawEntryDataSize: Integer read GetRawEntryDataSize;
  369. property ResourceType: TJclPeResourceKind read GetResourceType;
  370. property ResourceTypeStr: string read GetResourceTypeStr;
  371. end;
  372. TJclPeResourceList = class(TJclPeImageBaseList)
  373. private
  374. FDirectory: PImageResourceDirectory;
  375. FParentItem: TJclPeResourceItem;
  376. function GetItems(Index: Integer): TJclPeResourceItem;
  377. protected
  378. procedure CreateList(AParentItem: TJclPeResourceItem);
  379. public
  380. constructor Create(AImage: TJclPeImage; AParentItem: TJclPeResourceItem;
  381. ADirectory: PImageResourceDirectory);
  382. function FindName(const Name: string): TJclPeResourceItem;
  383. property Directory: PImageResourceDirectory read FDirectory;
  384. property Items[Index: Integer]: TJclPeResourceItem read GetItems; default;
  385. property ParentItem: TJclPeResourceItem read FParentItem;
  386. end;
  387. TJclPeRootResourceList = class(TJclPeResourceList)
  388. private
  389. FManifestContent: TStringList;
  390. function GetManifestContent: TStrings;
  391. public
  392. destructor Destroy; override;
  393. function FindResource(ResourceType: TJclPeResourceKind;
  394. const ResourceName: string = ''): TJclPeResourceItem; overload;
  395. function FindResource(const ResourceType: PChar;
  396. const ResourceName: PChar = nil): TJclPeResourceItem; overload;
  397. function ListResourceNames(ResourceType: TJclPeResourceKind; const Strings: TStrings): Boolean;
  398. property ManifestContent: TStrings read GetManifestContent;
  399. end;
  400. // Relocation section related classes
  401. TJclPeRelocation = record
  402. Address: Word;
  403. RelocType: Byte;
  404. VirtualAddress: DWORD;
  405. end;
  406. TJclPeRelocEntry = class(TObject)
  407. private
  408. FChunk: PImageBaseRelocation;
  409. FCount: Integer;
  410. function GetRelocations(Index: Integer): TJclPeRelocation;
  411. function GetSize: DWORD;
  412. function GetVirtualAddress: DWORD;
  413. public
  414. constructor Create(AChunk: PImageBaseRelocation; ACount: Integer);
  415. property Count: Integer read FCount;
  416. property Relocations[Index: Integer]: TJclPeRelocation read GetRelocations; default;
  417. property Size: DWORD read GetSize;
  418. property VirtualAddress: DWORD read GetVirtualAddress;
  419. end;
  420. TJclPeRelocList = class(TJclPeImageBaseList)
  421. private
  422. FAllItemCount: Integer;
  423. function GetItems(Index: Integer): TJclPeRelocEntry;
  424. function GetAllItems(Index: Integer): TJclPeRelocation;
  425. protected
  426. procedure CreateList;
  427. public
  428. constructor Create(AImage: TJclPeImage);
  429. property AllItems[Index: Integer]: TJclPeRelocation read GetAllItems;
  430. property AllItemCount: Integer read FAllItemCount;
  431. property Items[Index: Integer]: TJclPeRelocEntry read GetItems; default;
  432. end;
  433. // Debug section related classes
  434. TJclPeDebugList = class(TJclPeImageBaseList)
  435. private
  436. function GetItems(Index: Integer): TImageDebugDirectory;
  437. function IsTD32DebugInfo(DebugDir: PImageDebugDirectory): Boolean;
  438. protected
  439. procedure CreateList;
  440. public
  441. constructor Create(AImage: TJclPeImage);
  442. property Items[Index: Integer]: TImageDebugDirectory read GetItems; default;
  443. end;
  444. // Certificates section related classes
  445. TJclPeCertificate = class(TObject)
  446. private
  447. FData: Pointer;
  448. FHeader: TWinCertificate;
  449. public
  450. constructor Create(AHeader: TWinCertificate; AData: Pointer);
  451. property Data: Pointer read FData;
  452. property Header: TWinCertificate read FHeader;
  453. end;
  454. TJclPeCertificateList = class(TJclPeImageBaseList)
  455. private
  456. function GetItems(Index: Integer): TJclPeCertificate;
  457. protected
  458. procedure CreateList;
  459. public
  460. constructor Create(AImage: TJclPeImage);
  461. property Items[Index: Integer]: TJclPeCertificate read GetItems; default;
  462. end;
  463. // Common Language Runtime section related classes
  464. TJclPeCLRHeader = class(TObject)
  465. private
  466. FHeader: TImageCor20Header;
  467. FImage: TJclPeImage;
  468. function GetVersionString: string;
  469. function GetHasMetadata: Boolean;
  470. protected
  471. procedure ReadHeader;
  472. public
  473. constructor Create(AImage: TJclPeImage);
  474. property HasMetadata: Boolean read GetHasMetadata;
  475. property Header: TImageCor20Header read FHeader;
  476. property VersionString: string read GetVersionString;
  477. property Image: TJclPeImage read FImage;
  478. end;
  479. // PE Image
  480. TJclPeHeader = (
  481. JclPeHeader_Signature,
  482. JclPeHeader_Machine,
  483. JclPeHeader_NumberOfSections,
  484. JclPeHeader_TimeDateStamp,
  485. JclPeHeader_PointerToSymbolTable,
  486. JclPeHeader_NumberOfSymbols,
  487. JclPeHeader_SizeOfOptionalHeader,
  488. JclPeHeader_Characteristics,
  489. JclPeHeader_Magic,
  490. JclPeHeader_LinkerVersion,
  491. JclPeHeader_SizeOfCode,
  492. JclPeHeader_SizeOfInitializedData,
  493. JclPeHeader_SizeOfUninitializedData,
  494. JclPeHeader_AddressOfEntryPoint,
  495. JclPeHeader_BaseOfCode,
  496. JclPeHeader_BaseOfData,
  497. JclPeHeader_ImageBase,
  498. JclPeHeader_SectionAlignment,
  499. JclPeHeader_FileAlignment,
  500. JclPeHeader_OperatingSystemVersion,
  501. JclPeHeader_ImageVersion,
  502. JclPeHeader_SubsystemVersion,
  503. JclPeHeader_Win32VersionValue,
  504. JclPeHeader_SizeOfImage,
  505. JclPeHeader_SizeOfHeaders,
  506. JclPeHeader_CheckSum,
  507. JclPeHeader_Subsystem,
  508. JclPeHeader_DllCharacteristics,
  509. JclPeHeader_SizeOfStackReserve,
  510. JclPeHeader_SizeOfStackCommit,
  511. JclPeHeader_SizeOfHeapReserve,
  512. JclPeHeader_SizeOfHeapCommit,
  513. JclPeHeader_LoaderFlags,
  514. JclPeHeader_NumberOfRvaAndSizes);
  515. TJclLoadConfig = (
  516. JclLoadConfig_Characteristics, { TODO : rename to Size? }
  517. JclLoadConfig_TimeDateStamp,
  518. JclLoadConfig_Version,
  519. JclLoadConfig_GlobalFlagsClear,
  520. JclLoadConfig_GlobalFlagsSet,
  521. JclLoadConfig_CriticalSectionDefaultTimeout,
  522. JclLoadConfig_DeCommitFreeBlockThreshold,
  523. JclLoadConfig_DeCommitTotalFreeThreshold,
  524. JclLoadConfig_LockPrefixTable,
  525. JclLoadConfig_MaximumAllocationSize,
  526. JclLoadConfig_VirtualMemoryThreshold,
  527. JclLoadConfig_ProcessHeapFlags,
  528. JclLoadConfig_ProcessAffinityMask,
  529. JclLoadConfig_CSDVersion,
  530. JclLoadConfig_Reserved1,
  531. JclLoadConfig_EditList,
  532. JclLoadConfig_Reserved { TODO : extend to the new fields? }
  533. );
  534. TJclPeFileProperties = record
  535. Size: DWORD;
  536. CreationTime: TDateTime;
  537. LastAccessTime: TDateTime;
  538. LastWriteTime: TDateTime;
  539. Attributes: Integer;
  540. end;
  541. TJclPeImageStatus = (stNotLoaded, stOk, stNotPE, stNotSupported, stNotFound, stError);
  542. TJclPeTarget = (taUnknown, taWin32, taWin64);
  543. TJclPeImage = class(TObject)
  544. private
  545. FAttachedImage: Boolean;
  546. FCertificateList: TJclPeCertificateList;
  547. FCLRHeader: TJclPeCLRHeader;
  548. FDebugList: TJclPeDebugList;
  549. FFileName: TFileName;
  550. FImageSections: TStringList;
  551. FLoadedImage: TLoadedImage;
  552. FExportList: TJclPeExportFuncList;
  553. FImportList: TJclPeImportList;
  554. FNoExceptions: Boolean;
  555. FReadOnlyAccess: Boolean;
  556. FRelocationList: TJclPeRelocList;
  557. FResourceList: TJclPeRootResourceList;
  558. FResourceVA: TJclAddr;
  559. FStatus: TJclPeImageStatus;
  560. FTarget: TJclPeTarget;
  561. FVersionInfo: TJclFileVersionInfo;
  562. FStringTable: TStringList;
  563. function GetCertificateList: TJclPeCertificateList;
  564. function GetCLRHeader: TJclPeCLRHeader;
  565. function GetDebugList: TJclPeDebugList;
  566. function GetDescription: string;
  567. function GetDirectories(Directory: Word): TImageDataDirectory;
  568. function GetDirectoryExists(Directory: Word): Boolean;
  569. function GetExportList: TJclPeExportFuncList;
  570. {$IFNDEF WINSCP}
  571. function GetFileProperties: TJclPeFileProperties;
  572. {$ENDIF ~WINSCP}
  573. function GetImageSectionCount: Integer;
  574. function GetImageSectionHeaders(Index: Integer): TImageSectionHeader;
  575. function GetImageSectionNames(Index: Integer): string;
  576. function GetImageSectionNameFromRva(const Rva: DWORD): string;
  577. function GetImportList: TJclPeImportList;
  578. function GetHeaderValues(Index: TJclPeHeader): string;
  579. function GetLoadConfigValues(Index: TJclLoadConfig): string;
  580. function GetMappedAddress: TJclAddr;
  581. function GetOptionalHeader32: TImageOptionalHeader32;
  582. function GetOptionalHeader64: TImageOptionalHeader64;
  583. function GetRelocationList: TJclPeRelocList;
  584. function GetResourceList: TJclPeRootResourceList;
  585. function GetUnusedHeaderBytes: TImageDataDirectory;
  586. function GetVersionInfo: TJclFileVersionInfo;
  587. function GetVersionInfoAvailable: Boolean;
  588. procedure ReadImageSections;
  589. procedure ReadStringTable;
  590. procedure SetFileName(const Value: TFileName);
  591. function GetStringTableCount: Integer;
  592. function GetStringTableItem(Index: Integer): string;
  593. function GetImageSectionFullNames(Index: Integer): string;
  594. protected
  595. procedure AfterOpen; dynamic;
  596. procedure CheckNotAttached;
  597. procedure Clear; dynamic;
  598. function ExpandModuleName(const ModuleName: string): TFileName;
  599. procedure RaiseStatusException;
  600. function ResourceItemCreate(AEntry: PImageResourceDirectoryEntry;
  601. AParentItem: TJclPeResourceItem): TJclPeResourceItem; virtual;
  602. function ResourceListCreate(ADirectory: PImageResourceDirectory;
  603. AParentItem: TJclPeResourceItem): TJclPeResourceList; virtual;
  604. property NoExceptions: Boolean read FNoExceptions;
  605. public
  606. constructor Create(ANoExceptions: Boolean = False); virtual;
  607. destructor Destroy; override;
  608. procedure AttachLoadedModule(const Handle: HMODULE);
  609. function CalculateCheckSum: DWORD;
  610. function DirectoryEntryToData(Directory: Word): Pointer;
  611. function GetSectionHeader(const SectionName: string; out Header: PImageSectionHeader): Boolean;
  612. function GetSectionName(Header: PImageSectionHeader): string;
  613. function GetNameInStringTable(Offset: ULONG): string;
  614. function IsBrokenFormat: Boolean;
  615. function IsCLR: Boolean;
  616. function IsSystemImage: Boolean;
  617. // RVA are always DWORD
  618. function RawToVa(Raw: DWORD): Pointer; overload;
  619. function RvaToSection(Rva: DWORD): PImageSectionHeader; overload;
  620. function RvaToVa(Rva: DWORD): Pointer; overload;
  621. function ImageAddressToRva(Address: DWORD): DWORD;
  622. function StatusOK: Boolean;
  623. procedure TryGetNamesForOrdinalImports;
  624. function VerifyCheckSum: Boolean;
  625. class function DebugTypeNames(DebugType: DWORD): string;
  626. class function DirectoryNames(Directory: Word): string;
  627. class function ExpandBySearchPath(const ModuleName, BasePath: string): TFileName;
  628. class function HeaderNames(Index: TJclPeHeader): string;
  629. class function LoadConfigNames(Index: TJclLoadConfig): string;
  630. class function ShortSectionInfo(Characteristics: DWORD): string;
  631. class function DateTimeToStamp(const DateTime: TDateTime): DWORD;
  632. class function StampToDateTime(TimeDateStamp: DWORD): TDateTime;
  633. property AttachedImage: Boolean read FAttachedImage;
  634. property CertificateList: TJclPeCertificateList read GetCertificateList;
  635. property CLRHeader: TJclPeCLRHeader read GetCLRHeader;
  636. property DebugList: TJclPeDebugList read GetDebugList;
  637. property Description: string read GetDescription;
  638. property Directories[Directory: Word]: TImageDataDirectory read GetDirectories;
  639. property DirectoryExists[Directory: Word]: Boolean read GetDirectoryExists;
  640. property ExportList: TJclPeExportFuncList read GetExportList;
  641. property FileName: TFileName read FFileName write SetFileName;
  642. {$IFNDEF WINSCP}
  643. property FileProperties: TJclPeFileProperties read GetFileProperties;
  644. {$ENDIF ~WINSCP}
  645. property HeaderValues[Index: TJclPeHeader]: string read GetHeaderValues;
  646. property ImageSectionCount: Integer read GetImageSectionCount;
  647. property ImageSectionHeaders[Index: Integer]: TImageSectionHeader read GetImageSectionHeaders;
  648. property ImageSectionNames[Index: Integer]: string read GetImageSectionNames;
  649. property ImageSectionFullNames[Index: Integer]: string read GetImageSectionFullNames;
  650. property ImageSectionNameFromRva[const Rva: DWORD]: string read GetImageSectionNameFromRva;
  651. property ImportList: TJclPeImportList read GetImportList;
  652. property LoadConfigValues[Index: TJclLoadConfig]: string read GetLoadConfigValues;
  653. property LoadedImage: TLoadedImage read FLoadedImage;
  654. property MappedAddress: TJclAddr read GetMappedAddress;
  655. property StringTableCount: Integer read GetStringTableCount;
  656. property StringTable[Index: Integer]: string read GetStringTableItem;
  657. // use the following properties
  658. // property OptionalHeader: TImageOptionalHeader
  659. property OptionalHeader32: TImageOptionalHeader32 read GetOptionalHeader32;
  660. property OptionalHeader64: TImageOptionalHeader64 read GetOptionalHeader64;
  661. property ReadOnlyAccess: Boolean read FReadOnlyAccess write FReadOnlyAccess;
  662. property RelocationList: TJclPeRelocList read GetRelocationList;
  663. property ResourceVA: TJclAddr read FResourceVA;
  664. property ResourceList: TJclPeRootResourceList read GetResourceList;
  665. property Status: TJclPeImageStatus read FStatus;
  666. property Target: TJclPeTarget read FTarget;
  667. property UnusedHeaderBytes: TImageDataDirectory read GetUnusedHeaderBytes;
  668. property VersionInfo: TJclFileVersionInfo read GetVersionInfo;
  669. property VersionInfoAvailable: Boolean read GetVersionInfoAvailable;
  670. end;
  671. {$IFDEF BORLAND}
  672. TJclPeBorImage = class;
  673. TJclPeBorImagesCache = class(TJclPeImagesCache)
  674. private
  675. function GetImages(const FileName: TFileName): TJclPeBorImage;
  676. protected
  677. function GetPeImageClass: TJclPeImageClass; override;
  678. public
  679. property Images[const FileName: TFileName]: TJclPeBorImage read GetImages; default;
  680. end;
  681. // Borland Delphi PE Image specific information
  682. TJclPePackageInfo = class(TObject)
  683. private
  684. FAvailable: Boolean;
  685. FContains: TStringList;
  686. FDcpName: string;
  687. FRequires: TStringList;
  688. FFlags: Integer;
  689. FDescription: string;
  690. FEnsureExtension: Boolean;
  691. FSorted: Boolean;
  692. function GetContains: TStrings;
  693. function GetContainsCount: Integer;
  694. function GetContainsFlags(Index: Integer): Byte;
  695. function GetContainsNames(Index: Integer): string;
  696. function GetRequires: TStrings;
  697. function GetRequiresCount: Integer;
  698. function GetRequiresNames(Index: Integer): string;
  699. protected
  700. procedure ReadPackageInfo(ALibHandle: THandle);
  701. procedure SetDcpName(const Value: string);
  702. public
  703. constructor Create(ALibHandle: THandle);
  704. destructor Destroy; override;
  705. class function PackageModuleTypeToString(Flags: Cardinal): string;
  706. class function PackageOptionsToString(Flags: Cardinal): string;
  707. class function ProducerToString(Flags: Cardinal): string;
  708. class function UnitInfoFlagsToString(UnitFlags: Byte): string;
  709. property Available: Boolean read FAvailable;
  710. property Contains: TStrings read GetContains;
  711. property ContainsCount: Integer read GetContainsCount;
  712. property ContainsNames[Index: Integer]: string read GetContainsNames;
  713. property ContainsFlags[Index: Integer]: Byte read GetContainsFlags;
  714. property Description: string read FDescription;
  715. property DcpName: string read FDcpName;
  716. property EnsureExtension: Boolean read FEnsureExtension write FEnsureExtension;
  717. property Flags: Integer read FFlags;
  718. property Requires: TStrings read GetRequires;
  719. property RequiresCount: Integer read GetRequiresCount;
  720. property RequiresNames[Index: Integer]: string read GetRequiresNames;
  721. property Sorted: Boolean read FSorted write FSorted;
  722. end;
  723. TJclPeBorForm = class(TObject)
  724. private
  725. FFormFlags: TFilerFlags;
  726. FFormClassName: string;
  727. FFormObjectName: string;
  728. FFormPosition: Integer;
  729. FResItem: TJclPeResourceItem;
  730. function GetDisplayName: string;
  731. public
  732. constructor Create(AResItem: TJclPeResourceItem; AFormFlags: TFilerFlags;
  733. AFormPosition: Integer; const AFormClassName, AFormObjectName: string);
  734. procedure ConvertFormToText(const Stream: TStream); overload;
  735. procedure ConvertFormToText(const Strings: TStrings); overload;
  736. property FormClassName: string read FFormClassName;
  737. property FormFlags: TFilerFlags read FFormFlags;
  738. property FormObjectName: string read FFormObjectName;
  739. property FormPosition: Integer read FFormPosition;
  740. property DisplayName: string read GetDisplayName;
  741. property ResItem: TJclPeResourceItem read FResItem;
  742. end;
  743. TJclPeBorImage = class(TJclPeImage)
  744. private
  745. FForms: TObjectList;
  746. FIsPackage: Boolean;
  747. FIsBorlandImage: Boolean;
  748. FLibHandle: THandle;
  749. FPackageInfo: TJclPePackageInfo;
  750. FPackageInfoSorted: Boolean;
  751. FPackageCompilerVersion: Integer;
  752. function GetFormCount: Integer;
  753. function GetForms(Index: Integer): TJclPeBorForm;
  754. function GetFormFromName(const FormClassName: string): TJclPeBorForm;
  755. function GetLibHandle: THandle;
  756. function GetPackageCompilerVersion: Integer;
  757. function GetPackageInfo: TJclPePackageInfo;
  758. protected
  759. procedure AfterOpen; override;
  760. procedure Clear; override;
  761. procedure CreateFormsList;
  762. public
  763. constructor Create(ANoExceptions: Boolean = False); override;
  764. destructor Destroy; override;
  765. function DependedPackages(List: TStrings; FullPathName, Descriptions: Boolean): Boolean;
  766. function FreeLibHandle: Boolean;
  767. property Forms[Index: Integer]: TJclPeBorForm read GetForms;
  768. property FormCount: Integer read GetFormCount;
  769. property FormFromName[const FormClassName: string]: TJclPeBorForm read GetFormFromName;
  770. property IsBorlandImage: Boolean read FIsBorlandImage;
  771. property IsPackage: Boolean read FIsPackage;
  772. property LibHandle: THandle read GetLibHandle;
  773. property PackageCompilerVersion: Integer read GetPackageCompilerVersion;
  774. property PackageInfo: TJclPePackageInfo read GetPackageInfo;
  775. property PackageInfoSorted: Boolean read FPackageInfoSorted write FPackageInfoSorted;
  776. end;
  777. {$ENDIF BORLAND}
  778. // Threaded function search
  779. TJclPeNameSearchOption = (seImports, seDelayImports, seBoundImports, seExports);
  780. TJclPeNameSearchOptions = set of TJclPeNameSearchOption;
  781. TJclPeNameSearchNotifyEvent = procedure (Sender: TObject; PeImage: TJclPeImage;
  782. var Process: Boolean) of object;
  783. TJclPeNameSearchFoundEvent = procedure (Sender: TObject; const FileName: TFileName;
  784. const FunctionName: string; Option: TJclPeNameSearchOption) of object;
  785. TJclPeNameSearch = class(TThread)
  786. private
  787. F_FileName: TFileName;
  788. F_FunctionName: string;
  789. F_Option: TJclPeNameSearchOption;
  790. F_Process: Boolean;
  791. FFunctionName: string;
  792. FOptions: TJclPeNameSearchOptions;
  793. FPath: string;
  794. FPeImage: TJclPeImage;
  795. FOnFound: TJclPeNameSearchFoundEvent;
  796. FOnProcessFile: TJclPeNameSearchNotifyEvent;
  797. protected
  798. function CompareName(const FunctionName, ComparedName: string): Boolean; virtual;
  799. procedure DoFound;
  800. procedure DoProcessFile;
  801. procedure Execute; override;
  802. public
  803. constructor Create(const FunctionName, Path: string; Options: TJclPeNameSearchOptions = [seImports, seExports]);
  804. procedure Start;
  805. property OnFound: TJclPeNameSearchFoundEvent read FOnFound write FOnFound;
  806. property OnProcessFile: TJclPeNameSearchNotifyEvent read FOnProcessFile write FOnProcessFile;
  807. end;
  808. // PE Image miscellaneous functions
  809. type
  810. TJclRebaseImageInfo32 = record
  811. OldImageSize: DWORD;
  812. OldImageBase: TJclAddr32;
  813. NewImageSize: DWORD;
  814. NewImageBase: TJclAddr32;
  815. end;
  816. TJclRebaseImageInfo64 = record
  817. OldImageSize: DWORD;
  818. OldImageBase: TJclAddr64;
  819. NewImageSize: DWORD;
  820. NewImageBase: TJclAddr64;
  821. end;
  822. // renamed
  823. // TJclRebaseImageInfo = TJclRebaseImageInfo32;
  824. { Image validity }
  825. function IsValidPeFile(const FileName: TFileName): Boolean;
  826. // use PeGetNtHeaders32 for backward compatibility
  827. // function PeGetNtHeaders(const FileName: TFileName; out NtHeaders: TImageNtHeaders): Boolean;
  828. function PeGetNtHeaders32(const FileName: TFileName; out NtHeaders: TImageNtHeaders32): Boolean;
  829. function PeGetNtHeaders64(const FileName: TFileName; out NtHeaders: TImageNtHeaders64): Boolean;
  830. { Image modifications }
  831. function PeCreateNameHintTable(const FileName: TFileName): Boolean;
  832. // use PeRebaseImage32
  833. //function PeRebaseImage(const ImageName: TFileName; NewBase: DWORD = 0; TimeStamp: DWORD = 0;
  834. // MaxNewSize: DWORD = 0): TJclRebaseImageInfo;
  835. function PeRebaseImage32(const ImageName: TFileName; NewBase: TJclAddr32 = 0; TimeStamp: DWORD = 0;
  836. MaxNewSize: DWORD = 0): TJclRebaseImageInfo32;
  837. function PeRebaseImage64(const ImageName: TFileName; NewBase: TJclAddr64 = 0; TimeStamp: DWORD = 0;
  838. MaxNewSize: DWORD = 0): TJclRebaseImageInfo64;
  839. function PeUpdateLinkerTimeStamp(const FileName: TFileName; const Time: TDateTime): Boolean;
  840. function PeReadLinkerTimeStamp(const FileName: TFileName): TDateTime;
  841. function PeInsertSection(const FileName: TFileName; SectionStream: TStream; SectionName: string): Boolean;
  842. { Image Checksum }
  843. function PeVerifyCheckSum(const FileName: TFileName): Boolean;
  844. function PeClearCheckSum(const FileName: TFileName): Boolean;
  845. function PeUpdateCheckSum(const FileName: TFileName): Boolean;
  846. // Various simple PE Image searching and listing routines
  847. { Exports searching }
  848. function PeDoesExportFunction(const FileName: TFileName; const FunctionName: string;
  849. Options: TJclSmartCompOptions = []): Boolean;
  850. function PeIsExportFunctionForwardedEx(const FileName: TFileName; const FunctionName: string;
  851. out ForwardedName: string; Options: TJclSmartCompOptions = []): Boolean;
  852. function PeIsExportFunctionForwarded(const FileName: TFileName; const FunctionName: string;
  853. Options: TJclSmartCompOptions = []): Boolean;
  854. { Imports searching }
  855. function PeDoesImportFunction(const FileName: TFileName; const FunctionName: string;
  856. const LibraryName: string = ''; Options: TJclSmartCompOptions = []): Boolean;
  857. function PeDoesImportLibrary(const FileName: TFileName; const LibraryName: string;
  858. Recursive: Boolean = False): Boolean;
  859. { Imports listing }
  860. function PeImportedLibraries(const FileName: TFileName; const LibrariesList: TStrings;
  861. Recursive: Boolean = False; FullPathName: Boolean = False): Boolean;
  862. function PeImportedFunctions(const FileName: TFileName; const FunctionsList: TStrings;
  863. const LibraryName: string = ''; IncludeLibNames: Boolean = False): Boolean;
  864. { Exports listing }
  865. function PeExportedFunctions(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
  866. function PeExportedNames(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
  867. function PeExportedVariables(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
  868. { Resources listing }
  869. function PeResourceKindNames(const FileName: TFileName; ResourceType: TJclPeResourceKind;
  870. const NamesList: TStrings): Boolean;
  871. { Borland packages specific }
  872. {$IFDEF BORLAND}
  873. function PeBorFormNames(const FileName: TFileName; const NamesList: TStrings): Boolean;
  874. function PeBorDependedPackages(const FileName: TFileName; PackagesList: TStrings;
  875. FullPathName, Descriptions: Boolean): Boolean;
  876. {$ENDIF BORLAND}
  877. // Missing imports checking routines
  878. function PeFindMissingImports(const FileName: TFileName; MissingImportsList: TStrings): Boolean; overload;
  879. function PeFindMissingImports(RequiredImportsList, MissingImportsList: TStrings): Boolean; overload;
  880. function PeCreateRequiredImportList(const FileName: TFileName; RequiredImportsList: TStrings): Boolean;
  881. // Mapped or loaded image related routines
  882. // use PeMapImgNtHeaders32
  883. // function PeMapImgNtHeaders(const BaseAddress: Pointer): PImageNtHeaders;
  884. function PeMapImgNtHeaders32(const BaseAddress: Pointer): PImageNtHeaders32; overload;
  885. function PeMapImgNtHeaders32(Stream: TStream; const BasePosition: Int64; out NtHeaders32: TImageNtHeaders32): Int64; overload;
  886. function PeMapImgNtHeaders64(const BaseAddress: Pointer): PImageNtHeaders64; overload;
  887. function PeMapImgNtHeaders64(Stream: TStream; const BasePosition: Int64; out NtHeaders64: TImageNtHeaders64): Int64; overload;
  888. function PeMapImgLibraryName(const BaseAddress: Pointer): string;
  889. function PeMapImgLibraryName32(const BaseAddress: Pointer): string;
  890. function PeMapImgLibraryName64(const BaseAddress: Pointer): string;
  891. function PeMapImgSize(const BaseAddress: Pointer): DWORD; overload;
  892. function PeMapImgSize(Stream: TStream; const BasePosition: Int64): DWORD; overload;
  893. function PeMapImgSize32(const BaseAddress: Pointer): DWORD; overload;
  894. function PeMapImgSize32(Stream: TStream; const BasePosition: Int64): DWORD; overload;
  895. function PeMapImgSize64(const BaseAddress: Pointer): DWORD; overload;
  896. function PeMapImgSize64(Stream: TStream; const BasePosition: Int64): DWORD; overload;
  897. function PeMapImgTarget(const BaseAddress: Pointer): TJclPeTarget; overload;
  898. function PeMapImgTarget(Stream: TStream; const BasePosition: Int64): TJclPeTarget; overload;
  899. type
  900. TImageSectionHeaderArray = array of TImageSectionHeader;
  901. // use PeMapImgSections32
  902. // function PeMapImgSections(NtHeaders: PImageNtHeaders): PImageSectionHeader;
  903. function PeMapImgSections32(NtHeaders: PImageNtHeaders32): PImageSectionHeader; overload;
  904. function PeMapImgSections32(Stream: TStream; const NtHeaders32Position: Int64; const NtHeaders32: TImageNtHeaders32;
  905. out ImageSectionHeaders: TImageSectionHeaderArray): Int64; overload;
  906. function PeMapImgSections64(NtHeaders: PImageNtHeaders64): PImageSectionHeader; overload;
  907. function PeMapImgSections64(Stream: TStream; const NtHeaders64Position: Int64; const NtHeaders64: TImageNtHeaders64;
  908. out ImageSectionHeaders: TImageSectionHeaderArray): Int64; overload;
  909. // use PeMapImgFindSection32
  910. // function PeMapImgFindSection(NtHeaders: PImageNtHeaders;
  911. // const SectionName: string): PImageSectionHeader;
  912. function PeMapImgFindSection32(NtHeaders: PImageNtHeaders32;
  913. const SectionName: string): PImageSectionHeader;
  914. function PeMapImgFindSection64(NtHeaders: PImageNtHeaders64;
  915. const SectionName: string): PImageSectionHeader;
  916. function PeMapImgFindSection(const ImageSectionHeaders: TImageSectionHeaderArray;
  917. const SectionName: string): SizeInt;
  918. function PeMapImgFindSectionFromModule(const BaseAddress: Pointer;
  919. const SectionName: string): PImageSectionHeader;
  920. function PeMapImgExportedVariables(const Module: HMODULE; const VariablesList: TStrings): Boolean;
  921. function PeMapImgResolvePackageThunk(Address: Pointer): Pointer;
  922. function PeMapFindResource(const Module: HMODULE; const ResourceType: PChar;
  923. const ResourceName: string): Pointer;
  924. type
  925. TJclPeSectionStream = class(TCustomMemoryStream)
  926. private
  927. FInstance: HMODULE;
  928. FSectionHeader: TImageSectionHeader;
  929. procedure Initialize(Instance: HMODULE; const ASectionName: string);
  930. public
  931. constructor Create(Instance: HMODULE; const ASectionName: string);
  932. function Write(const Buffer; Count: Longint): Longint; override;
  933. property Instance: HMODULE read FInstance;
  934. property SectionHeader: TImageSectionHeader read FSectionHeader;
  935. end;
  936. // API hooking classes
  937. type
  938. TJclPeMapImgHookItem = class(TObject)
  939. private
  940. FBaseAddress: Pointer;
  941. FFunctionName: string;
  942. FModuleName: string;
  943. FNewAddress: Pointer;
  944. FOriginalAddress: Pointer;
  945. FList: TObjectList;
  946. protected
  947. function InternalUnhook: Boolean;
  948. public
  949. constructor Create(AList: TObjectList; const AFunctionName: string;
  950. const AModuleName: string; ABaseAddress, ANewAddress, AOriginalAddress: Pointer);
  951. destructor Destroy; override;
  952. function Unhook: Boolean;
  953. property BaseAddress: Pointer read FBaseAddress;
  954. property FunctionName: string read FFunctionName;
  955. property ModuleName: string read FModuleName;
  956. property NewAddress: Pointer read FNewAddress;
  957. property OriginalAddress: Pointer read FOriginalAddress;
  958. end;
  959. TJclPeMapImgHooks = class(TObjectList)
  960. private
  961. function GetItems(Index: Integer): TJclPeMapImgHookItem;
  962. function GetItemFromOriginalAddress(OriginalAddress: Pointer): TJclPeMapImgHookItem;
  963. function GetItemFromNewAddress(NewAddress: Pointer): TJclPeMapImgHookItem;
  964. public
  965. function HookImport(Base: Pointer; const ModuleName: string;
  966. const FunctionName: string; NewAddress: Pointer; var OriginalAddress: Pointer): Boolean;
  967. class function IsWin9xDebugThunk(P: Pointer): Boolean;
  968. class function ReplaceImport(Base: Pointer; const ModuleName: string; FromProc, ToProc: Pointer): Boolean;
  969. class function SystemBase: Pointer;
  970. procedure UnhookAll;
  971. function UnhookByNewAddress(NewAddress: Pointer): Boolean;
  972. procedure UnhookByBaseAddress(BaseAddress: Pointer);
  973. property Items[Index: Integer]: TJclPeMapImgHookItem read GetItems; default;
  974. property ItemFromOriginalAddress[OriginalAddress: Pointer]: TJclPeMapImgHookItem read GetItemFromOriginalAddress;
  975. property ItemFromNewAddress[NewAddress: Pointer]: TJclPeMapImgHookItem read GetItemFromNewAddress;
  976. end;
  977. // Image access under a debbuger
  978. function PeDbgImgNtHeaders32(ProcessHandle: THandle; BaseAddress: TJclAddr32;
  979. var NtHeaders: TImageNtHeaders32): Boolean;
  980. // TODO 64 bit version
  981. //function PeDbgImgNtHeaders64(ProcessHandle: THandle; BaseAddress: TJclAddr64;
  982. // var NtHeaders: TImageNtHeaders64): Boolean;
  983. function PeDbgImgLibraryName32(ProcessHandle: THandle; BaseAddress: TJclAddr32;
  984. var Name: string): Boolean;
  985. //function PeDbgImgLibraryName64(ProcessHandle: THandle; BaseAddress: TJclAddr64;
  986. // var Name: string): Boolean;
  987. // Borland BPL packages name unmangling
  988. type
  989. TJclBorUmSymbolKind = (skData, skFunction, skConstructor, skDestructor, skRTTI, skVTable);
  990. TJclBorUmSymbolModifier = (smQualified, smLinkProc);
  991. TJclBorUmSymbolModifiers = set of TJclBorUmSymbolModifier;
  992. TJclBorUmDescription = record
  993. Kind: TJclBorUmSymbolKind;
  994. Modifiers: TJclBorUmSymbolModifiers;
  995. end;
  996. TJclBorUmResult = (urOk, urNotMangled, urMicrosoft, urError);
  997. TJclPeUmResult = (umNotMangled, umBorland, umMicrosoft);
  998. function PeBorUnmangleName(const Name: string; out Unmangled: string;
  999. out Description: TJclBorUmDescription; out BasePos: Integer): TJclBorUmResult; overload;
  1000. function PeBorUnmangleName(const Name: string; out Unmangled: string;
  1001. out Description: TJclBorUmDescription): TJclBorUmResult; overload;
  1002. function PeBorUnmangleName(const Name: string; out Unmangled: string): TJclBorUmResult; overload;
  1003. function PeBorUnmangleName(const Name: string): string; overload;
  1004. function PeIsNameMangled(const Name: string): TJclPeUmResult;
  1005. function UndecorateSymbolName(const DecoratedName: string; out UnMangled: string; Flags: DWORD): Boolean;
  1006. function PeUnmangleName(const Name: string; out Unmangled: string): TJclPeUmResult;
  1007. {$IFDEF UNITVERSIONING}
  1008. const
  1009. UnitVersioning: TUnitVersionInfo = (
  1010. RCSfile: '$URL$';
  1011. Revision: '$Revision$';
  1012. Date: '$Date$';
  1013. LogPath: 'JCL\source\windows';
  1014. Extra: '';
  1015. Data: nil
  1016. );
  1017. {$ENDIF UNITVERSIONING}
  1018. implementation
  1019. uses
  1020. {$IFDEF HAS_UNITSCOPE}
  1021. System.RTLConsts,
  1022. System.Types, // for inlining TList.Remove
  1023. {$IFDEF HAS_UNIT_CHARACTER}
  1024. System.Character,
  1025. {$ENDIF HAS_UNIT_CHARACTER}
  1026. {$ELSE ~HAS_UNITSCOPE}
  1027. RTLConsts,
  1028. {$IFDEF HAS_UNIT_CHARACTER}
  1029. Character,
  1030. {$ENDIF HAS_UNIT_CHARACTER}
  1031. {$ENDIF ~HAS_UNITSCOPE}
  1032. {$IFNDEF WINSCP}JclLogic,{$ELSE}Math, System.AnsiStrings, {$ENDIF ~WINSCP} JclResources, JclSysUtils, {$IFNDEF WINSCP}JclAnsiStrings,{$ENDIF ~WINSCP} JclStrings{$IFNDEF WINSCP}, JclStringConversions{$ENDIF ~WINSCP}, JclTD32;
  1033. const
  1034. MANIFESTExtension = '.manifest';
  1035. DebugSectionName = '.debug';
  1036. ReadOnlySectionName = '.rdata';
  1037. BinaryExtensionLibrary = '.dll';
  1038. {$IFDEF BORLAND}
  1039. CompilerExtensionDCP = '.dcp';
  1040. BinaryExtensionPackage = '.bpl';
  1041. PackageInfoResName = 'PACKAGEINFO';
  1042. DescriptionResName = 'DESCRIPTION';
  1043. PackageOptionsResName = 'PACKAGEOPTIONS';
  1044. DVclAlResName = 'DVCLAL';
  1045. {$ENDIF BORLAND}
  1046. {$IFDEF WINSCP}
  1047. // Stubs for JclStringConversions functions
  1048. function TryUTF8ToString(const S: TUTF8String; out D: string): Boolean;
  1049. begin
  1050. Result := False;
  1051. end;
  1052. function TryStringToUTF8(const S: string; out D: TUTF8String): Boolean;
  1053. begin
  1054. Result := False;
  1055. end;
  1056. // stub for JclDateTime constant
  1057. const
  1058. UnixTimeStart = UnixDateDelta;
  1059. // from JclAnsiStrings.pas
  1060. function StrLCompA(const Str1, Str2: PAnsiChar; MaxLen: Cardinal): Integer;
  1061. begin
  1062. Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrLComp(Str1, Str2, MaxLen);
  1063. end;
  1064. function StrPLCopyA(Dest: PAnsiChar; const Source: AnsiString; MaxLen: Cardinal): PAnsiChar;
  1065. begin
  1066. Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrPLCopy(Dest, Source, MaxLen);
  1067. end;
  1068. function StrICompA(const Str1, Str2: PAnsiChar): Integer;
  1069. begin
  1070. Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrIComp(Str1, Str2);
  1071. end;
  1072. function StrLenA(S: PAnsiChar): Integer;
  1073. begin
  1074. Result := {$IFDEF DEPRECATED_SYSUTILS_ANSISTRINGS}System.AnsiStrings.{$ENDIF}StrLen(S);
  1075. end;
  1076. {$ENDIF}
  1077. // Helper routines
  1078. function AddFlagTextRes(var Text: string; const FlagText: PResStringRec; const Value, Mask: Cardinal): Boolean;
  1079. begin
  1080. Result := (Value and Mask <> 0);
  1081. if Result then
  1082. begin
  1083. if Length(Text) > 0 then
  1084. Text := Text + ', ';
  1085. Text := Text + LoadResString(FlagText);
  1086. end;
  1087. end;
  1088. function CompareResourceName(T1, T2: PChar): Boolean;
  1089. var
  1090. Long1, Long2: LongRec;
  1091. begin
  1092. {$IFDEF CPU64}
  1093. Long1 := LongRec(Int64Rec(T1).Lo);
  1094. Long2 := LongRec(Int64Rec(T2).Lo);
  1095. if (Int64Rec(T1).Hi = 0) and (Int64Rec(T2).Hi = 0) and (Long1.Hi = 0) and (Long2.Hi = 0) then
  1096. {$ENDIF CPU64}
  1097. {$IFDEF CPU32}
  1098. Long1 := LongRec(T1);
  1099. Long2 := LongRec(T2);
  1100. if (Long1.Hi = 0) or (Long2.Hi = 0) then
  1101. {$ENDIF CPU32}
  1102. Result := Long1.Lo = Long2.Lo
  1103. else
  1104. Result := (StrIComp(T1, T2) = 0);
  1105. end;
  1106. function CreatePeImage(const FileName: TFileName): TJclPeImage;
  1107. begin
  1108. Result := TJclPeImage.Create(True);
  1109. Result.FileName := FileName;
  1110. end;
  1111. function InternalImportedLibraries(const FileName: TFileName;
  1112. Recursive, FullPathName: Boolean; ExternalCache: TJclPeImagesCache): TStringList;
  1113. var
  1114. Cache: TJclPeImagesCache;
  1115. procedure ProcessLibraries(const AFileName: TFileName);
  1116. var
  1117. I: Integer;
  1118. S: TFileName;
  1119. ImportLib: TJclPeImportLibItem;
  1120. begin
  1121. with Cache[AFileName].ImportList do
  1122. for I := 0 to Count - 1 do
  1123. begin
  1124. ImportLib := Items[I];
  1125. if FullPathName then
  1126. S := ImportLib.FileName
  1127. else
  1128. S := TFileName(ImportLib.Name);
  1129. if Result.IndexOf(S) = -1 then
  1130. begin
  1131. Result.Add(S);
  1132. if Recursive then
  1133. ProcessLibraries(ImportLib.FileName);
  1134. end;
  1135. end;
  1136. end;
  1137. begin
  1138. if ExternalCache = nil then
  1139. Cache := TJclPeImagesCache.Create
  1140. else
  1141. Cache := ExternalCache;
  1142. try
  1143. Result := TStringList.Create;
  1144. try
  1145. Result.Sorted := True;
  1146. Result.Duplicates := dupIgnore;
  1147. ProcessLibraries(FileName);
  1148. except
  1149. FreeAndNil(Result);
  1150. raise;
  1151. end;
  1152. finally
  1153. if ExternalCache = nil then
  1154. Cache.Free;
  1155. end;
  1156. end;
  1157. // Smart name compare function
  1158. function PeStripFunctionAW(const FunctionName: string): string;
  1159. var
  1160. L: Integer;
  1161. begin
  1162. Result := FunctionName;
  1163. L := Length(Result);
  1164. if (L > 1) then
  1165. case Result[L] of
  1166. 'A', 'W':
  1167. if CharIsValidIdentifierLetter(Result[L - 1]) then
  1168. Delete(Result, L, 1);
  1169. end;
  1170. end;
  1171. function PeSmartFunctionNameSame(const ComparedName, FunctionName: string;
  1172. Options: TJclSmartCompOptions): Boolean;
  1173. var
  1174. S: string;
  1175. begin
  1176. if scIgnoreCase in Options then
  1177. Result := CompareText(FunctionName, ComparedName) = 0
  1178. else
  1179. Result := (FunctionName = ComparedName);
  1180. if (not Result) and not (scSimpleCompare in Options) then
  1181. begin
  1182. if Length(FunctionName) > 0 then
  1183. begin
  1184. S := PeStripFunctionAW(FunctionName);
  1185. if scIgnoreCase in Options then
  1186. Result := CompareText(S, ComparedName) = 0
  1187. else
  1188. Result := (S = ComparedName);
  1189. end
  1190. else
  1191. Result := False;
  1192. end;
  1193. end;
  1194. //=== { TJclPeImagesCache } ==================================================
  1195. constructor TJclPeImagesCache.Create;
  1196. begin
  1197. inherited Create;
  1198. FList := TStringList.Create;
  1199. FList.Sorted := True;
  1200. FList.Duplicates := dupIgnore;
  1201. end;
  1202. destructor TJclPeImagesCache.Destroy;
  1203. begin
  1204. Clear;
  1205. FreeAndNil(FList);
  1206. inherited Destroy;
  1207. end;
  1208. procedure TJclPeImagesCache.Clear;
  1209. var
  1210. I: Integer;
  1211. begin
  1212. with FList do
  1213. for I := 0 to Count - 1 do
  1214. Objects[I].Free;
  1215. FList.Clear;
  1216. end;
  1217. function TJclPeImagesCache.GetCount: Integer;
  1218. begin
  1219. Result := FList.Count;
  1220. end;
  1221. function TJclPeImagesCache.GetImages(const FileName: TFileName): TJclPeImage;
  1222. var
  1223. I: Integer;
  1224. begin
  1225. I := FList.IndexOf(FileName);
  1226. if I = -1 then
  1227. begin
  1228. Result := GetPeImageClass.Create(True);
  1229. Result.FileName := FileName;
  1230. FList.AddObject(FileName, Result);
  1231. end
  1232. else
  1233. Result := TJclPeImage(FList.Objects[I]);
  1234. end;
  1235. function TJclPeImagesCache.GetPeImageClass: TJclPeImageClass;
  1236. begin
  1237. Result := TJclPeImage;
  1238. end;
  1239. //=== { TJclPeImageBaseList } ================================================
  1240. constructor TJclPeImageBaseList.Create(AImage: TJclPeImage);
  1241. begin
  1242. inherited Create(True);
  1243. FImage := AImage;
  1244. end;
  1245. // Import sort functions
  1246. function ImportSortByName(Item1, Item2: Pointer): Integer;
  1247. begin
  1248. Result := CompareStr(TJclPeImportFuncItem(Item1).Name, TJclPeImportFuncItem(Item2).Name);
  1249. if Result = 0 then
  1250. Result := CompareStr(TJclPeImportFuncItem(Item1).ImportLib.Name, TJclPeImportFuncItem(Item2).ImportLib.Name);
  1251. if Result = 0 then
  1252. Result := TJclPeImportFuncItem(Item1).Ordinal - TJclPeImportFuncItem(Item2).Ordinal;
  1253. end;
  1254. function ImportSortByNameDESC(Item1, Item2: Pointer): Integer;
  1255. begin
  1256. Result := ImportSortByName(Item2, Item1);
  1257. end;
  1258. function ImportSortByHint(Item1, Item2: Pointer): Integer;
  1259. begin
  1260. Result := TJclPeImportFuncItem(Item1).Hint - TJclPeImportFuncItem(Item2).Hint;
  1261. end;
  1262. function ImportSortByHintDESC(Item1, Item2: Pointer): Integer;
  1263. begin
  1264. Result := ImportSortByHint(Item2, Item1);
  1265. end;
  1266. function ImportSortByDll(Item1, Item2: Pointer): Integer;
  1267. begin
  1268. Result := CompareStr(TJclPeImportFuncItem(Item1).ImportLib.Name,
  1269. TJclPeImportFuncItem(Item2).ImportLib.Name);
  1270. if Result = 0 then
  1271. Result := ImportSortByName(Item1, Item2);
  1272. end;
  1273. function ImportSortByDllDESC(Item1, Item2: Pointer): Integer;
  1274. begin
  1275. Result := ImportSortByDll(Item2, Item1);
  1276. end;
  1277. function ImportSortByOrdinal(Item1, Item2: Pointer): Integer;
  1278. begin
  1279. Result := CompareStr(TJclPeImportFuncItem(Item1).ImportLib.Name,
  1280. TJclPeImportFuncItem(Item2).ImportLib.Name);
  1281. if Result = 0 then
  1282. Result := TJclPeImportFuncItem(Item1).Ordinal - TJclPeImportFuncItem(Item2).Ordinal;
  1283. end;
  1284. function ImportSortByOrdinalDESC(Item1, Item2: Pointer): Integer;
  1285. begin
  1286. Result := ImportSortByOrdinal(Item2, Item1);
  1287. end;
  1288. function GetImportSortFunction(SortType: TJclPeImportSort; Descending: Boolean): TListSortCompare;
  1289. const
  1290. SortFunctions: array [TJclPeImportSort, Boolean] of TListSortCompare =
  1291. ((ImportSortByName, ImportSortByNameDESC),
  1292. (ImportSortByOrdinal, ImportSortByOrdinalDESC),
  1293. (ImportSortByHint, ImportSortByHintDESC),
  1294. (ImportSortByDll, ImportSortByDllDESC)
  1295. );
  1296. begin
  1297. Result := SortFunctions[SortType, Descending];
  1298. end;
  1299. function ImportLibSortByIndex(Item1, Item2: Pointer): Integer;
  1300. begin
  1301. Result := TJclPeImportLibItem(Item1).ImportDirectoryIndex -
  1302. TJclPeImportLibItem(Item2).ImportDirectoryIndex;
  1303. end;
  1304. function ImportLibSortByName(Item1, Item2: Pointer): Integer;
  1305. begin
  1306. Result := AnsiCompareStr(TJclPeImportLibItem(Item1).Name, TJclPeImportLibItem(Item2).Name);
  1307. if Result = 0 then
  1308. Result := ImportLibSortByIndex(Item1, Item2);
  1309. end;
  1310. function GetImportLibSortFunction(SortType: TJclPeImportLibSort): TListSortCompare;
  1311. const
  1312. SortFunctions: array [TJclPeImportLibSort] of TListSortCompare =
  1313. (ImportLibSortByName, ImportLibSortByIndex);
  1314. begin
  1315. Result := SortFunctions[SortType];
  1316. end;
  1317. //=== { TJclPeImportFuncItem } ===============================================
  1318. constructor TJclPeImportFuncItem.Create(AImportLib: TJclPeImportLibItem;
  1319. AOrdinal: Word; AHint: Word; const AName: string);
  1320. begin
  1321. inherited Create;
  1322. FImportLib := AImportLib;
  1323. FOrdinal := AOrdinal;
  1324. FHint := AHint;
  1325. FName := AName;
  1326. FResolveCheck := icNotChecked;
  1327. FIndirectImportName := False;
  1328. end;
  1329. function TJclPeImportFuncItem.GetIsByOrdinal: Boolean;
  1330. begin
  1331. Result := FOrdinal <> 0;
  1332. end;
  1333. procedure TJclPeImportFuncItem.SetIndirectImportName(const Value: string);
  1334. begin
  1335. FName := Value;
  1336. FIndirectImportName := True;
  1337. end;
  1338. procedure TJclPeImportFuncItem.SetName(const Value: string);
  1339. begin
  1340. FName := Value;
  1341. FIndirectImportName := False;
  1342. end;
  1343. procedure TJclPeImportFuncItem.SetResolveCheck(Value: TJclPeResolveCheck);
  1344. begin
  1345. FResolveCheck := Value;
  1346. end;
  1347. //=== { TJclPeImportLibItem } ================================================
  1348. constructor TJclPeImportLibItem.Create(AImage: TJclPeImage;
  1349. AImportDescriptor: Pointer; AImportKind: TJclPeImportKind; const AName: string;
  1350. AThunk: Pointer; AUseRVA: Boolean = True);
  1351. begin
  1352. inherited Create(AImage);
  1353. FTotalResolveCheck := icNotChecked;
  1354. FImportDescriptor := AImportDescriptor;
  1355. FImportKind := AImportKind;
  1356. FName := AName;
  1357. FThunk := AThunk;
  1358. FThunkData := AThunk;
  1359. FUseRVA := AUseRVA;
  1360. end;
  1361. procedure TJclPeImportLibItem.CheckImports(ExportImage: TJclPeImage);
  1362. var
  1363. I: Integer;
  1364. ExportList: TJclPeExportFuncList;
  1365. begin
  1366. if ExportImage.StatusOK then
  1367. begin
  1368. FTotalResolveCheck := icResolved;
  1369. ExportList := ExportImage.ExportList;
  1370. for I := 0 to Count - 1 do
  1371. begin
  1372. with Items[I] do
  1373. if IsByOrdinal then
  1374. begin
  1375. if ExportList.OrdinalValid(Ordinal) then
  1376. SetResolveCheck(icResolved)
  1377. else
  1378. begin
  1379. SetResolveCheck(icUnresolved);
  1380. Self.FTotalResolveCheck := icUnresolved;
  1381. end;
  1382. end
  1383. else
  1384. begin
  1385. if ExportList.ItemFromName[Items[I].Name] <> nil then
  1386. SetResolveCheck(icResolved)
  1387. else
  1388. begin
  1389. SetResolveCheck(icUnresolved);
  1390. Self.FTotalResolveCheck := icUnresolved;
  1391. end;
  1392. end;
  1393. end;
  1394. end
  1395. else
  1396. begin
  1397. FTotalResolveCheck := icUnresolved;
  1398. for I := 0 to Count - 1 do
  1399. Items[I].SetResolveCheck(icUnresolved);
  1400. end;
  1401. end;
  1402. procedure TJclPeImportLibItem.CreateList;
  1403. procedure CreateList32;
  1404. var
  1405. Thunk32: PImageThunkData32;
  1406. OrdinalName: PImageImportByName;
  1407. Ordinal, Hint: Word;
  1408. Name: PAnsiChar;
  1409. ImportName: string;
  1410. AddressOfData: DWORD;
  1411. begin
  1412. Thunk32 := PImageThunkData32(FThunk);
  1413. while Thunk32^.Function_ <> 0 do
  1414. begin
  1415. Ordinal := 0;
  1416. Hint := 0;
  1417. Name := nil;
  1418. if Thunk32^.Ordinal and IMAGE_ORDINAL_FLAG32 = 0 then
  1419. begin
  1420. case ImportKind of
  1421. ikImport, ikBoundImport:
  1422. begin
  1423. OrdinalName := PImageImportByName(Image.RvaToVa(Thunk32^.AddressOfData));
  1424. if OrdinalName <> nil then
  1425. begin
  1426. Hint := OrdinalName.Hint;
  1427. Name := OrdinalName.Name;
  1428. end;
  1429. end;
  1430. ikDelayImport:
  1431. begin
  1432. AddressOfData := Thunk32^.AddressOfData;
  1433. if not FUseRVA then
  1434. AddressOfData := Image.ImageAddressToRva(AddressOfData);
  1435. OrdinalName := PImageImportByName(Image.RvaToVa(AddressOfData));
  1436. if OrdinalName <> nil then
  1437. begin
  1438. Hint := OrdinalName.Hint;
  1439. Name := OrdinalName.Name;
  1440. end;
  1441. end;
  1442. end;
  1443. end
  1444. else
  1445. Ordinal := IMAGE_ORDINAL32(Thunk32^.Ordinal);
  1446. if (Ordinal <> 0) or (Hint <> 0) or (Name <> nil) then
  1447. begin
  1448. if not TryUTF8ToString(Name, ImportName) then
  1449. ImportName := string(Name);
  1450. Add(TJclPeImportFuncItem.Create(Self, Ordinal, Hint, ImportName));
  1451. end;
  1452. Inc(Thunk32);
  1453. end;
  1454. end;
  1455. procedure CreateList64;
  1456. var
  1457. Thunk64: PImageThunkData64;
  1458. OrdinalName: PImageImportByName;
  1459. Ordinal, Hint: Word;
  1460. Name: PAnsiChar;
  1461. ImportName: string;
  1462. begin
  1463. Thunk64 := PImageThunkData64(FThunk);
  1464. while Thunk64^.Function_ <> 0 do
  1465. begin
  1466. Ordinal := 0;
  1467. Hint := 0;
  1468. Name := nil;
  1469. if Thunk64^.Ordinal and IMAGE_ORDINAL_FLAG64 = 0 then
  1470. begin
  1471. case ImportKind of
  1472. ikImport, ikBoundImport:
  1473. begin
  1474. OrdinalName := PImageImportByName(Image.RvaToVa(Thunk64^.AddressOfData));
  1475. if OrdinalName <> nil then
  1476. begin
  1477. Hint := OrdinalName.Hint;
  1478. Name := OrdinalName.Name;
  1479. end;
  1480. end;
  1481. ikDelayImport:
  1482. begin
  1483. OrdinalName := PImageImportByName(Image.RvaToVa(Thunk64^.AddressOfData));
  1484. if OrdinalName <> nil then
  1485. begin
  1486. Hint := OrdinalName.Hint;
  1487. Name := OrdinalName.Name;
  1488. end;
  1489. end;
  1490. end;
  1491. end
  1492. else
  1493. Ordinal := IMAGE_ORDINAL64(Thunk64^.Ordinal);
  1494. if (Ordinal <> 0) or (Hint <> 0) or (Name <> nil) then
  1495. begin
  1496. if not TryUTF8ToString(Name, ImportName) then
  1497. ImportName := string(Name);
  1498. Add(TJclPeImportFuncItem.Create(Self, Ordinal, Hint, ImportName));
  1499. end;
  1500. Inc(Thunk64);
  1501. end;
  1502. end;
  1503. begin
  1504. if FThunk = nil then
  1505. Exit;
  1506. case Image.Target of
  1507. taWin32:
  1508. CreateList32;
  1509. taWin64:
  1510. CreateList64;
  1511. end;
  1512. FThunk := nil;
  1513. end;
  1514. function TJclPeImportLibItem.GetCount: Integer;
  1515. begin
  1516. if FThunk <> nil then
  1517. CreateList;
  1518. Result := inherited Count;
  1519. end;
  1520. function TJclPeImportLibItem.GetFileName: TFileName;
  1521. begin
  1522. Result := Image.ExpandModuleName(Name);
  1523. end;
  1524. function TJclPeImportLibItem.GetItems(Index: Integer): TJclPeImportFuncItem;
  1525. begin
  1526. Result := TJclPeImportFuncItem(Get(Index));
  1527. end;
  1528. function TJclPeImportLibItem.GetName: string;
  1529. begin
  1530. Result := AnsiLowerCase(OriginalName);
  1531. end;
  1532. function TJclPeImportLibItem.GetThunkData32: PImageThunkData32;
  1533. begin
  1534. if Image.Target = taWin32 then
  1535. Result := FThunkData
  1536. else
  1537. Result := nil;
  1538. end;
  1539. function TJclPeImportLibItem.GetThunkData64: PImageThunkData64;
  1540. begin
  1541. if Image.Target = taWin64 then
  1542. Result := FThunkData
  1543. else
  1544. Result := nil;
  1545. end;
  1546. procedure TJclPeImportLibItem.SetImportDirectoryIndex(Value: Integer);
  1547. begin
  1548. FImportDirectoryIndex := Value;
  1549. end;
  1550. procedure TJclPeImportLibItem.SetImportKind(Value: TJclPeImportKind);
  1551. begin
  1552. FImportKind := Value;
  1553. end;
  1554. procedure TJclPeImportLibItem.SetSorted(Value: Boolean);
  1555. begin
  1556. FSorted := Value;
  1557. end;
  1558. procedure TJclPeImportLibItem.SetThunk(Value: Pointer);
  1559. begin
  1560. FThunk := Value;
  1561. FThunkData := Value;
  1562. end;
  1563. procedure TJclPeImportLibItem.SortList(SortType: TJclPeImportSort; Descending: Boolean);
  1564. begin
  1565. if not FSorted or (SortType <> FLastSortType) or (Descending <> FLastSortDescending) then
  1566. begin
  1567. GetCount; // create list if it wasn't created
  1568. Sort(GetImportSortFunction(SortType, Descending));
  1569. FLastSortType := SortType;
  1570. FLastSortDescending := Descending;
  1571. FSorted := True;
  1572. end;
  1573. end;
  1574. //=== { TJclPeImportList } ===================================================
  1575. constructor TJclPeImportList.Create(AImage: TJclPeImage);
  1576. begin
  1577. inherited Create(AImage);
  1578. FAllItemsList := TList.Create;
  1579. FAllItemsList.Capacity := 256;
  1580. FUniqueNamesList := TStringList.Create;
  1581. FUniqueNamesList.Sorted := True;
  1582. FUniqueNamesList.Duplicates := dupIgnore;
  1583. FLastAllSortType := isName;
  1584. FLastAllSortDescending := False;
  1585. CreateList;
  1586. end;
  1587. destructor TJclPeImportList.Destroy;
  1588. var
  1589. I: Integer;
  1590. begin
  1591. FreeAndNil(FAllItemsList);
  1592. FreeAndNil(FUniqueNamesList);
  1593. for I := 0 to Length(FparallelImportTable) - 1 do
  1594. FreeMem(FparallelImportTable[I]);
  1595. inherited Destroy;
  1596. end;
  1597. procedure TJclPeImportList.CheckImports(PeImageCache: TJclPeImagesCache);
  1598. var
  1599. I: Integer;
  1600. ExportPeImage: TJclPeImage;
  1601. begin
  1602. Image.CheckNotAttached;
  1603. if PeImageCache <> nil then
  1604. ExportPeImage := nil // to make the compiler happy
  1605. else
  1606. ExportPeImage := TJclPeImage.Create(True);
  1607. try
  1608. for I := 0 to Count - 1 do
  1609. if Items[I].TotalResolveCheck = icNotChecked then
  1610. begin
  1611. if PeImageCache <> nil then
  1612. ExportPeImage := PeImageCache[Items[I].FileName]
  1613. else
  1614. ExportPeImage.FileName := Items[I].FileName;
  1615. ExportPeImage.ExportList.PrepareForFastNameSearch;
  1616. Items[I].CheckImports(ExportPeImage);
  1617. end;
  1618. finally
  1619. if PeImageCache = nil then
  1620. ExportPeImage.Free;
  1621. end;
  1622. end;
  1623. procedure TJclPeImportList.CreateList;
  1624. procedure CreateDelayImportList32(DelayImportDesc: PImgDelayDescrV1);
  1625. const
  1626. ATTRS_RVA = 1;
  1627. var
  1628. LibItem: TJclPeImportLibItem;
  1629. UTF8Name: TUTF8String;
  1630. LibName: string;
  1631. P, Thunk: Pointer;
  1632. UseRVA: Boolean;
  1633. begin
  1634. // 2010, XE use addresses whereas XE2 and newer use the RVA mode
  1635. while DelayImportDesc^.szName <> nil do
  1636. begin
  1637. UseRVA := DelayImportDesc^.grAttrs and ATTRS_RVA <> 0;
  1638. Thunk := DelayImportDesc^.pINT;
  1639. P := DelayImportDesc^.szName;
  1640. if not UseRVA then
  1641. begin
  1642. Thunk := Pointer(Image.ImageAddressToRva(DWORD(DelayImportDesc^.pINT)));
  1643. P := Pointer(Image.ImageAddressToRva(DWORD(DelayImportDesc^.szName)));
  1644. end;
  1645. UTF8Name := PAnsiChar(Image.RvaToVa(DWORD(P)));
  1646. if not TryUTF8ToString(UTF8Name, LibName) then
  1647. LibName := string(UTF8Name);
  1648. LibItem := TJclPeImportLibItem.Create(Image, DelayImportDesc, ikDelayImport,
  1649. LibName, Image.RvaToVa(DWORD(Thunk)), UseRVA);
  1650. Add(LibItem);
  1651. FUniqueNamesList.AddObject(AnsiLowerCase(LibItem.Name), LibItem);
  1652. Inc(DelayImportDesc);
  1653. end;
  1654. end;
  1655. procedure CreateDelayImportList64(DelayImportDesc: PImgDelayDescrV2);
  1656. var
  1657. LibItem: TJclPeImportLibItem;
  1658. UTF8Name: TUTF8String;
  1659. LibName: string;
  1660. begin
  1661. // 64 bit always uses RVA mode
  1662. while DelayImportDesc^.rvaDLLName <> 0 do
  1663. begin
  1664. UTF8Name := PAnsiChar(Image.RvaToVa(DelayImportDesc^.rvaDLLName));
  1665. if not TryUTF8ToString(UTF8Name, LibName) then
  1666. LibName := string(UTF8Name);
  1667. LibItem := TJclPeImportLibItem.Create(Image, DelayImportDesc, ikDelayImport,
  1668. LibName, Image.RvaToVa(DelayImportDesc^.rvaINT));
  1669. Add(LibItem);
  1670. FUniqueNamesList.AddObject(AnsiLowerCase(LibItem.Name), LibItem);
  1671. Inc(DelayImportDesc);
  1672. end;
  1673. end;
  1674. var
  1675. ImportDesc: PImageImportDescriptor;
  1676. LibItem: TJclPeImportLibItem;
  1677. UTF8Name: TUTF8String;
  1678. LibName, ModuleName: string;
  1679. DelayImportDesc: Pointer;
  1680. BoundImports, BoundImport: PImageBoundImportDescriptor;
  1681. S: string;
  1682. I: Integer;
  1683. Thunk: Pointer;
  1684. begin
  1685. SetCapacity(100);
  1686. with Image do
  1687. begin
  1688. if not StatusOK then
  1689. Exit;
  1690. ImportDesc := DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_IMPORT);
  1691. if ImportDesc <> nil then
  1692. while ImportDesc^.Name <> 0 do
  1693. begin
  1694. if ImportDesc^.Union.Characteristics = 0 then
  1695. begin
  1696. if AttachedImage then // Borland images doesn't have two parallel arrays
  1697. Thunk := nil // see MakeBorlandImportTableForMappedImage method
  1698. else
  1699. Thunk := RvaToVa(ImportDesc^.FirstThunk);
  1700. FLinkerProducer := lrBorland;
  1701. end
  1702. else
  1703. begin
  1704. Thunk := RvaToVa(ImportDesc^.Union.Characteristics);
  1705. FLinkerProducer := lrMicrosoft;
  1706. end;
  1707. UTF8Name := PAnsiChar(RvaToVa(ImportDesc^.Name));
  1708. if not TryUTF8ToString(UTF8Name, LibName) then
  1709. LibName := string(UTF8Name);
  1710. LibItem := TJclPeImportLibItem.Create(Image, ImportDesc, ikImport, LibName, Thunk);
  1711. Add(LibItem);
  1712. FUniqueNamesList.AddObject(AnsiLowerCase(LibItem.Name), LibItem);
  1713. Inc(ImportDesc);
  1714. end;
  1715. DelayImportDesc := DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
  1716. if DelayImportDesc <> nil then
  1717. begin
  1718. try
  1719. case Target of
  1720. taWin32:
  1721. CreateDelayImportList32(DelayImportDesc);
  1722. taWin64:
  1723. CreateDelayImportList64(DelayImportDesc);
  1724. end;
  1725. except
  1726. on E: EAccessViolation do // Mantis #6177. Some users seem to have module loaded that is broken
  1727. ; // ignore
  1728. end;
  1729. end;
  1730. BoundImports := DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT);
  1731. if BoundImports <> nil then
  1732. begin
  1733. BoundImport := BoundImports;
  1734. while BoundImport^.OffsetModuleName <> 0 do
  1735. begin
  1736. UTF8Name := PAnsiChar(TJclAddr(BoundImports) + BoundImport^.OffsetModuleName);
  1737. if not TryUTF8ToString(UTF8Name, ModuleName) then
  1738. ModuleName := string(UTF8Name);
  1739. S := AnsiLowerCase(ModuleName);
  1740. I := FUniqueNamesList.IndexOf(S);
  1741. if I >= 0 then
  1742. TJclPeImportLibItem(FUniqueNamesList.Objects[I]).SetImportKind(ikBoundImport);
  1743. for I := 1 to BoundImport^.NumberOfModuleForwarderRefs do
  1744. Inc(PImageBoundForwarderRef(BoundImport)); // skip forward information
  1745. Inc(BoundImport);
  1746. end;
  1747. end;
  1748. end;
  1749. for I := 0 to Count - 1 do
  1750. Items[I].SetImportDirectoryIndex(I);
  1751. end;
  1752. function TJclPeImportList.GetAllItemCount: Integer;
  1753. begin
  1754. Result := FAllItemsList.Count;
  1755. if Result = 0 then // we haven't created the list yet -> create unsorted list
  1756. begin
  1757. RefreshAllItems;
  1758. Result := FAllItemsList.Count;
  1759. end;
  1760. end;
  1761. function TJclPeImportList.GetAllItems(Index: Integer): TJclPeImportFuncItem;
  1762. begin
  1763. Result := TJclPeImportFuncItem(FAllItemsList[Index]);
  1764. end;
  1765. function TJclPeImportList.GetItems(Index: Integer): TJclPeImportLibItem;
  1766. begin
  1767. Result := TJclPeImportLibItem(Get(Index));
  1768. end;
  1769. function TJclPeImportList.GetUniqueLibItemCount: Integer;
  1770. begin
  1771. Result := FUniqueNamesList.Count;
  1772. end;
  1773. function TJclPeImportList.GetUniqueLibItemFromName(const Name: string): TJclPeImportLibItem;
  1774. var
  1775. I: Integer;
  1776. begin
  1777. I := FUniqueNamesList.IndexOf(Name);
  1778. if I = -1 then
  1779. Result := nil
  1780. else
  1781. Result := TJclPeImportLibItem(FUniqueNamesList.Objects[I]);
  1782. end;
  1783. function TJclPeImportList.GetUniqueLibItems(Index: Integer): TJclPeImportLibItem;
  1784. begin
  1785. Result := TJclPeImportLibItem(FUniqueNamesList.Objects[Index]);
  1786. end;
  1787. function TJclPeImportList.GetUniqueLibNames(Index: Integer): string;
  1788. begin
  1789. Result := FUniqueNamesList[Index];
  1790. end;
  1791. function TJclPeImportList.MakeBorlandImportTableForMappedImage: Boolean;
  1792. var
  1793. FileImage: TJclPeImage;
  1794. I, TableSize: Integer;
  1795. begin
  1796. if Image.AttachedImage and (LinkerProducer = lrBorland) and
  1797. (Length(FParallelImportTable) = 0) then
  1798. begin
  1799. FileImage := TJclPeImage.Create(True);
  1800. try
  1801. FileImage.FileName := Image.FileName;
  1802. Result := FileImage.StatusOK;
  1803. if Result then
  1804. begin
  1805. SetLength(FParallelImportTable, FileImage.ImportList.Count);
  1806. for I := 0 to FileImage.ImportList.Count - 1 do
  1807. begin
  1808. Assert(Items[I].ImportKind = ikImport); // Borland doesn't have Delay load or Bound imports
  1809. TableSize := (FileImage.ImportList[I].Count + 1);
  1810. case Image.Target of
  1811. taWin32:
  1812. begin
  1813. TableSize := TableSize * SizeOf(TImageThunkData32);
  1814. GetMem(FParallelImportTable[I], TableSize);
  1815. System.Move(FileImage.ImportList[I].ThunkData32^, FParallelImportTable[I]^, TableSize);
  1816. Items[I].SetThunk(FParallelImportTable[I]);
  1817. end;
  1818. taWin64:
  1819. begin
  1820. TableSize := TableSize * SizeOf(TImageThunkData64);
  1821. GetMem(FParallelImportTable[I], TableSize);
  1822. System.Move(FileImage.ImportList[I].ThunkData64^, FParallelImportTable[I]^, TableSize);
  1823. Items[I].SetThunk(FParallelImportTable[I]);
  1824. end;
  1825. end;
  1826. end;
  1827. end;
  1828. finally
  1829. FileImage.Free;
  1830. end;
  1831. end
  1832. else
  1833. Result := True;
  1834. end;
  1835. procedure TJclPeImportList.RefreshAllItems;
  1836. var
  1837. L, I: Integer;
  1838. LibItem: TJclPeImportLibItem;
  1839. begin
  1840. FAllItemsList.Clear;
  1841. for L := 0 to Count - 1 do
  1842. begin
  1843. LibItem := Items[L];
  1844. if (Length(FFilterModuleName) = 0) or (AnsiCompareText(LibItem.Name, FFilterModuleName) = 0) then
  1845. for I := 0 to LibItem.Count - 1 do
  1846. FAllItemsList.Add(LibItem[I]);
  1847. end;
  1848. end;
  1849. procedure TJclPeImportList.SetFilterModuleName(const Value: string);
  1850. begin
  1851. if (FFilterModuleName <> Value) or (FAllItemsList.Count = 0) then
  1852. begin
  1853. FFilterModuleName := Value;
  1854. RefreshAllItems;
  1855. FAllItemsList.Sort(GetImportSortFunction(FLastAllSortType, FLastAllSortDescending));
  1856. end;
  1857. end;
  1858. function TJclPeImportList.SmartFindName(const CompareName, LibName: string;
  1859. Options: TJclSmartCompOptions): TJclPeImportFuncItem;
  1860. var
  1861. L, I: Integer;
  1862. LibItem: TJclPeImportLibItem;
  1863. begin
  1864. Result := nil;
  1865. for L := 0 to Count - 1 do
  1866. begin
  1867. LibItem := Items[L];
  1868. if (Length(LibName) = 0) or (AnsiCompareText(LibItem.Name, LibName) = 0) then
  1869. for I := 0 to LibItem.Count - 1 do
  1870. if PeSmartFunctionNameSame(CompareName, LibItem[I].Name, Options) then
  1871. begin
  1872. Result := LibItem[I];
  1873. Break;
  1874. end;
  1875. end;
  1876. end;
  1877. procedure TJclPeImportList.SortAllItemsList(SortType: TJclPeImportSort; Descending: Boolean);
  1878. begin
  1879. GetAllItemCount; // create list if it wasn't created
  1880. FAllItemsList.Sort(GetImportSortFunction(SortType, Descending));
  1881. FLastAllSortType := SortType;
  1882. FLastAllSortDescending := Descending;
  1883. end;
  1884. procedure TJclPeImportList.SortList(SortType: TJclPeImportLibSort);
  1885. begin
  1886. Sort(GetImportLibSortFunction(SortType));
  1887. end;
  1888. procedure TJclPeImportList.TryGetNamesForOrdinalImports;
  1889. var
  1890. LibNamesList: TStringList;
  1891. L, I: Integer;
  1892. LibPeDump: TJclPeImage;
  1893. procedure TryGetNames(const ModuleName: string);
  1894. var
  1895. Item: TJclPeImportFuncItem;
  1896. I, L: Integer;
  1897. ImportLibItem: TJclPeImportLibItem;
  1898. ExportItem: TJclPeExportFuncItem;
  1899. ExportList: TJclPeExportFuncList;
  1900. begin
  1901. if Image.AttachedImage then
  1902. LibPeDump.AttachLoadedModule(GetModuleHandle(PChar(ModuleName)))
  1903. else
  1904. LibPeDump.FileName := Image.ExpandModuleName(ModuleName);
  1905. if not LibPeDump.StatusOK then
  1906. Exit;
  1907. ExportList := LibPeDump.ExportList;
  1908. for L := 0 to Count - 1 do
  1909. begin
  1910. ImportLibItem := Items[L];
  1911. if AnsiCompareText(ImportLibItem.Name, ModuleName) = 0 then
  1912. begin
  1913. for I := 0 to ImportLibItem.Count - 1 do
  1914. begin
  1915. Item := ImportLibItem[I];
  1916. if Item.IsByOrdinal then
  1917. begin
  1918. ExportItem := ExportList.ItemFromOrdinal[Item.Ordinal];
  1919. if (ExportItem <> nil) and (ExportItem.Name <> '') then
  1920. Item.SetIndirectImportName(ExportItem.Name);
  1921. end;
  1922. end;
  1923. ImportLibItem.SetSorted(False);
  1924. end;
  1925. end;
  1926. end;
  1927. begin
  1928. LibNamesList := TStringList.Create;
  1929. try
  1930. LibNamesList.Sorted := True;
  1931. LibNamesList.Duplicates := dupIgnore;
  1932. for L := 0 to Count - 1 do
  1933. with Items[L] do
  1934. for I := 0 to Count - 1 do
  1935. if Items[I].IsByOrdinal then
  1936. LibNamesList.Add(AnsiUpperCase(Name));
  1937. LibPeDump := TJclPeImage.Create(True);
  1938. try
  1939. for I := 0 to LibNamesList.Count - 1 do
  1940. TryGetNames(LibNamesList[I]);
  1941. finally
  1942. LibPeDump.Free;
  1943. end;
  1944. SortAllItemsList(FLastAllSortType, FLastAllSortDescending);
  1945. finally
  1946. LibNamesList.Free;
  1947. end;
  1948. end;
  1949. //=== { TJclPeExportFuncItem } ===============================================
  1950. constructor TJclPeExportFuncItem.Create(AExportList: TJclPeExportFuncList;
  1951. const AName, AForwardedName: string; AAddress: DWORD; AHint: Word;
  1952. AOrdinal: Word; AResolveCheck: TJclPeResolveCheck);
  1953. var
  1954. DotPos: Integer;
  1955. begin
  1956. inherited Create;
  1957. FExportList := AExportList;
  1958. FName := AName;
  1959. FForwardedName := AForwardedName;
  1960. FAddress := AAddress;
  1961. FHint := AHint;
  1962. FOrdinal := AOrdinal;
  1963. FResolveCheck := AResolveCheck;
  1964. DotPos := AnsiPos('.', ForwardedName);
  1965. if DotPos > 0 then
  1966. FForwardedDotPos := Copy(ForwardedName, DotPos + 1, Length(ForwardedName) - DotPos)
  1967. else
  1968. FForwardedDotPos := '';
  1969. end;
  1970. function TJclPeExportFuncItem.GetAddressOrForwardStr: string;
  1971. begin
  1972. if IsForwarded then
  1973. Result := ForwardedName
  1974. else
  1975. FmtStr(Result, '%.8x', [Address]);
  1976. end;
  1977. function TJclPeExportFuncItem.GetForwardedFuncName: string;
  1978. begin
  1979. if (Length(FForwardedDotPos) > 0) and (FForwardedDotPos[1] <> '#') then
  1980. Result := FForwardedDotPos
  1981. else
  1982. Result := '';
  1983. end;
  1984. function TJclPeExportFuncItem.GetForwardedFuncOrdinal: DWORD;
  1985. begin
  1986. if (Length(FForwardedDotPos) > 0) and (FForwardedDotPos[1] = '#') then
  1987. Result := StrToIntDef(FForwardedDotPos, 0)
  1988. else
  1989. Result := 0;
  1990. end;
  1991. function TJclPeExportFuncItem.GetForwardedLibName: string;
  1992. begin
  1993. if Length(FForwardedDotPos) = 0 then
  1994. Result := ''
  1995. else
  1996. Result := AnsiLowerCase(Copy(FForwardedName, 1, Length(FForwardedName) - Length(FForwardedDotPos) - 1)) + BinaryExtensionLibrary;
  1997. end;
  1998. function TJclPeExportFuncItem.GetIsExportedVariable: Boolean;
  1999. begin
  2000. case FExportList.Image.Target of
  2001. taWin32:
  2002. begin
  2003. {$IFDEF DELPHI64_TEMPORARY}
  2004. System.Error(rePlatformNotImplemented);//there is no BaseOfData in the 32-bit header for Win64
  2005. Result := False;
  2006. {$ELSE ~DELPHI64_TEMPORARY}
  2007. Result := (Address >= FExportList.Image.OptionalHeader32.BaseOfData);
  2008. {$ENDIF ~DELPHI64_TEMPORARY}
  2009. end;
  2010. taWin64:
  2011. Result := False;
  2012. // TODO equivalent for 64-bit modules
  2013. //Result := (Address >= FExportList.Image.OptionalHeader64.BaseOfData);
  2014. else
  2015. Result := False;
  2016. end;
  2017. end;
  2018. function TJclPeExportFuncItem.GetIsForwarded: Boolean;
  2019. begin
  2020. Result := Length(FForwardedName) <> 0;
  2021. end;
  2022. function TJclPeExportFuncItem.GetMappedAddress: Pointer;
  2023. begin
  2024. Result := FExportList.Image.RvaToVa(FAddress);
  2025. end;
  2026. function TJclPeExportFuncItem.GetSectionName: string;
  2027. begin
  2028. if IsForwarded then
  2029. Result := ''
  2030. else
  2031. with FExportList.Image do
  2032. Result := ImageSectionNameFromRva[Address];
  2033. end;
  2034. procedure TJclPeExportFuncItem.SetResolveCheck(Value: TJclPeResolveCheck);
  2035. begin
  2036. FResolveCheck := Value;
  2037. end;
  2038. // Export sort functions
  2039. function ExportSortByName(Item1, Item2: Pointer): Integer;
  2040. begin
  2041. Result := CompareStr(TJclPeExportFuncItem(Item1).Name, TJclPeExportFuncItem(Item2).Name);
  2042. end;
  2043. function ExportSortByNameDESC(Item1, Item2: Pointer): Integer;
  2044. begin
  2045. Result := ExportSortByName(Item2, Item1);
  2046. end;
  2047. function ExportSortByOrdinal(Item1, Item2: Pointer): Integer;
  2048. begin
  2049. Result := TJclPeExportFuncItem(Item1).Ordinal - TJclPeExportFuncItem(Item2).Ordinal;
  2050. end;
  2051. function ExportSortByOrdinalDESC(Item1, Item2: Pointer): Integer;
  2052. begin
  2053. Result := ExportSortByOrdinal(Item2, Item1);
  2054. end;
  2055. function ExportSortByHint(Item1, Item2: Pointer): Integer;
  2056. begin
  2057. Result := TJclPeExportFuncItem(Item1).Hint - TJclPeExportFuncItem(Item2).Hint;
  2058. end;
  2059. function ExportSortByHintDESC(Item1, Item2: Pointer): Integer;
  2060. begin
  2061. Result := ExportSortByHint(Item2, Item1);
  2062. end;
  2063. function ExportSortByAddress(Item1, Item2: Pointer): Integer;
  2064. begin
  2065. Result := INT_PTR(TJclPeExportFuncItem(Item1).Address) - INT_PTR(TJclPeExportFuncItem(Item2).Address);
  2066. if Result = 0 then
  2067. Result := ExportSortByName(Item1, Item2);
  2068. end;
  2069. function ExportSortByAddressDESC(Item1, Item2: Pointer): Integer;
  2070. begin
  2071. Result := ExportSortByAddress(Item2, Item1);
  2072. end;
  2073. function ExportSortByForwarded(Item1, Item2: Pointer): Integer;
  2074. begin
  2075. Result := CompareStr(TJclPeExportFuncItem(Item1).ForwardedName, TJclPeExportFuncItem(Item2).ForwardedName);
  2076. if Result = 0 then
  2077. Result := ExportSortByName(Item1, Item2);
  2078. end;
  2079. function ExportSortByForwardedDESC(Item1, Item2: Pointer): Integer;
  2080. begin
  2081. Result := ExportSortByForwarded(Item2, Item1);
  2082. end;
  2083. function ExportSortByAddrOrFwd(Item1, Item2: Pointer): Integer;
  2084. begin
  2085. Result := CompareStr(TJclPeExportFuncItem(Item1).AddressOrForwardStr, TJclPeExportFuncItem(Item2).AddressOrForwardStr);
  2086. end;
  2087. function ExportSortByAddrOrFwdDESC(Item1, Item2: Pointer): Integer;
  2088. begin
  2089. Result := ExportSortByAddrOrFwd(Item2, Item1);
  2090. end;
  2091. function ExportSortBySection(Item1, Item2: Pointer): Integer;
  2092. begin
  2093. Result := CompareStr(TJclPeExportFuncItem(Item1).SectionName, TJclPeExportFuncItem(Item2).SectionName);
  2094. if Result = 0 then
  2095. Result := ExportSortByName(Item1, Item2);
  2096. end;
  2097. function ExportSortBySectionDESC(Item1, Item2: Pointer): Integer;
  2098. begin
  2099. Result := ExportSortBySection(Item2, Item1);
  2100. end;
  2101. //=== { TJclPeExportFuncList } ===============================================
  2102. constructor TJclPeExportFuncList.Create(AImage: TJclPeImage);
  2103. begin
  2104. inherited Create(AImage);
  2105. FTotalResolveCheck := icNotChecked;
  2106. CreateList;
  2107. end;
  2108. destructor TJclPeExportFuncList.Destroy;
  2109. begin
  2110. FreeAndNil(FForwardedLibsList);
  2111. inherited Destroy;
  2112. end;
  2113. function TJclPeExportFuncList.CanPerformFastNameSearch: Boolean;
  2114. begin
  2115. Result := FSorted and (FLastSortType = esName) and not FLastSortDescending;
  2116. end;
  2117. procedure TJclPeExportFuncList.CheckForwards(PeImageCache: TJclPeImagesCache);
  2118. var
  2119. I: Integer;
  2120. FullFileName: TFileName;
  2121. ForwardPeImage: TJclPeImage;
  2122. ModuleResolveCheck: TJclPeResolveCheck;
  2123. procedure PerformCheck(const ModuleName: string);
  2124. var
  2125. I: Integer;
  2126. Item: TJclPeExportFuncItem;
  2127. EL: TJclPeExportFuncList;
  2128. begin
  2129. EL := ForwardPeImage.ExportList;
  2130. EL.PrepareForFastNameSearch;
  2131. ModuleResolveCheck := icResolved;
  2132. for I := 0 to Count - 1 do
  2133. begin
  2134. Item := Items[I];
  2135. if (not Item.IsForwarded) or (Item.ResolveCheck <> icNotChecked) or
  2136. (Item.ForwardedLibName <> ModuleName) then
  2137. Continue;
  2138. if EL.ItemFromName[Item.ForwardedFuncName] = nil then
  2139. begin
  2140. Item.SetResolveCheck(icUnresolved);
  2141. ModuleResolveCheck := icUnresolved;
  2142. end
  2143. else
  2144. Item.SetResolveCheck(icResolved);
  2145. end;
  2146. end;
  2147. begin
  2148. if not AnyForwards then
  2149. Exit;
  2150. FTotalResolveCheck := icResolved;
  2151. if PeImageCache <> nil then
  2152. ForwardPeImage := nil // to make the compiler happy
  2153. else
  2154. ForwardPeImage := TJclPeImage.Create(True);
  2155. try
  2156. for I := 0 to ForwardedLibsList.Count - 1 do
  2157. begin
  2158. FullFileName := Image.ExpandModuleName(ForwardedLibsList[I]);
  2159. if PeImageCache <> nil then
  2160. ForwardPeImage := PeImageCache[FullFileName]
  2161. else
  2162. ForwardPeImage.FileName := FullFileName;
  2163. if ForwardPeImage.StatusOK then
  2164. PerformCheck(ForwardedLibsList[I])
  2165. else
  2166. ModuleResolveCheck := icUnresolved;
  2167. FForwardedLibsList.Objects[I] := Pointer(ModuleResolveCheck);
  2168. if ModuleResolveCheck = icUnresolved then
  2169. FTotalResolveCheck := icUnresolved;
  2170. end;
  2171. finally
  2172. if PeImageCache = nil then
  2173. ForwardPeImage.Free;
  2174. end;
  2175. end;
  2176. procedure TJclPeExportFuncList.CreateList;
  2177. var
  2178. Functions: Pointer;
  2179. Address, NameCount: DWORD;
  2180. NameOrdinals: PWORD;
  2181. Names: PDWORD;
  2182. I: Integer;
  2183. ExportItem: TJclPeExportFuncItem;
  2184. ExportVABegin, ExportVAEnd: DWORD;
  2185. UTF8Name: TUTF8String;
  2186. ForwardedName, ExportName: string;
  2187. begin
  2188. with Image do
  2189. begin
  2190. if not StatusOK then
  2191. Exit;
  2192. with Directories[IMAGE_DIRECTORY_ENTRY_EXPORT] do
  2193. begin
  2194. ExportVABegin := VirtualAddress;
  2195. ExportVAEnd := VirtualAddress + TJclAddr(Size);
  2196. end;
  2197. FExportDir := DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_EXPORT);
  2198. if FExportDir <> nil then
  2199. begin
  2200. FBase := FExportDir^.Base;
  2201. FFunctionCount := FExportDir^.NumberOfFunctions;
  2202. Functions := RvaToVa(FExportDir^.AddressOfFunctions);
  2203. NameOrdinals := RvaToVa(FExportDir^.AddressOfNameOrdinals);
  2204. Names := RvaToVa(FExportDir^.AddressOfNames);
  2205. NameCount := FExportDir^.NumberOfNames;
  2206. Count := FExportDir^.NumberOfFunctions;
  2207. for I := 0 to Count - 1 do
  2208. begin
  2209. Address := PDWORD(TJclAddr(Functions) + TJclAddr(I) * SizeOf(DWORD))^;
  2210. if (Address >= ExportVABegin) and (Address <= ExportVAEnd) then
  2211. begin
  2212. FAnyForwards := True;
  2213. UTF8Name := PAnsiChar(RvaToVa(Address));
  2214. if not TryUTF8ToString(UTF8Name, ForwardedName) then
  2215. ForwardedName := string(UTF8Name);
  2216. end
  2217. else
  2218. ForwardedName := '';
  2219. ExportItem := TJclPeExportFuncItem.Create(Self, '',
  2220. ForwardedName, Address, $FFFF, TJclAddr(I) + FBase, icNotChecked);
  2221. List{$IFNDEF RTL230_UP}^{$ENDIF !RTL230_UP}[I] := ExportItem;
  2222. end;
  2223. if NameCount > 0 then
  2224. begin
  2225. for I := 0 to NameCount - 1 do
  2226. begin
  2227. // named function
  2228. UTF8Name := PAnsiChar(RvaToVa(Names^));
  2229. if not TryUTF8ToString(UTF8Name, ExportName) then
  2230. ExportName := string(UTF8Name);
  2231. ExportItem := TJclPeExportFuncItem(List{$IFNDEF RTL230_UP}^{$ENDIF !RTL230_UP}[NameOrdinals^]);
  2232. ExportItem.FName := ExportName;
  2233. ExportItem.FHint := I;
  2234. Inc(NameOrdinals);
  2235. Inc(Names);
  2236. end;
  2237. end;
  2238. end;
  2239. end;
  2240. end;
  2241. function TJclPeExportFuncList.GetForwardedLibsList: TStrings;
  2242. var
  2243. I: Integer;
  2244. begin
  2245. if FForwardedLibsList = nil then
  2246. begin
  2247. FForwardedLibsList := TStringList.Create;
  2248. FForwardedLibsList.Sorted := True;
  2249. FForwardedLibsList.Duplicates := dupIgnore;
  2250. if FAnyForwards then
  2251. for I := 0 to Count - 1 do
  2252. with Items[I] do
  2253. if IsForwarded then
  2254. FForwardedLibsList.AddObject(ForwardedLibName, Pointer(icNotChecked));
  2255. end;
  2256. Result := FForwardedLibsList;
  2257. end;
  2258. function TJclPeExportFuncList.GetItemFromAddress(Address: DWORD): TJclPeExportFuncItem;
  2259. var
  2260. I: Integer;
  2261. begin
  2262. Result := nil;
  2263. for I := 0 to Count - 1 do
  2264. if Items[I].Address = Address then
  2265. begin
  2266. Result := Items[I];
  2267. Break;
  2268. end;
  2269. end;
  2270. function TJclPeExportFuncList.GetItemFromName(const Name: string): TJclPeExportFuncItem;
  2271. var
  2272. L, H, I, C: Integer;
  2273. B: Boolean;
  2274. begin
  2275. Result := nil;
  2276. if CanPerformFastNameSearch then
  2277. begin
  2278. L := 0;
  2279. H := Count - 1;
  2280. B := False;
  2281. while L <= H do
  2282. begin
  2283. I := (L + H) shr 1;
  2284. C := CompareStr(Items[I].Name, Name);
  2285. if C < 0 then
  2286. L := I + 1
  2287. else
  2288. begin
  2289. H := I - 1;
  2290. if C = 0 then
  2291. begin
  2292. B := True;
  2293. L := I;
  2294. end;
  2295. end;
  2296. end;
  2297. if B then
  2298. Result := Items[L];
  2299. end
  2300. else
  2301. for I := 0 to Count - 1 do
  2302. if Items[I].Name = Name then
  2303. begin
  2304. Result := Items[I];
  2305. Break;
  2306. end;
  2307. end;
  2308. function TJclPeExportFuncList.GetItemFromOrdinal(Ordinal: DWORD): TJclPeExportFuncItem;
  2309. var
  2310. I: Integer;
  2311. begin
  2312. Result := nil;
  2313. for I := 0 to Count - 1 do
  2314. if Items[I].Ordinal = Ordinal then
  2315. begin
  2316. Result := Items[I];
  2317. Break;
  2318. end;
  2319. end;
  2320. function TJclPeExportFuncList.GetItems(Index: Integer): TJclPeExportFuncItem;
  2321. begin
  2322. Result := TJclPeExportFuncItem(Get(Index));
  2323. end;
  2324. function TJclPeExportFuncList.GetName: string;
  2325. var
  2326. UTF8ExportName: TUTF8String;
  2327. begin
  2328. if (FExportDir = nil) or (FExportDir^.Name = 0) then
  2329. Result := ''
  2330. else
  2331. begin
  2332. UTF8ExportName := PAnsiChar(Image.RvaToVa(FExportDir^.Name));
  2333. if not TryUTF8ToString(UTF8ExportName, Result) then
  2334. Result := string(UTF8ExportName);
  2335. end;
  2336. end;
  2337. class function TJclPeExportFuncList.ItemName(Item: TJclPeExportFuncItem): string;
  2338. begin
  2339. if Item = nil then
  2340. Result := ''
  2341. else
  2342. Result := Item.Name;
  2343. end;
  2344. function TJclPeExportFuncList.OrdinalValid(Ordinal: DWORD): Boolean;
  2345. begin
  2346. Result := (FExportDir <> nil) and (Ordinal >= Base) and
  2347. (Ordinal < FunctionCount + Base);
  2348. end;
  2349. procedure TJclPeExportFuncList.PrepareForFastNameSearch;
  2350. begin
  2351. if not CanPerformFastNameSearch then
  2352. SortList(esName, False);
  2353. end;
  2354. function TJclPeExportFuncList.SmartFindName(const CompareName: string;
  2355. Options: TJclSmartCompOptions): TJclPeExportFuncItem;
  2356. var
  2357. I: Integer;
  2358. begin
  2359. Result := nil;
  2360. for I := 0 to Count - 1 do
  2361. begin
  2362. if PeSmartFunctionNameSame(CompareName, Items[I].Name, Options) then
  2363. begin
  2364. Result := Items[I];
  2365. Break;
  2366. end;
  2367. end;
  2368. end;
  2369. procedure TJclPeExportFuncList.SortList(SortType: TJclPeExportSort; Descending: Boolean);
  2370. const
  2371. SortFunctions: array [TJclPeExportSort, Boolean] of TListSortCompare =
  2372. ((ExportSortByName, ExportSortByNameDESC),
  2373. (ExportSortByOrdinal, ExportSortByOrdinalDESC),
  2374. (ExportSortByHint, ExportSortByHintDESC),
  2375. (ExportSortByAddress, ExportSortByAddressDESC),
  2376. (ExportSortByForwarded, ExportSortByForwardedDESC),
  2377. (ExportSortByAddrOrFwd, ExportSortByAddrOrFwdDESC),
  2378. (ExportSortBySection, ExportSortBySectionDESC)
  2379. );
  2380. begin
  2381. if not FSorted or (SortType <> FLastSortType) or (Descending <> FLastSortDescending) then
  2382. begin
  2383. Sort(SortFunctions[SortType, Descending]);
  2384. FLastSortType := SortType;
  2385. FLastSortDescending := Descending;
  2386. FSorted := True;
  2387. end;
  2388. end;
  2389. //=== { TJclPeResourceRawStream } ============================================
  2390. constructor TJclPeResourceRawStream.Create(AResourceItem: TJclPeResourceItem);
  2391. begin
  2392. Assert(not AResourceItem.IsDirectory);
  2393. inherited Create;
  2394. SetPointer(AResourceItem.RawEntryData, AResourceItem.RawEntryDataSize);
  2395. end;
  2396. function TJclPeResourceRawStream.Write(const Buffer; Count: Integer): Longint;
  2397. begin
  2398. raise EJclPeImageError.CreateRes(@RsPeReadOnlyStream);
  2399. end;
  2400. //=== { TJclPeResourceItem } =================================================
  2401. constructor TJclPeResourceItem.Create(AImage: TJclPeImage;
  2402. AParentItem: TJclPeResourceItem; AEntry: PImageResourceDirectoryEntry);
  2403. begin
  2404. inherited Create;
  2405. FImage := AImage;
  2406. FEntry := AEntry;
  2407. FParentItem := AParentItem;
  2408. if AParentItem = nil then
  2409. FLevel := 1
  2410. else
  2411. FLevel := AParentItem.Level + 1;
  2412. end;
  2413. destructor TJclPeResourceItem.Destroy;
  2414. begin
  2415. FreeAndNil(FList);
  2416. inherited Destroy;
  2417. end;
  2418. function TJclPeResourceItem.CompareName(AName: PChar): Boolean;
  2419. var
  2420. P: PChar;
  2421. begin
  2422. if IsName then
  2423. P := PChar(Name)
  2424. else
  2425. P := PChar(FEntry^.Name and $FFFF); // Integer encoded in a PChar
  2426. Result := CompareResourceName(AName, P);
  2427. end;
  2428. function TJclPeResourceItem.GetDataEntry: PImageResourceDataEntry;
  2429. begin
  2430. if GetIsDirectory then
  2431. Result := nil
  2432. else
  2433. Result := PImageResourceDataEntry(OffsetToRawData(FEntry^.OffsetToData));
  2434. end;
  2435. function TJclPeResourceItem.GetIsDirectory: Boolean;
  2436. begin
  2437. Result := FEntry^.OffsetToData and IMAGE_RESOURCE_DATA_IS_DIRECTORY <> 0;
  2438. end;
  2439. function TJclPeResourceItem.GetIsName: Boolean;
  2440. begin
  2441. Result := FEntry^.Name and IMAGE_RESOURCE_NAME_IS_STRING <> 0;
  2442. end;
  2443. function TJclPeResourceItem.GetLangID: LANGID;
  2444. begin
  2445. if IsDirectory then
  2446. begin
  2447. GetList;
  2448. if FList.Count = 1 then
  2449. Result := StrToIntDef(FList[0].Name, 0)
  2450. else
  2451. Result := 0;
  2452. end
  2453. else
  2454. Result := StrToIntDef(Name, 0);
  2455. end;
  2456. function TJclPeResourceItem.GetList: TJclPeResourceList;
  2457. begin
  2458. if not IsDirectory then
  2459. begin
  2460. if Image.NoExceptions then
  2461. begin
  2462. Result := nil;
  2463. Exit;
  2464. end
  2465. else
  2466. raise EJclPeImageError.CreateRes(@RsPeNotResDir);
  2467. end;
  2468. if FList = nil then
  2469. FList := FImage.ResourceListCreate(SubDirData, Self);
  2470. Result := FList;
  2471. end;
  2472. function TJclPeResourceItem.GetName: string;
  2473. begin
  2474. if IsName then
  2475. begin
  2476. if FNameCache = '' then
  2477. begin
  2478. with PImageResourceDirStringU(OffsetToRawData(FEntry^.Name))^ do
  2479. FNameCache := WideCharLenToString(NameString, Length);
  2480. StrResetLength(FNameCache);
  2481. end;
  2482. Result := FNameCache;
  2483. end
  2484. else
  2485. Result := IntToStr(FEntry^.Name and $FFFF);
  2486. end;
  2487. function TJclPeResourceItem.GetParameterName: string;
  2488. begin
  2489. if IsName then
  2490. Result := Name
  2491. else
  2492. Result := Format('#%d', [FEntry^.Name and $FFFF]);
  2493. end;
  2494. function TJclPeResourceItem.GetRawEntryData: Pointer;
  2495. begin
  2496. if GetIsDirectory then
  2497. Result := nil
  2498. else
  2499. Result := FImage.RvaToVa(GetDataEntry^.OffsetToData);
  2500. end;
  2501. function TJclPeResourceItem.GetRawEntryDataSize: Integer;
  2502. begin
  2503. if GetIsDirectory then
  2504. Result := -1
  2505. else
  2506. Result := PImageResourceDataEntry(OffsetToRawData(FEntry^.OffsetToData))^.Size;
  2507. end;
  2508. function TJclPeResourceItem.GetResourceType: TJclPeResourceKind;
  2509. begin
  2510. with Level1Item do
  2511. begin
  2512. if FEntry^.Name < Cardinal(High(TJclPeResourceKind)) then
  2513. Result := TJclPeResourceKind(FEntry^.Name)
  2514. else
  2515. Result := rtUserDefined
  2516. end;
  2517. end;
  2518. function TJclPeResourceItem.GetResourceTypeStr: string;
  2519. begin
  2520. with Level1Item do
  2521. begin
  2522. if FEntry^.Name < Cardinal(High(TJclPeResourceKind)) then
  2523. Result := Copy(GetEnumName(TypeInfo(TJclPeResourceKind), Ord(FEntry^.Name)), 3, 30)
  2524. else
  2525. Result := Name;
  2526. end;
  2527. end;
  2528. function TJclPeResourceItem.Level1Item: TJclPeResourceItem;
  2529. begin
  2530. Result := Self;
  2531. while Result.FParentItem <> nil do
  2532. Result := Result.FParentItem;
  2533. end;
  2534. function TJclPeResourceItem.OffsetToRawData(Ofs: DWORD): TJclAddr;
  2535. begin
  2536. Result := (Ofs and $7FFFFFFF) + Image.ResourceVA;
  2537. end;
  2538. function TJclPeResourceItem.SubDirData: PImageResourceDirectory;
  2539. begin
  2540. Result := Pointer(OffsetToRawData(FEntry^.OffsetToData));
  2541. end;
  2542. //=== { TJclPeResourceList } =================================================
  2543. constructor TJclPeResourceList.Create(AImage: TJclPeImage;
  2544. AParentItem: TJclPeResourceItem; ADirectory: PImageResourceDirectory);
  2545. begin
  2546. inherited Create(AImage);
  2547. FDirectory := ADirectory;
  2548. FParentItem := AParentItem;
  2549. CreateList(AParentItem);
  2550. end;
  2551. procedure TJclPeResourceList.CreateList(AParentItem: TJclPeResourceItem);
  2552. var
  2553. Entry: PImageResourceDirectoryEntry;
  2554. DirItem: TJclPeResourceItem;
  2555. I: Integer;
  2556. begin
  2557. if FDirectory = nil then
  2558. Exit;
  2559. Entry := Pointer(TJclAddr(FDirectory) + SizeOf(TImageResourceDirectory));
  2560. for I := 1 to DWORD(FDirectory^.NumberOfNamedEntries) + DWORD(FDirectory^.NumberOfIdEntries) do
  2561. begin
  2562. DirItem := Image.ResourceItemCreate(Entry, AParentItem);
  2563. Add(DirItem);
  2564. Inc(Entry);
  2565. end;
  2566. end;
  2567. function TJclPeResourceList.FindName(const Name: string): TJclPeResourceItem;
  2568. var
  2569. I: Integer;
  2570. begin
  2571. Result := nil;
  2572. for I := 0 to Count - 1 do
  2573. if StrSame(Items[I].Name, Name) then
  2574. begin
  2575. Result := Items[I];
  2576. Break;
  2577. end;
  2578. end;
  2579. function TJclPeResourceList.GetItems(Index: Integer): TJclPeResourceItem;
  2580. begin
  2581. Result := TJclPeResourceItem(Get(Index));
  2582. end;
  2583. //=== { TJclPeRootResourceList } =============================================
  2584. destructor TJclPeRootResourceList.Destroy;
  2585. begin
  2586. FreeAndNil(FManifestContent);
  2587. inherited Destroy;
  2588. end;
  2589. function TJclPeRootResourceList.FindResource(ResourceType: TJclPeResourceKind;
  2590. const ResourceName: string): TJclPeResourceItem;
  2591. var
  2592. I: Integer;
  2593. TypeItem: TJclPeResourceItem;
  2594. begin
  2595. Result := nil;
  2596. TypeItem := nil;
  2597. for I := 0 to Count - 1 do
  2598. begin
  2599. if Items[I].ResourceType = ResourceType then
  2600. begin
  2601. TypeItem := Items[I];
  2602. Break;
  2603. end;
  2604. end;
  2605. if TypeItem <> nil then
  2606. if ResourceName = '' then
  2607. Result := TypeItem
  2608. else
  2609. with TypeItem.List do
  2610. for I := 0 to Count - 1 do
  2611. if Items[I].Name = ResourceName then
  2612. begin
  2613. Result := Items[I];
  2614. Break;
  2615. end;
  2616. end;
  2617. function TJclPeRootResourceList.FindResource(const ResourceType: PChar;
  2618. const ResourceName: PChar): TJclPeResourceItem;
  2619. var
  2620. I: Integer;
  2621. TypeItem: TJclPeResourceItem;
  2622. begin
  2623. Result := nil;
  2624. TypeItem := nil;
  2625. for I := 0 to Count - 1 do
  2626. if Items[I].CompareName(ResourceType) then
  2627. begin
  2628. TypeItem := Items[I];
  2629. Break;
  2630. end;
  2631. if TypeItem <> nil then
  2632. if ResourceName = nil then
  2633. Result := TypeItem
  2634. else
  2635. with TypeItem.List do
  2636. for I := 0 to Count - 1 do
  2637. if Items[I].CompareName(ResourceName) then
  2638. begin
  2639. Result := Items[I];
  2640. Break;
  2641. end;
  2642. end;
  2643. function TJclPeRootResourceList.GetManifestContent: TStrings;
  2644. var
  2645. ManifestFileName: string;
  2646. ResItem: TJclPeResourceItem;
  2647. ResStream: TJclPeResourceRawStream;
  2648. begin
  2649. if FManifestContent = nil then
  2650. begin
  2651. FManifestContent := TStringList.Create;
  2652. ResItem := FindResource(RT_MANIFEST, CREATEPROCESS_MANIFEST_RESOURCE_ID);
  2653. if ResItem = nil then
  2654. begin
  2655. ManifestFileName := Image.FileName + MANIFESTExtension;
  2656. if FileExists(ManifestFileName) then
  2657. FManifestContent.LoadFromFile(ManifestFileName);
  2658. end
  2659. else
  2660. begin
  2661. ResStream := TJclPeResourceRawStream.Create(ResItem.List[0]);
  2662. try
  2663. FManifestContent.LoadFromStream(ResStream);
  2664. finally
  2665. ResStream.Free;
  2666. end;
  2667. end;
  2668. end;
  2669. Result := FManifestContent;
  2670. end;
  2671. function TJclPeRootResourceList.ListResourceNames(ResourceType: TJclPeResourceKind;
  2672. const Strings: TStrings): Boolean;
  2673. var
  2674. ResTypeItem, TempItem: TJclPeResourceItem;
  2675. I: Integer;
  2676. begin
  2677. ResTypeItem := FindResource(ResourceType, '');
  2678. Result := (ResTypeItem <> nil);
  2679. if Result then
  2680. begin
  2681. Strings.BeginUpdate;
  2682. try
  2683. with ResTypeItem.List do
  2684. for I := 0 to Count - 1 do
  2685. begin
  2686. TempItem := Items[I];
  2687. Strings.AddObject(TempItem.Name, Pointer(TempItem.IsName));
  2688. end;
  2689. finally
  2690. Strings.EndUpdate;
  2691. end;
  2692. end;
  2693. end;
  2694. //=== { TJclPeRelocEntry } ===================================================
  2695. constructor TJclPeRelocEntry.Create(AChunk: PImageBaseRelocation; ACount: Integer);
  2696. begin
  2697. inherited Create;
  2698. FChunk := AChunk;
  2699. FCount := ACount;
  2700. end;
  2701. function TJclPeRelocEntry.GetRelocations(Index: Integer): TJclPeRelocation;
  2702. var
  2703. Temp: Word;
  2704. begin
  2705. Temp := PWord(TJclAddr(FChunk) + SizeOf(TImageBaseRelocation) + DWORD(Index) * SizeOf(Word))^;
  2706. Result.Address := Temp and $0FFF;
  2707. Result.RelocType := (Temp and $F000) shr 12;
  2708. Result.VirtualAddress := TJclAddr(Result.Address) + VirtualAddress;
  2709. end;
  2710. function TJclPeRelocEntry.GetSize: DWORD;
  2711. begin
  2712. Result := FChunk^.SizeOfBlock;
  2713. end;
  2714. function TJclPeRelocEntry.GetVirtualAddress: DWORD;
  2715. begin
  2716. Result := FChunk^.VirtualAddress;
  2717. end;
  2718. //=== { TJclPeRelocList } ====================================================
  2719. constructor TJclPeRelocList.Create(AImage: TJclPeImage);
  2720. begin
  2721. inherited Create(AImage);
  2722. CreateList;
  2723. end;
  2724. procedure TJclPeRelocList.CreateList;
  2725. var
  2726. Chunk: PImageBaseRelocation;
  2727. Item: TJclPeRelocEntry;
  2728. RelocCount: Integer;
  2729. begin
  2730. with Image do
  2731. begin
  2732. if not StatusOK then
  2733. Exit;
  2734. Chunk := DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_BASERELOC);
  2735. if Chunk = nil then
  2736. Exit;
  2737. FAllItemCount := 0;
  2738. while Chunk^.SizeOfBlock <> 0 do
  2739. begin
  2740. RelocCount := (Chunk^.SizeOfBlock - SizeOf(TImageBaseRelocation)) div SizeOf(Word);
  2741. Item := TJclPeRelocEntry.Create(Chunk, RelocCount);
  2742. Inc(FAllItemCount, RelocCount);
  2743. Add(Item);
  2744. Chunk := Pointer(TJclAddr(Chunk) + Chunk^.SizeOfBlock);
  2745. end;
  2746. end;
  2747. end;
  2748. function TJclPeRelocList.GetAllItems(Index: Integer): TJclPeRelocation;
  2749. var
  2750. I, N, C: Integer;
  2751. begin
  2752. N := Index;
  2753. for I := 0 to Count - 1 do
  2754. begin
  2755. C := Items[I].Count;
  2756. Dec(N, C);
  2757. if N < 0 then
  2758. begin
  2759. Result := Items[I][N + C];
  2760. Break;
  2761. end;
  2762. end;
  2763. end;
  2764. function TJclPeRelocList.GetItems(Index: Integer): TJclPeRelocEntry;
  2765. begin
  2766. Result := TJclPeRelocEntry(Get(Index));
  2767. end;
  2768. //=== { TJclPeDebugList } ====================================================
  2769. constructor TJclPeDebugList.Create(AImage: TJclPeImage);
  2770. begin
  2771. inherited Create(AImage);
  2772. OwnsObjects := False;
  2773. CreateList;
  2774. end;
  2775. function TJclPeDebugList.IsTD32DebugInfo(DebugDir: PImageDebugDirectory): Boolean;
  2776. var
  2777. Base: Pointer;
  2778. begin
  2779. Base := Image.RvaToVa(DebugDir^.AddressOfRawData);
  2780. Result := TJclTD32InfoParser.IsTD32DebugInfoValid(Base, DebugDir^.SizeOfData);
  2781. end;
  2782. procedure TJclPeDebugList.CreateList;
  2783. var
  2784. DebugImageDir: TImageDataDirectory;
  2785. DebugDir: PImageDebugDirectory;
  2786. Header: PImageSectionHeader;
  2787. FormatCount, I: Integer;
  2788. begin
  2789. with Image do
  2790. begin
  2791. if not StatusOK then
  2792. Exit;
  2793. DebugImageDir := Directories[IMAGE_DIRECTORY_ENTRY_DEBUG];
  2794. if DebugImageDir.VirtualAddress = 0 then
  2795. Exit;
  2796. if GetSectionHeader(DebugSectionName, Header) and
  2797. (Header^.VirtualAddress = DebugImageDir.VirtualAddress) and
  2798. (IsTD32DebugInfo(RvaToVa(DebugImageDir.VirtualAddress))) then
  2799. begin
  2800. // TD32 debug image directory is broken...size should be in bytes, not count.
  2801. FormatCount := DebugImageDir.Size;
  2802. end
  2803. else
  2804. begin
  2805. FormatCount := DebugImageDir.Size div SizeOf(TImageDebugDirectory);
  2806. end;
  2807. DebugDir := RvaToVa(DebugImageDir.VirtualAddress);
  2808. for I := 1 to FormatCount do
  2809. begin
  2810. Add(TObject(DebugDir));
  2811. Inc(DebugDir);
  2812. end;
  2813. end;
  2814. end;
  2815. function TJclPeDebugList.GetItems(Index: Integer): TImageDebugDirectory;
  2816. begin
  2817. Result := PImageDebugDirectory(Get(Index))^;
  2818. end;
  2819. //=== { TJclPeCertificate } ==================================================
  2820. constructor TJclPeCertificate.Create(AHeader: TWinCertificate; AData: Pointer);
  2821. begin
  2822. inherited Create;
  2823. FHeader := AHeader;
  2824. FData := AData;
  2825. end;
  2826. //=== { TJclPeCertificateList } ==============================================
  2827. constructor TJclPeCertificateList.Create(AImage: TJclPeImage);
  2828. begin
  2829. inherited Create(AImage);
  2830. CreateList;
  2831. end;
  2832. procedure TJclPeCertificateList.CreateList;
  2833. var
  2834. Directory: TImageDataDirectory;
  2835. CertPtr: PChar;
  2836. TotalSize: Integer;
  2837. Item: TJclPeCertificate;
  2838. begin
  2839. Directory := Image.Directories[IMAGE_DIRECTORY_ENTRY_SECURITY];
  2840. if Directory.VirtualAddress = 0 then
  2841. Exit;
  2842. CertPtr := Image.RawToVa(Directory.VirtualAddress); // Security directory is a raw offset
  2843. TotalSize := Directory.Size;
  2844. while TotalSize >= SizeOf(TWinCertificate) do
  2845. begin
  2846. Item := TJclPeCertificate.Create(PWinCertificate(CertPtr)^, CertPtr + SizeOf(TWinCertificate));
  2847. Dec(TotalSize, Item.Header.dwLength);
  2848. Add(Item);
  2849. end;
  2850. end;
  2851. function TJclPeCertificateList.GetItems(Index: Integer): TJclPeCertificate;
  2852. begin
  2853. Result := TJclPeCertificate(Get(Index));
  2854. end;
  2855. //=== { TJclPeCLRHeader } ====================================================
  2856. constructor TJclPeCLRHeader.Create(AImage: TJclPeImage);
  2857. begin
  2858. FImage := AImage;
  2859. ReadHeader;
  2860. end;
  2861. function TJclPeCLRHeader.GetHasMetadata: Boolean;
  2862. const
  2863. METADATA_SIGNATURE = $424A5342; // Reference: Partition II Metadata.doc - 23.2.1 Metadata root
  2864. begin
  2865. with Header.MetaData do
  2866. Result := (VirtualAddress <> 0) and (PDWORD(FImage.RvaToVa(VirtualAddress))^ = METADATA_SIGNATURE);
  2867. end;
  2868. { TODO -cDOC : "Flier Lu" <flier_lu att yahoo dott com dott cn> }
  2869. function TJclPeCLRHeader.GetVersionString: string;
  2870. begin
  2871. Result := FormatVersionString(Header.MajorRuntimeVersion, Header.MinorRuntimeVersion);
  2872. end;
  2873. procedure TJclPeCLRHeader.ReadHeader;
  2874. var
  2875. HeaderPtr: PImageCor20Header;
  2876. begin
  2877. HeaderPtr := Image.DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR);
  2878. if (HeaderPtr <> nil) and (HeaderPtr^.cb >= SizeOf(TImageCor20Header)) then
  2879. FHeader := HeaderPtr^;
  2880. end;
  2881. //=== { TJclPeImage } ========================================================
  2882. constructor TJclPeImage.Create(ANoExceptions: Boolean);
  2883. begin
  2884. FNoExceptions := ANoExceptions;
  2885. FReadOnlyAccess := True;
  2886. FImageSections := TStringList.Create;
  2887. FStringTable := TStringList.Create;
  2888. end;
  2889. destructor TJclPeImage.Destroy;
  2890. begin
  2891. Clear;
  2892. FreeAndNil(FImageSections);
  2893. FStringTable.Free;
  2894. inherited Destroy;
  2895. end;
  2896. procedure TJclPeImage.AfterOpen;
  2897. begin
  2898. end;
  2899. procedure TJclPeImage.AttachLoadedModule(const Handle: HMODULE);
  2900. procedure AttachLoadedModule32;
  2901. var
  2902. NtHeaders: PImageNtHeaders32;
  2903. begin
  2904. NtHeaders := PeMapImgNtHeaders32(Pointer(Handle));
  2905. if NtHeaders = nil then
  2906. FStatus := stNotPE
  2907. else
  2908. begin
  2909. FStatus := stOk;
  2910. FAttachedImage := True;
  2911. FFileName := GetModulePath(Handle);
  2912. // OF: possible loss of data
  2913. FLoadedImage.ModuleName := PAnsiChar(AnsiString(FFileName));
  2914. FLoadedImage.hFile := INVALID_HANDLE_VALUE;
  2915. FLoadedImage.MappedAddress := Pointer(Handle);
  2916. FLoadedImage.FileHeader := PImageNtHeaders(NtHeaders);
  2917. FLoadedImage.NumberOfSections := NtHeaders^.FileHeader.NumberOfSections;
  2918. FLoadedImage.Sections := PeMapImgSections32(NtHeaders);
  2919. FLoadedImage.LastRvaSection := FLoadedImage.Sections;
  2920. FLoadedImage.Characteristics := NtHeaders^.FileHeader.Characteristics;
  2921. FLoadedImage.fSystemImage := (FLoadedImage.Characteristics and IMAGE_FILE_SYSTEM <> 0);
  2922. FLoadedImage.fDOSImage := False;
  2923. FLoadedImage.SizeOfImage := NtHeaders^.OptionalHeader.SizeOfImage;
  2924. ReadImageSections;
  2925. ReadStringTable;
  2926. AfterOpen;
  2927. end;
  2928. RaiseStatusException;
  2929. end;
  2930. procedure AttachLoadedModule64;
  2931. var
  2932. NtHeaders: PImageNtHeaders64;
  2933. begin
  2934. NtHeaders := PeMapImgNtHeaders64(Pointer(Handle));
  2935. if NtHeaders = nil then
  2936. FStatus := stNotPE
  2937. else
  2938. begin
  2939. FStatus := stOk;
  2940. FAttachedImage := True;
  2941. FFileName := GetModulePath(Handle);
  2942. // OF: possible loss of data
  2943. FLoadedImage.ModuleName := PAnsiChar(AnsiString(FFileName));
  2944. FLoadedImage.hFile := INVALID_HANDLE_VALUE;
  2945. FLoadedImage.MappedAddress := Pointer(Handle);
  2946. FLoadedImage.FileHeader := PImageNtHeaders(NtHeaders);
  2947. FLoadedImage.NumberOfSections := NtHeaders^.FileHeader.NumberOfSections;
  2948. FLoadedImage.Sections := PeMapImgSections64(NtHeaders);
  2949. FLoadedImage.LastRvaSection := FLoadedImage.Sections;
  2950. FLoadedImage.Characteristics := NtHeaders^.FileHeader.Characteristics;
  2951. FLoadedImage.fSystemImage := (FLoadedImage.Characteristics and IMAGE_FILE_SYSTEM <> 0);
  2952. FLoadedImage.fDOSImage := False;
  2953. FLoadedImage.SizeOfImage := NtHeaders^.OptionalHeader.SizeOfImage;
  2954. ReadImageSections;
  2955. ReadStringTable;
  2956. AfterOpen;
  2957. end;
  2958. RaiseStatusException;
  2959. end;
  2960. begin
  2961. Clear;
  2962. if Handle = 0 then
  2963. Exit;
  2964. FTarget := PeMapImgTarget(Pointer(Handle));
  2965. case Target of
  2966. taWin32:
  2967. AttachLoadedModule32;
  2968. taWin64:
  2969. AttachLoadedModule64;
  2970. taUnknown:
  2971. FStatus := stNotSupported;
  2972. end;
  2973. end;
  2974. function TJclPeImage.CalculateCheckSum: DWORD;
  2975. var
  2976. C: DWORD;
  2977. begin
  2978. if StatusOK then
  2979. begin
  2980. CheckNotAttached;
  2981. if CheckSumMappedFile(FLoadedImage.MappedAddress, FLoadedImage.SizeOfImage,
  2982. C, Result) = nil then
  2983. RaiseLastOSError;
  2984. end
  2985. else
  2986. Result := 0;
  2987. end;
  2988. procedure TJclPeImage.CheckNotAttached;
  2989. begin
  2990. if FAttachedImage then
  2991. raise EJclPeImageError.CreateRes(@RsPeNotAvailableForAttached);
  2992. end;
  2993. procedure TJclPeImage.Clear;
  2994. begin
  2995. FImageSections.Clear;
  2996. FStringTable.Clear;
  2997. FreeAndNil(FCertificateList);
  2998. FreeAndNil(FCLRHeader);
  2999. FreeAndNil(FDebugList);
  3000. FreeAndNil(FImportList);
  3001. FreeAndNil(FExportList);
  3002. FreeAndNil(FRelocationList);
  3003. FreeAndNil(FResourceList);
  3004. FreeAndNil(FVersionInfo);
  3005. if not FAttachedImage and StatusOK then
  3006. UnMapAndLoad(FLoadedImage);
  3007. ResetMemory(FLoadedImage, SizeOf(FLoadedImage));
  3008. FStatus := stNotLoaded;
  3009. FAttachedImage := False;
  3010. end;
  3011. class function TJclPeImage.DateTimeToStamp(const DateTime: TDateTime): DWORD;
  3012. begin
  3013. Result := Round((DateTime - UnixTimeStart) * SecsPerDay);
  3014. end;
  3015. class function TJclPeImage.DebugTypeNames(DebugType: DWORD): string;
  3016. begin
  3017. case DebugType of
  3018. IMAGE_DEBUG_TYPE_UNKNOWN:
  3019. Result := LoadResString(@RsPeDEBUG_UNKNOWN);
  3020. IMAGE_DEBUG_TYPE_COFF:
  3021. Result := LoadResString(@RsPeDEBUG_COFF);
  3022. IMAGE_DEBUG_TYPE_CODEVIEW:
  3023. Result := LoadResString(@RsPeDEBUG_CODEVIEW);
  3024. IMAGE_DEBUG_TYPE_FPO:
  3025. Result := LoadResString(@RsPeDEBUG_FPO);
  3026. IMAGE_DEBUG_TYPE_MISC:
  3027. Result := LoadResString(@RsPeDEBUG_MISC);
  3028. IMAGE_DEBUG_TYPE_EXCEPTION:
  3029. Result := LoadResString(@RsPeDEBUG_EXCEPTION);
  3030. IMAGE_DEBUG_TYPE_FIXUP:
  3031. Result := LoadResString(@RsPeDEBUG_FIXUP);
  3032. IMAGE_DEBUG_TYPE_OMAP_TO_SRC:
  3033. Result := LoadResString(@RsPeDEBUG_OMAP_TO_SRC);
  3034. IMAGE_DEBUG_TYPE_OMAP_FROM_SRC:
  3035. Result := LoadResString(@RsPeDEBUG_OMAP_FROM_SRC);
  3036. else
  3037. Result := LoadResString(@RsPeDEBUG_UNKNOWN);
  3038. end;
  3039. end;
  3040. function TJclPeImage.DirectoryEntryToData(Directory: Word): Pointer;
  3041. var
  3042. Size: DWORD;
  3043. begin
  3044. Size := 0;
  3045. Result := ImageDirectoryEntryToData(FLoadedImage.MappedAddress, FAttachedImage, Directory, Size);
  3046. end;
  3047. class function TJclPeImage.DirectoryNames(Directory: Word): string;
  3048. begin
  3049. case Directory of
  3050. IMAGE_DIRECTORY_ENTRY_EXPORT:
  3051. Result := LoadResString(@RsPeImg_00);
  3052. IMAGE_DIRECTORY_ENTRY_IMPORT:
  3053. Result := LoadResString(@RsPeImg_01);
  3054. IMAGE_DIRECTORY_ENTRY_RESOURCE:
  3055. Result := LoadResString(@RsPeImg_02);
  3056. IMAGE_DIRECTORY_ENTRY_EXCEPTION:
  3057. Result := LoadResString(@RsPeImg_03);
  3058. IMAGE_DIRECTORY_ENTRY_SECURITY:
  3059. Result := LoadResString(@RsPeImg_04);
  3060. IMAGE_DIRECTORY_ENTRY_BASERELOC:
  3061. Result := LoadResString(@RsPeImg_05);
  3062. IMAGE_DIRECTORY_ENTRY_DEBUG:
  3063. Result := LoadResString(@RsPeImg_06);
  3064. IMAGE_DIRECTORY_ENTRY_COPYRIGHT:
  3065. Result := LoadResString(@RsPeImg_07);
  3066. IMAGE_DIRECTORY_ENTRY_GLOBALPTR:
  3067. Result := LoadResString(@RsPeImg_08);
  3068. IMAGE_DIRECTORY_ENTRY_TLS:
  3069. Result := LoadResString(@RsPeImg_09);
  3070. IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG:
  3071. Result := LoadResString(@RsPeImg_10);
  3072. IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT:
  3073. Result := LoadResString(@RsPeImg_11);
  3074. IMAGE_DIRECTORY_ENTRY_IAT:
  3075. Result := LoadResString(@RsPeImg_12);
  3076. IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT:
  3077. Result := LoadResString(@RsPeImg_13);
  3078. IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR:
  3079. Result := LoadResString(@RsPeImg_14);
  3080. else
  3081. Result := Format(LoadResString(@RsPeImg_Reserved), [Directory]);
  3082. end;
  3083. end;
  3084. class function TJclPeImage.ExpandBySearchPath(const ModuleName, BasePath: string): TFileName;
  3085. var
  3086. FullName: array [0..MAX_PATH] of Char;
  3087. FilePart: PChar;
  3088. begin
  3089. Result := PathAddSeparator(ExtractFilePath(BasePath)) + ModuleName;
  3090. if FileExists(Result) then
  3091. Exit;
  3092. FilePart := nil;
  3093. if SearchPath(nil, PChar(ModuleName), nil, Length(FullName), FullName, FilePart) = 0 then
  3094. Result := ModuleName
  3095. else
  3096. Result := FullName;
  3097. end;
  3098. function TJclPeImage.ExpandModuleName(const ModuleName: string): TFileName;
  3099. begin
  3100. Result := ExpandBySearchPath(ModuleName, ExtractFilePath(FFileName));
  3101. end;
  3102. function TJclPeImage.GetCertificateList: TJclPeCertificateList;
  3103. begin
  3104. if FCertificateList = nil then
  3105. FCertificateList := TJclPeCertificateList.Create(Self);
  3106. Result := FCertificateList;
  3107. end;
  3108. function TJclPeImage.GetCLRHeader: TJclPeCLRHeader;
  3109. begin
  3110. if FCLRHeader = nil then
  3111. FCLRHeader := TJclPeCLRHeader.Create(Self);
  3112. Result := FCLRHeader;
  3113. end;
  3114. function TJclPeImage.GetDebugList: TJclPeDebugList;
  3115. begin
  3116. if FDebugList = nil then
  3117. FDebugList := TJclPeDebugList.Create(Self);
  3118. Result := FDebugList;
  3119. end;
  3120. function TJclPeImage.GetDescription: string;
  3121. var
  3122. UTF8DescriptionName: TUTF8String;
  3123. begin
  3124. if DirectoryExists[IMAGE_DIRECTORY_ENTRY_COPYRIGHT] then
  3125. begin
  3126. UTF8DescriptionName := PAnsiChar(DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_COPYRIGHT));
  3127. if not TryUTF8ToString(UTF8DescriptionName, Result) then
  3128. Result := string(UTF8DescriptionName);
  3129. end
  3130. else
  3131. Result := '';
  3132. end;
  3133. function TJclPeImage.GetDirectories(Directory: Word): TImageDataDirectory;
  3134. begin
  3135. if StatusOK then
  3136. begin
  3137. case Target of
  3138. taWin32:
  3139. Result := PImageNtHeaders32(FLoadedImage.FileHeader)^.OptionalHeader.DataDirectory[Directory];
  3140. taWin64:
  3141. Result := PImageNtHeaders64(FLoadedImage.FileHeader)^.OptionalHeader.DataDirectory[Directory];
  3142. else
  3143. Result.VirtualAddress := 0;
  3144. Result.Size := 0;
  3145. end
  3146. end
  3147. else
  3148. begin
  3149. Result.VirtualAddress := 0;
  3150. Result.Size := 0;
  3151. end;
  3152. end;
  3153. function TJclPeImage.GetDirectoryExists(Directory: Word): Boolean;
  3154. begin
  3155. Result := (Directories[Directory].VirtualAddress <> 0);
  3156. end;
  3157. function TJclPeImage.GetExportList: TJclPeExportFuncList;
  3158. begin
  3159. if FExportList = nil then
  3160. FExportList := TJclPeExportFuncList.Create(Self);
  3161. Result := FExportList;
  3162. end;
  3163. {$IFNDEF WINSCP}
  3164. function TJclPeImage.GetFileProperties: TJclPeFileProperties;
  3165. var
  3166. FileAttributesEx: WIN32_FILE_ATTRIBUTE_DATA;
  3167. Size: TJclULargeInteger;
  3168. begin
  3169. ResetMemory(Result, SizeOf(Result));
  3170. if GetFileAttributesEx(PChar(FileName), GetFileExInfoStandard, @FileAttributesEx) then
  3171. begin
  3172. Size.LowPart := FileAttributesEx.nFileSizeLow;
  3173. Size.HighPart := FileAttributesEx.nFileSizeHigh;
  3174. Result.Size := Size.QuadPart;
  3175. Result.CreationTime := FileTimeToLocalDateTime(FileAttributesEx.ftCreationTime);
  3176. Result.LastAccessTime := FileTimeToLocalDateTime(FileAttributesEx.ftLastAccessTime);
  3177. Result.LastWriteTime := FileTimeToLocalDateTime(FileAttributesEx.ftLastWriteTime);
  3178. Result.Attributes := FileAttributesEx.dwFileAttributes;
  3179. end;
  3180. end;
  3181. {$ENDIF ~WINSCP}
  3182. function TJclPeImage.GetHeaderValues(Index: TJclPeHeader): string;
  3183. function GetMachineString(Value: DWORD): string;
  3184. begin
  3185. case Value of
  3186. IMAGE_FILE_MACHINE_UNKNOWN:
  3187. Result := LoadResString(@RsPeMACHINE_UNKNOWN);
  3188. IMAGE_FILE_MACHINE_I386:
  3189. Result := LoadResString(@RsPeMACHINE_I386);
  3190. IMAGE_FILE_MACHINE_R3000:
  3191. Result := LoadResString(@RsPeMACHINE_R3000);
  3192. IMAGE_FILE_MACHINE_R4000:
  3193. Result := LoadResString(@RsPeMACHINE_R4000);
  3194. IMAGE_FILE_MACHINE_R10000:
  3195. Result := LoadResString(@RsPeMACHINE_R10000);
  3196. IMAGE_FILE_MACHINE_WCEMIPSV2:
  3197. Result := LoadResString(@RsPeMACHINE_WCEMIPSV2);
  3198. IMAGE_FILE_MACHINE_ALPHA:
  3199. Result := LoadResString(@RsPeMACHINE_ALPHA);
  3200. IMAGE_FILE_MACHINE_SH3:
  3201. Result := LoadResString(@RsPeMACHINE_SH3); // SH3 little-endian
  3202. IMAGE_FILE_MACHINE_SH3DSP:
  3203. Result := LoadResString(@RsPeMACHINE_SH3DSP);
  3204. IMAGE_FILE_MACHINE_SH3E:
  3205. Result := LoadResString(@RsPeMACHINE_SH3E); // SH3E little-endian
  3206. IMAGE_FILE_MACHINE_SH4:
  3207. Result := LoadResString(@RsPeMACHINE_SH4); // SH4 little-endian
  3208. IMAGE_FILE_MACHINE_SH5:
  3209. Result := LoadResString(@RsPeMACHINE_SH5); // SH5
  3210. IMAGE_FILE_MACHINE_ARM:
  3211. Result := LoadResString(@RsPeMACHINE_ARM); // ARM Little-Endian
  3212. IMAGE_FILE_MACHINE_THUMB:
  3213. Result := LoadResString(@RsPeMACHINE_THUMB);
  3214. IMAGE_FILE_MACHINE_AM33:
  3215. Result := LoadResString(@RsPeMACHINE_AM33);
  3216. IMAGE_FILE_MACHINE_POWERPC:
  3217. Result := LoadResString(@RsPeMACHINE_POWERPC);
  3218. IMAGE_FILE_MACHINE_POWERPCFP:
  3219. Result := LoadResString(@RsPeMACHINE_POWERPCFP);
  3220. IMAGE_FILE_MACHINE_IA64:
  3221. Result := LoadResString(@RsPeMACHINE_IA64); // Intel 64
  3222. IMAGE_FILE_MACHINE_MIPS16:
  3223. Result := LoadResString(@RsPeMACHINE_MIPS16); // MIPS
  3224. IMAGE_FILE_MACHINE_ALPHA64:
  3225. Result := LoadResString(@RsPeMACHINE_AMPHA64); // ALPHA64
  3226. //IMAGE_FILE_MACHINE_AXP64
  3227. IMAGE_FILE_MACHINE_MIPSFPU:
  3228. Result := LoadResString(@RsPeMACHINE_MIPSFPU); // MIPS
  3229. IMAGE_FILE_MACHINE_MIPSFPU16:
  3230. Result := LoadResString(@RsPeMACHINE_MIPSFPU16); // MIPS
  3231. IMAGE_FILE_MACHINE_TRICORE:
  3232. Result := LoadResString(@RsPeMACHINE_TRICORE); // Infineon
  3233. IMAGE_FILE_MACHINE_CEF:
  3234. Result := LoadResString(@RsPeMACHINE_CEF);
  3235. IMAGE_FILE_MACHINE_EBC:
  3236. Result := LoadResString(@RsPeMACHINE_EBC); // EFI Byte Code
  3237. IMAGE_FILE_MACHINE_AMD64:
  3238. Result := LoadResString(@RsPeMACHINE_AMD64); // AMD64 (K8)
  3239. IMAGE_FILE_MACHINE_M32R:
  3240. Result := LoadResString(@RsPeMACHINE_M32R); // M32R little-endian
  3241. IMAGE_FILE_MACHINE_CEE:
  3242. Result := LoadResString(@RsPeMACHINE_CEE);
  3243. else
  3244. Result := Format('[%.8x]', [Value]);
  3245. end;
  3246. end;
  3247. function GetSubsystemString(Value: DWORD): string;
  3248. begin
  3249. case Value of
  3250. IMAGE_SUBSYSTEM_UNKNOWN:
  3251. Result := LoadResString(@RsPeSUBSYSTEM_UNKNOWN);
  3252. IMAGE_SUBSYSTEM_NATIVE:
  3253. Result := LoadResString(@RsPeSUBSYSTEM_NATIVE);
  3254. IMAGE_SUBSYSTEM_WINDOWS_GUI:
  3255. Result := LoadResString(@RsPeSUBSYSTEM_WINDOWS_GUI);
  3256. IMAGE_SUBSYSTEM_WINDOWS_CUI:
  3257. Result := LoadResString(@RsPeSUBSYSTEM_WINDOWS_CUI);
  3258. IMAGE_SUBSYSTEM_OS2_CUI:
  3259. Result := LoadResString(@RsPeSUBSYSTEM_OS2_CUI);
  3260. IMAGE_SUBSYSTEM_POSIX_CUI:
  3261. Result := LoadResString(@RsPeSUBSYSTEM_POSIX_CUI);
  3262. IMAGE_SUBSYSTEM_RESERVED8:
  3263. Result := LoadResString(@RsPeSUBSYSTEM_RESERVED8);
  3264. else
  3265. Result := Format('[%.8x]', [Value]);
  3266. end;
  3267. end;
  3268. function GetHeaderValues32(Index: TJclPeHeader): string;
  3269. var
  3270. OptionalHeader: TImageOptionalHeader32;
  3271. begin
  3272. OptionalHeader := OptionalHeader32;
  3273. case Index of
  3274. JclPeHeader_Magic:
  3275. Result := IntToHex(OptionalHeader.Magic, 4);
  3276. JclPeHeader_LinkerVersion:
  3277. Result := FormatVersionString(OptionalHeader.MajorLinkerVersion, OptionalHeader.MinorLinkerVersion);
  3278. JclPeHeader_SizeOfCode:
  3279. Result := IntToHex(OptionalHeader.SizeOfCode, 8);
  3280. JclPeHeader_SizeOfInitializedData:
  3281. Result := IntToHex(OptionalHeader.SizeOfInitializedData, 8);
  3282. JclPeHeader_SizeOfUninitializedData:
  3283. Result := IntToHex(OptionalHeader.SizeOfUninitializedData, 8);
  3284. JclPeHeader_AddressOfEntryPoint:
  3285. Result := IntToHex(OptionalHeader.AddressOfEntryPoint, 8);
  3286. JclPeHeader_BaseOfCode:
  3287. Result := IntToHex(OptionalHeader.BaseOfCode, 8);
  3288. JclPeHeader_BaseOfData:
  3289. {$IFDEF DELPHI64_TEMPORARY}
  3290. System.Error(rePlatformNotImplemented);
  3291. {$ELSE ~DELPHI64_TEMPORARY}
  3292. Result := IntToHex(OptionalHeader.BaseOfData, 8);
  3293. {$ENDIF ~DELPHI64_TEMPORARY}
  3294. JclPeHeader_ImageBase:
  3295. Result := IntToHex(OptionalHeader.ImageBase, 8);
  3296. JclPeHeader_SectionAlignment:
  3297. Result := IntToHex(OptionalHeader.SectionAlignment, 8);
  3298. JclPeHeader_FileAlignment:
  3299. Result := IntToHex(OptionalHeader.FileAlignment, 8);
  3300. JclPeHeader_OperatingSystemVersion:
  3301. Result := FormatVersionString(OptionalHeader.MajorOperatingSystemVersion, OptionalHeader.MinorOperatingSystemVersion);
  3302. JclPeHeader_ImageVersion:
  3303. Result := FormatVersionString(OptionalHeader.MajorImageVersion, OptionalHeader.MinorImageVersion);
  3304. JclPeHeader_SubsystemVersion:
  3305. Result := FormatVersionString(OptionalHeader.MajorSubsystemVersion, OptionalHeader.MinorSubsystemVersion);
  3306. JclPeHeader_Win32VersionValue:
  3307. Result := IntToHex(OptionalHeader.Win32VersionValue, 8);
  3308. JclPeHeader_SizeOfImage:
  3309. Result := IntToHex(OptionalHeader.SizeOfImage, 8);
  3310. JclPeHeader_SizeOfHeaders:
  3311. Result := IntToHex(OptionalHeader.SizeOfHeaders, 8);
  3312. JclPeHeader_CheckSum:
  3313. Result := IntToHex(OptionalHeader.CheckSum, 8);
  3314. JclPeHeader_Subsystem:
  3315. Result := GetSubsystemString(OptionalHeader.Subsystem);
  3316. JclPeHeader_DllCharacteristics:
  3317. Result := IntToHex(OptionalHeader.DllCharacteristics, 4);
  3318. JclPeHeader_SizeOfStackReserve:
  3319. Result := IntToHex(OptionalHeader.SizeOfStackReserve, 8);
  3320. JclPeHeader_SizeOfStackCommit:
  3321. Result := IntToHex(OptionalHeader.SizeOfStackCommit, 8);
  3322. JclPeHeader_SizeOfHeapReserve:
  3323. Result := IntToHex(OptionalHeader.SizeOfHeapReserve, 8);
  3324. JclPeHeader_SizeOfHeapCommit:
  3325. Result := IntToHex(OptionalHeader.SizeOfHeapCommit, 8);
  3326. JclPeHeader_LoaderFlags:
  3327. Result := IntToHex(OptionalHeader.LoaderFlags, 8);
  3328. JclPeHeader_NumberOfRvaAndSizes:
  3329. Result := IntToHex(OptionalHeader.NumberOfRvaAndSizes, 8);
  3330. end;
  3331. end;
  3332. function GetHeaderValues64(Index: TJclPeHeader): string;
  3333. var
  3334. OptionalHeader: TImageOptionalHeader64;
  3335. begin
  3336. OptionalHeader := OptionalHeader64;
  3337. case Index of
  3338. JclPeHeader_Magic:
  3339. Result := IntToHex(OptionalHeader.Magic, 4);
  3340. JclPeHeader_LinkerVersion:
  3341. Result := FormatVersionString(OptionalHeader.MajorLinkerVersion, OptionalHeader.MinorLinkerVersion);
  3342. JclPeHeader_SizeOfCode:
  3343. Result := IntToHex(OptionalHeader.SizeOfCode, 8);
  3344. JclPeHeader_SizeOfInitializedData:
  3345. Result := IntToHex(OptionalHeader.SizeOfInitializedData, 8);
  3346. JclPeHeader_SizeOfUninitializedData:
  3347. Result := IntToHex(OptionalHeader.SizeOfUninitializedData, 8);
  3348. JclPeHeader_AddressOfEntryPoint:
  3349. Result := IntToHex(OptionalHeader.AddressOfEntryPoint, 8);
  3350. JclPeHeader_BaseOfCode:
  3351. Result := IntToHex(OptionalHeader.BaseOfCode, 8);
  3352. JclPeHeader_BaseOfData:
  3353. Result := ''; // IntToHex(OptionalHeader.BaseOfData, 8);
  3354. JclPeHeader_ImageBase:
  3355. Result := IntToHex(OptionalHeader.ImageBase, 16);
  3356. JclPeHeader_SectionAlignment:
  3357. Result := IntToHex(OptionalHeader.SectionAlignment, 8);
  3358. JclPeHeader_FileAlignment:
  3359. Result := IntToHex(OptionalHeader.FileAlignment, 8);
  3360. JclPeHeader_OperatingSystemVersion:
  3361. Result := FormatVersionString(OptionalHeader.MajorOperatingSystemVersion, OptionalHeader.MinorOperatingSystemVersion);
  3362. JclPeHeader_ImageVersion:
  3363. Result := FormatVersionString(OptionalHeader.MajorImageVersion, OptionalHeader.MinorImageVersion);
  3364. JclPeHeader_SubsystemVersion:
  3365. Result := FormatVersionString(OptionalHeader.MajorSubsystemVersion, OptionalHeader.MinorSubsystemVersion);
  3366. JclPeHeader_Win32VersionValue:
  3367. Result := IntToHex(OptionalHeader.Win32VersionValue, 8);
  3368. JclPeHeader_SizeOfImage:
  3369. Result := IntToHex(OptionalHeader.SizeOfImage, 8);
  3370. JclPeHeader_SizeOfHeaders:
  3371. Result := IntToHex(OptionalHeader.SizeOfHeaders, 8);
  3372. JclPeHeader_CheckSum:
  3373. Result := IntToHex(OptionalHeader.CheckSum, 8);
  3374. JclPeHeader_Subsystem:
  3375. Result := GetSubsystemString(OptionalHeader.Subsystem);
  3376. JclPeHeader_DllCharacteristics:
  3377. Result := IntToHex(OptionalHeader.DllCharacteristics, 4);
  3378. JclPeHeader_SizeOfStackReserve:
  3379. Result := IntToHex(OptionalHeader.SizeOfStackReserve, 16);
  3380. JclPeHeader_SizeOfStackCommit:
  3381. Result := IntToHex(OptionalHeader.SizeOfStackCommit, 16);
  3382. JclPeHeader_SizeOfHeapReserve:
  3383. Result := IntToHex(OptionalHeader.SizeOfHeapReserve, 16);
  3384. JclPeHeader_SizeOfHeapCommit:
  3385. Result := IntToHex(OptionalHeader.SizeOfHeapCommit, 16);
  3386. JclPeHeader_LoaderFlags:
  3387. Result := IntToHex(OptionalHeader.LoaderFlags, 8);
  3388. JclPeHeader_NumberOfRvaAndSizes:
  3389. Result := IntToHex(OptionalHeader.NumberOfRvaAndSizes, 8);
  3390. end;
  3391. end;
  3392. begin
  3393. if StatusOK then
  3394. with FLoadedImage.FileHeader^ do
  3395. case Index of
  3396. JclPeHeader_Signature:
  3397. Result := IntToHex(Signature, 8);
  3398. JclPeHeader_Machine:
  3399. Result := GetMachineString(FileHeader.Machine);
  3400. JclPeHeader_NumberOfSections:
  3401. Result := IntToHex(FileHeader.NumberOfSections, 4);
  3402. JclPeHeader_TimeDateStamp:
  3403. Result := IntToHex(FileHeader.TimeDateStamp, 8);
  3404. JclPeHeader_PointerToSymbolTable:
  3405. Result := IntToHex(FileHeader.PointerToSymbolTable, 8);
  3406. JclPeHeader_NumberOfSymbols:
  3407. Result := IntToHex(FileHeader.NumberOfSymbols, 8);
  3408. JclPeHeader_SizeOfOptionalHeader:
  3409. Result := IntToHex(FileHeader.SizeOfOptionalHeader, 4);
  3410. JclPeHeader_Characteristics:
  3411. Result := IntToHex(FileHeader.Characteristics, 4);
  3412. JclPeHeader_Magic..JclPeHeader_NumberOfRvaAndSizes:
  3413. case Target of
  3414. taWin32:
  3415. Result := GetHeaderValues32(Index);
  3416. taWin64:
  3417. Result := GetHeaderValues64(Index);
  3418. //taUnknown:
  3419. else
  3420. Result := '';
  3421. end;
  3422. else
  3423. Result := '';
  3424. end
  3425. else
  3426. Result := '';
  3427. end;
  3428. function TJclPeImage.GetImageSectionCount: Integer;
  3429. begin
  3430. Result := FImageSections.Count;
  3431. end;
  3432. function TJclPeImage.GetImageSectionFullNames(Index: Integer): string;
  3433. var
  3434. Offset: Integer;
  3435. begin
  3436. Result := ImageSectionNames[Index];
  3437. if (Length(Result) > 0) and (Result[1] = '/') and TryStrToInt(Copy(Result, 2, MaxInt), Offset) then
  3438. Result := GetNameInStringTable(Offset);
  3439. end;
  3440. function TJclPeImage.GetImageSectionHeaders(Index: Integer): TImageSectionHeader;
  3441. begin
  3442. Result := PImageSectionHeader(FImageSections.Objects[Index])^;
  3443. end;
  3444. function TJclPeImage.GetImageSectionNameFromRva(const Rva: DWORD): string;
  3445. begin
  3446. Result := GetSectionName(RvaToSection(Rva));
  3447. end;
  3448. function TJclPeImage.GetImageSectionNames(Index: Integer): string;
  3449. begin
  3450. Result := FImageSections[Index];
  3451. end;
  3452. function TJclPeImage.GetImportList: TJclPeImportList;
  3453. begin
  3454. if FImportList = nil then
  3455. FImportList := TJclPeImportList.Create(Self);
  3456. Result := FImportList;
  3457. end;
  3458. function TJclPeImage.GetLoadConfigValues(Index: TJclLoadConfig): string;
  3459. function GetLoadConfigValues32(Index: TJclLoadConfig): string;
  3460. var
  3461. LoadConfig: PIMAGE_LOAD_CONFIG_DIRECTORY32;
  3462. begin
  3463. LoadConfig := DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG);
  3464. if LoadConfig <> nil then
  3465. with LoadConfig^ do
  3466. case Index of
  3467. JclLoadConfig_Characteristics:
  3468. Result := IntToHex(Size, 8);
  3469. JclLoadConfig_TimeDateStamp:
  3470. Result := IntToHex(TimeDateStamp, 8);
  3471. JclLoadConfig_Version:
  3472. Result := FormatVersionString(MajorVersion, MinorVersion);
  3473. JclLoadConfig_GlobalFlagsClear:
  3474. Result := IntToHex(GlobalFlagsClear, 8);
  3475. JclLoadConfig_GlobalFlagsSet:
  3476. Result := IntToHex(GlobalFlagsSet, 8);
  3477. JclLoadConfig_CriticalSectionDefaultTimeout:
  3478. Result := IntToHex(CriticalSectionDefaultTimeout, 8);
  3479. JclLoadConfig_DeCommitFreeBlockThreshold:
  3480. Result := IntToHex(DeCommitFreeBlockThreshold, 8);
  3481. JclLoadConfig_DeCommitTotalFreeThreshold:
  3482. Result := IntToHex(DeCommitTotalFreeThreshold, 8);
  3483. JclLoadConfig_LockPrefixTable:
  3484. Result := IntToHex(LockPrefixTable, 8);
  3485. JclLoadConfig_MaximumAllocationSize:
  3486. Result := IntToHex(MaximumAllocationSize, 8);
  3487. JclLoadConfig_VirtualMemoryThreshold:
  3488. Result := IntToHex(VirtualMemoryThreshold, 8);
  3489. JclLoadConfig_ProcessHeapFlags:
  3490. Result := IntToHex(ProcessHeapFlags, 8);
  3491. JclLoadConfig_ProcessAffinityMask:
  3492. Result := IntToHex(ProcessAffinityMask, 8);
  3493. JclLoadConfig_CSDVersion:
  3494. Result := IntToHex(CSDVersion, 4);
  3495. JclLoadConfig_Reserved1:
  3496. Result := IntToHex(Reserved1, 4);
  3497. JclLoadConfig_EditList:
  3498. Result := IntToHex(EditList, 8);
  3499. JclLoadConfig_Reserved:
  3500. Result := LoadResString(@RsPeReserved);
  3501. end;
  3502. end;
  3503. function GetLoadConfigValues64(Index: TJclLoadConfig): string;
  3504. var
  3505. LoadConfig: PIMAGE_LOAD_CONFIG_DIRECTORY64;
  3506. begin
  3507. LoadConfig := DirectoryEntryToData(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG);
  3508. if LoadConfig <> nil then
  3509. with LoadConfig^ do
  3510. case Index of
  3511. JclLoadConfig_Characteristics:
  3512. Result := IntToHex(Size, 8);
  3513. JclLoadConfig_TimeDateStamp:
  3514. Result := IntToHex(TimeDateStamp, 8);
  3515. JclLoadConfig_Version:
  3516. Result := FormatVersionString(MajorVersion, MinorVersion);
  3517. JclLoadConfig_GlobalFlagsClear:
  3518. Result := IntToHex(GlobalFlagsClear, 8);
  3519. JclLoadConfig_GlobalFlagsSet:
  3520. Result := IntToHex(GlobalFlagsSet, 8);
  3521. JclLoadConfig_CriticalSectionDefaultTimeout:
  3522. Result := IntToHex(CriticalSectionDefaultTimeout, 8);
  3523. JclLoadConfig_DeCommitFreeBlockThreshold:
  3524. Result := IntToHex(DeCommitFreeBlockThreshold, 16);
  3525. JclLoadConfig_DeCommitTotalFreeThreshold:
  3526. Result := IntToHex(DeCommitTotalFreeThreshold, 16);
  3527. JclLoadConfig_LockPrefixTable:
  3528. Result := IntToHex(LockPrefixTable, 16);
  3529. JclLoadConfig_MaximumAllocationSize:
  3530. Result := IntToHex(MaximumAllocationSize, 16);
  3531. JclLoadConfig_VirtualMemoryThreshold:
  3532. Result := IntToHex(VirtualMemoryThreshold, 16);
  3533. JclLoadConfig_ProcessHeapFlags:
  3534. Result := IntToHex(ProcessHeapFlags, 8);
  3535. JclLoadConfig_ProcessAffinityMask:
  3536. Result := IntToHex(ProcessAffinityMask, 16);
  3537. JclLoadConfig_CSDVersion:
  3538. Result := IntToHex(CSDVersion, 4);
  3539. JclLoadConfig_Reserved1:
  3540. Result := IntToHex(Reserved1, 4);
  3541. JclLoadConfig_EditList:
  3542. Result := IntToHex(EditList, 16);
  3543. JclLoadConfig_Reserved:
  3544. Result := LoadResString(@RsPeReserved);
  3545. end;
  3546. end;
  3547. begin
  3548. Result := '';
  3549. case Target of
  3550. taWin32:
  3551. Result := GetLoadConfigValues32(Index);
  3552. taWin64:
  3553. Result := GetLoadConfigValues64(Index);
  3554. end;
  3555. end;
  3556. function TJclPeImage.GetMappedAddress: TJclAddr;
  3557. begin
  3558. if StatusOK then
  3559. Result := TJclAddr(LoadedImage.MappedAddress)
  3560. else
  3561. Result := 0;
  3562. end;
  3563. function TJclPeImage.GetNameInStringTable(Offset: ULONG): string;
  3564. var
  3565. Index: Integer;
  3566. begin
  3567. Dec(Offset, SizeOf(ULONG));
  3568. Index := 0;
  3569. while (Offset > 0) and (Index < FStringTable.Count) do
  3570. begin
  3571. Dec(Offset, Length(FStringTable[Index]) + 1);
  3572. if Offset > 0 then
  3573. Inc(Index);
  3574. end;
  3575. if Offset = 0 then
  3576. Result := FStringTable[Index]
  3577. else
  3578. Result := '';
  3579. end;
  3580. function TJclPeImage.GetOptionalHeader32: TImageOptionalHeader32;
  3581. begin
  3582. if Target = taWin32 then
  3583. Result := PImageNtHeaders32(FLoadedImage.FileHeader)^.OptionalHeader
  3584. else
  3585. ZeroMemory(@Result, SizeOf(Result));
  3586. end;
  3587. function TJclPeImage.GetOptionalHeader64: TImageOptionalHeader64;
  3588. begin
  3589. if Target = taWin64 then
  3590. Result := PImageNtHeaders64(FLoadedImage.FileHeader)^.OptionalHeader
  3591. else
  3592. ZeroMemory(@Result, SizeOf(Result));
  3593. end;
  3594. function TJclPeImage.GetRelocationList: TJclPeRelocList;
  3595. begin
  3596. if FRelocationList = nil then
  3597. FRelocationList := TJclPeRelocList.Create(Self);
  3598. Result := FRelocationList;
  3599. end;
  3600. function TJclPeImage.GetResourceList: TJclPeRootResourceList;
  3601. begin
  3602. if FResourceList = nil then
  3603. begin
  3604. FResourceVA := Directories[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
  3605. if FResourceVA <> 0 then
  3606. FResourceVA := TJclAddr(RvaToVa(FResourceVA));
  3607. FResourceList := TJclPeRootResourceList.Create(Self, nil, PImageResourceDirectory(FResourceVA));
  3608. end;
  3609. Result := FResourceList;
  3610. end;
  3611. function TJclPeImage.GetSectionHeader(const SectionName: string;
  3612. out Header: PImageSectionHeader): Boolean;
  3613. var
  3614. I: Integer;
  3615. begin
  3616. I := FImageSections.IndexOf(SectionName);
  3617. if I = -1 then
  3618. begin
  3619. Header := nil;
  3620. Result := False;
  3621. end
  3622. else
  3623. begin
  3624. Header := PImageSectionHeader(FImageSections.Objects[I]);
  3625. Result := True;
  3626. end;
  3627. end;
  3628. function TJclPeImage.GetSectionName(Header: PImageSectionHeader): string;
  3629. var
  3630. I: Integer;
  3631. begin
  3632. I := FImageSections.IndexOfObject(TObject(Header));
  3633. if I = -1 then
  3634. Result := ''
  3635. else
  3636. Result := FImageSections[I];
  3637. end;
  3638. function TJclPeImage.GetStringTableCount: Integer;
  3639. begin
  3640. Result := FStringTable.Count;
  3641. end;
  3642. function TJclPeImage.GetStringTableItem(Index: Integer): string;
  3643. begin
  3644. Result := FStringTable[Index];
  3645. end;
  3646. function TJclPeImage.GetUnusedHeaderBytes: TImageDataDirectory;
  3647. begin
  3648. CheckNotAttached;
  3649. Result.Size := 0;
  3650. Result.VirtualAddress := GetImageUnusedHeaderBytes(FLoadedImage, Result.Size);
  3651. if Result.VirtualAddress = 0 then
  3652. RaiseLastOSError;
  3653. end;
  3654. function TJclPeImage.GetVersionInfo: TJclFileVersionInfo;
  3655. var
  3656. VersionInfoResource: TJclPeResourceItem;
  3657. begin
  3658. if (FVersionInfo = nil) and VersionInfoAvailable then
  3659. begin
  3660. VersionInfoResource := ResourceList.FindResource(rtVersion, '1').List[0];
  3661. with VersionInfoResource do
  3662. try
  3663. FVersionInfo := TJclFileVersionInfo.Attach(RawEntryData, RawEntryDataSize);
  3664. except
  3665. FreeAndNil(FVersionInfo);
  3666. end;
  3667. end;
  3668. Result := FVersionInfo;
  3669. end;
  3670. function TJclPeImage.GetVersionInfoAvailable: Boolean;
  3671. begin
  3672. Result := StatusOK and (ResourceList.FindResource(rtVersion, '1') <> nil);
  3673. end;
  3674. class function TJclPeImage.HeaderNames(Index: TJclPeHeader): string;
  3675. begin
  3676. case Index of
  3677. JclPeHeader_Signature:
  3678. Result := LoadResString(@RsPeSignature);
  3679. JclPeHeader_Machine:
  3680. Result := LoadResString(@RsPeMachine);
  3681. JclPeHeader_NumberOfSections:
  3682. Result := LoadResString(@RsPeNumberOfSections);
  3683. JclPeHeader_TimeDateStamp:
  3684. Result := LoadResString(@RsPeTimeDateStamp);
  3685. JclPeHeader_PointerToSymbolTable:
  3686. Result := LoadResString(@RsPePointerToSymbolTable);
  3687. JclPeHeader_NumberOfSymbols:
  3688. Result := LoadResString(@RsPeNumberOfSymbols);
  3689. JclPeHeader_SizeOfOptionalHeader:
  3690. Result := LoadResString(@RsPeSizeOfOptionalHeader);
  3691. JclPeHeader_Characteristics:
  3692. Result := LoadResString(@RsPeCharacteristics);
  3693. JclPeHeader_Magic:
  3694. Result := LoadResString(@RsPeMagic);
  3695. JclPeHeader_LinkerVersion:
  3696. Result := LoadResString(@RsPeLinkerVersion);
  3697. JclPeHeader_SizeOfCode:
  3698. Result := LoadResString(@RsPeSizeOfCode);
  3699. JclPeHeader_SizeOfInitializedData:
  3700. Result := LoadResString(@RsPeSizeOfInitializedData);
  3701. JclPeHeader_SizeOfUninitializedData:
  3702. Result := LoadResString(@RsPeSizeOfUninitializedData);
  3703. JclPeHeader_AddressOfEntryPoint:
  3704. Result := LoadResString(@RsPeAddressOfEntryPoint);
  3705. JclPeHeader_BaseOfCode:
  3706. Result := LoadResString(@RsPeBaseOfCode);
  3707. JclPeHeader_BaseOfData:
  3708. Result := LoadResString(@RsPeBaseOfData);
  3709. JclPeHeader_ImageBase:
  3710. Result := LoadResString(@RsPeImageBase);
  3711. JclPeHeader_SectionAlignment:
  3712. Result := LoadResString(@RsPeSectionAlignment);
  3713. JclPeHeader_FileAlignment:
  3714. Result := LoadResString(@RsPeFileAlignment);
  3715. JclPeHeader_OperatingSystemVersion:
  3716. Result := LoadResString(@RsPeOperatingSystemVersion);
  3717. JclPeHeader_ImageVersion:
  3718. Result := LoadResString(@RsPeImageVersion);
  3719. JclPeHeader_SubsystemVersion:
  3720. Result := LoadResString(@RsPeSubsystemVersion);
  3721. JclPeHeader_Win32VersionValue:
  3722. Result := LoadResString(@RsPeWin32VersionValue);
  3723. JclPeHeader_SizeOfImage:
  3724. Result := LoadResString(@RsPeSizeOfImage);
  3725. JclPeHeader_SizeOfHeaders:
  3726. Result := LoadResString(@RsPeSizeOfHeaders);
  3727. JclPeHeader_CheckSum:
  3728. Result := LoadResString(@RsPeCheckSum);
  3729. JclPeHeader_Subsystem:
  3730. Result := LoadResString(@RsPeSubsystem);
  3731. JclPeHeader_DllCharacteristics:
  3732. Result := LoadResString(@RsPeDllCharacteristics);
  3733. JclPeHeader_SizeOfStackReserve:
  3734. Result := LoadResString(@RsPeSizeOfStackReserve);
  3735. JclPeHeader_SizeOfStackCommit:
  3736. Result := LoadResString(@RsPeSizeOfStackCommit);
  3737. JclPeHeader_SizeOfHeapReserve:
  3738. Result := LoadResString(@RsPeSizeOfHeapReserve);
  3739. JclPeHeader_SizeOfHeapCommit:
  3740. Result := LoadResString(@RsPeSizeOfHeapCommit);
  3741. JclPeHeader_LoaderFlags:
  3742. Result := LoadResString(@RsPeLoaderFlags);
  3743. JclPeHeader_NumberOfRvaAndSizes:
  3744. Result := LoadResString(@RsPeNumberOfRvaAndSizes);
  3745. else
  3746. Result := '';
  3747. end;
  3748. end;
  3749. function TJclPeImage.IsBrokenFormat: Boolean;
  3750. function IsBrokenFormat32: Boolean;
  3751. var
  3752. OptionalHeader: TImageOptionalHeader32;
  3753. begin
  3754. OptionalHeader := OptionalHeader32;
  3755. Result := not ((OptionalHeader.AddressOfEntryPoint = 0) or IsCLR);
  3756. if Result then
  3757. begin
  3758. Result := (ImageSectionCount = 0);
  3759. if not Result then
  3760. with ImageSectionHeaders[0] do
  3761. Result := (VirtualAddress <> OptionalHeader.BaseOfCode) or (SizeOfRawData = 0) or
  3762. (OptionalHeader.AddressOfEntryPoint > VirtualAddress + Misc.VirtualSize) or
  3763. (Characteristics and (IMAGE_SCN_CNT_CODE or IMAGE_SCN_MEM_WRITE) <> IMAGE_SCN_CNT_CODE);
  3764. end;
  3765. end;
  3766. function IsBrokenFormat64: Boolean;
  3767. var
  3768. OptionalHeader: TImageOptionalHeader64;
  3769. begin
  3770. OptionalHeader := OptionalHeader64;
  3771. Result := not ((OptionalHeader.AddressOfEntryPoint = 0) or IsCLR);
  3772. if Result then
  3773. begin
  3774. Result := (ImageSectionCount = 0);
  3775. if not Result then
  3776. with ImageSectionHeaders[0] do
  3777. Result := (VirtualAddress <> OptionalHeader.BaseOfCode) or (SizeOfRawData = 0) or
  3778. (OptionalHeader.AddressOfEntryPoint > VirtualAddress + Misc.VirtualSize) or
  3779. (Characteristics and (IMAGE_SCN_CNT_CODE or IMAGE_SCN_MEM_WRITE) <> IMAGE_SCN_CNT_CODE);
  3780. end;
  3781. end;
  3782. begin
  3783. case Target of
  3784. taWin32:
  3785. Result := IsBrokenFormat32;
  3786. taWin64:
  3787. Result := IsBrokenFormat64;
  3788. //taUnknown:
  3789. else
  3790. Result := False; // don't know how to check it
  3791. end;
  3792. end;
  3793. function TJclPeImage.IsCLR: Boolean;
  3794. begin
  3795. Result := DirectoryExists[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR] and CLRHeader.HasMetadata;
  3796. end;
  3797. function TJclPeImage.IsSystemImage: Boolean;
  3798. begin
  3799. Result := StatusOK and FLoadedImage.fSystemImage;
  3800. end;
  3801. class function TJclPeImage.LoadConfigNames(Index: TJclLoadConfig): string;
  3802. begin
  3803. case Index of
  3804. JclLoadConfig_Characteristics:
  3805. Result := LoadResString(@RsPeCharacteristics);
  3806. JclLoadConfig_TimeDateStamp:
  3807. Result := LoadResString(@RsPeTimeDateStamp);
  3808. JclLoadConfig_Version:
  3809. Result := LoadResString(@RsPeVersion);
  3810. JclLoadConfig_GlobalFlagsClear:
  3811. Result := LoadResString(@RsPeGlobalFlagsClear);
  3812. JclLoadConfig_GlobalFlagsSet:
  3813. Result := LoadResString(@RsPeGlobalFlagsSet);
  3814. JclLoadConfig_CriticalSectionDefaultTimeout:
  3815. Result := LoadResString(@RsPeCriticalSectionDefaultTimeout);
  3816. JclLoadConfig_DeCommitFreeBlockThreshold:
  3817. Result := LoadResString(@RsPeDeCommitFreeBlockThreshold);
  3818. JclLoadConfig_DeCommitTotalFreeThreshold:
  3819. Result := LoadResString(@RsPeDeCommitTotalFreeThreshold);
  3820. JclLoadConfig_LockPrefixTable:
  3821. Result := LoadResString(@RsPeLockPrefixTable);
  3822. JclLoadConfig_MaximumAllocationSize:
  3823. Result := LoadResString(@RsPeMaximumAllocationSize);
  3824. JclLoadConfig_VirtualMemoryThreshold:
  3825. Result := LoadResString(@RsPeVirtualMemoryThreshold);
  3826. JclLoadConfig_ProcessHeapFlags:
  3827. Result := LoadResString(@RsPeProcessHeapFlags);
  3828. JclLoadConfig_ProcessAffinityMask:
  3829. Result := LoadResString(@RsPeProcessAffinityMask);
  3830. JclLoadConfig_CSDVersion:
  3831. Result := LoadResString(@RsPeCSDVersion);
  3832. JclLoadConfig_Reserved1:
  3833. Result := LoadResString(@RsPeReserved);
  3834. JclLoadConfig_EditList:
  3835. Result := LoadResString(@RsPeEditList);
  3836. JclLoadConfig_Reserved:
  3837. Result := LoadResString(@RsPeReserved);
  3838. else
  3839. Result := '';
  3840. end;
  3841. end;
  3842. procedure TJclPeImage.RaiseStatusException;
  3843. begin
  3844. if not FNoExceptions then
  3845. case FStatus of
  3846. stNotPE:
  3847. raise EJclPeImageError.CreateRes(@RsPeNotPE);
  3848. stNotFound:
  3849. raise EJclPeImageError.CreateResFmt(@RsPeCantOpen, [FFileName]);
  3850. stNotSupported:
  3851. raise EJclPeImageError.CreateRes(@RsPeUnknownTarget);
  3852. stError:
  3853. RaiseLastOSError;
  3854. end;
  3855. end;
  3856. function TJclPeImage.RawToVa(Raw: DWORD): Pointer;
  3857. begin
  3858. Result := Pointer(TJclAddr(FLoadedImage.MappedAddress) + Raw);
  3859. end;
  3860. procedure TJclPeImage.ReadImageSections;
  3861. var
  3862. I: Integer;
  3863. Header: PImageSectionHeader;
  3864. UTF8Name: TUTF8String;
  3865. SectionName: string;
  3866. begin
  3867. if not StatusOK then
  3868. Exit;
  3869. Header := FLoadedImage.Sections;
  3870. for I := 0 to FLoadedImage.NumberOfSections - 1 do
  3871. begin
  3872. SetLength(UTF8Name, IMAGE_SIZEOF_SHORT_NAME);
  3873. Move(Header.Name[0], UTF8Name[1], IMAGE_SIZEOF_SHORT_NAME * SizeOf(AnsiChar));
  3874. StrResetLength(UTF8Name);
  3875. if not TryUTF8ToString(UTF8Name, SectionName) then
  3876. SectionName := string(UTF8Name);
  3877. FImageSections.AddObject(SectionName, Pointer(Header));
  3878. Inc(Header);
  3879. end;
  3880. end;
  3881. procedure TJclPeImage.ReadStringTable;
  3882. var
  3883. SymbolTable: DWORD;
  3884. StringTablePtr: PAnsiChar;
  3885. Ptr: PAnsiChar;
  3886. ByteSize: ULONG;
  3887. Start: PAnsiChar;
  3888. StringEntry: AnsiString;
  3889. begin
  3890. SymbolTable := LoadedImage.FileHeader.FileHeader.PointerToSymbolTable;
  3891. if SymbolTable = 0 then
  3892. Exit;
  3893. StringTablePtr := PAnsiChar(LoadedImage.MappedAddress) +
  3894. SymbolTable +
  3895. (LoadedImage.FileHeader.FileHeader.NumberOfSymbols * SizeOf(IMAGE_SYMBOL));
  3896. ByteSize := PULONG(StringTablePtr)^;
  3897. Ptr := StringTablePtr + SizeOf(ByteSize);
  3898. while Ptr < StringTablePtr + ByteSize do
  3899. begin
  3900. Start := Ptr;
  3901. while (Ptr^ <> #0) and (Ptr < StringTablePtr + ByteSize) do
  3902. Inc(Ptr);
  3903. if Start <> Ptr then
  3904. begin
  3905. SetLength(StringEntry, Ptr - Start);
  3906. Move(Start^, StringEntry[1], Ptr - Start);
  3907. FStringTable.Add(string(StringEntry));
  3908. end;
  3909. Inc(Ptr); // to skip the #0 character
  3910. end;
  3911. end;
  3912. function TJclPeImage.ResourceItemCreate(AEntry: PImageResourceDirectoryEntry;
  3913. AParentItem: TJclPeResourceItem): TJclPeResourceItem;
  3914. begin
  3915. Result := TJclPeResourceItem.Create(Self, AParentItem, AEntry);
  3916. end;
  3917. function TJclPeImage.ResourceListCreate(ADirectory: PImageResourceDirectory;
  3918. AParentItem: TJclPeResourceItem): TJclPeResourceList;
  3919. begin
  3920. Result := TJclPeResourceList.Create(Self, AParentItem, ADirectory);
  3921. end;
  3922. function TJclPeImage.RvaToSection(Rva: DWORD): PImageSectionHeader;
  3923. var
  3924. I: Integer;
  3925. SectionHeader: PImageSectionHeader;
  3926. EndRVA: DWORD;
  3927. begin
  3928. Result := ImageRvaToSection(FLoadedImage.FileHeader, FLoadedImage.MappedAddress, Rva);
  3929. if Result = nil then
  3930. for I := 0 to FImageSections.Count - 1 do
  3931. begin
  3932. SectionHeader := PImageSectionHeader(FImageSections.Objects[I]);
  3933. if SectionHeader^.SizeOfRawData = 0 then
  3934. EndRVA := SectionHeader^.Misc.VirtualSize
  3935. else
  3936. EndRVA := SectionHeader^.SizeOfRawData;
  3937. Inc(EndRVA, SectionHeader^.VirtualAddress);
  3938. if (SectionHeader^.VirtualAddress <= Rva) and (EndRVA >= Rva) then
  3939. begin
  3940. Result := SectionHeader;
  3941. Break;
  3942. end;
  3943. end;
  3944. end;
  3945. function TJclPeImage.RvaToVa(Rva: DWORD): Pointer;
  3946. begin
  3947. if FAttachedImage then
  3948. Result := Pointer(TJclAddr(FLoadedImage.MappedAddress) + Rva)
  3949. else
  3950. Result := ImageRvaToVa(FLoadedImage.FileHeader, FLoadedImage.MappedAddress, Rva, nil);
  3951. end;
  3952. function TJclPeImage.ImageAddressToRva(Address: DWORD): DWORD;
  3953. var
  3954. ImageBase32: DWORD;
  3955. ImageBase64: Int64;
  3956. begin
  3957. case Target of
  3958. taWin32:
  3959. begin
  3960. ImageBase32 := PImageNtHeaders32(FLoadedImage.FileHeader)^.OptionalHeader.ImageBase;
  3961. Result := Address - ImageBase32;
  3962. end;
  3963. taWin64:
  3964. begin
  3965. ImageBase64 := PImageNtHeaders64(FLoadedImage.FileHeader)^.OptionalHeader.ImageBase;
  3966. Result := DWORD(Address - ImageBase64);
  3967. end;
  3968. //taUnknown:
  3969. else
  3970. Result := 0;
  3971. end;
  3972. end;
  3973. procedure TJclPeImage.SetFileName(const Value: TFileName);
  3974. begin
  3975. if FFileName <> Value then
  3976. begin
  3977. Clear;
  3978. FFileName := Value;
  3979. if FFileName = '' then
  3980. Exit;
  3981. // OF: possible loss of data
  3982. if MapAndLoad(PAnsiChar(AnsiString(FFileName)), nil, FLoadedImage, True, FReadOnlyAccess) then
  3983. begin
  3984. FTarget := PeMapImgTarget(FLoadedImage.MappedAddress);
  3985. if FTarget <> taUnknown then
  3986. begin
  3987. FStatus := stOk;
  3988. ReadImageSections;
  3989. ReadStringTable;
  3990. AfterOpen;
  3991. end
  3992. else
  3993. FStatus := stNotSupported;
  3994. end
  3995. else
  3996. case GetLastError of
  3997. ERROR_SUCCESS:
  3998. FStatus := stNotPE;
  3999. ERROR_FILE_NOT_FOUND:
  4000. FStatus := stNotFound;
  4001. else
  4002. FStatus := stError;
  4003. end;
  4004. RaiseStatusException;
  4005. end;
  4006. end;
  4007. class function TJclPeImage.ShortSectionInfo(Characteristics: DWORD): string;
  4008. type
  4009. TSectionCharacteristics = packed record
  4010. Mask: DWORD;
  4011. InfoChar: Char;
  4012. end;
  4013. const
  4014. Info: array [1..8] of TSectionCharacteristics = (
  4015. (Mask: IMAGE_SCN_CNT_CODE; InfoChar: 'C'),
  4016. (Mask: IMAGE_SCN_MEM_EXECUTE; InfoChar: 'E'),
  4017. (Mask: IMAGE_SCN_MEM_READ; InfoChar: 'R'),
  4018. (Mask: IMAGE_SCN_MEM_WRITE; InfoChar: 'W'),
  4019. (Mask: IMAGE_SCN_CNT_INITIALIZED_DATA; InfoChar: 'I'),
  4020. (Mask: IMAGE_SCN_CNT_UNINITIALIZED_DATA; InfoChar: 'U'),
  4021. (Mask: IMAGE_SCN_MEM_SHARED; InfoChar: 'S'),
  4022. (Mask: IMAGE_SCN_MEM_DISCARDABLE; InfoChar: 'D')
  4023. );
  4024. var
  4025. I: Integer;
  4026. begin
  4027. SetLength(Result, High(Info));
  4028. Result := '';
  4029. for I := Low(Info) to High(Info) do
  4030. with Info[I] do
  4031. if (Characteristics and Mask) = Mask then
  4032. Result := Result + InfoChar;
  4033. end;
  4034. function TJclPeImage.StatusOK: Boolean;
  4035. begin
  4036. Result := (FStatus = stOk);
  4037. end;
  4038. class function TJclPeImage.StampToDateTime(TimeDateStamp: DWORD): TDateTime;
  4039. begin
  4040. Result := TimeDateStamp / SecsPerDay + UnixTimeStart
  4041. end;
  4042. procedure TJclPeImage.TryGetNamesForOrdinalImports;
  4043. begin
  4044. if StatusOK then
  4045. begin
  4046. GetImportList;
  4047. FImportList.TryGetNamesForOrdinalImports;
  4048. end;
  4049. end;
  4050. function TJclPeImage.VerifyCheckSum: Boolean;
  4051. function VerifyCheckSum32: Boolean;
  4052. var
  4053. OptionalHeader: TImageOptionalHeader32;
  4054. begin
  4055. OptionalHeader := OptionalHeader32;
  4056. Result := StatusOK and ((OptionalHeader.CheckSum = 0) or (CalculateCheckSum = OptionalHeader.CheckSum));
  4057. end;
  4058. function VerifyCheckSum64: Boolean;
  4059. var
  4060. OptionalHeader: TImageOptionalHeader64;
  4061. begin
  4062. OptionalHeader := OptionalHeader64;
  4063. Result := StatusOK and ((OptionalHeader.CheckSum = 0) or (CalculateCheckSum = OptionalHeader.CheckSum));
  4064. end;
  4065. begin
  4066. CheckNotAttached;
  4067. case Target of
  4068. taWin32:
  4069. Result := VerifyCheckSum32;
  4070. taWin64:
  4071. Result := VerifyCheckSum64;
  4072. //taUnknown: ;
  4073. else
  4074. Result := True;
  4075. end;
  4076. end;
  4077. {$IFDEF BORLAND}
  4078. //=== { TJclPeBorImagesCache } ===============================================
  4079. function TJclPeBorImagesCache.GetImages(const FileName: TFileName): TJclPeBorImage;
  4080. begin
  4081. Result := TJclPeBorImage(inherited Images[FileName]);
  4082. end;
  4083. function TJclPeBorImagesCache.GetPeImageClass: TJclPeImageClass;
  4084. begin
  4085. Result := TJclPeBorImage;
  4086. end;
  4087. //=== { TJclPePackageInfo } ==================================================
  4088. constructor TJclPePackageInfo.Create(ALibHandle: THandle);
  4089. begin
  4090. FContains := TStringList.Create;
  4091. FRequires := TStringList.Create;
  4092. FEnsureExtension := True;
  4093. FSorted := True;
  4094. ReadPackageInfo(ALibHandle);
  4095. end;
  4096. destructor TJclPePackageInfo.Destroy;
  4097. begin
  4098. FreeAndNil(FContains);
  4099. FreeAndNil(FRequires);
  4100. inherited Destroy;
  4101. end;
  4102. function TJclPePackageInfo.GetContains: TStrings;
  4103. begin
  4104. Result := FContains;
  4105. end;
  4106. function TJclPePackageInfo.GetContainsCount: Integer;
  4107. begin
  4108. Result := Contains.Count;
  4109. end;
  4110. function TJclPePackageInfo.GetContainsFlags(Index: Integer): Byte;
  4111. begin
  4112. Result := Byte(Contains.Objects[Index]);
  4113. end;
  4114. function TJclPePackageInfo.GetContainsNames(Index: Integer): string;
  4115. begin
  4116. Result := Contains[Index];
  4117. end;
  4118. function TJclPePackageInfo.GetRequires: TStrings;
  4119. begin
  4120. Result := FRequires;
  4121. end;
  4122. function TJclPePackageInfo.GetRequiresCount: Integer;
  4123. begin
  4124. Result := Requires.Count;
  4125. end;
  4126. function TJclPePackageInfo.GetRequiresNames(Index: Integer): string;
  4127. begin
  4128. Result := Requires[Index];
  4129. if FEnsureExtension then
  4130. StrEnsureSuffix(BinaryExtensionPackage, Result);
  4131. end;
  4132. class function TJclPePackageInfo.PackageModuleTypeToString(Flags: Cardinal): string;
  4133. begin
  4134. case Flags and pfModuleTypeMask of
  4135. pfExeModule, pfModuleTypeMask:
  4136. Result := LoadResString(@RsPePkgExecutable);
  4137. pfPackageModule:
  4138. Result := LoadResString(@RsPePkgPackage);
  4139. pfLibraryModule:
  4140. Result := LoadResString(@PsPePkgLibrary);
  4141. else
  4142. Result := '';
  4143. end;
  4144. end;
  4145. class function TJclPePackageInfo.PackageOptionsToString(Flags: Cardinal): string;
  4146. begin
  4147. Result := '';
  4148. AddFlagTextRes(Result, @RsPePkgNeverBuild, Flags, pfNeverBuild);
  4149. AddFlagTextRes(Result, @RsPePkgDesignOnly, Flags, pfDesignOnly);
  4150. AddFlagTextRes(Result, @RsPePkgRunOnly, Flags, pfRunOnly);
  4151. AddFlagTextRes(Result, @RsPePkgIgnoreDupUnits, Flags, pfIgnoreDupUnits);
  4152. end;
  4153. class function TJclPePackageInfo.ProducerToString(Flags: Cardinal): string;
  4154. begin
  4155. case Flags and pfProducerMask of
  4156. pfV3Produced:
  4157. Result := LoadResString(@RsPePkgV3Produced);
  4158. pfProducerUndefined:
  4159. Result := LoadResString(@RsPePkgProducerUndefined);
  4160. pfBCB4Produced:
  4161. Result := LoadResString(@RsPePkgBCB4Produced);
  4162. pfDelphi4Produced:
  4163. Result := LoadResString(@RsPePkgDelphi4Produced);
  4164. else
  4165. Result := '';
  4166. end;
  4167. end;
  4168. procedure PackageInfoProc(const Name: string; NameType: TNameType; AFlags: Byte; Param: Pointer);
  4169. begin
  4170. with TJclPePackageInfo(Param) do
  4171. case NameType of
  4172. ntContainsUnit:
  4173. Contains.AddObject(Name, Pointer(AFlags));
  4174. ntRequiresPackage:
  4175. Requires.Add(Name);
  4176. ntDcpBpiName:
  4177. SetDcpName(Name);
  4178. end;
  4179. end;
  4180. procedure TJclPePackageInfo.ReadPackageInfo(ALibHandle: THandle);
  4181. var
  4182. DescrResInfo: HRSRC;
  4183. DescrResData: HGLOBAL;
  4184. begin
  4185. FAvailable := FindResource(ALibHandle, PackageInfoResName, RT_RCDATA) <> 0;
  4186. if FAvailable then
  4187. begin
  4188. GetPackageInfo(ALibHandle, Self, FFlags, PackageInfoProc);
  4189. if FDcpName = '' then
  4190. FDcpName := PathExtractFileNameNoExt(GetModulePath(ALibHandle)) + CompilerExtensionDCP;
  4191. if FSorted then
  4192. begin
  4193. FContains.Sort;
  4194. FRequires.Sort;
  4195. end;
  4196. end;
  4197. DescrResInfo := FindResource(ALibHandle, DescriptionResName, RT_RCDATA);
  4198. if DescrResInfo <> 0 then
  4199. begin
  4200. DescrResData := LoadResource(ALibHandle, DescrResInfo);
  4201. if DescrResData <> 0 then
  4202. begin
  4203. FDescription := WideCharLenToString(LockResource(DescrResData),
  4204. SizeofResource(ALibHandle, DescrResInfo));
  4205. StrResetLength(FDescription);
  4206. end;
  4207. end;
  4208. end;
  4209. procedure TJclPePackageInfo.SetDcpName(const Value: string);
  4210. begin
  4211. FDcpName := Value;
  4212. end;
  4213. class function TJclPePackageInfo.UnitInfoFlagsToString(UnitFlags: Byte): string;
  4214. begin
  4215. Result := '';
  4216. AddFlagTextRes(Result, @RsPePkgMain, UnitFlags, ufMainUnit);
  4217. AddFlagTextRes(Result, @RsPePkgPackage, UnitFlags, ufPackageUnit);
  4218. AddFlagTextRes(Result, @RsPePkgWeak, UnitFlags, ufWeakUnit);
  4219. AddFlagTextRes(Result, @RsPePkgOrgWeak, UnitFlags, ufOrgWeakUnit);
  4220. AddFlagTextRes(Result, @RsPePkgImplicit, UnitFlags, ufImplicitUnit);
  4221. end;
  4222. //=== { TJclPeBorForm } ======================================================
  4223. constructor TJclPeBorForm.Create(AResItem: TJclPeResourceItem;
  4224. AFormFlags: TFilerFlags; AFormPosition: Integer;
  4225. const AFormClassName, AFormObjectName: string);
  4226. begin
  4227. inherited Create;
  4228. FResItem := AResItem;
  4229. FFormFlags := AFormFlags;
  4230. FFormPosition := AFormPosition;
  4231. FFormClassName := AFormClassName;
  4232. FFormObjectName := AFormObjectName;
  4233. end;
  4234. procedure TJclPeBorForm.ConvertFormToText(const Stream: TStream);
  4235. var
  4236. SourceStream: TJclPeResourceRawStream;
  4237. begin
  4238. SourceStream := TJclPeResourceRawStream.Create(ResItem);
  4239. try
  4240. ObjectBinaryToText(SourceStream, Stream);
  4241. finally
  4242. SourceStream.Free;
  4243. end;
  4244. end;
  4245. procedure TJclPeBorForm.ConvertFormToText(const Strings: TStrings);
  4246. var
  4247. TempStream: TMemoryStream;
  4248. begin
  4249. TempStream := TMemoryStream.Create;
  4250. try
  4251. ConvertFormToText(TempStream);
  4252. TempStream.Seek(0, soFromBeginning);
  4253. Strings.LoadFromStream(TempStream);
  4254. finally
  4255. TempStream.Free;
  4256. end;
  4257. end;
  4258. function TJclPeBorForm.GetDisplayName: string;
  4259. begin
  4260. if FFormObjectName <> '' then
  4261. Result := FFormObjectName + ': '
  4262. else
  4263. Result := '';
  4264. Result := Result + FFormClassName;
  4265. end;
  4266. //=== { TJclPeBorImage } =====================================================
  4267. constructor TJclPeBorImage.Create(ANoExceptions: Boolean);
  4268. begin
  4269. FForms := TObjectList.Create(True);
  4270. FPackageInfoSorted := True;
  4271. inherited Create(ANoExceptions);
  4272. end;
  4273. destructor TJclPeBorImage.Destroy;
  4274. begin
  4275. inherited Destroy;
  4276. FreeAndNil(FForms);
  4277. end;
  4278. procedure TJclPeBorImage.AfterOpen;
  4279. var
  4280. HasDVCLAL, HasPACKAGEINFO, HasPACKAGEOPTIONS: Boolean;
  4281. begin
  4282. inherited AfterOpen;
  4283. if StatusOK then
  4284. with ResourceList do
  4285. begin
  4286. HasDVCLAL := (FindResource(rtRCData, DVclAlResName) <> nil);
  4287. HasPACKAGEINFO := (FindResource(rtRCData, PackageInfoResName) <> nil);
  4288. HasPACKAGEOPTIONS := (FindResource(rtRCData, PackageOptionsResName) <> nil);
  4289. FIsPackage := HasPACKAGEINFO and HasPACKAGEOPTIONS;
  4290. FIsBorlandImage := HasDVCLAL or FIsPackage;
  4291. end;
  4292. end;
  4293. procedure TJclPeBorImage.Clear;
  4294. begin
  4295. FForms.Clear;
  4296. FreeAndNil(FPackageInfo);
  4297. FreeLibHandle;
  4298. inherited Clear;
  4299. FIsBorlandImage := False;
  4300. FIsPackage := False;
  4301. FPackageCompilerVersion := 0;
  4302. end;
  4303. procedure TJclPeBorImage.CreateFormsList;
  4304. var
  4305. ResTypeItem: TJclPeResourceItem;
  4306. I: Integer;
  4307. procedure ProcessListItem(DfmResItem: TJclPeResourceItem);
  4308. const
  4309. FilerSignature: array [1..4] of AnsiChar = string('TPF0');
  4310. var
  4311. SourceStream: TJclPeResourceRawStream;
  4312. Reader: TReader;
  4313. FormFlags: TFilerFlags;
  4314. FormPosition: Integer;
  4315. ClassName, FormName: string;
  4316. begin
  4317. SourceStream := TJclPeResourceRawStream.Create(DfmResItem);
  4318. try
  4319. if (SourceStream.Size > SizeOf(FilerSignature)) and
  4320. (PInteger(SourceStream.Memory)^ = Integer(FilerSignature)) then
  4321. begin
  4322. Reader := TReader.Create(SourceStream, 4096);
  4323. try
  4324. Reader.ReadSignature;
  4325. Reader.ReadPrefix(FormFlags, FormPosition);
  4326. ClassName := Reader.ReadStr;
  4327. FormName := Reader.ReadStr;
  4328. FForms.Add(TJclPeBorForm.Create(DfmResItem, FormFlags, FormPosition,
  4329. ClassName, FormName));
  4330. finally
  4331. Reader.Free;
  4332. end;
  4333. end;
  4334. finally
  4335. SourceStream.Free;
  4336. end;
  4337. end;
  4338. begin
  4339. if StatusOK then
  4340. with ResourceList do
  4341. begin
  4342. ResTypeItem := FindResource(rtRCData, '');
  4343. if ResTypeItem <> nil then
  4344. with ResTypeItem.List do
  4345. for I := 0 to Count - 1 do
  4346. ProcessListItem(Items[I].List[0]);
  4347. end;
  4348. end;
  4349. function TJclPeBorImage.DependedPackages(List: TStrings; FullPathName, Descriptions: Boolean): Boolean;
  4350. var
  4351. ImportList: TStringList;
  4352. I: Integer;
  4353. Name: string;
  4354. begin
  4355. Result := IsBorlandImage;
  4356. if not Result then
  4357. Exit;
  4358. ImportList := InternalImportedLibraries(FileName, True, FullPathName, nil);
  4359. List.BeginUpdate;
  4360. try
  4361. for I := 0 to ImportList.Count - 1 do
  4362. begin
  4363. Name := ImportList[I];
  4364. if StrSame(ExtractFileExt(Name), BinaryExtensionPackage) then
  4365. begin
  4366. if Descriptions then
  4367. List.Add(Name + '=' + GetPackageDescription(PChar(Name)))
  4368. else
  4369. List.Add(Name);
  4370. end;
  4371. end;
  4372. finally
  4373. ImportList.Free;
  4374. List.EndUpdate;
  4375. end;
  4376. end;
  4377. function TJclPeBorImage.FreeLibHandle: Boolean;
  4378. begin
  4379. if FLibHandle <> 0 then
  4380. begin
  4381. Result := FreeLibrary(FLibHandle);
  4382. FLibHandle := 0;
  4383. end
  4384. else
  4385. Result := True;
  4386. end;
  4387. function TJclPeBorImage.GetFormCount: Integer;
  4388. begin
  4389. if FForms.Count = 0 then
  4390. CreateFormsList;
  4391. Result := FForms.Count;
  4392. end;
  4393. function TJclPeBorImage.GetFormFromName(const FormClassName: string): TJclPeBorForm;
  4394. var
  4395. I: Integer;
  4396. begin
  4397. Result := nil;
  4398. for I := 0 to FormCount - 1 do
  4399. if StrSame(FormClassName, Forms[I].FormClassName) then
  4400. begin
  4401. Result := Forms[I];
  4402. Break;
  4403. end;
  4404. end;
  4405. function TJclPeBorImage.GetForms(Index: Integer): TJclPeBorForm;
  4406. begin
  4407. Result := TJclPeBorForm(FForms[Index]);
  4408. end;
  4409. function TJclPeBorImage.GetLibHandle: THandle;
  4410. begin
  4411. if StatusOK and (FLibHandle = 0) then
  4412. begin
  4413. FLibHandle := LoadLibraryEx(PChar(FileName), 0, LOAD_LIBRARY_AS_DATAFILE);
  4414. if FLibHandle = 0 then
  4415. RaiseLastOSError;
  4416. end;
  4417. Result := FLibHandle;
  4418. end;
  4419. function TJclPeBorImage.GetPackageCompilerVersion: Integer;
  4420. var
  4421. I: Integer;
  4422. ImportName: string;
  4423. function CheckName: Boolean;
  4424. begin
  4425. Result := False;
  4426. ImportName := AnsiUpperCase(ImportName);
  4427. if StrSame(ExtractFileExt(ImportName), BinaryExtensionPackage) then
  4428. begin
  4429. ImportName := PathExtractFileNameNoExt(ImportName);
  4430. if (Length(ImportName) = 5) and
  4431. CharIsDigit(ImportName[4]) and CharIsDigit(ImportName[5]) and
  4432. ((Pos('RTL', ImportName) = 1) or (Pos('VCL', ImportName) = 1)) then
  4433. begin
  4434. FPackageCompilerVersion := StrToIntDef(Copy(ImportName, 4, 2), 0);
  4435. Result := True;
  4436. end;
  4437. end;
  4438. end;
  4439. begin
  4440. if (FPackageCompilerVersion = 0) and IsPackage then
  4441. begin
  4442. with ImportList do
  4443. for I := 0 to UniqueLibItemCount - 1 do
  4444. begin
  4445. ImportName := UniqueLibNames[I];
  4446. if CheckName then
  4447. Break;
  4448. end;
  4449. if FPackageCompilerVersion = 0 then
  4450. begin
  4451. ImportName := ExtractFileName(FileName);
  4452. CheckName;
  4453. end;
  4454. end;
  4455. Result := FPackageCompilerVersion;
  4456. end;
  4457. function TJclPeBorImage.GetPackageInfo: TJclPePackageInfo;
  4458. begin
  4459. if StatusOK and (FPackageInfo = nil) then
  4460. begin
  4461. GetLibHandle;
  4462. FPackageInfo := TJclPePackageInfo.Create(FLibHandle);
  4463. FPackageInfo.Sorted := FPackageInfoSorted;
  4464. FreeLibHandle;
  4465. end;
  4466. Result := FPackageInfo;
  4467. end;
  4468. {$ENDIF BORLAND}
  4469. //=== { TJclPeNameSearch } ===================================================
  4470. constructor TJclPeNameSearch.Create(const FunctionName, Path: string; Options: TJclPeNameSearchOptions);
  4471. begin
  4472. inherited Create(True);
  4473. FFunctionName := FunctionName;
  4474. FOptions := Options;
  4475. FPath := Path;
  4476. FreeOnTerminate := True;
  4477. end;
  4478. function TJclPeNameSearch.CompareName(const FunctionName, ComparedName: string): Boolean;
  4479. begin
  4480. Result := PeSmartFunctionNameSame(ComparedName, FunctionName, [scIgnoreCase]);
  4481. end;
  4482. procedure TJclPeNameSearch.DoFound;
  4483. begin
  4484. if Assigned(FOnFound) then
  4485. FOnFound(Self, F_FileName, F_FunctionName, F_Option);
  4486. end;
  4487. procedure TJclPeNameSearch.DoProcessFile;
  4488. begin
  4489. if Assigned(FOnProcessFile) then
  4490. FOnProcessFile(Self, FPeImage, F_Process);
  4491. end;
  4492. procedure TJclPeNameSearch.Execute;
  4493. var
  4494. PathList: TStringList;
  4495. I: Integer;
  4496. function CompareNameAndNotify(const S: string): Boolean;
  4497. begin
  4498. Result := CompareName(S, FFunctionName);
  4499. if Result and not Terminated then
  4500. begin
  4501. F_FunctionName := S;
  4502. Synchronize(DoFound);
  4503. end;
  4504. end;
  4505. procedure ProcessDirectorySearch(const DirName: string);
  4506. var
  4507. Se: TSearchRec;
  4508. SearchResult: Integer;
  4509. ImportList: TJclPeImportList;
  4510. ExportList: TJclPeExportFuncList;
  4511. I: Integer;
  4512. begin
  4513. SearchResult := FindFirst(DirName, faArchive + faReadOnly, Se);
  4514. try
  4515. while not Terminated and (SearchResult = 0) do
  4516. begin
  4517. F_FileName := PathAddSeparator(ExtractFilePath(DirName)) + Se.Name;
  4518. F_Process := True;
  4519. FPeImage.FileName := F_FileName;
  4520. if Assigned(FOnProcessFile) then
  4521. Synchronize(DoProcessFile);
  4522. if F_Process and FPeImage.StatusOK then
  4523. begin
  4524. if seExports in FOptions then
  4525. begin
  4526. ExportList := FPeImage.ExportList;
  4527. F_Option := seExports;
  4528. for I := 0 to ExportList.Count - 1 do
  4529. begin
  4530. if Terminated then
  4531. Break;
  4532. CompareNameAndNotify(ExportList[I].Name);
  4533. end;
  4534. end;
  4535. if FOptions * [seImports, seDelayImports, seBoundImports] <> [] then
  4536. begin
  4537. ImportList := FPeImage.ImportList;
  4538. FPeImage.TryGetNamesForOrdinalImports;
  4539. for I := 0 to ImportList.AllItemCount - 1 do
  4540. with ImportList.AllItems[I] do
  4541. begin
  4542. if Terminated then
  4543. Break;
  4544. case ImportLib.ImportKind of
  4545. ikImport:
  4546. if seImports in FOptions then
  4547. begin
  4548. F_Option := seImports;
  4549. CompareNameAndNotify(Name);
  4550. end;
  4551. ikDelayImport:
  4552. if seDelayImports in FOptions then
  4553. begin
  4554. F_Option := seDelayImports;
  4555. CompareNameAndNotify(Name);
  4556. end;
  4557. ikBoundImport:
  4558. if seDelayImports in FOptions then
  4559. begin
  4560. F_Option := seBoundImports;
  4561. CompareNameAndNotify(Name);
  4562. end;
  4563. end;
  4564. end;
  4565. end;
  4566. end;
  4567. SearchResult := FindNext(Se);
  4568. end;
  4569. finally
  4570. FindClose(Se);
  4571. end;
  4572. end;
  4573. begin
  4574. FPeImage := TJclPeImage.Create(True);
  4575. PathList := TStringList.Create;
  4576. try
  4577. PathList.Sorted := True;
  4578. PathList.Duplicates := dupIgnore;
  4579. StrToStrings(FPath, ';', PathList);
  4580. for I := 0 to PathList.Count - 1 do
  4581. ProcessDirectorySearch(PathAddSeparator(Trim(PathList[I])) + '*.*');
  4582. finally
  4583. PathList.Free;
  4584. FPeImage.Free;
  4585. end;
  4586. end;
  4587. procedure TJclPeNameSearch.Start;
  4588. begin
  4589. {$IFDEF RTL210_UP}
  4590. Suspended := False;
  4591. {$ELSE ~RTL210_UP}
  4592. Resume;
  4593. {$ENDIF ~RTL210_UP}
  4594. end;
  4595. //=== PE Image miscellaneous functions =======================================
  4596. function IsValidPeFile(const FileName: TFileName): Boolean;
  4597. var
  4598. NtHeaders: TImageNtHeaders32;
  4599. begin
  4600. Result := PeGetNtHeaders32(FileName, NtHeaders);
  4601. end;
  4602. function InternalGetNtHeaders32(const FileName: TFileName; out NtHeaders): Boolean;
  4603. var
  4604. FileHandle: THandle;
  4605. Mapping: TJclFileMapping;
  4606. View: TJclFileMappingView;
  4607. HeadersPtr: PImageNtHeaders32;
  4608. begin
  4609. Result := False;
  4610. ResetMemory(NtHeaders, SizeOf(TImageNtHeaders32));
  4611. FileHandle := FileOpen(FileName, fmOpenRead or fmShareDenyWrite);
  4612. if FileHandle = INVALID_HANDLE_VALUE then
  4613. Exit;
  4614. try
  4615. if GetSizeOfFile(FileHandle) >= SizeOf(TImageDosHeader) then
  4616. begin
  4617. Mapping := TJclFileMapping.Create(FileHandle, '', PAGE_READONLY, 0, nil);
  4618. try
  4619. View := TJclFileMappingView.Create(Mapping, FILE_MAP_READ, 0, 0);
  4620. HeadersPtr := PeMapImgNtHeaders32(View.Memory);
  4621. if HeadersPtr <> nil then
  4622. begin
  4623. Result := True;
  4624. TImageNtHeaders32(NtHeaders) := HeadersPtr^;
  4625. end;
  4626. finally
  4627. Mapping.Free;
  4628. end;
  4629. end;
  4630. finally
  4631. FileClose(FileHandle);
  4632. end;
  4633. end;
  4634. function PeGetNtHeaders32(const FileName: TFileName; out NtHeaders: TImageNtHeaders32): Boolean;
  4635. begin
  4636. Result := InternalGetNtHeaders32(FileName, NtHeaders);
  4637. end;
  4638. function PeGetNtHeaders64(const FileName: TFileName; out NtHeaders: TImageNtHeaders64): Boolean;
  4639. var
  4640. FileHandle: THandle;
  4641. Mapping: TJclFileMapping;
  4642. View: TJclFileMappingView;
  4643. HeadersPtr: PImageNtHeaders64;
  4644. begin
  4645. Result := False;
  4646. ResetMemory(NtHeaders, SizeOf(NtHeaders));
  4647. FileHandle := FileOpen(FileName, fmOpenRead or fmShareDenyWrite);
  4648. if FileHandle = INVALID_HANDLE_VALUE then
  4649. Exit;
  4650. try
  4651. if GetSizeOfFile(FileHandle) >= SizeOf(TImageDosHeader) then
  4652. begin
  4653. Mapping := TJclFileMapping.Create(FileHandle, '', PAGE_READONLY, 0, nil);
  4654. try
  4655. View := TJclFileMappingView.Create(Mapping, FILE_MAP_READ, 0, 0);
  4656. HeadersPtr := PeMapImgNtHeaders64(View.Memory);
  4657. if HeadersPtr <> nil then
  4658. begin
  4659. Result := True;
  4660. NtHeaders := HeadersPtr^;
  4661. end;
  4662. finally
  4663. Mapping.Free;
  4664. end;
  4665. end;
  4666. finally
  4667. FileClose(FileHandle);
  4668. end;
  4669. end;
  4670. function PeCreateNameHintTable(const FileName: TFileName): Boolean;
  4671. var
  4672. PeImage, ExportsImage: TJclPeImage;
  4673. I: Integer;
  4674. ImportItem: TJclPeImportLibItem;
  4675. Thunk32: PImageThunkData32;
  4676. Thunk64: PImageThunkData64;
  4677. OrdinalName: PImageImportByName;
  4678. ExportItem: TJclPeExportFuncItem;
  4679. Cache: TJclPeImagesCache;
  4680. ImageBase32: TJclAddr32;
  4681. ImageBase64: TJclAddr64;
  4682. UTF8Name: TUTF8String;
  4683. ExportName: string;
  4684. begin
  4685. Cache := TJclPeImagesCache.Create;
  4686. try
  4687. PeImage := TJclPeImage.Create(False);
  4688. try
  4689. PeImage.ReadOnlyAccess := False;
  4690. PeImage.FileName := FileName;
  4691. Result := PeImage.ImportList.Count > 0;
  4692. for I := 0 to PeImage.ImportList.Count - 1 do
  4693. begin
  4694. ImportItem := PeImage.ImportList[I];
  4695. if ImportItem.ImportKind = ikBoundImport then
  4696. Continue;
  4697. ExportsImage := Cache[ImportItem.FileName];
  4698. ExportsImage.ExportList.PrepareForFastNameSearch;
  4699. case PEImage.Target of
  4700. taWin32:
  4701. begin
  4702. Thunk32 := ImportItem.ThunkData32;
  4703. ImageBase32 := PeImage.OptionalHeader32.ImageBase;
  4704. while Thunk32^.Function_ <> 0 do
  4705. begin
  4706. if Thunk32^.Ordinal and IMAGE_ORDINAL_FLAG32 = 0 then
  4707. begin
  4708. case ImportItem.ImportKind of
  4709. ikImport:
  4710. OrdinalName := PImageImportByName(PeImage.RvaToVa(Thunk32^.AddressOfData));
  4711. ikDelayImport:
  4712. OrdinalName := PImageImportByName(PeImage.RvaToVa(Thunk32^.AddressOfData - ImageBase32));
  4713. else
  4714. OrdinalName := nil;
  4715. end;
  4716. UTF8Name := PAnsiChar(@OrdinalName.Name);
  4717. if not TryUTF8ToString(UTF8Name, ExportName) then
  4718. ExportName := string(UTF8Name);
  4719. ExportItem := ExportsImage.ExportList.ItemFromName[ExportName];
  4720. if ExportItem <> nil then
  4721. OrdinalName.Hint := ExportItem.Hint
  4722. else
  4723. OrdinalName.Hint := 0;
  4724. end;
  4725. Inc(Thunk32);
  4726. end;
  4727. end;
  4728. taWin64:
  4729. begin
  4730. Thunk64 := ImportItem.ThunkData64;
  4731. ImageBase64 := PeImage.OptionalHeader64.ImageBase;
  4732. while Thunk64^.Function_ <> 0 do
  4733. begin
  4734. if Thunk64^.Ordinal and IMAGE_ORDINAL_FLAG64 = 0 then
  4735. begin
  4736. case ImportItem.ImportKind of
  4737. ikImport:
  4738. OrdinalName := PImageImportByName(PeImage.RvaToVa(Thunk64^.AddressOfData));
  4739. ikDelayImport:
  4740. OrdinalName := PImageImportByName(PeImage.RvaToVa(Thunk64^.AddressOfData - ImageBase64));
  4741. else
  4742. OrdinalName := nil;
  4743. end;
  4744. UTF8Name := PAnsiChar(@OrdinalName.Name);
  4745. if not TryUTF8ToString(UTF8Name, ExportName) then
  4746. ExportName := string(UTF8Name);
  4747. ExportItem := ExportsImage.ExportList.ItemFromName[ExportName];
  4748. if ExportItem <> nil then
  4749. OrdinalName.Hint := ExportItem.Hint
  4750. else
  4751. OrdinalName.Hint := 0;
  4752. end;
  4753. Inc(Thunk64);
  4754. end;
  4755. end;
  4756. end;
  4757. end;
  4758. finally
  4759. PeImage.Free;
  4760. end;
  4761. finally
  4762. Cache.Free;
  4763. end;
  4764. end;
  4765. function PeRebaseImage32(const ImageName: TFileName; NewBase: TJclAddr32;
  4766. TimeStamp, MaxNewSize: DWORD): TJclRebaseImageInfo32;
  4767. function CalculateBaseAddress: TJclAddr32;
  4768. var
  4769. FirstChar: Char;
  4770. ModuleName: string;
  4771. begin
  4772. ModuleName := ExtractFileName(ImageName);
  4773. if Length(ModuleName) > 0 then
  4774. FirstChar := UpCase(ModuleName[1])
  4775. else
  4776. FirstChar := NativeNull;
  4777. if not CharIsUpper(FirstChar) then
  4778. FirstChar := 'A';
  4779. Result := $60000000 + (((Ord(FirstChar) - Ord('A')) div 3) * $1000000);
  4780. end;
  4781. {$IFDEF CPU64}
  4782. {$IFNDEF DELPHI64_TEMPORARY}
  4783. var
  4784. NewIB, OldIB: QWord;
  4785. {$ENDIF CPU64}
  4786. {$ENDIF ~DELPHI64_TEMPORARY}
  4787. begin
  4788. if NewBase = 0 then
  4789. NewBase := CalculateBaseAddress;
  4790. with Result do
  4791. begin
  4792. NewImageBase := NewBase;
  4793. // OF: possible loss of data
  4794. {$IFDEF CPU32}
  4795. Win32Check(ReBaseImage(PAnsiChar(AnsiString(ImageName)), nil, True, False, False, MaxNewSize,
  4796. OldImageSize, OldImageBase, NewImageSize, NewImageBase, TimeStamp));
  4797. {$ENDIF CPU32}
  4798. {$IFDEF CPU64}
  4799. {$IFDEF DELPHI64_TEMPORARY}
  4800. System.Error(rePlatformNotImplemented);
  4801. {$ELSE ~DELPHI64_TEMPORARY}
  4802. NewIB := NewImageBase;
  4803. OldIB := OldImageBase;
  4804. Win32Check(ReBaseImage(PAnsiChar(AnsiString(ImageName)), nil, True, False, False, MaxNewSize,
  4805. OldImageSize, OldIB, NewImageSize, NewIB, TimeStamp));
  4806. NewImageBase := NewIB;
  4807. OldImageBase := OldIB;
  4808. {$ENDIF ~DELPHI64_TEMPORARY}
  4809. {$ENDIF CPU64}
  4810. end;
  4811. end;
  4812. function PeRebaseImage64(const ImageName: TFileName; NewBase: TJclAddr64;
  4813. TimeStamp, MaxNewSize: DWORD): TJclRebaseImageInfo64;
  4814. function CalculateBaseAddress: TJclAddr64;
  4815. var
  4816. FirstChar: Char;
  4817. ModuleName: string;
  4818. begin
  4819. ModuleName := ExtractFileName(ImageName);
  4820. if Length(ModuleName) > 0 then
  4821. FirstChar := UpCase(ModuleName[1])
  4822. else
  4823. FirstChar := NativeNull;
  4824. if not CharIsUpper(FirstChar) then
  4825. FirstChar := 'A';
  4826. Result := $60000000 + (((Ord(FirstChar) - Ord('A')) div 3) * $1000000);
  4827. Result := Result shl 32;
  4828. end;
  4829. begin
  4830. if NewBase = 0 then
  4831. NewBase := CalculateBaseAddress;
  4832. with Result do
  4833. begin
  4834. NewImageBase := NewBase;
  4835. // OF: possible loss of data
  4836. Win32Check(ReBaseImage64(PAnsiChar(AnsiString(ImageName)), nil, True, False, False, MaxNewSize,
  4837. OldImageSize, OldImageBase, NewImageSize, NewImageBase, TimeStamp));
  4838. end;
  4839. end;
  4840. function PeUpdateLinkerTimeStamp(const FileName: TFileName; const Time: TDateTime): Boolean;
  4841. var
  4842. Mapping: TJclFileMapping;
  4843. View: TJclFileMappingView;
  4844. Headers: PImageNtHeaders32; // works with 64-bit binaries too
  4845. // only the optional field differs
  4846. begin
  4847. Mapping := TJclFileMapping.Create(FileName, fmOpenReadWrite, '', PAGE_READWRITE, 0, nil);
  4848. try
  4849. View := TJclFileMappingView.Create(Mapping, FILE_MAP_WRITE, 0, 0);
  4850. Headers := PeMapImgNtHeaders32(View.Memory);
  4851. Result := (Headers <> nil);
  4852. if Result then
  4853. Headers^.FileHeader.TimeDateStamp := TJclPeImage.DateTimeToStamp(Time);
  4854. finally
  4855. Mapping.Free;
  4856. end;
  4857. end;
  4858. function PeReadLinkerTimeStamp(const FileName: TFileName): TDateTime;
  4859. var
  4860. Mapping: TJclFileMappingStream;
  4861. Headers: PImageNtHeaders32; // works with 64-bit binaries too
  4862. // only the optional field differs
  4863. begin
  4864. Mapping := TJclFileMappingStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  4865. try
  4866. Headers := PeMapImgNtHeaders32(Mapping.Memory);
  4867. if Headers <> nil then
  4868. Result := TJclPeImage.StampToDateTime(Headers^.FileHeader.TimeDateStamp)
  4869. else
  4870. Result := -1;
  4871. finally
  4872. Mapping.Free;
  4873. end;
  4874. end;
  4875. { TODO -cHelp : Author: Uwe Schuster(just a generic version of JclDebug.InsertDebugDataIntoExecutableFile) }
  4876. function PeInsertSection(const FileName: TFileName; SectionStream: TStream; SectionName: string): Boolean;
  4877. procedure RoundUpToAlignment(var Value: DWORD; Alignment: DWORD);
  4878. begin
  4879. if (Value mod Alignment) <> 0 then
  4880. Value := ((Value div Alignment) + 1) * Alignment;
  4881. end;
  4882. function PeInsertSection32(ImageStream: TMemoryStream): Boolean;
  4883. var
  4884. NtHeaders: PImageNtHeaders32;
  4885. Sections, LastSection, NewSection: PImageSectionHeader;
  4886. VirtualAlignedSize: DWORD;
  4887. I, X, NeedFill: Integer;
  4888. SectionDataSize: Integer;
  4889. UTF8Name: TUTF8String;
  4890. begin
  4891. Result := True;
  4892. try
  4893. SectionDataSize := SectionStream.Size;
  4894. NtHeaders := PeMapImgNtHeaders32(ImageStream.Memory);
  4895. Assert(NtHeaders <> nil);
  4896. Sections := PeMapImgSections32(NtHeaders);
  4897. Assert(Sections <> nil);
  4898. // Check whether there is not a section with the name already. If so, return True (#0000069)
  4899. if PeMapImgFindSection32(NtHeaders, SectionName) <> nil then
  4900. begin
  4901. Result := True;
  4902. Exit;
  4903. end;
  4904. LastSection := Sections;
  4905. Inc(LastSection, NtHeaders^.FileHeader.NumberOfSections - 1);
  4906. NewSection := LastSection;
  4907. Inc(NewSection);
  4908. // Increase the number of sections
  4909. Inc(NtHeaders^.FileHeader.NumberOfSections);
  4910. ResetMemory(NewSection^, SizeOf(TImageSectionHeader));
  4911. // JCLDEBUG Virtual Address
  4912. NewSection^.VirtualAddress := LastSection^.VirtualAddress + LastSection^.Misc.VirtualSize;
  4913. RoundUpToAlignment(NewSection^.VirtualAddress, NtHeaders^.OptionalHeader.SectionAlignment);
  4914. // JCLDEBUG Physical Offset
  4915. NewSection^.PointerToRawData := LastSection^.PointerToRawData + LastSection^.SizeOfRawData;
  4916. RoundUpToAlignment(NewSection^.PointerToRawData, NtHeaders^.OptionalHeader.FileAlignment);
  4917. // JCLDEBUG Section name
  4918. if not TryStringToUTF8(SectionName, UTF8Name) then
  4919. UTF8Name := TUTF8String(SectionName);
  4920. StrPLCopyA(PAnsiChar(@NewSection^.Name), UTF8Name, IMAGE_SIZEOF_SHORT_NAME);
  4921. // JCLDEBUG Characteristics flags
  4922. NewSection^.Characteristics := IMAGE_SCN_MEM_READ or IMAGE_SCN_CNT_INITIALIZED_DATA;
  4923. // Size of virtual data area
  4924. NewSection^.Misc.VirtualSize := SectionDataSize;
  4925. VirtualAlignedSize := SectionDataSize;
  4926. RoundUpToAlignment(VirtualAlignedSize, NtHeaders^.OptionalHeader.SectionAlignment);
  4927. // Update Size of Image
  4928. Inc(NtHeaders^.OptionalHeader.SizeOfImage, VirtualAlignedSize);
  4929. // Raw data size
  4930. NewSection^.SizeOfRawData := SectionDataSize;
  4931. RoundUpToAlignment(NewSection^.SizeOfRawData, NtHeaders^.OptionalHeader.FileAlignment);
  4932. // Update Initialized data size
  4933. Inc(NtHeaders^.OptionalHeader.SizeOfInitializedData, NewSection^.SizeOfRawData);
  4934. // Fill data to alignment
  4935. NeedFill := INT_PTR(NewSection^.SizeOfRawData) - SectionDataSize;
  4936. // Note: Delphi linker seems to generate incorrect (unaligned) size of
  4937. // the executable when adding TD32 debug data so the position could be
  4938. // behind the size of the file then.
  4939. ImageStream.Seek(NewSection^.PointerToRawData, soBeginning);
  4940. ImageStream.CopyFrom(SectionStream, 0);
  4941. X := 0;
  4942. for I := 1 to NeedFill do
  4943. ImageStream.WriteBuffer(X, 1);
  4944. except
  4945. Result := False;
  4946. end;
  4947. end;
  4948. function PeInsertSection64(ImageStream: TMemoryStream): Boolean;
  4949. var
  4950. NtHeaders: PImageNtHeaders64;
  4951. Sections, LastSection, NewSection: PImageSectionHeader;
  4952. VirtualAlignedSize: DWORD;
  4953. I, X, NeedFill: Integer;
  4954. SectionDataSize: Integer;
  4955. UTF8Name: TUTF8String;
  4956. begin
  4957. Result := True;
  4958. try
  4959. SectionDataSize := SectionStream.Size;
  4960. NtHeaders := PeMapImgNtHeaders64(ImageStream.Memory);
  4961. Assert(NtHeaders <> nil);
  4962. Sections := PeMapImgSections64(NtHeaders);
  4963. Assert(Sections <> nil);
  4964. // Check whether there is not a section with the name already. If so, return True (#0000069)
  4965. if PeMapImgFindSection64(NtHeaders, SectionName) <> nil then
  4966. begin
  4967. Result := True;
  4968. Exit;
  4969. end;
  4970. LastSection := Sections;
  4971. Inc(LastSection, NtHeaders^.FileHeader.NumberOfSections - 1);
  4972. NewSection := LastSection;
  4973. Inc(NewSection);
  4974. // Increase the number of sections
  4975. Inc(NtHeaders^.FileHeader.NumberOfSections);
  4976. ResetMemory(NewSection^, SizeOf(TImageSectionHeader));
  4977. // JCLDEBUG Virtual Address
  4978. NewSection^.VirtualAddress := LastSection^.VirtualAddress + LastSection^.Misc.VirtualSize;
  4979. RoundUpToAlignment(NewSection^.VirtualAddress, NtHeaders^.OptionalHeader.SectionAlignment);
  4980. // JCLDEBUG Physical Offset
  4981. NewSection^.PointerToRawData := LastSection^.PointerToRawData + LastSection^.SizeOfRawData;
  4982. RoundUpToAlignment(NewSection^.PointerToRawData, NtHeaders^.OptionalHeader.FileAlignment);
  4983. // JCLDEBUG Section name
  4984. if not TryStringToUTF8(SectionName, UTF8Name) then
  4985. UTF8Name := TUTF8String(SectionName);
  4986. StrPLCopyA(PAnsiChar(@NewSection^.Name), UTF8Name, IMAGE_SIZEOF_SHORT_NAME);
  4987. // JCLDEBUG Characteristics flags
  4988. NewSection^.Characteristics := IMAGE_SCN_MEM_READ or IMAGE_SCN_CNT_INITIALIZED_DATA;
  4989. // Size of virtual data area
  4990. NewSection^.Misc.VirtualSize := SectionDataSize;
  4991. VirtualAlignedSize := SectionDataSize;
  4992. RoundUpToAlignment(VirtualAlignedSize, NtHeaders^.OptionalHeader.SectionAlignment);
  4993. // Update Size of Image
  4994. Inc(NtHeaders^.OptionalHeader.SizeOfImage, VirtualAlignedSize);
  4995. // Raw data size
  4996. NewSection^.SizeOfRawData := SectionDataSize;
  4997. RoundUpToAlignment(NewSection^.SizeOfRawData, NtHeaders^.OptionalHeader.FileAlignment);
  4998. // Update Initialized data size
  4999. Inc(NtHeaders^.OptionalHeader.SizeOfInitializedData, NewSection^.SizeOfRawData);
  5000. // Fill data to alignment
  5001. NeedFill := INT_PTR(NewSection^.SizeOfRawData) - SectionDataSize;
  5002. // Note: Delphi linker seems to generate incorrect (unaligned) size of
  5003. // the executable when adding TD32 debug data so the position could be
  5004. // behind the size of the file then.
  5005. ImageStream.Seek(NewSection^.PointerToRawData, soBeginning);
  5006. ImageStream.CopyFrom(SectionStream, 0);
  5007. X := 0;
  5008. for I := 1 to NeedFill do
  5009. ImageStream.WriteBuffer(X, 1);
  5010. except
  5011. Result := False;
  5012. end;
  5013. end;
  5014. var
  5015. ImageStream: TMemoryStream;
  5016. begin
  5017. Result := Assigned(SectionStream) and (SectionName <> '');
  5018. if not Result then
  5019. Exit;
  5020. ImageStream := TMemoryStream.Create;
  5021. try
  5022. ImageStream.LoadFromFile(FileName);
  5023. case PeMapImgTarget(ImageStream.Memory) of
  5024. taWin32:
  5025. Result := PeInsertSection32(ImageStream);
  5026. taWin64:
  5027. Result := PeInsertSection64(ImageStream);
  5028. //taUnknown:
  5029. else
  5030. Result := False;
  5031. end;
  5032. if Result then
  5033. ImageStream.SaveToFile(FileName);
  5034. finally
  5035. ImageStream.Free;
  5036. end;
  5037. end;
  5038. function PeVerifyCheckSum(const FileName: TFileName): Boolean;
  5039. begin
  5040. with CreatePeImage(FileName) do
  5041. try
  5042. Result := VerifyCheckSum;
  5043. finally
  5044. Free;
  5045. end;
  5046. end;
  5047. function PeClearCheckSum(const FileName: TFileName): Boolean;
  5048. function PeClearCheckSum32(ModuleAddress: Pointer): Boolean;
  5049. var
  5050. Headers: PImageNtHeaders32;
  5051. begin
  5052. Headers := PeMapImgNtHeaders32(ModuleAddress);
  5053. Result := (Headers <> nil);
  5054. if Result then
  5055. Headers^.OptionalHeader.CheckSum := 0;
  5056. end;
  5057. function PeClearCheckSum64(ModuleAddress: Pointer): Boolean;
  5058. var
  5059. Headers: PImageNtHeaders64;
  5060. begin
  5061. Headers := PeMapImgNtHeaders64(ModuleAddress);
  5062. Result := (Headers <> nil);
  5063. if Result then
  5064. Headers^.OptionalHeader.CheckSum := 0;
  5065. end;
  5066. var
  5067. Mapping: TJclFileMapping;
  5068. View: TJclFileMappingView;
  5069. begin
  5070. Mapping := TJclFileMapping.Create(FileName, fmOpenReadWrite, '', PAGE_READWRITE, 0, nil);
  5071. try
  5072. View := TJclFileMappingView.Create(Mapping, FILE_MAP_WRITE, 0, 0);
  5073. case PeMapImgTarget(View.Memory) of
  5074. taWin32:
  5075. Result := PeClearCheckSum32(View.Memory);
  5076. taWin64:
  5077. Result := PeClearCheckSum64(View.Memory);
  5078. //taUnknown:
  5079. else
  5080. Result := False;
  5081. end;
  5082. finally
  5083. Mapping.Free;
  5084. end;
  5085. end;
  5086. function PeUpdateCheckSum(const FileName: TFileName): Boolean;
  5087. var
  5088. LI: TLoadedImage;
  5089. begin
  5090. LI.ModuleName := nil;
  5091. // OF: possible loss of data
  5092. Result := MapAndLoad(PAnsiChar(AnsiString(FileName)), nil, LI, True, False);
  5093. if Result then
  5094. Result := UnMapAndLoad(LI);
  5095. end;
  5096. // Various simple PE Image searching and listing routines
  5097. function PeDoesExportFunction(const FileName: TFileName; const FunctionName: string;
  5098. Options: TJclSmartCompOptions): Boolean;
  5099. begin
  5100. with CreatePeImage(FileName) do
  5101. try
  5102. Result := StatusOK and Assigned(ExportList.SmartFindName(FunctionName, Options));
  5103. finally
  5104. Free;
  5105. end;
  5106. end;
  5107. function PeIsExportFunctionForwardedEx(const FileName: TFileName; const FunctionName: string;
  5108. out ForwardedName: string; Options: TJclSmartCompOptions): Boolean;
  5109. var
  5110. ExportItem: TJclPeExportFuncItem;
  5111. begin
  5112. with CreatePeImage(FileName) do
  5113. try
  5114. Result := StatusOK;
  5115. if Result then
  5116. begin
  5117. ExportItem := ExportList.SmartFindName(FunctionName, Options);
  5118. if ExportItem <> nil then
  5119. begin
  5120. Result := ExportItem.IsForwarded;
  5121. ForwardedName := ExportItem.ForwardedName;
  5122. end
  5123. else
  5124. begin
  5125. Result := False;
  5126. ForwardedName := '';
  5127. end;
  5128. end;
  5129. finally
  5130. Free;
  5131. end;
  5132. end;
  5133. function PeIsExportFunctionForwarded(const FileName: TFileName; const FunctionName: string;
  5134. Options: TJclSmartCompOptions): Boolean;
  5135. var
  5136. Dummy: string;
  5137. begin
  5138. Result := PeIsExportFunctionForwardedEx(FileName, FunctionName, Dummy, Options);
  5139. end;
  5140. function PeDoesImportFunction(const FileName: TFileName; const FunctionName: string;
  5141. const LibraryName: string; Options: TJclSmartCompOptions): Boolean;
  5142. begin
  5143. with CreatePeImage(FileName) do
  5144. try
  5145. Result := StatusOK;
  5146. if Result then
  5147. with ImportList do
  5148. begin
  5149. TryGetNamesForOrdinalImports;
  5150. Result := SmartFindName(FunctionName, LibraryName, Options) <> nil;
  5151. end;
  5152. finally
  5153. Free;
  5154. end;
  5155. end;
  5156. function PeDoesImportLibrary(const FileName: TFileName; const LibraryName: string;
  5157. Recursive: Boolean): Boolean;
  5158. var
  5159. SL: TStringList;
  5160. begin
  5161. with CreatePeImage(FileName) do
  5162. try
  5163. Result := StatusOK;
  5164. if Result then
  5165. begin
  5166. SL := InternalImportedLibraries(FileName, Recursive, False, nil);
  5167. try
  5168. Result := SL.IndexOf(LibraryName) > -1;
  5169. finally
  5170. SL.Free;
  5171. end;
  5172. end;
  5173. finally
  5174. Free;
  5175. end;
  5176. end;
  5177. function PeImportedLibraries(const FileName: TFileName; const LibrariesList: TStrings;
  5178. Recursive, FullPathName: Boolean): Boolean;
  5179. var
  5180. SL: TStringList;
  5181. begin
  5182. with CreatePeImage(FileName) do
  5183. try
  5184. Result := StatusOK;
  5185. if Result then
  5186. begin
  5187. SL := InternalImportedLibraries(FileName, Recursive, FullPathName, nil);
  5188. try
  5189. LibrariesList.Assign(SL);
  5190. finally
  5191. SL.Free;
  5192. end;
  5193. end;
  5194. finally
  5195. Free;
  5196. end;
  5197. end;
  5198. function PeImportedFunctions(const FileName: TFileName; const FunctionsList: TStrings;
  5199. const LibraryName: string; IncludeLibNames: Boolean): Boolean;
  5200. var
  5201. I: Integer;
  5202. begin
  5203. with CreatePeImage(FileName) do
  5204. try
  5205. Result := StatusOK;
  5206. if Result then
  5207. with ImportList do
  5208. begin
  5209. TryGetNamesForOrdinalImports;
  5210. FunctionsList.BeginUpdate;
  5211. try
  5212. for I := 0 to AllItemCount - 1 do
  5213. with AllItems[I] do
  5214. if ((Length(LibraryName) = 0) or StrSame(ImportLib.Name, LibraryName)) and
  5215. (Name <> '') then
  5216. begin
  5217. if IncludeLibNames then
  5218. FunctionsList.Add(ImportLib.Name + '=' + Name)
  5219. else
  5220. FunctionsList.Add(Name);
  5221. end;
  5222. finally
  5223. FunctionsList.EndUpdate;
  5224. end;
  5225. end;
  5226. finally
  5227. Free;
  5228. end;
  5229. end;
  5230. function PeExportedFunctions(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
  5231. var
  5232. I: Integer;
  5233. begin
  5234. with CreatePeImage(FileName) do
  5235. try
  5236. Result := StatusOK;
  5237. if Result then
  5238. begin
  5239. FunctionsList.BeginUpdate;
  5240. try
  5241. with ExportList do
  5242. for I := 0 to Count - 1 do
  5243. with Items[I] do
  5244. if not IsExportedVariable then
  5245. FunctionsList.Add(Name);
  5246. finally
  5247. FunctionsList.EndUpdate;
  5248. end;
  5249. end;
  5250. finally
  5251. Free;
  5252. end;
  5253. end;
  5254. function PeExportedNames(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
  5255. var
  5256. I: Integer;
  5257. begin
  5258. with CreatePeImage(FileName) do
  5259. try
  5260. Result := StatusOK;
  5261. if Result then
  5262. begin
  5263. FunctionsList.BeginUpdate;
  5264. try
  5265. with ExportList do
  5266. for I := 0 to Count - 1 do
  5267. FunctionsList.Add(Items[I].Name);
  5268. finally
  5269. FunctionsList.EndUpdate;
  5270. end;
  5271. end;
  5272. finally
  5273. Free;
  5274. end;
  5275. end;
  5276. function PeExportedVariables(const FileName: TFileName; const FunctionsList: TStrings): Boolean;
  5277. var
  5278. I: Integer;
  5279. begin
  5280. with CreatePeImage(FileName) do
  5281. try
  5282. Result := StatusOK;
  5283. if Result then
  5284. begin
  5285. FunctionsList.BeginUpdate;
  5286. try
  5287. with ExportList do
  5288. for I := 0 to Count - 1 do
  5289. with Items[I] do
  5290. if IsExportedVariable then
  5291. FunctionsList.AddObject(Name, Pointer(Address));
  5292. finally
  5293. FunctionsList.EndUpdate;
  5294. end;
  5295. end;
  5296. finally
  5297. Free;
  5298. end;
  5299. end;
  5300. function PeResourceKindNames(const FileName: TFileName; ResourceType: TJclPeResourceKind;
  5301. const NamesList: TStrings): Boolean;
  5302. begin
  5303. with CreatePeImage(FileName) do
  5304. try
  5305. Result := StatusOK and ResourceList.ListResourceNames(ResourceType, NamesList);
  5306. finally
  5307. Free;
  5308. end;
  5309. end;
  5310. {$IFDEF BORLAND}
  5311. function PeBorFormNames(const FileName: TFileName; const NamesList: TStrings): Boolean;
  5312. var
  5313. I: Integer;
  5314. BorImage: TJclPeBorImage;
  5315. BorForm: TJclPeBorForm;
  5316. begin
  5317. BorImage := TJclPeBorImage.Create(True);
  5318. try
  5319. BorImage.FileName := FileName;
  5320. Result := BorImage.IsBorlandImage;
  5321. if Result then
  5322. begin
  5323. NamesList.BeginUpdate;
  5324. try
  5325. for I := 0 to BorImage.FormCount - 1 do
  5326. begin
  5327. BorForm := BorImage.Forms[I];
  5328. NamesList.AddObject(BorForm.DisplayName, Pointer(BorForm.ResItem.RawEntryDataSize));
  5329. end;
  5330. finally
  5331. NamesList.EndUpdate;
  5332. end;
  5333. end;
  5334. finally
  5335. BorImage.Free;
  5336. end;
  5337. end;
  5338. function PeBorDependedPackages(const FileName: TFileName; PackagesList: TStrings;
  5339. FullPathName, Descriptions: Boolean): Boolean;
  5340. var
  5341. BorImage: TJclPeBorImage;
  5342. begin
  5343. BorImage := TJclPeBorImage.Create(True);
  5344. try
  5345. BorImage.FileName := FileName;
  5346. Result := BorImage.DependedPackages(PackagesList, FullPathName, Descriptions);
  5347. finally
  5348. BorImage.Free;
  5349. end;
  5350. end;
  5351. {$ENDIF BORLAND}
  5352. // Missing imports checking routines
  5353. function PeFindMissingImports(const FileName: TFileName; MissingImportsList: TStrings): Boolean;
  5354. var
  5355. Cache: TJclPeImagesCache;
  5356. FileImage, LibImage: TJclPeImage;
  5357. L, I: Integer;
  5358. LibItem: TJclPeImportLibItem;
  5359. List: TStringList;
  5360. begin
  5361. Result := False;
  5362. List := nil;
  5363. Cache := TJclPeImagesCache.Create;
  5364. try
  5365. List := TStringList.Create;
  5366. List.Duplicates := dupIgnore;
  5367. List.Sorted := True;
  5368. FileImage := Cache[FileName];
  5369. if FileImage.StatusOK then
  5370. begin
  5371. for L := 0 to FileImage.ImportList.Count - 1 do
  5372. begin
  5373. LibItem := FileImage.ImportList[L];
  5374. LibImage := Cache[LibItem.FileName];
  5375. if LibImage.StatusOK then
  5376. begin
  5377. LibImage.ExportList.PrepareForFastNameSearch;
  5378. for I := 0 to LibItem.Count - 1 do
  5379. if LibImage.ExportList.ItemFromName[LibItem[I].Name] = nil then
  5380. List.Add(LibItem.Name + '=' + LibItem[I].Name);
  5381. end
  5382. else
  5383. List.Add(LibItem.Name + '=');
  5384. end;
  5385. MissingImportsList.Assign(List);
  5386. Result := List.Count > 0;
  5387. end;
  5388. finally
  5389. List.Free;
  5390. Cache.Free;
  5391. end;
  5392. end;
  5393. function PeFindMissingImports(RequiredImportsList, MissingImportsList: TStrings): Boolean;
  5394. var
  5395. Cache: TJclPeImagesCache;
  5396. LibImage: TJclPeImage;
  5397. I, SepPos: Integer;
  5398. List: TStringList;
  5399. S, LibName, ImportName: string;
  5400. begin
  5401. List := nil;
  5402. Cache := TJclPeImagesCache.Create;
  5403. try
  5404. List := TStringList.Create;
  5405. List.Duplicates := dupIgnore;
  5406. List.Sorted := True;
  5407. for I := 0 to RequiredImportsList.Count - 1 do
  5408. begin
  5409. S := RequiredImportsList[I];
  5410. SepPos := Pos('=', S);
  5411. if SepPos = 0 then
  5412. Continue;
  5413. LibName := StrLeft(S, SepPos - 1);
  5414. LibImage := Cache[LibName];
  5415. if LibImage.StatusOK then
  5416. begin
  5417. LibImage.ExportList.PrepareForFastNameSearch;
  5418. ImportName := StrRestOf(S, SepPos + 1);
  5419. if LibImage.ExportList.ItemFromName[ImportName] = nil then
  5420. List.Add(LibName + '=' + ImportName);
  5421. end
  5422. else
  5423. List.Add(LibName + '=');
  5424. end;
  5425. MissingImportsList.Assign(List);
  5426. Result := List.Count > 0;
  5427. finally
  5428. List.Free;
  5429. Cache.Free;
  5430. end;
  5431. end;
  5432. function PeCreateRequiredImportList(const FileName: TFileName; RequiredImportsList: TStrings): Boolean;
  5433. begin
  5434. Result := PeImportedFunctions(FileName, RequiredImportsList, '', True);
  5435. end;
  5436. // Mapped or loaded image related functions
  5437. function PeMapImgNtHeaders32(const BaseAddress: Pointer): PImageNtHeaders32;
  5438. begin
  5439. Result := nil;
  5440. if IsBadReadPtr(BaseAddress, SizeOf(TImageDosHeader)) then
  5441. Exit;
  5442. if (PImageDosHeader(BaseAddress)^.e_magic <> IMAGE_DOS_SIGNATURE) or
  5443. (PImageDosHeader(BaseAddress)^._lfanew = 0) then
  5444. Exit;
  5445. Result := PImageNtHeaders32(TJclAddr(BaseAddress) + DWORD(PImageDosHeader(BaseAddress)^._lfanew));
  5446. if IsBadReadPtr(Result, SizeOf(TImageNtHeaders32)) or
  5447. (Result^.Signature <> IMAGE_NT_SIGNATURE) then
  5448. Result := nil
  5449. end;
  5450. function PeMapImgNtHeaders32(Stream: TStream; const BasePosition: Int64; out NtHeaders32: TImageNtHeaders32): Int64;
  5451. var
  5452. ImageDosHeader: TImageDosHeader;
  5453. begin
  5454. ResetMemory(NtHeaders32, SizeOf(NtHeaders32));
  5455. Result := -1;
  5456. if (Stream.Seek(BasePosition, soBeginning) <> BasePosition) or
  5457. (Stream.Read(ImageDosHeader, SizeOf(ImageDosHeader)) <> SizeOf(ImageDosHeader)) then
  5458. raise EJclPeImageError.CreateRes(@SReadError);
  5459. if (ImageDosHeader.e_magic <> IMAGE_DOS_SIGNATURE) or
  5460. (ImageDosHeader._lfanew = 0) then
  5461. Exit;
  5462. Result := BasePosition + DWORD(ImageDosHeader._lfanew);
  5463. if (Stream.Seek(Result, soBeginning) <> Result) or
  5464. (Stream.Read(NtHeaders32, SizeOf(NtHeaders32)) <> SizeOf(NtHeaders32)) then
  5465. raise EJclPeImageError.CreateRes(@SReadError);
  5466. if NtHeaders32.Signature <> IMAGE_NT_SIGNATURE then
  5467. Result := -1;
  5468. end;
  5469. function PeMapImgNtHeaders64(const BaseAddress: Pointer): PImageNtHeaders64;
  5470. begin
  5471. Result := nil;
  5472. if IsBadReadPtr(BaseAddress, SizeOf(TImageDosHeader)) then
  5473. Exit;
  5474. if (PImageDosHeader(BaseAddress)^.e_magic <> IMAGE_DOS_SIGNATURE) or
  5475. (PImageDosHeader(BaseAddress)^._lfanew = 0) then
  5476. Exit;
  5477. Result := PImageNtHeaders64(TJclAddr(BaseAddress) + DWORD(PImageDosHeader(BaseAddress)^._lfanew));
  5478. if IsBadReadPtr(Result, SizeOf(TImageNtHeaders64)) or
  5479. (Result^.Signature <> IMAGE_NT_SIGNATURE) then
  5480. Result := nil
  5481. end;
  5482. function PeMapImgNtHeaders64(Stream: TStream; const BasePosition: Int64; out NtHeaders64: TImageNtHeaders64): Int64;
  5483. var
  5484. ImageDosHeader: TImageDosHeader;
  5485. begin
  5486. ResetMemory(NtHeaders64, SizeOf(NtHeaders64));
  5487. Result := -1;
  5488. if (Stream.Seek(BasePosition, soBeginning) <> BasePosition) or
  5489. (Stream.Read(ImageDosHeader, SizeOf(ImageDosHeader)) <> SizeOf(ImageDosHeader)) then
  5490. raise EJclPeImageError.CreateRes(@SReadError);
  5491. if (ImageDosHeader.e_magic <> IMAGE_DOS_SIGNATURE) or
  5492. (ImageDosHeader._lfanew = 0) then
  5493. Exit;
  5494. Result := BasePosition + DWORD(ImageDosHeader._lfanew);
  5495. if (Stream.Seek(Result, soBeginning) <> Result) or
  5496. (Stream.Read(NtHeaders64, SizeOf(NtHeaders64)) <> SizeOf(NtHeaders64)) then
  5497. raise EJclPeImageError.CreateRes(@SReadError);
  5498. if NtHeaders64.Signature <> IMAGE_NT_SIGNATURE then
  5499. Result := -1;
  5500. end;
  5501. function PeMapImgSize(const BaseAddress: Pointer): DWORD;
  5502. begin
  5503. case PeMapImgTarget(BaseAddress) of
  5504. taWin32:
  5505. Result := PeMapImgSize32(BaseAddress);
  5506. taWin64:
  5507. Result := PeMapImgSize64(BaseAddress);
  5508. //taUnknown:
  5509. else
  5510. Result := 0;
  5511. end;
  5512. end;
  5513. function PeMapImgSize(Stream: TStream; const BasePosition: Int64): DWORD;
  5514. begin
  5515. case PeMapImgTarget(Stream, BasePosition) of
  5516. taWin32:
  5517. Result := PeMapImgSize32(Stream, BasePosition);
  5518. taWin64:
  5519. Result := PeMapImgSize64(Stream, BasePosition);
  5520. //taUnknown:
  5521. else
  5522. Result := 0;
  5523. end;
  5524. end;
  5525. function PeMapImgSize32(const BaseAddress: Pointer): DWORD;
  5526. var
  5527. NtHeaders32: PImageNtHeaders32;
  5528. begin
  5529. Result := 0;
  5530. NtHeaders32 := PeMapImgNtHeaders32(BaseAddress);
  5531. if Assigned(NtHeaders32) then
  5532. Result := NtHeaders32^.OptionalHeader.SizeOfImage;
  5533. end;
  5534. function PeMapImgSize32(Stream: TStream; const BasePosition: Int64): DWORD;
  5535. var
  5536. NtHeaders32: TImageNtHeaders32;
  5537. begin
  5538. Result := 0;
  5539. if PeMapImgNtHeaders32(Stream, BasePosition, NtHeaders32) <> -1 then
  5540. Result := NtHeaders32.OptionalHeader.SizeOfImage;
  5541. end;
  5542. function PeMapImgSize64(const BaseAddress: Pointer): DWORD;
  5543. var
  5544. NtHeaders64: PImageNtHeaders64;
  5545. begin
  5546. Result := 0;
  5547. NtHeaders64 := PeMapImgNtHeaders64(BaseAddress);
  5548. if Assigned(NtHeaders64) then
  5549. Result := NtHeaders64^.OptionalHeader.SizeOfImage;
  5550. end;
  5551. function PeMapImgSize64(Stream: TStream; const BasePosition: Int64): DWORD;
  5552. var
  5553. NtHeaders64: TImageNtHeaders64;
  5554. begin
  5555. Result := 0;
  5556. if PeMapImgNtHeaders64(Stream, BasePosition, NtHeaders64) <> -1 then
  5557. Result := NtHeaders64.OptionalHeader.SizeOfImage;
  5558. end;
  5559. function PeMapImgLibraryName(const BaseAddress: Pointer): string;
  5560. begin
  5561. case PeMapImgTarget(BaseAddress) of
  5562. taWin32:
  5563. Result := PeMapImgLibraryName32(BaseAddress);
  5564. taWin64:
  5565. Result := PeMapImgLibraryName64(BaseAddress);
  5566. //taUnknown:
  5567. else
  5568. Result := '';
  5569. end;
  5570. end;
  5571. function PeMapImgLibraryName32(const BaseAddress: Pointer): string;
  5572. var
  5573. NtHeaders: PImageNtHeaders32;
  5574. DataDir: TImageDataDirectory;
  5575. ExportDir: PImageExportDirectory;
  5576. UTF8Name: TUTF8String;
  5577. begin
  5578. Result := '';
  5579. NtHeaders := PeMapImgNtHeaders32(BaseAddress);
  5580. if NtHeaders = nil then
  5581. Exit;
  5582. DataDir := NtHeaders^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
  5583. if DataDir.Size = 0 then
  5584. Exit;
  5585. ExportDir := PImageExportDirectory(TJclAddr(BaseAddress) + DataDir.VirtualAddress);
  5586. if IsBadReadPtr(ExportDir, SizeOf(TImageExportDirectory)) or (ExportDir^.Name = 0) then
  5587. Exit;
  5588. UTF8Name := PAnsiChar(TJclAddr(BaseAddress) + ExportDir^.Name);
  5589. if not TryUTF8ToString(UTF8Name, Result) then
  5590. Result := string(UTF8Name);
  5591. end;
  5592. function PeMapImgLibraryName64(const BaseAddress: Pointer): string;
  5593. var
  5594. NtHeaders: PImageNtHeaders64;
  5595. DataDir: TImageDataDirectory;
  5596. ExportDir: PImageExportDirectory;
  5597. UTF8Name: TUTF8String;
  5598. begin
  5599. Result := '';
  5600. NtHeaders := PeMapImgNtHeaders64(BaseAddress);
  5601. if NtHeaders = nil then
  5602. Exit;
  5603. DataDir := NtHeaders^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
  5604. if DataDir.Size = 0 then
  5605. Exit;
  5606. ExportDir := PImageExportDirectory(TJclAddr(BaseAddress) + DataDir.VirtualAddress);
  5607. if IsBadReadPtr(ExportDir, SizeOf(TImageExportDirectory)) or (ExportDir^.Name = 0) then
  5608. Exit;
  5609. UTF8Name := PAnsiChar(TJclAddr(BaseAddress) + ExportDir^.Name);
  5610. if not TryUTF8ToString(UTF8Name, Result) then
  5611. Result := string(UTF8Name);
  5612. end;
  5613. function PeMapImgTarget(const BaseAddress: Pointer): TJclPeTarget;
  5614. var
  5615. ImageNtHeaders: PImageNtHeaders32;
  5616. begin
  5617. Result := taUnknown;
  5618. ImageNtHeaders := PeMapImgNtHeaders32(BaseAddress);
  5619. if Assigned(ImageNtHeaders) then
  5620. case ImageNtHeaders.FileHeader.Machine of
  5621. IMAGE_FILE_MACHINE_I386:
  5622. Result := taWin32;
  5623. IMAGE_FILE_MACHINE_AMD64:
  5624. Result := taWin64;
  5625. end;
  5626. end;
  5627. function PeMapImgTarget(Stream: TStream; const BasePosition: Int64): TJclPeTarget;
  5628. var
  5629. ImageNtHeaders: TImageNtHeaders32;
  5630. begin
  5631. Result := taUnknown;
  5632. if PeMapImgNtHeaders32(Stream, BasePosition, ImageNtHeaders) <> -1 then
  5633. begin
  5634. case ImageNtHeaders.FileHeader.Machine of
  5635. IMAGE_FILE_MACHINE_I386:
  5636. Result := taWin32;
  5637. IMAGE_FILE_MACHINE_AMD64:
  5638. Result := taWin64;
  5639. end;
  5640. end;
  5641. end;
  5642. function PeMapImgSections32(NtHeaders: PImageNtHeaders32): PImageSectionHeader;
  5643. begin
  5644. if NtHeaders = nil then
  5645. Result := nil
  5646. else
  5647. Result := PImageSectionHeader(TJclAddr(@NtHeaders^.OptionalHeader) +
  5648. NtHeaders^.FileHeader.SizeOfOptionalHeader);
  5649. end;
  5650. function PeMapImgSections32(Stream: TStream; const NtHeaders32Position: Int64; const NtHeaders32: TImageNtHeaders32;
  5651. out ImageSectionHeaders: TImageSectionHeaderArray): Int64;
  5652. var
  5653. SectionSize: Integer;
  5654. begin
  5655. if NtHeaders32Position = -1 then
  5656. begin
  5657. SetLength(ImageSectionHeaders, 0);
  5658. Result := -1;
  5659. end
  5660. else
  5661. begin
  5662. SetLength(ImageSectionHeaders, NtHeaders32.FileHeader.NumberOfSections);
  5663. Result := NtHeaders32Position + SizeOf(NtHeaders32.Signature) + SizeOf(NtHeaders32.FileHeader) + NtHeaders32.FileHeader.SizeOfOptionalHeader;
  5664. SectionSize := SizeOf(ImageSectionHeaders[0]) * Length(ImageSectionHeaders);
  5665. if (Stream.Seek(Result, soBeginning) <> Result) or
  5666. (Stream.Read(ImageSectionHeaders[0], SectionSize) <> SectionSize) then
  5667. raise EJclPeImageError.CreateRes(@SReadError);
  5668. end;
  5669. end;
  5670. function PeMapImgSections64(NtHeaders: PImageNtHeaders64): PImageSectionHeader;
  5671. begin
  5672. if NtHeaders = nil then
  5673. Result := nil
  5674. else
  5675. Result := PImageSectionHeader(TJclAddr(@NtHeaders^.OptionalHeader) +
  5676. NtHeaders^.FileHeader.SizeOfOptionalHeader);
  5677. end;
  5678. function PeMapImgSections64(Stream: TStream; const NtHeaders64Position: Int64; const NtHeaders64: TImageNtHeaders64;
  5679. out ImageSectionHeaders: TImageSectionHeaderArray): Int64;
  5680. var
  5681. SectionSize: Integer;
  5682. begin
  5683. if NtHeaders64Position = -1 then
  5684. begin
  5685. SetLength(ImageSectionHeaders, 0);
  5686. Result := -1;
  5687. end
  5688. else
  5689. begin
  5690. SetLength(ImageSectionHeaders, NtHeaders64.FileHeader.NumberOfSections);
  5691. Result := NtHeaders64Position + SizeOf(NtHeaders64.Signature) + SizeOf(NtHeaders64.FileHeader) + NtHeaders64.FileHeader.SizeOfOptionalHeader;
  5692. SectionSize := SizeOf(ImageSectionHeaders[0]) * Length(ImageSectionHeaders);
  5693. if (Stream.Seek(Result, soBeginning) <> Result) or
  5694. (Stream.Read(ImageSectionHeaders[0], SectionSize) <> SectionSize) then
  5695. raise EJclPeImageError.CreateRes(@SReadError);
  5696. end;
  5697. end;
  5698. function PeMapImgFindSection32(NtHeaders: PImageNtHeaders32;
  5699. const SectionName: string): PImageSectionHeader;
  5700. var
  5701. Header: PImageSectionHeader;
  5702. I: Integer;
  5703. P: PAnsiChar;
  5704. UTF8Name: TUTF8String;
  5705. begin
  5706. Result := nil;
  5707. if NtHeaders <> nil then
  5708. begin
  5709. if not TryStringToUTF8(SectionName, UTF8Name) then
  5710. UTF8Name := TUTF8String(SectionName);
  5711. P := PAnsiChar(UTF8Name);
  5712. Header := PeMapImgSections32(NtHeaders);
  5713. for I := 1 to NtHeaders^.FileHeader.NumberOfSections do
  5714. if StrLCompA(PAnsiChar(@Header^.Name), P, IMAGE_SIZEOF_SHORT_NAME) = 0 then
  5715. begin
  5716. Result := Header;
  5717. Break;
  5718. end
  5719. else
  5720. Inc(Header);
  5721. end;
  5722. end;
  5723. function PeMapImgFindSection64(NtHeaders: PImageNtHeaders64;
  5724. const SectionName: string): PImageSectionHeader;
  5725. var
  5726. Header: PImageSectionHeader;
  5727. I: Integer;
  5728. P: PAnsiChar;
  5729. UTF8Name: TUTF8String;
  5730. begin
  5731. Result := nil;
  5732. if NtHeaders <> nil then
  5733. begin
  5734. if not TryStringToUTF8(SectionName, UTF8Name) then
  5735. UTF8Name := TUTF8String(SectionName);
  5736. P := PAnsiChar(UTF8Name);
  5737. Header := PeMapImgSections64(NtHeaders);
  5738. for I := 1 to NtHeaders^.FileHeader.NumberOfSections do
  5739. if StrLCompA(PAnsiChar(@Header^.Name), P, IMAGE_SIZEOF_SHORT_NAME) = 0 then
  5740. begin
  5741. Result := Header;
  5742. Break;
  5743. end
  5744. else
  5745. Inc(Header);
  5746. end;
  5747. end;
  5748. function PeMapImgFindSection(const ImageSectionHeaders: TImageSectionHeaderArray;
  5749. const SectionName: string): SizeInt;
  5750. var
  5751. P: PAnsiChar;
  5752. UTF8Name: TUTF8String;
  5753. begin
  5754. if Length(ImageSectionHeaders) > 0 then
  5755. begin
  5756. if not TryStringToUTF8(SectionName, UTF8Name) then
  5757. UTF8Name := TUTF8String(SectionName);
  5758. P := PAnsiChar(UTF8Name);
  5759. for Result := Low(ImageSectionHeaders) to High(ImageSectionHeaders) do
  5760. if StrLCompA(PAnsiChar(@ImageSectionHeaders[Result].Name), P, IMAGE_SIZEOF_SHORT_NAME) = 0 then
  5761. Exit;
  5762. end;
  5763. Result := -1;
  5764. end;
  5765. function PeMapImgFindSectionFromModule(const BaseAddress: Pointer;
  5766. const SectionName: string): PImageSectionHeader;
  5767. function PeMapImgFindSectionFromModule32(const BaseAddress: Pointer;
  5768. const SectionName: string): PImageSectionHeader;
  5769. var
  5770. NtHeaders32: PImageNtHeaders32;
  5771. begin
  5772. Result := nil;
  5773. NtHeaders32 := PeMapImgNtHeaders32(BaseAddress);
  5774. if Assigned(NtHeaders32) then
  5775. Result := PeMapImgFindSection32(NtHeaders32, SectionName);
  5776. end;
  5777. function PeMapImgFindSectionFromModule64(const BaseAddress: Pointer;
  5778. const SectionName: string): PImageSectionHeader;
  5779. var
  5780. NtHeaders64: PImageNtHeaders64;
  5781. begin
  5782. Result := nil;
  5783. NtHeaders64 := PeMapImgNtHeaders64(BaseAddress);
  5784. if Assigned(NtHeaders64) then
  5785. Result := PeMapImgFindSection64(NtHeaders64, SectionName);
  5786. end;
  5787. begin
  5788. case PeMapImgTarget(BaseAddress) of
  5789. taWin32:
  5790. Result := PeMapImgFindSectionFromModule32(BaseAddress, SectionName);
  5791. taWin64:
  5792. Result := PeMapImgFindSectionFromModule64(BaseAddress, SectionName);
  5793. //taUnknown:
  5794. else
  5795. Result := nil;
  5796. end;
  5797. end;
  5798. function PeMapImgExportedVariables(const Module: HMODULE; const VariablesList: TStrings): Boolean;
  5799. var
  5800. I: Integer;
  5801. begin
  5802. with TJclPeImage.Create(True) do
  5803. try
  5804. AttachLoadedModule(Module);
  5805. Result := StatusOK;
  5806. if Result then
  5807. begin
  5808. VariablesList.BeginUpdate;
  5809. try
  5810. with ExportList do
  5811. for I := 0 to Count - 1 do
  5812. with Items[I] do
  5813. if IsExportedVariable then
  5814. VariablesList.AddObject(Name, MappedAddress);
  5815. finally
  5816. VariablesList.EndUpdate;
  5817. end;
  5818. end;
  5819. finally
  5820. Free;
  5821. end;
  5822. end;
  5823. function PeMapImgResolvePackageThunk(Address: Pointer): Pointer;
  5824. {$IFDEF BORLAND}
  5825. const
  5826. JmpInstructionCode = $25FF;
  5827. type
  5828. PPackageThunk = ^TPackageThunk;
  5829. TPackageThunk = packed record
  5830. JmpInstruction: Word;
  5831. {$IFDEF CPU32}
  5832. JmpAddress: PPointer;
  5833. {$ENDIF CPU32}
  5834. {$IFDEF CPU64}
  5835. JmpOffset: Int32;
  5836. {$ENDIF CPU64}
  5837. end;
  5838. begin
  5839. if not IsCompiledWithPackages then
  5840. Result := Address
  5841. else
  5842. if not IsBadReadPtr(Address, SizeOf(TPackageThunk)) and
  5843. (PPackageThunk(Address)^.JmpInstruction = JmpInstructionCode) then
  5844. {$IFDEF CPU32}
  5845. Result := PPackageThunk(Address)^.JmpAddress^
  5846. {$ENDIF CPU32}
  5847. {$IFDEF CPU64}
  5848. Result := PPointer(PByte(Address) + SizeOf(TPackageThunk) +
  5849. PPackageThunk(Address)^.JmpOffset)^
  5850. {$ENDIF CPU64}
  5851. else
  5852. Result := nil;
  5853. end;
  5854. {$ENDIF BORLAND}
  5855. {$IFDEF FPC}
  5856. begin
  5857. Result := Address;
  5858. end;
  5859. {$ENDIF FPC}
  5860. function PeMapFindResource(const Module: HMODULE; const ResourceType: PChar;
  5861. const ResourceName: string): Pointer;
  5862. var
  5863. ResItem: TJclPeResourceItem;
  5864. begin
  5865. Result := nil;
  5866. with TJclPeImage.Create(True) do
  5867. try
  5868. AttachLoadedModule(Module);
  5869. if StatusOK then
  5870. begin
  5871. ResItem := ResourceList.FindResource(ResourceType, PChar(ResourceName));
  5872. if (ResItem <> nil) and ResItem.IsDirectory then
  5873. Result := ResItem.List[0].RawEntryData;
  5874. end;
  5875. finally
  5876. Free;
  5877. end;
  5878. end;
  5879. //=== { TJclPeSectionStream } ================================================
  5880. constructor TJclPeSectionStream.Create(Instance: HMODULE; const ASectionName: string);
  5881. begin
  5882. inherited Create;
  5883. Initialize(Instance, ASectionName);
  5884. end;
  5885. procedure TJclPeSectionStream.Initialize(Instance: HMODULE; const ASectionName: string);
  5886. var
  5887. Header: PImageSectionHeader;
  5888. NtHeaders32: PImageNtHeaders32;
  5889. NtHeaders64: PImageNtHeaders64;
  5890. DataSize: Integer;
  5891. begin
  5892. FInstance := Instance;
  5893. case PeMapImgTarget(Pointer(Instance)) of
  5894. taWin32:
  5895. begin
  5896. NtHeaders32 := PeMapImgNtHeaders32(Pointer(Instance));
  5897. if NtHeaders32 = nil then
  5898. raise EJclPeImageError.CreateRes(@RsPeNotPE);
  5899. Header := PeMapImgFindSection32(NtHeaders32, ASectionName);
  5900. end;
  5901. taWin64:
  5902. begin
  5903. NtHeaders64 := PeMapImgNtHeaders64(Pointer(Instance));
  5904. if NtHeaders64 = nil then
  5905. raise EJclPeImageError.CreateRes(@RsPeNotPE);
  5906. Header := PeMapImgFindSection64(NtHeaders64, ASectionName);
  5907. end;
  5908. //toUnknown:
  5909. else
  5910. raise EJclPeImageError.CreateRes(@RsPeUnknownTarget);
  5911. end;
  5912. if Header = nil then
  5913. raise EJclPeImageError.CreateResFmt(@RsPeSectionNotFound, [ASectionName]);
  5914. // Borland and Microsoft seems to have swapped the meaning of this items.
  5915. DataSize := Min(Header^.SizeOfRawData, Header^.Misc.VirtualSize);
  5916. SetPointer(Pointer(FInstance + Header^.VirtualAddress), DataSize);
  5917. FSectionHeader := Header^;
  5918. end;
  5919. function TJclPeSectionStream.Write(const Buffer; Count: Integer): Longint;
  5920. begin
  5921. raise EJclPeImageError.CreateRes(@RsPeReadOnlyStream);
  5922. end;
  5923. //=== { TJclPeMapImgHookItem } ===============================================
  5924. constructor TJclPeMapImgHookItem.Create(AList: TObjectList;
  5925. const AFunctionName: string; const AModuleName: string;
  5926. ABaseAddress, ANewAddress, AOriginalAddress: Pointer);
  5927. begin
  5928. inherited Create;
  5929. FList := AList;
  5930. FFunctionName := AFunctionName;
  5931. FModuleName := AModuleName;
  5932. FBaseAddress := ABaseAddress;
  5933. FNewAddress := ANewAddress;
  5934. FOriginalAddress := AOriginalAddress;
  5935. end;
  5936. destructor TJclPeMapImgHookItem.Destroy;
  5937. begin
  5938. if FBaseAddress <> nil then
  5939. InternalUnhook;
  5940. inherited Destroy;
  5941. end;
  5942. function TJclPeMapImgHookItem.InternalUnhook: Boolean;
  5943. var
  5944. Buf: TMemoryBasicInformation;
  5945. begin
  5946. Buf.AllocationBase := nil;
  5947. if (VirtualQuery(FBaseAddress, Buf, SizeOf(Buf)) = SizeOf(Buf)) and (Buf.State and MEM_FREE = 0) then
  5948. Result := TJclPeMapImgHooks.ReplaceImport(FBaseAddress, ModuleName, NewAddress, OriginalAddress)
  5949. else
  5950. Result := True; // PE image is not available anymore (DLL got unloaded)
  5951. if Result then
  5952. FBaseAddress := nil;
  5953. end;
  5954. function TJclPeMapImgHookItem.Unhook: Boolean;
  5955. begin
  5956. Result := InternalUnhook;
  5957. if Result then
  5958. FList.Remove(Self);
  5959. end;
  5960. //=== { TJclPeMapImgHooks } ==================================================
  5961. type
  5962. PWin9xDebugThunk32 = ^TWin9xDebugThunk32;
  5963. TWin9xDebugThunk32 = packed record
  5964. PUSH: Byte; // PUSH instruction opcode ($68)
  5965. Addr: DWORD; // The actual address of the DLL routine
  5966. JMP: Byte; // JMP instruction opcode ($E9)
  5967. Rel: DWORD; // Relative displacement (a Kernel32 address)
  5968. end;
  5969. function TJclPeMapImgHooks.GetItemFromNewAddress(NewAddress: Pointer): TJclPeMapImgHookItem;
  5970. var
  5971. I: Integer;
  5972. begin
  5973. Result := nil;
  5974. for I := 0 to Count - 1 do
  5975. if Items[I].NewAddress = NewAddress then
  5976. begin
  5977. Result := Items[I];
  5978. Break;
  5979. end;
  5980. end;
  5981. function TJclPeMapImgHooks.GetItemFromOriginalAddress(OriginalAddress: Pointer): TJclPeMapImgHookItem;
  5982. var
  5983. I: Integer;
  5984. begin
  5985. Result := nil;
  5986. for I := 0 to Count - 1 do
  5987. if Items[I].OriginalAddress = OriginalAddress then
  5988. begin
  5989. Result := Items[I];
  5990. Break;
  5991. end;
  5992. end;
  5993. function TJclPeMapImgHooks.GetItems(Index: Integer): TJclPeMapImgHookItem;
  5994. begin
  5995. Result := TJclPeMapImgHookItem(Get(Index));
  5996. end;
  5997. function TJclPeMapImgHooks.HookImport(Base: Pointer; const ModuleName: string;
  5998. const FunctionName: string; NewAddress: Pointer; var OriginalAddress: Pointer): Boolean;
  5999. var
  6000. ModuleHandle: THandle;
  6001. OriginalItem: TJclPeMapImgHookItem;
  6002. UTF8Name: TUTF8String;
  6003. begin
  6004. ModuleHandle := GetModuleHandle(PChar(ModuleName));
  6005. Result := (ModuleHandle <> 0);
  6006. if not Result then
  6007. begin
  6008. SetLastError(ERROR_MOD_NOT_FOUND);
  6009. Exit;
  6010. end;
  6011. if not TryStringToUTF8(FunctionName, UTF8Name) then
  6012. UTF8Name := TUTF8String(FunctionName);
  6013. OriginalAddress := GetProcAddress(ModuleHandle, PAnsiChar(UTF8Name));
  6014. Result := (OriginalAddress <> nil);
  6015. if not Result then
  6016. begin
  6017. SetLastError(ERROR_PROC_NOT_FOUND);
  6018. Exit;
  6019. end;
  6020. OriginalItem := ItemFromOriginalAddress[OriginalAddress];
  6021. Result := ((OriginalItem = nil) or (OriginalItem.ModuleName = ModuleName)) and
  6022. (NewAddress <> nil) and (OriginalAddress <> NewAddress);
  6023. if not Result then
  6024. begin
  6025. SetLastError(ERROR_ALREADY_EXISTS);
  6026. Exit;
  6027. end;
  6028. if Result then
  6029. Result := ReplaceImport(Base, ModuleName, OriginalAddress, NewAddress);
  6030. if Result then
  6031. begin
  6032. Add(TJclPeMapImgHookItem.Create(Self, FunctionName, ModuleName, Base,
  6033. NewAddress, OriginalAddress));
  6034. end
  6035. else
  6036. SetLastError(ERROR_INVALID_PARAMETER);
  6037. end;
  6038. class function TJclPeMapImgHooks.IsWin9xDebugThunk(P: Pointer): Boolean;
  6039. begin
  6040. with PWin9xDebugThunk32(P)^ do
  6041. Result := (PUSH = $68) and (JMP = $E9);
  6042. end;
  6043. class function TJclPeMapImgHooks.ReplaceImport(Base: Pointer; const ModuleName: string;
  6044. FromProc, ToProc: Pointer): Boolean;
  6045. var
  6046. {$IFDEF CPU32}
  6047. FromProcDebugThunk32, ImportThunk32: PWin9xDebugThunk32;
  6048. IsThunked: Boolean;
  6049. NtHeader: PImageNtHeaders32;
  6050. ImportEntry: PImageThunkData32;
  6051. {$ENDIF CPU32}
  6052. {$IFDEF CPU64}
  6053. NtHeader: PImageNtHeaders64;
  6054. ImportEntry: PImageThunkData64;
  6055. {$ENDIF CPU64}
  6056. ImportDir: TImageDataDirectory;
  6057. ImportDesc: PImageImportDescriptor;
  6058. CurrName, RefName: PAnsiChar;
  6059. FoundProc: Boolean;
  6060. WrittenBytes: Cardinal;
  6061. UTF8Name: TUTF8String;
  6062. begin
  6063. Result := False;
  6064. {$IFDEF CPU32}
  6065. FromProcDebugThunk32 := PWin9xDebugThunk32(FromProc);
  6066. IsThunked := (Win32Platform <> VER_PLATFORM_WIN32_NT) and IsWin9xDebugThunk(FromProcDebugThunk32);
  6067. NtHeader := PeMapImgNtHeaders32(Base);
  6068. {$ENDIF CPU32}
  6069. {$IFDEF CPU64}
  6070. NtHeader := PeMapImgNtHeaders64(Base);
  6071. {$ENDIF CPU64}
  6072. if NtHeader = nil then
  6073. Exit;
  6074. ImportDir := NtHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
  6075. if ImportDir.VirtualAddress = 0 then
  6076. Exit;
  6077. ImportDesc := PImageImportDescriptor(TJclAddr(Base) + ImportDir.VirtualAddress);
  6078. if not TryStringToUTF8(ModuleName, UTF8Name) then
  6079. UTF8Name := TUTF8String(ModuleName);
  6080. RefName := PAnsiChar(UTF8Name);
  6081. while ImportDesc^.Name <> 0 do
  6082. begin
  6083. CurrName := PAnsiChar(Base) + ImportDesc^.Name;
  6084. if StrICompA(CurrName, RefName) = 0 then
  6085. begin
  6086. {$IFDEF CPU32}
  6087. ImportEntry := PImageThunkData32(TJclAddr(Base) + ImportDesc^.FirstThunk);
  6088. {$ENDIF CPU32}
  6089. {$IFDEF CPU64}
  6090. ImportEntry := PImageThunkData64(TJclAddr(Base) + ImportDesc^.FirstThunk);
  6091. {$ENDIF CPU64}
  6092. while ImportEntry^.Function_ <> 0 do
  6093. begin
  6094. {$IFDEF CPU32}
  6095. if IsThunked then
  6096. begin
  6097. ImportThunk32 := PWin9xDebugThunk32(ImportEntry^.Function_);
  6098. FoundProc := IsWin9xDebugThunk(ImportThunk32) and (ImportThunk32^.Addr = FromProcDebugThunk32^.Addr);
  6099. end
  6100. else
  6101. {$ENDIF CPU32}
  6102. FoundProc := Pointer(ImportEntry^.Function_) = FromProc;
  6103. if FoundProc then
  6104. Result := WriteProtectedMemory(@ImportEntry^.Function_, @ToProc, SizeOf(ToProc), WrittenBytes);
  6105. Inc(ImportEntry);
  6106. end;
  6107. end;
  6108. Inc(ImportDesc);
  6109. end;
  6110. end;
  6111. class function TJclPeMapImgHooks.SystemBase: Pointer;
  6112. begin
  6113. Result := Pointer(SystemTObjectInstance);
  6114. end;
  6115. procedure TJclPeMapImgHooks.UnhookAll;
  6116. var
  6117. I: Integer;
  6118. begin
  6119. I := 0;
  6120. while I < Count do
  6121. if not Items[I].Unhook then
  6122. Inc(I);
  6123. end;
  6124. function TJclPeMapImgHooks.UnhookByNewAddress(NewAddress: Pointer): Boolean;
  6125. var
  6126. Item: TJclPeMapImgHookItem;
  6127. begin
  6128. Item := ItemFromNewAddress[NewAddress];
  6129. Result := (Item <> nil) and Item.Unhook;
  6130. end;
  6131. procedure TJclPeMapImgHooks.UnhookByBaseAddress(BaseAddress: Pointer);
  6132. var
  6133. I: Integer;
  6134. begin
  6135. for I := Count - 1 downto 0 do
  6136. if Items[I].BaseAddress = BaseAddress then
  6137. Items[I].Unhook;
  6138. end;
  6139. // Image access under a debbuger
  6140. {$IFDEF USE_64BIT_TYPES}
  6141. function InternalReadProcMem(ProcessHandle: THandle; Address: DWORD;
  6142. Buffer: Pointer; Size: SIZE_T): Boolean;
  6143. var
  6144. BR: SIZE_T;
  6145. {$ELSE}
  6146. function InternalReadProcMem(ProcessHandle: THandle; Address: DWORD;
  6147. Buffer: Pointer; Size: Integer): Boolean;
  6148. var
  6149. BR: DWORD;
  6150. {$ENDIF}
  6151. begin
  6152. BR := 0;
  6153. Result := ReadProcessMemory(ProcessHandle, Pointer(Address), Buffer, Size, BR);
  6154. end;
  6155. // TODO: 64 bit version
  6156. function PeDbgImgNtHeaders32(ProcessHandle: THandle; BaseAddress: TJclAddr32;
  6157. var NtHeaders: TImageNtHeaders32): Boolean;
  6158. var
  6159. DosHeader: TImageDosHeader;
  6160. begin
  6161. Result := False;
  6162. ResetMemory(NtHeaders, SizeOf(NtHeaders));
  6163. ResetMemory(DosHeader, SizeOf(DosHeader));
  6164. if not InternalReadProcMem(ProcessHandle, TJclAddr32(BaseAddress), @DosHeader, SizeOf(DosHeader)) then
  6165. Exit;
  6166. if DosHeader.e_magic <> IMAGE_DOS_SIGNATURE then
  6167. Exit;
  6168. Result := InternalReadProcMem(ProcessHandle, TJclAddr32(BaseAddress) + TJclAddr32(DosHeader._lfanew),
  6169. @NtHeaders, SizeOf(TImageNtHeaders32));
  6170. end;
  6171. // TODO: 64 bit version
  6172. function PeDbgImgLibraryName32(ProcessHandle: THandle; BaseAddress: TJclAddr32;
  6173. var Name: string): Boolean;
  6174. var
  6175. NtHeaders32: TImageNtHeaders32;
  6176. DataDir: TImageDataDirectory;
  6177. ExportDir: TImageExportDirectory;
  6178. UTF8Name: TUTF8String;
  6179. begin
  6180. Name := '';
  6181. NtHeaders32.Signature := 0;
  6182. Result := PeDbgImgNtHeaders32(ProcessHandle, BaseAddress, NtHeaders32);
  6183. if not Result then
  6184. Exit;
  6185. DataDir := NtHeaders32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
  6186. if DataDir.Size = 0 then
  6187. Exit;
  6188. if not InternalReadProcMem(ProcessHandle, TJclAddr(BaseAddress) + DataDir.VirtualAddress,
  6189. @ExportDir, SizeOf(ExportDir)) then
  6190. Exit;
  6191. if ExportDir.Name = 0 then
  6192. Exit;
  6193. SetLength(UTF8Name, MAX_PATH);
  6194. if InternalReadProcMem(ProcessHandle, TJclAddr(BaseAddress) + ExportDir.Name, PAnsiChar(UTF8Name), MAX_PATH) then
  6195. begin
  6196. StrResetLength(UTF8Name);
  6197. if not TryUTF8ToString(UTF8Name, Name) then
  6198. Name := string(UTF8Name);
  6199. end
  6200. else
  6201. Name := '';
  6202. end;
  6203. // Borland BPL packages name unmangling
  6204. {$IFDEF CPU64}
  6205. function PeBorUnmangleName(const Name: string; out Unmangled: string;
  6206. out Description: TJclBorUmDescription; out BasePos: Integer): TJclBorUmResult;
  6207. var
  6208. CurPos: Integer;
  6209. EndPos: Integer;
  6210. Len: Integer;
  6211. PrevBasePos: Integer;
  6212. begin
  6213. if (Length(Name) > 3) and (Name[1] = '_') and (Name[2] = 'Z') and (Name[3] = 'N') then
  6214. begin
  6215. Result := urOk;
  6216. CurPos := 4;
  6217. BasePos := 0;
  6218. PrevBasePos := 0;
  6219. while CurPos < Length(Name) do
  6220. begin
  6221. EndPos := CurPos;
  6222. while CharInSet(Name[EndPos], ['0'..'9']) do
  6223. Inc(EndPos);
  6224. if not TryStrToInt(Copy(Name, CurPos, EndPos - CurPos), Len) then
  6225. Break;
  6226. BasePos := PrevBasePos;
  6227. PrevBasePos := Length(Unmangled);
  6228. if Unmangled <> '' then
  6229. Unmangled := Unmangled + '.';
  6230. Unmangled := Unmangled + Copy(Name, EndPos, Len);
  6231. CurPos := EndPos + Len;
  6232. end;
  6233. if BasePos = 0 then
  6234. BasePos := PrevBasePos + 2
  6235. else
  6236. BasePos := BasePos + 2;
  6237. Description.Kind := skFunction;
  6238. Description.Modifiers := [];
  6239. end
  6240. else
  6241. Result := urNotMangled;
  6242. end;
  6243. {$ENDIF CPU64}
  6244. {$IFDEF CPU32}
  6245. function PeBorUnmangleName(const Name: string; out Unmangled: string;
  6246. out Description: TJclBorUmDescription; out BasePos: Integer): TJclBorUmResult;
  6247. var
  6248. NameP, NameU, NameUFirst: PAnsiChar;
  6249. QualifierFound, LinkProcFound: Boolean;
  6250. UTF8Unmangled, UTF8Name: TUTF8String;
  6251. procedure MarkQualifier;
  6252. begin
  6253. if not QualifierFound then
  6254. begin
  6255. QualifierFound := True;
  6256. BasePos := NameU - NameUFirst + 2;
  6257. end;
  6258. end;
  6259. procedure ReadSpecialSymbol;
  6260. var
  6261. SymbolLength: Integer;
  6262. begin
  6263. SymbolLength := 0;
  6264. while CharIsDigit(Char(NameP^)) do
  6265. begin
  6266. SymbolLength := SymbolLength * 10 + Ord(NameP^) - 48;
  6267. Inc(NameP);
  6268. end;
  6269. while (SymbolLength > 0) and (NameP^ <> #0) do
  6270. begin
  6271. if NameP^ = '@' then
  6272. begin
  6273. MarkQualifier;
  6274. NameU^ := '.';
  6275. end
  6276. else
  6277. NameU^ := NameP^;
  6278. Inc(NameP);
  6279. Inc(NameU);
  6280. Dec(SymbolLength);
  6281. end;
  6282. end;
  6283. procedure ReadRTTI;
  6284. begin
  6285. if StrLCompA(NameP, '$xp$', 4) = 0 then
  6286. begin
  6287. Inc(NameP, 4);
  6288. Description.Kind := skRTTI;
  6289. QualifierFound := False;
  6290. ReadSpecialSymbol;
  6291. if QualifierFound then
  6292. Include(Description.Modifiers, smQualified);
  6293. end
  6294. else
  6295. Result := urError;
  6296. end;
  6297. procedure ReadNameSymbol;
  6298. begin
  6299. if NameP^ = '@' then
  6300. begin
  6301. LinkProcFound := True;
  6302. Inc(NameP);
  6303. end;
  6304. while CharIsValidIdentifierLetter(Char(NameP^)) do
  6305. begin
  6306. NameU^ := NameP^;
  6307. Inc(NameP);
  6308. Inc(NameU);
  6309. end;
  6310. end;
  6311. procedure ReadName;
  6312. begin
  6313. Description.Kind := skData;
  6314. QualifierFound := False;
  6315. LinkProcFound := False;
  6316. repeat
  6317. ReadNameSymbol;
  6318. if LinkProcFound and not QualifierFound then
  6319. LinkProcFound := False;
  6320. case NameP^ of
  6321. '@':
  6322. case (NameP + 1)^ of
  6323. #0:
  6324. begin
  6325. Description.Kind := skVTable;
  6326. Break;
  6327. end;
  6328. '$':
  6329. begin
  6330. if (NameP + 2)^ = 'b' then
  6331. begin
  6332. case (NameP + 3)^ of
  6333. 'c':
  6334. Description.Kind := skConstructor;
  6335. 'd':
  6336. Description.Kind := skDestructor;
  6337. end;
  6338. Inc(NameP, 6);
  6339. end
  6340. else
  6341. Description.Kind := skFunction;
  6342. Break; // no parameters unmangling yet
  6343. end;
  6344. else
  6345. MarkQualifier;
  6346. NameU^ := '.';
  6347. Inc(NameU);
  6348. Inc(NameP);
  6349. end;
  6350. '$':
  6351. begin
  6352. Description.Kind := skFunction;
  6353. Break; // no parameters unmangling yet
  6354. end;
  6355. else
  6356. Break;
  6357. end;
  6358. until False;
  6359. if QualifierFound then
  6360. Include(Description.Modifiers, smQualified);
  6361. if LinkProcFound then
  6362. Include(Description.Modifiers, smLinkProc);
  6363. end;
  6364. begin
  6365. if not TryStringToUTF8(Name, UTF8Name) then
  6366. UTF8Name := TUTF8String(Name);
  6367. NameP := PAnsiChar(UTF8Name);
  6368. Result := urError;
  6369. case NameP^ of
  6370. '@':
  6371. Result := urOk;
  6372. '?':
  6373. Result := urMicrosoft;
  6374. '_', 'A'..'Z', 'a'..'z':
  6375. Result := urNotMangled;
  6376. end;
  6377. if Result <> urOk then
  6378. Exit;
  6379. Inc(NameP);
  6380. SetLength(UTF8UnMangled, 1024);
  6381. NameU := PAnsiChar(UTF8UnMangled);
  6382. NameUFirst := NameU;
  6383. Description.Modifiers := [];
  6384. BasePos := 1;
  6385. case NameP^ of
  6386. '$':
  6387. ReadRTTI;
  6388. '_', 'A'..'Z', 'a'..'z':
  6389. ReadName;
  6390. else
  6391. Result := urError;
  6392. end;
  6393. NameU^ := #0;
  6394. SetLength(UTF8Unmangled, StrLenA(PAnsiChar(UTF8Unmangled))); // SysUtils prefix due to compiler bug
  6395. if not TryUTF8ToString(UTF8Unmangled, Unmangled) then
  6396. Unmangled := string(UTF8Unmangled);
  6397. end;
  6398. {$ENDIF CPU32}
  6399. function PeBorUnmangleName(const Name: string; out Unmangled: string;
  6400. out Description: TJclBorUmDescription): TJclBorUmResult;
  6401. var
  6402. BasePos: Integer;
  6403. begin
  6404. Result := PeBorUnmangleName(Name, Unmangled, Description, BasePos);
  6405. end;
  6406. function PeBorUnmangleName(const Name: string; out Unmangled: string): TJclBorUmResult;
  6407. var
  6408. Description: TJclBorUmDescription;
  6409. BasePos: Integer;
  6410. begin
  6411. Result := PeBorUnmangleName(Name, Unmangled, Description, BasePos);
  6412. end;
  6413. function PeBorUnmangleName(const Name: string): string;
  6414. var
  6415. Unmangled: string;
  6416. Description: TJclBorUmDescription;
  6417. BasePos: Integer;
  6418. begin
  6419. if PeBorUnmangleName(Name, Unmangled, Description, BasePos) = urOk then
  6420. Result := Unmangled
  6421. else
  6422. Result := '';
  6423. end;
  6424. function PeIsNameMangled(const Name: string): TJclPeUmResult; {$IFDEF SUPPORTS_INLINE}inline;{$ENDIF}
  6425. begin
  6426. Result := umNotMangled;
  6427. if Length(Name) > 0 then
  6428. case Name[1] of
  6429. '@':
  6430. Result := umBorland;
  6431. '?':
  6432. Result := umMicrosoft;
  6433. {$IFDEF CPU64}
  6434. '_':
  6435. if (Length(Name) > 3) and (Name[2] = 'Z') and (Name[3] = 'N') then
  6436. Result := umBorland;
  6437. {$ENDIF CPU64}
  6438. end;
  6439. end;
  6440. type
  6441. TUndecorateSymbolNameA = function (DecoratedName: PAnsiChar;
  6442. UnDecoratedName: PAnsiChar; UndecoratedLength: DWORD; Flags: DWORD): DWORD; stdcall;
  6443. // 'imagehlp.dll' 'UnDecorateSymbolName'
  6444. TUndecorateSymbolNameW = function (DecoratedName: PWideChar;
  6445. UnDecoratedName: PWideChar; UndecoratedLength: DWORD; Flags: DWORD): DWORD; stdcall;
  6446. // 'imagehlp.dll' 'UnDecorateSymbolNameW'
  6447. var
  6448. UndecorateSymbolNameA: TUndecorateSymbolNameA = nil;
  6449. UndecorateSymbolNameAFailed: Boolean = False;
  6450. UndecorateSymbolNameW: TUndecorateSymbolNameW = nil;
  6451. UndecorateSymbolNameWFailed: Boolean = False;
  6452. function UndecorateSymbolName(const DecoratedName: string; out UnMangled: string; Flags: DWORD): Boolean;
  6453. const
  6454. ModuleName = 'imagehlp.dll';
  6455. BufferSize = 512;
  6456. var
  6457. ModuleHandle: HMODULE;
  6458. WideBuffer: WideString;
  6459. AnsiBuffer: AnsiString;
  6460. Res: DWORD;
  6461. begin
  6462. Result := False;
  6463. if ((not Assigned(UndecorateSymbolNameA)) and (not UndecorateSymbolNameAFailed)) or
  6464. ((not Assigned(UndecorateSymbolNameW)) and (not UndecorateSymbolNameWFailed)) then
  6465. begin
  6466. ModuleHandle := GetModuleHandle(ModuleName);
  6467. if ModuleHandle = 0 then
  6468. begin
  6469. ModuleHandle := SafeLoadLibrary(ModuleName);
  6470. if ModuleHandle = 0 then
  6471. Exit;
  6472. end;
  6473. UndecorateSymbolNameA := GetProcAddress(ModuleHandle, 'UnDecorateSymbolName');
  6474. UndecorateSymbolNameAFailed := not Assigned(UndecorateSymbolNameA);
  6475. UndecorateSymbolNameW := GetProcAddress(ModuleHandle, 'UnDecorateSymbolNameW');
  6476. UndecorateSymbolNameWFailed := not Assigned(UndecorateSymbolNameW);
  6477. end;
  6478. if Assigned(UndecorateSymbolNameW) then
  6479. begin
  6480. SetLength(WideBuffer, BufferSize);
  6481. Res := UnDecorateSymbolNameW(PWideChar({$IFNDEF UNICODE}WideString{$ENDIF}(DecoratedName)), PWideChar(WideBuffer), BufferSize, Flags);
  6482. if Res > 0 then
  6483. begin
  6484. StrResetLength(WideBuffer);
  6485. UnMangled := string(WideBuffer);
  6486. Result := True;
  6487. end;
  6488. end
  6489. else
  6490. if Assigned(UndecorateSymbolNameA) then
  6491. begin
  6492. SetLength(AnsiBuffer, BufferSize);
  6493. Res := UnDecorateSymbolNameA(PAnsiChar(AnsiString(DecoratedName)), PAnsiChar(AnsiBuffer), BufferSize, Flags);
  6494. if Res > 0 then
  6495. begin
  6496. StrResetLength(AnsiBuffer);
  6497. UnMangled := string(AnsiBuffer);
  6498. Result := True;
  6499. end;
  6500. end;
  6501. // For some functions UnDecorateSymbolName returns 'long'
  6502. if Result and (UnMangled = 'long') then
  6503. UnMangled := DecoratedName;
  6504. end;
  6505. function PeUnmangleName(const Name: string; out Unmangled: string): TJclPeUmResult;
  6506. begin
  6507. Result := umNotMangled;
  6508. case PeBorUnmangleName(Name, Unmangled) of
  6509. urOk:
  6510. Result := umBorland;
  6511. urMicrosoft:
  6512. if UndecorateSymbolName(Name, Unmangled, UNDNAME_NAME_ONLY) then
  6513. Result := umMicrosoft;
  6514. end;
  6515. if Result = umNotMangled then
  6516. Unmangled := Name;
  6517. end;
  6518. {$IFDEF UNITVERSIONING}
  6519. initialization
  6520. RegisterUnitVersion(HInstance, UnitVersioning);
  6521. finalization
  6522. UnregisterUnitVersion(HInstance);
  6523. {$ENDIF UNITVERSIONING}
  6524. end.