| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987 | {**************************************************************************************************}{                                                                                                  }{ 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}interfaceuses  {$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;    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);    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;  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 RvaToVaEx(Rva: DWORD): Pointer; overload;    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 functionstype  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 routinesfunction 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 classestype  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 debbugerfunction 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 unmanglingtype  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}implementationuses  {$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};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 functionsfunction 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 constantconst  UnixTimeStart = UnixDateDelta;// from JclAnsiStrings.pasfunction 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 routinesfunction 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 functionfunction 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 functionsfunction 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);begin  inherited Create(AImage);  FTotalResolveCheck := icNotChecked;  FImportDescriptor := AImportDescriptor;  FImportKind := AImportKind;  FName := AName;  FThunk := AThunk;  FThunkData := AThunk;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;  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));              Hint := OrdinalName.Hint;              Name := OrdinalName.Name;            end;          ikDelayImport:            begin              OrdinalName := PImageImportByName(Image.RvaToVaEx(Thunk32^.AddressOfData));              Hint := OrdinalName.Hint;              Name := OrdinalName.Name;            end;        end;      end      else        Ordinal := IMAGE_ORDINAL32(Thunk32^.Ordinal);      if not TryUTF8ToString(Name, ImportName) then        ImportName := string(Name);      Add(TJclPeImportFuncItem.Create(Self, Ordinal, Hint, ImportName));      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));              Hint := OrdinalName.Hint;              Name := OrdinalName.Name;            end;          ikDelayImport:            begin              OrdinalName := PImageImportByName(Image.RvaToVaEx(Thunk64^.AddressOfData));              Hint := OrdinalName.Hint;              Name := OrdinalName.Name;            end;        end;      end      else        Ordinal := IMAGE_ORDINAL64(Thunk64^.Ordinal);      if not TryUTF8ToString(Name, ImportName) then        ImportName := string(Name);      Add(TJclPeImportFuncItem.Create(Self, Ordinal, Hint, ImportName));      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);  var    LibItem: TJclPeImportLibItem;    UTF8Name: TUTF8String;    LibName: string;  begin    while DelayImportDesc^.szName <> nil do    begin      UTF8Name := PAnsiChar(Image.RvaToVaEx(DWORD(DelayImportDesc^.szName)));      if not TryUTF8ToString(UTF8Name, LibName) then        LibName := string(UTF8Name);      LibItem := TJclPeImportLibItem.Create(Image, DelayImportDesc, ikDelayImport,        LibName, Image.RvaToVaEx(DWORD(DelayImportDesc^.pINT)));      Add(LibItem);      FUniqueNamesList.AddObject(AnsiLowerCase(LibItem.Name), LibItem);      Inc(DelayImportDesc);    end;  end;  procedure CreateDelayImportList64(DelayImportDesc: PImgDelayDescrV2);  var    LibItem: TJclPeImportLibItem;    UTF8Name: TUTF8String;    LibName: string;  begin    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      case Target of        taWin32:          CreateDelayImportList32(DelayImportDesc);        taWin64:          CreateDelayImportList64(DelayImportDesc);      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 functionsfunction 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;      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;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;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) then    begin      FormatCount := DebugImageDir.Size;      DebugDir := RvaToVa(Header^.VirtualAddress);    end    else    begin      if not GetSectionHeader(ReadOnlySectionName, Header) then        Exit;      FormatCount := DebugImageDir.Size div SizeOf(TImageDebugDirectory);      DebugDir := Pointer(MappedAddress + DebugImageDir.VirtualAddress -        Header^.VirtualAddress + Header^.PointerToRawData);    end;    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 rootbegin  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;beginend;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.RvaToVaEx(Rva: DWORD): Pointer;  function RvaToVaEx32(Rva: DWORD): Pointer;  var    OptionalHeader: TImageOptionalHeader32;  begin    OptionalHeader := OptionalHeader32;    if (Rva >= OptionalHeader.ImageBase) and (Rva < (OptionalHeader.ImageBase + FLoadedImage.SizeOfImage)) then      Dec(Rva, OptionalHeader.ImageBase);    Result := RvaToVa(Rva);  end;  function RvaToVaEx64(Rva: DWORD): Pointer;  var    OptionalHeader: TImageOptionalHeader64;  begin    OptionalHeader := OptionalHeader64;    if (Rva >= OptionalHeader.ImageBase) and (Rva < (OptionalHeader.ImageBase + FLoadedImage.SizeOfImage)) then      Dec(Rva, OptionalHeader.ImageBase);    Result := RvaToVa(Rva);  end;begin  case Target of    taWin32:      Result := RvaToVaEx32(Rva);    taWin64:      Result := RvaToVaEx64(Rva);    //taUnknown:  else    Result := nil;  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 + UnixTimeStartend;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 differsbegin  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 differsbegin  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 routinesfunction 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 routinesfunction 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 functionsfunction 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 := nilend;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 := nilend;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;    JmpAddress: PPointer;  end;begin  if not IsCompiledWithPackages then    Result := Address  else  if not IsBadReadPtr(Address, SizeOf(TPackageThunk)) and    (PPackageThunk(Address)^.JmpInstruction = JmpInstructionCode) then    Result := PPackageThunk(Address)^.JmpAddress^  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 versionfunction 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 versionfunction 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 unmanglingfunction 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;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;begin  Result := umNotMangled;  if Length(Name) > 0 then    case Name[1] of      '@':        Result := umBorland;      '?':        Result := umMicrosoft;    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.
 |