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